AWSTemplateFormatVersion: 2010-09-09 Description: With this CFT you'll be able to install all relevant resources needed to setup your event based solution. Parameters: S3SourceBucket: Description: S3 Source Bucket Type: String AllowedPattern: ^[a-zA-Z0-9-]*$ DetectorName: Description: S3 Source Bucket Type: String AllowedPattern: ^[a-z]*$ DetectorEvent: Description: S3 Source Bucket Type: String AllowedPattern: ^[a-z]*$ DetectorEntity: Description: S3 Source Bucket Type: String AllowedPattern: ^[a-z]*$ FlowID: Description: Contact Flow ID Type: String AllowedPattern: ^[a-zA-Z0-9-]*$ InstanceID: Description: Amazon Connect Instance ID Type: String AllowedPattern: ^[a-zA-Z0-9-]*$ SourceNumber: Description: Claimed number in Amazon Connect Type: String AllowedPattern: ^[0-9+]*$ DynamoTable: Description: DynamoDB Table Name Type: String AllowedPattern: ^[a-zA-Z0-9-]*$ Resources: SagemakerPolicy: Type: 'AWS::IAM::Policy' Properties: PolicyName: SagemakerPolicy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - s3:GetObject - s3:PutObject - s3:DeleteObject - s3:ListBucket Resource: arn:aws:s3:::* Roles: - !Ref SagemakerRole SagemakerRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - sagemaker.amazonaws.com Action: - 'sts:AssumeRole' - Effect: Allow Principal: Service: - frauddetector.amazonaws.com Action: - 'sts:AssumeRole' Path: / ManagedPolicyArns: - 'arn:aws:iam::aws:policy/AmazonSageMakerFullAccess' - 'arn:aws:iam::aws:policy/AmazonFraudDetectorFullAccessPolicy' BlockCreditCardRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - 'sts:AssumeRole' Path: / Policies: - PolicyName: LambdaBlockCreditCardPolicy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - logs:CreateLogGroup - dynamodb:PutItem - dynamodb:Query Resource: - !Join [':', [ 'arn:aws:logs', !Ref AWS::Region, !Ref AWS::AccountId, '*' ] ] - !Join ['', [ 'arn:aws:dynamodb:', !Ref AWS::Region, ':', !Ref AWS::AccountId, ':table/', !Ref DynamoTable, "/index/*" ] ] - !Join ['', [ 'arn:aws:dynamodb:', !Ref AWS::Region, ':', !Ref AWS::AccountId, ':table/', !Ref DynamoTable ] ] - Effect: Allow Action: - logs:CreateLogStream - logs:PutLogEvents Resource: !Join ['', [ 'arn:aws:logs:', !Ref AWS::Region, ':', !Ref AWS::AccountId, ':log-group:/aws/lambda/block-credit-card:*' ] ] LambdaEventRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - 'sts:AssumeRole' Path: / Policies: - PolicyName: LambdaEventPolicy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - logs:CreateLogGroup - dynamodb:Query - connect:StartOutboundVoiceContact Resource: - !Join [':', [ 'arn:aws:logs', !Ref AWS::Region, !Ref AWS::AccountId, '*' ] ] - !Join ['', [ 'arn:aws:dynamodb:', !Ref AWS::Region, ':', !Ref AWS::AccountId, ':table/', !Ref DynamoTable, "/index/*" ] ] - !Join ['', [ 'arn:aws:dynamodb:', !Ref AWS::Region, ':', !Ref AWS::AccountId, ':table/', !Ref DynamoTable ] ] - !Join ['', [ 'arn:aws:connect:', !Ref AWS::Region, ':', !Ref AWS::AccountId, ':instance/', !Ref InstanceID, '/*' ] ] - Effect: Allow Action: - logs:CreateLogStream - logs:PutLogEvents Resource: !Join ['', [ 'arn:aws:logs:', !Ref AWS::Region, ':', !Ref AWS::AccountId, ':log-group:/aws/lambda/event-based-fraud-detection:*' ] ] - Effect: Allow Action: - frauddetector:* Resource: "*" CFNSagemakerLifeCyclePolicy: Type: AWS::SageMaker::NotebookInstanceLifecycleConfig Properties: NotebookInstanceLifecycleConfigName: fraud-detection-lfc OnStart: - Content: Fn::Base64: !Sub | #!/bin/bash sudo -u ec2-user -i <<'EOF' cd /home/ec2-user/SageMaker git clone https://github.com/aws-samples/event-based-amazon-fraud-detector.git echo '{"ENTITY_TYPE": "${DetectorEntity}","EVENT_TYPE": "${DetectorEvent}","MODEL_NAME": "${DetectorName}_model","DETECTOR_NAME": "${DetectorName}","S3_BUCKET": "${S3SourceBucket}","S3_FILE": "cnp_example_30k.csv"}' >> event-based-amazon-fraud-detector/fraud-detector-example/config.json EOF SagemakerNotebook: Type: AWS::SageMaker::NotebookInstance Properties: DirectInternetAccess: Enabled InstanceType: ml.t3.medium LifecycleConfigName: fraud-detection-lfc NotebookInstanceName: event-based-fraud-detection RoleArn: !Join [ '', [ 'arn:aws:iam::', !Ref AWS::AccountId, ':role/', !Ref SagemakerRole ] ] RootAccess: Enabled VolumeSizeInGB: 10 S3Bucket: Type: 'AWS::S3::Bucket' DeletionPolicy: Retain Properties: BucketName: !Ref S3SourceBucket EventPrediction: Type: AWS::Lambda::Function Properties: FunctionName: fraud-detection Environment: Variables: DETECTOR_NAME: !Ref DetectorName EVENT_TYPE: !Ref DetectorEvent ENTITY_TYPE: !Ref DetectorEntity FLOW_ID: !Ref FlowID INSTANCE_ID: !Ref InstanceID SOURCE_NUMBER: !Ref SourceNumber TABLE_NAME: !Ref DynamoTable Code: ZipFile: | import os import json import boto3 import uuid from datetime import datetime from boto3.dynamodb.conditions import Key, Attr connect = boto3.client('connect') dynamodb = boto3.resource('dynamodb') client = boto3.client('frauddetector') DETECTOR_NAME = os.getenv("DETECTOR_NAME") EVENT_TYPE = os.getenv("EVENT_TYPE") ENTITY_TYPE = os.getenv("ENTITY_TYPE") TABLE = dynamodb.Table(os.getenv('TABLE_NAME')) INSTANCE_ID = os.getenv("INSTANCE_ID") FLOW_ID = os.getenv("FLOW_ID") SOURCE_NUMBER = os.getenv("SOURCE_NUMBER") def call_customer(customer, card_number, amount): result_map = TABLE.query(KeyConditionExpression=Key('customer_id').eq(customer))["Items"][0] response = connect.start_outbound_voice_contact( DestinationPhoneNumber=result_map["phone_number"], ContactFlowId=FLOW_ID, InstanceId=INSTANCE_ID, SourcePhoneNumber=SOURCE_NUMBER, Attributes={ "Salutation": result_map["salutation"], "Name": result_map["last_name"], "CardNo": str(result_map["card_number"])[-4:], "Amount": str(amount), "Customer": customer } ) print("call_customer response:", response) return response def lambda_handler(event, context): print("Event from Amazon Connect:", event) try: customer = event["customer"] card_number = event["card_number"] amount = event["transaction"]["transaction_amt"] eventId = uuid.uuid1() timestamp = datetime.now().strftime("%Y-%m-%dT%H:%M:%SZ") response = client.get_event_prediction( detectorId=DETECTOR_NAME, detectorVersionId='1', eventId=str(eventId), eventTypeName=EVENT_TYPE, entities=[ { 'entityType': ENTITY_TYPE, 'entityId': str(eventId.int) }, ], eventTimestamp=timestamp, eventVariables=event["transaction"] ) prediction = response["ruleResults"][0]["outcomes"][0] if prediction == "fraud": call_customer(customer=customer, card_number=card_number, amount=amount) output = { 'statusCode': 200, 'body': "Success!", } except: output = { 'statusCode': 400, 'body': "Failure", 'metadata': "" } return output Timeout: 30 Handler: index.lambda_handler Runtime: python3.8 MemorySize: 128 Role: !Join [ '', [ 'arn:aws:iam::', !Ref AWS::AccountId, ':role/', !Ref LambdaEventRole ] ] BlockCreditCard: Type: AWS::Lambda::Function Properties: FunctionName: block-credit-card Environment: Variables: TABLE_NAME: !Ref DynamoTable Code: ZipFile: | import os import json import boto3 from boto3.dynamodb.conditions import Key, Attr dynamodb = boto3.resource('dynamodb') TABLE = dynamodb.Table(os.getenv('TABLE_NAME')) def block_credit_card(customer): result_map = TABLE.query(KeyConditionExpression=Key('customer_id').eq(customer))["Items"][0] result_map["is_blocked"] = True response = TABLE.put_item(Item=result_map) print("block_credit_card response:", response) return response def lambda_handler(event, context): print("Event from Amazon Connect:", event) try: result_map = event["Details"]["ContactData"]["Attributes"] customer = result_map["Customer"] response = block_credit_card(customer=customer) output = { 'statusCode': 200, 'body': "Success!" } except: output = { 'statusCode': 400, 'body': "Bad Request!" } return output Timeout: 30 Handler: index.lambda_handler Runtime: python3.8 MemorySize: 128 Role: !Join [ '', [ 'arn:aws:iam::', !Ref AWS::AccountId, ':role/', !Ref BlockCreditCardRole ] ] DDBTable: Type: AWS::DynamoDB::Table Properties: TableName: !Ref DynamoTable AttributeDefinitions: - AttributeName: customer_id AttributeType: S - AttributeName: card_number AttributeType: S KeySchema: - AttributeName: customer_id KeyType: HASH - AttributeName: card_number KeyType: RANGE ProvisionedThroughput: ReadCapacityUnits: 1 WriteCapacityUnits: 2