8

I have a S3 bucket read policy :

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

Based on a cloud trail logs when new bucket is created , I am creating an event which will invoke a Lambda function.

Able to read json for the policy and add a new resource (bucket) to the same policy. Is there a direct python API to be invoked which will update an existing IAM policy with new resource ?

3
  • No, you need to replace the policy. Of course you could do that by loading the current policy into some kind of JSON-aware code, insert the things that are currently missing, emit the updated policy as a string, and then update the S3 policy with that. By the way that's an S3 policy you've shown, not an IAM policy - they look similar but are different (it has a Principal). Commented Jun 19, 2018 at 20:23
  • An alternative is to have a bucket naming scheme (eg foo-24) and grant the Lambda function permission to access foo-*. You then won't have to modify the permissions each time. Or, since you're always adding permissions for every new bucket, just grant it access to every bucket in the first place and you won't have to modify the policy. Commented Jun 19, 2018 at 21:53
  • @jarmod , thanks for pointing out changed to IAM policy now Commented Jun 19, 2018 at 22:15

2 Answers 2

13

I found the right way of doing it:

You have to create a policy version (including your policy changes) of your existing policy and tag it as default. As so the new version will replace the existing policy.

Get your existing policy :

policy = iam.Policy('arn:aws:iam::' + ACCOUNT_ID + ':policy/' + POLICY_NAME)

Get JSON from this policy:

policyJson = policy.default_version.document

Change it as you want:

policyJson['Statement'].append({  
'Action': '*',
'Resource': 'arn:aws:ec2:::*/*',
'Effect': 'Allow'
})

Create a policy version with the new JSON and the option SetAsDefault to True

response = client.create_policy_version(
    PolicyArn= 'arn:aws:iam::' + ACCOUNT_ID + ':policy/' + POLICY_NAME,
    PolicyDocument= json.dumps(policyJson),
    SetAsDefault= True
)

Delete the previous version (optional but recommanded max 5 versions ):

response = client.delete_policy_version(
    PolicyArn= 'arn:aws:iam::' + ACCOUNT_ID + ':policy/' + POLICY_NAME,
    VersionId= version.version_id
    ) 

And you're good to go!

Thomas.

Ref: IAM DOC

Sign up to request clarification or add additional context in comments.

Comments

-1

You have to get the IAM policy, then delete and finally create it again with modified JSON as it was previously suggested.

Code Snippet

import boto3, json

# Create IAM client
iam = boto3.resource('iam')

policy = iam.Policy('arn:aws:iam::ACCCOUNT_ID:policy/CustomS3Policy')
version = policy.default_version
policyJson = version.document
policyJson['Statement'][0]['Resource'].append('arn:aws:s3:::anotherbucket/*')

print(policyJson)

client = boto3.client('iam')
response = client.delete_policy(
    PolicyArn='arn:aws:iam::ACCCOUNT_ID:policy/CustomS3Policy'
)
print(response)

response = client.create_policy(
  PolicyName='CustomS3Policy',
  PolicyDocument=json.dumps(policyJson)
)
print(response)

References:

http://boto3.readthedocs.io/en/latest/guide/iam-example-policies.html https://boto3.readthedocs.io/en/latest/reference/services/iam.html#IAM.Client.delete_policy https://gist.github.com/alexcasalboni/07414d62290828ea03a14b4bf2157fd1

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.