Skip to content

Commit

Permalink
Merge pull request #735 from turbot/release/v0.83
Browse files Browse the repository at this point in the history
Release/v0.83
  • Loading branch information
madhushreeray30 authored Nov 30, 2023
2 parents 3e38f44 + 4ccdf18 commit 295fc36
Show file tree
Hide file tree
Showing 16 changed files with 479 additions and 0 deletions.
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
## v0.83 [2023-11-30]

_Enhancements_

- Added the following controls to the `All Controls` benchmark: ([#733](https://github.com/turbot/steampipe-mod-aws-compliance/pull/733))
- `api_gateway_rest_api_public_endpoint_with_authorizer`
- `dlm_ebs_snapshot_lifecycle_policy_enabled`
- `docdb_cluster_instance_encryption_at_rest_enabled`
- `ebs_volume_snapshot_exists`
- `elasticache_cluster_no_public_subnet`
- `iam_role_no_administrator_access_policy_attached`
- `iam_user_access_key_unused_45`
- `iam_user_console_access_unused_45`
- `neptune_db_cluster_no_public_subnet`

## v0.82 [2023-11-03]

_Breaking changes_
Expand Down
1 change: 1 addition & 0 deletions all_controls/all_controls.sp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ benchmark "all_controls" {
benchmark.all_controls_config,
benchmark.all_controls_dax,
benchmark.all_controls_directoryservice,
benchmark.all_controls_dlm,
benchmark.all_controls_dms,
benchmark.all_controls_docdb,
benchmark.all_controls_drs,
Expand Down
1 change: 1 addition & 0 deletions all_controls/apigateway.sp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ benchmark "all_controls_apigateway" {
title = "API Gateway"
description = "This section contains recommendations for configuring API Gateway resources."
children = [
control.api_gateway_rest_api_public_endpoint_with_authorizer,
control.api_gatewayv2_route_authorization_type_configured,
control.api_gatewayv2_route_authorizer_configured,
control.apigateway_rest_api_authorizers_configured,
Expand Down
17 changes: 17 additions & 0 deletions all_controls/dlm.sp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
locals {
all_controls_dlm_common_tags = merge(local.all_controls_common_tags, {
service = "AWS/DLM"
})
}

benchmark "all_controls_dlm" {
title = "DLM"
description = "This section contains recommendations for configuring DLM resources."
children = [
control.dlm_ebs_snapshot_lifecycle_policy_enabled
]

tags = merge(local.all_controls_dlm_common_tags, {
type = "Benchmark"
})
}
1 change: 1 addition & 0 deletions all_controls/docdb.sp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ benchmark "all_controls_docdb" {
children = [
control.docdb_cluster_backup_retention_period_7_days,
control.docdb_cluster_encryption_at_rest_enabled,
control.docdb_cluster_instance_encryption_at_rest_enabled,
control.docdb_cluster_instance_logging_enabled
]

Expand Down
1 change: 1 addition & 0 deletions all_controls/ebs.sp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ benchmark "all_controls_ebs" {
control.ebs_volume_encryption_at_rest_enabled,
control.ebs_volume_in_backup_plan,
control.ebs_volume_protected_by_backup_plan,
control.ebs_volume_snapshot_exists,
control.ebs_volume_unused
]

Expand Down
1 change: 1 addition & 0 deletions all_controls/elasticache.sp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ benchmark "all_controls_elasticache" {
children = [
control.elasticache_cluster_auto_minor_version_upgrade_enabled,
control.elasticache_cluster_no_default_subnet_group,
control.elasticache_cluster_no_public_subnet,
control.elasticache_redis_cluster_automatic_backup_retention_15_days,
control.elasticache_replication_group_auto_failover_enabled,
control.elasticache_replication_group_encryption_at_rest_enabled,
Expand Down
3 changes: 3 additions & 0 deletions all_controls/iam.sp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ benchmark "all_controls_iam" {
control.iam_policy_no_star_star,
control.iam_policy_unused,
control.iam_role_cross_account_read_only_access_policy,
control.iam_role_no_administrator_access_policy_attached,
control.iam_role_unused_60,
control.iam_root_last_used,
control.iam_root_user_hardware_mfa_enabled,
Expand All @@ -47,8 +48,10 @@ benchmark "all_controls_iam" {
control.iam_server_certificate_not_expired,
control.iam_support_role,
control.iam_user_access_key_age_90,
control.iam_user_access_key_unused_45,
control.iam_user_access_keys_and_password_at_setup,
control.iam_user_console_access_mfa_enabled,
control.iam_user_console_access_unused_45,
control.iam_user_group_role_cloudshell_fullaccess_restricted,
control.iam_user_hardware_mfa_enabled,
control.iam_user_in_group,
Expand Down
1 change: 1 addition & 0 deletions all_controls/neptune.sp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ benchmark "all_controls_neptune" {
control.neptune_db_cluster_deletion_protection_enabled,
control.neptune_db_cluster_encryption_at_rest_enabled,
control.neptune_db_cluster_iam_authentication_enabled,
control.neptune_db_cluster_no_public_subnet,
control.neptune_db_cluster_snapshot_encryption_at_rest_enabled,
control.neptune_db_cluster_snapshot_prohibit_public_access
]
Expand Down
30 changes: 30 additions & 0 deletions conformance_pack/apigateway.sp
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,14 @@ control "api_gatewayv2_route_authorizer_configured" {
tags = local.conformance_pack_apigateway_common_tags
}

control "api_gateway_rest_api_public_endpoint_with_authorizer" {
title = "API Gateway REST API public endpoints should be configured with authorizer"
description = "Ensure API Gateway REST API public endpoint is configured with authorizer. This rule is non-compliant if API Gateway REST API public endpoint has no authorizer configured."
query = query.api_gateway_rest_api_public_endpoint_with_authorizer

tags = local.conformance_pack_apigateway_common_tags
}

query "apigateway_stage_cache_encryption_at_rest_enabled" {
sql = <<-EOQ
select
Expand Down Expand Up @@ -354,3 +362,25 @@ query "gatewayv2_stage_access_logging_enabled" {
aws_api_gatewayv2_stage;
EOQ
}

query "api_gateway_rest_api_public_endpoint_with_authorizer" {
sql = <<-EOQ
select
'arn:' || p.partition || ':apigateway:' || p.region || '::/apis/' || p.api_id as resource,
case
when not (endpoint_configuration_types ? 'PRIVATE') and (a.provider_arns is not null and jsonb_array_length(a.provider_arns) > 0 ) then 'ok'
when not (endpoint_configuration_types ? 'PRIVATE') and ( a.provider_arns is null or jsonb_array_length(a.provider_arns) = 0 ) then 'alarm'
else 'ok'
end as status,
case
when not (endpoint_configuration_types ? 'PRIVATE') and (a.provider_arns is not null and jsonb_array_length(a.provider_arns) > 0 ) then p.name || ' has public endpoint with authorizer.'
when not (endpoint_configuration_types ? 'PRIVATE') and ( a.provider_arns is null or jsonb_array_length(a.provider_arns) = 0 ) then p.name || ' has public endpoint without authorizer.'
else p.name || ' has private endpoint.'
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
}
55 changes: 55 additions & 0 deletions conformance_pack/dlm.sp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
locals {
conformance_pack_dlm_common_tags = merge(local.aws_compliance_common_tags, {
service = "AWS/DLM"
})
}

control "dlm_ebs_snapshot_lifecycle_policy_enabled" {
title = "DLM EBS snapshot lifecycle policy should be enabled"
description = "Ensure DLM EBS snapshot lifecycle policy is enabled in all the regions with EBS snapshots."
query = query.dlm_ebs_snapshot_lifecycle_policy_enabled

tags = local.conformance_pack_dlm_common_tags
}

query "dlm_ebs_snapshot_lifecycle_policy_enabled" {
sql = <<-EOQ
with region_with_ebs_snapshots as(
select
distinct region,
partition,
account_id,
_ctx
from
aws_ebs_snapshot
), dlm_ebs_lifecycle_policy as (
select
region,
account_id,
count(*)
from
aws_dlm_lifecycle_policy
where
policy_details ->> 'PolicyType' like 'EBS_SNAPSHOT%'
group by
region,
account_id
)
select
'arn:' || r.partition || '::' || r.region || ':' || r.account_id as resource,
case
when p.region is not null then 'ok'
else 'alarm'
end as status,
case
when p.region is not null then 'EBS snapshot DLM policy exist in region ' || r.region || '.'
else 'EBS snapshots DLM policy does not exist in region ' || r.region || '.'
end as reason
${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "r.")}
from
region_with_ebs_snapshots as r
left join dlm_ebs_lifecycle_policy as p on p.region = r.region and r.account_id = p.account_id;
EOQ
}


27 changes: 27 additions & 0 deletions conformance_pack/docdb.sp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ control "docdb_cluster_instance_logging_enabled" {
tags = local.conformance_pack_docdb_common_tags
}

control "docdb_cluster_instance_encryption_at_rest_enabled" {
title = "DocumentDB instance should be encrypted at rest"
description = "This control checks whether an DocumentDB instance is encrypted at rest. The control fails if an DocumentDB instance isn't encrypted at rest."
query = query.docdb_cluster_instance_encryption_at_rest_enabled

tags = local.conformance_pack_docdb_common_tags
}

query "docdb_cluster_instance_logging_enabled" {
sql = <<-EOQ
select
Expand Down Expand Up @@ -83,3 +91,22 @@ query "docdb_cluster_backup_retention_period_7_days" {
aws_docdb_cluster;
EOQ
}

query "docdb_cluster_instance_encryption_at_rest_enabled" {
sql = <<-EOQ
select
db_instance_arn as resource,
case
when storage_encrypted then 'ok'
else 'alarm'
end as status,
case
when storage_encrypted then title || ' encrypted at rest.'
else title || ' not encrypted at rest.'
end as reason
${local.tag_dimensions_sql}
${local.common_dimensions_sql}
from
aws_docdb_cluster_instance;
EOQ
}
37 changes: 37 additions & 0 deletions conformance_pack/ebs.sp
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,14 @@ control "ebs_snapshot_encryption_enabled" {
tags = local.conformance_pack_ebs_common_tags
}

control "ebs_volume_snapshot_exists" {
title = "EBS volume snapshots should exist"
description = "Ensure that EBS volume snapshots exist. This rule is non-compliant if the EBS volume does not have any snapshot."
query = query.ebs_volume_snapshot_exists

tags = local.conformance_pack_ebs_common_tags
}

query "ebs_snapshot_not_publicly_restorable" {
sql = <<-EOQ
select
Expand Down Expand Up @@ -344,3 +352,32 @@ query "ebs_snapshot_encryption_enabled" {
aws_ebs_snapshot;
EOQ
}

query "ebs_volume_snapshot_exists" {
sql = <<-EOQ
with volume_with_snapshots as (
select
volume_id,
count(*) as snap_count
from
aws_ebs_snapshot
group by
volume_id
)
select
v.arn as resource,
case
when s.volume_id is not null then 'ok'
else 'alarm'
end as status,
case
when s.volume_id is not null then v.title || ' has ' || s.snap_count || ' snapshot(s).'
else v.title || ' does not have snapshot.'
end as reason
${local.tag_dimensions_sql}
${local.common_dimensions_sql}
from
aws_ebs_volume as v
left join volume_with_snapshots as s on s.volume_id = v.volume_id;
EOQ
}
90 changes: 90 additions & 0 deletions conformance_pack/elasticache.sp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,14 @@ control "elasticache_redis_cluster_automatic_backup_retention_15_days" {
})
}

control "elasticache_cluster_no_public_subnet" {
title = "ElastiCache clusters should not use public_subnet"
description = "This control checks if ElastiCache clusters are configured with public subnet as there is a risk of exposing sensitive data."
query = query.elasticache_cluster_no_public_subnet

tags = local.conformance_pack_elasticache_common_tags
}

query "elasticache_redis_cluster_automatic_backup_retention_15_days" {
sql = <<-EOQ
select
Expand Down Expand Up @@ -215,3 +223,85 @@ query "elasticache_cluster_auto_minor_version_upgrade_enabled" {
aws_elasticache_cluster;
EOQ
}

query "elasticache_cluster_no_public_subnet" {
sql = <<-EOQ
with subnets_with_explicit_route as (
select
distinct ( a ->> 'SubnetId') as all_sub
from
aws_vpc_route_table as t,
jsonb_array_elements(associations) as a
where
a ->> 'SubnetId' is not null
), public_subnets_with_explicit_route as (
select
distinct a ->> 'SubnetId' as SubnetId
from
aws_vpc_route_table as t,
jsonb_array_elements(associations) as a,
jsonb_array_elements(routes) as r
where
r ->> 'DestinationCidrBlock' = '0.0.0.0/0'
and
(
r ->> 'GatewayId' like 'igw-%'
or r ->> 'NatGatewayId' like 'nat-%'
)
and a ->> 'SubnetId' is not null
), public_subnets_with_implicit_route as (
select
distinct route_table_id,
vpc_id,
region
from
aws_vpc_route_table as t,
jsonb_array_elements(associations) as a,
jsonb_array_elements(routes) as r
where
a ->> 'Main' = 'true'
and r ->> 'DestinationCidrBlock' = '0.0.0.0/0'
and (
r ->> 'GatewayId' like 'igw-%'
or r ->> 'NatGatewayId' like 'nat-%'
)
), subnet_accessibility as (
select
subnet_id,
vpc_id,
case
when s.subnet_id in (select all_sub from subnets_with_explicit_route where all_sub not in (select SubnetId from public_subnets_with_explicit_route )) then 'private'
when p.SubnetId is not null or s.vpc_id in ( select vpc_id from public_subnets_with_implicit_route) then 'public'
else 'private'
end as access
from
aws_vpc_subnet as s
left join public_subnets_with_explicit_route as p on p.SubnetId = s.subnet_id
), cluster_public_subnet as (
select
distinct arn,
cache_subnet_group_name
from
aws_elasticache_subnet_group,
jsonb_array_elements(subnets) as s
left join subnet_accessibility as a on a.subnet_id = s ->> 'SubnetIdentifier'
where
a.access = 'public'
)
select
c.arn as resource,
case
when s.cache_subnet_group_name is not null then 'alarm'
else 'ok'
end as status,
case
when s.cache_subnet_group_name is not null then c.title || ' has public subnet.'
else c.title || ' has private subnet.'
end as reason
${local.tag_dimensions_sql}
${local.common_dimensions_sql}
from
aws_elasticache_cluster as c
left join cluster_public_subnet as s on s.cache_subnet_group_name = c.cache_subnet_group_name;
EOQ
}
Loading

0 comments on commit 295fc36

Please sign in to comment.