# MIT No Attribution # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # Permission is hereby granted, free of charge, to any person obtaining a copy of this # software and associated documentation files (the "Software"), to deal in the Software # without restriction, including without limitation the rights to use, copy, modify, # merge, publish, distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. AWSTemplateFormatVersion: 2010-09-09 Description: > "CloudFormation for re:Invent 2022 - BIZ310 - Real-time churn prediction in AI powered contact centres - Lambdas, Kinesis, API Gateway, EventBridge, Step Functions, DynamoDB tables, Lex, S3 Bucket, and CloudFront Distribution" Parameters: AmazonConnectInstanceARN: Default: "**** Enter the Full Amazon Connect Instance ARN ****" Description: The Amazon Connect Instance ARN Type: String SageMakerFeatureGroupName: Default: "fg-contact-center-data" Description: The Amazon SageMaker Feature Group Name Type: String SageMakerEndPointName: Default: "sagemaker-endpoint-xgboost-customerchurn" Description: The Amazon SageMaker Endpoint Name Type: String CustomerProfilesDomain: Default: "**** Enter the Customer Profiles Domain ****" Description: The Amazon Connect Customers Profile Domain (amazon-connect-[alias]) Type: String EmailForNotifications: Default: "**** Enter an email address for Contact Lens Notifications ****" Description: Email for Contact Lens Notification Type: String S3bucketWorkshopFiles: Default: "**** Enter the S3 bucket where the Workshop Files were uploaded ****" Description: S3Bucket with Workshop Files Type: String KMSforSNS: Default: "**** KMS ID for SNS ****" Description: Enter the KMS ID for SNS Type: String # API Gateway URLs, Queue Retention ARN, and LexV2Bot ARN to be used in the Website Outputs: apiGatewayInvokeURLchurn: Description: API Endpoint to capture Churn updates Value: !Sub https://${reInvent2022AgentInterfaceRestApi}.execute-api.${AWS::Region}.amazonaws.com/prod apiGatewayInvokeURLcontract: Description: API Endpoint to update contracted months Value: !Sub https://${reInvent2022AgentInterfaceRestApi}.execute-api.${AWS::Region}.amazonaws.com/prod/update LexV2BotARN: Description: The ARN of the LexV2 Bot Value: !GetAtt IVR.Arn CloudfrontEndpoint: Description: Endpoint for Custom CCP distribution Value: !Join - '' - - 'https://' - !GetAtt [CFCloudFrontDistribution, DomainName] CustomCCPS3Bucket: Description: Bucket for the CustomCCP Website Value: !Ref createCustomCCPS3Bucket Resources: # Sentiments DynamoDB Table, partition key contact Id SentimentsDDBTable: Type: AWS::DynamoDB::Table Properties: AttributeDefinitions: - AttributeName: ContactId AttributeType: S KeySchema: - AttributeName: ContactId KeyType: HASH ProvisionedThroughput: ReadCapacityUnits: 5 WriteCapacityUnits: 5 TableName: reInvent2022-Sentiments TimeToLiveSpecification: AttributeName: ttl Enabled: true # Contacts ID DynamoDB Table, store customer ID per contact ID ContactIdsDDBTable: Type: AWS::DynamoDB::Table Properties: AttributeDefinitions: - AttributeName: ContactId AttributeType: S KeySchema: - AttributeName: ContactId KeyType: HASH ProvisionedThroughput: ReadCapacityUnits: 5 WriteCapacityUnits: 5 TableName: reInvent2022-ContactIds TimeToLiveSpecification: AttributeName: ttl Enabled: true # Churn prediction table storing all the predictions per contact ID, # partition key Contact ID and sort key Time ChurnPredictionDDBTable: Type: AWS::DynamoDB::Table Properties: AttributeDefinitions: - AttributeName: ContactId AttributeType: S - AttributeName: When AttributeType: S KeySchema: - AttributeName: ContactId KeyType: HASH - AttributeName: When KeyType: RANGE ProvisionedThroughput: ReadCapacityUnits: 5 WriteCapacityUnits: 5 TableName: reInvent2022-ChurnPrediction TimeToLiveSpecification: AttributeName: ttl Enabled: true # IAM Role for Lambda functions LambdasIAMRole: Type: "AWS::IAM::Role" DependsOn: - ChurnPredictionDDBTable - ContactIdsDDBTable - SentimentsDDBTable Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - "sts:AssumeRole" Description: A role to allow all the functions in the re:Invent2022 BIZ310 Project Policies: - PolicyName: reInvent2022role PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - dynamodb:GetItem - dynamodb:UpdateItem - dynamodb:PutItem - dynamodb:PartiQLSelect Resource: - !GetAtt ContactIdsDDBTable.Arn - !GetAtt ChurnPredictionDDBTable.Arn - !GetAtt SentimentsDDBTable.Arn - Effect: Allow Action: - profile:SearchProfiles - profile:UpdateProfile Resource: - !Sub arn:aws:profile:${AWS::Region}:${AWS::AccountId}:domains/${CustomerProfilesDomain} - Effect: Allow Action: - connect:AssociateInstanceStorageConfig - connect:UpdateContactAttributes Resource: - !Ref AmazonConnectInstanceARN - !Sub ${AmazonConnectInstanceARN}/* - Effect: Allow Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents - sagemaker:* - kinesis:* - iam:PutRolePolicy Resource: "*" - Effect: Allow Action: - states:StartExecution Resource: - !Sub arn:aws:states:${AWS::Region}:${AWS::AccountId}:stateMachine:ContractCancelled # IAM Service Link Role for Lex LexServiceLinkRole: Type: 'AWS::IAM::ServiceLinkedRole' Properties: AWSServiceName: lexv2.amazonaws.com Description: AWSServiceRoleForLexV2Bots CustomSuffix: reInvent2022 # IAM Role for Step Functions StepsIAMRole: Type: 'AWS::IAM::Role' Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: !Sub 'states.${AWS::Region}.amazonaws.com' Action: 'sts:AssumeRole' Policies: - PolicyName: ConnectTasksAPI PolicyDocument: Statement: - Effect: Allow Action: - connect:StartTaskContact Resource: - !Sub ${AmazonConnectInstanceARN}/* - Effect: Allow Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Resource: "*" # SNS Topic to send email with notification about negative sentiment SNSforNegativeSentiment: Type: AWS::SNS::Topic Properties: TopicName: NegativeSentiment KmsMasterKeyId: !Ref KMSforSNS # SNS Policy for Event Bridge SNSpolicyforEventBridge: Type: AWS::SNS::TopicPolicy Properties: PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: - events.amazonaws.com Action: - sns:Publish Resource: - !Ref 'SNSforNegativeSentiment' Topics: - !Ref 'SNSforNegativeSentiment' # Subscription to send email with negative sentiment EmailSubscription: Type: AWS::SNS::Subscription Properties: Protocol: email Endpoint: !Ref EmailForNotifications TopicArn: !Ref 'SNSforNegativeSentiment' # EventBridge Rule to capture Negative Sentiment based on Contact Lens Events NegSentimentEventBridgeRule: Type: AWS::Events::Rule Properties: Description: Rule to capture Negative Sentiment based on Contact Lens Events EventBusName: default EventPattern: source: - aws.connect detail-type: - "Contact Lens Realtime Rules Matched" detail: actionName: - "LongNegativeSentiment" State: ENABLED Targets: - Arn: !Ref SNSforNegativeSentiment Id: Id1234 InputTransformer: InputPathsMap: Region: "$.region" ContactArn: "$.detail.contactArn" RuleName: "$.detail.ruleName" Time: "$.time" InputTemplate: | "There is a call in with , customer has been experiencing negative sentiment since