首页 > 解决方案 > AWS Cognito 90 天自动密码轮换

问题描述

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

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

除了出现在 admin_list_user_auth_events 中的忘记密码并且该响应不包括响应中的用户名之外,我似乎找不到任何 boto3 cognito 客户端获取有关此信息的方法。我想既然你提供了用户名来获取事件,你可以想办法从事件中找到最新的忘记密码并将其与用户名联系起来。

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

标签: python-3.xboto3amazon-cognito

解决方案


这是我登陆的地方,请理解 coginito 有一些限制,这使得真正完美的密码轮换变得困难。还知道您是否可以使脚本更高效,因为在 lambda 中,由于管理 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'])

推荐阅读