首页 > 解决方案 > CloudFormation 更新 SNS 主题的奇怪行为

问题描述

抱歉读了很久,但我只包括了必要的相关部分。我为一个项目继承了一些代码和 CloudFormation 脚本,之前的开发人员留下了一个神秘的注释:

您必须更新 app-deploy.cfn.yaml 中以下项目的跟踪日期才能使更改生效。

他早已不在,我无法向他询问他的指示。以下是必须更新的项目:

ApiDeployment20200214:
    Type: AWS::ApiGateway::Deployment
    Properties:
      RestApiId: !Ref NaasRestApi

RestApiStage:
    Type: AWS::ApiGateway::Stage
    Properties:
      DeploymentId: !Ref ApiDeployment20200214
      RestApiId: !Ref NaasRestApi
      StageName: !Sub ${Environment}

ApiBasePathMapping:
    Type: AWS::ApiGateway::BasePathMapping
    Condition: IsMainPipeline
    DependsOn: ApiDeployment20200214
    Properties:
      BasePath: ''
      DomainName: !Ref ApiGatewayDomainName
      RestApiId: !Ref NaasRestApi
      Stage: !Sub ${Environment}

老实说,这似乎很不寻常。看起来他正在将缓存清除技术应用于 API 网关。据我所知,这不应该发生。

男孩是我错了。

我最近需要对 SNS 订阅进行一项简单的更改,仅将其添加- redirect为特定 Lambda 订阅的源。这是添加了新源的资源:

BHIEventLambdaSubscription:
    Type: AWS::SNS::Subscription
    Properties:
      Endpoint: !GetAtt BHIEventLambdaFunction.Arn
      Protocol: lambda
      TopicArn: !Ref EventTopicArn
      FilterPolicy:
        domain:
          - payments
        source:
          - recycling
          - processor
          - paas
          - redirect
        type:
          - payment.approved
          - payment.declined
        brand_id:
          - '40'

我部署了脚本并见证了更新的发生。我检查了控制台是否有正确的 JSON,揭示了这一点:

{
  "source": [
    "recycling",
    "processor",
    "paas",
    "redirect"
  ],
  "type": [
    "payment.approved",
    "payment.declined"
  ],
  "domain": [
    "payments"
  ],
  "brand_id": [
    "40"

都好!我应该很高兴,但是当我发送正确的消息来测试源时,我收到了一条错误消息:

@message 2020-02-14 19:11:02 <071acec7-096b-4c45-996a-5ed996df7c23> 错误 AbstractEventHandler:66 - java.lang.IllegalArgumentException:无法处理消息,格式无效。

在我的用户界面中

{"message": "Invalid request body"}

检查 CloudWatch Logs,我可以看到使用该源正确发出请求:

@message 2020-02-14 19:13:41 INFO BHIEventHandler:23 - BHI Handler Received: {[{sns: {messageAttributes: {domain={type: String,value: payment}, source={type: String,value : 重定向} , type={type: String,value: payment.approved}, brand_id={type: String,value: 40}}, ....


突然,我想起了之前开发人员的神秘信息,但我看不出这将如何应用于对 SNS 进行更改,尤其是因为该更新似乎已正确部署到 AWS。与我讨论这个问题的另一位开发人员说:“你可以通过尝试来证明老布鲁斯是错的,在这一点上你没有什么可失去的,我们可以消除它作为一种干扰。”

出发,我们更改分配/附加/标记到 API 资源的日期并重新部署。我在控制台中看到更新,CodePipeline 报告部署已成功完成。我们发送测试...

……那该死的东西起作用了!

我的问题

为什么对 CF 的完全(显然)不相关的部分进行更改会使这项工作有效?我们做错了什么吗?如果是这样,我该如何纠正?

按要求

这是完整的模板:

Transform: AWS::Serverless-2016-10-31
Parameters:
  DeveloperPrefix:
    Type: String
    Default: ''
  AppName:
    Type: String
    Description: The application name
  Environment:
    Type: String
    Description: The environment name
  AppVersion:
    Type: String
    Description: The application version
  SharedBucketName:
    Type: String
    Description: Shared bucket name containing the deployable artifact
  WorkspacePrefix:
    Type: String
    Description: App workspace in shared bucket
  DeployPhase:
    Type: String
  CustomResourceLambdaS3Version:
    Type: String
    Description: The Custom Resource Lambda S3 version of the artifact
  S3Version:
    Type: String
    Description: The S3 Version
  HGEventLambdaS3Version:
    Type: String
    Description: The HG Event Lambda S3 version of the artifact
  HGEventRetryLambdaS3Version:
    Type: String
    Description: HG Event Retry Lambda S3 Version artifact
  SBEventLambdaS3Version:
    Type: String
    Description: The SB Event Lambda S3 version of the artifact
  SBEventRetryLambdaS3Version:
    Type: String
    Description: SB Event Retry Lambda S3 Version artifact
  BHEventLambdaS3Version:
    Type: String
    Description: The BH Event Lambda S3 version of the artifact
  BHEventRetryLambdaS3Version:
    Type: String
    Description: BH Event Retry Lambda S3 Version artifact
  BHIEventLambdaS3Version:
    Type: String
    Description: The BHI Event Lambda S3 version of the artifact
  BHIEventRetryLambdaS3Version:
    Type: String
    Description: BHI Event Retry Lambda S3 Version artifact
  AsoEventLambdaS3Version:
    Type: String
    Description: The ASO Event Lambda S3 version of the artifact
  AsoEventRetryLambdaS3Version:
    Type: String
    Description: ASO Event Retry Lambda S3 Version artifact
  CTEventLambdaS3Version:
    Type: String
    Description: The CT Event Lambda S3 version of the artifact
  CTEventRetryLambdaS3Version:
    Type: String
    Description: The CT Event Retry Lambda S3 Version artifact
  HZ:
    Type: String
    Description: The hosted zone in Route53
    Default: "notifications.svcs.example.com"
  CloudFrontHZ:
    Type: String
    Default: Z2FDTNDATAQYW2
  VPCStackName:
    Type: String
    Description: "The Stack containing the VPC you wish to attach the VPN to"

Mappings:
  EnvironmentMap:
    dev:
      EnvironmentName: 'dev.'
      CertificateId: ''
      HostedZoneId: ''
      VpcStackName: VPC-QA
    qa:
      EnvironmentName: 'qa.'
      CertificateId: 'xxxxxxxxxxxx'
      HostedZoneId: 'xxxxxxxxxxxx'
      VpcStackName: VPC-QA
    stage:
      EnvironmentName: 'stage.'
      CertificateId: 'xxxxxxxxxxxx'
      HostedZoneId: 'xxxxxxxxxxxx'
      VpcStackName: VPC-Stage
    prod:
      EnvironmentName: ''
      CertificateId: 'xxxxxxxxxxxx'
      HostedZoneId: 'xxxxxxxxxxxx'
      VpcStackName: VPC-Prod

Conditions:
  IsMainPipeline: !And
    - !Equals [ !Ref DeveloperPrefix, '' ]
    - !Equals [ !Ref DeployPhase, rel ]

Resources:
  #####################
  # HostedZone Config #
  #####################
  HostedZoneResource:
    Type: "AWS::CloudFormation::Stack"
    Condition: IsMainPipeline
    Properties:
      Parameters:
        DeveloperPrefix: !Ref DeveloperPrefix
        Environment: !Ref Environment
        DeployPhase: !Ref DeployPhase
      TemplateURL: !Sub "https://s3.amazonaws.com/${SharedBucketName}/${DeveloperPrefix}${AppName}/${Environment}/cf/nested/${S3Version}/hosted-zone.cfn.yaml"

  ####################
  # Lambda Resources #
  ####################
  CustomResource:
    Type: "AWS::CloudFormation::Stack"
    Properties:
      Parameters:
        AppName: !Ref AppName
        Environment: !Ref Environment
        DeveloperPrefix: !Ref DeveloperPrefix
        DeployPhase: !Ref DeployPhase
        AppVersion: !Ref AppVersion
        SharedBucketName: !Ref SharedBucketName
        WorkspacePrefix: !Ref WorkspacePrefix
        CustomResourceLambdaS3Version: !Ref CustomResourceLambdaS3Version
        #VPCStackName: !Ref VPCStackName
        VPCStackName: !FindInMap
          - EnvironmentMap
          - !Ref Environment
          - VpcStackName
      TemplateURL: !Sub "https://s3.amazonaws.com/${SharedBucketName}/${DeveloperPrefix}${AppName}/${Environment}/cf/nested/${S3Version}/custom-resource.cfn.yaml"

  HGResources:
    Type: "AWS::CloudFormation::Stack"
    Properties:
      Parameters:
        AppName: !Ref AppName
        Environment: !Ref Environment
        DeveloperPrefix: !Ref DeveloperPrefix
        DeployPhase: !Ref DeployPhase
        AppVersion: !Ref AppVersion
        SharedBucketName: !Ref SharedBucketName
        WorkspacePrefix: !Ref WorkspacePrefix
        HGEventLambdaS3Version: !Ref HGEventLambdaS3Version
        HGEventRetryLambdaS3Version: !Ref HGEventRetryLambdaS3Version
        EventTopicArn: !Ref EventTopic
        #VPCStackName: !Ref VPCStackName
        VPCStackName: !FindInMap
          - EnvironmentMap
          - !Ref Environment
          - VpcStackName
      TemplateURL: !Sub "https://s3.amazonaws.com/${SharedBucketName}/${DeveloperPrefix}${AppName}/${Environment}/cf/nested/${S3Version}/HG-subscriber.cfn.yaml"

  SBResources:
    Type: "AWS::CloudFormation::Stack"
    Properties:
      Parameters:
        AppName: !Ref AppName
        Environment: !Ref Environment
        DeveloperPrefix: !Ref DeveloperPrefix
        DeployPhase: !Ref DeployPhase
        AppVersion: !Ref AppVersion
        SharedBucketName: !Ref SharedBucketName
        WorkspacePrefix: !Ref WorkspacePrefix
        SBEventLambdaS3Version: !Ref SBEventLambdaS3Version
        SBEventRetryLambdaS3Version: !Ref SBEventRetryLambdaS3Version
        EventTopicArn: !Ref EventTopic
        #VPCStackName: !Ref VPCStackName
        VPCStackName: !FindInMap
          - EnvironmentMap
          - !Ref Environment
          - VpcStackName
      TemplateURL: !Sub "https://s3.amazonaws.com/${SharedBucketName}/${DeveloperPrefix}${AppName}/${Environment}/cf/nested/${S3Version}/SB-subscriber.cfn.yaml"

  BHResources:
    Type: "AWS::CloudFormation::Stack"
    Properties:
      Parameters:
        AppName: !Ref AppName
        Environment: !Ref Environment
        DeveloperPrefix: !Ref DeveloperPrefix
        DeployPhase: !Ref DeployPhase
        AppVersion: !Ref AppVersion
        SharedBucketName: !Ref SharedBucketName
        WorkspacePrefix: !Ref WorkspacePrefix
        BHEventLambdaS3Version: !Ref BHEventLambdaS3Version
        BHEventRetryLambdaS3Version: !Ref BHEventRetryLambdaS3Version
        EventTopicArn: !Ref EventTopic
        #VPCStackName: !Ref VPCStackName
        VPCStackName: !FindInMap
        - EnvironmentMap
        - !Ref Environment
        - VpcStackName
      TemplateURL: !Sub "https://s3.amazonaws.com/${SharedBucketName}/${DeveloperPrefix}${AppName}/${Environment}/cf/nested/${S3Version}/BH-subscriber.cfn.yaml"

  BHIResources:
    Type: "AWS::CloudFormation::Stack"
    Properties:
      Parameters:
        AppName: !Ref AppName
        Environment: !Ref Environment
        DeveloperPrefix: !Ref DeveloperPrefix
        DeployPhase: !Ref DeployPhase
        AppVersion: !Ref AppVersion
        SharedBucketName: !Ref SharedBucketName
        WorkspacePrefix: !Ref WorkspacePrefix
        BHIEventLambdaS3Version: !Ref BHIEventLambdaS3Version
        BHIEventRetryLambdaS3Version: !Ref BHIEventRetryLambdaS3Version
        EventTopicArn: !Ref EventTopic
        #VPCStackName: !Ref VPCStackName
        VPCStackName: !FindInMap
          - EnvironmentMap
          - !Ref Environment
          - VpcStackName
      TemplateURL: !Sub "https://s3.amazonaws.com/${SharedBucketName}/${DeveloperPrefix}${AppName}/${Environment}/cf/nested/${S3Version}/BHI-subscriber.cfn.yaml"

  AsoResources:
    Type: "AWS::CloudFormation::Stack"
    Properties:
      Parameters:
        AppName: !Ref AppName
        Environment: !Ref Environment
        DeveloperPrefix: !Ref DeveloperPrefix
        DeployPhase: !Ref DeployPhase
        AppVersion: !Ref AppVersion
        SharedBucketName: !Ref SharedBucketName
        WorkspacePrefix: !Ref WorkspacePrefix
        AsoEventLambdaS3Version: !Ref AsoEventLambdaS3Version
        AsoEventRetryLambdaS3Version: !Ref AsoEventRetryLambdaS3Version
        EventTopicArn: !Ref EventTopic
        #VPCStackName: !Ref VPCStackName
        VPCStackName: !FindInMap
        - EnvironmentMap
        - !Ref Environment
        - VpcStackName
      TemplateURL: !Sub "https://s3.amazonaws.com/${SharedBucketName}/${DeveloperPrefix}${AppName}/${Environment}/cf/nested/${S3Version}/aso-subscriber.cfn.yaml"

  CTResources:
    Type: "AWS::CloudFormation::Stack"
    Properties:
      Parameters:
        AppName: !Ref AppName
        Environment: !Ref Environment
        DeveloperPrefix: !Ref DeveloperPrefix
        DeployPhase: !Ref DeployPhase
        AppVersion: !Ref AppVersion
        SharedBucketName: !Ref SharedBucketName
        WorkspacePrefix: !Ref WorkspacePrefix
        CTEventLambdaS3Version: !Ref CTEventLambdaS3Version
        CTEventRetryLambdaS3Version: !Ref CTEventRetryLambdaS3Version
        EventTopicArn: !Ref EventTopic
        #VPCStackName: !Ref VPCStackName
        VPCStackName: !FindInMap
          - EnvironmentMap
          - !Ref Environment
          - VpcStackName
      TemplateURL: !Sub "https://s3.amazonaws.com/${SharedBucketName}/${DeveloperPrefix}${AppName}/${Environment}/cf/nested/${S3Version}/CT-subscriber.cfn.yaml"

  #########################
  # API Gateway Resources #
  #########################
  ApiGatewayDomainName:
    Type: AWS::ApiGateway::DomainName
    Condition: IsMainPipeline
    Properties:
      CertificateArn: !Join ["", ['arn:aws:acm:', !Ref 'AWS::Region', ':', !Ref 'AWS::AccountId', ':certificate/', !FindInMap [ EnvironmentMap, !Ref Environment, CertificateId ] ] ]
      DomainName: !Join [ '', [ !FindInMap [ EnvironmentMap, !Ref Environment, EnvironmentName ], !Ref HZ ] ]

  ApiBasePathMapping:
    Type: AWS::ApiGateway::BasePathMapping
    Condition: IsMainPipeline
    DependsOn: ApiDeployment20200214
    Properties:
      BasePath: ''
      DomainName: !Ref ApiGatewayDomainName
      RestApiId: !Ref NaasRestApi
      Stage: !Sub ${Environment}

  ApiGatewayARecord:
    Type: AWS::Route53::RecordSetGroup
    Condition: IsMainPipeline
    Properties:
      HostedZoneId: !FindInMap [ EnvironmentMap, !Ref Environment, HostedZoneId ]
      RecordSets:
        - Type: A
          Name: !Join  [ "", [ !FindInMap [ EnvironmentMap, !Ref Environment, EnvironmentName ], !Ref HZ, "." ] ]
          AliasTarget:
            HostedZoneId: !Ref CloudFrontHZ
            DNSName: !GetAtt ApiGatewayDomainName.DistributionDomainName

  NaasRestApi:
    Type: AWS::ApiGateway::RestApi
    DependsOn: EventTopic
    Properties:
      Body:
        Fn::Transform:
          Name: 'AWS::Include'
          Parameters:
            Location: !Join ['/', [ 's3:/', !Ref SharedBucketName, !Ref WorkspacePrefix, 'naas.yaml' ]]

  RestApiStage:
    Type: AWS::ApiGateway::Stage
    Properties:
      DeploymentId: !Ref ApiDeployment20200214
      RestApiId: !Ref NaasRestApi
      StageName: !Sub ${Environment}

  ApiDeployment20200214:
    Type: AWS::ApiGateway::Deployment
    Properties:
      RestApiId: !Ref NaasRestApi

  TESTApiGatewayUsagePlan:
    Type: AWS::ApiGateway::UsagePlan
    DependsOn: RestApiStage
    Properties:
      UsagePlanName: !Sub TEST-${DeveloperPrefix}${AppName}-${Environment}-${DeployPhase}-UsagePlan
      Description: !Sub 'TEST-${DeveloperPrefix}${AppName}-${Environment}-${DeployPhase} Usage plan for Testing ONLY.'
      ApiStages:
        - ApiId: !Ref NaasRestApi
          Stage: !Sub ${Environment}
      Quota:
        Limit: 5000
        Offset: 0
        Period: DAY
      Throttle:
        BurstLimit: 150
        RateLimit: 100

  DefaultUsagePlan:
    Type: AWS::ApiGateway::UsagePlan
    Condition: IsMainPipeline
    DependsOn: RestApiStage
    Properties:
      UsagePlanName: !Sub ${DeveloperPrefix}${AppName}-${Environment}-Default-UsagePlan
      Description: !Sub '${DeveloperPrefix}${AppName}-${Environment} Default Usage plan for Brands'
      ApiStages:
        - ApiId: !Ref NaasRestApi
          Stage: !Sub ${Environment}
      Quota:
        Limit: 50000
        Offset: 0
        Period: DAY
      Throttle:
        BurstLimit: 1500
        RateLimit: 1000

  ApiGatewayNaasSNSRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub ${DeveloperPrefix}${AppName}-${Environment}-${DeployPhase}-ApiGatewayNaasSNSRole
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - apigateway.amazonaws.com
            Action: ['sts:AssumeRole']
      Path: /
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSNSFullAccess

  TESTApiKey:
    Type: AWS::ApiGateway::ApiKey
    DependsOn: RestApiStage
    Properties:
      Name: !Sub "TEST-${DeveloperPrefix}${Environment}-${DeployPhase}"
      Description: "TEST API Key"
      Enabled: true
      StageKeys:
        - RestApiId: !Ref NaasRestApi
          StageName: !Sub ${Environment}

  CTApiKey:
    Type: AWS::ApiGateway::ApiKey
    Condition: IsMainPipeline
    DependsOn: RestApiStage
    Properties:
      Name: !Sub "${DeveloperPrefix}CT-${Environment}"
      Description: !Sub "CT API Key"
      Enabled: true
      StageKeys:
        - RestApiId: !Ref NaasRestApi
          StageName: !Sub ${Environment}

  TESTUsagePlanKey:
    Type: AWS::ApiGateway::UsagePlanKey
    Properties:
      KeyId: !Ref TESTApiKey
      KeyType: API_KEY
      UsagePlanId: !Ref TESTApiGatewayUsagePlan

  CTUsagePlanKey:
    Type: AWS::ApiGateway::UsagePlanKey
    Condition: IsMainPipeline
    Properties:
      KeyId: !Ref CTApiKey
      KeyType: API_KEY
      UsagePlanId: !Ref DefaultUsagePlan

  ################################
  # Cognito User Pools Resources #
  ################################
  NaasUserPool:
    Type: AWS::Cognito::UserPool
    Properties:
      UserPoolName: !Sub ${DeveloperPrefix}${AppName}-${Environment}-${DeployPhase}

  TESTUserPoolClient:
    Type: AWS::Cognito::UserPoolClient
    Properties:
      ClientName: 'TEST Brand'
      GenerateSecret: true
      UserPoolId: !Ref NaasUserPool

  CTUserPoolClient:
    Type: AWS::Cognito::UserPoolClient
    Condition: IsMainPipeline
    Properties:
      ClientName: 'CT'
      GenerateSecret: true
      UserPoolId: !Ref NaasUserPool

  UserPoolResourceServer:
    Type: Custom::CognitoUserPoolResourceServer
    DependsOn:
      - NaasRestApi
      - CustomResource
    Properties:
      ServiceToken: !Sub ${CustomResource.Outputs.CustomResourceLambdaFunctionArn}
      RequestTypes:
        Create:
          Service: 'com.example.naas.lambda.cloudformation.service.CognitoService'
          Method: createResourceServer
          Model: 'com.amazonaws.services.cognitoidp.model.CreateResourceServerRequest'
          Parameters:
            userPoolId: !Ref NaasUserPool
            name: NaaS
            identifier: naas
            scopes:
              - scopeName: "fraud.publish"
                scopeDescription: "Fraud Decision Change Event"
        Delete:
          Service: 'com.example.naas.lambda.cloudformation.service.CognitoService'
          Method: deleteResourceServer
          Model: 'com.amazonaws.services.cognitoidp.model.DeleteResourceServerRequest'
          Parameters:
            userPoolId: !Ref NaasUserPool
            identifier: naas
        Update:
          Service: 'com.example.naas.lambda.cloudformation.service.CognitoService'
          Method: updateResourceServer
          Model: 'com.amazonaws.services.cognitoidp.model.UpdateResourceServerRequest'

  TESTBrandUserPoolClientSettings:
    Type: Custom::CognitoUserPoolClientSettings
    DependsOn: UserPoolResourceServer
    Properties:
      ServiceToken: !Sub ${CustomResource.Outputs.CustomResourceLambdaFunctionArn}
      RequestTypes:
        Create:
          Service: 'com.example.naas.lambda.cloudformation.service.CognitoService'
          Method: updateUserPoolClientSettings
          Model: 'com.amazonaws.services.cognitoidp.model.UpdateUserPoolClientRequest'
          Parameters:
            userPoolId: !Ref NaasUserPool
            clientId: !Ref TESTUserPoolClient
            allowedOAuthFlowsUserPoolClient: true
            explicitAuthFlows:
              - 'ADMIN_NO_SRP_AUTH'
            supportedIdentityProviders:
              - COGNITO
            allowedOAuthFlows:
              - client_credentials
            allowedOAuthScopes:
              - 'naas/fraud.publish'
        Delete:
          Service: 'com.example.naas.lambda.cloudformation.service.CognitoService'
          Method: deleteUserPoolClientSettings
          Model: 'com.amazonaws.services.cognitoidp.model.DeleteUserPoolClientRequest'
          Parameters:
            userPoolId: !Ref NaasUserPool
            clientId: !Ref TESTUserPoolClient
        Update:
          Service: 'com.example.naas.lambda.cloudformation.service.CognitoService'
          Method: updateUserPoolClientSettings
          Model: 'com.amazonaws.services.cognitoidp.model.UpdateUserPoolClientRequest'

  CTUserPoolClientSettings:
    Type: Custom::CognitoUserPoolClientSettings
    Condition: IsMainPipeline
    DependsOn: UserPoolResourceServer
    Properties:
      ServiceToken: !Sub ${CustomResource.Outputs.CustomResourceLambdaFunctionArn}
      RequestTypes:
        Create:
          Service: 'com.example.naas.lambda.cloudformation.service.CognitoService'
          Method: updateUserPoolClientSettings
          Model: 'com.amazonaws.services.cognitoidp.model.UpdateUserPoolClientRequest'
          Parameters:
            userPoolId: !Ref NaasUserPool
            clientId: !Ref CTUserPoolClient
            allowedOAuthFlowsUserPoolClient: true
            explicitAuthFlows:
              - 'ADMIN_NO_SRP_AUTH'
            supportedIdentityProviders:
              - COGNITO
            allowedOAuthFlows:
              - client_credentials
            allowedOAuthScopes:
              - 'naas/fraud.publish'
        Delete:
          Service: 'com.example.naas.lambda.cloudformation.service.CognitoService'
          Method: deleteUserPoolClientSettings
          Model: 'com.amazonaws.services.cognitoidp.model.DeleteUserPoolClientRequest'
          Parameters:
            userPoolId: !Ref NaasUserPool
            clientId: !Ref CTUserPoolClient
        Update:
          Service: 'com.example.naas.lambda.cloudformation.service.CognitoService'
          Method: updateUserPoolClientSettings
          Model: 'com.amazonaws.services.cognitoidp.model.UpdateUserPoolClientRequest'

  CognitoUserPoolDomain:
    Type: Custom::CreateCognitoUserPoolDomain
    DependsOn: CustomResource
    Properties:
      ServiceToken: !Sub ${CustomResource.Outputs.CustomResourceLambdaFunctionArn}
      RequestTypes:
        Create:
          Service: 'com.example.naas.lambda.cloudformation.service.CognitoService'
          Method: createUserPoolDomain
          Model: 'com.amazonaws.services.cognitoidp.model.CreateUserPoolDomainRequest'
          Parameters:
            domain: !Sub ${DeveloperPrefix}${AppName}-${Environment}-${DeployPhase}
            userPoolId: !Ref NaasUserPool
        Delete:
          Service: 'com.example.naas.lambda.cloudformation.service.CognitoService'
          Method: deleteUserPoolDomain
          Model: 'com.amazonaws.services.cognitoidp.model.DeleteUserPoolDomainRequest'
          Parameters:
            domain: !Sub ${DeveloperPrefix}${AppName}-${Environment}-${DeployPhase}
            userPoolId: !Ref NaasUserPool

  #################
  # SNS Resources #
  #################
  EventTopic:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: !Sub '${DeveloperPrefix}event-${Environment}-${DeployPhase}'

  ##############################
  # Third-party Role Resources #
  ##############################
  SSMRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub ${DeveloperPrefix}3rdPartySSMRole-${Environment}
      AssumeRolePolicyDocument:
        Statement:
          - Sid: ''
            Effect: Allow
            Principal:
              AWS: arn:aws:iam::431055993173:root
            Action: sts:AssumeRole
            Condition:
              Bool:
                aws:MultiFactorAuthPresent: 'true'
      Path: /
      Policies:
        - PolicyName: !Sub 3rdPartySSMRole-${Environment}
          PolicyDocument:
            Statement:
              - Sid: SSMPermissions
                Effect: Allow
                Action:
                  - ssm:DescribeDocument
                  - ssm:GetDocument
                  - ssm:GetParameter
                  - ssm:GetParameters
                  - ssm:GetParametersByPath
                  - ssm:ListCommands
                  - ssm:ListDocuments
                  - ssm:CancelCommand
                  - ssm:PutParameter
                  - ssm:DeleteParameter
                  - ssm:SendCommand
                  - ssm:AddTagsToResource
                  - ssm:RemoveTagsFromResource
                Resource: !Join ['', ['arn:aws:ssm:', !Ref 'AWS::Region', ':', !Ref 'AWS::AccountId', ':', 'parameter/', 'third-party', '/', !Ref Environment,'/', '*']]
              - Sid: SSMDescribePermissions
                Effect: Allow
                Action:
                  - ssm:DescribeParameters
                Resource: '*'
              - Sid: KMSPermissions
                Effect: Allow
                Action:
                  - kms:ListAliases
                Resource: '*'


Outputs:
  SSMRoleName:
    Value: !Ref SSMRole
  SSMRoleNameArn:
    Value: !GetAtt SSMRole.Arn

标签: amazon-web-servicesaws-lambdaamazon-cloudformationamazon-snsaws-cloudformation-custom-resource

解决方案


推荐阅读