---
# Copyright widdix GmbH
#
# 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 
# OLDERS 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.
Description: bucketAV Amazon Connect integration Add-On for Amazon S3
AWSTemplateFormatVersion: "2010-09-09"
Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: Required Parameters
        Parameters:
          - BucketAVStackName
      - Label:
          default: Amazon Connect Parameters
        Parameters:
          - LogsRetentionInDays
      - Label:
          default: Permissions Parameters
        Parameters:
          - PermissionsBoundary
      - Label:
          default: Lambda Parameters
        Parameters:
          - ConnectLambdaFunctionReservedConcurrentExecutions
          - SubscriptionLambdaFunctionReservedConcurrentExecutions
Parameters:
  BucketAVStackName:
    Type: String
    Description: CloudFormation stack name of bucketAV (if you followed our docs, the name is bucketav, or s3-virusscan for older installations)
  LogsRetentionInDays:
    Type: Number
    Default: 14
    AllowedValues:
      - 1
      - 3
      - 5
      - 7
      - 14
      - 30
      - 60
      - 90
      - 120
      - 150
      - 180
      - 365
      - 400
      - 545
      - 731
      - 1827
      - 3653
    Description: Specifies the number of days you want to retain log events.
  PermissionsBoundary:
    Type: String
    Default: ""
    Description: Optional IAM policy ARN that will be used as the permissions boundary for all roles.
  SubscriptionLambdaFunctionReservedConcurrentExecutions:
    Type: Number
    Default: 0
    Description: Maximum number of execution environment instances for the Lambda function (set to 0 to disable; Check out the CloudWatch metric ConcurrentExecutions to get the maximum concurrent invocations of the past).
    MinValue: 0
  ConnectLambdaFunctionReservedConcurrentExecutions:
    Type: Number
    Default: 0
    Description: Maximum number of execution environment instances for the Lambda function (set to 0 to disable; Check out the CloudWatch metric ConcurrentExecutions to get the maximum concurrent invocations of the past).
    MinValue: 0
  LambdaSubnets:
    Type: CommaDelimitedList
    Default: ""
    Description: Optionally configure Lambda functions to run in theses subnets, requires route to NAT Gateway or VPC Endpoints.
  LambdaVpc:
    Type: String
    Default: ""
    Description: Optionally configure Lambda functions to run in this VPC, requires route to NAT Gateway or VPC Endpoints.
Conditions:
  HasLambdaVpc:
    Fn::And:
      - Fn::Not:
          - Fn::Equals:
              - Fn::Join:
                  - ""
                  - Ref: LambdaSubnets
              - ""
      - Fn::Not:
          - Fn::Equals:
              - Ref: LambdaVpc
              - ""
  HasPermissionsBoundary:
    Fn::Not:
      - Fn::Equals:
          - Ref: PermissionsBoundary
          - ""
  HasSubscriptionLambdaFunctionReservedConcurrentExecutions:
    Fn::Not:
      - Fn::Equals:
          - Ref: SubscriptionLambdaFunctionReservedConcurrentExecutions
          - 0
  HasConnectLambdaFunctionReservedConcurrentExecutions:
    Fn::Not:
      - Fn::Equals:
          - Ref: ConnectLambdaFunctionReservedConcurrentExecutions
          - 0
Resources:
  Table:
    Type: AWS::DynamoDB::Table
    Properties:
      AttributeDefinitions:
        - AttributeName: id
          AttributeType: S
      BillingMode: PAY_PER_REQUEST
      KeySchema:
        - AttributeName: id
          KeyType: HASH
      SSESpecification:
        SSEEnabled: true
      TimeToLiveSpecification:
        AttributeName: ttl
        Enabled: true
  TableUserErrorsAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmActions:
        - Fn::ImportValue:
            Fn::Join:
              - ""
              - - Ref: BucketAVStackName
                - -InfrastructureAlarmsTopicArn
      AlarmDescription: bucketAV connect add-on user errors.
      ComparisonOperator: GreaterThanThreshold
      Dimensions:
        - Name: TableName
          Value:
            Ref: Table
      EvaluationPeriods: 1
      MetricName: UserErrors
      Namespace: AWS/DynamoDB
      Period: 300
      Statistic: Sum
      Threshold: 0
      TreatMissingData: notBreaching
  TableSystemErrorsAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmActions:
        - Fn::ImportValue:
            Fn::Join:
              - ""
              - - Ref: BucketAVStackName
                - -InfrastructureAlarmsTopicArn
      AlarmDescription: bucketAV connect add-on system errors.
      ComparisonOperator: GreaterThanThreshold
      Dimensions:
        - Name: TableName
          Value:
            Ref: Table
      EvaluationPeriods: 1
      MetricName: SystemErrors
      Namespace: AWS/DynamoDB
      Period: 300
      Statistic: Sum
      Threshold: 0
      TreatMissingData: notBreaching
  SubscriptionLambdaRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: sts:AssumeRole
      PermissionsBoundary:
        Fn::If:
          - HasPermissionsBoundary
          - Ref: PermissionsBoundary
          - Ref: AWS::NoValue
      Policies:
        - PolicyDocument:
            Statement:
              - Effect: Allow
                Action: dynamodb:PutItem
                Resource:
                  Fn::GetAtt:
                    - Table
                    - Arn
          PolicyName: lambda
        - PolicyDocument:
            Statement:
              - Effect: Allow
                Action: sqs:SendMessage
                Resource:
                  Fn::GetAtt:
                    - SubscriptionLambdaDeadLetterQueue
                    - Arn
          PolicyName: dlq
  LambdaSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription:
        Fn::Join:
          - ""
          - - Ref: AWS::StackName
            - -lambda
      SecurityGroupEgress:
        - CidrIp: 0.0.0.0/0
          Description: Allow outgoing HTTPS traffic.
          FromPort: 443
          IpProtocol: tcp
          ToPort: 443
      VpcId:
        Ref: LambdaVpc
    Condition: HasLambdaVpc
  SubscriptionLambdaFunction:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        ZipFile: |
          var __defProp = Object.defineProperty;
          var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
          var __getOwnPropNames = Object.getOwnPropertyNames;
          var __hasOwnProp = Object.prototype.hasOwnProperty;
          var __export = (target, all) => {
            for (var name in all)
              __defProp(target, name, { get: all[name], enumerable: true });
          };
          var __copyProps = (to, from, except, desc) => {
            if (from && typeof from === "object" || typeof from === "function") {
              for (let key of __getOwnPropNames(from))
                if (!__hasOwnProp.call(to, key) && key !== except)
                  __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
            }
            return to;
          };
          var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

          // lambda/add-on-connect-subscription.js
          var add_on_connect_subscription_exports = {};
          __export(add_on_connect_subscription_exports, {
            handler: () => handler
          });
          module.exports = __toCommonJS(add_on_connect_subscription_exports);
          var import_client_dynamodb = require("@aws-sdk/client-dynamodb");
          var TRACE_TTL_IN_SECONDS = 120;
          var dynamodb = new import_client_dynamodb.DynamoDBClient({ apiVersion: "2012-08-10" });
          async function handler(event) {
            console.log(`Invoke: ${JSON.stringify(event)}`);
            const now = Date.now();
            await Promise.all(event.Records.map((record) => dynamodb.send(new import_client_dynamodb.PutItemCommand({
              TableName: process.env.TABLE_NAME,
              Item: {
                id: { S: record.Sns.MessageAttributes.trace_id.Value },
                status: { S: record.Sns.MessageAttributes.status.Value },
                ttl: { N: (now / 1e3 + TRACE_TTL_IN_SECONDS).toFixed(0) }
              }
            }))));
            return true;
          }
          // Annotate the CommonJS export names for ESM import in node:
          0 && (module.exports = {
            handler
          });
      DeadLetterConfig:
        TargetArn:
          Fn::GetAtt:
            - SubscriptionLambdaDeadLetterQueue
            - Arn
      Environment:
        Variables:
          TABLE_NAME:
            Ref: Table
      Handler: index.handler
      MemorySize: 1769
      ReservedConcurrentExecutions:
        Fn::If:
          - HasSubscriptionLambdaFunctionReservedConcurrentExecutions
          - Ref: SubscriptionLambdaFunctionReservedConcurrentExecutions
          - Ref: AWS::NoValue
      Role:
        Fn::GetAtt:
          - SubscriptionLambdaRole
          - Arn
      Runtime: nodejs22.x
      Timeout: 60
      VpcConfig:
        Fn::If:
          - HasLambdaVpc
          - SecurityGroupIds:
              - Ref: LambdaSecurityGroup
            SubnetIds:
              Ref: LambdaSubnets
          - Ref: AWS::NoValue
    Metadata:
      bucketav::SubscriptionLambdaVpcAllowPolicy:
        Fn::If:
          - HasLambdaVpc
          - Ref: SubscriptionLambdaVpcAllowPolicy
          - Ref: AWS::NoValue
  SubscriptionLambdaVpcAllowPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyDocument:
        Statement:
          - Effect: Allow
            Action:
              - ec2:CreateNetworkInterface
              - ec2:DeleteNetworkInterface
              - ec2:AssignPrivateIpAddresses
              - ec2:UnassignPrivateIpAddresses
              - ec2:DescribeNetworkInterfaces
              - ec2:DescribeSubnets
            Resource:
              - "*"
      PolicyName: vpc-allow
      Roles:
        - Ref: SubscriptionLambdaRole
    Condition: HasLambdaVpc
  SubscriptionLambdaVpcDenyPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyDocument:
        Statement:
          - Effect: Deny
            Action:
              - ec2:CreateNetworkInterface
              - ec2:DescribeNetworkInterfaces
              - ec2:DescribeSubnets
              - ec2:DeleteNetworkInterface
              - ec2:AssignPrivateIpAddresses
              - ec2:UnassignPrivateIpAddresses
            Resource: "*"
            Condition:
              ArnEquals:
                lambda:SourceFunctionArn:
                  - Fn::GetAtt:
                      - SubscriptionLambdaFunction
                      - Arn
      PolicyName: vpc-deny
      Roles:
        - Ref: SubscriptionLambdaRole
    Condition: HasLambdaVpc
  SubscriptionLambdaErrorsAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmActions:
        - Fn::ImportValue:
            Fn::Join:
              - ""
              - - Ref: BucketAVStackName
                - -InfrastructureAlarmsTopicArn
      AlarmDescription:
        Fn::Join:
          - ""
          - - "bucketAV connect add-on failed. Check logs of AWS Lambda Function "
            - Ref: SubscriptionLambdaFunction
            - "!"
      ComparisonOperator: GreaterThanOrEqualToThreshold
      Dimensions:
        - Name: FunctionName
          Value:
            Ref: SubscriptionLambdaFunction
      EvaluationPeriods: 1
      MetricName: Errors
      Namespace: AWS/Lambda
      Period: 360
      Statistic: Sum
      Threshold: 1
      TreatMissingData: notBreaching
  SubscriptionLambdaThrottlesAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmActions:
        - Fn::ImportValue:
            Fn::Join:
              - ""
              - - Ref: BucketAVStackName
                - -InfrastructureAlarmsTopicArn
      AlarmDescription: bucketAV connect add-on throttled.
      ComparisonOperator: GreaterThanOrEqualToThreshold
      Dimensions:
        - Name: FunctionName
          Value:
            Ref: SubscriptionLambdaFunction
      EvaluationPeriods: 1
      MetricName: Throttles
      Namespace: AWS/Lambda
      Period: 360
      Statistic: Sum
      Threshold: 1
      TreatMissingData: notBreaching
  SubscriptionLambdaDeadLetterQueue:
    Type: AWS::SQS::Queue
    Properties:
      MessageRetentionPeriod: 1209600
      SqsManagedSseEnabled: true
  SubscriptionLambdaDeadLetterQueueAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmActions:
        - Fn::ImportValue:
            Fn::Join:
              - ""
              - - Ref: BucketAVStackName
                - -InfrastructureAlarmsTopicArn
      AlarmDescription: bucketAV connect add-on has dead letter queue messages.
      ComparisonOperator: GreaterThanOrEqualToThreshold
      Dimensions:
        - Name: QueueName
          Value:
            Fn::GetAtt:
              - SubscriptionLambdaDeadLetterQueue
              - QueueName
      EvaluationPeriods: 1
      MetricName: ApproximateNumberOfMessagesVisible
      Namespace: AWS/SQS
      Period: 360
      Statistic: Sum
      Threshold: 1
      TreatMissingData: notBreaching
  SubscriptionLambdaDeadLetterErrorsAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmActions:
        - Fn::ImportValue:
            Fn::Join:
              - ""
              - - Ref: BucketAVStackName
                - -InfrastructureAlarmsTopicArn
      AlarmDescription: bucketAV connect add-on has dead letter queue errors.
      ComparisonOperator: GreaterThanOrEqualToThreshold
      Dimensions:
        - Name: FunctionName
          Value:
            Ref: SubscriptionLambdaFunction
      EvaluationPeriods: 1
      MetricName: DeadLetterErrors
      Namespace: AWS/Lambda
      Period: 360
      Statistic: Sum
      Threshold: 1
      TreatMissingData: notBreaching
  SubscriptionLambdaLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName:
        Fn::Join:
          - ""
          - - /aws/lambda/
            - Ref: SubscriptionLambdaFunction
      RetentionInDays:
        Ref: LogsRetentionInDays
  SubscriptionLambdaPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName:
        Ref: SubscriptionLambdaFunction
      Principal: sns.amazonaws.com
      SourceArn:
        Fn::ImportValue:
          Fn::Join:
            - ""
            - - Ref: BucketAVStackName
              - -FindingsTopicArn
  SubscriptionLambdaPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyDocument:
        Statement:
          - Effect: Allow
            Action:
              - logs:CreateLogStream
              - logs:PutLogEvents
            Resource:
              Fn::GetAtt:
                - SubscriptionLambdaLogGroup
                - Arn
      PolicyName: logs
      Roles:
        - Ref: SubscriptionLambdaRole
  Subscription:
    Type: AWS::SNS::Subscription
    Properties:
      Endpoint:
        Fn::GetAtt:
          - SubscriptionLambdaFunction
          - Arn
      FilterPolicy:
        trace_id:
          - prefix:
              Fn::Join:
                - ""
                - - "bucketav:connect:"
                  - Ref: AWS::StackName
                  - ":"
      Protocol: lambda
      TopicArn:
        Fn::ImportValue:
          Fn::Join:
            - ""
            - - Ref: BucketAVStackName
              - -FindingsTopicArn
    DependsOn:
      - SubscriptionLambdaPermission
      - SubscriptionLambdaPolicy
  ConnectLambdaRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: sts:AssumeRole
      PermissionsBoundary:
        Fn::If:
          - HasPermissionsBoundary
          - Ref: PermissionsBoundary
          - Ref: AWS::NoValue
      Policies:
        - PolicyDocument:
            Statement:
              - Effect: Allow
                Action: sqs:SendMessage
                Resource:
                  Fn::ImportValue:
                    Fn::Join:
                      - ""
                      - - Ref: BucketAVStackName
                        - -ScanQueueArn
              - Effect: Allow
                Action: dynamodb:GetItem
                Resource:
                  Fn::GetAtt:
                    - Table
                    - Arn
          PolicyName: lambda
  ConnectLambdaFunction:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        ZipFile: |
          var __defProp = Object.defineProperty;
          var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
          var __getOwnPropNames = Object.getOwnPropertyNames;
          var __hasOwnProp = Object.prototype.hasOwnProperty;
          var __export = (target, all) => {
            for (var name in all)
              __defProp(target, name, { get: all[name], enumerable: true });
          };
          var __copyProps = (to, from, except, desc) => {
            if (from && typeof from === "object" || typeof from === "function") {
              for (let key of __getOwnPropNames(from))
                if (!__hasOwnProp.call(to, key) && key !== except)
                  __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
            }
            return to;
          };
          var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

          // lambda/add-on-connect.js
          var add_on_connect_exports = {};
          __export(add_on_connect_exports, {
            handler: () => handler
          });
          module.exports = __toCommonJS(add_on_connect_exports);
          var import_client_sqs = require("@aws-sdk/client-sqs");
          var import_client_dynamodb = require("@aws-sdk/client-dynamodb");
          var POLL_TIMEOUT_IN_MILLISECONDS = 1e3 * 55;
          var sqs = new import_client_sqs.SQSClient({ apiVersion: "2012-11-05" });
          var dynamodb = new import_client_dynamodb.DynamoDBClient({ apiVersion: "2012-08-10" });
          async function wait(ms) {
            return new Promise((resolve) => setTimeout(resolve, ms));
          }
          async function handler(event) {
            console.log(`Invoke: ${JSON.stringify(event)}`);
            const start = Date.now();
            const traceId = `bucketav:connect:${process.env.ADDON_STACK_NAME}:${event.File.FileId}`;
            const object = {
              bucket: event.File.FileLocation.S3Location.Bucket,
              key: event.File.FileLocation.S3Location.Key,
              trace_id: traceId
            };
            await sqs.send(new import_client_sqs.SendMessageCommand({
              MessageBody: JSON.stringify({
                objects: [object]
              }),
              QueueUrl: process.env.SCAN_QUEUE_URL,
              MessageGroupId: `bucketav:connect:${process.env.ADDON_STACK_NAME.substring(0, 111)}`
              // max 128 chars
            }));
            while (Date.now() - start < POLL_TIMEOUT_IN_MILLISECONDS) {
              const { Item: item } = await dynamodb.send(new import_client_dynamodb.GetItemCommand({
                TableName: process.env.TABLE_NAME,
                Key: {
                  id: { S: traceId }
                }
              }));
              if (item === void 0) {
                await wait(1e3);
                continue;
              } else if (item.status.S === "clean") {
                return {
                  Status: "APPROVED"
                };
              } else if (item.status.S === "infected" || item.status.S === "no") {
                return {
                  Status: "REJECTED"
                };
              } else {
                throw new Error(`unexpected status: ${item.status.S}`);
              }
            }
            throw new Error("timeout");
          }
          // Annotate the CommonJS export names for ESM import in node:
          0 && (module.exports = {
            handler
          });
      Environment:
        Variables:
          TABLE_NAME:
            Ref: Table
          ADDON_STACK_NAME:
            Ref: AWS::StackName
          SCAN_QUEUE_URL:
            Fn::ImportValue:
              Fn::Join:
                - ""
                - - Ref: BucketAVStackName
                  - -ScanQueueUrl
      Handler: index.handler
      MemorySize: 1769
      ReservedConcurrentExecutions:
        Fn::If:
          - HasConnectLambdaFunctionReservedConcurrentExecutions
          - Ref: ConnectLambdaFunctionReservedConcurrentExecutions
          - Ref: AWS::NoValue
      Role:
        Fn::GetAtt:
          - ConnectLambdaRole
          - Arn
      Runtime: nodejs22.x
      Timeout: 60
      VpcConfig:
        Fn::If:
          - HasLambdaVpc
          - SecurityGroupIds:
              - Ref: LambdaSecurityGroup
            SubnetIds:
              Ref: LambdaSubnets
          - Ref: AWS::NoValue
    Metadata:
      bucketav::ConnectLambdaVpcAllowPolicy:
        Fn::If:
          - HasLambdaVpc
          - Ref: ConnectLambdaVpcAllowPolicy
          - Ref: AWS::NoValue
  ConnectLambdaVpcAllowPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyDocument:
        Statement:
          - Effect: Allow
            Action:
              - ec2:CreateNetworkInterface
              - ec2:DeleteNetworkInterface
              - ec2:AssignPrivateIpAddresses
              - ec2:UnassignPrivateIpAddresses
              - ec2:DescribeNetworkInterfaces
              - ec2:DescribeSubnets
            Resource:
              - "*"
      PolicyName: vpc-allow
      Roles:
        - Ref: ConnectLambdaRole
    Condition: HasLambdaVpc
  ConnectLambdaVpcDenyPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyDocument:
        Statement:
          - Effect: Deny
            Action:
              - ec2:CreateNetworkInterface
              - ec2:DescribeNetworkInterfaces
              - ec2:DescribeSubnets
              - ec2:DeleteNetworkInterface
              - ec2:AssignPrivateIpAddresses
              - ec2:UnassignPrivateIpAddresses
            Resource: "*"
            Condition:
              ArnEquals:
                lambda:SourceFunctionArn:
                  - Fn::GetAtt:
                      - ConnectLambdaFunction
                      - Arn
      PolicyName: vpc-deny
      Roles:
        - Ref: ConnectLambdaRole
    Condition: HasLambdaVpc
  ConnectLambdaErrorsAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmActions:
        - Fn::ImportValue:
            Fn::Join:
              - ""
              - - Ref: BucketAVStackName
                - -InfrastructureAlarmsTopicArn
      AlarmDescription:
        Fn::Join:
          - ""
          - - "bucketAV connect add-on failed. Check logs of AWS Lambda Function "
            - Ref: ConnectLambdaFunction
            - "!"
      ComparisonOperator: GreaterThanOrEqualToThreshold
      Dimensions:
        - Name: FunctionName
          Value:
            Ref: ConnectLambdaFunction
      EvaluationPeriods: 1
      MetricName: Errors
      Namespace: AWS/Lambda
      Period: 360
      Statistic: Sum
      Threshold: 1
      TreatMissingData: notBreaching
  ConnectLambdaThrottlesAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmActions:
        - Fn::ImportValue:
            Fn::Join:
              - ""
              - - Ref: BucketAVStackName
                - -InfrastructureAlarmsTopicArn
      AlarmDescription: bucketAV connect add-on throttled.
      ComparisonOperator: GreaterThanOrEqualToThreshold
      Dimensions:
        - Name: FunctionName
          Value:
            Ref: ConnectLambdaFunction
      EvaluationPeriods: 1
      MetricName: Throttles
      Namespace: AWS/Lambda
      Period: 360
      Statistic: Sum
      Threshold: 1
      TreatMissingData: notBreaching
  ConnectLambdaLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName:
        Fn::Join:
          - ""
          - - /aws/lambda/
            - Ref: ConnectLambdaFunction
      RetentionInDays:
        Ref: LogsRetentionInDays
  ConnectLambdaPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyDocument:
        Statement:
          - Effect: Allow
            Action:
              - logs:CreateLogStream
              - logs:PutLogEvents
            Resource:
              Fn::GetAtt:
                - ConnectLambdaLogGroup
                - Arn
      PolicyName: logs
      Roles:
        - Ref: ConnectLambdaRole
  ServiceDiscoveryVersion:
    Type: AWS::SSM::Parameter
    Properties:
      Description: bucketAV managed value. DO NOT CHANGE!
      Name:
        Fn::Join:
          - ""
          - - /bucketAV/
            - Ref: BucketAVStackName
            - /AddOn/connect/
            - Ref: AWS::StackName
            - /Version
      Type: String
      Value: 2.6.0
Outputs:
  SubscriptionLambdaDeadLetterQueueName:
    Description: The name of the Dead Letter Queue used by the Lambda function.
    Value:
      Fn::GetAtt:
        - SubscriptionLambdaDeadLetterQueue
        - QueueName
  ScannerLambdaFunctionName:
    Description: Amazon Connect attachment scanner Lambda function name.
    Value:
      Ref: ConnectLambdaFunction
    Export:
      Name:
        Fn::Join:
          - ""
          - - Ref: AWS::StackName
            - -ScannerLambdaFunctionName
  ScannerLambdaFunctionArn:
    Description: Amazon Connect attachment scanner Lambda function name.
    Value:
      Fn::GetAtt:
        - ConnectLambdaFunction
        - Arn
    Export:
      Name:
        Fn::Join:
          - ""
          - - Ref: AWS::StackName
            - -ScannerLambdaFunctionArn
  AddOn:
    Description: bucketAV add-on.
    Value: connect
  Platform:
    Description: bucketAV platform.
    Value: aws
  Version:
    Description: bucketAV add-on version.
    Value: 2.6.0
  StackName:
    Description: Stack name.
    Value:
      Ref: AWS::StackName

