diff --git a/.gitignore b/.gitignore index d48b33794..61e3fb1a7 100644 --- a/.gitignore +++ b/.gitignore @@ -157,7 +157,7 @@ cython_debug/ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore # and can be added to the global gitignore or merged into this file. For a more nuclear # option (not recommended) you can uncomment the following to ignore the entire idea folder. -#.idea/ +.idea/ .DS_Store transformations/aws_compliance/.user.yml diff --git a/transformations/aws/asset-inventory-free/manifest.json b/transformations/aws/asset-inventory-free/manifest.json index 9fb912ffd..089fec786 100644 --- a/transformations/aws/asset-inventory-free/manifest.json +++ b/transformations/aws/asset-inventory-free/manifest.json @@ -8,6 +8,6 @@ "message": "@./changelog.md", "doc": "./README.md", "path": "./build/aws_asset_inventory_free.zip", - "plugin_deps": ["cloudquery/source/aws@v22.19.0"], + "plugin_deps": ["cloudquery/source/aws@v23.3.1"], "addon_deps": [] } diff --git a/transformations/aws/asset-inventory-free/tests/postgres.yml b/transformations/aws/asset-inventory-free/tests/postgres.yml index b471a3da6..6b4cc4b5b 100644 --- a/transformations/aws/asset-inventory-free/tests/postgres.yml +++ b/transformations/aws/asset-inventory-free/tests/postgres.yml @@ -2,7 +2,8 @@ kind: source spec: name: aws path: cloudquery/aws - version: "v22.19.2" # latest version of source aws plugin + registry: cloudquery + version: "v23.3.1" # latest version of source aws plugin destinations: ["postgresql"] tables: ["*"] --- @@ -14,4 +15,4 @@ spec: version: "v7.1.3" # latest version of postgresql plugin spec: batch_size: 10000 - connection_string: ${CQ_DSN} \ No newline at end of file + connection_string: ${CQ_DSN} diff --git a/transformations/aws/compliance-free/manifest.json b/transformations/aws/compliance-free/manifest.json index 3239855fe..ecfe1a367 100644 --- a/transformations/aws/compliance-free/manifest.json +++ b/transformations/aws/compliance-free/manifest.json @@ -8,6 +8,6 @@ "message": "@./changelog.md", "doc": "./README.md", "path": "./build/aws_compliance_free.zip", - "plugin_deps": ["cloudquery/source/aws@v22.18.0"], + "plugin_deps": ["cloudquery/source/aws@v23.3.1"], "addon_deps": [] } diff --git a/transformations/aws/compliance-free/tests/bigquery.yml b/transformations/aws/compliance-free/tests/bigquery.yml index fcb4e3992..4e5febc5d 100644 --- a/transformations/aws/compliance-free/tests/bigquery.yml +++ b/transformations/aws/compliance-free/tests/bigquery.yml @@ -2,7 +2,8 @@ kind: source spec: name: aws path: cloudquery/aws - version: "v22.19.2" # latest version of source aws plugin + registry: cloudquery + version: "v23.3.1" # latest version of source aws plugin destinations: ["bigquery"] tables: ["*"] --- @@ -15,4 +16,4 @@ spec: write_mode: "append" spec: project_id: cq-integration-tests - dataset_id: policies_premium_ci_test \ No newline at end of file + dataset_id: policies_premium_ci_test diff --git a/transformations/aws/compliance-free/tests/postgres.yml b/transformations/aws/compliance-free/tests/postgres.yml index b471a3da6..6b4cc4b5b 100644 --- a/transformations/aws/compliance-free/tests/postgres.yml +++ b/transformations/aws/compliance-free/tests/postgres.yml @@ -2,7 +2,8 @@ kind: source spec: name: aws path: cloudquery/aws - version: "v22.19.2" # latest version of source aws plugin + registry: cloudquery + version: "v23.3.1" # latest version of source aws plugin destinations: ["postgresql"] tables: ["*"] --- @@ -14,4 +15,4 @@ spec: version: "v7.1.3" # latest version of postgresql plugin spec: batch_size: 10000 - connection_string: ${CQ_DSN} \ No newline at end of file + connection_string: ${CQ_DSN} diff --git a/transformations/aws/compliance-free/tests/snowflake.yml b/transformations/aws/compliance-free/tests/snowflake.yml index cecf7b64e..3a384a5a9 100644 --- a/transformations/aws/compliance-free/tests/snowflake.yml +++ b/transformations/aws/compliance-free/tests/snowflake.yml @@ -2,7 +2,8 @@ kind: source spec: name: aws path: cloudquery/aws - version: "v22.19.2" # latest version of source aws plugin + registry: cloudquery + version: "v23.3.1" # latest version of source aws plugin destinations: ["snowflake"] tables: ["*"] --- diff --git a/transformations/aws/compliance-premium/manifest.json b/transformations/aws/compliance-premium/manifest.json index df2e14ab6..173311720 100644 --- a/transformations/aws/compliance-premium/manifest.json +++ b/transformations/aws/compliance-premium/manifest.json @@ -8,6 +8,6 @@ "message": "@./changelog.md", "doc": "./README.md", "path": "./build/aws_compliance_premium.zip", - "plugin_deps": ["cloudquery/source/aws@v22.18.0"], + "plugin_deps": ["cloudquery/source/aws@v23.3.1"], "addon_deps": [] } diff --git a/transformations/aws/compliance-premium/tests/bigquery.yml b/transformations/aws/compliance-premium/tests/bigquery.yml index fcb4e3992..4e5febc5d 100644 --- a/transformations/aws/compliance-premium/tests/bigquery.yml +++ b/transformations/aws/compliance-premium/tests/bigquery.yml @@ -2,7 +2,8 @@ kind: source spec: name: aws path: cloudquery/aws - version: "v22.19.2" # latest version of source aws plugin + registry: cloudquery + version: "v23.3.1" # latest version of source aws plugin destinations: ["bigquery"] tables: ["*"] --- @@ -15,4 +16,4 @@ spec: write_mode: "append" spec: project_id: cq-integration-tests - dataset_id: policies_premium_ci_test \ No newline at end of file + dataset_id: policies_premium_ci_test diff --git a/transformations/aws/compliance-premium/tests/postgres.yml b/transformations/aws/compliance-premium/tests/postgres.yml index b471a3da6..6b4cc4b5b 100644 --- a/transformations/aws/compliance-premium/tests/postgres.yml +++ b/transformations/aws/compliance-premium/tests/postgres.yml @@ -2,7 +2,8 @@ kind: source spec: name: aws path: cloudquery/aws - version: "v22.19.2" # latest version of source aws plugin + registry: cloudquery + version: "v23.3.1" # latest version of source aws plugin destinations: ["postgresql"] tables: ["*"] --- @@ -14,4 +15,4 @@ spec: version: "v7.1.3" # latest version of postgresql plugin spec: batch_size: 10000 - connection_string: ${CQ_DSN} \ No newline at end of file + connection_string: ${CQ_DSN} diff --git a/transformations/aws/compliance-premium/tests/snowflake.yml b/transformations/aws/compliance-premium/tests/snowflake.yml index cecf7b64e..3a384a5a9 100644 --- a/transformations/aws/compliance-premium/tests/snowflake.yml +++ b/transformations/aws/compliance-premium/tests/snowflake.yml @@ -2,7 +2,8 @@ kind: source spec: name: aws path: cloudquery/aws - version: "v22.19.2" # latest version of source aws plugin + registry: cloudquery + version: "v23.3.1" # latest version of source aws plugin destinations: ["snowflake"] tables: ["*"] --- diff --git a/transformations/aws/cost/tests/postgres.yml b/transformations/aws/cost/tests/postgres.yml index b471a3da6..6b4cc4b5b 100644 --- a/transformations/aws/cost/tests/postgres.yml +++ b/transformations/aws/cost/tests/postgres.yml @@ -2,7 +2,8 @@ kind: source spec: name: aws path: cloudquery/aws - version: "v22.19.2" # latest version of source aws plugin + registry: cloudquery + version: "v23.3.1" # latest version of source aws plugin destinations: ["postgresql"] tables: ["*"] --- @@ -14,4 +15,4 @@ spec: version: "v7.1.3" # latest version of postgresql plugin spec: batch_size: 10000 - connection_string: ${CQ_DSN} \ No newline at end of file + connection_string: ${CQ_DSN} diff --git a/transformations/aws/data-resilience/manifest.json b/transformations/aws/data-resilience/manifest.json index 29872780d..cba8baa24 100644 --- a/transformations/aws/data-resilience/manifest.json +++ b/transformations/aws/data-resilience/manifest.json @@ -8,6 +8,6 @@ "message": "@./changelog.md", "doc": "./README.md", "path": "./build/aws_data_resilience.zip", - "plugin_deps": ["cloudquery/source/aws@v22.19.0"], + "plugin_deps": ["cloudquery/source/aws@v23.3.1"], "addon_deps": [] } diff --git a/transformations/aws/data-resilience/tests/postgres.yml b/transformations/aws/data-resilience/tests/postgres.yml index b471a3da6..6b4cc4b5b 100644 --- a/transformations/aws/data-resilience/tests/postgres.yml +++ b/transformations/aws/data-resilience/tests/postgres.yml @@ -2,7 +2,8 @@ kind: source spec: name: aws path: cloudquery/aws - version: "v22.19.2" # latest version of source aws plugin + registry: cloudquery + version: "v23.3.1" # latest version of source aws plugin destinations: ["postgresql"] tables: ["*"] --- @@ -14,4 +15,4 @@ spec: version: "v7.1.3" # latest version of postgresql plugin spec: batch_size: 10000 - connection_string: ${CQ_DSN} \ No newline at end of file + connection_string: ${CQ_DSN} diff --git a/transformations/aws/encryption/manifest.json b/transformations/aws/encryption/manifest.json index 06172bb30..8dbcf15ad 100644 --- a/transformations/aws/encryption/manifest.json +++ b/transformations/aws/encryption/manifest.json @@ -8,6 +8,6 @@ "message": "@./changelog.md", "doc": "./README.md", "path": "./build/aws_encryption.zip", - "plugin_deps": ["cloudquery/source/aws@v22.19.0"], + "plugin_deps": ["cloudquery/source/aws@v23.3.1"], "addon_deps": [] } diff --git a/transformations/aws/encryption/tests/postgres.yml b/transformations/aws/encryption/tests/postgres.yml index b471a3da6..6b4cc4b5b 100644 --- a/transformations/aws/encryption/tests/postgres.yml +++ b/transformations/aws/encryption/tests/postgres.yml @@ -2,7 +2,8 @@ kind: source spec: name: aws path: cloudquery/aws - version: "v22.19.2" # latest version of source aws plugin + registry: cloudquery + version: "v23.3.1" # latest version of source aws plugin destinations: ["postgresql"] tables: ["*"] --- @@ -14,4 +15,4 @@ spec: version: "v7.1.3" # latest version of postgresql plugin spec: batch_size: 10000 - connection_string: ${CQ_DSN} \ No newline at end of file + connection_string: ${CQ_DSN} diff --git a/transformations/aws/macros/cloudtrail/bucket_access_logging.sql b/transformations/aws/macros/cloudtrail/bucket_access_logging.sql index 75ca04ddb..98b6619f6 100644 --- a/transformations/aws/macros/cloudtrail/bucket_access_logging.sql +++ b/transformations/aws/macros/cloudtrail/bucket_access_logging.sql @@ -12,11 +12,14 @@ select 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' + when l.logging_enabled is null then 'fail' + when l.logging_enabled -> 'TargetBucket' is null then 'fail' + when l.logging_enabled -> 'TargetPrefix' is null then 'fail' else 'pass' end as status from aws_cloudtrail_trails t inner join aws_s3_buckets b on t.s3_bucket_name = b.name +inner join aws_s3_bucket_loggings l on b.arn = l.bucket_arn {% endmacro %} {% macro bigquery__bucket_access_logging(framework, check_id) %} @@ -27,11 +30,14 @@ select 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' + when l.logging_enabled is null then 'fail' + when l.logging_enabled.TargetBucket is null then 'fail' + when l.logging_enabled.TargetPrefix 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 +inner join {{ full_table_name("aws_s3_bucket_loggings") }} l on b.arn = l.bucket_arn {% endmacro %} {% macro snowflake__bucket_access_logging(framework, check_id) %} @@ -42,9 +48,12 @@ select 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' + when l.logging_enabled is null then 'fail' + when l.logging_enabled:TargetBucket is null then 'fail' + when l.logging_enabled:TargetPrefix is null then 'fail' else 'pass' end as status from aws_cloudtrail_trails t inner join aws_s3_buckets b on t.s3_bucket_name = b.name -{% endmacro %} \ No newline at end of file +inner join aws_s3_bucket_loggings l on b.arn = l.bucket_arn +{% endmacro %} diff --git a/transformations/aws/macros/cloudtrail/enabled_in_all_regions.sql b/transformations/aws/macros/cloudtrail/enabled_in_all_regions.sql index 09c8dbc96..2e2b916fd 100644 --- a/transformations/aws/macros/cloudtrail/enabled_in_all_regions.sql +++ b/transformations/aws/macros/cloudtrail/enabled_in_all_regions.sql @@ -10,10 +10,17 @@ select 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' + when aws_cloudtrail_trails.is_multi_region_trail = FALSE then 'fail' + when exists(select * + from jsonb_array_elements(aws_cloudtrail_trail_event_selectors.event_selectors) as es + where es ->>'ReadWriteType' != 'All' or (es->>'IncludeManagementEvents')::boolean = FALSE) + then 'fail' + when exists(select * + from jsonb_array_elements(aws_cloudtrail_trail_event_selectors.advanced_event_selectors) as aes + where exists(select * + from jsonb_array_elements(aes ->'FieldSelectors') as aes_fs + where aes_fs ->>'Field' = 'readOnly')) + then 'fail' else 'pass' end as status from aws_cloudtrail_trails @@ -32,10 +39,18 @@ select 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' + when aws_cloudtrail_trails.is_multi_region_trail = FALSE then 'fail' + when exists(select * + from UNNEST(JSON_QUERY_ARRAY(aws_cloudtrail_trail_event_selectors.event_selectors)) AS es + where JSON_VALUE(es.ReadWriteType) != 'All' or (CAST( JSON_VALUE(es.IncludeManagementEvents) AS BOOL)= FALSE ) + ) + then 'fail' + when exists(select * + from UNNEST(JSON_QUERY_ARRAY(aws_cloudtrail_trail_event_selectors.advanced_event_selectors)) AS aes + where exists(select * + from UNNEST(JSON_QUERY_ARRAY(aes.FieldSelectors)) as aes_fs + where JSON_VALUE(aes_fs.Field) = 'readOnly')) + then 'fail' else 'pass' end as status from {{ full_table_name("aws_cloudtrail_trails") }} @@ -47,6 +62,12 @@ inner join {% endmacro %} {% macro snowflake__cloudtrail_enabled_all_regions(framework, check_id) %} +with aes as +( + select * + from aws_cloudtrail_trail_event_selectors, + LATERAL FLATTEN (advanced_event_selectors) as aes +) select '{{framework}}' as framework, '{{check_id}}' as check_id, @@ -54,10 +75,20 @@ select 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' + when aws_cloudtrail_trails.is_multi_region_trail = FALSE then 'fail' + when exists(select * + from aws_cloudtrail_trail_event_selectors, + LATERAL FLATTEN(event_selectors) as es + where es.value:ReadWriteType != 'All' or (es.value:IncludeManagementEvents)::boolean = FALSE + ) + then 'fail' + when exists( + select * + from aes, + LATERAL FLATTEN (value:FieldSelectors) as aes_fs + where aes_fs.value:Field = 'readOnly' + ) + then 'fail' else 'pass' end as status from aws_cloudtrail_trails diff --git a/transformations/aws/macros/elasticbeanstalk/elastic_beanstalk_stream_logs_to_cloudwatch.sql b/transformations/aws/macros/elasticbeanstalk/elastic_beanstalk_stream_logs_to_cloudwatch.sql index 2242d659c..1ab8c8e40 100644 --- a/transformations/aws/macros/elasticbeanstalk/elastic_beanstalk_stream_logs_to_cloudwatch.sql +++ b/transformations/aws/macros/elasticbeanstalk/elastic_beanstalk_stream_logs_to_cloudwatch.sql @@ -1,7 +1,7 @@ {% macro elastic_beanstalk_stream_logs_to_cloudwatch(framework, check_id) %} with flat_configs as ( select - c.environment_id, + c.environment_arn, f.value:Namespace:Value::string as is_log_streaming from @@ -26,5 +26,5 @@ SELECT END as status FROM aws_elasticbeanstalk_environments e JOIN flat_configs as fc - ON e.environment_id = fc.environment_id + ON e.arn = fc.environment_arn {% endmacro %} \ No newline at end of file diff --git a/transformations/aws/macros/guardduty/detector_enabled.sql b/transformations/aws/macros/guardduty/detector_enabled.sql index 2e0f0d121..c528dbb7a 100644 --- a/transformations/aws/macros/guardduty/detector_enabled.sql +++ b/transformations/aws/macros/guardduty/detector_enabled.sql @@ -4,7 +4,7 @@ {% macro snowflake__detector_enabled(framework, check_id) %} with enabled_detector_regions as ( - select account_id, region + select request_account_id as account_id, request_region as region from aws_guardduty_detectors where status = 'ENABLED' ) @@ -26,8 +26,8 @@ select '{{framework}}' As framework, '{{check_id}}' As check_id, 'GuardDuty should be enabled (detectors)' AS title, - account_id, - region AS resource_id, + request_account_id as account_id, + request_region AS resource_id, case when data_sources:S3Logs:Status != 'ENABLED' AND data_sources:DNSLogs:Status != 'ENABLED' AND @@ -41,7 +41,7 @@ where {% macro postgres__detector_enabled(framework, check_id) %} with enabled_detector_regions as ( - select account_id, region + select request_account_id as account_id, request_region as region from aws_guardduty_detectors where status = 'ENABLED' ) @@ -63,8 +63,8 @@ select '{{framework}}' as framework, '{{check_id}}' as check_id, 'GuardDuty should be enabled (detectors)' AS title, - account_id, - region AS resource_id, + request_account_id as account_id, + request_region AS resource_id, case when data_sources->'S3Logs'->>'Status' != 'ENABLED' AND data_sources->'DNSLogs'->>'Status' != 'ENABLED' AND @@ -77,4 +77,4 @@ where {% endmacro %} {% macro default__detector_enabled(framework, check_id) %}{% endmacro %} - \ No newline at end of file + diff --git a/transformations/aws/macros/iam/no_star.sql b/transformations/aws/macros/iam/no_star.sql index 246dac2fd..72a892cdc 100644 --- a/transformations/aws/macros/iam/no_star.sql +++ b/transformations/aws/macros/iam/no_star.sql @@ -7,7 +7,11 @@ {% macro postgres__no_star(framework, check_id) %} with pvs as ( - select id, (v->>'Document')::jsonb as document from aws_iam_policies, jsonb_array_elements(aws_iam_policies.policy_version_list) AS v + select + p.id, + pv.document_json as document + from aws_iam_policies p + inner join aws_iam_policy_versions pv on p.account_id = pv.account_id AND p.arn = pv.policy_arn ), violations as ( select id, @@ -46,3 +50,37 @@ select distinct from aws_iam_policies left join violations on violations.id = aws_iam_policies.id {% endmacro %} + +{% macro snowflake__no_star(framework, check_id) %} +with pvs as ( + select + p.id, + pv.document_json as document + from aws_iam_policies p + inner join aws_iam_policy_versions pv on p.account_id = pv.account_id AND p.arn = pv.policy_arn +), violations as ( + select + id, + COUNT(*) as violations + from pvs, + LATERAL FLATTEN(document:Statement) as statement, + LATERAL FLATTEN(statement.value:Resource) as resource, + LATERAL FLATTEN(statement.value:Action) as action + where statement.value:Effect = 'Allow' + and resource.value = '*' + and ( action.value = '*' or action.value = '*:*' ) + group by id +) + +select distinct + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'IAM policies should not allow full ''*'' administrative privileges' as title, + account_id, + arn AS resource_id, + case when + violations.id is not null AND violations.violations > 0 + then 'fail' else 'pass' end as status +from aws_iam_policies +left join violations on violations.id = aws_iam_policies.id +{% endmacro %} \ No newline at end of file diff --git a/transformations/aws/macros/iam/policies_have_wildcard_actions.sql b/transformations/aws/macros/iam/policies_have_wildcard_actions.sql index 3d86c1668..d488ea7b4 100644 --- a/transformations/aws/macros/iam/policies_have_wildcard_actions.sql +++ b/transformations/aws/macros/iam/policies_have_wildcard_actions.sql @@ -1,4 +1,42 @@ {% macro policies_have_wildcard_actions(framework, check_id) %} + {{ return(adapter.dispatch('policies_have_wildcard_actions')(framework, check_id)) }} +{% endmacro %} + +{% macro default__policies_have_wildcard_actions(framework, check_id) %}{% endmacro %} + +{% macro postgres__policies_have_wildcard_actions(framework, check_id) %} +with bad_statements as ( +SELECT + p.account_id, + p.arn as resource_id, + CASE + WHEN s ->> 'Action' ~ '^[a-zA-Z0-9]+:\*$' + OR s ->> 'Action' = '*:*' THEN 1 + ELSE 0 + END as status + +FROM + aws_iam_policies p +INNER JOIN aws_iam_policy_versions pv ON p.account_id = pv.account_id AND p.arn = pv.policy_arn + , JSONB_ARRAY_ELEMENTS(pv.document_json -> 'Statement') as s +where pv.is_default_version = true AND s ->> 'Effect' = 'Allow' + + ) +select DISTINCT + '{{framework}}' As framework, + '{{check_id}}' As check_id, + 'IAM customer managed policies that you create should not allow wildcard actions for services' AS title, + account_id, + resource_id, + CASE + WHEN max(status) over(partition by resource_id) = 1 THEN 'fail' + ELSE 'pass' + END as status +FROM + bad_statements +{% endmacro %} + +{% macro snowflake__policies_have_wildcard_actions(framework, check_id) %} with bad_statements as ( SELECT p.account_id, @@ -11,11 +49,10 @@ SELECT FROM aws_iam_policies p - , lateral flatten(input => p.POLICY_VERSION_LIST) as f - , lateral flatten(input => parse_json(f.value:Document):Statement) as s -where f.value:IsDefaultVersion = 'true' AND s.value:Effect = 'Allow' - - ) + INNER JOIN aws_iam_policy_versions pv ON p.account_id = pv.account_id AND p.arn = pv.policy_arn + , lateral flatten(input => pv.document_json:Statement) as s +where pv.is_default_version = true AND s.value:Effect = 'Allow' +) select DISTINCT '{{framework}}' As framework, '{{check_id}}' As check_id, diff --git a/transformations/aws/macros/iam/policies_with_admin_rights.sql b/transformations/aws/macros/iam/policies_with_admin_rights.sql index 0a8d920b3..fad0ee0fb 100644 --- a/transformations/aws/macros/iam/policies_with_admin_rights.sql +++ b/transformations/aws/macros/iam/policies_with_admin_rights.sql @@ -8,12 +8,12 @@ SELECT p.id FROM aws_iam_policies p - , lateral flatten(input => p.POLICY_VERSION_LIST) as f - , lateral flatten(input => parse_json(f.value:Document):Statement) as s -where f.value:IsDefaultVersion = 'true' + INNER JOIN aws_iam_policy_versions pv ON p.account_id = pv.account_id AND p.arn = pv.policy_arn + , lateral flatten(input => pv.document_json:Statement) as s +where pv.is_default_version = 'true' AND s.value:Effect = 'Allow' and s.value:Effect = 'Allow' and (s.value:Action = '*' or s.value:Action = '*:*') - and s.value:Resource = '*' + and s.value:Resource = '*' ) select '{{framework}}' As framework, @@ -33,23 +33,20 @@ WHERE p.arn REGEXP '.*\d{12}.*' {% endmacro %} {% macro postgres__policies_with_admin_rights(framework, check_id) %} - with iam_policies as ( select - id, - (v->>'Document')::jsonb AS document - from aws_iam_policies, jsonb_array_elements(aws_iam_policies.policy_version_list) AS v - where aws_iam_policies.default_version_id = v->>'VersionId' and arn not like 'arn:aws:iam::aws:policy%' + p.id as id, + pv.document_json as document + from aws_iam_policies p + inner join aws_iam_policy_versions pv on p.account_id = pv.account_id AND p.arn = pv.policy_arn + where pv.is_default_version = true and p.arn not like 'arn:aws:iam::aws:policy%' ), policy_statements as ( select id, JSONB_ARRAY_ELEMENTS( case JSONB_TYPEOF(document -> 'Statement') - when - 'string' then JSONB_BUILD_ARRAY( - document ->> 'Statement' - ) + when 'string' then JSONB_BUILD_ARRAY(document ->> 'Statement') when 'array' then document -> 'Statement' end ) as statement from diff --git a/transformations/aws/macros/iam/wildcard_access_policies.sql b/transformations/aws/macros/iam/wildcard_access_policies.sql index bbf861a56..e1ac468f7 100644 --- a/transformations/aws/macros/iam/wildcard_access_policies.sql +++ b/transformations/aws/macros/iam/wildcard_access_policies.sql @@ -8,20 +8,19 @@ with policy_statements as ( select - aws_iam_policies.id, + p.id, JSONB_ARRAY_ELEMENTS( - case JSONB_TYPEOF(((v->>'Document')::jsonb) -> 'Statement') + case JSONB_TYPEOF(v.document_json -> 'Statement') when - 'string' then JSONB_BUILD_ARRAY( - ((v->>'Document')::jsonb) ->> 'Statement' - ) + 'string' then JSONB_BUILD_ARRAY(v.document_json ->> 'Statement') when - 'array' then ((v->>'Document')::jsonb) -> 'Statement' + 'array' then v.document_json -> 'Statement' end ) as statement from - aws_iam_policies, jsonb_array_elements(aws_iam_policies.policy_version_list) AS v - where aws_iam_policies.arn not like 'arn:aws:iam::aws:policy%' + aws_iam_policies p + inner join aws_iam_policy_versions pv on p.account_id = pv.account_id AND p.arn = pv.policy_arn + where p.arn not like 'arn:aws:iam::aws:policy%' ), allow_all_statements as ( diff --git a/transformations/aws/macros/kms/customer_policy_blocked_kms_actions.sql b/transformations/aws/macros/kms/customer_policy_blocked_kms_actions.sql index c5ec5520f..10f5c778b 100644 --- a/transformations/aws/macros/kms/customer_policy_blocked_kms_actions.sql +++ b/transformations/aws/macros/kms/customer_policy_blocked_kms_actions.sql @@ -8,11 +8,12 @@ with iam_policies as ( select - (v->>'Document')::jsonb AS document, - account_id, - arn, - id - from aws_iam_policies, jsonb_array_elements(aws_iam_policies.policy_version_list) AS v + pv.document_json as document, + p.account_id, + p.arn, + p.id + from aws_iam_policies p + inner join aws_iam_policy_versions pv on p.account_id = pv.account_id AND p.arn = pv.policy_arn ), violations as ( diff --git a/transformations/aws/macros/kms/iam_customer_policy_no_kms_decrypt.sql b/transformations/aws/macros/kms/iam_customer_policy_no_kms_decrypt.sql index 4b0018e01..f4ec0c67a 100644 --- a/transformations/aws/macros/kms/iam_customer_policy_no_kms_decrypt.sql +++ b/transformations/aws/macros/kms/iam_customer_policy_no_kms_decrypt.sql @@ -1,18 +1,58 @@ {% macro iam_customer_policy_no_kms_decrypt(framework, check_id) %} wITH policy_with_decrypt AS ( + {{ return(adapter.dispatch('iam_customer_policy_no_kms_decrypt')(framework, check_id)) }} +{% endmacro %} + +{% macro default__iam_customer_policy_no_kms_decrypt(framework, check_id) %}{% endmacro %} + +{% macro postgres__iam_customer_policy_no_kms_decrypt(framework, check_id) %} +WITH policy_with_decrypt AS ( SELECT DISTINCT arn FROM aws_iam_policies p - ,lateral flatten(input => p.POLICY_VERSION_LIST) as f - ,lateral flatten(input => parse_json(f.value:Document):Statement) as s - WHERE + INNER JOIN aws_iam_policy_versions pv ON p.account_id = pv.account_id AND p.arn = pv.policy_arn + , JSONB_ARRAY_ELEMENTS(pv.document_json -> 'Statement') as s + WHERE + s ->> 'Effect' = 'Allow' + AND + (s ->> 'Resource' = '*' OR + s ->> 'Resource' LIKE '%kms%') + AND + (s ->> 'Action' = '*' + OR s ->> 'Action' LIKE '%kms:*%' + OR s ->> 'Action' LIKE '%kms:decrypt%' + OR s ->> 'Action' LIKE '%kms:reencryptfrom%' + OR s ->> 'Action' LIKE '%kms:reencrypt*%') +) +SELECT + '{{framework}}' As framework, + '{{check_id}}' As check_id, + 'IAM customer managed policies should not allow decryption actions on all KMS keys' AS title, + i.account_id, + i.arn AS resource_id, + CASE + WHEN d.arn IS NULL THEN 'pass' + ELSE 'fail' + END AS status +FROM + aws_iam_policies i +LEFT JOIN policy_with_decrypt d ON i.arn = d.arn +{% endmacro %} + +{% macro snowflake__iam_customer_policy_no_kms_decrypt(framework, check_id) %} +WITH policy_with_decrypt AS ( + SELECT DISTINCT arn + FROM aws_iam_policies p + INNER JOIN aws_iam_policy_versions pv ON p.account_id = pv.account_id AND p.arn = pv.policy_arn + , lateral flatten(input => pv.document_json:Statement) as s + WHERE s.value:Effect = 'Allow' AND (s.value:Resource = '*' OR - s.value:Resource LIKE '%kms%') + s.value:Resource LIKE '%kms%') AND - (s.value:Action = '*' - OR s.value:Action ILIKE '%kms:*%' - OR s.value:Action ILIKE '%kms:decrypt%' + (s.value:Action = '*' + OR s.value:Action ILIKE '%kms:*%' + OR s.value:Action ILIKE '%kms:decrypt%' OR s.value:Action ILIKE '%kms:reencryptfrom%' OR s.value:Action ILIKE '%kms:reencrypt*%') ) diff --git a/transformations/aws/macros/log_metric_filter_and_alarm.sql b/transformations/aws/macros/log_metric_filter_and_alarm.sql index 93574864f..6e5ddac75 100644 --- a/transformations/aws/macros/log_metric_filter_and_alarm.sql +++ b/transformations/aws/macros/log_metric_filter_and_alarm.sql @@ -8,6 +8,16 @@ 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 +), +tes as ( + select trail_arn from aws_cloudtrail_trail_event_selectors + where exists( + select * from jsonb_array_elements(event_selectors) as es + where es ->>'ReadWriteType' = 'All' and (es->>'IncludeManagementEvents')::boolean = TRUE + ) or exists( + select * from jsonb_array_elements(advanced_event_selectors) as aes + where not exists(select * from jsonb_array_elements(aes ->'FieldSelectors') as aes_fs where aes_fs ->>'Field' = 'readOnly') + ) ) select t.account_id, @@ -15,14 +25,12 @@ select 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 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 %} @@ -49,39 +57,42 @@ where t.is_multi_region_trail = TRUE {% endmacro %} {% macro snowflake__log_metric_filter_and_alarm() %} -WITH af AS ( - SELECT DISTINCT - a.arn, - a.actions_enabled, - a.alarm_actions, - m.value:MetricStat:Metric:MetricName AS metric_name - FROM aws_cloudwatch_alarms a, - LATERAL FLATTEN(input => a.metrics) AS m +with af as ( + select distinct a.arn, a.actions_enabled, a.alarm_actions, m.value:MetricStat:Metric:MetricName as metric_name -- TODO check + from aws_cloudwatch_alarms a, + LATERAL FLATTEN (metrics) as m +), +aes as ( +select * from aws_cloudtrail_trail_event_selectors, + LATERAL FLATTEN (advanced_event_selectors) as aes +), +tes as ( + select trail_arn from aws_cloudtrail_trail_event_selectors + where exists( + select * from + aws_cloudtrail_trail_event_selectors, + LATERAL FLATTEN(event_selectors) as es + where es.value:ReadWriteType = 'All' and (es.value:IncludeManagementEvents)::boolean = TRUE + ) + or exists( + select * from aes + where not exists ( + select * from aes, LATERAL FLATTEN(value:FieldSelectors) as aes_fs + where aes_fs.value:Field = 'readOnly' + ) + ) ) - -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 LATERAL ( - SELECT arn, topic_arn - FROM aws_sns_subscriptions ss - WHERE ARRAY_CONTAINS(ss.topic_arn::variant, af.alarm_actions) - LIMIT 1 -) ss ON TRUE -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:%' +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 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 ARRAY_CONTAINS((ss.topic_arn)::variant, af.alarm_actions) +where t.is_multi_region_trail = TRUE + and (t.status:IsLogging)::boolean = TRUE + and ss.arn like 'aws:arn:%' {% endmacro %} \ No newline at end of file diff --git a/transformations/aws/macros/s3/deny_http_requests.sql b/transformations/aws/macros/s3/deny_http_requests.sql index 171010fa0..be83867eb 100644 --- a/transformations/aws/macros/s3/deny_http_requests.sql +++ b/transformations/aws/macros/s3/deny_http_requests.sql @@ -20,8 +20,9 @@ WHERE b.arn, statements.value AS statement FROM - aws_s3_buckets AS b, - LATERAL FLATTEN(INPUT => IFF(TYPEOF(b.policy:Statement) = 'STRING', TO_ARRAY(b.policy:Statement), b.policy:Statement)) AS statements + aws_s3_buckets AS b + inner join aws_s3_bucket_policies on b.arn = aws_s3_bucket_policies.bucket_arn, + LATERAL FLATTEN(INPUT => IFF(TYPEOF(aws_s3_bucket_policies.policy_json:Statement) = 'STRING', TO_ARRAY(aws_s3_bucket_policies.policy_json:Statement), aws_s3_bucket_policies.policy_json:Statement)) AS statements WHERE GET_PATH(statement, 'Effect')::STRING = 'Deny' AND GET_PATH(statement, 'Condition.Bool.aws:SecureTransport')::STRING = 'false' @@ -49,14 +50,15 @@ where from (select aws_s3_buckets.arn, statements, statements -> 'Principal' as principals - from aws_s3_buckets, + from aws_s3_buckets + inner join aws_s3_bucket_policies on aws_s3_buckets.arn = aws_s3_bucket_policies.bucket_arn, jsonb_array_elements( - case jsonb_typeof(policy -> 'Statement') + case jsonb_typeof(aws_s3_bucket_policies.policy_json -> 'Statement') when 'string' then jsonb_build_array( - policy ->> 'Statement' + aws_s3_bucket_policies.policy_json ->> 'Statement' ) - when 'array' then policy -> 'Statement' + when 'array' then aws_s3_bucket_policies.policy_json -> 'Statement' end ) as statements where statements -> 'Effect' = '"Deny"') as foo, diff --git a/transformations/aws/macros/s3/publicly_readable_buckets.sql b/transformations/aws/macros/s3/publicly_readable_buckets.sql index d8b591b2e..a43754d1e 100644 --- a/transformations/aws/macros/s3/publicly_readable_buckets.sql +++ b/transformations/aws/macros/s3/publicly_readable_buckets.sql @@ -13,10 +13,11 @@ WITH policy_allow_public AS ( aws_s3_buckets.arn, statements.value:Principal AS principals FROM - aws_s3_buckets, - LATERAL FLATTEN(INPUT => IFF(TYPEOF(policy:Statement) = 'STRING', - TO_ARRAY(policy:Statement), - policy:Statement)) AS statements + aws_s3_buckets + inner join aws_s3_bucket_policies bp on aws_s3_buckets.arn = bp.bucket_arn, + LATERAL FLATTEN(INPUT => IFF(TYPEOF(bp.policy_json:Statement) = 'STRING', + TO_ARRAY(bp.policy_json:Statement), + bp.policy_json:Statement)) AS statements WHERE statements.value:Effect::STRING = 'Allow' ) AS foo @@ -47,16 +48,18 @@ LEFT JOIN aws_s3_buckets.arn = aws_s3_bucket_grants.bucket_arn LEFT JOIN policy_allow_public ON aws_s3_buckets.arn = policy_allow_public.arn +LEFT JOIN aws_s3_bucket_public_access_blocks ON + aws_s3_buckets.arn = aws_s3_bucket_public_access_blocks.bucket_arn WHERE ( - aws_s3_buckets.block_public_acls != TRUE + (aws_s3_bucket_public_access_blocks.public_access_block_configuration:BlockPublicAcls)::boolean != TRUE AND ( aws_s3_bucket_grants.grantee:URI::STRING = 'http://acs.amazonaws.com/groups/global/AllUsers' AND aws_s3_bucket_grants.permission IN ('READ_ACP', 'FULL_CONTROL') ) ) OR ( - aws_s3_buckets.block_public_policy != TRUE + (aws_s3_bucket_public_access_blocks.public_access_block_configuration:BlockPublicPolicy)::boolean != TRUE AND policy_allow_public.statement_count > 0 ) {% endmacro %} @@ -69,21 +72,13 @@ with policy_allow_public as ( from ( select - aws_s3_buckets.arn, - statements -> 'Principal' as principals + b.arn, + bp.policy_json -> 'Statement' -> 'Principal' as principals from - aws_s3_buckets, - jsonb_array_elements( - case jsonb_typeof(policy::jsonb -> 'Statement') - when - 'string' then jsonb_build_array( - policy::jsonb ->> 'Statement' - ) - when 'array' then policy::jsonb -> 'Statement' - end - ) as statements + aws_s3_buckets b + inner join aws_s3_bucket_policies bp on b.arn = bp.bucket_arn where - statements -> 'Effect' = '"Allow"' + bp.policy_json -> 'Statement' -> 'Effect' = '"Allow"' ) as foo where principals = '"*"' @@ -118,16 +113,18 @@ left join -- Principal = "*" left join policy_allow_public on aws_s3_buckets.arn = policy_allow_public.arn +left join aws_s3_bucket_public_access_blocks on + aws_s3_buckets.arn = aws_s3_bucket_public_access_blocks.bucket_arn where ( - aws_s3_buckets.block_public_acls != TRUE + (aws_s3_bucket_public_access_blocks.public_access_block_configuration -> 'BlockPublicAcls')::boolean != TRUE and ( grantee->>'URI' = 'http://acs.amazonaws.com/groups/global/AllUsers' and permission in ('READ_ACP', 'FULL_CONTROL') ) ) or ( - aws_s3_buckets.block_public_policy != TRUE + (aws_s3_bucket_public_access_blocks.public_access_block_configuration -> 'BlockPublicPolicy')::boolean != TRUE and policy_allow_public.statement_count > 0 ) {% endmacro %} diff --git a/transformations/aws/macros/s3/publicly_writable_buckets.sql b/transformations/aws/macros/s3/publicly_writable_buckets.sql index ebc525cd0..71d79b152 100644 --- a/transformations/aws/macros/s3/publicly_writable_buckets.sql +++ b/transformations/aws/macros/s3/publicly_writable_buckets.sql @@ -13,10 +13,11 @@ WITH policy_allow_public AS ( aws_s3_buckets.arn, statements.value:Principal AS principals FROM - aws_s3_buckets, - LATERAL FLATTEN(INPUT => IFF(TYPEOF(policy:Statement) = 'STRING', - TO_ARRAY(policy:Statement), - policy:Statement)) AS statements + aws_s3_buckets + inner join aws_s3_bucket_policies bp on aws_s3_buckets.arn = bp.bucket_arn, + LATERAL FLATTEN(INPUT => IFF(TYPEOF(bp.policy_json:Statement) = 'STRING', + TO_ARRAY(bp.policy_json:Statement), + bp.policy_json:Statement)) AS statements WHERE statements.value:Effect::STRING = 'Allow' ) AS foo @@ -47,16 +48,18 @@ LEFT JOIN aws_s3_buckets.arn = aws_s3_bucket_grants.bucket_arn LEFT JOIN policy_allow_public ON aws_s3_buckets.arn = policy_allow_public.arn +LEFT JOIN aws_s3_bucket_public_access_blocks ON + aws_s3_buckets.arn = aws_s3_bucket_public_access_blocks.bucket_arn WHERE ( - aws_s3_buckets.block_public_acls != TRUE + (aws_s3_bucket_public_access_blocks.public_access_block_configuration:BlockPublicAcls)::boolean != TRUE AND ( aws_s3_bucket_grants.grantee:URI::STRING = 'http://acs.amazonaws.com/groups/global/AllUsers' AND aws_s3_bucket_grants.permission IN ('WRITE_ACP', 'FULL_CONTROL') ) ) OR ( - aws_s3_buckets.block_public_policy != TRUE + (aws_s3_bucket_public_access_blocks.public_access_block_configuration:BlockPublicPolicy)::boolean != TRUE AND policy_allow_public.statement_count > 0 ) {% endmacro %} @@ -69,21 +72,13 @@ with policy_allow_public as ( from ( select - aws_s3_buckets.arn, - statements -> 'Principal' as principals + b.arn, + bp.policy_json -> 'Statement' -> 'Principal' as principals from - aws_s3_buckets, - jsonb_array_elements( - case jsonb_typeof(policy::jsonb -> 'Statement') - when - 'string' then jsonb_build_array( - policy::jsonb ->> 'Statement' - ) - when 'array' then policy::jsonb -> 'Statement' - end - ) as statements + aws_s3_buckets b + inner join aws_s3_bucket_policies bp on b.arn = bp.bucket_arn where - statements -> 'Effect' = '"Allow"' + bp.policy_json -> 'Statement' -> 'Effect' = '"Allow"' ) as foo where principals = '"*"' @@ -118,16 +113,18 @@ left join -- Principal = "*" left join policy_allow_public on aws_s3_buckets.arn = policy_allow_public.arn +left join aws_s3_bucket_public_access_blocks on + aws_s3_buckets.arn = aws_s3_bucket_public_access_blocks.bucket_arn where ( - aws_s3_buckets.block_public_acls != TRUE + (aws_s3_bucket_public_access_blocks.public_access_block_configuration -> 'BlockPublicAcls')::boolean != TRUE and ( grantee->>'URI' = 'http://acs.amazonaws.com/groups/global/AllUsers' and permission in ('WRITE_ACP', 'FULL_CONTROL') ) ) or ( - aws_s3_buckets.block_public_policy != TRUE + (aws_s3_bucket_public_access_blocks.public_access_block_configuration -> 'BlockPublicPolicy')::boolean != TRUE and policy_allow_public.statement_count > 0 ) {% endmacro %} diff --git a/transformations/aws/macros/s3/restrict_cross_account_actions.sql b/transformations/aws/macros/s3/restrict_cross_account_actions.sql index f9db971a1..c942baaff 100644 --- a/transformations/aws/macros/s3/restrict_cross_account_actions.sql +++ b/transformations/aws/macros/s3/restrict_cross_account_actions.sql @@ -13,9 +13,9 @@ select FROM ( SELECT aws_s3_buckets.arn, - account_id, - name, - region, + aws_s3_buckets.account_id, + aws_s3_buckets.name, + aws_s3_buckets.region, -- For each Statement return an array containing the principals CASE WHEN @@ -38,11 +38,12 @@ FROM ( statements.VALUE:Action END AS actions FROM - aws_s3_buckets, + aws_s3_buckets + inner join aws_s3_bucket_policies bp on aws_s3_buckets.arn = bp.bucket_arn, LATERAL FLATTEN( INPUT => CASE - WHEN TYPEOF(policy:Statement) = 'STRING' THEN TO_ARRAY(policy:Statement) - WHEN TYPEOF(policy:Statement) = 'ARRAY' THEN policy:Statement + WHEN TYPEOF(bp.policy_json:Statement) = 'STRING' THEN TO_ARRAY(bp.policy_json:Statement) + WHEN TYPEOF(bp.policy_json:Statement) = 'ARRAY' THEN bp.policy_json:Statement END ) statements WHERE @@ -74,10 +75,10 @@ select arn as resource_id, 'fail' as status -- TODO FIXME FROM ( - SELECT aws_s3_buckets.arn, - account_id, - name, - region, + SELECT b.arn, + b.account_id, + b.name, + b.region, -- For each Statement return an array containing the principals CASE WHEN @@ -97,11 +98,12 @@ FROM ( WHEN JSONB_TYPEOF(statements -> 'Action') = 'array' THEN statements -> 'Action' END AS actions - FROM aws_s3_buckets, + FROM aws_s3_buckets b + INNER JOIN aws_s3_bucket_policies ON b.arn = aws_s3_bucket_policies.bucket_arn, jsonb_array_elements( - CASE JSONB_TYPEOF(policy -> 'Statement') - WHEN 'string' THEN JSONB_BUILD_ARRAY(policy ->> 'Statement') - WHEN 'array' THEN policy -> 'Statement' + CASE JSONB_TYPEOF(aws_s3_bucket_policies.policy_json -> 'Statement') + WHEN 'string' THEN JSONB_BUILD_ARRAY(aws_s3_bucket_policies.policy_json ->> 'Statement') + WHEN 'array' THEN aws_s3_bucket_policies.policy_json -> 'Statement' END ) AS statements WHERE statements -> 'Effect' = '"Allow"') AS flatten_statements, diff --git a/transformations/aws/macros/s3/s3_bucket_level_public_access_prohibited.sql b/transformations/aws/macros/s3/s3_bucket_level_public_access_prohibited.sql index c80e33e45..bf8380127 100644 --- a/transformations/aws/macros/s3/s3_bucket_level_public_access_prohibited.sql +++ b/transformations/aws/macros/s3/s3_bucket_level_public_access_prohibited.sql @@ -3,15 +3,17 @@ select '{{framework}}' As framework, '{{check_id}}' As check_id, 'S3 Block Public Access setting should be enabled at the bucket-level' AS title, - account_id, - arn AS resource_id, + b.account_id, + b.arn AS resource_id, CASE - when block_public_acls - and block_public_policy - and ignore_public_acls - and restrict_public_buckets THEN 'pass' + when pab.public_access_block_configuration:block_public_acls + and pab.public_access_block_configuration:block_public_policy + and pab.public_access_block_configuration:ignore_public_acls + and pab.public_access_block_configuration:restrict_public_buckets THEN 'pass' ELSE 'fail' END AS status FROM - aws_s3_buckets + aws_s3_buckets as b +LEFT JOIN + aws_s3_bucket_public_access_blocks as pab on pab.bucket_arn = b.arn {% endmacro %} \ No newline at end of file diff --git a/transformations/aws/macros/s3/s3_bucket_logging_enabled.sql b/transformations/aws/macros/s3/s3_bucket_logging_enabled.sql index 836058828..d570b839b 100644 --- a/transformations/aws/macros/s3/s3_bucket_logging_enabled.sql +++ b/transformations/aws/macros/s3/s3_bucket_logging_enabled.sql @@ -3,12 +3,14 @@ select '{{framework}}' As framework, '{{check_id}}' As check_id, 'S3 bucket server access logging should be enabled' AS title, - account_id, - arn AS resource_id, + b.account_id, + b.arn AS resource_id, CASE - when logging_target_bucket IS NOT NULL + when bl.logging_enabled:TargetBucket IS NOT NULL THEN 'pass' ELSE 'fail' END AS status FROM - aws_s3_buckets + aws_s3_buckets as b +LEFT JOIN + aws_s3_bucket_loggings as bl on bl.bucket_arn = b.arn {% endmacro %} \ No newline at end of file diff --git a/transformations/aws/macros/s3/s3_cross_region_replication.sql b/transformations/aws/macros/s3/s3_cross_region_replication.sql index 9759a784a..4eafd8eb1 100644 --- a/transformations/aws/macros/s3/s3_cross_region_replication.sql +++ b/transformations/aws/macros/s3/s3_cross_region_replication.sql @@ -12,13 +12,26 @@ select aws_s3_buckets.account_id, aws_s3_buckets.arn as resource_id, case when - r->>'Status' is distinct from 'Enabled' + aws_s3_bucket_replications.replication_configuration -> 'Rule' ->>'Status' is distinct from 'Enabled' then 'fail' else 'pass' end as status from - aws_s3_buckets, JSONB_ARRAY_ELEMENTS( - case jsonb_typeof(replication_rules) - when 'array' then replication_rules - else '[]' end - ) as r + aws_s3_buckets + inner join aws_s3_bucket_replications on aws_s3_buckets.arn = aws_s3_bucket_replications.bucket_arn -- Note: This query doesn't validate that the destination bucket is actually in a different region {% endmacro %} + +{% macro snowflake__s3_cross_region_replication(framework, check_id) %} +select + '{{framework}}' as framework, + '{{check_id}}' as check_id, + 'S3 buckets with replication rules should be enabled' as title, + aws_s3_buckets.account_id, + aws_s3_buckets.arn as resource_id, + case when + aws_s3_bucket_replications.replication_configuration:Rule:Status is distinct from 'Enabled' + then 'fail' else 'pass' end as status +from + aws_s3_buckets + inner join aws_s3_bucket_replications on aws_s3_buckets.arn = aws_s3_bucket_replications.bucket_arn +-- Note: This query doesn't validate that the destination bucket is actually in a different region +{% endmacro %} \ No newline at end of file diff --git a/transformations/aws/macros/s3/s3_version_lifecycle_policy_check.sql b/transformations/aws/macros/s3/s3_version_lifecycle_policy_check.sql index 230deb88a..f3aa24bb3 100644 --- a/transformations/aws/macros/s3/s3_version_lifecycle_policy_check.sql +++ b/transformations/aws/macros/s3/s3_version_lifecycle_policy_check.sql @@ -11,9 +11,13 @@ select END AS status FROM aws_s3_buckets AS b +LEFT JOIN + aws_s3_bucket_versionings AS bv + ON + b.arn = bv.bucket_arn LEFT JOIN aws_s3_bucket_lifecycles AS l -ON + ON b.arn = l.bucket_arn -where b.versioning_status = 'Enabled' +where bv.status = 'Enabled' {% endmacro %} \ No newline at end of file diff --git a/transformations/aws/macros/unused/unused_directconntect_connections.sql b/transformations/aws/macros/unused/unused_directconntect_connections.sql index 110c1b65a..8397f12a4 100644 --- a/transformations/aws/macros/unused/unused_directconntect_connections.sql +++ b/transformations/aws/macros/unused/unused_directconntect_connections.sql @@ -6,8 +6,8 @@ {% macro postgres__unused_directconntect_connections(framework, check_id) %} select - dc.account_id, - dc.arn as resource_id, + dc.request_account_id as account_id, + dc.arn as resource_id, rbc.cost from aws_directconnect_connections dc JOIN {{ ref('aws_cost__by_resources') }} rbc ON dc.arn = rbc.line_item_resource_id @@ -16,4 +16,4 @@ where dc.connection_state = 'down' {% macro snowflake__unused_directconntect_connections(framework, check_id) %} -{% endmacro %} \ No newline at end of file +{% endmacro %} diff --git a/visualizations/aws/asset_inventory/manifest.json b/visualizations/aws/asset_inventory/manifest.json index ce723b967..90ed0971c 100644 --- a/visualizations/aws/asset_inventory/manifest.json +++ b/visualizations/aws/asset_inventory/manifest.json @@ -8,6 +8,6 @@ "message": "@./changelog.md", "doc": "./README.md", "path": "./build/aws_asset_inventory.zip", - "plugin_deps": ["cloudquery/source/aws@v22.19.0"], + "plugin_deps": ["cloudquery/source/aws@v23.3.1"], "addon_deps": ["cloudquery/transformation/aws-asset-inventory@v1.0.0"] } \ No newline at end of file diff --git a/visualizations/aws/compliance/manifest.json b/visualizations/aws/compliance/manifest.json index 7d3b1e604..79b4907f3 100644 --- a/visualizations/aws/compliance/manifest.json +++ b/visualizations/aws/compliance/manifest.json @@ -8,6 +8,6 @@ "message": "@./changelog.md", "doc": "./README.md", "path": "./build/aws_compliance.zip", - "plugin_deps": ["cloudquery/source/aws@v22.19.0"], + "plugin_deps": ["cloudquery/source/aws@v23.3.1"], "addon_deps": ["cloudquery/transformation/aws-compliance-free@v0.0.1"] } diff --git a/visualizations/aws/data_resilience/manifest.json b/visualizations/aws/data_resilience/manifest.json index a4359c897..1123d19c0 100644 --- a/visualizations/aws/data_resilience/manifest.json +++ b/visualizations/aws/data_resilience/manifest.json @@ -8,6 +8,6 @@ "message": "@./changelog.md", "doc": "./README.md", "path": "./build/aws_data_resilience.zip", - "plugin_deps": ["cloudquery/source/aws@v22.19.0"], + "plugin_deps": ["cloudquery/source/aws@v23.3.1"], "addon_deps": ["cloudquery/transformation/aws-data-resilience@v1.0.0"] }