turbot/steampipe-mod-aws-compliance

Control: Ensure the S3 bucket CloudTrail logs to is not publicly accessible

Description

CloudTrail logs a record of every API call made in your account. These log files are stored in an S3 bucket. Security Hub recommends that the S3 bucket policy, or access control list (ACL), be applied to the S3 bucket that CloudTrail logs to prevent public access to the CloudTrail logs.

Usage

Run the control in your terminal:

powerpipe control run aws_compliance.control.cloudtrail_bucket_not_public

Snapshot and share results via Turbot Pipes:

powerpipe login
powerpipe control run aws_compliance.control.cloudtrail_bucket_not_public --share

SQL

This control uses a named query:

with public_bucket_data as (
-- note the counts are not exactly CORRECT because of the jsonb_array_elements joins,
-- but will be non-zero if any matches are found
select
t.s3_bucket_name as name,
b.arn,
t.region,
t.account_id,
t.tags,
t._ctx,
count(acl_grant) filter (where acl_grant -> 'Grantee' ->> 'URI' like '%acs.amazonaws.com/groups/global/AllUsers') as all_user_grants,
count(acl_grant) filter (where acl_grant -> 'Grantee' ->> 'URI' like '%acs.amazonaws.com/groups/global/AuthenticatedUsers') as auth_user_grants,
count(s) filter (where s ->> 'Effect' = 'Allow' and p = '*' ) as anon_statements
from
aws_cloudtrail_trail as t
left join aws_s3_bucket as b on t.s3_bucket_name = b.name
left join jsonb_array_elements(acl -> 'Grants') as acl_grant on true
left join jsonb_array_elements(policy_std -> 'Statement') as s on true
left join jsonb_array_elements_text(s -> 'Principal' -> 'AWS') as p on true
group by
t.s3_bucket_name,
b.arn,
t.region,
t.account_id,
t.tags,
t._ctx
)
select
case
when arn is null then 'arn:aws:s3::' || name
else arn
end as resource,
case
when arn is null then 'skip'
when all_user_grants > 0 then 'alarm'
when auth_user_grants > 0 then 'alarm'
when anon_statements > 0 then 'alarm'
else 'ok'
end as status,
case
when arn is null then name || ' not found in account ' || account_id || '.'
when all_user_grants > 0 then name || ' grants access to AllUsers in ACL.'
when auth_user_grants > 0 then name || ' grants access to AuthenticatedUsers in ACL.'
when anon_statements > 0 then name || ' grants access to AWS:*" in bucket policy.'
else name || ' does not grant anonymous access in ACL or bucket policy.'
end as reason
, region, account_id
from
public_bucket_data;

Tags