Control: KMS CMK policies should prohibit public access
Description
Manage access to resources in the AWS Cloud by ensuring AWS KMS CMK cannot be publicly accessed.
Usage
Run the control in your terminal:
powerpipe control run aws_compliance.control.kms_cmk_policy_prohibit_public_access
Snapshot and share results via Turbot Pipes:
powerpipe loginpowerpipe control run aws_compliance.control.kms_cmk_policy_prohibit_public_access --share
SQL
This control uses a named query:
with wildcard_action_policies as ( select arn, count(*) as statements_num from aws_kms_key, jsonb_array_elements(policy_std -> 'Statement') as s where s ->> 'Effect' = 'Allow' -- kms:CallerAccount and s -> 'Condition' -> 'StringEquals' -> 'kms:calleraccount' is null and s -> 'Condition' -> 'StringEqualsIgnoreCase' -> 'kms:calleraccount' is null and ( s -> 'Condition' -> 'StringLike' -> 'kms:calleraccount' is null or s -> 'Condition' -> 'StringLike' -> 'kms:calleraccount' ? '*' ) -- aws:SourceOwner and s -> 'Condition' -> 'StringEquals' -> 'aws:sourceowner' is null and s -> 'Condition' -> 'StringEqualsIgnoreCase' -> 'aws:sourceowner' is null and ( s -> 'Condition' -> 'StringLike' -> 'aws:sourceowner' is null or s -> 'Condition' -> 'StringLike' -> 'aws:sourceowner' ? '*' ) -- aws:SourceAccount and s -> 'Condition' -> 'StringEquals' -> 'aws:sourceaccount' is null and s -> 'Condition' -> 'StringEqualsIgnoreCase' -> 'aws:sourceaccount' is null and ( s -> 'Condition' -> 'StringLike' -> 'aws:sourceaccount' is null or s -> 'Condition' -> 'StringLike' -> 'aws:sourceaccount' ? '*' ) -- aws:PrincipalOrgID and s -> 'Condition' -> 'StringEquals' -> 'aws:principalorgid' is null and s -> 'Condition' -> 'StringEqualsIgnoreCase' -> 'aws:principalorgid' is null and ( s -> 'Condition' -> 'StringLike' -> 'aws:principalorgid' is null or s -> 'Condition' -> 'StringLike' -> 'aws:principalorgid' ? '*' ) -- aws:PrincipalAccount and s -> 'Condition' -> 'StringEquals' -> 'aws:principalaccount' is null and s -> 'Condition' -> 'StringEqualsIgnoreCase' -> 'aws:principalaccount' is null and ( s -> 'Condition' -> 'StringLike' -> 'aws:principalaccount' is null or s -> 'Condition' -> 'StringLike' -> 'aws:principalaccount' ? '*' ) -- aws:PrincipalArn and s -> 'Condition' -> 'StringEquals' -> 'aws:principalarn' is null and s -> 'Condition' -> 'StringEqualsIgnoreCase' -> 'aws:principalarn' is null and ( s -> 'Condition' -> 'StringLike' -> 'aws:principalarn' is null or s -> 'Condition' -> 'StringLike' -> 'aws:principalarn' ? '*' ) and ( s -> 'Condition' -> 'ArnEquals' -> 'aws:principalarn' is null or s -> 'Condition' -> 'ArnEquals' -> 'aws:principalarn' ? '*' ) and ( s -> 'Condition' -> 'ArnLike' -> 'aws:principalarn' is null or s -> 'Condition' -> 'ArnLike' -> 'aws:principalarn' ? '*' ) -- aws:SourceArn and s -> 'Condition' -> 'StringEquals' -> 'aws:sourcearn' is null and s -> 'Condition' -> 'StringEqualsIgnoreCase' -> 'aws:sourcearn' is null and ( s -> 'Condition' -> 'StringLike' -> 'aws:sourcearn' is null or s -> 'Condition' -> 'StringLike' -> 'aws:sourcearn' ? '*' ) and ( s -> 'Condition' -> 'ArnEquals' -> 'aws:sourcearn' is null or s -> 'Condition' -> 'ArnEquals' -> 'aws:sourcearn' ? '*' ) and ( s -> 'Condition' -> 'ArnLike' -> 'aws:sourcearn' is null or s -> 'Condition' -> 'ArnLike' -> 'aws:sourcearn' ? '*' ) and ( s -> 'Principal' -> 'AWS' = '["*"]' or s ->> 'Principal' = '*' ) group by arn)select k.arn as resource, case when p.arn is null then 'ok' else 'alarm' end status, case when p.arn is null then title || ' does not allow public access.' else title || ' contains ' || coalesce(p.statements_num, 0) || ' statements that allow public access.' end as reason , k.region, k.account_idfrom aws_kms_key as k left join wildcard_action_policies as p on p.arn = k.arnwhere key_manager = 'CUSTOMER';