### # Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. # # Licensed under the Apache License Version 2.0 (the 'License'). # You may not use this file except in compliance with the License. # A copy of the License is located at # # http://www.apache.org/licenses/ # # or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express or implied. See the License for the # specific language governing permissions and limitations under the License. # ## service: aws-connect-vm plugins: - serverless-prune-plugin custom: config: ${file(env/${self:provider.stage}-${self:provider.region}.yml)} authorizers: custom-roles: name: Authorizer identitySource: method.request.header.Authorization identityValidationExpression: Bearer (.*) type: TOKEN package: exclude: - "target/**" - "src/**" - "tests/**" - "tools/**" - "mock/**" - "env/**" provider: name: aws runtime: nodejs16.x versionFunctions: false stage: ${opt:stage, 'prod'} region: ${opt:region, 'us-east-1'} timeout: 30 functions: ContactVoicemailStream: handler: handler/voicemail.stream role: ContactVoicemailStreamIamRole description: > AWS Lambda Function that will be triggered when records are written into the ContactVoicemail Table. events: - stream: type: dynamodb arn: !GetAtt ContactVoicemailTable.StreamArn environment: USERS_TABLE_NAME: !Ref UsersTable AMAZON_CONNECT_INSTANCE_ARN: !Ref AmazonConnectInstanceArn GLOBAL_TABLE_NAME: !Ref GlobalTable CONTACT_VOICEMAIL_TABLE_NAME: !Ref ContactVoicemailTable SIGNED_RECORDING_URL_EXP: !Ref SignedRecordingUrlExpiration DELIVERY_EMAIL: !Ref DeliveryEmail AVAILABLE_SMS_COUNTRIES: !Ref AvailableSMSCountries SECRET_ARN: !Ref VoicemailSecret TranscriptionEvents: handler: handler/transcription.process role: TranscriptionEventsIamRole description: > AWS Lambda Function that will be triggered when transcription status changes. events: - cloudwatchEvent: event: source: - "aws.transcribe" detail-type: - "Transcribe Job State Change" detail: TranscriptionJobStatus: - COMPLETED - FAILED environment: USERS_TABLE_NAME: !Ref UsersTable AMAZON_CONNECT_INSTANCE_ARN: !Ref AmazonConnectInstanceArn GLOBAL_TABLE_NAME: !Ref GlobalTable CONTACT_VOICEMAIL_TABLE_NAME: !Ref ContactVoicemailTable SIGNED_RECORDING_URL_EXP: !Ref SignedRecordingUrlExpiration AVAILABLE_SMS_COUNTRIES: !Ref AvailableSMSCountries SECRET_ARN: !Ref VoicemailSecret GetAgentByExtension: description: > AWS Lambda Function that will be triggered when dialog flow needs to get agent's information based on phone extension handler: handler/agents.getAgentByExtension role: GetAgentByExtensionIamRole environment: USERS_TABLE_NAME: !Ref UsersTable AMAZON_CONNECT_INSTANCE_ARN: !Ref AmazonConnectInstanceArn CognitoUsersConfig: handler: handler/cognito.usersConfig role: CognitoUsersConfigIamRole environment: AMAZON_CONNECT_INSTANCE_ARN: !Ref AmazonConnectInstanceArn GLOBAL_TABLE_NAME: !Ref GlobalTable AVAILABLE_SMS_COUNTRIES: !Ref AvailableSMSCountries COGNITO_USER_POOL_ID: !Ref CognitoUserPoolUserPool DELIVERY_EMAIL: !Ref DeliveryEmail Authorizer: handler: handler/authorizer.handler role: AuthorizerIamRole environment: COGNITO_USER_POOL_ID: !Ref CognitoUserPoolUserPool APP_REGION: !Ref AWS::Region AgentsGet: handler: handler/agents.getAgents role: AgentsGetIamRole events: - http: method: get cors: true path: agents authorizer: ${self:custom.authorizers.custom-roles} environment: USERS_TABLE_NAME: !Ref UsersTable AMAZON_CONNECT_INSTANCE_ARN: !Ref AmazonConnectInstanceArn AgentsUpdateById: handler: handler/agents.updateAgentById role: AgentsUpdateByIdIamRole events: - http: method: post cors: true path: agents/{agentId} authorizer: ${self:custom.authorizers.custom-roles} environment: USERS_TABLE_NAME: !Ref UsersTable AMAZON_CONNECT_INSTANCE_ARN: !Ref AmazonConnectInstanceArn AgentsGetById: handler: handler/agents.getAgentById role: AgentsGetByIdIamRole events: - http: method: get cors: true path: agents/{agentId} authorizer: ${self:custom.authorizers.custom-roles} environment: USERS_TABLE_NAME: !Ref UsersTable AMAZON_CONNECT_INSTANCE_ARN: !Ref AmazonConnectInstanceArn GlobalSettingsUpdate: handler: handler/global-settings.update role: GlobalSettingsUpdateIamRole events: - http: method: post cors: true path: global/settings authorizer: ${self:custom.authorizers.custom-roles} environment: GLOBAL_TABLE_NAME: !Ref GlobalTable AVAILABLE_SMS_COUNTRIES: !Ref AvailableSMSCountries AMAZON_CONNECT_INSTANCE_ARN: !Ref AmazonConnectInstanceArn GlobalSettingsGet: handler: handler/global-settings.get role: GlobalSettingsGetIamRole events: - http: method: get cors: true path: global/settings authorizer: ${self:custom.authorizers.custom-roles} environment: GLOBAL_TABLE_NAME: !Ref GlobalTable AVAILABLE_SMS_COUNTRIES: !Ref AvailableSMSCountries AMAZON_CONNECT_INSTANCE_ARN: !Ref AmazonConnectInstanceArn BuildContactFlow: handler: handler/contact-flow.build role: BuildContactFlowIamRole events: - http: method: post cors: true path: contact/flow authorizer: ${self:custom.authorizers.custom-roles} environment: GET_AGENT_BY_EXTENSION_LAMBDA_ARN: !Sub "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${GetAgentByExtensionLambdaFunction}" AMAZON_CONNECT_INSTANCE_ARN: !Ref AmazonConnectInstanceArn SOLUTION_ID: !Ref SolutionId UUID: !Ref Uuid SEND_ANON_DATA: !Ref SendAnonymousData KvsProcessRecording: handler: "com.amazonaws.kvstream.KVSProcessRecordingLambda::handleRequest" role: KvsProcessRecordingIamRole timeout: 900 runtime: java8.al2 package: individually: true artifact: "target/${self:service}-java.jar" description: > Process recording via CTR events: - stream: type: kinesis arn: !GetAtt DataStream.Arn batchWindow: 1 environment: START_SELECTOR_TYPE: FRAGMENT_NUMBER TRANSCRIBE_REGION: !Ref AWS::Region RECORDINGS_KEY_PREFIX: "recordings/" RECORDINGS_BUCKET_NAME: !Ref AudioRecordingsBucket INPUT_KEY_PREFIX: "audio-file-input/" LOG_RECORDS_FLAG: "TRUE" RECORDINGS_PUBLIC_READ_ACL: "FALSE" APP_REGION: !Ref AWS::Region CONTACT_VOICEMAIL_TABLE_NAME: !Ref ContactVoicemailTable SOLUTION_ID: !Ref SolutionId UUID: !Ref Uuid SEND_ANON_DATA: !Ref SendAnonymousData ConnectSyncRequest: handler: handler/sync-vm-connect.syncRequestHandler role: ConnectSyncRequestIamRole timeout: 60 events: - http: method: post cors: true path: agents/sync authorizer: ${self:custom.authorizers.custom-roles} environment: USERS_TABLE_NAME: !Ref UsersTable AMAZON_CONNECT_INSTANCE_ARN: !Ref AmazonConnectInstanceArn SOLUTION_ID: !Ref SolutionId UUID: !Ref Uuid SEND_ANON_DATA: !Ref SendAnonymousData ConnectSync: handler: handler/sync-vm-connect.syncHandler role: ConnectSyncIamRole timeout: 900 events: - schedule: cron(0 0 * * ? *) environment: USERS_TABLE_NAME: !Ref UsersTable AMAZON_CONNECT_INSTANCE_ARN: !Ref AmazonConnectInstanceArn SOLUTION_ID: !Ref SolutionId UUID: !Ref Uuid SEND_ANON_DATA: !Ref SendAnonymousData resources: Description: Amazon Connect Voicemail Stack Parameters: AmazonConnectInstanceArn: Type: String Default: ${self:custom.config.AMAZON_CONNECT_INSTANCE_ARN, ""} Description: The ARN of your Amazon Connect Instance DataStreamRetention: Description: Data Stream Retention in Hours Default: 24 Type: Number DataStreamShardCount: Description: Number of shards for the Data Stream Default: 1 Type: Number DeliveryEmail: Description: Transcription delivery email. Make sure this email is verified Default: ${self:custom.config.DELIVERY_EMAIL, ""} Type: String AvailableSMSCountries: Default: ${self:custom.config.AVAILABLE_SMS_COUNTRIES, "us"} Type: String AdminEmail: Default: ${self:custom.config.ADMIN_EMAIL, ""} Type: String AdminFirstName: Default: ${self:custom.config.ADMIN_FIRST_NAME, ""} Type: String AdminLastName: Default: ${self:custom.config.ADMIN_LAST_NAME, ""} Type: String ManagerEmail: Default: ${self:custom.config.MANAGER_EMAIL, ""} Type: String ManagerFirstName: Default: ${self:custom.config.MANAGER_FIRST_NAME, ""} Type: String ManagerLastName: Default: ${self:custom.config.MANAGER_LAST_NAME, ""} Type: String SignedRecordingUrlExpiration: Default: ${self:custom.config.SIGNED_RECORDING_URL_EXP, "900"} Type: String UserPoolDomainName: Default: ${self:custom.config.USER_POOL_DOMAIN, ""} Type: String SolutionId: Default: ${self:custom.config.SOLUTION_ID, ""} Type: String Uuid: Default: ${self:custom.config.UUID, ""} Type: String VoicemailAccessLogBucket: Default: "VoicemailAccessLogBucket" Type: String SendAnonymousData: Default: ${self:customer.config.SEND_ANON_DATA, ""} Type: String IsSamlInstance: Default: false Type: String AllowedValues: [true, false] Resources: # Cognito CognitoUserPoolUserPool: Type: AWS::Cognito::UserPool Properties: UsernameAttributes: - email Schema: - AttributeDataType: String Mutable: true Name: roles - AttributeDataType: String Name: email Mutable: !Ref IsSamlInstance Required: true AdminCreateUserConfig: AllowAdminCreateUserOnly: true UserPoolAddOns: AdvancedSecurityMode: ENFORCED UserPoolDomain: Type: AWS::Cognito::UserPoolDomain Properties: Domain: !Ref UserPoolDomainName UserPoolId: !Ref CognitoUserPoolUserPool UserPoolAdminGroup: Type: AWS::Cognito::UserPoolGroup Properties: GroupName: Admin UserPoolId: !Ref CognitoUserPoolUserPool UserPoolManagerGroup: Type: AWS::Cognito::UserPoolGroup Properties: GroupName: Manager UserPoolId: !Ref CognitoUserPoolUserPool AmazonConnectGetAgentLambdaRights: Type: AWS::Lambda::Permission Properties: FunctionName: Ref: GetAgentByExtensionLambdaFunction Action: lambda:InvokeFunction Principal: connect.amazonaws.com CognitoUsersConfig: Type: Custom::CognitoUsersConfig DependsOn: - CognitoUserPoolUserPool Properties: ServiceToken: Fn::GetAtt: [CognitoUsersConfigLambdaFunction, Arn] UUID: ${file(src/lib/uuid.js)} AdminEmail: !Ref AdminEmail AdminFirstName: !Ref AdminFirstName AdminLastName: !Ref AdminLastName ManagerEmail: !Ref ManagerEmail ManagerFirstName: !Ref ManagerFirstName ManagerLastName: !Ref ManagerLastName # Tables UsersTable: Type: AWS::DynamoDB::Table Properties: AttributeDefinitions: - AttributeName: agentId AttributeType: S - AttributeName: extension AttributeType: S KeySchema: - AttributeName: agentId KeyType: HASH BillingMode: PAY_PER_REQUEST GlobalSecondaryIndexes: - IndexName: AgentExtensionIndex KeySchema: - AttributeName: extension KeyType: HASH Projection: ProjectionType: ALL PointInTimeRecoverySpecification: PointInTimeRecoveryEnabled: True SSESpecification: SSEEnabled: True GlobalTable: Type: AWS::DynamoDB::Table Properties: AttributeDefinitions: - AttributeName: instanceArn AttributeType: S KeySchema: - AttributeName: instanceArn KeyType: HASH BillingMode: PAY_PER_REQUEST PointInTimeRecoverySpecification: PointInTimeRecoveryEnabled: True SSESpecification: SSEEnabled: True ContactVoicemailTable: Type: AWS::DynamoDB::Table Properties: AttributeDefinitions: - AttributeName: contactId AttributeType: S - AttributeName: readerId AttributeType: S - AttributeName: assigneeId AttributeType: S KeySchema: - AttributeName: contactId KeyType: HASH - AttributeName: readerId KeyType: RANGE BillingMode: PAY_PER_REQUEST SSESpecification: SSEEnabled: True PointInTimeRecoverySpecification: PointInTimeRecoveryEnabled: True StreamSpecification: StreamViewType: NEW_AND_OLD_IMAGES GlobalSecondaryIndexes: - IndexName: AssigneeIdIndex KeySchema: - AttributeName: assigneeId KeyType: HASH Projection: ProjectionType: ALL # Kinesis DataStream: Type: AWS::Kinesis::Stream Properties: RetentionPeriodHours: !Ref DataStreamRetention ShardCount: !Ref DataStreamShardCount StreamEncryption: EncryptionType: KMS KeyId: alias/aws/kinesis # Bucket AudioRecordingsBucket: Type: AWS::S3::Bucket Properties: AccessControl: LogDeliveryWrite VersioningConfiguration: Status: Enabled OwnershipControls: Rules: - ObjectOwnership: BucketOwnerPreferred PublicAccessBlockConfiguration: BlockPublicAcls: True BlockPublicPolicy: True IgnorePublicAcls: True RestrictPublicBuckets: True BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: SSEAlgorithm: AES256 CorsConfiguration: CorsRules: - AllowedOrigins: - "*" AllowedHeaders: - "*" AllowedMethods: - PUT - HEAD MaxAge: "3000" LoggingConfiguration: DestinationBucketName: !Ref VoicemailAccessLogBucket LogFilePrefix: "audio-recording-bucket-logs" # Log Group ApiAccessLogGroup: Type: AWS::Logs::LogGroup ApiGwIamRole: Type: AWS::IAM::Role Properties: Path: / AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: - apigateway.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - "arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs" ApiGwAccountConfig: Type: "AWS::ApiGateway::Account" Properties: CloudWatchRoleArn: !GetAtt "ApiGwIamRole.Arn" # IAM Permissions ContactVoicemailStreamIamRole: DependsOn: - VoicemailSecret Type: AWS::IAM::Role Properties: Path: / AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: ContactVoicemailStreamPolicy 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: - ses:SendRawEmail Resource: "*" - Effect: Allow Action: - sns:Publish NotResource: "arn:aws:sns:*:*:*" - Effect: Allow Action: - transcribe:GetTranscriptionJob Resource: "*" - Effect: Allow Action: - dynamodb:DescribeStream - dynamodb:GetRecords - dynamodb:GetShardIterator - dynamodb:ListStreams Resource: - !GetAtt ContactVoicemailTable.StreamArn - Effect: Allow Action: - dynamodb:GetItem Resource: - !GetAtt GlobalTable.Arn - !GetAtt UsersTable.Arn - Effect: Allow Action: - connect:DescribeUser Resource: Fn::Join: - "" - - !Ref AmazonConnectInstanceArn - "/agent/*" - Effect: Allow Action: - s3:GetObject - s3:GetSignedUrl Resource: Fn::Join: - "" - - !GetAtt AudioRecordingsBucket.Arn - "/*" - Effect: Allow Action: - secretsmanager:GetSecretValue Resource: !Ref VoicemailSecret TranscriptionEventsIamRole: Type: AWS::IAM::Role Properties: Path: / AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: TranscriptionEventsPolicy 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: - dynamodb:Query - dynamodb:UpdateItem Resource: !GetAtt ContactVoicemailTable.Arn - Effect: Allow Action: - secretsmanager:GetSecretValue Resource: !Ref VoicemailSecret GetAgentByExtensionIamRole: Type: AWS::IAM::Role Properties: Path: / AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: GetAgentByExtensionPolicy 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: - dynamodb:Query Resource: Fn::Join: - "" - - !GetAtt UsersTable.Arn - "/index/*" - Effect: Allow Action: - connect:ListUsers - connect:DescribeUser Resource: - !Ref AmazonConnectInstanceArn - Fn::Join: - "" - - !Ref AmazonConnectInstanceArn - "/agent/*" CognitoUsersConfigIamRole: Type: AWS::IAM::Role Properties: Path: / AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: CognitoUsersConfigPolicy 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: - cognito-idp:AdminCreateUser - cognito-idp:AdminDeleteUser - cognito-idp:AdminGetUser - cognito-idp:AdminAddUserToGroup Resource: !GetAtt CognitoUserPoolUserPool.Arn - Effect: Allow Action: - dynamodb:PutItem Resource: - !GetAtt GlobalTable.Arn AuthorizerIamRole: Type: AWS::IAM::Role Properties: Path: / AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: AuthorizerPolicy 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/*" AgentsGetIamRole: Type: AWS::IAM::Role Properties: Path: / AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: AgentsGetPolicy 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: - dynamodb:Scan Resource: - !GetAtt UsersTable.Arn AgentsUpdateByIdIamRole: Type: AWS::IAM::Role Properties: Path: / AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: AgentsUpdateByIdPolicy 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: - dynamodb:GetItem - dynamodb:PutItem - dynamodb:Query - dynamodb:UpdateItem Resource: - !GetAtt UsersTable.Arn - Fn::Join: - "" - - !GetAtt UsersTable.Arn - "/index/*" - Effect: Allow Action: - connect:DescribeUser Resource: Fn::Join: - "" - - !Ref AmazonConnectInstanceArn - "/agent/*" AgentsGetByIdIamRole: Type: AWS::IAM::Role Properties: Path: / AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: AgentsGetByIdPolicy 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: - dynamodb:GetItem - dynamodb:PutItem Resource: - !GetAtt UsersTable.Arn - Effect: Allow Action: - connect:ListUsers - connect:DescribeUser Resource: Fn::Join: - "" - - !Ref AmazonConnectInstanceArn - "/agent/*" GlobalSettingsUpdateIamRole: Type: AWS::IAM::Role Properties: Path: / AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: GlobalSettingsUpdatePolicy 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: - dynamodb:GetItem - dynamodb:PutItem - dynamodb:UpdateItem Resource: - !GetAtt GlobalTable.Arn GlobalSettingsGetIamRole: Type: AWS::IAM::Role Properties: Path: / AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: GlobalSettingsGetPolicy 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: - dynamodb:GetItem Resource: - !GetAtt GlobalTable.Arn BuildContactFlowIamRole: Type: AWS::IAM::Role Properties: Path: / AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: BuildContactFlowPolicy 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: - connect:ListQueues Resource: Fn::Join: - "" - - !Ref AmazonConnectInstanceArn - "/queue/*" KvsProcessRecordingIamRole: Type: AWS::IAM::Role Properties: Path: / AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: KvsProcessRecordingPolicy 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: - transcribe:GetTranscriptionJob - transcribe:StartTranscriptionJob Resource: "*" - Effect: Allow Action: - kinesis:GetMedia - kinesis:GetRecords - kinesis:GetShardIterator - kinesis:DescribeStream - kinesis:ListStreams Resource: !GetAtt DataStream.Arn - Effect: Allow Action: - dynamodb:PutItem Resource: !GetAtt ContactVoicemailTable.Arn - Effect: Allow Action: - s3:PutObject - s3:GetObject - s3:PutObjectAcl Resource: Fn::Join: - "" - - !GetAtt AudioRecordingsBucket.Arn - "/*" - Effect: Allow Action: - kinesisvideo:GetMedia - kinesisvideo:GetDataEndpoint Resource: "*" ConnectSyncRequestIamRole: Type: AWS::IAM::Role Properties: Path: / AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: ConnectSyncRequestPolicy 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: - dynamodb:Scan - dynamodb:BatchWriteItem Resource: - !GetAtt UsersTable.Arn - Effect: Allow Action: - connect:ListUsers Resource: !Ref AmazonConnectInstanceArn ConnectSyncIamRole: Type: AWS::IAM::Role Properties: Path: / AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: ConnectSyncPolicy 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: - dynamodb:Scan - dynamodb:BatchWriteItem Resource: - !GetAtt UsersTable.Arn - Effect: Allow Action: - connect:ListUsers Resource: !Ref AmazonConnectInstanceArn VoicemailIamUser: DependsOn: - VoicemailIamUserGroup Type: AWS::IAM::User Properties: Groups: - !Ref VoicemailIamUserGroup VoicemailIamUserGroup: Type: AWS::IAM::Group Properties: Policies: - PolicyName: VoicemailIamPolicy PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - s3:GetObject - s3:GetSignedUrl Resource: Fn::Join: - "" - - !GetAtt AudioRecordingsBucket.Arn - "/*" VoicemailIamUserAccessKey: DependsOn: - VoicemailIamUser Type: AWS::IAM::AccessKey Properties: UserName: !Ref VoicemailIamUser VoicemailSecret: DependsOn: - VoicemailIamUser - VoicemailIamUserAccessKey Type: AWS::SecretsManager::Secret Properties: Description: "IAM Access Key Secret" SecretString: Fn::Join: - "" - - '{"accessKeyId":' - '"' - !Ref VoicemailIamUserAccessKey - '"' - ',"secretAccessKey":' - '"' - !GetAtt VoicemailIamUserAccessKey.SecretAccessKey - '"}' Metadata: cfn_nag: rules_to_suppress: - id: W77 reason: Uses the account's default AWS managed CMK for Secrets ManagerĀ· ApiGatewayApiKey1: Type: "AWS::ApiGateway::ApiKey" Properties: Enabled: true StageKeys: - RestApiId: Ref: ApiGatewayRestApi StageName: ${self:provider.stage} DependsOn: ApiGatewayDeployment${sls:instanceId} ApiGatewayUsagePlan: Type: "AWS::ApiGateway::UsagePlan" DependsOn: ApiGatewayDeployment${sls:instanceId} Properties: ApiStages: - ApiId: Ref: ApiGatewayRestApi Stage: ${self:provider.stage} Description: Usage plan for aws-connect-vm prod stage Throttle: BurstLimit: 500 RateLimit: 50 ApiGatewayUsagePlanKey1: Type: "AWS::ApiGateway::UsagePlanKey" Properties: KeyId: Ref: ApiGatewayApiKey1 KeyType: API_KEY UsagePlanId: Ref: ApiGatewayUsagePlan Outputs: ApiGatewayApiKey: Value: !GetAtt ApiGatewayApiKey1.APIKeyId CognitoDomain: Value: !Sub "${UserPoolDomain}.auth.${AWS::Region}.amazoncognito.com" UserPoolId: Value: !Ref CognitoUserPoolUserPool UserPoolArn: Value: !GetAtt CognitoUserPoolUserPool.Arn