turbot/steampipe-mod-aws-compliance

Control: 2 S3 buckets should prohibit public read access

Description

This control checks whether your S3 buckets allow public read access by evaluating the Block Public Access settings, the bucket policy, and the bucket access control list (ACL).

Unless you explicitly require everyone on the internet to be able to write to your S3 bucket, you should ensure that your S3 bucket is not publicly writable.

It does not check for read access to the bucket by internal principals, such as IAM roles. You should ensure that access to the bucket is restricted to authorized principals only.

Remediation

  1. Open the Amazon S3 console.
  2. Choose the name of the bucket identified in the finding.
  3. Choose Permissions and then choose Public access settings.
  4. Choose Edit, select all four options, and then choose Save.
  5. If prompted, enter confirm and then choose Confirm.

Usage

Run the control in your terminal:

powerpipe control run aws_compliance.control.foundational_security_s3_2

Snapshot and share results via Turbot Pipes:

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

SQL

This control uses a named query:

with public_acl as (
select
distinct name
from
aws_s3_bucket,
jsonb_array_elements(acl -> 'Grants') as grants
where
(grants -> 'Grantee' ->> 'URI' = 'http://acs.amazonaws.com/groups/global/AllUsers'
or grants -> 'Grantee' ->> 'URI' = 'http://acs.amazonaws.com/groups/global/AuthenticatedUsers')
and (
grants ->> 'Permission' = 'FULL_CONTROL'
or grants ->> 'Permission' = 'READ_ACP'
or grants ->> 'Permission' = 'READ'
)
),read_access_policy as (
select
distinct name
from
aws_s3_bucket,
jsonb_array_elements(policy_std -> 'Statement') as s,
jsonb_array_elements_text(s -> 'Action') as action
where
s ->> 'Effect' = 'Allow'
and (
s -> 'Principal' -> 'AWS' = '["*"]'
or s ->> 'Principal' = '*'
)
and (
action = '*'
or action = '*:*'
or action = 's3:*'
or action ilike 's3:get%'
or action ilike 's3:list%'
)
)
select
b.arn as resource,
case
when (block_public_acls or a.name is null) and not bucket_policy_is_public then 'ok'
when (block_public_acls or a.name is null) and (bucket_policy_is_public and block_public_policy) then 'ok'
when (block_public_acls or a.name is null) and (bucket_policy_is_public and p.name is null) then 'ok'
else 'alarm'
end as status,
case
when (block_public_acls or a.name is null) and not bucket_policy_is_public then b.title || ' not publicly readable.'
when (block_public_acls or a.name is null) and (bucket_policy_is_public and block_public_policy) then b.title || ' not publicly readable.'
when (block_public_acls or a.name is null) and (bucket_policy_is_public and p.name is null) then b.title || ' not publicly readable.'
else b.title || ' publicly readable.'
end as reason
, b.region, b.account_id
from
aws_s3_bucket as b
left join public_acl as a on b.name = a.name
left join read_access_policy as p on b.name = p.name;

Tags