Skip to content

Commit

Permalink
Add common dimensions and tag dimensions to AWS Compliance Mod (#574)
Browse files Browse the repository at this point in the history
Co-authored-by: khushboo9024 <khushboo@turbot.com>
Co-authored-by: rajmohanty17 <raj@turbot.com>
  • Loading branch information
3 people committed Mar 22, 2023
1 parent c84f8aa commit 1bbc45c
Show file tree
Hide file tree
Showing 444 changed files with 11,100 additions and 9,657 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@

# Swap files
*.swp

# Steampipe variable files
*.spvars
*.auto.spvars
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,31 @@ This mod uses the credentials configured in the [Steampipe AWS plugin](https://h

No extra configuration is required.

### Common and Tag Dimensions

The benchmark queries use common properties (like `account_id`, `connection_name` and `region`) and tags that are defined in the form of a default list of strings in the `mod.sp` file. These properties can be overwritten in several ways:

- Copy and rename the `steampipe.spvars.example` file to `steampipe.spvars`, and then modify the variable values inside that file
- Pass in a value on the command line:

```shell
steampipe check benchmark.cis_v150 --var 'common_dimensions=["account_id", "connection_name", "region"]'
```

```shell
steampipe check benchmark.cis_v150 --var 'tag_dimensions=["Environment", "Owner"]'
```

- Set an environment variable:

```shell
SP_VAR_common_dimensions='["account_id", "connection_name", "region"]' steampipe check control.cis_v150_5_1
```

```shell
SP_VAR_tag_dimensions='["Environment", "Owner"]' steampipe check control.cis_v150_5_1
```

## Contributing

If you have an idea for additional controls or just want to help maintain and extend this mod ([or others](https://github.com/topics/steampipe-mod)) we would love you to join the community and start contributing.
Expand Down
32 changes: 32 additions & 0 deletions conformance_pack/account.sp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Non-Config rule query

query "account_alternate_contact_security_registered" {
sql = <<-EOQ
with alternate_security_contact as (
select
name,
account_id
from
aws_account_alternate_contact
where
contact_type = 'SECURITY'
)
select
arn as resource,
case
when a.partition = 'aws-us-gov' then 'info'
-- Name is a required field if setting a security contact
when c.name is not null then 'ok'
else 'alarm'
end as status,
case
when a.partition = 'aws-us-gov' then a.title || ' in GovCloud, manual verification required.'
when c.name is not null then a.title || ' has security contact ' || c.name || ' registered.'
else a.title || ' security contact not registered.'
end as reason
${replace(local.common_dimensions_qualifier_global_sql, "__QUALIFIER__", "a.")}
from
aws_account as a
left join alternate_security_contact as c on c.account_id = a.account_id;
EOQ
}
61 changes: 61 additions & 0 deletions conformance_pack/acm.sp
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,64 @@ control "acm_certificate_no_wildcard_domain_name" {
other_checks = "true"
})
}

query "acm_certificate_expires_30_days" {
sql = <<-EOQ
select
certificate_arn as resource,
case
when renewal_eligibility = 'INELIGIBLE' then 'skip'
when date(not_after) - date(current_date) >= 30 then 'ok'
else 'alarm'
end as status,
case
when renewal_eligibility = 'INELIGIBLE' then title || ' not eligible for renewal.'
else title || ' expires ' || to_char(not_after, 'DD-Mon-YYYY') ||
' (' || extract(day from not_after - current_date) || ' days).'
end as reason
${local.tag_dimensions_sql}
${local.common_dimensions_sql}
from
aws_acm_certificate;
EOQ
}

query "acm_certificate_no_wildcard_domain_name" {
sql = <<-EOQ
select
certificate_arn as resource,
case
when domain_name like '*%' then 'alarm'
else 'ok'
end as status,
case
when domain_name like '*%' then title || ' uses wildcard domain name.'
else title || ' does not use wildcard domain name.'
end as reason
${local.tag_dimensions_sql}
${local.common_dimensions_sql}
from
aws_acm_certificate;
EOQ
}

query "acm_certificate_transparency_logging_enabled" {
sql = <<-EOQ
select
certificate_arn as resource,
case
when type = 'IMPORTED' then 'skip'
when certificate_transparency_logging_preference = 'ENABLED' then 'ok'
else 'alarm'
end as status,
case
when type = 'IMPORTED' then title || ' is imported.'
when certificate_transparency_logging_preference = 'ENABLED' then title || ' transparency logging enabled.'
else title || ' transparency logging disabled.'
end as reason
${local.tag_dimensions_sql}
${local.common_dimensions_sql}
from
aws_acm_certificate;
EOQ
}
182 changes: 182 additions & 0 deletions conformance_pack/apigateway.sp
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,185 @@ control "apigateway_rest_api_authorizers_configured" {
other_checks = "true"
})
}

query "apigateway_stage_cache_encryption_at_rest_enabled" {
sql = <<-EOQ
select
'arn:' || partition || ':apigateway:' || region || '::/apis/' || rest_api_id || '/stages/' || name as resource,
case
when method_settings -> '*/*' ->> 'CachingEnabled' = 'true'
and method_settings -> '*/*' ->> 'CacheDataEncrypted' = 'true' then 'ok'
else 'alarm'
end as status,
case
when method_settings -> '*/*' ->> 'CachingEnabled' = 'true'
and method_settings -> '*/*' ->> 'CacheDataEncrypted' = 'true'
then title || ' API cache and encryption enabled.'
else title || ' API cache and encryption not enabled.'
end as reason
${local.tag_dimensions_sql}
${local.common_dimensions_sql}
from
aws_api_gateway_stage;
EOQ
}

query "apigateway_stage_logging_enabled" {
sql = <<-EOQ
with all_stages as (
select
name as stage_name,
'arn:' || partition || ':apigateway:' || region || '::/apis/' || rest_api_id || '/stages/' || name as arn,
method_settings -> '*/*' ->> 'LoggingLevel' as log_level,
title,
region,
account_id,
tags
from
aws_api_gateway_stage
union
select
stage_name,
'arn:' || partition || ':apigateway:' || region || '::/apis/' || api_id || '/stages/' || stage_name as arn,
default_route_logging_level as log_level,
title,
region,
account_id,
tags
from
aws_api_gatewayv2_stage
)
select
arn as resource,
case
when log_level is null or log_level = '' or log_level = 'OFF' then 'alarm'
else 'ok'
end as status,
case
when log_level is null or log_level = '' or log_level = 'OFF' then title || ' logging not enabled.'
else title || ' logging enabled.'
end as reason
${local.tag_dimensions_sql}
${local.common_dimensions_sql}
from
all_stages;
EOQ
}

query "apigateway_rest_api_stage_use_ssl_certificate" {
sql = <<-EOQ
select
arn as resource,
case
when client_certificate_id is null then 'alarm'
else 'ok'
end as status,
case
when client_certificate_id is null then title || ' does not use SSL certificate.'
else title || ' uses SSL certificate.'
end as reason
${local.tag_dimensions_sql}
${local.common_dimensions_sql}
from
aws_api_gateway_stage;
EOQ
}

query "apigateway_stage_use_waf_web_acl" {
sql = <<-EOQ
select
arn as resource,
case
when web_acl_arn is not null then 'ok'
else 'alarm'
end as status,
case
when web_acl_arn is not null then title || ' associated with WAF web ACL.'
else title || ' not associated with WAF web ACL.'
end as reason
${local.tag_dimensions_sql}
${local.common_dimensions_sql}
from
aws_api_gateway_stage;
EOQ
}

query "apigateway_rest_api_authorizers_configured" {
sql = <<-EOQ
select
p.name as resource,
case
when jsonb_array_length(a.provider_arns) > 0 then 'ok'
else 'alarm'
end as status,
case
when jsonb_array_length(a.provider_arns) > 0 then p.name || ' authorizers configured.'
else p.name || ' authorizers not configured.'
end as reason
${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "p.")}
${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "p.")}
from
aws_api_gateway_rest_api as p
left join aws_api_gateway_authorizer as a on p.api_id = a.rest_api_id;
EOQ
}

# Non-Config rule query

query "api_gatewayv2_route_authorization_type_configured" {
sql = <<-EOQ
select
'arn:' || partition || ':apigateway:' || region || '::/apis/' || api_id || '/routes/' || route_id as resource,
case
when authorization_type is null then 'alarm'
else 'ok'
end as status,
case
when authorization_type is null then route_id || ' authorization type not configured.'
else route_id || ' authorization type ' || authorization_type || ' configured.'
end as reason
${local.common_dimensions_sql}
from
aws_api_gatewayv2_route;
EOQ
}

query "apigateway_rest_api_stage_xray_tracing_enabled" {
sql = <<-EOQ
select
arn as resource,
case
when tracing_enabled then 'ok'
else 'alarm'
end as status,
case
when tracing_enabled then title || ' X-Ray tracing enabled.'
else title || ' X-Ray tracing disabled.'
end as reason
${local.tag_dimensions_sql}
${local.common_dimensions_sql}
from
aws_api_gateway_stage;
EOQ
}

query "gatewayv2_stage_access_logging_enabled" {
sql = <<-EOQ
select
'arn:' || partition || ':apigateway:' || region || '::/apis/' || api_id || '/stages/' || stage_name as resource,
case
when access_log_settings is null then 'alarm'
else 'ok'
end as status,
case
when access_log_settings is null then title || ' access logging disabled.'
else title || ' access logging enabled.'
end as reason
${local.tag_dimensions_sql}
${local.common_dimensions_sql}
from
aws_api_gatewayv2_stage;
EOQ
}
Loading

0 comments on commit 1bbc45c

Please sign in to comment.