AWS Boto3 is the Python SDK for AWS. Boto3 can be used to directly interact with AWS resources from Python scripts. In this tutorial, we will look at how we can use the Boto3 library to perform various operations on AWS IAM. IAM (Identity & Access Management) can be used to create new AWS users, manage their permissions, create new policies and much more.

Table of contents

Prerequisites

  • Python3
  • Boto3: Boto3 can be installed using pip: pip install boto3
  • AWS Credentials: If you haven’t setup AWS credentials before, this resource from AWS is helpful.

How to create a user?

AWS recommends creating a new IAM user as soon as you setup a new AWS account and not to use the root account.

def create_user(username):
    iam = boto3.client("iam")
    response = iam.create_user(UserName=username)
    print(response)

The output of this function is:

create_user("test-iam-user")

{'User': {'Path': '/', 'UserName': 'test-iam-user', 'UserId': 'AIDA2V2OH2EKN7ZFKTIAK', 'Arn': 'arn:aws:iam::xxxxx:user/test-iam-user', 'CreateDate': datetime.datetime(2021, 5, 12, 3, 14, 32, tzinfo=tzutc())}, 'ResponseMetadata': {'RequestId': 'b9fb6223-723d-4d32-9e20-d743ce86e78c', 'HTTPStatusCode': 200, 'HTTPHeaders': {'x-amzn-requestid': 'b9fb6223-723d-4d32-9e20-d743ce86e78c', 'content-type': 'text/xml', 'content-length': '487', 'date': 'Wed, 12 May 2021 03:14:32 GMT'}, 'RetryAttempts': 0}}


How to list all users?

Next, we will see how we can list all the IAM users within the AWS account. We will be using a paginator to iterate over the response from AWS.


def list_users():
    iam = boto3.client("iam")
    paginator = iam.get_paginator('list_users')
    for response in paginator.paginate():
        for user in response["Users"]:
            print(f"Username: {user['UserName']}, Arn: {user['Arn']}")

The output would look something like this:


Username: test-iam-user, Arn: arn:aws:iam::xxx:user/test-iam-user


How to update a user?

We can also update the username for a particular user using the update_user function.


def update_user(old_user_name, new_user_name):
    iam = boto3.client('iam')
    # Update a user name
    response = iam.update_user(
        UserName=old_user_name,
        NewUserName=new_user_name
    )
    print(response)

The output of would be:

update_user("test-iam-user", "test-iam-user-updated")

{'ResponseMetadata': {'RequestId': '1a1263cd-12d0-4a80-b21c-1d07c9e5f0cc', 'HTTPStatusCode': 200, 'HTTPHeaders': {'x-amzn-requestid': '1a1263cd-12d0-4a80-b21c-1d07c9e5f0cc', 'content-type': 'text/xml', 'content-length': '200', 'date': 'Wed, 12 May 2021 03:23:42 GMT'}, 'RetryAttempts': 0}}


How to create an IAM policy?

Next, we will look into how to create a new IAM policy using the boto3 library. A policy is a document that lists the actions that user can perform and the resources those actions affects.

In this example, we will create an IAM policy that allows access to 2 actions in DynamoDB over all DynamoDB resources.


import json

def create_iam_policy():
    # Create IAM client
    iam = boto3.client('iam')

    # Create a policy
    my_managed_policy = {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": [
                    "dynamodb:GetItem",
                    "dynamodb:Scan",
                ],
                "Resource": "*"
            }
        ]
    }
    response = iam.create_policy(
        PolicyName='testDynamoDBPolicy',
        PolicyDocument=json.dumps(my_managed_policy)
    )
    print(response)

We can test this method as follows:


create_iam_policy()

{'Policy': {'PolicyName': 'testDynamoDBPolicy', 'PolicyId': 'ANPA2V2OH2EKLIGCTLU73', 'Arn': 'arn:aws:iam::xxxx:policy/testDynamoDBPolicy', 'Path': '/', 'DefaultVersionId': 'v1', 'AttachmentCount': 0, 'PermissionsBoundaryUsageCount': 0, 'IsAttachable': True, 'CreateDate': datetime.datetime(2021, 5, 12, 3, 33, 20, tzinfo=tzutc()), 'UpdateDate': datetime.datetime(2021, 5, 12, 3, 33, 20, tzinfo=tzutc())}, 'ResponseMetadata': {'RequestId': 'bb9d38e5-8663-4056-b946-d51bd10f65ff', 'HTTPStatusCode': 200, 'HTTPHeaders': {'x-amzn-requestid': 'bb9d38e5-8663-4056-b946-d51bd10f65ff', 'content-type': 'text/xml', 'content-length': '767', 'date': 'Wed, 12 May 2021 03:33:20 GMT'}, 'RetryAttempts': 0}}


How to list all IAM policies?

Next, we will look at how to list all IAM policies in an AWS account. For this example, we will be filtering all IAM policies that were created by us.


def list_policies():
    iam = boto3.client("iam")
    paginator = iam.get_paginator('list_policies')
    for response in paginator.paginate(Scope="Local"):
        for policy in response["Policies"]:
            print(f"Policy Name: {policy['PolicyName']} ARN: {policy['Arn']}")

The output of this function would be:

Policy Name: testDynamoDBPolicy ARN: arn:aws:iam::xxxx:policy/testDynamoDBPolicy

How to attach a policy to a user?

IAM policies can be attached to users to give them more permissions. We can attach a policy to a particular user by specifying the ARN of the policy.


def attach_user_policy(policy_arn, username):
    iam = boto3.client("iam")
    response = iam.attach_user_policy(
        UserName=username,
        PolicyArn=policy_arn
    )
    print(response)


We can attach the IAM policy we created earlier like this:

attach_user_policy(policy_arn="arn:aws:iam::xxx:policy/testDynamoDBPolicy", username="test-iam-user")

{'ResponseMetadata': {'RequestId': 'd755523a-3871-418d-b858-05fc52480247', 'HTTPStatusCode': 200, 'HTTPHeaders': {'x-amzn-requestid': 'd755523a-3871-418d-b858-05fc52480247', 'content-type': 'text/xml', 'content-length': '212', 'date': 'Wed, 12 May 2021 03:44:06 GMT'}, 'RetryAttempts': 0}}


How to create a Group?

Adding permissions to each individual user can get cumbersome if there are a lot of users to manage. Instad, we can create a Group and then add users to the group. Any IAM policies attached to a group, will be attached to all users in that group as well.


def create_group(group_name):
  iam = boto3.client('iam') # IAM low level client object
  iam.create_group(GroupName=group_name)

How to add a user to a group?

We can add a user to a group using the add_user_to_group method.


def add_user_to_group(username, group_name):
    iam = boto3.client('iam') # IAM low level client object
    response = iam.add_user_to_group(
        UserName=username,
        GroupName=group_name
    )
    print(response)

Output:

add_user_to_group("test-iam-user", "my-test-group")

{'ResponseMetadata': {'RequestId': '972173b6-cd0a-47c4-a5c9-13bfff049f2f', 'HTTPStatusCode': 200, 'HTTPHeaders': {'x-amzn-requestid': '972173b6-cd0a-47c4-a5c9-13bfff049f2f', 'content-type': 'text/xml', 'content-length': '208', 'date': 'Wed, 12 May 2021 03:45:54 GMT'}, 'RetryAttempts': 0}}

How to attach an IAM policy to a group?

Attaching a policy to a group is similar to attaching a policy to a user.


def attach_group_policy(policy_arn, group_name):
    iam = boto3.client("iam")
    response = iam.attach_group_policy(
        GroupName=group_name,
        PolicyArn=policy_arn
    )
    print(response)

Output:


attach_group_policy(policy_arn="arn:aws:iam::xxx:policy/testDynamoDBPolicy", group_name="my-test-group")

{'ResponseMetadata': {'RequestId': 'c840682f-f0be-4074-9891-c4a3d1f646d4', 'HTTPStatusCode': 200, 'HTTPHeaders': {'x-amzn-requestid': 'c840682f-f0be-4074-9891-c4a3d1f646d4', 'content-type': 'text/xml', 'content-length': '214', 'date': 'Wed, 12 May 2021 03:47:21 GMT'}, 'RetryAttempts': 0}}

How to create an IAM role?

We will use the create_role method to create an IAM role. We also need to provide a trust relationship policy as part of the IAM role. This policy grants an entity (like AWS Glue in our example) the permission to assume the role.


def create_iam_role():
    iam = boto3.client("iam")

    assume_role_policy_document = json.dumps({
        "Version": "2012-10-17",
        "Statement": [
            {
            "Effect": "Allow",
            "Principal": {
                "Service": "glue.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
            }
        ]
    })

    response = iam.create_role(
        RoleName = "glueS3CrawlerRole",
        AssumeRolePolicyDocument = assume_role_policy_document
    )

    return response["Role"]["RoleName"]

How to attach an IAM policy to the role?

We will be attaching an IAM policy to the IAM role using the attach_role_policy method.



def attach_iam_policy(policy_arn, role_name):
    iam = boto3.client("iam")

    response = iam.attach_role_policy(
        RoleName=role_name,
        PolicyArn=policy_arn
    )

    print(response)

How to delete an IAM user?

Before we can delete an IAM user, we need to detach any IAM policies attached to the user as well as remove the user from any groups they are in.

We can detach a policy from a user as follows:

def detach_user_policy(username, policy_arn):
    iam = boto3.resource("iam")
    attached_policy = iam.Policy(policy_arn)
    response = attached_policy.detach_user(
        UserName=username
    )
    print(response)



detach_user_policy(username="test-iam-user", policy_arn="arn:aws:iam::xxx:policy/testDynamoDBPolicy")

{'ResponseMetadata': {'RequestId': 'b15a3c08-64e2-4b65-9290-467c8dedc1c4', 'HTTPStatusCode': 200, 'HTTPHeaders': {'x-amzn-requestid': 'b15a3c08-64e2-4b65-9290-467c8dedc1c4', 'content-type': 'text/xml', 'content-length': '212', 'date': 'Wed, 12 May 2021 22:06:56 GMT'}, 'RetryAttempts': 0}}

Next, let’s look at how to remove a user from a group.


def remove_user_group(username, group_name):
    iam = boto3.resource("iam")
    group = iam.Group(group_name)
    response = group.remove_user(
        UserName=username
    )

    print(response)

Output:

remove_user_group(username="test-iam-user", group_name="my-test-group")

{'ResponseMetadata': {'RequestId': '44ff3f9f-1839-439f-8923-cf8339b30352', 'HTTPStatusCode': 200, 'HTTPHeaders': {'x-amzn-requestid': '44ff3f9f-1839-439f-8923-cf8339b30352', 'content-type': 'text/xml', 'content-length': '218', 'date': 'Wed, 12 May 2021 22:09:51 GMT'}, 'RetryAttempts': 0}}

Finally, we will delete the user


def delete_user(username):
    # Create IAM client
    iam = boto3.client('iam')

    # Delete a user
    response = iam.delete_user(
        UserName=username
    )
    print(response)

Output:

delete_user(username="test-iam-user")

{'ResponseMetadata': {'RequestId': 'ce895b88-ad43-47ed-82ac-4fb25acb3616', 'HTTPStatusCode': 200, 'HTTPHeaders': {'x-amzn-requestid': 'ce895b88-ad43-47ed-82ac-4fb25acb3616', 'content-type': 'text/xml', 'content-length': '200', 'date': 'Wed, 12 May 2021 22:10:50 GMT'}, 'RetryAttempts': 0}}