Skip to content

Commit

Permalink
feat: Added queries for Foundational Security compliance for bigquery (
Browse files Browse the repository at this point in the history
…#515)

* feat: Added queries for Foundational Security compliance for bigquery

* chore: Fix DBT BigQuery auth in CI

* Revert "chore: Fix DBT BigQuery auth in CI"

This reverts commit a174a37.

* chore: Add location to bigquery profile

* Change restrict_cross_account_actions query

---------

Co-authored-by: erezrokah <[email protected]>
  • Loading branch information
ronsh12 and erezrokah authored Jan 24, 2024
1 parent 6e90d16 commit 5209331
Show file tree
Hide file tree
Showing 193 changed files with 3,928 additions and 513 deletions.
3 changes: 2 additions & 1 deletion transformations/aws/compliance-free/tests/profiles.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ aws_compliance: # This should match the name in your dbt_project.yml
method: oauth
project: cq-integration-tests
dataset: policies_premium_ci_test # You can also use "schema" here
threads: 4 # Must be a value of 1 or greater
threads: 4 # Must be a value of 1 or greater
location: us-west1

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion transformations/aws/compliance-premium/tests/profiles.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ aws_compliance: # This should match the name in your dbt_project.yml
method: oauth
project: cq-integration-tests
dataset: policies_premium_ci_test # You can also use "schema" here
threads: 4 # Must be a value of 1 or greater
threads: 4 # Must be a value of 1 or greater
location: us-west1
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,25 @@ WHERE alternate_contact_type = 'SECURITY'
ON aws_iam_accounts.account_id = account_security_contacts.account_id{% endmacro %}

{% macro default__security_account_information_provided(framework, check_id) %}{% endmacro %}


{% macro bigquery__security_account_information_provided(framework, check_id) %}
SELECT
'{{framework}}' As framework,
'{{check_id}}' As check_id,
'Security contact information should be provided for an AWS account' AS title,
aws_iam_accounts.account_id as account_id,
aws_iam_accounts.account_id as resource_id,
CASE WHEN
'alternate_contact_type' IS NULL
THEN 'fail'
ELSE 'pass'
END AS status
FROM {{ full_table_name("aws_iam_accounts") }}

LEFT JOIN(
SELECT * FROM {{ full_table_name("aws_account_alternate_contacts") }}

WHERE alternate_contact_type='SECURITY'
) AS account_security_contacts
ON aws_iam_accounts.account_id = account_security_contacts.account_id
{% endmacro %}
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,18 @@ FROM aws_acm_certificates
{% endmacro %}

{% macro default__certificates_should_be_renewed(framework, check_id) %}{% endmacro %}


{% macro bigquery__certificates_should_be_renewed(framework, check_id) %}
select
'{{framework}}' As framework,
'{{check_id}}' As check_id,
'certificate has less than 30 days to be renewed' as title,
account_id,
arn AS resource_id,
case when
not_after < CAST( {{ dbt.dateadd('day', 30, 'current_date') }} AS TIMESTAMP )
then 'fail'
else 'pass'
end as status
FROM {{ full_table_name("aws_acm_certificates") }}
{% endmacro %}
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,20 @@ select
END AS status
FROM aws_acm_certificates
WHERE left(key_algorithm, 3) = 'RSA'
{% endmacro %}

{% macro bigquery__rsa_certificate_key_length_should_be_more_than_2048_bits(framework, check_id) %}
select
'{{framework}}' As framework,
'{{check_id}}' As check_id,
'rsa certificate key length is less than 2048 bits' as title,
account_id,
arn AS resource_id,
CASE
WHEN key_algorithm IN ('RSA-1024', 'RSA 1024', 'RSA_1024')
THEN 'fail'
ELSE 'pass'
END AS status
FROM {{ full_table_name("aws_acm_certificates") }}
WHERE left(key_algorithm, 3) = 'RSA'
{% endmacro %}
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,23 @@ JOIN aws_apigateway_rest_apis r ON s.rest_api_arn=r.arn,
LATERAL FLATTEN(input=>PARSE_JSON(s.method_settings))

{% endmacro %}

{% macro bigquery__api_gateway_method_settings() %}
SELECT
s.arn,
s.rest_api_arn,
s.stage_name,
s.tracing_enabled AS stage_data_trace_enabled,
s.cache_cluster_enabled AS stage_caching_enabled,
s.web_acl_arn AS waf,
s.client_certificate_id AS cert,
ms.key AS method,
CASE WHEN CAST(JSON_VALUE(ms.DataTraceEnabled) AS STRING) = 'true' THEN 1 ELSE 0 END AS data_trace_enabled,
CASE WHEN CAST(JSON_VALUE(ms.CachingEnabled) AS STRING) = 'true' THEN 1 ELSE 0 END AS caching_enabled,
CASE WHEN CAST(JSON_VALUE(ms.CacheDataEncrypted) AS STRING) = 'true' THEN 1 ELSE 0 END AS cache_data_encrypted,
CAST(JSON_VALUE(ms.LoggingLevel) AS STRING) AS logging_level,
r.account_id
FROM {{ full_table_name("aws_apigateway_rest_api_stages") }} s
JOIN {{ full_table_name("aws_apigateway_rest_apis") }} r ON s.rest_api_arn=r.arn,
UNNEST(JSON_QUERY_ARRAY(s.method_settings)) AS ms
{% endmacro %}
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,21 @@ FROM
aws_apigatewayv2_api_stages
{% endmacro %}

{% macro bigquery__api_gw_access_logging_should_be_configured(framework, check_id) %}
select
'{{framework}}' As framework,
'{{check_id}}' As check_id,
'Access logging should be configured for API Gateway V2 Stages' as title,
account_id,
arn AS resource_id,
CASE
WHEN coalesce( CAST(JSON_VALUE(access_log_settings) AS STRING) , '') = '' THEN 'fail'
ELSE 'pass'
END AS status
FROM
{{ full_table_name("aws_apigatewayv2_api_stages") }}
{% endmacro %}




Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,19 @@ SELECT
END as status
FROM
aws_apigateway_rest_api_stages
{% endmacro %}

{% macro bigquery__api_gw_associated_wth_waf(framework, check_id) %}
SELECT
'{{framework}}' As framework,
'{{check_id}}' As check_id,
'API Gateway should be associated with a WAF We0ACL' as title,
account_id,
arn as resource_id,
CASE
WHEN web_acl_arn is not null THEN 'pass'
ELSE 'fail'
END as status
FROM
{{ full_table_name("aws_apigateway_rest_api_stages") }}
{% endmacro %}
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,42 @@ LATERAL FLATTEN(input => COALESCE(s.method_settings, ARRAY_CONSTRUCT())) as ms
WHERE
ms.value:CachingEnabled = 'true'
)
SELECT
'{{framework}}' As framework,
'{{check_id}}' As check_id,
'API Gateway REST API cache data should be encrypted at rest' as title,
ce.account_id,
ce.arn as resource_id,
CASE
WHEN b.arn is not null THEN 'fail'
ELSE 'pass'
END as status
FROM
cache_enabled ce
LEFT JOIN bad_methods as b
ON ce.arn = b.arn
{% endmacro %}

{% macro bigquery__api_gw_cache_data_encrypted(framework, check_id) %}
with bad_methods as (
select DISTINCT
arn
from {{ full_table_name("aws_apigateway_rest_api_stages") }} as s,
UNNEST(JSON_QUERY_ARRAY(s.method_settings)) AS ms
WHERE
JSON_VALUE(ms.CachingEnabled) = 'true'
AND
JSON_VALUE(ms.CacheDataEncrypted) <> 'true'
),
cache_enabled AS (
select DISTINCT
arn,
account_id
FROM {{ full_table_name("aws_apigateway_rest_api_stages") }} as s,
UNNEST(JSON_QUERY_ARRAY(s.method_settings)) AS ms
WHERE
JSON_VALUE(ms.CachingEnabled) = 'true'
)
SELECT
'{{framework}}' As framework,
'{{check_id}}' As check_id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,39 @@ left join
{% endmacro %}

{% macro default__api_gw_execution_logging_enabled(framework, check_id) %}{% endmacro %}


{% macro bigquery__api_gw_execution_logging_enabled(framework, check_id) %}
(select distinct
'{{framework}}' As framework,
'{{check_id}}' As check_id,
'API Gateway REST and WebSocket API logging should be enabled' as title,
r.account_id,
'arn:' || 'aws' || ':apigateway:' || r.region || ':/restapis/' || r.id as resource_id,
case
when s.logging_level not in ('"ERROR"', '"INFO"') then 'fail'
else 'pass'
end as status
from
{{ ref('aws_compliance__api_gateway_method_settings') }} s
left join
{{ full_table_name("aws_apigateway_rest_apis") }} r on s.rest_api_arn = r.arn
)

union all

(select distinct
'{{framework}}' As framework,
'{{check_id}}' As check_id,
'API Gateway REST and WebSocket API logging should be enabled' as title,
a.account_id,
'arn:' || 'aws' || ':apigateway:' || a.region || ':/apis/' || a.id as resource_id,
case
when JSON_VALUE(s.default_route_settings.LoggingLevel) in (NULL, 'OFF') then 'fail'
else 'pass'
end as status
from
{{ full_table_name("aws_apigatewayv2_api_stages") }} s
left join
{{ full_table_name("aws_apigatewayv2_apis") }} a on s.api_arn = a.arn
)
{% endmacro %}
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,19 @@ select
END AS status
FROM
aws_apigatewayv2_api_routes
{% endmacro %}

{% macro bigquery__api_gw_routes_should_specify_authorization_type(framework, check_id) %}
select
'{{framework}}' As framework,
'{{check_id}}' As check_id,
'API Gateway routes should specify an authorization type' as title,
account_id,
arn as resource_id,
CASE
WHEN authorization_type IS NULL OR authorization_type = '' OR authorization_type = 'NONE' THEN 'fail'
ELSE 'pass'
END AS status
FROM
{{ full_table_name("aws_apigatewayv2_api_routes") }}
{% endmacro %}
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,19 @@ select
END as status
FROM
aws_apigateway_rest_api_stages
{% endmacro %}

{% macro bigquery__api_gw_stage_should_have_xray_tracing_enabled(framework, check_id) %}
select
'{{framework}}' As framework,
'{{check_id}}' As check_id,
'API Gateway REST API stages should have AWS X-Ray tracing enabled' as title,
account_id,
arn as resource_id,
CASE
WHEN tracing_enabled = true THEN 'pass'
ELSE 'fail'
END as status
FROM
{{ full_table_name("aws_apigateway_rest_api_stages") }}
{% endmacro %}
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,19 @@ select
END as status

from aws_apigateway_rest_api_stages
{% endmacro %}

{% macro bigquery__api_gw_stage_should_use_ssl(framework, check_id) %}
select
'{{framework}}' As framework,
'{{check_id}}' As check_id,
'API Gateway REST API stages should be configured to use SSL certificates for backend authentication' as title,
account_id,
arn as resource_id,
CASE
WHEN client_certificate_id is not null THEN 'pass'
ELSE 'fail'
END as status

from {{ full_table_name("aws_apigateway_rest_api_stages") }}
{% endmacro %}
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,20 @@ select
ELSE 'pass'
END AS status
FROM aws_appsync_graphql_apis
{% endmacro %}

{% macro bigquery__appsync_should_have_logging_turned_on(framework, check_id) %}
select
'{{framework}}' As framework,
'{{check_id}}' As check_id,
'AWS AppSync should have request-level and field-level logging turned on' as title,
account_id,
arn as resource_id,
CASE
WHEN (log_config.cloudWatchLogsRoleArn IS NULL OR CAST(JSON_VALUE(log_config.cloudWatchLogsRoleArn) AS STRING) = '')
OR
JSON_VALUE(log_config.fieldLogLevel) = 'NONE' THEN 'fail'
ELSE 'pass'
END AS status
FROM {{ full_table_name("aws_appsync_graphql_apis") }}
{% endmacro %}
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,17 @@ select
WHEN CONFIGURATION:ResultConfiguration:EncryptionConfiguration::STRING IS NULL THEN 'fail'
else 'pass' end as status
from aws_athena_work_groups
{% endmacro %}

{% macro bigquery__athena_workgroup_encrypted_at_rest(framework, check_id) %}
select
'{{framework}}' As framework,
'{{check_id}}' As check_id,
'Athena workgroups should be encrypted at rest' AS title,
account_id,
arn as resource_id,
case
WHEN CAST(JSON_VALUE(CONFIGURATION.ResultConfiguration.EncryptionConfiguration) AS STRING) IS NULL THEN 'fail'
else 'pass' end as status
from {{ full_table_name("aws_athena_work_groups") }}
{% endmacro %}
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,21 @@ select
AS status
FROM
aws_autoscaling_groups
{% endmacro %}

{% macro bigquery__autoscaling_group_elb_healthcheck_required(framework, check_id) %}
select
'{{framework}}' As framework,
'{{check_id}}' As check_id,
'Auto Scaling groups associated with a Classic Load Balancer should use load balancer health checks' AS title,
account_id,
arn AS resource_id,
case
when ARRAY_LENGTH(load_balancer_names) = 0 and ARRAY_LENGTH(target_group_arns) = 0 then 'fail'
when health_check_type not like '%ELB%' then 'fail'
else 'pass'
END
AS status
FROM
{{ full_table_name("aws_autoscaling_groups") }}
{% endmacro %}
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,20 @@ select
AS status
FROM
aws_autoscaling_launch_configurations
{% endmacro %}

{% macro bigquery__autoscaling_launch_config_hop_limit(framework, check_id) %}
select
'{{framework}}' As framework,
'{{check_id}}' As check_id,
'Auto Scaling group launch configuration should not have a metadata response hop limit greater than 1' AS title,
account_id,
arn AS resource_id,
case
when CAST(JSON_VALUE(METADATA_OPTIONS.HttpPutResponseHopLimit) AS INT64) > 1 then 'fail'
else 'pass'
END
AS status
FROM
{{ full_table_name("aws_autoscaling_launch_configurations") }}
{% endmacro %}
Loading

0 comments on commit 5209331

Please sign in to comment.