cloudformationTemplates/asyncCustomerChatUX/cloudformation.yaml [321:591]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  CreateWebsiteS3Bucket:
    Type: 'AWS::S3::Bucket'
    Properties:
      BucketName: !Ref WebsiteS3BucketName
      AccessControl: LogDeliveryWrite
      LoggingConfiguration:
        DestinationBucketName: !Ref WebsiteS3BucketName
        LogFilePrefix: 'logs/'
      PublicAccessBlockConfiguration:
        BlockPublicAcls: True
        BlockPublicPolicy: True
        IgnorePublicAcls: True
        RestrictPublicBuckets: True
      CorsConfiguration:
        CorsRules:
          -
            AllowedHeaders:
              - "*"
            AllowedMethods:
              - GET
              - POST
            AllowedOrigins:
              - "*" #!Sub "https://${CloudFrontDistribution.DomainName}"
            MaxAge: 3000

  s3BucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref CreateWebsiteS3Bucket
      PolicyDocument:
        Statement:
          - Action:
              - "s3:GetObject"
            Effect: "Allow"
            Principal:
              CanonicalUser:
                Fn::GetAtt: [ CloudFrontDistributionAccessIdentity , S3CanonicalUserId ]
            Resource:
              !Sub ${CreateWebsiteS3Bucket.Arn}/*

  CustomResourceHelper:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        S3Bucket:
          !Join
            - '.'
            - - !Ref 'AWS::Region'
              - !FindInMap [FunctionMap, Configuration, S3Bucket]
        S3Key: !Join ["", [!FindInMap [FunctionMap, Configuration, S3Key], 'custom-resource-helper.zip']]
      Description: Solution Accelerator for Amazon Connect customer side Chat
      Handler: customResourceHelper.handler
      MemorySize: 256
      Role: !GetAtt CustomResourceHelperIamRole.Arn
      Runtime: nodejs10.x
      Timeout: 300

  CustomResourceHelperIamRole:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: "Allow"
            Principal:
              Service:
                - "lambda.amazonaws.com"
            Action:
              - "sts:AssumeRole"
      Path: "/"
      Policies:
        - PolicyName: connect-chat-resource-helper
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: "Allow"
                Action:
                  - 'logs:CreateLogGroup'
                  - 'logs:CreateLogStream'
                  - 'logs:PutLogEvents'
                Resource:
                  - !Sub "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*"
              - Effect: "Allow"
                Action:
                  - "s3:PutObject"
                  - "s3:GetObject"
                  - "s3:PutObjectAcl"
                Resource:
                  - !Sub ${CreateWebsiteS3Bucket.Arn}/*
              - Effect: "Allow"
                Action:
                  - "s3:GetObject"
                Resource:
                  - !Join
                    - ''
                    - - 'arn:'
                      - !Ref 'AWS::Partition'
                      - ':s3:::'
                      - !Ref 'AWS::Region'
                      - '.'
                      - !FindInMap [FunctionMap, Configuration, S3Bucket]
                      - '/*'

  ConfigureWebsite:
    Type: Custom::LoadLambda
    DependsOn:
      - CreateWebsiteS3Bucket
    Properties:
      ServiceToken: !GetAtt CustomResourceHelper.Arn
      Region: !Ref AWS::Region
      customAction: configureWebsite
      sourceS3Bucket:
        !Join
          - '.'
          - - !Ref 'AWS::Region'
            - !FindInMap [FunctionMap, Configuration, S3Bucket]
      sourceS3key: !FindInMap [FunctionMap, Configuration, S3Key]
      destS3Bucket: !Ref WebsiteS3BucketName
      destS3KeyPrefix: contents/
      UUID: !GetAtt SolutionUuid.UUID
      data: !Ref allowAnonymousUsageMetrics
      solutionId: !FindInMap [FunctionMap, Configuration, SolutionID]

  SolutionAnonymousMetric:
    Type: "Custom::LoadLambda"
    Condition: AnonymousUsageMetrics
    Properties:
      ServiceToken: !GetAtt CustomResourceHelper.Arn
      Region: !Ref AWS::Region
      solutionId: !FindInMap ["FunctionMap", "Configuration", "SolutionID"]
      UUID: !GetAtt SolutionUuid.UUID
      version: "1"
      anonymousData: !Ref allowAnonymousUsageMetrics
      customAction: "sendMetric"

  SolutionUuid:
    Type: "Custom::LoadLambda"
    Properties:
      ServiceToken: !GetAtt CustomResourceHelper.Arn
      Region: !Ref AWS::Region
      customAction: "createUuid"

  CloudFrontDistributionAccessIdentity:
    Type: AWS::CloudFront::CloudFrontOriginAccessIdentity
    Properties:
      CloudFrontOriginAccessIdentityConfig:
        Comment: 'CloudFront OAI for Amazon Connect Chat'

  CloudFrontDistribution:
    Type: AWS::CloudFront::Distribution
    DependsOn:
      - CustomResourceHelper
    Properties:
      DistributionConfig:
        Origins:
          - DomainName:
              !Join
              - ''
              - - !Ref WebsiteS3BucketName
                - .s3.amazonaws.com
            Id: !Ref WebsiteS3BucketName
            OriginPath: /contents
            S3OriginConfig:
              OriginAccessIdentity:
                !Join
                - ''
                - - 'origin-access-identity/cloudfront/'
                  - !Ref CloudFrontDistributionAccessIdentity
        Enabled: true
        Logging:
          Bucket: !GetAtt CreateWebsiteS3Bucket.DomainName
          Prefix: 'logs/'
          IncludeCookies: true
        Comment: CloudFront for Chat UI
        DefaultRootObject: index.html
        DefaultCacheBehavior:
          AllowedMethods:
            - DELETE
            - GET
            - HEAD
            - OPTIONS
            - PATCH
            - POST
            - PUT
          TargetOriginId: !Ref WebsiteS3BucketName
          ForwardedValues:
            QueryString: false
            Cookies:
              Forward: none
          ViewerProtocolPolicy: redirect-to-https
        PriceClass: !Ref cloudFrontPriceClass

  #### API Gateway ##### https://blog.jayway.com/2016/08/17/introduction-to-cloudformation-for-api-gateway/
  # CORS: https://bitbucket.org/snippets/spenser_filler/LenB4p

  ApiGatewayRestAPI: #DONE
    Type: AWS::ApiGateway::RestApi
    Properties:
      Name: "initiateChatConnection"
      Description: "API to initiate chat with Amazon Connect"

  LambdaApiGatewayInvokePermission: #DONE
    Type: AWS::Lambda::Permission
    Properties:
      Action: "lambda:InvokeFunction"
      FunctionName: !GetAtt InitiateChatLambda.Arn
      Principal: "apigateway.amazonaws.com"
      SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ApiGatewayRestAPI}/*"

  ApiGatewayDeployment:
    Type: AWS::ApiGateway::Deployment
    DependsOn:
      - ApiGatewayRootMethod
    Properties:
      RestApiId: !Ref ApiGatewayRestAPI
      StageName: "Prod"

  ApiGatewayRootMethod: #DONE
    Type: AWS::ApiGateway::Method
    DependsOn: LambdaApiGatewayInvokePermission
    Properties:
      AuthorizationType: "NONE"
      HttpMethod: "POST"
      Integration:
        IntegrationHttpMethod: "POST"
        Type: "AWS_PROXY"
        Uri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${InitiateChatLambda.Arn}/invocations"
        PassthroughBehavior: WHEN_NO_MATCH
      ResourceId:  !GetAtt ApiGatewayRestAPI.RootResourceId
      RestApiId: !Ref ApiGatewayRestAPI
      MethodResponses:
        - StatusCode: "200"
          ResponseParameters:
            method.response.header.Access-Control-Allow-Origin: true
          ResponseModels:
            application/json: Empty
        - StatusCode: "500"
          ResponseParameters:
            method.response.header.Access-Control-Allow-Origin: true
          ResponseModels:
            application/json: Empty

  ApiGatewayOptionsMethod: #DONE
    Type: AWS::ApiGateway::Method
    Properties:
      ResourceId: !GetAtt ApiGatewayRestAPI.RootResourceId
      RestApiId: !Ref ApiGatewayRestAPI
      AuthorizationType: NONE
      HttpMethod: OPTIONS
      Integration:
        Type: MOCK
        IntegrationResponses:
          - ResponseParameters:
              method.response.header.Access-Control-Allow-Headers: >-
                'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'
              method.response.header.Access-Control-Allow-Methods: '''POST,OPTIONS'''
              method.response.header.Access-Control-Allow-Origin: !Sub '''${CloudFrontDistribution.DomainName}'''
            ResponseTemplates:
              application/json: ''
            StatusCode: '200'
        PassthroughBehavior: NEVER
        RequestTemplates:
          application/json: '{"statusCode": 200}'
      MethodResponses:
        - ResponseModels:
            application/json: Empty
          ResponseParameters:
            method.response.header.Access-Control-Allow-Headers: true
            method.response.header.Access-Control-Allow-Methods: true
            method.response.header.Access-Control-Allow-Origin: true
          StatusCode: '200'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



cloudformationTemplates/urlPreviewForAsyncChat/cloudformation.yaml [397:666]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  CreateWebsiteS3Bucket:
    Type: 'AWS::S3::Bucket'
    Properties:
      BucketName: !Ref WebsiteS3BucketName
      AccessControl: LogDeliveryWrite
      LoggingConfiguration:
        DestinationBucketName: !Ref WebsiteS3BucketName
        LogFilePrefix: 'logs/'
      PublicAccessBlockConfiguration:
        BlockPublicAcls: True
        BlockPublicPolicy: True
        IgnorePublicAcls: True
        RestrictPublicBuckets: True
      CorsConfiguration:
        CorsRules:
          -
            AllowedHeaders:
              - "*"
            AllowedMethods:
              - GET
              - POST
            AllowedOrigins:
              - "*" #!Sub "https://${CloudFrontDistribution.DomainName}"
            MaxAge: 3000

  s3BucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref CreateWebsiteS3Bucket
      PolicyDocument:
        Statement:
          - Action:
              - "s3:GetObject"
            Effect: "Allow"
            Principal:
              CanonicalUser:
                Fn::GetAtt: [ CloudFrontDistributionAccessIdentity , S3CanonicalUserId ]
            Resource:
              !Sub ${CreateWebsiteS3Bucket.Arn}/*

  CustomResourceHelper:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        S3Bucket:
          !Join
            - '.'
            - - !Ref 'AWS::Region'
              - !FindInMap [FunctionMap, Configuration, S3Bucket]
        S3Key: !Join ["", [!FindInMap [FunctionMap, Configuration, S3Key], 'custom-resource-helper.zip']]
      Description: Solution Accelerator for Amazon Connect customer side Chat
      Handler: customResourceHelper.handler
      MemorySize: 256
      Role: !GetAtt CustomResourceHelperIamRole.Arn
      Runtime: nodejs10.x
      Timeout: 300

  CustomResourceHelperIamRole:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: "Allow"
            Principal:
              Service:
                - "lambda.amazonaws.com"
            Action:
              - "sts:AssumeRole"
      Path: "/"
      Policies:
        - PolicyName: connect-chat-resource-helper
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: "Allow"
                Action:
                  - 'logs:CreateLogGroup'
                  - 'logs:CreateLogStream'
                  - 'logs:PutLogEvents'
                Resource:
                  - !Sub "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*"
              - Effect: "Allow"
                Action:
                  - "s3:PutObject"
                  - "s3:GetObject"
                  - "s3:PutObjectAcl"
                Resource:
                  - !Sub ${CreateWebsiteS3Bucket.Arn}/*
              - Effect: "Allow"
                Action:
                  - "s3:GetObject"
                Resource:
                  - !Join
                    - ''
                    - - 'arn:'
                      - !Ref 'AWS::Partition'
                      - ':s3:::'
                      - !Ref 'AWS::Region'
                      - '.'
                      - !FindInMap [FunctionMap, Configuration, S3Bucket]
                      - '/*'

  ConfigureWebsite:
    Type: Custom::LoadLambda
    DependsOn:
      - CreateWebsiteS3Bucket
    Properties:
      ServiceToken: !GetAtt CustomResourceHelper.Arn
      Region: !Ref AWS::Region
      customAction: configureWebsite
      sourceS3Bucket:
        !Join
          - '.'
          - - !Ref 'AWS::Region'
            - !FindInMap [FunctionMap, Configuration, S3Bucket]
      sourceS3key: !FindInMap [FunctionMap, Configuration, S3Key]
      destS3Bucket: !Ref WebsiteS3BucketName
      destS3KeyPrefix: contents/
      UUID: !GetAtt SolutionUuid.UUID
      data: !Ref allowAnonymousUsageMetrics
      solutionId: !FindInMap [FunctionMap, Configuration, SolutionID]

  SolutionAnonymousMetric:
    Type: "Custom::LoadLambda"
    Condition: AnonymousUsageMetrics
    Properties:
      ServiceToken: !GetAtt CustomResourceHelper.Arn
      Region: !Ref AWS::Region
      solutionId: !FindInMap ["FunctionMap", "Configuration", "SolutionID"]
      UUID: !GetAtt SolutionUuid.UUID
      version: "1"
      anonymousData: !Ref allowAnonymousUsageMetrics
      customAction: "sendMetric"

  SolutionUuid:
    Type: "Custom::LoadLambda"
    Properties:
      ServiceToken: !GetAtt CustomResourceHelper.Arn
      Region: !Ref AWS::Region
      customAction: "createUuid"

  CloudFrontDistributionAccessIdentity:
    Type: AWS::CloudFront::CloudFrontOriginAccessIdentity
    Properties:
      CloudFrontOriginAccessIdentityConfig:
        Comment: 'CloudFront OAI for Amazon Connect Chat'

  CloudFrontDistribution:
    Type: AWS::CloudFront::Distribution
    DependsOn:
      - CustomResourceHelper
    Properties:
      DistributionConfig:
        Origins:
          - DomainName:
              !Join
              - ''
              - - !Ref WebsiteS3BucketName
                - .s3.amazonaws.com
            Id: !Ref WebsiteS3BucketName
            OriginPath: /contents
            S3OriginConfig:
              OriginAccessIdentity:
                !Join
                - ''
                - - 'origin-access-identity/cloudfront/'
                  - !Ref CloudFrontDistributionAccessIdentity
        Enabled: true
        Logging:
          Bucket: !GetAtt CreateWebsiteS3Bucket.DomainName
          Prefix: 'logs/'
          IncludeCookies: true
        Comment: CloudFront for Chat UI
        DefaultRootObject: index.html
        DefaultCacheBehavior:
          AllowedMethods:
            - DELETE
            - GET
            - HEAD
            - OPTIONS
            - PATCH
            - POST
            - PUT
          TargetOriginId: !Ref WebsiteS3BucketName
          ForwardedValues:
            QueryString: false
            Cookies:
              Forward: none
          ViewerProtocolPolicy: redirect-to-https
        PriceClass: !Ref cloudFrontPriceClass

  #### API Gateway ####

  ApiGatewayRestAPI: 
    Type: AWS::ApiGateway::RestApi
    Properties:
      Name: "initiateChatConnection"
      Description: "API to initiate chat with Amazon Connect"

  LambdaApiGatewayInvokePermission: 
    Type: AWS::Lambda::Permission
    Properties:
      Action: "lambda:InvokeFunction"
      FunctionName: !GetAtt InitiateChatLambda.Arn
      Principal: "apigateway.amazonaws.com"
      SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ApiGatewayRestAPI}/*"

  ApiGatewayDeployment:
    Type: AWS::ApiGateway::Deployment
    DependsOn:
      - ApiGatewayRootMethod
    Properties:
      RestApiId: !Ref ApiGatewayRestAPI
      StageName: "Prod"

  ApiGatewayRootMethod: 
    Type: AWS::ApiGateway::Method
    DependsOn: LambdaApiGatewayInvokePermission
    Properties:
      AuthorizationType: "NONE"
      HttpMethod: "POST"
      Integration:
        IntegrationHttpMethod: "POST"
        Type: "AWS_PROXY"
        Uri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${InitiateChatLambda.Arn}/invocations"
        PassthroughBehavior: WHEN_NO_MATCH
      ResourceId:  !GetAtt ApiGatewayRestAPI.RootResourceId
      RestApiId: !Ref ApiGatewayRestAPI
      MethodResponses:
        - StatusCode: "200"
          ResponseParameters:
            method.response.header.Access-Control-Allow-Origin: true
          ResponseModels:
            application/json: Empty
        - StatusCode: "500"
          ResponseParameters:
            method.response.header.Access-Control-Allow-Origin: true
          ResponseModels:
            application/json: Empty

  ApiGatewayOptionsMethod: 
    Type: AWS::ApiGateway::Method
    Properties:
      ResourceId: !GetAtt ApiGatewayRestAPI.RootResourceId
      RestApiId: !Ref ApiGatewayRestAPI
      AuthorizationType: NONE
      HttpMethod: OPTIONS
      Integration:
        Type: MOCK
        IntegrationResponses:
          - ResponseParameters:
              method.response.header.Access-Control-Allow-Headers: >-
                'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'
              method.response.header.Access-Control-Allow-Methods: '''POST,OPTIONS'''
              method.response.header.Access-Control-Allow-Origin: !Sub '''${CloudFrontDistribution.DomainName}'''
            ResponseTemplates:
              application/json: ''
            StatusCode: '200'
        PassthroughBehavior: NEVER
        RequestTemplates:
          application/json: '{"statusCode": 200}'
      MethodResponses:
        - ResponseModels:
            application/json: Empty
          ResponseParameters:
            method.response.header.Access-Control-Allow-Headers: true
            method.response.header.Access-Control-Allow-Methods: true
            method.response.header.Access-Control-Allow-Origin: true
          StatusCode: '200'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



