【问题标题】:Cannot set a property of cognito userpool client via cloudformation无法通过 cloudformation 设置 cognito userpool 客户端的属性
【发布时间】:2024-04-19 15:20:01
【问题描述】:

我正在尝试通过 cloudformation 运行 congnito,一切正常,但 cognito 中有如下部分:

如您所见,有“启用身份提供者”部分 而且我找不到可以在 cloudformation 中将其设置到我的 cognito 用户池的位置!

我试过这个属性,但它说不支持。

SupportedIdentityProviders

这是我的用户池客户端代码:

  UserPoolClient:
Type: "AWS::Cognito::UserPoolClient"
Properties:
  ClientName: !Sub ${project}-client
  ExplicitAuthFlows:
   - ADMIN_NO_SRP_AUTH
   - USER_PASSWORD_AUTH
  GenerateSecret: false
  UserPoolId: !Ref UserPool
  RefreshTokenValidity: 30

这是我的用户池:

  UserPool:
Type: "AWS::Cognito::UserPool"
Properties:
  UserPoolName: !Sub ${project}-user-pool-test
  AutoVerifiedAttributes:
    - email
  UsernameAttributes:
    - email
  MfaConfiguration: "OFF"
  LambdaConfig:
    CustomMessage:
      Fn::ImportValue: !Sub ${project}-${EnvironmentApp}-lambda-cognito-custom-message-post
  Policies:
    PasswordPolicy:
      MinimumLength: !Ref MinimumLength
      RequireLowercase: !Ref RequireLowercase
      RequireNumbers: !Ref RequireNumbers
      RequireSymbols: !Ref RequireSymbols
      RequireUppercase: !Ref RequireUppercase
  Schema:
    -
        AttributeDataType: String
        DeveloperOnlyAttribute: false
        Mutable: true
        Name: !Sub ${project}-stg
        Required: false
    -
        AttributeDataType: String
        DeveloperOnlyAttribute: false
        Mutable: true
        Name: !Sub zuora-stg
        Required: false
    -
        AttributeDataType: String
        DeveloperOnlyAttribute: false
        Mutable: true
        Name: !Sub salesforce-stg
        Required: false

云的形成是否支持?感谢您的帮助?

【问题讨论】:

    标签: amazon-web-services amazon-cloudformation amazon-cognito aws-opsworks


    【解决方案1】:

    正如其他答案所暗示的,目前尚无法在 CloudFormation 本机中完成此操作。但是,正如 ASR 回答所建议的那样,可以通过 CloudFormation 自定义资源来做到这一点。

    我的雇主已将其自定义资源集合开源,包括 CognitoUserPoolCognitoDomainName (CloudFormation 也不支持)。自定义资源源码 can be found on github

    以下是有关设置的手动说明 - 您始终可以通过在 CloudFormation 中放置自定义资源支持 Lambda 来进一步自动化操作。

    以下所有命令均适用于 Mac。您可能需要修改其他 base64 标志 平台

    1。为 Lambda 创建 IAM 角色

    aws iam create-role --role-name LambdaRoleCognito --assume-role-policy-document '{
          "Version": "2012-10-17",
          "Statement": [
          {
              "Effect": "Allow",
              "Principal": {
                  "Service": "lambda.amazonaws.com"
              },
              "Action": "sts:AssumeRole"
          }
      ]
      }'
    aws iam attach-role-policy --role-name LambdaRoleCognito \
      --policy-arn  arn:aws:iam::aws:policy/CloudWatchLogsFullAccess
    
    aws iam attach-role-policy --role-name LambdaRoleCognito \
      --policy-arn  arn:aws:iam::aws:policy/AmazonCognitoPowerUser
    

    2。下载lambda源码,上传到本地bucket,创建lambda

    wget https://github.com/base2Services/cloudformation-custom-resources-nodejs/releases/download/1.0.0/ccr-nodejs-1.0.0.zip
    account_id=$(aws sts get-caller-identity --query Account --output text)
    aws s3 mb s3://${account_id}.cfncustomres.source
    aws s3 cp ccr-nodejs-1.0.0.zip s3://${account_id}.cfncustomres.source/ccr-nodejs-1.0.0.zip
    
    aws lambda create-function --function-name CfnCrCognitUPC --runtime nodejs6.10 \
        --role arn:aws:iam::${account_id}:role/LambdaRoleCognito  \
        --timeout 30 \
        --memory-size 512 \
        --code S3Bucket=${account_id}.cfncustomres.source,S3Key=ccr-nodejs-1.0.0.zip \
        --handler cognito-user-pool-client/index.handler
    

    3。 可选通过调用测试负载来测试 lambda

    aws lambda invoke --function-name CfnCrCognitUPC --payload '{
      "StackId": "arn:aws:cloudformation:us-west-2:EXAMPLE/stack-name/guid",
      "ResponseURL": "http://pre-signed-S3-url-for-response",
      "ResourceProperties": {
        "ClientName": "MyCCRCreatedUP",
        "SupportedIdentityProviders": [
          "COGNITO"
        ],
        "UserPoolId":"!! REPLACE WITH YOUR USER POOL ID !!"
      },
      "RequestType": "Create",
      "ResourceType": "Custom::TestResource",
      "RequestId": "unique id for this create request",
      "LogicalResourceId": "MyTestResource"
    }' --log-type Tail --invocation-type RequestResponse output.txt --query LogResult --output text | base64 -D
    

    4。在 CloudFormation 模板中创建自定义资源

    查看所有支持的属性列表custom resource JSON schema

    Resources:
      MyPoolApplication:
        Type: Custom::CognitoUserPool
        Properties:
          ServiceToken: arn:aws:lambda:<<REPLACE_WITH_YOUR_REGION>>:<<REPLACE_WITH_YOUR_ACCOUNT_ID>>:function:CfnCrCognitUPC
          ClientName: ApplicationClientNameHere
          UserPoolId: 
            Ref: UserPool
          SupportedIdentityProviders:
            - COGNITO
          .... other support properties .... 
    

    【讨论】:

    【解决方案2】:

    正如其他答案所述,现在有一种使用 CloudFormation 设置 UserPoolClient 的方法,但是我来到这个问题是为了寻找具体的例子,因为我在处理一些参数时遇到了困难。我想把它放在这里,以防万一有人也在寻找一个例子。

    在我的示例中,我还包含了与 google 的联合登录,以使其更加完整。如果您不想使用 google 登录,只需将其从 SupportedIdentityProviders 中删除即可。

    下面的模板:

    AWSTemplateFormatVersion: 2010-09-09
    Parameters: 
      envParameter: 
        Type: String
        Default: dev
        AllowedValues: [ dev, staging, prod ]
        Description: Suffix to be added for names.
    Resources:
      myUserPool:
        DependsOn: [ cognitoSMSRole ]
        Type: AWS::Cognito::UserPool
        Properties:
          AccountRecoverySetting:
            RecoveryMechanisms: 
              - Name: verified_email
                Priority: 1
              - Name: verified_phone_number
                Priority: 2
          AdminCreateUserConfig: 
              AllowAdminCreateUserOnly: False
          AutoVerifiedAttributes: 
            - phone_number
          EnabledMfas: 
            - SMS_MFA
          MfaConfiguration: OPTIONAL
          Policies: 
            PasswordPolicy: 
              MinimumLength: 8
              RequireLowercase: True
              RequireNumbers: True
              RequireSymbols: True
              RequireUppercase: True
              TemporaryPasswordValidityDays: 7
          Schema: 
            - AttributeDataType: String
              DeveloperOnlyAttribute: False
              Mutable: False
              Name: name
              Required: True
            - AttributeDataType: String
              DeveloperOnlyAttribute: False
              Mutable: False
              Name: last_name
              Required: False
          SmsConfiguration:
              ExternalId: !Sub cognito-sms-role-${envParameter}
              SnsCallerArn: !GetAtt cognitoSMSRole.Arn
          UsernameAttributes: 
            - phone_number
          UsernameConfiguration: 
            CaseSensitive: False
          UserPoolName: !Sub UserPool-${envParameter}
    
      cognitoSMSRole:
        Type: "AWS::IAM::Role"
        Properties:
          AssumeRolePolicyDocument: 
            Version: "2012-10-17"
            Statement:
              - Effect: "Allow"
                Principal: 
                  Service: 
                    - "cognito-idp.amazonaws.com"
                Action: 
                  - "sts:AssumeRole"
          Policies:
            - PolicyName: "CognitoSNSPolicy"
              PolicyDocument: 
                Version: "2012-10-17"
                Statement: 
                  - Effect: "Allow"
                    Action: "sns:publish"
                    Resource: "*"
    
      cognitoClient:
        DependsOn: [ myUserPool, googleProvider ]
        Type: AWS::Cognito::UserPoolClient
        Properties: 
          AllowedOAuthFlows: 
            - code
            - implicit
          AllowedOAuthFlowsUserPoolClient: True
          AllowedOAuthScopes: 
            - email
            - openid
            - profile
          CallbackURLs: 
            - http://google.co.uk
          ClientName: !Sub cognito-appid-${envParameter}
          GenerateSecret: False
          LogoutURLs: 
            - http://google.co.uk
          PreventUserExistenceErrors: ENABLED 
          RefreshTokenValidity: 1
          SupportedIdentityProviders: 
            - COGNITO
            - Google
          UserPoolId: !Ref myUserPool
      googleProvider:
        DependsOn: [ myUserPool ]
        Type: AWS::Cognito::UserPoolIdentityProvider
        Properties: 
          AttributeMapping:
            name: emailAddress
            sub: Username
          ProviderDetails: 
            client_id: client_id.apps.googleusercontent.com
            client_secret: this_is_the_client_secret
            authorize_scopes: email openid profile
          ProviderName: Google
          ProviderType: Google
          UserPoolId: !Ref myUserPool
    
    
    Outputs:
     userPool:
        Description: "User pool ID"
        Value: !Ref myUserPool
     identityPool:
        Description: "Identity pool ID"
        Value: !Ref cognitoClient
    
    

    【讨论】:

    • 这行得通!谢谢你。如果有人感兴趣,同样的语法也适用于 Serverless.com YML。我需要 AllowedOAuthFlows 和 SupportedIdentityProviders,它们工作得很好。
    【解决方案3】:

    我上个月遇到了同样的问题。 CFN 尚不支持此属性。所以我最终使用 CFN 自定义资源来创建池客户端。更多关于CFN Custom Resource的信息。本质上,我让 CFN 调用 Lambda 函数来创建用户池客户端(SDK 支持所有属性)。

    【讨论】:

    • 感谢您的回答
    【解决方案4】:

    正如 ASR 所说,Cloudformation 似乎还不支持这一点。

    我们最终尝试了 Terraform - 它确实支持它,例如

    resource "aws_cognito_user_pool_client" "my_client" {
      ...
      supported_identity_providers = ["COGNITO"]
    }
    

    我们现在已将所有内容切换为使用 terraform,因为它比 Cloudformation 更易于理解、阅读和编写。

    我知道这可能不是您想要的答案,但我希望它有所帮助。

    【讨论】:

    • 感谢您的洞察
    【解决方案5】:

    截至October 2019 cognito 资源现在由 cloudformation 支持。使用 AWS::Cognito::UserPool、AWS::Cognito::UserPoolClient、AWS::Cognito::UserPoolDomain 等预期类型创建资源。

    要启用身份提供者,需要设置以下相关的 CF 属性。

      UserPoolClient:
        Type: AWS::Cognito::UserPoolClient
          UserPoolId: !Ref UserPool
          SupportedIdentityProviders:
            - COGNITO
            - Facebook
            - Google
            - LoginWithAmazon
            ...
    

    cloudformation 的文档在here 可用。

    【讨论】:

    • 你能解释一下这实际上是如何解决 OP 的问题的吗?如屏幕截图中所述,我在您列出的文档中找不到实际启用客户端 Cognito 池的任何地方。
    • 更新了答案以包含相关的云形成属性以启用身份提供者。