Boto3: How to determine if an IAM user has only API key access (no console access)?

Created on 13 Jan 2016  路  6Comments  路  Source: boto/boto3

Here's some psuedocode for what I'd like to do:


for user in iam.users.all():
    if user.password_enabled:
        #Do something

In the credentials report, there's a field for password_enabled. What's the equivalent property of an IAM user object?

If such a thing doesn't exist, I am requesting one.

Thanks!

question

Most helpful comment

Update. This is the code I got working.

https://gist.github.com/jonathanwcrane/68ddff397ec85a8dddae

All 6 comments

To find if a user has a login profile, you perform a GetLoginProfile command, which will 404 if the user doesn't have one. In boto3 this translates into having to catch the resulting exception, like so:

import boto3
from botocore.exceptions import ClientError

iam = boto3.resource('iam')

for user in iam.users.all():
    # Nothing is initially loaded
    profile = user.LoginProfile()
    try:
        profile.load()
        # Do something with the profile
    except ClientError as e:
        if 'NoSuchEntity' not in e.message:
            raise e

Hey there, thanks for this methodology. But it doesn't work as written. I have:

svc_re = re.compile('^svc_')
iam = boto3.resource('iam')

for user in iam.users.all():
    # Nothing is initially loaded
    profile = user.LoginProfile()
    try:
        profile.load()
        # We don't care if this works
    except ClientError as e:
        print(e.__dict__)
        if 'NoSuchEntity' in e.message:
            nm = user.name
            print(nm,"is a service account.")
            if not svc_re.search(nm):
                new_name = 'svc_'+uname
                print(nm,"is a mis-named service account and should be renamed to",new_name)
                #iam_user = iam.User(uname)
                #user.update(NewUserName='svc_'+name)
        else:
            raise e

The message I get is

 if 'NoSuchEntity' in e.message:
AttributeError: 'ClientError' object has no attribute 'message'

When I do a print(e.dict) I get

{'response': {'Error': {'Code': 'NoSuchEntity', 'Message': 'Cannot find Login Profile for User REDACTED', 'Type': 'Sender'}, 'ResponseMetadata': {'HTTPStatusCode': 404, 'RequestId': '70438bb1-bae5-11e5-9a31-4932678efe5c'}}}

But when I try to reference e['response']['Error']['Code'] I get that e is not subscriptable.

How do I actually reference the attribute of a ClientError to get the text I want to compare to 'NoSuchEntity'?

Update. This is the code I got working.

https://gist.github.com/jonathanwcrane/68ddff397ec85a8dddae

Glad you got it working!

Man this is one of those things that really annoys me about boto3/AWS API. Why not have this in the API or boto3? This is the kind of helper code that hundreds of people have to build for themselves.

If your users (or AWS account) are created after October 20th, 2014 then the code below should do the trick.
See the docs for more info: http://boto3.readthedocs.io/en/latest/reference/services/iam.html#IAM.User.password_last_used

It makes the code far less verbose ;-)

for iam_user in iam.users.all():      
    if iam_user.password_last_used:
        print('User has console access')
    else:
        print('User has only programmatic access')
Was this page helpful?
0 / 5 - 0 ratings

Related issues

chesstrian picture chesstrian  路  3Comments

danielmorozoff picture danielmorozoff  路  3Comments

amattie picture amattie  路  4Comments

arnonki picture arnonki  路  3Comments

leima965 picture leima965  路  3Comments