[AWS] S3 Security and Encryption

You can control S3 access in 3 ways:

  • Bucket Policies apply across the bucket.
  • Object Permissions apply to individual files.
  • IAM (Identity) policies apply to users and groups

S3 Security

Bucket authorization is controlled on many levels as well.

  • By default, the public access is disabled (private), and only a creator can access it.
  • Policies will be combined in the order of
    • Explicit Deny -> Explicit Allow -> Implicit Deny

Identity policies

  • are attached to IAM users, roles, and groups in your account.

Bucket policies

  • are the resource policies that apply to a bucket or objects.
  • grant permissions to anonymous users or IAM identities in another account (cross-account access). – Principal
  • are specific to S3 and cannot be used to access other services (e.g., EC2).
  • make the entire bucket (e.g., S3 static website) public
  • You can use the “Policy Generator
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::<Bucket-Name>/*"
            ]
        }
    ]
}

ACLs (Access Control Lists)

  • ACLs are applied to a bucket and an object – Not recommended anymore.
  • Bucket ACL is a legacy method, used to allow public access (Everyone group)
    • Bucket ACL is used to grant permission to an S3 Log Delivery group or everyone.
  • Note that Object ACL can be applied to an object directly.
    • Object ACL is used when an object is not owned by a bucket owner or grant public access.
  • Block public access is a setting applied on top of any settings. It overrules any other public grant.
  • S3 buckets can be configured to create “S3 access logs”.
  • S3 access logs contain all requests made to the bucket.

S3 Cross-Account Access

There are 3 ways to share S3 bucket access across accounts:

  • Using Bucket policies and IAM for the entire bucket – Programmatic access only.
  • Using Bucket ACLs and IAM for individual objects – Programmatic access only.
  • Using Cross-account IAM Roles – Programmatic access and Console access.

Data Encryption

Encryption in Transit

  • 3S Endpoints
    • HTTPS (SSL/TLS): Encrypted
    • HTTP: Not encrypted

Encryption at rest (Client-side)

  • The client is responsible for both the encryption/decryption and its keys.
  • You can use a customer master key (CMK) stored in AWS Key Management Service (AWS KMS) or use a master key that you store within your application.

Encryption at rest (Server-side)

TypeAbbreviationFeaturesPermissions
Customer-Managed KeysSSE-CS3 handles the process, but the customer needs to provide the key with each PUT and GET request.
S3-Managed KeysSSE-S3Objects are encrypted with AES-256 by S3.
Keys are stored with objects in an encrypted form.

You just need permission on the object to decrypt and access.
KMS-Managed KeysSSE-KMSObjects are encrypted using individual keys generated by KMS.You need both S3 and KMS permissions to access objects – role separation.
Server-side Encryption
  • Note that in S3 Glacier, all data is encrypted with SSE-S3 (AES-256).

Enforcing Encryption on S3 Buckets

Protecting data using server-side encryption with Amazon S3 managed encryption keys (SSE-S3) – Amazon Simple Storage Service

  • Objects (not Buckets) are encrypted in S3. Each put operation needs to specify an encryption type. The “Default encryption” setting in the bucket is used when a new object is uploaded. The change of the setting does not affect existing objects.
  • You can specify the encryption type in the S3 PUT Request.
  • The “x-amz-server-side-encryption” parameter is included in the request header:
    • AES256 (S3 Managed)
    • aws:kms
  • You can create a bucket policy that denies any S3 PUT request that does not include the “x-amz-server-side-encryption” parameter.
{
    "Version": "2012-10-17",
    "Statement": [
    {
        "Sid": "DenyIncorrectEncryptionHeader",
        "Effect": "Deny",
        "Principal": "*",
        "Action": [
            "s3:PutObject"
 	    ],
        "Resource": [
            "arn:aws:s3:::<Bucket-Name>/*"
        ],
        "Condition": {
            "StringNotEquals": {
                "s3:x-amz-server-side-encryption": "AES256"
            }
        }
    },
    {
        "Sid": "DenyUnencryptedObjectUploads",
        "Effect": "Deny",
        "Principal": "*",
        "Action": [
            "s3:PutObject"
 	    ],      
        "Resource": [
            "arn:aws:s3:::<Bucket-Name>/*"
        ],
        "Condition": {
            "Null": {
               "s3:x-amz-server-side-encryption": "true"
            }
        }
    }
    ]
}
  • Enforce HTTPS: Use “aws:SecureTransport
{
    "Version": "2012-10-17",
    "Statement": [
     {
         "Sid": "AllowHTTPSRequestOnly",
         "Effect": "Deny",
         "Principal": "*",
         "Action": [
              "s3:*"
         ],
         "Resource": [
            "arn:aws:s3:::<Bucket-Name>/*"
         ],
		 "Condition": {
		     "Bool": {
                 "aws:SecureTransport": "false"
             }
	     }
    }
    ]
}

Leave a Comment