Skip to content

Instantly share code, notes, and snippets.

@magnetikonline
Last active November 22, 2023 06:42
Show Gist options
  • Save magnetikonline/6215d9e80021c1f8de12 to your computer and use it in GitHub Desktop.
Save magnetikonline/6215d9e80021c1f8de12 to your computer and use it in GitHub Desktop.
AWS S3 bucket and IAM policy recipes.

AWS S3 bucket and IAM policy recipes

Recipes

Anonymous GET access

Type: bucket

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "s3:GetObject",
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Resource": [
        "arn:aws:s3:::BUCKET_NAME/*"
      ]
    }
  ]
}

Anonymous GET access - match HTTP referrer

Type: bucket

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "s3:GetObject",
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Resource": [
        "arn:aws:s3:::BUCKET_NAME/*"
      ],
      "Condition": {
        "StringLike": {
          "aws:Referer": [
            "http://domain.com/*",
            "http://www.domain.com/*"
          ]
        }
      }
    }
  ]
}

Full access for specific IAM user/role

Type: bucket

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "s3:*",
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "arn:aws:iam::ACCOUNT_ID:user/USERNAME_A",
          "arn:aws:iam::ACCOUNT_ID:user/USERNAME_B",
          "arn:aws:iam::ACCOUNT_ID:user/USERNAME_C",
          "arn:aws:iam::ACCOUNT_ID:role/ROLE_A",
          "arn:aws:iam::ACCOUNT_ID:role/ROLE_B",
          "arn:aws:iam::ACCOUNT_ID:role/ROLE_C"
        ]
      },
      "Resource": [
        "arn:aws:s3:::BUCKET_NAME",
        "arn:aws:s3:::BUCKET_NAME/*"
      ]
    }
  ]
}

GET/PUT/DELETE access to specific path within a bucket

Type: user/group/role

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "s3:ListBucket",
      "Effect": "Allow",
      "Resource": [
        "arn:aws:s3:::BUCKET_NAME"
      ]
    },
    {
      "Action": [
        "s3:DeleteObject",
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Effect": "Allow",
      "Resource": [
        "arn:aws:s3:::BUCKET_NAME/BUCKET_PATH/*"
      ]
    }
  ]
}

Note: The s3:ListBucket action against the bucket as a whole allows for the listing of bucket objects.

Restricted LIST & PUT/DELETE access to specific path within a bucket

Type: user/group/role

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "s3:ListBucket",
      "Effect": "Allow",
      "Resource": [
        "arn:aws:s3:::BUCKET_NAME"
      ],
      "Condition": {
        "StringEquals": {
          "s3:delimiter": ["/"],
          "s3:prefix": ["","BUCKET_PATH/"]
        }
      }
    },
    {
      "Action": "s3:ListBucket",
      "Effect": "Allow",
      "Resource": [
        "arn:aws:s3:::BUCKET_NAME"
      ],
      "Condition": {
        "StringLike": {
          "s3:prefix": ["BUCKET_PATH/BUCKET_SUB_PATH/*"]
        }
      }
    },
    {
      "Action": [
        "s3:DeleteObject",
        "s3:PutObject"
      ],
      "Effect": "Allow",
      "Resource": [
        "arn:aws:s3:::BUCKET_NAME/BUCKET_PATH/BUCKET_SUB_PATH/*"
      ]
    }
  ]
}

Note: This policy effectively provides protected user folders within an S3 bucket:

  • The first s3:ListBucket action allows listing only of objects at the bucket root and under BUCKET_PATH/.
  • The second s3:ListBucket action allows listing of objects from the path of BUCKET_PATH/BUCKET_SUB_PATH/ and below.
  • Technique is covered here under the heading Block 2: Allow listing objects in root and home folders.

Full access (and S3 console) for specific IAM users

Type: user/group/role

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "s3:ListAllMyBuckets",
      "Effect": "Allow",
      "Resource": [
        "arn:aws:s3:::*"
      ]
    },
    {
      "Action": "s3:*",
      "Effect": "Allow",
      "Resource": [
        "arn:aws:s3:::BUCKET_NAME/*"
      ]
    }
  ]
}

Bucket and object delete deny

Type: bucket

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "s3:DeleteBucket",
      "Effect": "Deny",
      "Principal": "*",
      "Resource": [
        "arn:aws:s3:::BUCKET_NAME"
      ]
    },
    {
      "Action": "s3:DeleteObject",
      "Effect": "Deny",
      "Principal": "*",
      "Resource": [
        "arn:aws:s3:::BUCKET_NAME/*"
      ]
    }
  ]
}

Bucket enforce SSL requests only

Type: bucket

See: https://repost.aws/knowledge-center/s3-bucket-policy-for-config-rule

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "s3:*",
      "Effect": "Deny",
      "Principal": "*",
      "Resource": [
        "arn:aws:s3:::BUCKET_NAME/",
        "arn:aws:s3:::BUCKET_NAME/*"
      ],
      "Condition": {
        "Bool": {
          "aws:SecureTransport": "false"
        }
      }
    }
  ]
}

CloudTrail log receive

Type: bucket

See: https://docs.aws.amazon.com/awscloudtrail/latest/userguide/create-s3-bucket-policy-for-cloudtrail.html

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "s3:GetBucketAcl",
      "Effect": "Allow",
      "Principal": {
        "Service": "cloudtrail.amazonaws.com"
      },
      "Resource": [
        "arn:aws:s3:::BUCKET_NAME/*"
      ],
      "Condition": {
        "StringEquals": {
          "aws:SourceArn": "arn:aws:cloudtrail:AWS_REGION:AWS_ACCOUNT_ID:trail/TRAIL_NAME"
        }
      }
    },
    {
      "Action": "s3:PutObject",
      "Effect": "Allow",
      "Principal": {
        "Service": "cloudtrail.amazonaws.com"
      },
      "Resource": [
        "arn:aws:s3:::BUCKET_NAME/AWSLogs/AWS_ACCOUNT_ID/*"
      ],
      "Condition": {
        "StringEquals": {
          "aws:SourceArn": "arn:aws:cloudtrail:AWS_REGION:AWS_ACCOUNT_ID:trail/TRAIL_NAME",
          "s3:x-amz-acl": "bucket-owner-full-control"
        }
      }
    }
  ]
}

CloudFront origin access control (OAC) GET access

Type: bucket

See: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-s3.html

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "s3:GetObject",
      "Effect": "Allow",
      "Principal": {
        "Service": "cloudfront.amazonaws.com"
      },
      "Resource": [
        "arn:aws:s3:::BUCKET_NAME/*"
      ],
      "Condition": {
        "StringEquals": {
          "aws:SourceArn": "arn:aws:cloudfront::AWS_ACCOUNT_ID:distribution/DISTRIBUTION_ID"
        }
      }
    }
  ]
}

Reference

@magnetikonline
Copy link
Author

Hi, I have a similar need, to grant access on a bucket for a list of roles and users.
If I grant the access for the users - it is working, but for the roles it is not. Do you know if the roles need to also have some specific settings?

Thanks

Hey @gheorghina shouldn't be anything special, you would add the policy (from the template above) to a new role, then assign the role to EC2 compute/Lambda functions/etc. to which they should apply.

@gheorghina
Copy link

Hey thank you for the answer.
I figured it out my case. I write here, maybe it will help someone else at some point also.

My case is to copy an object from one bucket (from an Account A) to a different bucket( in an Account B).

In this case, the corresponding permissions have to be set:

  • in the IAM role or user which performs the copy action :
    - ListObject, GetObject, PutObject - from the source bucket
    - PutObject and PutObjectAcl for the destination bucket
  • in the destination bucket:
    - Allow PutObject and PutObjectAcl for the source account - set as Principal.

@magnetikonline
Copy link
Author

Nice one @gheorghina - i've had major pains with bucket -> bucket copies in the past.

The best advice I can give, always copy from a user/role in the target bucket account that can reach into the source. That way, you don't have to worry about getting ACL's correct on the new objects as they are placed into the target bucket.

I've had a few instances where I've not done this, and then the target bucket objects can't actually be read by account itself!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment