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!
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.
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')
Most helpful comment
Update. This is the code I got working.
https://gist.github.com/jonathanwcrane/68ddff397ec85a8dddae