更新CloudFormation模板时IAM用户密码被重置问题求助
解决CloudFormation更新时重置IAM用户密码的问题
问题根源在于模板中直接定义了LoginProfile属性,每次更新CloudFormation栈时,该属性会被重新应用,导致原有用户的密码被强制重置。以下是几种无需使用SSO的解决方案:
方案1:条件参数控制LoginProfile的生效时机
通过添加参数控制是否为用户设置初始登录配置,首次创建时启用,后续更新时禁用,避免密码被重置。
Parameters: InitializeJohnDoePassword: Type: String Default: "true" AllowedValues: ["true", "false"] Resources: JohnDoeUser: Type: AWS::IAM::User Properties: Groups: - !Ref DevelopersGroup ManagedPolicyArns: - arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess # 仅当参数为true时才设置LoginProfile LoginProfile: !If - InitializeJohnDoePassword - Password: "Pa$$wOrd123456!#" PasswordResetRequired: true - !Ref "AWS::NoValue"
- 首次创建栈时,保持
InitializeJohnDoePassword默认值true,完成初始密码配置 - 后续更新栈(如新增用户)时,将该参数改为
false,LoginProfile会被CloudFormation忽略,不会重置原有密码 - 新增用户时,为每个用户添加对应的控制参数和条件判断即可
方案2:嵌套栈独立管理单个用户
将每个IAM用户封装到独立的嵌套栈中,新增用户时只需创建新的嵌套栈,原有用户的栈不进行更新操作,从根本上避免密码重置。
父模板示例
Resources: JohnDoeUserStack: Type: AWS::CloudFormation::Stack Properties: TemplateURL: ./iam-user-template.yaml Parameters: UserName: JohnDoe Group: !Ref DevelopersGroup PolicyArn: arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess InitialPassword: "Pa$$wOrd123456!#" # 新增用户时添加新的嵌套栈资源 JaneDoeUserStack: Type: AWS::CloudFormation::Stack Properties: TemplateURL: ./iam-user-template.yaml Parameters: UserName: JaneDoe Group: !Ref DevelopersGroup PolicyArn: arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess InitialPassword: "Pa$$wOrd123456!#"
子模板(iam-user-template.yaml)示例
Parameters: UserName: Type: String Group: Type: String PolicyArn: Type: String InitialPassword: Type: String NoEcho: true Resources: IAMUser: Type: AWS::IAM::User Properties: UserName: !Ref UserName Groups: - !Ref Group LoginProfile: Password: !Ref InitialPassword PasswordResetRequired: true ManagedPolicyArns: - !Ref PolicyArn
方案3:自定义资源实现仅首次设置密码
通过Lambda自定义资源,在用户首次创建时调用IAM API设置初始密码,后续更新时跳过密码设置逻辑,实现自动化的无干扰更新。
模板示例
Resources: JohnDoeUser: Type: AWS::IAM::User Properties: Groups: - !Ref DevelopersGroup ManagedPolicyArns: - arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess # 自定义资源控制登录配置的创建 JohnDoeLoginProfile: Type: Custom::IAMLoginProfile Properties: ServiceToken: !Ref IAMLoginProfileLambdaArn # 替换为你的Lambda函数ARN UserName: !Ref JohnDoeUser Password: "Pa$$wOrd123456!#" PasswordResetRequired: true
Lambda核心逻辑(Python示例)
import boto3 import cfnresponse iam = boto3.client('iam') def handler(event, context): try: user_name = event['ResourceProperties']['UserName'] password = event['ResourceProperties']['Password'] reset_required = event['ResourceProperties'].get('PasswordResetRequired', True) if event['RequestType'] == 'Create': # 仅创建时设置登录配置 iam.create_login_profile( UserName=user_name, Password=password, PasswordResetRequired=reset_required ) cfnresponse.send(event, context, cfnresponse.SUCCESS, {}) elif event['RequestType'] == 'Update': # 更新时不执行任何操作 cfnresponse.send(event, context, cfnresponse.SUCCESS, {}) elif event['RequestType'] == 'Delete': # 删除时清理登录配置 iam.delete_login_profile(UserName=user_name) cfnresponse.send(event, context, cfnresponse.SUCCESS, {}) except Exception as e: cfnresponse.send(event, context, cfnresponse.FAILED, {'Error': str(e)})
内容的提问来源于stack exchange,提问作者omar
相关产品推荐
相关产品推荐

