当AWS :: Cognito :: IdentityPoolRoleAttachment资源具有RoleMappings属性时,AWS Cloudformation无法创建堆栈

时间:2018-11-03 11:53:52

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

我正在尝试通过cloudformation创建我的认知资源。下面的模板可以正常工作;

AWSTemplateFormatVersion: 2010-09-09
Resources:
  CognitoAuthRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Federated: cognito-identity.amazonaws.com
            Action:
              - 'sts:AssumeRoleWithWebIdentity'
            Condition:
              StringEquals:
                'cognito-identity.amazonaws.com:aud':
                  Ref: CognitoIdentityPool
              'ForAnyValue:StringLike':
                'cognito-identity.amazonaws.com:amr': authenticated
  CognitoUserPool:
    Type: 'AWS::Cognito::UserPool'
    Properties:
      UsernameAttributes:
        - email
      AutoVerifiedAttributes:
        - email
  CognitoUserPoolClient:
    Type: 'AWS::Cognito::UserPoolClient'
    Properties:
      UserPoolId:
        Ref: CognitoUserPool
      ExplicitAuthFlows:
        - ADMIN_NO_SRP_AUTH
      GenerateSecret: false
  CognitoIdentityPool:
    Type: 'AWS::Cognito::IdentityPool'
    Properties:
      AllowUnauthenticatedIdentities: true
      CognitoIdentityProviders:
        - ClientId:
            Ref: CognitoUserPoolClient
          ProviderName:
            'Fn::GetAtt':
              - CognitoUserPool
              - ProviderName
  CognitoIdentityPoolRoles:
    Type: 'AWS::Cognito::IdentityPoolRoleAttachment'
    Properties:
      IdentityPoolId:
        Ref: CognitoIdentityPool
      Roles:
        authenticated:
          'Fn::GetAtt':
            - CognitoAuthRole
            - Arn

但是,当我将RoleMappings属性添加到CognitoIdentityPoolRoles资源时,Cloudformation返回错误并且无法创建堆栈。修改后的资源如下;

  CognitoIdentityPoolRoles:
    Type: 'AWS::Cognito::IdentityPoolRoleAttachment'
    Properties:
      IdentityPoolId:
        Ref: CognitoIdentityPool
      Roles:
        authenticated:
          'Fn::GetAtt':
            - CognitoAuthRole
            - Arn
      RoleMappings:
        AmbiguousRoleResolution: Deny
        Type: Rules
        RulesConfiguration:
          Rules:
            - Claim: 'custom:role'
              MatchType: Equals
              Value: viewer
              RoleARN:
                'Fn::GetAtt':
                  - CognitoAuthRole
                  - Arn
            - Claim: 'custom:role'
              MatchType: Equals
              Value: editor
              RoleARN:
                'Fn::GetAtt':
                  - CognitoAuthRole
                  - Arn

如您所见,RoleMappings的类型为“规则”。您可以尝试使用Token参数,并且结果不会改变。

  CognitoIdentityPoolRoles:
    Type: 'AWS::Cognito::IdentityPoolRoleAttachment'
    Properties:
      IdentityPoolId:
        Ref: CognitoIdentityPool
      Roles:
        authenticated:
          'Fn::GetAtt':
            - CognitoAuthRole
            - Arn
      RoleMappings:
        AmbiguousRoleResolution: Deny
        Type: Token

不幸的是,错误消息没有提供任何线索,我无法取得任何进展,并停留在此阶段。

Status  Type    Logical ID  Status Reason
CREATE_FAILED   AWS::Cognito::IdentityPoolRoleAttachment    CognitoIdentityPoolRoles    Internal Failure

如何使带有RoleMappings的IdentityPoolRoleAttachment工作?

1 个答案:

答案 0 :(得分:1)

我遇到了同样的问题,不幸的是,我看到CloudFormation还不支持RoleMappings,所以我们永远都会遇到这种“内部故障”。 但是,您可以采取一些解决方法来解决问题。在我的情况下,我使用了boto3 library来调用 Lambda函数中的IdentityPool更新,并且使用了 Severless Framework ,但是相同的目的可能是使用SAM或其他CloudFormation堆栈框架。 因此,我使用2个单独的堆栈完成了这些步骤:

  1. 创建包括所有Cognito资源(UserPool,UserPoolClient,IdentityPool)和IamRoles的第一个堆栈,您将为其分配它们,并在 Outputs 部分的 Export 中导出必要的 ID 和 ARN 用于下一个堆栈。

service: cognito-template

provider:
  name: aws
  stage: dev
  region: us-east-1
  stackName: cognito-template-${self:provider.stage}-resources

custom:
  system:
    name: myapp
    cognitoclientname: MyAppClient

resources:
  Resources:
    # ## ## ## ## ## ## ## ## ## ## ## ## ## Definicao de Usuários Cognito UserPool ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## # 
    UserPool:
      Type: AWS::Cognito::UserPool
      Properties:
        UserPoolName: ${self:custom.system.name}userpool
        AdminCreateUserConfig: 
          AllowAdminCreateUserOnly: True
          UnusedAccountValidityDays: 30
        EmailVerificationMessage: Clique no link abaixo para verificar seu endereço de e-mail. {####}
        EmailVerificationSubject: Seu link de verificação
        MfaConfiguration: OFF
        Policies: 
          PasswordPolicy:
            MinimumLength: 8
            RequireLowercase: false
            RequireNumbers: false
            RequireSymbols: false
            RequireUppercase: false
        Schema: 
          - AttributeDataType: String
            DeveloperOnlyAttribute: false
            Mutable: true
            Name: name
            Required: true
          - AttributeDataType: String
            DeveloperOnlyAttribute: false
            Mutable: true
            Name: family_name
            Required: true
          - AttributeDataType: String
            DeveloperOnlyAttribute: false
            Mutable: true
            Name: email
            Required: true
          - AttributeDataType: String
            DeveloperOnlyAttribute: false
            Mutable: true
            Name: phone_number
            Required: true
          - AttributeDataType: String
            DeveloperOnlyAttribute: false
            Mutable: true
            Name: gender
            Required: true
          - AttributeDataType: String
            DeveloperOnlyAttribute: false
            Mutable: true
            Name: permission
            Required: false
        UsernameAttributes: 
          - email
          - phone_number
    # ## ## ## ## ## ## ## ## ## ## ## ## ## Client Cognito ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## # 
    AppUserPoolClient:
      Type: AWS::Cognito::UserPoolClient
      Properties:
          ClientName: ${self:custom.system.cognitoclientname}
          ExplicitAuthFlows: 
            - ADMIN_NO_SRP_AUTH
            - USER_PASSWORD_AUTH
          GenerateSecret: false
          RefreshTokenValidity: 1
          UserPoolId: !Ref UserPool
    # ## ## ## ## ## ## ## ## ## ## ## ## ## Provedor de Identidade Cognito ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## # 
    AppIdentityPool:
      Type: AWS::Cognito::IdentityPool
      Properties:
        IdentityPoolName: ${self:custom.system.name}identitypool
        AllowUnauthenticatedIdentities: false
        CognitoIdentityProviders: 
          - ClientId: !Ref AppUserPoolClient
            ProviderName: !GetAtt UserPool.ProviderName
    AppIdentitiesRolesAttachment:
      Type: AWS::Cognito::IdentityPoolRoleAttachment
      DependsOn:
        - AppIdentityPool
        - CognitoAuthorizedRole
        - CognitoUnAuthorizedRole
      Properties:
        IdentityPoolId: !Ref AppIdentityPool
        Roles: 
          authenticated: !GetAtt CognitoAuthorizedRole.Arn
          unauthenticated: !GetAtt CognitoUnAuthorizedRole.Arn
    CognitoAuthorizedRole:
      Type: "AWS::IAM::Role"
      Properties:
        AssumeRolePolicyDocument: 
          Version: "2012-10-17"
          Statement:
            - Effect: "Allow"
              Principal: 
                Federated: "cognito-identity.amazonaws.com"
              Action: 
                - "sts:AssumeRoleWithWebIdentity"
              Condition:
                StringEquals: 
                  "cognito-identity.amazonaws.com:aud": !Ref AppIdentityPool
                "ForAnyValue:StringLike":
                  "cognito-identity.amazonaws.com:amr": authenticated
        Policies:
          - PolicyName: "CognitoAuthorizedPolicy"
            PolicyDocument: 
              Version: "2012-10-17"
              Statement: 
                - Effect: "Allow"
                  Action:
                    - "mobileanalytics:PutEvents"
                    - "cognito-sync:*"
                    - "cognito-identity:*"
                  Resource: "*"
                - Effect: "Allow"
                  Action:
                    - "lambda:InvokeFunction"
                  Resource: "*"
    CognitoUnAuthorizedRole:
      Type: "AWS::IAM::Role"
      Properties:
        AssumeRolePolicyDocument: 
          Version: "2012-10-17"
          Statement:
            - Effect: "Allow"
              Principal: 
                Federated: "cognito-identity.amazonaws.com"
              Action: 
                - "sts:AssumeRoleWithWebIdentity"
              Condition:
                StringEquals: 
                  "cognito-identity.amazonaws.com:aud": !Ref AppIdentityPool
                "ForAnyValue:StringLike":
                  "cognito-identity.amazonaws.com:amr": unauthenticated
        Policies:
          - PolicyName: "CognitoUnauthorizedPolicy"
            PolicyDocument: 
              Version: "2012-10-17"
              Statement: 
                - Effect: "Allow"
                  Action:
                    - "mobileanalytics:PutEvents"
                    - "cognito-sync:*"
                  Resource: "*"
    AdministradorRole:
      Type: "AWS::IAM::Role"
      Properties:
        AssumeRolePolicyDocument: 
          Version: "2012-10-17"
          Statement:
            - Effect: "Allow"
              Principal: 
                Federated: "cognito-identity.amazonaws.com"
              Action: 
                - "sts:AssumeRoleWithWebIdentity"
              Condition:
                StringEquals: 
                  "cognito-identity.amazonaws.com:aud": !Ref AppIdentityPool
                "ForAnyValue:StringLike":
                  "cognito-identity.amazonaws.com:amr": authenticated
        Policies:
          - PolicyName: "CognitoAdministradorPolicy"
            PolicyDocument: 
              Version: "2012-10-17"
              Statement: 
                - Effect: "Allow"
                  Action:
                    - "mobileanalytics:PutEvents"
                    - "cognito-sync:*"
                  Resource: "*"
    GerenciadorRole:
      Type: "AWS::IAM::Role"
      Properties:
        AssumeRolePolicyDocument: 
          Version: "2012-10-17"
          Statement:
            - Effect: "Allow"
              Principal: 
                Federated: "cognito-identity.amazonaws.com"
              Action: 
                - "sts:AssumeRoleWithWebIdentity"
              Condition:
                StringEquals: 
                  "cognito-identity.amazonaws.com:aud": !Ref AppIdentityPool
                "ForAnyValue:StringLike":
                  "cognito-identity.amazonaws.com:amr": authenticated
        Policies:
          - PolicyName: "CognitoAdministradorPolicy"
            PolicyDocument: 
              Version: "2012-10-17"
              Statement: 
                - Effect: "Allow"
                  Action:
                    - "mobileanalytics:PutEvents"
                    - "cognito-sync:*"
                  Resource: "*"
                - Effect: "Allow"
                  Action:
                    - "s3:GetObject"
                    - "s3:PutObject"
                  Resource: 
                    - "arn:aws:s3:::${self:custom.system.name}/public/*"
  # ## ## ## ## ## ## ## ## ## ## ## ## ## IAM Permission to lambda script execute update into IdentityPoolRoleMappings ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #                   
    MigrationScriptRole:
      Type: AWS::IAM::Role
      Properties:
        AssumeRolePolicyDocument: 
          Version: "2012-10-17"
          Statement:
            - Effect: "Allow"
              Principal: 
                Service: 
                  - lambda.amazonaws.com
              Action: 
                - "sts:AssumeRole"
        Policies:
          - PolicyName: "MigrationScriptPolicy"
            PolicyDocument: 
              Version: "2012-10-17"
              Statement: 
                - Effect: "Allow"
                  Action: 
                    - "cognito-idp:*"
                    - "cognito-identity:*"
                    - "iam:*"
                  Resource: "*"
  Outputs:
    UserPoolId:
      Value: !Ref UserPool
      Export:
        Name: "UserPool::Id"
    UserPoolArn:
      Value: !GetAtt UserPool.Arn
      Export:
        Name: "UserPool::Arn"
    UserPoolClientId:
      Value: !Ref AppUserPoolClient
      Export:
        Name: "AppUserPoolClient::Id"
    AppIdentityPoolId:
      Value: !Ref AppIdentityPool
      Export:
        Name: "AppIdentityPool::Id"
    AdministradorRoleArn:
      Value: !GetAtt AdministradorRole.Arn
      Export:
        Name: "AdministradorRole::Arn"
    GerenciadorRoleArn:
      Value: !GetAtt GerenciadorRole.Arn
      Export:
        Name: "GerenciadorRole::Arn"
    MigrationScriptRoleArn:
      Value: !GetAtt MigrationScriptRole.Arn
      Export:
        Name: "MigrationScriptRole::Arn"
  1. 创建包括lambda函数的第二个堆栈,该函数将从 boto3 库调用 update_user_pool 。此函数必须接收第一个堆栈的导出值,并将它们附加到环境变量中,以便在调用该函数时使用。

service: cognito-template

provider:
  name: aws
  stage: dev
  region: us-east-1
  stackName: cognito-template-${self:provider.stage}-functions

functions:
  migration-script:
    handler: lambda_function.handler
    runtime: python3.6
    role: 
      Fn::ImportValue: !Sub MigrationScriptRole::Arn
    environment:
      USER_POOL_REGION: us-east-1 # here you can change to you preferred region if you want
      USER_POOL_ID: 
        Fn::ImportValue: !Sub UserPool::Id
      USER_POOL_CLIENT_ID:
        Fn::ImportValue: !Sub AppUserPoolClient::Id
      IDENTITY_POOL_ID:
        Fn::ImportValue: !Sub AppIdentityPool::Id
      ADMINISTRADOR_ROLE_ARN:
        Fn::ImportValue: !Sub AdministradorRole::Arn
      GERENCIADOR_ROLE_ARN:
        Fn::ImportValue: !Sub GerenciadorRole::Arn
  1. 最后,lambda函数的代码通过 boto3 调用执行更新,为此,我使用了 python3.6 ,但是可以使用 Node must see the boto3 docs for Node

    
    import boto3
    import os

    def handler(event, context): setup_cognito() return event def setup_cognito(): define_cognito_attributes() create_cognito_identity_roles() def create_cognito_identity_roles(): user_pool_region = os.environ['USER_POOL_REGION'] user_pool_id = os.environ['USER_POOL_ID'] user_pool_client_id = os.environ['USER_POOL_CLIENT_ID'] identity_pool_id = os.environ['IDENTITY_POOL_ID']
    administrador_role = os.environ['ADMINISTRADOR_ROLE_ARN'] gerenciador_role = os.environ['GERENCIADOR_ROLE_ARN'] client_identity = boto3.client('cognito-identity') client_idp = boto3.client('cognito-idp') response = client_identity.get_identity_pool_roles(IdentityPoolId=identity_pool_id) identity_provider = "cognito-idp.{}.amazonaws.com/{}:{}".format(user_pool_region, user_pool_id, user_pool_client_id) options = { 'IdentityPoolId': response['IdentityPoolId'], 'Roles': response['Roles'], 'RoleMappings': { identity_provider: { 'Type': 'Rules', 'AmbiguousRoleResolution': 'AuthenticatedRole', 'RulesConfiguration': { 'Rules': [ { 'Claim': 'custom:permission', 'MatchType': 'Equals', 'Value': 'ADMNISTRADOR', 'RoleARN': administrador_role }, { 'Claim': 'custom:permission', 'MatchType': 'Equals', 'Value': 'GERENCIADOR', 'RoleARN': gerenciador_role } ] } } } } response = client_identity.set_identity_pool_roles(IdentityPoolId=options['IdentityPoolId'], Roles=options['Roles'], RoleMappings=options['RoleMappings']) def define_cognito_attributes(): user_pool_id = os.environ['USER_POOL_ID'] user_pool_client_id = os.environ['USER_POOL_CLIENT_ID'] client = boto3.client('cognito-idp') response = client.update_user_pool_client( UserPoolId=user_pool_id, ClientId=user_pool_client_id, WriteAttributes=[ 'custom:permission', 'phone_number', 'email', 'name', 'family_name', 'gender' ] )

创建后,可以通过 CLI WEB'测试'按钮调用lambda函数,然后将您希望的角色映射分配给您IdentityPool。 / p>

希望它可以为您提供帮助! (是)