In the spirt of the AWS automation and helper I've posted recently here is another one.  Control [S3.5] of the AWS Foundational Security Best Practices states that S3 buckets should require requests to use Secure Socket Layer.

Cool.  Seams easy enough and frankly everything uses SSL these days so changing any buckets that don't disable SSL is a pretty innocuous change.  As far as I can tell though there isn't an easy button in AWS to make this a reality, so we're back to bash scripting.

The trick here is that if a bucket already has a policy and it doesn't already enforce SSL we have to append the bits that deny any non-secure connections.  If no policy exists we have to create a new one.

#!/bin/bash

buckets=`aws s3api list-buckets | jq -r '.Buckets[].Name'`

for bucket in $buckets
do
    #echo "$bucket"
    if aws s3api get-bucket-policy --bucket $bucket --query Policy --output text &> /dev/null; then
        size=`aws s3api get-bucket-policy --bucket $bucket --query Policy --output text | jq -r 'select(.Statement[].Condition.Bool."aws:SecureTransport"=="false")' | wc | awk {'print $1'}`
        
        if [ $size == 0 ]; then 
            echo "Appending Policy to $bucket"
            aws s3api put-bucket-policy --bucket $bucket --policy "$(aws s3api get-bucket-policy --bucket $bucket --query Policy --output text | jq --arg bucket "$bucket" '.Statement += [{"Sid":"AllowSSLRequestsOnly","Action":"s3:*","Effect":"Deny","Resource":["arn:aws:s3:::" + $bucket + "","arn:aws:s3:::" + $bucket + "/*"],"Condition":{"Bool":{"aws:SecureTransport":"false"}},"Principal":"*"}]')"
        fi
    else
        echo "Creating Policy for $bucket"
        #echo '{"Id":"ExamplePolicy","Version":"2012-10-17","Statement":[{"Sid":"AllowSSLRequestsOnly","Action":"s3:*","Effect":"Deny","Resource":["arn:aws:s3:::'"$bucket"'","arn:aws:s3:::'"$bucket"'/*"],"Condition":{"Bool":{"aws:SecureTransport":"false"}},"Principal":"*"}]}'
        aws s3api put-bucket-policy --bucket $bucket --policy '{"Id":"ExamplePolicy","Version":"2012-10-17","Statement":[{"Sid":"AllowSSLRequestsOnly","Action":"s3:*","Effect":"Deny","Resource":["arn:aws:s3:::'"$bucket"'","arn:aws:s3:::'"$bucket"'/*"],"Condition":{"Bool":{"aws:SecureTransport":"false"}},"Principal":"*"}]}'
    fi
done

As always I'm sure there are probably more concise or cleaner ways to do this, but I'm just you local neighborhood product manager and not a developer and certainly not a DevOps person.

Use this at your own risk.