Manage IAM policies using Python boto3 and AWS CLI
IAM Policies is a way to manage permissions for Groups, Users and Roles in AWS. IAM Policy is a list of permitted actions for particular resources. In this tutorial, we are going to learn how to manage IAM Policies using Python and AWS CLI. So, let’s get started.
List Managed IAM Policies
When we create an AWS account, it comes with a set of predefined IAM polices. These are called managed policies (i.e. policies managed by AWS). The first thing we will do is list all polices in the AWS account.
1 2 3 4 5 6 7 8 |
import boto3 iam = boto3.client('iam') # IAM low level client object response = iam.list_policies( Scope = 'AWS' # 'AWS'|'Local'|'All' ) for user in response['Policies']: print("PolicyName: {0}\nCreateDate: {1}\n" .format(user['PolicyName'], user['CreateDate'])) |
This function will return all of the AWS managed policies. There are a few important parameters to know while listing policies.
- Score – It has three possible values ‘AWS’, ‘Local’, and ‘All’. We can either list all AWS managed policies using ‘AWS’ or list all policies created by users using ‘Local’. And if we want to list all of the policies created by users as well as AWS then we can use ‘All’
- OnlyAttached – (True|Fasle) By default it is false and returns all policies. If it is True then only policies attached to Group, User or Role are returned.
- MaxItems – To limit the number of policies returned in one call we can use this parameter.
We can do this using AWS CLI in the following way.
1 2 3 |
mahesh@mahesh:~$ aws iam list-policies \ > --scope 'AWS' \ > --max-items 2 |
Create IAM policy
Now that we have listed all managed policies in AWS, Let us create our first user-managed or local policy. For creating policy, we need to give Policy Document which is nothing but a list of permissions for AWS resources represented in JSON format. If you are not familiar with how to create a policy document then you can visit the AWS Policy Generator to get the policy document. You can refer below the policy document which grants read and write access to only one S3 bucket. I have created an S3 bucket with the name my-test-bucket-123df and we will only grant read and write access to that bucket and no other S3 bucket using the below policy.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
import boto3 import json iam = boto3.client('iam') # IAM low level client object policyDocumet = { "Version": "2012-10-17", "Statement": [ { "Sid": "ListObjectsInBucket", "Effect": "Allow", "Action": ["s3:ListBucket"], "Resource": ["arn:aws:s3:::my-test-bucket-123df"] }, { "Sid": "AllObjectActions", "Effect": "Allow", "Action": "s3:*Object", "Resource": ["arn:aws:s3:::my-test-bucket-123df/*"] } ] } response = iam.create_policy( PolicyName='my-test-bucket-123df-admin-policy', PolicyDocument=json.dumps(policyDocumet), Description='Read and Write policy for my-test-bucket-123df bucket' ) print(response) |
This will create local policy in AWS IAM with “my-test-bucket-123df-admin-policy” name. We can verify that on the console.
To create an IAM policy using AWS CLI, we can run the following command.
1 2 3 4 5 |
mahesh@mahesh:~$ vi policy_doc.json mahesh@mahesh:~$ aws iam create-policy \ > --policy-name 'my-test-bucket-123df' \ > --policy-document policy_doc.json \ > --desciption 'a local policy' |
Create a New version of IAM Policy
There will be certain times that we need to update managed or local policy. Instead of updating policy, we can create different versions and use them. We also have the option to roll back to the previous version if have to.
There are few things to remember before we create a new version for policy. We can only have at max 5 versions of each policy. While creating policy version we can set that up as default version using SetAsDefault parameter. Now we know this, let us see, how to create a policy version
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
import boto3 import json iam = boto3.client('iam') # IAM low level client object policyDocumet = { "Version":"2012-10-17", "Statement":[ { "Sid":"AddPerm", "Effect":"Allow", "Action":["s3:GetObject"], "Resource":["arn:aws:s3:::my-test-bucket-123df/*"] } ] } response = iam.create_policy_version( PolicyArn='arn:aws:iam::195556345987:policy/my-test-bucket-123df-admin-policy', PolicyDocument=json.dumps(policyDocumet), SetAsDefault=True ) print(response) #same function using resource object iam_resource = boto3.resource('iam') #resource representing IAM policy = iam_resource.Policy('arn:aws:iam::195556345987:policy/my-test-bucket-123df-admin-policy') policy_version = policy.create_version( PolicyDocument=json.dumps(policyDocumet), SetAsDefault=True ) print(response) |
We can validate versions of policy on our AWS console.
We can create IAM Policy using AWS CLI using the command below.
1 2 3 4 |
mahesh@mahesh:~$ aws iam create-policy-version \ > --policy-arn 'arn:aws:iam::195556345987:policy/my-test-bucket-123df-admin-policy' \ > --policy-document policy_doc_v2.json \ > --set-as-default |
List Versions of IAM Policy
Now that we have different versions for IAM policies, the next logical step will be to write script list all versions of that policy. So let’s do it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import boto3 iam = boto3.client('iam') # IAM low level client object response = iam.list_policy_versions( PolicyArn='arn:aws:iam::195556345987:policy/my-test-bucket-123df-admin-policy' ) for policy_version in response['Versions']: print('VersionID: {0}\nIsDefaultVersion: {1}'.format( policy_version['VersionId'], policy_version['IsDefaultVersion'] )) iam_resource = boto3.resource('iam') #resource representing IAM policy = iam_resource.Policy('arn:aws:iam::195556345987:policy/my-test-bucket-123df-admin-policy') policy_version_iterator = policy.versions.all() for policy_version in policy_version_iterator: print(policy_version) |
Again, let’s see how we can do this in AWS CLI.
1 2 |
aws iam list-policy-versions \ > --policy-arn 'arn:aws:iam::195556345987:policy/my-test-bucket-123df-admin-policy' |
Get Policy and its Policy Document
We can get policy details using below python code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import boto3 iam = boto3.client('iam') # IAM low level client object response = iam.get_policy( PolicyArn='arn:aws:iam::195556345987:policy/my-test-bucket-123df-admin-policy' ) print(response) iam_resource = boto3.resource('iam') #resource representing IAM policy = iam_resource.Policy('arn:aws:iam::195556345987:policy/my-test-bucket-123df-admin-policy') """ following functions can be used with policy resouce to get policy level details attachment_count create_date default_version_id description is_attachable path permissions_boundary_usage_count policy_id policy_name update_date """ |
You will notice that this function “get_policy” does not return policy document. For getting the policy document, we have to use “get_policy_version” function.
1 2 3 4 5 |
response = iam.get_policy_version( PolicyArn='arn:aws:iam::195556345987:policy/my-test-bucket-123df-admin-policy', VersionId='v2' ) print(response['PolicyVersion']['Document']) |
1 2 3 4 |
#AWS CLI CODE aws iam get-policy-version \ > --policy-arn 'arn:aws:iam::195556345987:policy/my-test-bucket-123df-admin-policy' \ > --version-id 'v2' |
Delete Policy
Now we are going to write code for deleting IAM Policy using Python. Before we can delete policy, we need to make sure we have detached that policy from all Groups, Users, and Roles. Not only that, we have to delete all versions of that policy except the default version. So lets us start by deleting the policy version.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import boto3 iam = boto3.client('iam') # IAM low level client object response = iam.list_policy_versions( PolicyArn='arn:aws:iam::195556345987:policy/my-test-bucket-123df-admin-policy' ) for policy_version in response['Versions']: if policy_version['IsDefaultVersion']: continue response = iam.delete_policy_version( PolicyArn='arn:aws:iam::195556345987:policy/my-test-bucket-123df-admin-policy', VersionId=policy_version['VersionId'] ) response = iam.delete_policy( PolicyArn='arn:aws:iam::195556345987:policy/my-test-bucket-123df-admin-policy' ) print(response) |
Now let us write a script to delete IAM Policy using AWS CLI. Now I am not writing code with for loop but you get the idea. If you want that script with for loop to delete all versions of policy or to detach policy form Groups and users please let me know in comments.
1 2 3 4 5 6 |
mahesh@mahesh:~$ aws iam delete-policy-version \ > --policy-arn 'arn:aws:iam::195556345987:policy/my-test-bucket-123df-admin-policy' \ > --version-id 'v1' #delete policy command aws iam delete-policy \ > --policy-arn 'arn:aws:iam::195556345987:policy/my-test-bucket-123df-admin-policy' |
Conclusion
In this tutorial, we have learned how to manage IAM policies using python and AWS CLI. This is very useful when you have to write automated scripts or your applications. I hope you found this useful. See you in the next article.