AWS Cognito 90天自动密码轮换

时间:2020-01-10 17:11:43

标签: python-3.x boto3 amazon-cognito

我需要创建一个自动密码重置脚本。我创建了一个自定义字段,以尝试对此进行跟踪,也希望我可以访问一些标准字段。该脚本应找到符合以下条件的用户:

以下是== 90天之前的以下3个日期中的任何一个的最新日期:Sign_Up,Forgot_Password或custom:pwdCreateDate

除了在admin_list_user_auth_events中显示的忘记密码并且该响应在响应中不包含用户名之外,我似乎找不到任何关于boto3 cognito客户端的信息获取方式。我想,既然您提供了用于获取事件的用户名,便可以找到一种从事件中查找最新的忘记密码并将其与用户名绑定的方法。

其他人是否实现了任何boto3自动化功能来根据这些字段中的任何一个来设置帐户以强制重置密码?

1 个答案:

答案 0 :(得分:2)

这是我登陆的地方,但要了解coginito有一些限制,这些限制使真正无瑕的密码轮换变得困难。还应该知道是否可以使脚本更高效,因为在lambda中,由于admin API上的5RPS,您可能会超过350个用户。

先决条件:将lambda函数设置为5并发,否则您将超过5RPS的限制。您的cognito用户池属性中有1个可变字段,用于输入日期。自定义lambda zip文件包含保存到s3的熊猫。

import os
import sys

# this adds the parent directory of bin so we can find the  module
parent_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir))
sys.path.append(parent_dir)
#This addes venv lib/python2.7/site-packages/ to the search path
mod_path = os.path.abspath(parent_dir+"/lib/python"+str(sys.version_info[0])+"."+str(sys.version_info[1])+"/site-packages/")
sys.path.append(mod_path)

import boto3
import datetime
import pandas as pd
import time

current_path = os.path.dirname(os.path.realpath(__file__))
# Use this one for the parent directory
ENV_ROOT =  os.path.abspath(os.path.join(current_path, os.path.pardir))
# Use this one for the current directory
#ENV_ROOT =  os.path.abspath(os.path.join(current_path))
sys.path.append(ENV_ROOT)

#if __name__ == "__main__":
def lambda_handler(event, context):
    user_pool_id = os.environ['USER_POOL_ID']
    idp_client = boto3.client('cognito-idp')
    users_list = []
    page_token = None    
    dateToday = datetime.datetime.today().date()

    def update_user(user) :
        idp_client.admin_update_user_attributes(
            UserPoolId = user_pool_id,
            Username = user,
            UserStatus = 'RESET_REQUIRED',
            UserAttributes = [
                    {
                        'Name': 'custom:pwdCreateDate',
                        'Value': str(dateToday)
                    }            
                ]
            )   


    users = idp_client.list_users(
        UserPoolId = user_pool_id
        )
    for user in users['Users']: users_list.append(user['Username'])
    page_token = users['PaginationToken']

    while 'PaginationToken' in users :
        users = idp_client.list_users(
            UserPoolId = user_pool_id,
            PaginationToken = page_token
            )
        for user in users["Users"]: users_list.append(user["Username"])

        if 'PaginationToken' in users :
            page_token = users['PaginationToken']

    attrPwdDates = []
    for i in range(len(users_list)) :
        userAttributes = idp_client.admin_get_user(
                UserPoolId = user_pool_id,
                Username = users_list[i]
                )
        for a in userAttributes['UserAttributes'] :
            if a['Name'] == 'custom:pwdCreateDate' :
                attrPwdDates.append(datetime.datetime.strptime(a['Value'], '%Y-%m-%d %H:%M:%S.%f').date())
        time.sleep(1.0)

    list_of_userattr_tuples = list(zip(users_list, attrPwdDates))                            
    df1 = pd.DataFrame(list_of_userattr_tuples,columns = ['Username','Password_Last_Set'])

    authPwdDates = []
    for i in range(len(users_list)) :
        authEvents = idp_client.admin_list_user_auth_events(
        UserPoolId = user_pool_id,
        Username = users_list[i]
        )

        for event in authEvents['AuthEvents'] :
            if event['EventType'] == 'ForgotPassword' and event['EventResponse'] == 'Pass' :
                authPwdDates.append(event['CreationDate'].date())
                break
        time.sleep(1.0)

    list_of_userauth_tuples = list(zip(users_list, authPwdDates))        
    df2 = pd.DataFrame(list_of_userauth_tuples,columns = ['Username','Password_Last_Forgot'])

    df3 = df1.merge(df2,how='left', on = 'Username')

    df3[['Password_Last_Set','Password_Last_Forgot']] = df3[['Password_Last_Set','Password_Last_Forgot']].apply(pd.to_datetime)

    cols = ['Password_Last_Set','Password_Last_Forgot']
    df4 = df3.loc[df3[cols].max(axis=1)<=pd.Timestamp.now() - pd.Timedelta(90, unit='d'), 'Username']

    for i,r in df4.iterrows() :
        update_user(r['Username'])