S3 modify bucket policy using boto/boto3

0

Hi Team, Need help, was looking for a way to modify S3 bucket policy with Lambda (Python3.10) trigger. Since there is no update bucket policy is possible I was looking for option by which I can fetch existing bucket policy then modify that and put the bucket policy back. I was trying the below code but that did not help...

`#s3_client = boto3.client('s3')

bucket_name = 'vpc-flow-log-sudsark'

def lambda_handler(event, context):

# Or use client to get Bucket policy
s3_client = boto3.client('s3')
policy = s3_client.get_bucket_policy(Bucket='vpc-flow-log-sudsark')

# assign policy using s3 resource 
user_policy = {
        "Sid": "AutomatedRestrictiveAccess",
        "Effect": "Allow",
        "Principal": {
            "Service": "delivery.logs.amazonaws.com"
        },
        "Action": "s3:PutObject",
        "Resource": "arn:aws:s3:::vpc-flow-log-sudsark/*",
        "Condition": {
            "StringEquals": {
                "s3:x-amz-acl": "bucket-owner-full-control",
                "aws:SourceAccount": "333344445555"
            }
        }
    }
new_policy =  policy['Statement'].append(user_policy)
s3_client.put_bucket_policy(Policy=new_policy)

`

asked 2 months ago311 views
1 Answer
0

Hello.

I modified the Lambda code as below.
There are a few changes, but "get_bucket_policy()" does not directly retrieve the bucket policy in json, so it is necessary to retrieve only the bucket policy part from the response.
The response looks like this:

{'ResponseMetadata': {'RequestId': 'TTTTTTTTTT', 'HostId': 'TTTTTTTTTTTTTT=', 'HTTPStatusCode': 200, 'HTTPHeaders': {'x-amz-id-2': 'TTTTTTTTTTT=', 'x-amz-request-id': 'TTTTTTTTTTTT', 'date': 'Sat, 09 Mar 2024 05:58:03 GMT', 'content-type': 'application/json', 'transfer-encoding': 'chunked', 'server': 'AmazonS3'}, 'RetryAttempts': 0}, 'Policy': '{"Version":"2012-10-17","Statement":[{"Sid":"AWSLogDeliveryAclCheck","Effect":"Allow","Principal":{"Service":"delivery.logs.amazonaws.com"},"Action":"s3:GetBucketAcl","Resource":"arn:aws:s3:::test-s3","Condition":{"StringEquals":{"aws:SourceAccount":"1111111111111"},"ArnLike":{"aws:SourceArn":"arn:aws:logs:ap-northeast-1:111111111111:*"}}}]}'}

Also, near the end, a variable called "new_policy" is created, but since it only contained statement, we modified it to contain the bucket policy after creation.
"put_bucket_policy()" requires a bucket name to be specified as a parameter, so I added it.
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3/client/put_bucket_policy.html

import boto3
import json
s3_client = boto3.client('s3')

bucket_name = 'vpc-flow-log-sudsark'

def lambda_handler(event, context):

    # Or use client to get Bucket policy
    s3_client = boto3.client('s3')
    res = s3_client.get_bucket_policy(Bucket='vpc-flow-log-sudsark')
    policy_json = res['Policy']
    policy = json.loads(policy_json)

    # assign policy using s3 resource 
    user_policy = {
            "Sid": "AutomatedRestrictiveAccess",
            "Effect": "Allow",
            "Principal": {
                "Service": "delivery.logs.amazonaws.com"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::vpc-flow-log-sudsark/*",
            "Condition": {
                "StringEquals": {
                    "s3:x-amz-acl": "bucket-owner-full-control",
                    "aws:SourceAccount": "333344445555"
                }
            }
        }
    policy['Statement'].append(user_policy)
    new_policy = json.dumps(policy)
    print(new_policy)
    s3_client.put_bucket_policy(Bucket='vpc-flow-log-sudsark', Policy=new_policy)
profile picture
EXPERT
answered 2 months ago
profile pictureAWS
EXPERT
reviewed 2 months ago
  • Thanks Riku, this helps . Much appreciated. I just went ahead and looking for further enhancement where I was like checking an option to append only the "aws:SourceAccount": "333344445555" with the existing bucket policy. As an example say I ale4ready have this bucket policy having an account into it already added, then I want to append another account just created with "aws:SourceAccount": "666677778888". While doing so it would help reduce the policy size and also much more better looking. ANy help on this would be greatly appreciated, i am still checking how can i do that no success yet.

  • I think I got it, let me try out .

  • I have tried below code, but its atually returning null in account number, could you please check once and let me know if you found anything of it .

    `import boto3 import json s3_client = boto3.client('s3')

    bucket_name = 'vpc-flow-log-sudsark' NEW_ACCOUNT_ID = '999999999999' def lambda_handler(event, context):

    # Or use client to get Bucket policy
    s3_client = boto3.client('s3')
    res = s3_client.get_bucket_policy(Bucket='vpc-flow-log-sudsark')
    policy_json = res['Policy']
    policy = json.loads(policy_json)
    
    # assign policy using s3 resource 
    
    for statement in policy['Statement']:
        if 'Condition' in statement:
            if 'StringEquals' in statement['Condition']:
                if 'aws:SourceAccount' in statement['Condition']['StringEquals']:
                    if statement['Condition']['StringEquals']['aws:SourceAccount'] is list:
                        statement['Condition']['StringEquals']['aws:SourceAccount'].append(NEW_ACCOUNT_ID)
                    else:
                        statement['Condition']['StringEquals']['aws:SourceAccount'] = list(statement['Condition']['StringEquals']['aws:SourceAccount']).append(NEW_ACCOUNT_ID)
    
    new_policy = json.dumps(policy)
    print(new_policy)
    

    s3_client.put_bucket_policy(Bucket='vpc-flow-log-sudsark', Policy=new_policy)`

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions