turbot/steampipe-mod-aws-compliance

Control: 3.1.1 Ensure S3 Bucket Policy is set to deny HTTP requests

Description

At the Amazon S3 bucket level, you can configure permissions through a bucket policy, making the objects accessible only through HTTPS.

By default, Amazon S3 allows both HTTP and HTTPS requests. To ensure that access to Amazon S3 objects is only permitted through HTTPS, you must explicitly deny HTTP requests. Bucket policies that allow HTTPS requests without explicitly denying HTTP requests will not comply with this recommendation.

Remediation

From Console:

  1. Login to the AWS Management Console and open the Amazon S3 console using https://console.aws.amazon.com/s3/.
  2. Select the check box next to the Bucket.
  3. Click on Permissions.
  4. Click Bucket Policy.
  5. Add either of the following to the existing policy, filling in the required information:
{
"Sid": "<optional>",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": "arn:aws:s3:::<bucket_name>/*",
"Condition": {
"Bool": {
"aws:SecureTransport": "false"
}
}
}

or

{
"Sid": "<optional>",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::<bucket_name>",
"arn:aws:s3:::<bucket_name>/*"
],
"Condition": {
"NumericLessThan": {
"s3:TlsVersion": "1.2"
}
}
}
  1. Save.
  2. Repeat for all the buckets in your AWS account that contain sensitive data.

From Console

Using AWS Policy Generator:

  1. Repeat steps 1-4 above.
  2. Click on Policy Generator at the bottom of the Bucket Policy Editor.
  3. Select Policy Type
  4. Add Statements:
  • Effect = Deny
  • Principal = *
  • AWS Service = Amazon S3
  • Actions = *
  • Amazon Resource Name = <ARN of the S3 Bucket>
  1. Generate Policy.
  2. Copy the text and add it to the Bucket Policy.

From Command Line:

  1. Export the bucket policy to a json file:
aws s3api get-bucket-policy --bucket <bucket_name> --query Policy --output text > policy.json
  1. Modify the policy.json file by adding either of the following:
{
"Sid": "<optional>",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": "arn:aws:s3:::<bucket_name>/*",
"Condition": {
"Bool": {
"aws:SecureTransport": "false"
}
}
}

or

{
"Sid": "<optional>",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::<bucket_name>",
"arn:aws:s3:::<bucket_name>/*"
],
"Condition": {
"NumericLessThan": {
"s3:TlsVersion": "1.2"
}
}
}
  1. Apply this modified policy back to the S3 bucket:
aws s3api put-bucket-policy --bucket <bucket_name> --policy file://policy.json

Default Value:

By default, Amazon S3 accepts both HTTP and HTTPS requests. No bucket policy is applied to deny unencrypted (HTTP) access unless explicitly configured.

Usage

Run the control in your terminal:

powerpipe control run aws_compliance.control.cis_v600_3_1_1

Snapshot and share results via Turbot Pipes:

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

SQL

This control uses a named query:

with ssl_ok as (
select
distinct b.name,
b.arn,
'ok' as status
from
aws_s3_bucket b,
jsonb_array_elements(b.policy_std -> 'Statement') as s,
jsonb_array_elements_text(s -> 'Principal' -> 'AWS') as p,
jsonb_array_elements_text(s -> 'Action') as a,
jsonb_array_elements_text(s -> 'Resource') as r,
jsonb_array_elements_text (
case
when (s -> 'Condition' -> 'NumericLessThan' -> 's3:tlsversion') is not null then (s -> 'Condition' -> 'NumericLessThan' -> 's3:tlsversion')
when (s -> 'Condition' -> 'Bool' -> 'aws:securetransport') is not null then (s -> 'Condition' -> 'Bool' -> 'aws:securetransport')
else null end
) as ssl
where
p = '*'
and s ->> 'Effect' = 'Deny'
and (ssl = '1.2' or ssl :: bool = false)
)
select
b.arn as resource,
case
when ok.status = 'ok' then 'ok'
else 'alarm'
end status,
case
when ok.status = 'ok' then b.name || ' bucket policy enforces HTTPS.'
else b.name || ' bucket policy does not enforce HTTPS.'
end reason
, b.region, b.account_id
from
aws_s3_bucket as b
left join ssl_ok as ok on ok.name = b.name;

Tags