Using boto3, how to check if AWS IAM user has password? - python

Among the users in IAM, I want to programmatically get the list of all password enabled users. From AWS Console, I can easily spot them. But, how to get their list programmatically? I want to use python boto to get that.
I was reading up here http://boto3.readthedocs.io/en/latest/reference/services/iam.html#iam, but by most of the ways listed in this doc, I can only see option of using 'PasswordLastUsed' which would be null in three cases
The user does not have a password
The password exists but has never been used
there is no sign-in data associated with the user.
So just by checking if 'PasswordLastUsed' is null I can not claim that user does not have password and thereby, can not get all the users with password. Am I missing something here? Any other way or any other python resource I can use to do this?

import boto3
iam = boto3.resource('iam')
def isPasswordEnabled(user):
login_profile = iam.LoginProfile(user)
try:
login_profile.create_date
print True
except:
print False
>>> isPasswordEnabled('user1')
True
>>> isPasswordEnabled('user2')
False

I can see that there is a way, just where you would expect it to be...
http://boto3.readthedocs.io/en/latest/reference/services/iam.html#IAM.Client.get_credential_report
In the report, field password_enabled set to false indicates no password.

You could use the GetLoginProfile API request to determine if an IAM user has a login profile or not. If there is no login profile associated with the user this request will return a 404 response. Some code like this should work:
import boto3
iam = boto3.client('iam')
user_name = 'bob'
try:
response = iam.get_login_profile(UserName=user_name)
except Exception, e:
if e.response['ResponseMetadata']['HTTPStatusCode'] == 404:
print('User {} has no login profile'.format(user_name))

Related

How to import firebase accounts with the same password?

I'm using Firebase authentication to manage my users accounts.
Now, I need to change the uid of the users, then I'm trying to delete the user and import it again with the same password using python.
I'm trying to follow the documentation. But I might be missing something.
So, in the Firebase authentication page, I'm going to menu (in the right upper corner) and getting the base64_signer_key and base64_salt_separator values.
And trying to use the code below to delete the user, import the user and update the other fields:
for user in auth.list_users().iterate_all():
if user.email == 'myname#yahoo.com':
newId = CPF(cpf()).rawValue
oldId = user.uid
print('User: {}'.format(user._data))
# Delete the user
auth.delete_user(oldId)
# Recreate the user
users = [
auth.ImportUserRecord(
uid=newId,
email=user.email,
password_hash=user.password_hash.encode('utf-8'),
password_salt=None
),
]
hash_alg = auth.UserImportHash.scrypt(
key=base64.b64decode(base64_signer_key),
salt_separator=base64.b64decode(base64_salt_separator),
rounds=8,
memory_cost=14
)
try:
result = auth.import_users(users, hash_alg=hash_alg)
print('Successfully imported {0} users. Failed to import {1} users.'.format(
result.success_count, result.failure_count))
for err in result.errors:
print('Failed to import {0} due to {1}'.format(users[err.index].uid, err.reason))
except Exception as e:
print(e)
# Update user
auth.update_user(
newId,
phone_number=user.phone_number,
email_verified=user.email_verified,
display_name=user.display_name,
disabled=user.disabled
)
I'm following this documentation https://firebase.google.com/docs/auth/admin/import-users#import_users_with_firebase_scrypt_hashed_passwords
I'm able to delete and recreate the user, but when I try to login with the same user/password I'm getting FirebaseInvalidPasswordError.
What should I do recreate the user with same password and be able to authenticate in the standard way ?
After many tests, maybe I've managed to find a working way to solve the problem.
First of all, if you have created a new service account private key, go to GCP console here https://console.cloud.google.com/iam-admin/iam?authuser=0&project=[your_firebase-proect-id] and make sure your service account have the "Firebase Authentication" admin rights
(note the service account)
(check permission)
This was my first problem since without that permission, the firebase admin SDK always returns an empty password_salt and the string "UkVEQUNURUQ=" for the password_hash (which translates to "REDACTED").
Once I got the correct password hash and salt for user, your code should looks like this
# Recreate the user
users = [
auth.ImportUserRecord(
uid=newId,
email=user.email,
password_hash=base64.urlsafe_b64decode(user.password_hash),
password_salt=base64.urlsafe_b64decode(user.password_salt)
),
]
Note the base64.urlsafe_b64decode part? I've tried to manually export my probject users with the firebase cli though
firebase auth:export --project [project-id] users.csv
and noticed a big difference: Python password hash was
utfZLdz4phgAnRIKRUOxxFTKmbUEenbV1CbkQC0o4iorXpx-BJsdwofjAQkb1mUAgs_sO49cBv_lT8QuCztRzA== while CSV password hash was utfZLdz4phgAnRIKRUOxxFTKmbUEenbV1CbkQC0o4iorXpx+BJsdwofjAQkb1mUAgs/sO49cBv/lT8QuCztRzA== (in python slashes are undercores)
Don't know if my approach would cover all cases, but exporting auth from the cli and comparing their hashes with the python ones could lead you to solve further cases.

How to do google Sign In with the help of idToken in Django

This is the code I use to retrieve idToken in my flutter app
Future<void> _handleSignIn() async {
try {
final result = await _googleSignIn.signIn();
final ggAuth = await result!.authentication;
print(ggAuth.idToken); // this is the one that I use as token value
print(ggAuth.accessToken);
} catch (error) {
print(error);
}
}
And this is the code I use to access user info in my backend.
from google.oauth2 import id_token
from google.auth.transport import requests
try:
idinfo = id_token.verify_oauth2_token(token, requests.Request(), CLIENT_ID)
userid = idinfo['sub']
print(userid)
except ValueError:
print('Invalid token)
But after replacing the token variable with the token received from flutter app and replacing the CLIENT_ID with the id generated for my app (available in the console) , it still throws the error of invalid token. What am I doing wrong?
EDIT- When I use https://jwt.io/ to decode the token it works as expected and I get all the details.
Authentication Think of the id token as your birth certificate. It just identifies you as a person.
Authorization Think of the access token as your drivers license its what contains the permissions that you have to drive a car.
An Id token does not out write give you permission to access any data on google servers. With an access token you have been authorized to access some data in this case some profile information.
The issue you are having is that you are using sign-in in. Sign in is Open id connect think of it as a birth certificate (Id token). There is a user their who is signing in to your app. They are in fount of their computer. By default with Google signin gives you get basic profile information. What you are doing with Jwt.io is checking the claims that are returned in the Id token. Id tokens are just the token that allows your application to identify that the user is logged in. There should also be a sub claim there you should use this id to map the user to your integral user system. There may be a user name and email address in the claims but you can not guarantee that they will be there every time google has stated they do not always return these claims.
To get user profile information after the user has logged in you should be using the people api the people.get method when passed the access token will return to you the profile information of the currently authenticated user.
beyond that you should IMO not be passing tokens to your backend if you want the token in the backend you should log the user in using your backend language.
Okay so the idToken that I had was correct but flutter terminal was not able to print its full length and because of which I was copying only half the token and was getting a signature error when checking manually.

List all users from Firebase Authentication

I am currently using the Pyrebase wrapper to get information (such as their email and created date) of all users. I tried looking through the documentation and cross reference it to Pyrebase documentation however i don't seem to get what i'm looking for. Currently i have tried this:
import pyrebase
config={all required information, including path to service account .json file}
firebase=pyrebase.initialize_app(config)
db=firebase.database()
auth=firebase.auth()
extract_user = db.child('users').child('userId').get()
for x in extract_user.each():
print(x.val())
auth.get_account_info(user[x.val()])
However i still failed, i know im missing something but im not sure what.
Note: I saved the users userID in the database under userId. So i looped through each and every ID to be used in the 'get_account_info'
Any suggestions or ways i can get this to be done?
from firebase_admin import credentials
from firebase_admin import auth
cred = credentials.Certificate("./key.json")
initialize_app(cred, {'databaseURL' : "your database..."})
page = auth.list_users()
while page:
for user in page.users:
print("user: ", user.uid)
page = page.get_next_page()
Then, after you get user id that looks like "F5aQ0kAe41eV2beoasfhaksfjh2323alskjal" you can see the actual email by:
user = auth.get_user("F5aQ0kAe41eV2beoasfhaksfjh2323alskjal")
print("user email: ", user.email)
The db.child('users').child('userId').get() in your code reads users from the Realtime Database, where they'll only exist if your application added the there explicitly. Adding a user to Firebase Authentication does not automatically also add it to the Realtime Database.
While Pyrebase allows you to initialize it with a service account, it doesn't replicate all administrative functionality of the Firebase Admin SDKs. As far as I can see in Pyrebase's code, Pyrebase's does not implement a way to list users.
Consider using the Firebase Admin SDK, which has a built-in API to list users.

Authenticate with Flask-LDAP3-Login based on group membership

I'm new to Flask and I'm trying out Flask-LDAP3-Login.
I've followed the documentation here and i have it working which is great: https://flask-ldap3-login.readthedocs.io/en/latest/index.html
How would i go about authenticating a user based on whether they are a member of a specific group? I see the docs mention group filtering but i'm not sure how to put it all together.
If anyone is curious, i solved this myself doing the following:
First, i integrated flask-ldap3-login with Flask-SQLAlchemy using steps here - https://github.com/nickw444/flask-ldap3-login/issues/26
My save user method now looks like this:
#ldap_manager.save_user
def save_user(dn, username, data, memberships):
id=int(data.get("uidNumber"))
if 'group-goes-here' in data.get("memberOf"):
user=User.query.filter_by(id=id).first()
if not user:
user=User(
id=int(id),
dn=dn,
username=username,
email=data['mail'],
firstname=data['givenName'],
lastname=data['sn']
)
db.session.add(user)
db.session.commit()
return user
So basically provided the user enters valid LDAP credentials it goes to AD to retrieve their group memberships and its a simple if 'group-goes-here' in data.get("memberOf"): determines whether to save the user in my User model and return it back to the handler.
#auth.route('/login', methods=['GET', 'POST'])
def login():
# Redirect users who are not logged in.
form = LDAPLoginForm()
if form.validate_on_submit():
if form.user:
login_user(form.user)
else:
flash('Login Failed', 'warning')
return redirect(url_for('auth.login'))
return redirect(url_for('main.home'))
Hope this helps!
The LDAP_USER_OBJECT_FILTER can be used to check group membership. If a user is not found within the group, an authentication fail will be produced. This is taken from the flask-ldap3-login docs:
Specifies what object filter to apply when searching for users. Defaults to '(objectclass=person)'
Matching direct members of a group:
app.config['LDAP_USER_OBJECT_FILTER'] = '(objectclass=person)(memberOf=<DN of Group>)'
For nested group membership you can use LDAP_MATCHING_RULE_IN_CHAIN:
app.config['LDAP_USER_OBJECT_FILTER'] = '(objectclass=person)(memberOf:1.2.840.113556.1.4.1941:=<DN of Group>)'
The Microsoft Search Filter Syntax docs state:
This is a special "extended" match operator that walks the chain of ancestry in objects all the way to the root until it finds a match.
Do you have a ldap server ? if not go to https://www.openldap.org/ and follow instructions on how to install openldap server
if you prefer a docker container then go here
https://github.com/osixia/docker-openldap and follow steps to get the container up and running
then go here https://ldap3.readthedocs.io/tutorial.html
pip install ldap3 on the machine which has your python env or another python container (same bridge network as your ldap container)
open python console and type the following commands
>>> from ldap3 import Server, Connection, ALL
>>> server = Server('ipa.demo1.freeipa.org')
>>> conn = Connection(server)
>>> conn.bind()
True
first with this free ldap server ipa.demo1.freeipa.org
and then with your own ldap server ip address

How can I find how many days has an AWS IAM user been inactive/idle for with boto3?

I would like to enforce a user lockout if that user has not logged in with username and password in aws account.
How can I poll for user activity, when he/she was last active on his/her account?
The following code prints the time the password was last used.
import boto3
iam = boto3.resource('iam')
user = iam.User('john')
print user.password_last_used
2018-05-02 16:47:28+00:00
If you have to check the last use of their access keys and not just their password, you can do the following:
import boto3
iam = boto3.resource('iam')
user = iam.User('john')
# use the account creation date if the user has never logged in.
latest = user.password_last_used or user.create_date
for k in user.access_keys.all():
key_used = iam_client.get_access_key_last_used(AccessKeyId=k.id)
key_date = key_used['AccessKeyLastUsed']['LastUsedDate']
if key_date > latest:
latest = key_date
print latest
However, it may be easier just to use aws console.

Categories

Resources