Home > Software design >  List RoleNames based on Action in AssumeRolePolicyDocument using boto3
List RoleNames based on Action in AssumeRolePolicyDocument using boto3

Time:04-27

I am using below python code to list all the IAM Role Names.

from boto3 import Session
import logging
from botocore.exceptions import ClientError


logger = logging.getLogger(__name__)


def list_iam_roles(profile):
    boto_sess = Session(profile_name=profile)
    client = boto_sess.client('iam')

    roles = client.list_roles()
    for role in roles["Roles"]:
        print (role["RoleName"])
    return 

list_iam_roles('some_profile')

It successfully returns the list of the all the IAM Role Names, but my requirement is to filter based on specific AssumeRolePolicyDocument.

I want to filter Role Names which has Action: sts:AssumeRoleWithSAML.

Any hints how can I filter it?

The sample output of each role is pasted below. Ciphering some important information already with xxx.

{'Path': '/', 'RoleName': 'some_role_name', 'RoleId': 'some_id', 'Arn': 'arn:aws:iam::xxxxx:role/some_role_name', 'CreateDate': datetime.datetime(2021, 2, 14, 12, 49, 26, tzinfo=tzutc()), 'AssumeRolePolicyDocument': {'Version': '2012-10-17', 'Statement': [{'Sid': '', 'Effect': 'Allow', 'Principal': {'Federated': 'arn:aws:iam::xxxxx:saml-provider/provider_name'}, 'Action': 'sts:AssumeRoleWithSAML', 'Condition': {'StringEquals': {'SAML:aud': 'https://signin.aws.amazon.com/saml'}}}]}, 'MaxSessionDuration': 36000}

CodePudding user response:

There is another slightly more explicit check. Just checking a string is probably sufficient.

roles = [
    {
        "Path": "/",
        "RoleName": "some_role_name",
        "RoleId": "some_id",
        "Arn": "arn:aws:iam::xxxxx:role/some_role_name",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Sid": "",
                    "Effect": "Allow",
                    "Principal": {
                        "Federated": "arn:aws:iam::xxxxx:saml-provider/provider_name"
                    },
                    "Action": "sts:AssumeRoleWithSAML",
                    "Condition": {
                        "StringEquals": {
                            "SAML:aud": "https://signin.aws.amazon.com/saml"
                        }
                    },
                }
            ],
        },
        "MaxSessionDuration": 36000,
    },
    {
        "Path": "/",
        "RoleName": "some_other_role_name",
        "RoleId": "some_other_id",
        "Arn": "arn:aws:iam::xxxxx:role/some_other_role_name",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Sid": "",
                    "Effect": "Allow",
                    "Principal": {
                        "Federated": "arn:aws:iam::xxxxx:saml-provider/provider_name"
                    },
                    "Action": "not:theActionYoureLookingFor",
                }
            ],
        },
        "MaxSessionDuration": 36000,
    },
]

filtered = set()

for r in roles:
    for s in r.get("AssumeRolePolicyDocument", {}).get("Statement", []):
        actions = s.get("Action", [])
        for a in actions if isinstance(actions, list) else [actions]:
            if "sts:AssumeRoleWithSAML" in a:
                filtered.add(r.get("RoleName"))

print(filtered)

output:

{'some_role_name'}

In the context of your function, that would be:

def list_iam_roles(profile):
    filtered = set()
    for r in Session(profile_name=profile).client("iam").list_roles().get("Roles", []):
        for s in r.get("AssumeRolePolicyDocument", {}).get("Statement", []):
            actions = s.get("Action", [])
            for a in actions if isinstance(actions, list) else [actions]:
                if "sts:AssumeRoleWithSAML" in a:
                    filtered.add(r.get("RoleName"))
    return list(filtered)

There is surely a really nasty comprehension that could do this, but this should be pretty clear, and deals with the policy values that can be string or list.

CodePudding user response:

One way would be simply to convert your role to string and do string search:


def list_iam_roles(profile):
    boto_sess = Session(profile_name=profile)
    client = boto_sess.client('iam')

    roles = client.list_roles()
    for role in roles["Roles"]:
        if "sts:AssumeRoleWithSAML".lower() in str(role).lower(): 
            print (role["RoleName"])
    return 
  • Related