What are the IAM and bucket policies for allowing users to PUT objects only if they come from a S3 bucket source?

Viewed 79

Currently, S3 GET and PUT actions allow users to upload anything from their local environment into S3 buckets. I am interested in restricting this.

Imagine I have two buckets:

  • One called landing-zone, which can be used by data engineers to GET and PUT objects from their local environment or all other buckets.
  • One called analysis, which can only be used by data analysts to PUT objects which originate from the landing-zone or analysis S3 bucket. (Ideally, analysts would be able to take data from the landing-zone or analysis S3 bucket, modify it, and PUT it back into analysis S3.)

enter image description here

I created separate access points for the landing-zone and analysis S3 buckets and then created S3 bucket policies for each, for an analyst user, using the following format.

{
    "Version": "2012-10-17",
    "Statement" : 
    [
        {
            "Effect": "Allow",
            "Principal" : {"AWS": "arn-user-analyst-name"},
            "Action" : "s3:*",
            "Resource" : "access-point-arn-landing-zone",
            "Condition": {"StringEquals": {"s3:DataAccessPointAccount": "aws-account-id"}}
        }
    ]
}

I then created an IAM access policy for analysts with the following S3 permissions.

...
{
            "Sid": "AccessAllS3Settings",
            "Effect": "Allow",
            "Action": [
                "s3:ListAllMyBuckets",
                "s3:ListBucket",
                "s3:ListBucketVersions",
                "s3:GetBucketVersioning",
                "s3:GetBucketPolicyStatus",
                "s3:GetBucketPublicAccessBlock",
                "s3:GetAccountPublicAccessBlock",
                "s3:GetBucketAcl",
                "s3:GetObjectAcl",
                "s3:ListAccessPointsForObjectLambda",
                "s3:ListBucketMultipartUploads",
                "s3:ListAccessPoints",
                "s3:GetAccessPoint",
                "s3:CreateAccessPoint",
                "s3:ListJobs",
                "s3:CreateJob",
                "s3:ListStorageLensConfigurations",
                "s3:PutStorageLensConfiguration",
                "s3:ListMultipartUploadParts",
                "s3:ListMultiRegionAccessPoints",
                "s3:GetBucketPolicy",
                "s3:GetBucketLogging",
                "s3:GetBucketNotification",
                "s3:GetBucketLocation",
                "s3:GetEncryptionConfiguration"
                ],
            "Resource": "*", 
            "Condition": {"StringEquals": {"aws:RequestedRegion": "ap-southeast-2"}}
        },

        {
            "Sid": "GetAllS3Buckets",
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:GetObjectVersion", 
                "s3:GetObjectVersionAttributes",
                "s3:GetObjectAttributes"
                ],
            "Resource": [
                "arn:aws:s3:::landing-zone",
                "arn:aws:s3:::landing-zone/*",
                "arn:aws:s3:::analysis",
                "arn:aws:s3:::analysis/*"
                ], 
            "Condition": {"StringEquals": {"aws:RequestedRegion": "ap-southeast-2"}}
        },

        {
            "Sid": "PutAnalysisS3BucketLimitedBySource",
            "Effect": "Allow",
            "Action": "s3:PutObject",
            "Resource": [
                "arn:aws:s3:::analysis",
                "arn:aws:s3:::analysis/*"
                ], 
            "Condition": {
                "StringEquals": {"aws:RequestedRegion": "ap-southeast-2"},
                "ForAnyValue:StringEquals": {"s3:DataAccessPointArn": [
                    "access-point-arn-landing-zone>",
                    "access-point-arn-analysis>"
                    ]}  
                }
        }
...

However, when I test this policy as an analyst, copying an existing test dataset from the landing-zone to analysis S3 bucket fails i.e. aws s3 cp s3://landing-zone/test.txt s3://analysis/test.txt --sse AES256 produces An error occurred (AccessDenied) when calling the CopyObject operation: Access Denied.

I can open datasets in the landing-zone to analysis S3 buckets fine.

What am I doing wrong?

1 Answers

The error you're receiving is for the CopyObject action, which isn't the same as GetObject or PutObject.

If you add s3:CopyObject to your actions this should work, but with the current setup I believe this would allow the analyst to copy from landing-zone to analysis and vice versa, which would mean analysts can mess with the data in the landing-zone.

Related