From fa306064d4c92dba769fffe8f1efebe7240a3204 Mon Sep 17 00:00:00 2001 From: ronsh12 <101520407+ronsh12@users.noreply.github.com> Date: Sun, 26 Nov 2023 17:40:55 +0200 Subject: [PATCH 1/2] feat: Added AWS Bigquery dbt --- .../aws_compliance__cis_v1.2.0_free.sql | 12 +++++----- .../macros/cloudfront/access_logs_enabled.sql | 14 +++++++++++ .../access_point_enforce_user_identity.sql | 24 +++++++++++++++++++ .../aws/macros/full_table_name.sql | 3 +++ .../aws/macros/iam/avoid_root_usage.sql | 15 ++++++++++++ .../iam/mfa_enabled_for_console_access.sql | 15 ++++++++++++ .../aws/macros/iam/old_access_keys.sql | 15 ++++++++++++ .../iam/password_policy_min_lowercase.sql | 16 +++++++++++++ .../iam/password_policy_min_uppercase.sql | 16 +++++++++++++ .../aws/macros/iam/unused_creds_disabled.sql | 17 +++++++++++++ transformations/aws/macros/timestamp.sql | 7 ++++++ transformations/aws/macros/union.sql | 7 ++++++ 12 files changed, 155 insertions(+), 6 deletions(-) create mode 100644 transformations/aws/macros/full_table_name.sql create mode 100644 transformations/aws/macros/timestamp.sql create mode 100644 transformations/aws/macros/union.sql diff --git a/transformations/aws/compliance-free/models/aws_compliance__cis_v1.2.0_free.sql b/transformations/aws/compliance-free/models/aws_compliance__cis_v1.2.0_free.sql index b58119b8a..2c58f706d 100644 --- a/transformations/aws/compliance-free/models/aws_compliance__cis_v1.2.0_free.sql +++ b/transformations/aws/compliance-free/models/aws_compliance__cis_v1.2.0_free.sql @@ -1,18 +1,18 @@ with aggregated as ( ({{ avoid_root_usage('cis_v1.2.0','1.1') }}) - UNION + {{ union() }} ({{ mfa_enabled_for_console_access('cis_v1.2.0','1.2') }}) - UNION + {{ union() }} ({{ unused_creds_disabled('cis_v1.2.0','1.3') }}) - UNION + {{ union() }} ({{ old_access_keys('cis_v1.2.0','1.4') }}) - UNION + {{ union() }} ({{ password_policy_min_uppercase('cis_v1.2.0','1.5') }}) - UNION + {{ union() }} ({{ password_policy_min_lowercase('cis_v1.2.0','1.6') }}) ) select - ('{{ run_started_at }}')::timestamp as policy_execution_time, + {{ gen_timestamp() }}, aggregated.* from aggregated diff --git a/transformations/aws/macros/cloudfront/access_logs_enabled.sql b/transformations/aws/macros/cloudfront/access_logs_enabled.sql index 8c54cbe7a..77f89cc44 100644 --- a/transformations/aws/macros/cloudfront/access_logs_enabled.sql +++ b/transformations/aws/macros/cloudfront/access_logs_enabled.sql @@ -30,3 +30,17 @@ select end as status from aws_cloudfront_distributions {% endmacro %} + +{% macro bigquery__access_logs_enabled(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'CloudFront distributions should have logging enabled' as title, + account_id, + arn as resource_id, + case + when CAST( JSON_VALUE(distribution_config.Logging.Enabled) AS BOOL)is distinct from true then 'fail' + else 'pass' + end as status +from {{ full_table_name("aws_cloudfront_distributions") }} +{% endmacro %} \ No newline at end of file diff --git a/transformations/aws/macros/efs/access_point_enforce_user_identity.sql b/transformations/aws/macros/efs/access_point_enforce_user_identity.sql index 28e854902..43d4bc69b 100644 --- a/transformations/aws/macros/efs/access_point_enforce_user_identity.sql +++ b/transformations/aws/macros/efs/access_point_enforce_user_identity.sql @@ -1,4 +1,10 @@ {% macro access_point_enforce_user_identity(framework, check_id) %} + {{ return(adapter.dispatch('access_point_enforce_user_identity')(framework, check_id)) }} +{% endmacro %} + +{% macro default__access_point_enforce_user_identity(framework, check_id) %}{% endmacro %} + +{% macro snowflake__access_point_enforce_user_identity(framework, check_id) %} select '{{framework}}' As framework, '{{check_id}}' As check_id, @@ -14,4 +20,22 @@ select END as status FROM aws_efs_access_points +{% endmacro %} + +{% macro bigquery__(framework, check_id) %} +select + '{{framework}}' As framework, + '{{check_id}}' As check_id, + 'EFS access points should enforce a user identity' as title, + account_id, + arn as resource_id, + CASE + WHEN posix_user IS NULL + OR CAST(JSON_VALUE(posix_user.uid) AS STRING) IS NULL + OR CAST(JSON_VALUE(posix_user.gid) AS STRING) IS NULL + THEN 'fail' + ELSE 'pass' + END as status +FROM + {{ full_table_name("aws_efs_access_points") }} {% endmacro %} \ No newline at end of file diff --git a/transformations/aws/macros/full_table_name.sql b/transformations/aws/macros/full_table_name.sql new file mode 100644 index 000000000..0c62c16d6 --- /dev/null +++ b/transformations/aws/macros/full_table_name.sql @@ -0,0 +1,3 @@ +{% macro full_table_name(table_name) %} + {{target.database}}.{{target.schema}}.{{table_name}} +{% endmacro %} \ No newline at end of file diff --git a/transformations/aws/macros/iam/avoid_root_usage.sql b/transformations/aws/macros/iam/avoid_root_usage.sql index 6111cd087..3cb65e063 100644 --- a/transformations/aws/macros/iam/avoid_root_usage.sql +++ b/transformations/aws/macros/iam/avoid_root_usage.sql @@ -18,3 +18,18 @@ select end as status from aws_iam_users {% endmacro %} + +{% macro bigquery__avoid_root_usage(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'Avoid the use of "root" account. Show used in last 30 days (Scored)' as title, + account_id, + arn as resource_id, + case when + user_name = '' and password_last_used > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY) + then 'fail' + else 'pass' + end as status +from {{ full_table_name("aws_iam_users") }} +{% endmacro %} \ No newline at end of file diff --git a/transformations/aws/macros/iam/mfa_enabled_for_console_access.sql b/transformations/aws/macros/iam/mfa_enabled_for_console_access.sql index 9269b73c5..941e16290 100644 --- a/transformations/aws/macros/iam/mfa_enabled_for_console_access.sql +++ b/transformations/aws/macros/iam/mfa_enabled_for_console_access.sql @@ -31,3 +31,18 @@ select end as status from aws_iam_credential_reports {% endmacro %} + +{% macro bigquery__(framework, check_id) %} +select + '{{framework}}' As framework, + '{{check_id}}' As check_id, + 'Ensure MFA is enabled for all IAM users that have a console password (Scored)' as title, + SPLIT(arn, ':')[SAFE_OFFSET(4)] as account_id, + arn as resource_id, + case when + password_status IN ('TRUE', 'true') and not mfa_active + then 'fail' + else 'pass' + end as status +from {{ full_table_name("aws_iam_credential_reports") }} +{% endmacro %} \ No newline at end of file diff --git a/transformations/aws/macros/iam/old_access_keys.sql b/transformations/aws/macros/iam/old_access_keys.sql index da95565df..3b4a2af51 100644 --- a/transformations/aws/macros/iam/old_access_keys.sql +++ b/transformations/aws/macros/iam/old_access_keys.sql @@ -18,3 +18,18 @@ select end from aws_iam_user_access_keys {% endmacro %} + +{% macro bigquery__old_access_keys(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'Ensure access keys are rotated every 90 days or less' as title, + account_id, + user_arn, + case when + last_rotated < TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 90 DAY) + then 'fail' + else 'pass' + end +from {{ full_table_name("aws_iam_user_access_keys") }} +{% endmacro %} \ No newline at end of file diff --git a/transformations/aws/macros/iam/password_policy_min_lowercase.sql b/transformations/aws/macros/iam/password_policy_min_lowercase.sql index af3b7003f..8cfd35f92 100644 --- a/transformations/aws/macros/iam/password_policy_min_lowercase.sql +++ b/transformations/aws/macros/iam/password_policy_min_lowercase.sql @@ -20,3 +20,19 @@ from aws_iam_password_policies {% endmacro %} + +{% macro bigquery__password_policy_min_lowercase(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'Ensure IAM password policy requires at least one lowercase letter' as title, + account_id, + account_id, + case when + require_lowercase_characters = false or policy_exists = false + then 'fail' + else 'pass' + end as status +from + {{ full_table_name("aws_iam_password_policies") }} +{% endmacro %} \ No newline at end of file diff --git a/transformations/aws/macros/iam/password_policy_min_uppercase.sql b/transformations/aws/macros/iam/password_policy_min_uppercase.sql index 26b86e177..ab54a0527 100644 --- a/transformations/aws/macros/iam/password_policy_min_uppercase.sql +++ b/transformations/aws/macros/iam/password_policy_min_uppercase.sql @@ -19,3 +19,19 @@ select from aws_iam_password_policies {% endmacro %} + +{% macro bigquery__password_policy_min_uppercase(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'Ensure IAM password policy requires at least one uppercase letter' as title, + account_id, + account_id, + case when + require_uppercase_characters is not true or policy_exists is not true + then 'fail' + else 'pass' + end +from + {{ full_table_name("aws_iam_password_policies") }} +{% endmacro %} diff --git a/transformations/aws/macros/iam/unused_creds_disabled.sql b/transformations/aws/macros/iam/unused_creds_disabled.sql index 4c2763869..30b1487bf 100644 --- a/transformations/aws/macros/iam/unused_creds_disabled.sql +++ b/transformations/aws/macros/iam/unused_creds_disabled.sql @@ -20,3 +20,20 @@ select from aws_iam_credential_reports r left join aws_iam_user_access_keys k on k.user_arn = r.arn {% endmacro %} + +{% macro bigquery__unused_creds_disabled(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'Ensure credentials unused for 90 days or greater are disabled (Scored)' as title, + SPLIT(arn, ':')[SAFE_OFFSET(4)] AS account_id, + r.arn, + case when + (r.password_status IN ('TRUE', 'true') and r.password_last_used < TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 90 DAY) + or (k.last_used < TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 90 DAY))) + then 'fail' + else 'pass' + end +from {{ full_table_name("aws_iam_credential_reports") }} r +left join {{ full_table_name("aws_iam_user_access_keys") }} k on k.user_arn = r.arn +{% endmacro %} diff --git a/transformations/aws/macros/timestamp.sql b/transformations/aws/macros/timestamp.sql new file mode 100644 index 000000000..ac412e8c8 --- /dev/null +++ b/transformations/aws/macros/timestamp.sql @@ -0,0 +1,7 @@ +{% macro gen_timestamp() %} + {% if target.type == 'bigquery' %} + CAST('{{ run_started_at }}' AS timestamp) as policy_execution_time + {% else %} + ('{{ run_started_at }}')::timestamp as policy_execution_time + {% endif %} +{% endmacro %} \ No newline at end of file diff --git a/transformations/aws/macros/union.sql b/transformations/aws/macros/union.sql new file mode 100644 index 000000000..3854bedcd --- /dev/null +++ b/transformations/aws/macros/union.sql @@ -0,0 +1,7 @@ +{% macro union() %} + {% if target.type == 'bigquery' %} + union all + {% else %} + union + {% endif %} +{% endmacro %} \ No newline at end of file From 0d71e8642b6e4c619dfcb7b17880bdf1373bfa10 Mon Sep 17 00:00:00 2001 From: ronsh12 <101520407+ronsh12@users.noreply.github.com> Date: Tue, 28 Nov 2023 11:48:44 +0200 Subject: [PATCH 2/2] Updated cis bigquery --- .../models/aws_compliance__cis_v1.2.0.sql | 76 +-- .../aws_compliance__foundational_security.sql | 436 +----------------- .../cloudtrail/bucket_access_logging.sql | 15 + .../cloudtrail/enabled_in_all_regions.sql | 22 + .../integrated_with_cloudwatch_logs.sql | 16 + .../log_file_validation_enabled.sql | 14 + .../aws/macros/cloudtrail/logs_encrypted.sql | 14 + .../cloudwatch/alarm_aws_config_changes.sql | 17 + .../cloudwatch/alarm_console_auth_failure.sql | 16 + .../cloudwatch/alarm_delete_customer_cmk.sql | 17 + .../cloudwatch/alarm_iam_policy_change.sql | 29 ++ .../macros/cloudwatch/alarm_nacl_changes.sql | 20 + .../cloudwatch/alarm_network_gateways.sql | 20 + .../macros/cloudwatch/alarm_root_account.sql | 19 +- .../cloudwatch/alarm_route_table_changes.sql | 20 + .../alarm_s3_bucket_policy_change.sql | 24 + .../alarm_security_group_changes.sql | 19 + .../cloudwatch/alarm_unauthorized_api.sql | 15 + .../macros/cloudwatch/alarm_vpc_changes.sql | 25 + .../aws/macros/ec2/default_sg_no_access.sql | 20 +- .../ec2/ec2_security_group_ingress_rules.sql | 43 ++ .../ec2/flow_logs_enabled_in_all_vpcs.sql | 17 + .../no_broad_public_ingress_on_port_22.sql | 18 + .../no_broad_public_ingress_on_port_3389.sql | 19 + .../access_point_enforce_user_identity.sql | 4 +- .../iam/hardware_mfa_enabled_for_root.sql | 19 + .../iam/mfa_enabled_for_console_access.sql | 2 +- .../aws/macros/iam/mfa_enabled_for_root.sql | 14 + .../password_policy_expire_old_passwords.sql | 16 + .../macros/iam/password_policy_min_length.sql | 16 + .../macros/iam/password_policy_min_number.sql | 17 +- .../iam/password_policy_min_one_symbol.sql | 16 + .../iam/password_policy_prevent_reuse.sql | 16 + .../iam/policies_attached_to_groups_roles.sql | 19 + .../macros/iam/root_user_no_access_keys.sql | 15 + .../kms/rotation_enabled_for_customer_key.sql | 15 + .../macros/log_metric_filter_and_alarm.sql | 49 ++ ...ompliance__log_metric_filter_and_alarm.sql | 24 +- 38 files changed, 698 insertions(+), 495 deletions(-) create mode 100644 transformations/aws/macros/log_metric_filter_and_alarm.sql diff --git a/transformations/aws/compliance-premium/models/aws_compliance__cis_v1.2.0.sql b/transformations/aws/compliance-premium/models/aws_compliance__cis_v1.2.0.sql index 958bd7e07..dfdffc1b5 100644 --- a/transformations/aws/compliance-premium/models/aws_compliance__cis_v1.2.0.sql +++ b/transformations/aws/compliance-premium/models/aws_compliance__cis_v1.2.0.sql @@ -1,82 +1,82 @@ with aggregated as ( ({{ alarm_unauthorized_api('cis_v1.2.0','3.1') }}) - UNION + {{ union() }} ({{ alarm_root_account('cis_v1.2.0','3.3') }}) - UNION + {{ union() }} ({{ alarm_iam_policy_change('cis_v1.2.0','3.4') }}) - UNION + {{ union() }} ({{ alarm_cloudtrail_config_changes('cis_v1.2.0','3.5') }}) - UNION + {{ union() }} ({{ alarm_console_auth_failure('cis_v1.2.0','3.6') }}) - UNION + {{ union() }} ({{ alarm_delete_customer_cmk('cis_v1.2.0','3.7') }}) - UNION + {{ union() }} ({{ alarm_s3_bucket_policy_change('cis_v1.2.0','3.8') }}) - UNION + {{ union() }} ({{ alarm_aws_config_changes('cis_v1.2.0','3.9') }}) - UNION + {{ union() }} ({{ alarm_security_group_changes('cis_v1.2.0','3.10') }}) - UNION + {{ union() }} ({{ alarm_nacl_changes('cis_v1.2.0','3.11') }}) - UNION + {{ union() }} ({{ alarm_network_gateways('cis_v1.2.0','3.12') }}) - UNION + {{ union() }} ({{ alarm_route_table_changes('cis_v1.2.0','3.13') }}) - UNION + {{ union() }} ({{ alarm_vpc_changes('cis_v1.2.0','3.14') }}) - UNION + {{ union() }} ({{ cloudtrail_enabled_all_regions('cis_v1.2.0','2.1') }}) - UNION + {{ union() }} ({{ log_file_validation_enabled('cis_v1.2.0','2.2') }}) - UNION + {{ union() }} ({{ integrated_with_cloudwatch_logs('cis_v1.2.0','2.4') }}) - UNION + {{ union() }} ({{ bucket_access_logging('cis_v1.2.0','2.6') }}) - UNION + {{ union() }} ({{ logs_encrypted('cis_v1.2.0','2.7') }}) - UNION + {{ union() }} ({{ rotation_enabled_for_customer_key('cis_v1.2.0','2.8') }}) - UNION + {{ union() }} ({{ flow_logs_enabled_in_all_vpcs('cis_v1.2.0','2.9') }}) - UNION + {{ union() }} ({{ avoid_root_usage('cis_v1.2.0','1.1') }}) - UNION + {{ union() }} ({{ mfa_enabled_for_console_access('cis_v1.2.0','1.2') }}) - UNION + {{ union() }} ({{ unused_creds_disabled('cis_v1.2.0','1.3') }}) - UNION + {{ union() }} ({{ old_access_keys('cis_v1.2.0','1.4') }}) - UNION + {{ union() }} ({{ password_policy_min_uppercase('cis_v1.2.0','1.5') }}) - UNION + {{ union() }} ({{ password_policy_min_lowercase('cis_v1.2.0','1.6') }}) - UNION + {{ union() }} ({{ password_policy_min_one_symbol('cis_v1.2.0','1.7') }}) - UNION + {{ union() }} ({{ password_policy_min_number('cis_v1.2.0','1.8') }}) - UNION + {{ union() }} ({{ password_policy_min_length('cis_v1.2.0','1.9') }}) - UNION + {{ union() }} ({{ password_policy_prevent_reuse('cis_v1.2.0','1.10') }}) - UNION + {{ union() }} ({{ password_policy_expire_old_passwords('cis_v1.2.0','1.11') }}) - UNION + {{ union() }} ({{ root_user_no_access_keys('cis_v1.2.0','1.12') }}) - UNION + {{ union() }} ({{ mfa_enabled_for_root('cis_v1.2.0','1.13') }}) - UNION + {{ union() }} ({{ hardware_mfa_enabled_for_root('cis_v1.2.0','1.14') }}) - UNION + {{ union() }} ({{ policies_attached_to_groups_roles('cis_v1.2.0','1.16') }}) - UNION + {{ union() }} ({{ no_broad_public_ingress_on_port_22('cis_v1.2.0','4.1') }}) - UNION + {{ union() }} ({{ no_broad_public_ingress_on_port_3389('cis_v1.2.0','4.2') }}) - UNION + {{ union() }} ({{ default_sg_no_access('cis_v1.2.0','4.3') }}) ) select - ('{{ run_started_at }}')::timestamp as policy_execution_time, + {{ gen_timestamp() }}, aggregated.* from aggregated diff --git a/transformations/aws/compliance-premium/models/aws_compliance__foundational_security.sql b/transformations/aws/compliance-premium/models/aws_compliance__foundational_security.sql index 5929d4b3c..6e5c4d0a9 100644 --- a/transformations/aws/compliance-premium/models/aws_compliance__foundational_security.sql +++ b/transformations/aws/compliance-premium/models/aws_compliance__foundational_security.sql @@ -1,442 +1,12 @@ with aggregated as ( - {{ access_logs_enabled('foundational_security','cloudfront.5') }} - union - ({{ access_point_enforce_user_identity('foundational_security','efs.4') }}) + ({{ access_logs_enabled('foundational_security','cloudfront.5') }}) + union ({{ access_point_path_should_not_be_root('foundational_security','efs.3') }}) union ({{ account_level_public_access_blocks('foundational_security','s3.1') }}) - union - ({{ advanced_health_reporting_enabled('foundational_security','elastic_beanstalk.1') }}) - union - ({{ alb_deletion_protection_enabled('foundational_security','elb.6') }}) - union - ({{ alb_drop_http_headers('foundational_security','elb.4') }}) - union - ({{ alb_logging_enabled('foundational_security','elb.5') }}) - union - ({{ amazon_aurora_clusters_should_have_backtracking_enabled('foundational_security','rds.14') }}) - union - ({{ api_gw_access_logging_should_be_configured('foundational_security','apigateway.9') }}) - union - ({{ api_gw_associated_wth_waf('foundational_security','apigateway.4') }}) - union - ({{ api_gw_cache_data_encrypted('foundational_security','apigateway.5') }}) - union - ({{ api_gw_execution_logging_enabled('foundational_security','apigateway.1') }}) - union - ({{ api_gw_routes_should_specify_authorization_type('foundational_security','apigateway.8') }}) - union - ({{ api_gw_stage_should_have_xray_tracing_enabled('foundational_security','apigateway.3') }}) - union - ({{ api_gw_stage_should_use_ssl('foundational_security','apigateway.2') }}) - union - ({{ appsync_should_have_logging_turned_on('foundational_security','appsync.2') }}) - union - ({{ associated_with_waf('foundational_security','cloudfront.6') }}) - union - ({{ athena_workgroup_encrypted_at_rest('foundational_security','athena.1') }}) - union - ({{ autoscale_or_ondemand('foundational_security','dynamodb.1') }}) - union - ({{ autoscaling_group_elb_healthcheck_required('foundational_security','autoscaling.1') }}) - union - ({{ autoscaling_launch_config_hop_limit('foundational_security','autoscaling.4') }}) - union - ({{ autoscaling_launch_config_public_ip_disabled('foundational_security','autoscaling.5') }}) - union - ({{ autoscaling_launch_template('foundational_security','autoscaling.9') }}) - union - ({{ autoscaling_launchconfig_requires_imdsv2('foundational_security','autoscaling.3') }}) - union - ({{ autoscaling_multiple_az('foundational_security','autoscaling.2') }}) - union - ({{ autoscaling_multiple_instance_types('foundational_security','autoscaling.6') }}) - union - ({{ both_vpn_channels_should_be_up('foundational_security','ec2.20') }}) - union - ({{ certificates_should_be_renewed('foundational_security','acm.1') }}) - union - ({{ check_environment_variables('foundational_security','codebuild.2') }}) - union - ({{ check_oauth_usage_for_sources('foundational_security','codebuild.1') }}) - union - ({{ cloudformation_stack_notification_check('foundational_security','cloudformation.1') }}) - union - ({{ cluster_endpoints_not_publicly_accessible('foundational_security','eks.1') }}) - union - ({{ cluster_publicly_accessible('foundational_security','redshift.1') }}) - union - ({{ cluster_snapshots_and_database_snapshots_should_be_encrypted_at_rest('foundational_security','rds.4') }}) - union - ({{ clusters_should_be_configured_for_multiple_availability_zones('foundational_security','rds.15') }}) - union - ({{ clusters_should_be_configured_to_copy_tags_to_snapshots('foundational_security','rds.16') }}) - union - ({{ clusters_should_be_encrypted_at_rest('foundational_security','documentdb.1') }}) - union - ({{ clusters_should_be_encrypted_in_transit('foundational_security','redshift.2') }}) - union - ({{ clusters_should_have_7_days_backup_retention('foundational_security','documentdb.2') }}) - union - ({{ clusters_should_have_audit_logging_enabled('foundational_security','redshift.4') }}) - union - ({{ clusters_should_have_automatic_snapshots_enabled('foundational_security','redshift.3') }}) - union - ({{ clusters_should_have_automatic_upgrades_to_major_versions_enabled('foundational_security','redshift.6') }}) - union - ({{ clusters_should_have_deletion_protection_enabled('foundational_security','rds.7') }}) - union - ({{ clusters_should_not_use_default_subnet_group('foundational_security','elasticache.7') }}) - union - ({{ clusters_should_run_on_supported_kuberneters_version('foundational_security','eks.2') }}) - union - ({{ clusters_should_use_container_insights('foundational_security','ecs.12') }}) - union - ({{ clusters_should_use_enhanced_vpc_routing('foundational_security','redshift.7') }}) - union - ({{ connections_to_elasticsearch_domains_should_be_encrypted_using_tls_1_2('foundational_security','elastic_search.8') }}) - union - ({{ containers_limited_read_only_root_filesystems('foundational_security','ecs.5') }}) - union - ({{ containers_should_run_as_non_privileged('foundational_security','ecs.4') }}) - union - ({{ database_logging_should_be_enabled('foundational_security','rds.9') }}) - union - ({{ databases_and_clusters_should_not_use_database_engine_default_port('foundational_security','rds.23') }}) - union - ({{ dax_encrypted_at_rest('foundational_security','dynamodb.3') }}) - union - ({{ db_instance_backup_enabled('foundational_security','rds.11') }}) - union - ({{ default_root_object_configured('foundational_security','cloudfront.1') }}) - union - ({{ default_sg_no_access('foundational_security','ec2.2') }}) - union - ({{ deny_http_requests('foundational_security','s3.5') }}) - union - ({{ detector_enabled('foundational_security','guarddury.1') }}) - union - ({{ distribution_should_encrypt_traffic_to_custom_origins('foundational_security','cloudfront.9') }}) - union - ({{ distribution_should_not_point_to_non_existent_s3_origins('foundational_security','cloudfront.12') }}) - union - ({{ distribution_should_not_use_depricated_ssl_protocols('foundational_security','cloudfront.10') }}) - union - ({{ distribution_should_use_origin_access_control('foundational_security','cloudfront.13') }}) - union - ({{ distribution_should_use_sni('foundational_security','cloudfront.8') }}) - union - ({{ distribution_should_use_ssl_tls_certificates('foundational_security','cloudfront.7') }}) - union - ({{ documents_should_not_be_public('foundational_security','ssm.4') }}) - union - ({{ ebs_encryption_by_default_disabled('foundational_security','ec2.7') }}) - union - ({{ ebs_snapshot_permissions_check('foundational_security','ec2.1') }}) - union - ({{ ec2_instances_should_be_managed_by_ssm('foundational_security','ssm.1') }}) - union - ({{ ecs_services_with_public_ips('foundational_security','ecs.2') }}) - union - ({{ efs_filesystems_with_disabled_backups('foundational_security','efs.2') }}) - union - ({{ elastic_beanstalk_managed_updates_enabled('foundational_security','elastic_beanstalk.2') }}) - union - ({{ elastic_beanstalk_stream_logs_to_cloudwatch('foundational_security','elastic_beanstalk.3') }}) - union - ({{ elasticsearch_domain_error_logging_to_cloudwatch_logs_should_be_enabled('foundational_security','elastic_search.4') }}) - union - ({{ elasticsearch_domains_should_be_configured_with_at_least_three_dedicated_master_nodes('foundational_security','elastic_search.7') }}) - union - ({{ elasticsearch_domains_should_be_in_vpc('foundational_security','elastic_search.2') }}) - union - ({{ elasticsearch_domains_should_encrypt_data_sent_between_nodes('foundational_security','elastic_search.3') }}) - union - ({{ elasticsearch_domains_should_have_at_least_three_data_nodes('foundational_security','elastic_search.6') }}) - union - ({{ elasticsearch_domains_should_have_audit_logging_enabled('foundational_security','elastic_search.5') }}) - union - ({{ elasticsearch_domains_should_have_encryption_at_rest_enabled('foundational_security','elastic_search.1') }}) - union - ({{ elbv1_cert_provided_by_acm('foundational_security','elb.2') }}) - union - ({{ elbv1_conn_draining_enabled('foundational_security','elb.7') }}) - union - ({{ elbv1_desync_migration_mode_defensive_or_strictest('foundational_security','elb.14') }}) - union - ({{ elbv1_have_cross_zone_load_balancing('foundational_security','elb.9') }}) - union - ({{ elbv1_have_multiple_availability_zones('foundational_security','elb.10') }}) - union - ({{ elbv1_https_or_tls('foundational_security','elb.3') }}) - union - ({{ elbv1_https_predefined_policy('foundational_security','elb.8') }}) - union - ({{ elbv2_desync_migration_mode_defensive_or_strictest('foundational_security','elbv2.12') }}) - union - ({{ elbv2_have_multiple_availability_zones('foundational_security','elbv2.13') }}) - union - ({{ elbv2_redirect_http_to_https('foundational_security','elbv2.1') }}) - union - ({{ emr_cluster_master_nodes_should_not_have_public_ip_addresses('foundational_security','emr.1') }}) - union - ({{ config_enabled_all_regions('foundational_security','awsconfig.1') }}) - union - ({{ cloudtrail_enabled_all_regions('foundational_security','cloudtrail.1') }}) - union - ({{ enhanced_monitoring_should_be_configured_for_instances_and_clusters('foundational_security','rds.6') }}) - union - ({{ fargate_should_run_on_latest_version('foundational_security','ecs.10') }}) - union - ({{ flow_logs_enabled_in_all_vpcs('foundational_security','ec2.6') }}) - union - ({{ hardware_mfa_enabled_for_root('foundational_security','iam.6') }}) - union - ({{ iam_access_keys_rotated_more_than_90_days('foundational_security','iam.3') }}) - union - ({{ iam_access_keys_rotated_more_than_90_days('foundational_security','iam.8') }}) - union - ({{ iam_authentication_should_be_configured_for_rds_clusters('foundational_security','rds.12') }}) - union - ({{ iam_authentication_should_be_configured_for_rds_instances('foundational_security','rds.10') }}) - union - ({{ iam_customer_policy_no_kms_decrypt('foundational_security','kms.1') }}) - union - ({{ iam_inline_policy_no_kms_decrypt('foundational_security','kms.2') }}) - union - ({{ instances_should_be_configured_to_copy_tags_to_snapshots('foundational_security','rds.17') }}) - union - ({{ instances_should_be_configured_with_multiple_azs('foundational_security','rds.5') }}) - union - ({{ instances_should_be_deployed_in_a_vpc('foundational_security','rds.18') }}) - union - ({{ instances_should_have_association_compliance_status_of_compliant('foundational_security','ssm.3') }}) - union - ({{ instances_should_have_deletion_protection_enabled('foundational_security','rds.8') }}) - union - ({{ instances_should_have_ecnryption_at_rest_enabled('foundational_security','rds.3') }}) - union - ({{ instances_should_have_patch_compliance_status_of_compliant('foundational_security','ssm.2') }}) - union - ({{ instances_should_prohibit_public_access('foundational_security','rds.2') }}) - union - ({{ instances_with_more_than_2_network_interfaces('foundational_security','ec2.17') }}) - union - ({{ instances_with_public_ip('foundational_security','ec2.9') }}) - union - ({{ integrated_with_cloudwatch_logs('foundational_security','cloudtrail.5') }}) - union - ({{ key_rotation_enabled('foundational_security','kms.4') }}) - union - ({{ keys_not_unintentionally_deleted('foundational_security','kms.3') }}) - union - ({{ kinesis_stream_encrypted('foundational_security','kinesis') }}) - union - ({{ lambda_function_public_access_prohibited('foundational_security','lambda.1') }}) - union - ({{ lambda_functions_should_use_supported_runtimes('foundational_security','lambda.2') }}) - union - ({{ lambda_inside_vpc('foundational_security','lambda.3') }}) - union - ({{ lambda_vpc_multi_az_check('foundational_security','lambda.5') }}) - union - ({{ launch_templates_should_not_assign_public_ip('foundational_security','ec2.25') }}) - union - ({{ logs_encrypted('foundational_security','cloudtrail.2') }}) - union - ({{ logs_file_validation_enabled('foundational_security','cloudtrail.3') }}) - union - ({{ logs_file_validation_enabled('foundational_security','cloudtrail.4') }}) - union - ({{ mfa_enabled_for_console_access('foundational_security','iam.5') }}) - union - ({{ neptune_cluster_backup_retention_check('foundational_security','neptune.5') }}) - union - ({{ neptune_cluster_cloudwatch_log_export_enabled('foundational_security','neptune.2') }}) - union - ({{ neptune_cluster_copy_tags_to_snapshot_enabled('foundational_security','neptune.8') }}) - union - ({{ neptune_cluster_deletion_protection_enabled('foundational_security','neptune.4') }}) - union - ({{ neptune_cluster_encrypted('foundational_security','neptune.1') }}) - union - ({{ neptune_cluster_iam_database_authentication('foundational_security','neptune.7') }}) - union - ({{ neptune_cluster_snapshot_encrypted('foundational_security','neptune.6') }}) - union - ({{ neptune_cluster_snapshot_public_prohibited('foundational_security','neptune.3') }}) - union - ({{ netfw_policy_default_action_fragment_packets('foundational_security','networkfirewall.5') }}) - union - ({{ netfw_policy_default_action_full_packets('foundational_security','networkfirewall.4') }}) - union - ({{ netfw_policy_rule_group_associated('foundational_security','networkfirewall.3') }}) - union - ({{ netfw_stateless_rule_group_not_empty('foundational_security','networkfirewall.6') }}) - union - ({{ network_acls_should_not_allow_ingress_for_ssh_rdp_ports('foundational_security','ec2.21') }}) - union - ({{ not_imdsv2_instances('foundational_security','ec2.8') }}) - union - ({{ origin_access_identity_enabled('foundational_security','cloudfront.2') }}) - union - ({{ origin_failover_enabled('foundational_security','cloudfront.4') }}) - union - ({{ paravirtual_instances_should_not_be_used('foundational_security','ec2.24') }}) - union - ({{ password_policy_strong('foundational_security','iam.7') }}) - union - ({{ point_in_time_recovery('foundational_security','dynamodb.2') }}) - union - ({{ policies_attached_to_groups_roles('foundational_security','iam.2') }}) - union - ({{ policies_have_wildcard_actions('foundational_security','iam.21') }}) - union - ({{ policies_with_admin_rights('foundational_security','iam.1') }}) - union - ({{ private_repositories_have_image_scanning_configured('foundational_security','ecr.1') }}) - union - ({{ private_repositories_have_tag_immutability_configured('foundational_security','ecr.2') }}) - union - ({{ project_environment_has_logging_aws_configuration('foundational_security','codebuild.4') }}) - union - ({{ project_environment_should_not_have_privileged_mode('foundational_security','codebuild.5') }}) - union - ({{ publicly_readable_buckets('foundational_security','s3.2') }}) - union - ({{ publicly_writable_buckets('foundational_security','s3.3') }}) - union - ({{ rds_automatic_minor_version_upgrades_should_be_enabled('foundational_security','rds.13') }}) - union - ({{ rds_cluster_default_admin_check('foundational_security','rds.24') }}) - union - ({{ rds_cluster_encrypted_at_rest('foundational_security','rds.27') }}) - union - ({{ rds_cluster_event_notifications_configured('foundational_security','rds.19') }}) - union - ({{ rds_instance_default_admin_check('foundational_security','rds.25') }}) - union - ({{ rds_instance_event_notifications_configured('foundational_security','rds.20') }}) - union - ({{ rds_pg_event_notifications_configured('foundational_security','rds.21') }}) - union - ({{ rds_sg_event_notifications_configured('foundational_security','rds.22') }}) - union - ({{ rds_snapshots_public_prohibited('foundational_security','rds.1') }}) - union - ({{ redis_clusters_have_autominorversionupgrade('foundational_security','elasticache.2') }}) - union - ({{ redis_clusters_should_have_automatic_backups('foundational_security','elasticache.1') }}) - union - ({{ redis_replication_groups_automatic_failover_enabled('foundational_security','elasticache.3') }}) - union - ({{ redis_replication_groups_encrypted_at_rest('foundational_security','elasticache.4') }}) - union - ({{ redis_replication_groups_encrypted_in_transit('foundational_security','elasticache.5') }}) - union - ({{ redis_replication_groups_under_version_6_use_auth('foundational_security','elasticache.6') }}) - union - ({{ redshift_cluster_kms_enabled('foundational_security','redshift.10') }}) - union - ({{ redshift_default_admin_check('foundational_security','redshift.8') }}) - union - ({{ redshift_default_db_name_check('foundational_security','redshift.9') }}) - union - ({{ remove_unused_secrets_manager_secrets('foundational_security','secretmanager.3') }}) - union - ({{ replication_not_public('foundational_security','dms.1') }}) - union - ({{ repositories_have_at_least_one_lifecycle_policy('foundational_security','ecr.3') }}) - union - ({{ restrict_cross_account_actions('foundational_security','s3.6') }}) - union - ({{ root_user_no_access_keys('foundational_security','iam.4') }}) - union - ({{ rsa_certificate_key_length_should_be_more_than_2048_bits('foundational_security','acm.2') }}) - union - ({{ s3_bucket_default_lock_enabled('foundational_security','s3.15') }}) - union - ({{ s3_bucket_level_public_access_prohibited('foundational_security','s3.8') }}) - union - ({{ s3_bucket_logging_enabled('foundational_security','s3.9') }}) - union - ({{ s3_event_notifications_enabled('foundational_security','s3.11') }}) - union - ({{ s3_lifecycle_policy_check('foundational_security','s3.13') }}) - union - ({{ s3_logs_encrypted('foundational_security','codebuild.3') }}) - union - ({{ s3_server_side_encryption_enabled('foundational_security','s3.4') }}) - union - ({{ s3_version_lifecycle_policy_check('foundational_security','s3.10') }}) - union - ({{ sagemaker_notebook_instance_direct_internet_access_disabled('foundational_security','sagemaker.1') }}) - union - ({{ sagemaker_notebook_instance_inside_vpc('foundational_security','sagemaker.2') }}) - union - ({{ sagemaker_notebook_instance_root_access_check('foundational_security','sagemaker.3') }}) - union - ({{ secrets_configured_with_automatic_rotation_should_rotate_successfully('foundational_security','secretmanager.2') }}) - union - ({{ secrets_should_be_rotated_within_a_specified_number_of_days('foundational_security','secretmanager.4') }}) - union - ({{ secrets_should_have_automatic_rotation_enabled('foundational_security','secretmanager.1') }}) - union - ({{ secrets_should_not_be_in_environment_variables('foundational_security','ecs.8') }}) - union - ({{ security_account_information_provided('foundational_security','account.1') }}) - union - ({{ security_groups_not_associated('foundational_security','ec2.22') }}) - union - ({{ security_groups_with_access_to_unauthorized_ports('foundational_security','ec2.18') }}) - union - ({{ security_groups_with_open_critical_ports('foundational_security','ec2.19') }}) - union - ({{ sns_topics_should_be_encrypted_at_rest_using_aws_kms('foundational_security','sns.1') }}) - union - ({{ sns_topics_should_have_message_delivery_notification_enabled('foundational_security','sns.2') }}) - union - ({{ sqs_queues_should_be_encrypted_at_rest('foundational_security','sqs.1') }}) - union - ({{ step_functions_state_machine_logging_enabled('foundational_security','stepfunctions.1') }}) - union - ({{ stopped_more_than_30_days_ago_instances('foundational_security','ec2.4') }}) - union - ({{ subnets_that_assign_public_ips('foundational_security','ec2.15') }}) - union - ({{ task_definitions_secure_networking('foundational_security','ecs.1') }}) - union - ({{ task_definitions_should_not_share_host_namespace('foundational_security','ecs.3') }}) - union - ({{ transit_gateways_should_not_auto_accept_vpc_attachments('foundational_security','ec2.23') }}) - union - ({{ unencrypted_ebs_volumes('foundational_security','ec2.3') }}) - union - ({{ unencrypted_efs_filesystems('foundational_security','efs.1') }}) - union - ({{ unused_acls('foundational_security','ec2.16') }}) - union - ({{ viewer_policy_https('foundational_security','cloudfront.3') }}) - union - ({{ vpcs_without_ec2_endpoint('foundational_security','ec2.10') }}) - union - ({{ waf_global_rule_not_empty('foundational_security','waf.6') }}) - union - ({{ waf_global_rulegroup_not_empty('foundational_security','waf.7') }}) - union - ({{ waf_global_webacl_not_empty('foundational_security','waf.8') }}) - union - ({{ waf_regional_rule_not_empty('foundational_security','waf.2') }}) - union - ({{ waf_regional_rulegroup_not_empty('foundational_security','waf.3') }}) - union - ({{ waf_regional_webacl_not_empty('foundational_security','waf.4') }}) - union - ({{ waf_web_acl_logging_should_be_enabled('foundational_security','waf.1') }}) - union - ({{ wafv2_webacl_not_empty('foundational_security','waf.10') }}) + ) select ('{{ run_started_at }}')::timestamp as policy_execution_time, diff --git a/transformations/aws/macros/cloudtrail/bucket_access_logging.sql b/transformations/aws/macros/cloudtrail/bucket_access_logging.sql index 1252c541a..a7469ceeb 100644 --- a/transformations/aws/macros/cloudtrail/bucket_access_logging.sql +++ b/transformations/aws/macros/cloudtrail/bucket_access_logging.sql @@ -18,3 +18,18 @@ select from aws_cloudtrail_trails t inner join aws_s3_buckets b on t.s3_bucket_name = b.name {% endmacro %} + +{% macro bigquery__bucket_access_logging(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket' as title, + t.account_id, + t.arn as resource_id, + case + when b.logging_target_bucket is null or b.logging_target_prefix is null then 'fail' + else 'pass' + end as status +from {{ full_table_name("aws_cloudtrail_trails") }} t +inner join {{ full_table_name("aws_s3_buckets") }} b on t.s3_bucket_name = b.name +{% endmacro %} \ No newline at end of file diff --git a/transformations/aws/macros/cloudtrail/enabled_in_all_regions.sql b/transformations/aws/macros/cloudtrail/enabled_in_all_regions.sql index cde848cba..e43c21741 100644 --- a/transformations/aws/macros/cloudtrail/enabled_in_all_regions.sql +++ b/transformations/aws/macros/cloudtrail/enabled_in_all_regions.sql @@ -23,3 +23,25 @@ inner join and aws_cloudtrail_trails.region = aws_cloudtrail_trail_event_selectors.region and aws_cloudtrail_trails.account_id = aws_cloudtrail_trail_event_selectors.account_id {% endmacro %} + +{% macro bigquery__cloudtrail_enabled_all_regions(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'Ensure CloudTrail is enabled in all regions' as title, + aws_cloudtrail_trails.account_id, + arn as resource_id, + case + when is_multi_region_trail = FALSE or ( + is_multi_region_trail = TRUE and ( + read_write_type != 'All' or include_management_events = FALSE + )) then 'fail' + else 'pass' + end as status +from {{ full_table_name("aws_cloudtrail_trails") }} +inner join + {{ full_table_name("aws_cloudtrail_trail_event_selectors") }} on + aws_cloudtrail_trails.arn = aws_cloudtrail_trail_event_selectors.trail_arn + and aws_cloudtrail_trails.region = aws_cloudtrail_trail_event_selectors.region + and aws_cloudtrail_trails.account_id = aws_cloudtrail_trail_event_selectors.account_id +{% endmacro %} \ No newline at end of file diff --git a/transformations/aws/macros/cloudtrail/integrated_with_cloudwatch_logs.sql b/transformations/aws/macros/cloudtrail/integrated_with_cloudwatch_logs.sql index aa59f79df..260601bf9 100644 --- a/transformations/aws/macros/cloudtrail/integrated_with_cloudwatch_logs.sql +++ b/transformations/aws/macros/cloudtrail/integrated_with_cloudwatch_logs.sql @@ -33,3 +33,19 @@ select end as status from aws_cloudtrail_trails {% endmacro %} + +{% macro bigquery__integrated_with_cloudwatch_logs(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'CloudTrail trails should be integrated with CloudWatch Logs' as title, + account_id, + arn as resource_id, + case + when cloud_watch_logs_log_group_arn is null + OR CAST(JSON_VALUE(status.LatestCloudWatchLogsDeliveryTime) AS timestamp) < TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 1 DAY) + then 'fail' + else 'pass' + end as status +from {{ full_table_name("aws_cloudtrail_trails") }} +{% endmacro %} \ No newline at end of file diff --git a/transformations/aws/macros/cloudtrail/log_file_validation_enabled.sql b/transformations/aws/macros/cloudtrail/log_file_validation_enabled.sql index 7ab5c6b6b..0514239aa 100644 --- a/transformations/aws/macros/cloudtrail/log_file_validation_enabled.sql +++ b/transformations/aws/macros/cloudtrail/log_file_validation_enabled.sql @@ -17,3 +17,17 @@ select end as status from aws_cloudtrail_trails {% endmacro %} + +{% macro bigquery__log_file_validation_enabled(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'Ensure CloudTrail log file validation is enabled' as title, + account_id, + arn as resource_id, + case + when log_file_validation_enabled = false then 'fail' + else 'pass' + end as status +from {{ full_table_name("aws_cloudtrail_trails") }} +{% endmacro %} diff --git a/transformations/aws/macros/cloudtrail/logs_encrypted.sql b/transformations/aws/macros/cloudtrail/logs_encrypted.sql index 9dc560c72..fdc53a2aa 100644 --- a/transformations/aws/macros/cloudtrail/logs_encrypted.sql +++ b/transformations/aws/macros/cloudtrail/logs_encrypted.sql @@ -29,3 +29,17 @@ select end as status FROM aws_cloudtrail_trails {% endmacro %} + +{% macro bigquery__logs_encrypted(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'CloudTrail should have encryption at rest enabled' as title, + account_id, + arn as resource_id, + case + when kms_key_id is NULL then 'fail' + else 'pass' + end as status +FROM {{ full_table_name("aws_cloudtrail_trails") }} +{% endmacro %} diff --git a/transformations/aws/macros/cloudwatch/alarm_aws_config_changes.sql b/transformations/aws/macros/cloudwatch/alarm_aws_config_changes.sql index 08c69a8d1..bea7e254a 100644 --- a/transformations/aws/macros/cloudwatch/alarm_aws_config_changes.sql +++ b/transformations/aws/macros/cloudwatch/alarm_aws_config_changes.sql @@ -20,3 +20,20 @@ select end as status from {{ ref('aws_compliance__log_metric_filter_and_alarm') }} {% endmacro %} + +{% macro bigquery__alarm_aws_config_changes(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'Ensure a log metric filter and alarm exist for AWS Config configuration changes (Scored)' as title, + account_id, + cloud_watch_logs_log_group_arn as resource_id, + case + when pattern NOT LIKE '%NOT%' + AND pattern LIKE '%($.eventSource = kms.amazonaws.com)%' + AND pattern LIKE '%($.eventName = DisableKey)%' + AND pattern LIKE '%($.eventName = ScheduleKeyDeletion)%' then 'pass' + else 'fail' + end as status +from {{ ref('aws_compliance__log_metric_filter_and_alarm') }} +{% endmacro %} diff --git a/transformations/aws/macros/cloudwatch/alarm_console_auth_failure.sql b/transformations/aws/macros/cloudwatch/alarm_console_auth_failure.sql index 386733b49..337062b15 100644 --- a/transformations/aws/macros/cloudwatch/alarm_console_auth_failure.sql +++ b/transformations/aws/macros/cloudwatch/alarm_console_auth_failure.sql @@ -19,3 +19,19 @@ select end as status from {{ ref('aws_compliance__log_metric_filter_and_alarm') }} {% endmacro %} + +{% macro bigquery__alarm_console_auth_failure(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'Ensure a log metric filter and alarm exist for AWS Management Console authentication failures (Scored)' as title, + account_id, + cloud_watch_logs_log_group_arn as resource_id, + case + when pattern NOT LIKE '%NOT%' + AND pattern LIKE '%($.eventName = ConsoleLogin)%' + AND pattern LIKE '%($.errorMessage = "Failed authentication")%' then 'pass' + else 'fail' + end as status +from {{ ref('aws_compliance__log_metric_filter_and_alarm') }} +{% endmacro %} \ No newline at end of file diff --git a/transformations/aws/macros/cloudwatch/alarm_delete_customer_cmk.sql b/transformations/aws/macros/cloudwatch/alarm_delete_customer_cmk.sql index 0ceff6789..305f8e239 100644 --- a/transformations/aws/macros/cloudwatch/alarm_delete_customer_cmk.sql +++ b/transformations/aws/macros/cloudwatch/alarm_delete_customer_cmk.sql @@ -20,3 +20,20 @@ select end as status from {{ ref('aws_compliance__log_metric_filter_and_alarm') }} {% endmacro %} + +{% macro bigquery__alarm_delete_customer_cmk(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs (Scored)' as title, + account_id, + cloud_watch_logs_log_group_arn as resource_id, + case + when pattern NOT LIKE '%NOT%' + AND pattern LIKE '%($.eventSource = kms.amazonaws.com)%' + AND pattern LIKE '%($.eventName=DisableKey)%' + AND pattern LIKE '%($.eventName=ScheduleKeyDeletion)%' then 'pass' + else 'fail' + end as status +from {{ ref('aws_compliance__log_metric_filter_and_alarm') }} +{% endmacro %} diff --git a/transformations/aws/macros/cloudwatch/alarm_iam_policy_change.sql b/transformations/aws/macros/cloudwatch/alarm_iam_policy_change.sql index 6fa3f38a7..05fa46c8b 100644 --- a/transformations/aws/macros/cloudwatch/alarm_iam_policy_change.sql +++ b/transformations/aws/macros/cloudwatch/alarm_iam_policy_change.sql @@ -32,3 +32,32 @@ select end as status from {{ ref('aws_compliance__log_metric_filter_and_alarm') }} {% endmacro %} + +{% macro bigquery__alarm_iam_policy_change(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'Ensure a log metric filter and alarm exist for IAM policy changes (Score)' as title, + account_id, + cloud_watch_logs_log_group_arn as resource_id, + case + when pattern NOT LIKE '%NOT%' + AND pattern LIKE '%($.eventName = DeleteGroupPolicy)%' + AND pattern LIKE '%($.eventName = DeleteUserPolicy)%' + AND pattern LIKE '%($.eventName = PutGroupPolicy)%' + AND pattern LIKE '%($.eventName = PutRolePolicy)%' + AND pattern LIKE '%($.eventName = PutUserPolicy)%' + AND pattern LIKE '%($.eventName = CreatePolicy)%' + AND pattern LIKE '%($.eventName = DeletePolicy)%' + AND pattern LIKE '%($.eventName=CreatePolicyVersion)%' + AND pattern LIKE '%($.eventName=DeletePolicyVersion)%' + AND pattern LIKE '%($.eventName=AttachRolePolicy)%' + AND pattern LIKE '%($.eventName=DetachRolePolicy)%' + AND pattern LIKE '%($.eventName=AttachUserPolicy)%' + AND pattern LIKE '%($.eventName = DetachUserPolicy)%' + AND pattern LIKE '%($.eventName = AttachGroupPolicy)%' + AND pattern LIKE '%($.eventName = DetachGroupPolicy)%' then 'pass' + else 'fail' + end as status +from {{ ref('aws_compliance__log_metric_filter_and_alarm') }} +{% endmacro %} \ No newline at end of file diff --git a/transformations/aws/macros/cloudwatch/alarm_nacl_changes.sql b/transformations/aws/macros/cloudwatch/alarm_nacl_changes.sql index 8aeddca35..8b4d35b83 100644 --- a/transformations/aws/macros/cloudwatch/alarm_nacl_changes.sql +++ b/transformations/aws/macros/cloudwatch/alarm_nacl_changes.sql @@ -23,3 +23,23 @@ select end as status from {{ ref('aws_compliance__log_metric_filter_and_alarm') }} {% endmacro %} + +{% macro bigquery__alarm_nacl_changes(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL) (Scored)' as title, + account_id, + cloud_watch_logs_log_group_arn as resource_id, + case + when pattern NOT LIKE '%NOT%' + AND pattern LIKE '%($.eventName = CreateNetworkAcl)%' + AND pattern LIKE '%($.eventName = CreateNetworkAclEntry)%' + AND pattern LIKE '%($.eventName = DeleteNetworkAcl)%' + AND pattern LIKE '%($.eventName = DeleteNetworkAclEntry)%' + AND pattern LIKE '%($.eventName = ReplaceNetworkAclAssociation)%' + AND pattern LIKE '%($.eventName = ReplaceNetworkAclEntry)%' then 'pass' + else 'fail' + end as status +from {{ ref('aws_compliance__log_metric_filter_and_alarm') }} +{% endmacro %} diff --git a/transformations/aws/macros/cloudwatch/alarm_network_gateways.sql b/transformations/aws/macros/cloudwatch/alarm_network_gateways.sql index 7f41f4263..d4a528a22 100644 --- a/transformations/aws/macros/cloudwatch/alarm_network_gateways.sql +++ b/transformations/aws/macros/cloudwatch/alarm_network_gateways.sql @@ -23,3 +23,23 @@ select end as status from {{ ref('aws_compliance__log_metric_filter_and_alarm') }} {% endmacro %} + +{% macro bigquery__alarm_network_gateways(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'Ensure a log metric filter and alarm exist for changes to network gateways (Scored)' as title, + account_id, + cloud_watch_logs_log_group_arn as resource_id, + case + when pattern NOT LIKE '%NOT%' + AND pattern LIKE '%($.eventName = CreateCustomerGateway)%' + AND pattern LIKE '%($.eventName = DeleteCustomerGateway)%' + AND pattern LIKE '%($.eventName = AttachInternetGateway)%' + AND pattern LIKE '%($.eventName = CreateInternetGateway)%' + AND pattern LIKE '%($.eventName = DeleteInternetGateway)%' + AND pattern LIKE '%($.eventName = DetachInternetGateway)%' then 'pass' + else 'fail' + end as status +from {{ ref('aws_compliance__log_metric_filter_and_alarm') }} +{% endmacro %} diff --git a/transformations/aws/macros/cloudwatch/alarm_root_account.sql b/transformations/aws/macros/cloudwatch/alarm_root_account.sql index 9ac926eef..3cc84c5ea 100644 --- a/transformations/aws/macros/cloudwatch/alarm_root_account.sql +++ b/transformations/aws/macros/cloudwatch/alarm_root_account.sql @@ -17,6 +17,23 @@ select AND pattern LIKE '%$.userIdentity.invokedBy NOT EXISTS%' AND pattern LIKE '%$.eventType != "AwsServiceEvent"%' then 'pass' else 'fail' - end as title + end as status from {{ ref('aws_compliance__log_metric_filter_and_alarm') }} {% endmacro %} + +{% macro bigquery__alarm_root_account(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'Ensure a log metric filter and alarm exist for usage of "root" account (Score)' as title, + account_id, + cloud_watch_logs_log_group_arn as resource_id, + case + when pattern NOT LIKE '%NOT%' + AND pattern LIKE '%$.userIdentity.type = "Root"%' + AND pattern LIKE '%$.userIdentity.invokedBy NOT EXISTS%' + AND pattern LIKE '%$.eventType != "AwsServiceEvent"%' then 'pass' + else 'fail' + end as status +from {{ ref('aws_compliance__log_metric_filter_and_alarm') }} +{% endmacro %} \ No newline at end of file diff --git a/transformations/aws/macros/cloudwatch/alarm_route_table_changes.sql b/transformations/aws/macros/cloudwatch/alarm_route_table_changes.sql index 3e511bcb7..d1a321599 100644 --- a/transformations/aws/macros/cloudwatch/alarm_route_table_changes.sql +++ b/transformations/aws/macros/cloudwatch/alarm_route_table_changes.sql @@ -23,3 +23,23 @@ select end as status from {{ ref('aws_compliance__log_metric_filter_and_alarm') }} {% endmacro %} + +{% macro bigquery__alarm_route_table_changes(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'Ensure a log metric filter and alarm exist for route table changes (Scored)' as title, + account_id, + cloud_watch_logs_log_group_arn, + case when pattern NOT LIKE '%NOT%' + AND pattern LIKE '%($.eventName = CreateRoute)%' + AND pattern LIKE '%($.eventName = CreateRouteTable)%' + AND pattern LIKE '%($.eventName = ReplaceRoute)%' + AND pattern LIKE '%($.eventName = ReplaceRouteTableAssociation)%' + AND pattern LIKE '%($.eventName = DeleteRouteTable)%' + AND pattern LIKE '%($.eventName = DeleteRoute)%' + AND pattern LIKE '%(($.eventName = DisassociateRouteTable)%' then 'pass' + else 'fail' + end as status +from {{ ref('aws_compliance__log_metric_filter_and_alarm') }} +{% endmacro %} diff --git a/transformations/aws/macros/cloudwatch/alarm_s3_bucket_policy_change.sql b/transformations/aws/macros/cloudwatch/alarm_s3_bucket_policy_change.sql index 39579dfeb..818a3d60c 100644 --- a/transformations/aws/macros/cloudwatch/alarm_s3_bucket_policy_change.sql +++ b/transformations/aws/macros/cloudwatch/alarm_s3_bucket_policy_change.sql @@ -27,3 +27,27 @@ select end as status from {{ ref('aws_compliance__log_metric_filter_and_alarm') }} {% endmacro %} + +{% macro bigquery__alarm_s3_bucket_policy_change(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'Ensure a log metric filter and alarm exist for S3 bucket policy changes (Scored)' as title, + account_id, + cloud_watch_logs_log_group_arn as resource_id, + case + when pattern NOT LIKE '%NOT%' + AND pattern LIKE '%($.eventSource = s3.amazonaws.com)%' + AND pattern LIKE '%($.eventName = PutBucketAcl)%' + AND pattern LIKE '%($.eventName = PutBucketPolicy)%' + AND pattern LIKE '%($.eventName = PutBucketCors)%' + AND pattern LIKE '%($.eventName = PutBucketLifecycle)%' + AND pattern LIKE '%($.eventName = PutBucketReplication)%' + AND pattern LIKE '%($.eventName = DeleteBucketPolicy)%' + AND pattern LIKE '%($.eventName = DeleteBucketCors)%' + AND pattern LIKE '%($.eventName = DeleteBucketLifecycle)%' + AND pattern LIKE '%($.eventName = DeleteBucketReplication)%' then 'pass' + else 'fail' + end as status +from {{ ref('aws_compliance__log_metric_filter_and_alarm') }} +{% endmacro %} diff --git a/transformations/aws/macros/cloudwatch/alarm_security_group_changes.sql b/transformations/aws/macros/cloudwatch/alarm_security_group_changes.sql index a0ef977e9..7c7396c45 100644 --- a/transformations/aws/macros/cloudwatch/alarm_security_group_changes.sql +++ b/transformations/aws/macros/cloudwatch/alarm_security_group_changes.sql @@ -22,3 +22,22 @@ select end as status from {{ ref('aws_compliance__log_metric_filter_and_alarm') }} {% endmacro %} + +{% macro bigquery__alarm_security_group_changes(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'Ensure a log metric filter and alarm exist for security group changes (Scored)' as title, + account_id, + cloud_watch_logs_log_group_arn as resource_id, + case when pattern NOT LIKE '%NOT%' + AND pattern LIKE '%($.eventName = AuthorizeSecurityGroupIngress)%' + AND pattern LIKE '%($.eventName = AuthorizeSecurityGroupEgress)%' + AND pattern LIKE '%($.eventName = RevokeSecurityGroupIngress)%' + AND pattern LIKE '%($.eventName = RevokeSecurityGroupEgress)%' + AND pattern LIKE '%($.eventName = CreateSecurityGroup)%' + AND pattern LIKE '%($.eventName = DeleteSecurityGroup)%' then 'pass' + else 'fail' + end as status +from {{ ref('aws_compliance__log_metric_filter_and_alarm') }} +{% endmacro %} diff --git a/transformations/aws/macros/cloudwatch/alarm_unauthorized_api.sql b/transformations/aws/macros/cloudwatch/alarm_unauthorized_api.sql index b81b1931c..04a3b9d0c 100644 --- a/transformations/aws/macros/cloudwatch/alarm_unauthorized_api.sql +++ b/transformations/aws/macros/cloudwatch/alarm_unauthorized_api.sql @@ -18,3 +18,18 @@ select end as status from {{ ref('aws_compliance__log_metric_filter_and_alarm') }} {% endmacro %} + +{% macro bigquery__alarm_unauthorized_api(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'Ensure a log metric filter and alarm exist for Management Console sign-in without MFA (Scored)' as title, + account_id, + cloud_watch_logs_log_group_arn as resource_id, + case when pattern NOT LIKE '%NOT%' + AND pattern LIKE '%($.errorCode = "*UnauthorizedOperation")%' + AND pattern LIKE '%($.errorCode = "AccessDenied*")%' then 'pass' + else 'fail' + end as status +from {{ ref('aws_compliance__log_metric_filter_and_alarm') }} +{% endmacro %} diff --git a/transformations/aws/macros/cloudwatch/alarm_vpc_changes.sql b/transformations/aws/macros/cloudwatch/alarm_vpc_changes.sql index fb6d8d53f..c1e45f1aa 100644 --- a/transformations/aws/macros/cloudwatch/alarm_vpc_changes.sql +++ b/transformations/aws/macros/cloudwatch/alarm_vpc_changes.sql @@ -28,3 +28,28 @@ select end as status from {{ ref('aws_compliance__log_metric_filter_and_alarm') }} {% endmacro %} + +{% macro postgres__bigquery(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'Ensure a log metric filter and alarm exist for VPC changes (Scored)' as title, + account_id, + cloud_watch_logs_log_group_arn as resource_id, + case when pattern NOT LIKE '%NOT%' + AND pattern LIKE '%($.eventName = CreateVpc)%' + AND pattern LIKE '%($.eventName = DeleteVpc)%' + AND pattern LIKE '%($.eventName = ModifyVpcAttribute)%' + AND pattern LIKE '%($.eventName = AcceptVpcPeeringConnection)%' + AND pattern LIKE '%($.eventName = CreateVpcPeeringConnection)%' + AND pattern LIKE '%($.eventName = DeleteVpcPeeringConnection)%' + AND pattern LIKE '%($.eventName = RejectVpcPeeringConnection)%' + AND pattern LIKE '%($.eventName = AttachClassicLinkVpc)%' + AND pattern LIKE '%($.eventName = DetachClassicLinkVpc)%' + AND pattern LIKE '%($.eventName = DisableVpcClassicLink)%' + AND pattern LIKE '%($.eventName = EnableVpcClassicLink)%' + then 'pass' + else 'fail' + end as status +from {{ ref('aws_compliance__log_metric_filter_and_alarm') }} +{% endmacro %} diff --git a/transformations/aws/macros/ec2/default_sg_no_access.sql b/transformations/aws/macros/ec2/default_sg_no_access.sql index e8c8c241e..d5fe77e44 100644 --- a/transformations/aws/macros/ec2/default_sg_no_access.sql +++ b/transformations/aws/macros/ec2/default_sg_no_access.sql @@ -32,7 +32,25 @@ select OR jsonb_array_length(ip_permissions_egress) > 0) then 'fail' else 'pass' - end + end as status from aws_ec2_security_groups {% endmacro %} + +{% macro bigquery__default_sg_no_access(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'The VPC default security group should not allow inbound and outbound traffic' as title, + account_id, + arn, + CASE + WHEN group_name = 'default' + AND ARRAY_LENGTH(JSON_EXTRACT_ARRAY(ip_permissions)) > 0 + OR ARRAY_LENGTH(JSON_EXTRACT_ARRAY(ip_permissions_egress)) > 0 + THEN 'fail' + ELSE 'pass' + END AS status +from + {{ full_table_name("aws_ec2_security_groups") }} +{% endmacro %} diff --git a/transformations/aws/macros/ec2/ec2_security_group_ingress_rules.sql b/transformations/aws/macros/ec2/ec2_security_group_ingress_rules.sql index a77497f10..c5025005c 100644 --- a/transformations/aws/macros/ec2/ec2_security_group_ingress_rules.sql +++ b/transformations/aws/macros/ec2/ec2_security_group_ingress_rules.sql @@ -40,3 +40,46 @@ lateral flatten(input => ip_permissions.value:IpRanges, OUTER => TRUE) as ip_ranges, lateral flatten(input => ip_permissions.value:Ipv6Ranges, OUTER => TRUE) as ip6_ranges {% endmacro %} + +{% macro biguery__ec2_security_group_ingress_rules() %} + WITH + ip_permissions as ( + select + i as value, + account_id, + region, + group_name, + arn, + group_id , + vpc_id, + from {{ full_table_name("aws_ec2_security_groups") }}, + UNNEST(JSON_QUERY_ARRAY(aws_ec2_security_groups.ip_permissions)) as i + ), + ip_ranges as ( + select + ip_ranges as value + FROM ip_permissions, + UNNEST(JSON_QUERY_ARRAY(value.IpRanges)) as ip_ranges + ), + ip6_ranges as ( + select + ip6_ranges as value + FROM ip_permissions, + UNNEST(JSON_QUERY_ARRAY(value.Ipv6Ranges)) as ip6_ranges + ) +select + account_id, + region, + group_name, + arn, + group_id as id, + vpc_id, + CAST(JSON_VALUE(i.value.FromPort) AS INT64) AS from_port, + CAST(JSON_VALUE(i.value.ToPort) AS INT64) AS to_port, + JSON_VALUE(i.value.IpProtocol) AS ip_protocol, + JSON_VALUE(ip_ranges.value.CidrIp) AS ip, + JSON_VALUE(ip6_ranges.value.CidrIpv6) AS ip6 + from ip_permissions as i + LEFT JOIN ip_ranges ON TRUE + LEFT JOIN ip6_ranges ON TRUE +{% endmacro %} \ No newline at end of file diff --git a/transformations/aws/macros/ec2/flow_logs_enabled_in_all_vpcs.sql b/transformations/aws/macros/ec2/flow_logs_enabled_in_all_vpcs.sql index cf58e165c..4ebaa8381 100644 --- a/transformations/aws/macros/ec2/flow_logs_enabled_in_all_vpcs.sql +++ b/transformations/aws/macros/ec2/flow_logs_enabled_in_all_vpcs.sql @@ -35,3 +35,20 @@ from aws_ec2_vpcs left join aws_ec2_flow_logs on aws_ec2_vpcs.vpc_id = aws_ec2_flow_logs.resource_id {% endmacro %} + +{% macro bigquery__flow_logs_enabled_in_all_vpcs(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'VPC flow logging should be enabled in all VPCs' as title, + aws_ec2_vpcs.account_id, + aws_ec2_vpcs.arn, + case when + aws_ec2_flow_logs.resource_id is null + then 'fail' + else 'pass' + end +from {{ full_table_name("aws_ec2_vpcs") }} +left join {{ full_table_name("aws_ec2_flow_logs") }} on + aws_ec2_vpcs.vpc_id = aws_ec2_flow_logs.resource_id +{% endmacro %} \ No newline at end of file diff --git a/transformations/aws/macros/ec2/no_broad_public_ingress_on_port_22.sql b/transformations/aws/macros/ec2/no_broad_public_ingress_on_port_22.sql index 7d3816d88..8cde79c80 100644 --- a/transformations/aws/macros/ec2/no_broad_public_ingress_on_port_22.sql +++ b/transformations/aws/macros/ec2/no_broad_public_ingress_on_port_22.sql @@ -22,3 +22,21 @@ select end from {{ ref('aws_compliance__security_group_ingress_rules') }} {% endmacro %} + +{% macro bigquery__no_broad_public_ingress_on_port_22(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'Ensure no security groups allow ingress from 0.0.0.0/0 to port 22 (Scored)' as title, + account_id, + arn, + case when + (ip = '0.0.0.0/0' or ip = '::/0') + and ( + (from_port is null and to_port is null) -- all ports + or 22 between from_port and to_port) + then 'fail' + else 'pass' + end +from {{ ref('aws_compliance__security_group_ingress_rules') }} +{% endmacro %} \ No newline at end of file diff --git a/transformations/aws/macros/ec2/no_broad_public_ingress_on_port_3389.sql b/transformations/aws/macros/ec2/no_broad_public_ingress_on_port_3389.sql index 8323527b0..1e802fd2d 100644 --- a/transformations/aws/macros/ec2/no_broad_public_ingress_on_port_3389.sql +++ b/transformations/aws/macros/ec2/no_broad_public_ingress_on_port_3389.sql @@ -22,3 +22,22 @@ select end from {{ ref('aws_compliance__security_group_ingress_rules') }} {% endmacro %} + +{% macro bigquery__no_broad_public_ingress_on_port_3389(framework, check_id) %} +-- uses view which uses aws_security_group_ingress_rules.sql query +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'Ensure no security groups allow ingress from 0.0.0.0/0 to port 3389 (Scored)' as title, + account_id, + arn, + case when + (ip = '0.0.0.0/0' or ip = '::/0') + and ( + (from_port is null and to_port is null) -- all ports + or 3389 between from_port and to_port + ) then 'fail' + else 'pass' + end +from {{ ref('aws_compliance__security_group_ingress_rules') }} +{% endmacro %} diff --git a/transformations/aws/macros/efs/access_point_enforce_user_identity.sql b/transformations/aws/macros/efs/access_point_enforce_user_identity.sql index 43d4bc69b..75f490e26 100644 --- a/transformations/aws/macros/efs/access_point_enforce_user_identity.sql +++ b/transformations/aws/macros/efs/access_point_enforce_user_identity.sql @@ -1,3 +1,5 @@ +{{ config(enabled=is_snowflake()) }} + {% macro access_point_enforce_user_identity(framework, check_id) %} {{ return(adapter.dispatch('access_point_enforce_user_identity')(framework, check_id)) }} {% endmacro %} @@ -22,7 +24,7 @@ FROM aws_efs_access_points {% endmacro %} -{% macro bigquery__(framework, check_id) %} +{% macro bigquery__access_point_enforce_user_identity(framework, check_id) %} select '{{framework}}' As framework, '{{check_id}}' As check_id, diff --git a/transformations/aws/macros/iam/hardware_mfa_enabled_for_root.sql b/transformations/aws/macros/iam/hardware_mfa_enabled_for_root.sql index 1bd24a83b..5af5f34b5 100644 --- a/transformations/aws/macros/iam/hardware_mfa_enabled_for_root.sql +++ b/transformations/aws/macros/iam/hardware_mfa_enabled_for_root.sql @@ -39,3 +39,22 @@ left join where cr.user = '' group by mfa.serial_number, cr.mfa_active, cr.arn {% endmacro %} + +{% macro bigquery__hardware_mfa_enabled_for_root(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'Ensure hardware MFA is enabled for the "root" account (Scored)' as title, + SPLIT(cr.arn, ':')[SAFE_OFFSET(4)] AS account_id, + cr.arn as resource_id, + case + when mfa.serial_number is null or cr.mfa_active = FALSE then 'fail' + when mfa.serial_number is not null and cr.mfa_active = TRUE then 'pass' + end as status +from {{ full_table_name("aws_iam_credential_reports") }} cr +left join + {{ full_table_name("aws_iam_virtual_mfa_devices") }} mfa on + JSON_VALUE(mfa.user.Arn) = cr.arn +where cr.user = '' +group by mfa.serial_number, cr.mfa_active, cr.arn +{% endmacro %} diff --git a/transformations/aws/macros/iam/mfa_enabled_for_console_access.sql b/transformations/aws/macros/iam/mfa_enabled_for_console_access.sql index 941e16290..e2b2b5d71 100644 --- a/transformations/aws/macros/iam/mfa_enabled_for_console_access.sql +++ b/transformations/aws/macros/iam/mfa_enabled_for_console_access.sql @@ -32,7 +32,7 @@ select from aws_iam_credential_reports {% endmacro %} -{% macro bigquery__(framework, check_id) %} +{% macro bigquery__mfa_enabled_for_console_access(framework, check_id) %} select '{{framework}}' As framework, '{{check_id}}' As check_id, diff --git a/transformations/aws/macros/iam/mfa_enabled_for_root.sql b/transformations/aws/macros/iam/mfa_enabled_for_root.sql index 6142b2294..80dbcaf68 100644 --- a/transformations/aws/macros/iam/mfa_enabled_for_root.sql +++ b/transformations/aws/macros/iam/mfa_enabled_for_root.sql @@ -17,3 +17,17 @@ select end as status from aws_iam_credential_reports {% endmacro %} + +{% macro bigquery__mfa_enabled_for_root(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'Ensure MFA is enabled for the "root" account' as title, + SPLIT(arn, ':')[SAFE_OFFSET(4)] AS account_id, + arn as resource_id, + case + when user = '' and not mfa_active then 'fail' -- TODO check + when user = '' and mfa_active then 'pass' + end as status +from {{ full_table_name("aws_iam_credential_reports") }} +{% endmacro %} diff --git a/transformations/aws/macros/iam/password_policy_expire_old_passwords.sql b/transformations/aws/macros/iam/password_policy_expire_old_passwords.sql index c74390a1e..2bfd544a1 100644 --- a/transformations/aws/macros/iam/password_policy_expire_old_passwords.sql +++ b/transformations/aws/macros/iam/password_policy_expire_old_passwords.sql @@ -19,3 +19,19 @@ select from aws_iam_password_policies {% endmacro %} + +{% macro bigquery__password_policy_expire_old_passwords(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'Ensure IAM password policy expires passwords within 90 days or less' as title, + account_id, + account_id, + case when + (max_password_age is null or max_password_age > 90) or policy_exists = false + then 'fail' + else 'pass' + end +from + {{ full_table_name("aws_iam_password_policies") }} +{% endmacro %} diff --git a/transformations/aws/macros/iam/password_policy_min_length.sql b/transformations/aws/macros/iam/password_policy_min_length.sql index 4ed62e538..79267f247 100644 --- a/transformations/aws/macros/iam/password_policy_min_length.sql +++ b/transformations/aws/macros/iam/password_policy_min_length.sql @@ -19,3 +19,19 @@ select from aws_iam_password_policies {% endmacro %} + +{% macro bigquery__password_policy_min_length(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'Ensure IAM password policy requires minimum length of 14 or greater' as title, + account_id, + account_id, + case when + (minimum_password_length < 14) or policy_exists = FALSE + then 'fail' + else 'pass' + end +from + {{ full_table_name("aws_iam_password_policies") }} +{% endmacro %} diff --git a/transformations/aws/macros/iam/password_policy_min_number.sql b/transformations/aws/macros/iam/password_policy_min_number.sql index 509c2d06c..bbe894c72 100644 --- a/transformations/aws/macros/iam/password_policy_min_number.sql +++ b/transformations/aws/macros/iam/password_policy_min_number.sql @@ -18,5 +18,20 @@ select end as status from aws_iam_password_policies - {% endmacro %} + +{% macro bigquery__password_policy_min_number(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'Ensure IAM password policy requires at least one number' as title, + account_id, + account_id, + case when + require_numbers = FALSE or policy_exists = FALSE + then 'fail' + else 'pass' + end as status +from + {{ full_table_name("aws_iam_password_policies") }} +{% endmacro %} \ No newline at end of file diff --git a/transformations/aws/macros/iam/password_policy_min_one_symbol.sql b/transformations/aws/macros/iam/password_policy_min_one_symbol.sql index 5eef88ec6..a87f17e42 100644 --- a/transformations/aws/macros/iam/password_policy_min_one_symbol.sql +++ b/transformations/aws/macros/iam/password_policy_min_one_symbol.sql @@ -19,3 +19,19 @@ select from aws_iam_password_policies {% endmacro %} + +{% macro bigquery__password_policy_min_one_symbol(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'Ensure IAM password policy requires at least one symbol' as title, + account_id, + account_id, + case when + require_symbols = false or policy_exists = false + then 'fail' + else 'pass' + end as status +from + {{ full_table_name("aws_iam_password_policies") }} +{% endmacro %} \ No newline at end of file diff --git a/transformations/aws/macros/iam/password_policy_prevent_reuse.sql b/transformations/aws/macros/iam/password_policy_prevent_reuse.sql index 3d0ed1377..5fe3eb9d4 100644 --- a/transformations/aws/macros/iam/password_policy_prevent_reuse.sql +++ b/transformations/aws/macros/iam/password_policy_prevent_reuse.sql @@ -19,3 +19,19 @@ select from aws_iam_password_policies {% endmacro %} + +{% macro bigquery__password_policy_prevent_reuse(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'Ensure IAM password policy prevents password reuse' as title, + account_id, + account_id, + case when + password_reuse_prevention is distinct from 24 + then 'fail' + else 'pass' + end +from + {{ full_table_name("aws_iam_password_policies") }} +{% endmacro %} diff --git a/transformations/aws/macros/iam/policies_attached_to_groups_roles.sql b/transformations/aws/macros/iam/policies_attached_to_groups_roles.sql index 5bb383b3c..92404842d 100644 --- a/transformations/aws/macros/iam/policies_attached_to_groups_roles.sql +++ b/transformations/aws/macros/iam/policies_attached_to_groups_roles.sql @@ -34,3 +34,22 @@ from aws_iam_users left join aws_iam_user_attached_policies on aws_iam_users.arn = aws_iam_user_attached_policies.user_arn left join aws_iam_user_policies on aws_iam_users.arn = aws_iam_user_policies.user_arn {% endmacro %} + +{% macro bigquery__policies_attached_to_groups_roles(framework, check_id) %} +select distinct + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'IAM users should not have IAM policies attached' as title, + aws_iam_users.account_id, + arn AS resource_id, + case + when + aws_iam_user_attached_policies.user_arn is not null + or aws_iam_user_policies.user_arn is not null + then 'fail' + else 'pass' + end as status +from {{ full_table_name("aws_iam_users") }} +left join {{ full_table_name("aws_iam_user_attached_policies") }} on aws_iam_users.arn = aws_iam_user_attached_policies.user_arn +left join {{ full_table_name("aws_iam_user_policies") }} on aws_iam_users.arn = aws_iam_user_policies.user_arn +{% endmacro %} \ No newline at end of file diff --git a/transformations/aws/macros/iam/root_user_no_access_keys.sql b/transformations/aws/macros/iam/root_user_no_access_keys.sql index ed85ac79b..460c224be 100644 --- a/transformations/aws/macros/iam/root_user_no_access_keys.sql +++ b/transformations/aws/macros/iam/root_user_no_access_keys.sql @@ -31,3 +31,18 @@ select end from aws_iam_user_access_keys {% endmacro %} + +{% macro bigquery__root_user_no_access_keys(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'Ensure no root account access key exists (Scored)' as title, + account_id, + user_arn AS resource_id, + case when + user_name IN ('', '') + then 'fail' + else 'pass' + end +from {{ full_table_name("aws_iam_user_access_keys") }} +{% endmacro %} diff --git a/transformations/aws/macros/kms/rotation_enabled_for_customer_key.sql b/transformations/aws/macros/kms/rotation_enabled_for_customer_key.sql index a01898837..703af914a 100644 --- a/transformations/aws/macros/kms/rotation_enabled_for_customer_key.sql +++ b/transformations/aws/macros/kms/rotation_enabled_for_customer_key.sql @@ -18,3 +18,18 @@ select end from aws_kms_keys {% endmacro %} + +{% macro bigquery__rotation_enabled_for_customer_key(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'Ensure rotation for customer created custom master keys is enabled (Scored)' as title, + account_id, + arn, + case when + rotation_enabled is FALSE and key_manager = 'CUSTOMER' + then 'fail' + else 'pass' + end +from {{ full_table_name("aws_kms_keys") }} +{% endmacro %} diff --git a/transformations/aws/macros/log_metric_filter_and_alarm.sql b/transformations/aws/macros/log_metric_filter_and_alarm.sql new file mode 100644 index 000000000..1e8b4d729 --- /dev/null +++ b/transformations/aws/macros/log_metric_filter_and_alarm.sql @@ -0,0 +1,49 @@ +{% macro log_metric_filter_and_alarm(framework, check_id) %} + {{ return(adapter.dispatch('log_metric_filter_and_alarm')()) }} +{% endmacro %} + +{% macro default__log_metric_filter_and_alarm() %}{% endmacro %} + +{% macro postgres__log_metric_filter_and_alarm() %} +with af as ( + select distinct a.arn, a.actions_enabled, a.alarm_actions, m->'MetricStat'->'Metric'->>'MetricName' as metric_name -- TODO check + from aws_cloudwatch_alarms a, jsonb_array_elements(a.metrics) as m +) +select + t.account_id, + t.region, + t.cloud_watch_logs_log_group_arn, + mf.filter_pattern as pattern +from aws_cloudtrail_trails t +inner join aws_cloudtrail_trail_event_selectors tes on t.arn = tes.trail_arn +inner join aws_cloudwatchlogs_metric_filters mf on mf.log_group_name = t.cloudwatch_logs_log_group_name +inner join af on mf.filter_name = af.metric_name +inner join aws_sns_subscriptions ss on ss.topic_arn = ANY(af.alarm_actions) +where t.is_multi_region_trail = TRUE + and (t.status->>'IsLogging')::boolean = TRUE + and tes.include_management_events = TRUE + and tes.read_write_type = 'All' + and ss.arn like 'aws:arn:%' +{% endmacro %} + +{% macro bigquery__log_metric_filter_and_alarm() %} +with af as ( + select distinct a.arn, a.actions_enabled, ARRAY_TO_STRING(a.alarm_actions, ',') as alarm_actions, JSON_VALUE(m.MetricStat.Metric.MetricName) as metric_name -- TODO check + from {{ full_table_name("aws_cloudwatch_alarms") }} a, UNNEST(JSON_QUERY_ARRAY(metrics)) as m +) +select + t.account_id, + t.region, + t.cloud_watch_logs_log_group_arn, + mf.filter_pattern as pattern +from {{ full_table_name("aws_cloudtrail_trails") }} t +inner join {{ full_table_name("aws_cloudtrail_trail_event_selectors") }} tes on t.arn = tes.trail_arn +inner join {{ full_table_name("aws_cloudwatchlogs_metric_filters") }} mf on mf.log_group_name = t.cloudwatch_logs_log_group_name +inner join af on mf.filter_name = af.metric_name +inner join {{ full_table_name("aws_sns_subscriptions") }} ss on ss.topic_arn in UNNEST(SPLIT(af.alarm_actions, ',')) +where t.is_multi_region_trail = TRUE + and CAST( JSON_VALUE(t.status.IsLogging) AS BOOL) = TRUE + and tes.include_management_events = TRUE + and tes.read_write_type = 'All' + and ss.arn like 'aws:arn:%' +{% endmacro %} diff --git a/transformations/aws/models/aws_compliance__log_metric_filter_and_alarm.sql b/transformations/aws/models/aws_compliance__log_metric_filter_and_alarm.sql index 705ce2ba4..d6dbe90a5 100644 --- a/transformations/aws/models/aws_compliance__log_metric_filter_and_alarm.sql +++ b/transformations/aws/models/aws_compliance__log_metric_filter_and_alarm.sql @@ -1,19 +1,5 @@ -with af as ( - select distinct a.arn, a.actions_enabled, a.alarm_actions, m->'MetricStat'->'Metric'->>'MetricName' as metric_name -- TODO check - from aws_cloudwatch_alarms a, jsonb_array_elements(a.metrics) as m -) -select - t.account_id, - t.region, - t.cloud_watch_logs_log_group_arn, - mf.filter_pattern as pattern -from aws_cloudtrail_trails t -inner join aws_cloudtrail_trail_event_selectors tes on t.arn = tes.trail_arn -inner join aws_cloudwatchlogs_metric_filters mf on mf.log_group_name = t.cloudwatch_logs_log_group_name -inner join af on mf.filter_name = af.metric_name -inner join aws_sns_subscriptions ss on ss.topic_arn = ANY(af.alarm_actions) -where t.is_multi_region_trail = TRUE - and (t.status->>'IsLogging')::boolean = TRUE - and tes.include_management_events = TRUE - and tes.read_write_type = 'All' - and ss.arn like 'aws:arn:%' +with + aggregated as ( + ({{ log_metric_filter_and_alarm() }}) + ) +select * from aggregated