Home > Enterprise >  Last marker for boto3 pagination is not working
Last marker for boto3 pagination is not working

Time:11-12

I'm working with roles and policies using AWS boto3 SDK. I want to get the policies attached to a given role and then do some processing. Here's the code.

def get_policies(role_name):
    marker = None
    while True:
        print ('marker in get_policies is {} '.format(marker))
        if marker:
            response_iterator = iam.list_attached_role_policies(
                RoleName=role_name,
                # PathPrefix='string',
                Marker=marker,
                MaxItems=1
            )
        else:
            response_iterator = iam.list_attached_role_policies(
                RoleName=role_name,
                # PathPrefix='string',
                MaxItems=1
            )
        print("Next Page in get_policy : {} ".format(response_iterator['IsTruncated']))
        print(response_iterator['AttachedPolicies'])
        for policy in response_iterator['AttachedPolicies']:
            detach_policy_from_entities(policy['PolicyArn'])
            print(policy['PolicyName']   " has to be deleted")
            # delete_policy_response = iam.delete_policy(
            #     PolicyArn=policy['PolicyArn']
            # )
            print('deleted {}'.format(policy['PolicyName']))
        if response_iterator['IsTruncated']:
            marker = response_iterator['Marker']
        else:
            print("done with policy deletion")
            return "finished"

The code works fine except it returns an empty list with the last marker. So, I have 3 policies attached to the given role. The code works as follows:

  1. initially marker is None, it just run the else part and returns 1 result with marker for next iteration
  2. I use the marker to get another set of result. It works and returns 1 result with marker for the next iteration
  3. Here I use the marker but it returns and empty list for the policy but I have one more policy

Any help will be greatly appreciated.

CodePudding user response:

Your code works fine with your pagination logic, but I do not think you will need pagination as by default if you do not use MaxItems the list_attached_role_policies function is to return 100 values.

Also, as the Default quotas for IAM entities defines that you can have as default 10 Managed policies attached to an IAM role, if you don't request an increment (More information IAM object quotas can be found here).

So, for you logic works you need something like this:

import boto3

iam = boto3.client("iam")
role = "role_name"
policies = iam.list_attached_role_policies(RoleName=role)
policies_list = policies['AttachedPolicies']
for policy in policies_list:
    print(policy['PolicyName'])
    # you can add your detach logic here

Also the list_attached_role_policies method does not return inline policies, if the policies that are not being showed to you are inline policies you will need the list_role_policies method.

import boto3

iam = boto3.client("iam")
role = "role_name"
policies = iam.list_role_policies(RoleName=role)
policies_list = policies['PolicyNames']
for policy in policies_list:
    print(policy)
    # you can add your detach logic here

CodePudding user response:

It looks like you are mutating the attached role policies and hence invalidating the pagination marker. Also, unless you specifically need it, I would remove MaxItems=1.

One solution is to change the code to simply append the policy ARNs to a list and then process that list for detachment after your for policy in ... loop.

As an FYI, you should consider using the resource-level IAM.Role as it simplifies access to the associated policies (they are available via simple policies and attached_policies collections on the role). For example:

import boto3

iam = boto3.resource("iam")
role = iam.Role("role-name-here")

for p in role.attached_policies.all():
    print(p)
  • Related