Cloudformation Cognito - 如何通过 SAM 模板设置应用程序客户端设置、域和联合身份

Posted

技术标签:

【中文标题】Cloudformation Cognito - 如何通过 SAM 模板设置应用程序客户端设置、域和联合身份【英文标题】:Cloudformation Cognito - how to setup App Client Settings, Domain, and Federated Identities via SAM template 【发布时间】:2018-09-06 13:08:42 【问题描述】:

我的 cognito 用户池 cloudformation 模板已经在工作,并将其集成到我的 api 网关。但不知何故,我仍然必须手动配置应用程序客户端设置、域和联合身份,以便为用户提供一个有效的登录门户。我一直在到处寻找自动化这些可能的解决方案,但我似乎找不到任何接近它的东西。

我想通过 cloudformation sam 模板自动配置应用程序客户端设置、域和联合身份,因此我不必手动执行这些操作。

非常感谢任何建议。谢谢。

(附加信息发布的附件)

https://i.stack.imgur.com/I7NSt.png https://i.stack.imgur.com/ZbiTI.png https://i.stack.imgur.com/F8rfH.png

【问题讨论】:

提前感谢大家的任何建议或回答 根据我的回答-您使用什么工具进行自动化? (如 CodeBuild/Pipeline、Jenkins 等) 【参考方案1】:

我创建了两个 CloudFormation 自定义资源来应用 Cognito 应用程序客户端设置和域名。有了这些资源,你可以有这样的脚本:

UserPoolTestClient:
  Type: 'AWS::Cognito::UserPoolClient'
  Properties:
    ClientName: UserPoolTestClient
    GenerateSecret: true
    UserPoolId: !Ref UserPoolTest
UserPoolTestClientSettings:
  Type: 'Custom::CognitoUserPoolClientSettings'
  Properties:
    ServiceToken: !GetAtt CloudFormationCognitoUserPoolClientSettings.Arn
    UserPoolId: !Ref UserPoolTest
    UserPoolClientId: !Ref UserPoolTestClient
    SupportedIdentityProviders:
      - COGNITO
    CallbackURL: 'https://www.amazon.com'
    LogoutURL: 'https://www.google.com'
    AllowedOAuthFlowsUserPoolClient: true
    AllowedOAuthFlows:
      - code
    AllowedOAuthScopes:
      - openid
UserPoolTestDomain:
  Type: 'Custom::CognitoUserPoolDomain'
  Properties:
    ServiceToken: !GetAtt CloudFormationCognitoUserPoolDomain.Arn
    UserPoolId: !Ref UserPoolTest
    Domain: 'userpool-test-01'

完整代码为here。

【讨论】:

您好罗斯伯格,感谢您的回复!如果我们仍然可以进行更改(因为我们已经提交了部署),我将检查我的部署并与我们的管理员交谈。但真的谢谢。在我最需要的时候,这个答案在哪里。 @rosberg-linhares:我看到你在AllowedOAuthScopes 中指定了openid。这是否意味着将在幕后创建 OpenIDConnectProvider?我之前创建了另一个自定义资源,显式调用iam.createOpenIDConnectProvider(),但我希望重构该代码。 @rosberg-linhares - 太好了,非常感谢您启动这个项目。现在还有一个用于创建 IdentityProviders 的 PR。 还有几个其他(通用)选项,即:github.com/ab77/cfn-generic-custom-resource#cognito-demo 和 github.com/emdgroup/…(我可以找到)。【参考方案2】:

更新:自 2019 年底以来,AWS Cloudformation 原生支持应用程序客户端设置、域和联合身份。查看其他答案。

似乎无法通过 CloudFormation 提供 应用集成 -> 域名联合 -> 身份提供者

我发现只有 User Pool Client 的参考(常规设置 -> 应用程序客户端),但它不会配置 应用程序集成 -> 应用程序客户端设置

如果您需要自动化为用户池提供 Domain nameIdentity providersApp client settings 的过程,您可以通过创建自定义脚本 (AWS CLI) 或 Lambda (AWS SDK) 来实现,这应该在堆栈之后执行部署。

**更新**

查看 excellent example (answer below),它显示了 CloudFormation Custom Resources 与 Lambda 的用法。

【讨论】:

感谢 Michal,到目前为止,这是我得到的最好和最诚实的答案。我同意,可能无法通过 SAM 模板执行此操作,但自定义脚本可以。我只是希望有某种方法可以自动化它(因为我很懒)。谢谢老兄。 自 2019 年 10 月 3 日起,用户池域可通过 cloudformation 在本地实现。请参阅下面@matsev 的答案或此发布页面docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/…【参考方案3】:

CloudFormation 已添加资源AWS::Cognito::UserPoolDomain 来管理用户池域:

Type: AWS::Cognito::UserPoolDomain
Properties: 
  CustomDomainConfig: 
     CertificateArn: !Ref CertificateArn
  Domain: "your.custom.domain.com"
  UserPoolId: !Ref UserPool

另外,还有AWS::Cognito::UserPoolClient的配置:

Type: AWS::Cognito::UserPoolClient
Properties: 
  AllowedOAuthFlows: 
    - String
  AllowedOAuthFlowsUserPoolClient: Boolean
  AllowedOAuthScopes: 
    - String
  AnalyticsConfiguration: 
    AnalyticsConfiguration
  CallbackURLs: 
    - String
  ClientName: String
  DefaultRedirectURI: String
  ExplicitAuthFlows: 
    - String
  GenerateSecret: Boolean
  LogoutURLs: 
    - String
  ReadAttributes: 
    - String
  RefreshTokenValidity: Integer
  SupportedIdentityProviders: 
    - String
  UserPoolId: String
  WriteAttributes: 
    - String

【讨论】:

【参考方案4】:

从昨天开始,AWS CloudFormation 增加了对直接配置域名、身份和其他设置的原生支持: https://aws.amazon.com/about-aws/whats-new/2019/10/amazon-cognito-increases-cloudformation-support/

这项新支持包括安全和自动配置托管 UI 域、为托管 UI 配置自定义、配置 IdentityProvider、配置高级安全功能的行为和配置资源服务器的能力,所有这些都直接在 CloudFormation 内完成。

(感谢我的同事 Bernhard 的这次更新)

【讨论】:

【参考方案5】:

我想添加一个不同的解决方案(由 Mickael 建议),因为 CloudFormation 的设置很复杂;此命令行将在创建 CloudFormation 堆栈后创建您的域:

 aws cognito-idp create-user-pool-domain --domain test-domain --user-pool-id eu-west-1_xxxxxxxx 

在您的自动化部署中,您可以添加一个脚本来设置您的域。不如 CF 上的所有东西都好,但它可以工作

【讨论】:

自定义资源对我来说效果很好。我不能使用 CLI,因为我需要通过 SAM 模板获取所有内容。 嗨@jeff,您能否提供域的自定义资源,因为上述来自 Rosberg 的 Repo 会在该部分引发错误?【参考方案6】:

我为自己和其他想要尝试的人推出了这 3 种资源的解决方案。 https://github.com/cyrfer/cloudformation-custom-resource-provider

【讨论】:

【参考方案7】:

非常受 Rosberg Linhares 示例的启发,但在 python 中,并使用 AWS cfn helper 模块:

如果你用这段代码写一个lambda函数,基本上是用boto3来做客户端应用设置

from crhelper import CfnResource
import boto3
from copy import copy

# setup the cfn helper 
helper = CfnResource()
client = boto3.client('cognito-idp')

# these wrappers return the function unaltered, so we can chain them to apply
# the function in both create and update
@helper.create
@helper.update
def update_on_create(event, _):

        params = copy(event['ResourceProperties'])
        del params['ServiceToken']

        client.update_user_pool_client(**params) 

# don't do anything on delete. Deleting the client app is handled by the template
@helper.delete
def delete_user_pool_client(event, _):
        pass


def handler(event, context):
    helper(event, context)

那么你的 cloudformation 将是相似的,例如

UserPoolClient:
    Type: AWS::Cognito::UserPoolClient
    Properties:
      ClientName: 'TestClient'
      GenerateSecret: true
      UserPoolId: !Ref UserPool
  UserPoolClientSettings:
    Type: Custom::CognitoUserPoolClientSettings
    DependsOn: 
        - LambdaForAppClientSettings
        - UserPoolClient
    Properties:
      ServiceToken: !GetAtt LambdaForAppClientSettings.Arn
      UserPoolId: !Ref UserPool
      ClientId: !Ref UserPoolClient
      CallbackURLs: 
          - https://www.amazon.com
      SupportedIdentityProviders:
          - COGNITO 

由于client.update_user_pool_client(**params) 中的参数扩展,您可以为update_user_pool_client() 指定部分或全部参数可能带来的好处。您必须确保 cloudformation 自定义资源的 Properties 映射中的键与 boto3 所需的完全匹配。检查boto3 documentation 以获取可能的参数列表。

【讨论】:

【参考方案8】:

正如 matsev 和 Gregor 所指出的,现在这可以通过 cloudformation 轻松完成。这意味着同时已弃用接受的答案和与接受的答案相关的答案。

查看文档:

    UserPoolIdentityProvider UserPoolClient UserPoolDomain

这是我自己的模板中的一个示例:

  UserPoolClient:
    Type: "AWS::Cognito::UserPoolClient"
    Properties:
      ClientName: !Sub $AppName-$Env-appsync-client
      GenerateSecret: false
      UserPoolId: !Ref UserPool
      SupportedIdentityProviders:
        - COGNITO
        - Facebook
        #- SignInWithApple
        - Google
      AllowedOAuthFlowsUserPoolClient: true
      AllowedOAuthFlows: 
        - code
      AllowedOAuthScopes:
        - email
        - openid
        - profile
        - aws.cognito.signin.user.admin 
      CallbackURLs: 
        - !Sub $AppName://
      DefaultRedirectURI: !Sub $AppName://
      LogoutURLs: 
        - !Sub $AppName://
    DependsOn: 
      - GoogleCognitoUserPoolIdentityProvider
      #- AppleUserPoolIdentityProvider
      - FacebookCognitoUserPoolIdentityProvider

  CognitoUserPoUserPoolDomain: 
    Type: AWS::Cognito::UserPoolDomain 
    Properties:
      UserPoolId: !Ref UserPool 
      Domain: !Sub $AppName-$Env

  FacebookCognitoUserPoolIdentityProvider:
    Type: AWS::Cognito::UserPoolIdentityProvider
    Properties:
      ProviderName: Facebook
      AttributeMapping:
        email: email
      ProviderDetails:
        client_id: TODOYourFacebookAppId
        client_secret: TODOYourFacebookAppSecret
        authorize_scopes: email,public_profile
      ProviderType: Facebook
      UserPoolId: !Ref UserPool
    
  GoogleCognitoUserPoolIdentityProvider:
    Type: AWS::Cognito::UserPoolIdentityProvider
    Properties:
      ProviderName: Google
      AttributeMapping:
        email: email
      ProviderDetails:
        client_id: TODOYourGoogleAppId
        client_secret: TODOYourGoogleAppSecret
        authorize_scopes: email openid profile
      ProviderType: Google
      UserPoolId: !Ref UserPool

【讨论】:

以上是关于Cloudformation Cognito - 如何通过 SAM 模板设置应用程序客户端设置、域和联合身份的主要内容,如果未能解决你的问题,请参考以下文章

在 CloudFormation 中将 Cognito 验证类型设置为链接

CloudFormation AWS::Cognito::IdentityPoolRoleAttachment RoleMappings 语法错误

带有 CloudFormation 的 AWS Cognito - 架构属性上的 InvalidParameterException

我们可以使用 Cloudformation 为 Cognito UserPool 定义社交提供者吗?

如何通过 CloudFormation 在 Cognito 中要求电子邮件验证?

如何使用 cloudformation 在 AWS cognito 上设置验证属性?