AWSTemplateFormatVersion: 2010-09-09
Description: Version 9.09.000 - CloudFormation template for CloudStorageSec Console software.
Parameters:
  DeploymentType:
    Type: String
    Description: "The deployment type where the Console will be running"
    AllowedValues:
      - ECS
      - EKS
      - KubernetesAnywhere
    Default: ECS
  EksClusterName:
    Type: String
    Description: "The name of the existing EKS cluster where the CloudStorageSec Console and Agents will be deployed"
    Default: ""
  EksNamespace:
    Type: String
    Description: "The name of the Kubernetes namespace where the CloudStorageSec Console and Agents will be deployed"
    Default: ""
  EksConsoleServiceAccountName:
    Type: String
    Description: "The name of the Kubernetes service account for the CloudStorageSec Console in the EKS cluster"
    Default: ""
  EksAgentServiceAccountName:
    Type: String
    Description: "The name of the Kubernetes service account for the CloudStorageSec Agents in the EKS cluster"
    Default: ""
  IamOidcProviderName:
    Type: String
    Description: "The name of the IAM OIDC identity provider associated with the EKS cluster for service account authentication"
    Default: ""
  VPC:
    Type: AWS::EC2::VPC::Id
    MinLength: 1
    Description: The VPC in which to place the public facing Console (Considered only by ECS deployment)
    ConstraintDescription: VPC is a mandatory input parameter. Select an existing VPC ID.
  SubnetA:
    Type: AWS::EC2::Subnet::Id
    MinLength: 1
    Description: A subnet in your VPC in which the public facing Console can be placed. Ensure this subnet allows outbound internet traffic. (Considered only by ECS deployment)
    ConstraintDescription: SubnetA is a mandatory input parameter. Select existing subnet from the selected VPC.
  SubnetB:
    Type: AWS::EC2::Subnet::Id
    MinLength: 1
    Description: A subnet in your VPC in which the public facing Console can be placed. Ensure this subnet allows outbound internet traffic. **Subnet B must be different from Subnet A and should be in a different Availability Zones** (Considered only by ECS deployment)
    ConstraintDescription: SubnetB is a mandatory input parameter. Select existing subnet from the selected VPC.
  ConsoleSecurityGroup:
    Type: String
    Default: "Created by CFT"
    Description: The Security Group for the Console management website (Optional, leave blank to create a new security group).
  ConsoleSecurityGroupCidrBlock:
    Type: String
    Description: The IP address range that can access the Console management website (e.g. X.X.X.X/32 for a single given IP, 0.0.0.0/0 for open access)
    MinLength: 9
    MaxLength: 18
    AllowedPattern: ((\d{1,3})\.){3}\d{1,3}/\d{1,2}
    ConstraintDescription: Must be valid CIDR notation of the form X.X.X.X/X
  MinRunningAgents:
    Type: Number
    Default: 1
    MinValue: 0
    Description: Cannot be greater than Maximum Running Agents
  MaxRunningAgents:
    Type: Number
    Default: 12
    MinValue: 1
    Description: Cannot be less than Minimum Running Agents
  NumMessagesInQueueScalingThreshold:
    Type: Number
    Default: 1000
    Description: The number of pending files to be scanned before adding or removing agents
  AzureMinRunningAgents:
    Type: Number
    Default: 1
    MinValue: 0
    Description: Cannot be greater than Azure Maximum Running Agents
  AzureMaxRunningAgents:
    Type: Number
    Default: 12
    MinValue: 1
    Description: Cannot be less than Azure Minimum Running Agents
  AzureNumMessagesInQueueScalingThreshold:
    Type: Number
    Default: 1000
    Description: The number of pending files to be scanned before adding or removing agents
  ConsoleCpu:
    Type: String
    Default: 0.5vCPU
    AllowedValues: ["0.5vCPU", "1vCPU", "2vCPU", "4vCPU"]
    Description: The number of vCPU units for the Console (1024 vCPU units per 1 vCPU)
  ConsoleMemory:
    Type: String
    Default: 1GB
    AllowedValues:
      [
        "1GB",
        "2GB",
        "3GB",
        "4GB",
        "5GB",
        "6GB",
        "7GB",
        "8GB",
        "9GB",
        "10GB",
        "11GB",
        "12GB",
        "13GB",
        "14GB",
        "15GB",
        "16GB",
        "17GB",
        "18GB",
        "19GB",
        "20GB",
        "21GB",
        "22GB",
        "23GB",
        "24GB",
        "25GB",
        "26GB",
        "27GB",
        "28GB",
        "29GB",
        "30GB",
      ]
    Description: The amount of memory for the Console. Must be 2-8x the vCPU. i.e. 0.5 vCPU should have 1-4GB of memory.
  ConsoleAutoAssignPublicIp:
    Type: String
    Default: "ENABLED"
    AllowedValues: ["ENABLED", "DISABLED"]
    Description: "Should a public IP be assigned to the Console? (WARNING: do not set to disabled unless you have configured your AWS VPC in a manner that would still allow access to the console.)"
  EnableCloudTrailLake:
    Type: String
    Default: "No"
    AllowedValues: ["Yes", "No"]
    Description: Would you like to send audit logs to CloudTrail Lake?
  DisableEBSScanning:
    Type: String
    Default: "No"
    AllowedValues: ["Yes", "No"]
    Description: Would you like to disable the AWS EBS Service?
  DisableEFSScanning:
    Type: String
    Default: "No"
    AllowedValues: ["Yes", "No"]
    Description: Would you like to disable the AWS EFS Service?
  DisableFSxScanning:
    Type: String
    Default: "No"
    AllowedValues: ["Yes", "No"]
    Description: Would you like to disable the AWS FSx Service?
  CloudTrailLakeDataStoreName:
    Type: String
    Default: "default"
    Description: Enter a CloudTrail Event Data Store name if you would like to use an existing one. Otherwise we will create a new one. If existing, must be in same region as this deployment.
  CloudTrailLakeChannelName:
    Type: String
    Default: "default"
    Description: Enter a CloudTrail Channel name if you would like to use an existing one. Otherwise we will create a new one. If existing, must be in same region as this deployment.
  DeployApiAgent:
    Type: String
    Default: "No"
    AllowedValues: ["Yes", "No"]
    Description: "Deploy an API Agent alongside the Console? If Yes, complete the API Agent Configuration section below."
  ApiAgentVpc:
    Type: String
    Default: ""
    Description: The VPC in which to place the API Agent and its load balancer. Required when Deploy API Agent is Yes.
    ConstraintDescription: Enter an existing VPC ID.
  ApiAgentSubnets:
    Type: String
    Default: ""
    Description: "Comma-separated list of at least 2 subnet IDs in different Availability Zones for the API Agent tasks. Must belong to the selected API Agent VPC. Required when Deploy API Agent is Yes."
    ConstraintDescription: Enter at least 2 comma-separated subnet IDs from the selected VPC, each in a different Availability Zone.
  ApiAgentLBSubnets:
    Type: String
    Default: ""
    Description: "Comma-separated list of at least 2 subnet IDs in different Availability Zones for the API Agent load balancer. Must match the Availability Zones of the API Agent Subnets. Required when Deploy API Agent is Yes."
    ConstraintDescription: Enter at least 2 comma-separated subnet IDs from the selected VPC, each in a different Availability Zone, matching those chosen for the API Agent.
  ApiAgentInboundCidr:
    Type: String
    Default: ""
    Description: "The IP address range allowed to access the API Agent load balancer (e.g. 0.0.0.0/0 for open access, X.X.X.X/32 for a single IP). Required when Deploy API Agent is Yes."
    AllowedPattern: "(^$|(\\d{1,3}\\.){3}\\d{1,3}/\\d{1,2})"
    ConstraintDescription: Must be a valid CIDR notation of the form X.X.X.X/X
  ApiAgentSslCertArn:
    Type: String
    Default: "arn:aws:acm:region:123456789012:certificate/00000000-0000-0000-0000-000000000000"
    Description: "Enter the ARN of an existing ACM certificate for the API Agent load balancer. Format: arn:aws:acm:<region>:<account-id>:certificate/<certificate-id>. Only needed if Deploy API Agent is Yes."
    ConstraintDescription: "Enter a valid ACM certificate ARN. Format: arn:aws:acm:<region>:<account-id>:certificate/<certificate-id>"
  ApiAgentInternetFacingLB:
    Type: String
    Default: "Yes"
    AllowedValues: ["Yes", "No"]
    Description: "Should the API Agent load balancer be internet-facing? Set to No for an internal load balancer."
  ApiAgentAllowedOrigins:
    Type: String
    Default: ""
    Description: "(Optional) Comma-separated list of allowed origins for API Agent CORS (e.g. https://example.com). Leave blank to allow no origins."
  ApiAgentMinAgents:
    Type: Number
    Default: 1
    MinValue: 0
    Description: Minimum number of running API Agent tasks. Cannot be greater than ApiAgentMaxAgents.
  ApiAgentMaxAgents:
    Type: Number
    Default: 3
    MinValue: 1
    Description: Maximum number of running API Agent tasks. Cannot be less than ApiAgentMinAgents.
  ApiAgentCpu:
    Type: String
    Default: "1vCPU"
    AllowedValues: ["1vCPU", "2vCPU", "4vCPU"]
    Description: The number of vCPU units for the API Agent (1024 vCPU units = 1 vCPU).
  ApiAgentMemory:
    Type: String
    Default: "3GB"
    AllowedValues:
      [
        "2GB",
        "3GB",
        "4GB",
        "5GB",
        "6GB",
        "7GB",
        "8GB",
        "9GB",
        "10GB",
        "11GB",
        "12GB",
        "13GB",
        "14GB",
        "15GB",
        "16GB",
        "17GB",
        "18GB",
        "19GB",
        "20GB",
        "21GB",
        "22GB",
        "23GB",
        "24GB",
        "25GB",
        "26GB",
        "27GB",
        "28GB",
        "29GB",
        "30GB",
      ]
    Description: The amount of memory for the API Agent. Must be 2-8x the vCPU. i.e. 2 vCPU should have 4-16GB of memory.
  ApiAgentDiskSize:
    Type: Number
    Default: 20
    MinValue: 20
    MaxValue: 200
    Description: Disk size (GB) for the API Agent container. Use a larger value (up to 200 GB) to enable scanning of larger files with Sophos and/or CSS Premium.
  ApiAgentScanningEngine:
    Type: String
    Default: "Default"
    AllowedValues: ["Default", "ClamAV", "Sophos", "Bitdefender", "All"]
    Description: "The scanning engine for the API Agent. Select 'Default' to use the same engine as the global Agent setting. Select 'All' to scan every file with ClamAV, Sophos, and Bitdefender simultaneously. (See Marketplace listing for pricing differences)"
  ApiAgentEnableAsynchronousScanning:
    Type: String
    Default: "No"
    AllowedValues: ["Yes", "No"]
    Description: "(Optional) Enable asynchronous scanning for the API Agent. When enabled, scan requests are queued and processed asynchronously via SQS."
  AgentCpu:
    Type: String
    Default: "1vCPU"
    AllowedValues: ["1vCPU", "2vCPU", "4vCPU"]
    Description: The number of vCPU units for the Agents (1024 vCPU units = 1 vCPU)
  AgentMemory:
    Type: String
    Default: 3GB
    AllowedValues:
      [
        "2GB",
        "3GB",
        "4GB",
        "5GB",
        "6GB",
        "7GB",
        "8GB",
        "9GB",
        "10GB",
        "11GB",
        "12GB",
        "13GB",
        "14GB",
        "15GB",
        "16GB",
        "17GB",
        "18GB",
        "19GB",
        "20GB",
        "21GB",
        "22GB",
        "23GB",
        "24GB",
        "25GB",
        "26GB",
        "27GB",
        "28GB",
        "29GB",
        "30GB",
      ]
    Description: The amount of memory for the scanning Agent. Must be 2-8x the vCPU. i.e. 2 vCPU should have 4-16GB of memory.
  AgentScanningEngine:
    Type: String
    Default: "ClamAV"
    AllowedValues: ["ClamAV", "Sophos", "Bitdefender"]
    Description: "Choose the engine that should be used to scan files (See Marketplace listing for pricing differences)"
  MultiEngineScanningMode:
    Type: String
    Default: "Disabled"
    AllowedValues: ["Disabled", "All", "LargeFiles"]
    Description: "Choose if you want to use multiple engines to scan files. All will scan every file with all selected engines, LargeFiles will scan files larger than 2GB with Sophos or CSS Premium. If choosing All, select additional engines in the Console after deployment. Premium Engine pricing applies."
  LargeFileEngine:
    Type: String
    Default: "Sophos"
    AllowedValues: ["Sophos", "Bitdefender"]
    Description: "Choose which premium engine to use for scanning large files (those over 2GB is using CSS Secure). Only applies if Multi-Engine Scanning Mode is 'LargeFiles'. Premium Engine pricing applies."
  AgentDiskSize:
    Type: Number
    Default: 20
    MinValue: 20
    MaxValue: 200
    Description: Choose a larger disk size (up to 200 GB) to enable scanning larger files, up to 5 GB fewer than the total disk size. This only applies when using the Sophos and/or CSS Premium scanning engines.
  EnableLargeFileScanning:
    Type: String
    Default: "No"
    AllowedValues: ["Yes", "No"]
    Description: Pick Yes if you would like to have EC2 instances launched to scan files too large to be scanned by the normal agent
  LargeFileDiskSize:
    Type: Number
    Default: 2000
    MinValue: 20
    MaxValue: 16300
    Description: Choose a larger disk size (between 20 - 16,300 GB) to enable scanning larger files, up to 5 GB fewer than the total disk size. This only applies when using the Sophos and/or CSS Premium scanning engines with EC2 large file scanning enabled.
  EbsVolumeEncryption:
    Type: String
    Default: "No"
    AllowedValues: ["Yes", "No"]
    Description: Pick Yes if you would like to encrypt EBS volumes created during scans (such as EBS, EC2, or LFS scanning)
  EbsVolumeEncryptionKmsKeyId:
    Type: String
    Default: "default"
    Description: Enter an optional custom KMS Key ARN to use for EBS encryption; otherwise, the default AWS-managed key will be applied
  S3KmsKeyId:
    Type: String
    Default: "default"
    Description: Enter an optional custom global KMS Key ARN to use for S3 encryption; otherwise, the default AWS-managed key will be applied
  LargeFileEC2Tags:
    Type: String
    Default: "CloudStorageSec-[appId]=EC2Instance"
    Description: "Enter an optional comma-separated list of key=value tags to place on extra large file scanning EC2 instances (Note: if you use [appId] in your tag name, we will replace it with the CSS application ID. It is highly recommended to leave the default in order to identify resources and configure permissions from this product)"
  AgentAutoAssignPublicIp:
    Type: String
    Default: "ENABLED"
    AllowedValues: ["ENABLED", "DISABLED"]
    Description: "Should public IPs be assigned to the Agents? (WARNING: do not set to disabled unless you have configured your AWS VPC in a manner that would still allow the agents to reach AWS services over the internet.)"
  UserName:
    Type: String
    Description: Initial user name for the Console management website
    MinLength: 3
    MaxLength: 128
    Default: admin
  Email:
    Type: String
    Description: Email address for Console management website account
    AllowedPattern: ^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$
    ConstraintDescription: Must be a valid email address.
  OnlyScanWhenQueueThresholdExceeded:
    Type: String
    Default: "No"
    AllowedValues: ["Yes", "No"]
    Description: Pick Yes if you would like to only run scanning agents when the number of files waiting to be scanned exceeds the queue scaling threshold
  AzureOnlyScanWhenQueueThresholdExceeded:
    Type: String
    Default: "No"
    AllowedValues: ["Yes", "No"]
    Description: Pick Yes if you would like to only run scanning Azure agents when the number of files waiting to be scanned exceeds the queue scaling threshold
  QuarantineInPrimaryAccount:
    Type: String
    Default: "No"
    AllowedValues: ["Yes", "No"]
    Description: Pick Yes if you would like to create quarantine buckets in the primary account only (if you utilize linked accounts, infected objects will be moved to the quarantine bucket(s) in the primary account)
  AllowAccessToAllKmsKeys:
    Type: String
    Default: "Yes"
    AllowedValues: ["Yes", "No"]
    Description: Pick Yes if you would like to give the scanner access to all KMS encrypted buckets
  CustomDynamoDBKmsKey:
    Type: String
    Default: ""
    Description: Enter an optional KMS Key ARN to configure encryption for the DynamoDB tables
  CustomSnsConsoleKmsKey:
    Type: String
    Default: ""
    Description: Enter an optional KMS Key ARN to configure encryption for the SNS service in the Console Region. Ensure the key policy grants the S3 and Event Bridge services permission to decrypt and generate data keys
  CustomSnsAgentKmsKeys:
    Type: String
    Default: ""
    Description: Enter an optional comma-separated list of KMS Key ARNs for encrypting the SNS service for each region you want to protect. Ensure each key policy grants the S3 and Event Bridge services permission to decrypt and generate data keys
  CustomSqsConsoleKmsKey:
    Type: String
    Default: ""
    Description: Enter an optional KMS Key ARN to configure encryption for the SQS service in the Console Region. Ensure the key policy grants the SNS service permission to decrypt and generate data keys
  CustomSqsAgentKmsKeys:
    Type: String
    Default: ""
    Description: Enter an optional comma-separated list of KMS Key ARNs for encrypting the SQS service for each region you want to protect. Ensure each key policy grants the SNS service permission to decrypt and generate data keys
  StorageAssessmentEnabled:
    Type: String
    Default: "No"
    AllowedValues: ["Yes", "No"]
    Description: Pick Yes if you would like to enable Storage Assessment to run
  UseLoadBalancer:
    Type: String
    Default: "No"
    AllowedValues: ["Yes", "No"]
    Description: Pick Yes if you would like to use a load balancer for the console service. Note that in doing so you will not be able to use the custom DNS feature and would need to provide your own DNS and SSL certificate for the load balancer
  TrustedLoadBalancerNetwork:
    Type: String
    Description: If you are using your own load balancer or traffic forwarding, enter the trusted IP address range (CIDR notation) that will be routing traffic to the Console
    Default: ""
  ExistingTargetGroup:
    Type: String
    Description: If you are using your own AWS load balancer, provide the Target Group ARN that the Console service should register with. If configured, "Use a Load Balancer for the Console?" must be set to "Yes", and "Trusted Custom Load Balancer Network" must be specified.
    Default: ""
  ContainerSecurityGroupLB:
    Type: String
    Default: "Created by CFT"
    Description: The Security Group for the Console Service (ECS Container) to allow connections from the Load Balancer (Optional, leave blank to create a new security group).
  Certificate:
    Type: String
    Default: "arn:aws:acm:region:123456789012:certificate/00000000-0000-0000-0000-000000000000"
    Description: Enter the ARN for the certificate you wish to use for the load balancer. Only needed if using a load balancer.
  LBScheme:
    Type: String
    Default: "internet-facing"
    AllowedValues: ["internet-facing", "internal"]
    Description: Should the load balancer be internet facing or internal only?
  LBSubnetA:
    Type: String
    Default: enter-subnet-id
    Description: A subnet in your VPC in which the Load Balancer can be placed. Ensure this subnet allows outbound internet traffic. ** Leave blank to use same subnet as Console. If specified, must be in same AZ as Console subnet. **
  LBSubnetB:
    Type: String
    Default: enter-subnet-id
    Description: A subnet in your VPC in which the Load Balancer can be placed. Ensure this subnet allows outbound internet traffic. **Subnet B must be different from Subnet A and should be in a different Availability Zones. Leave blank to use same subnet as Console. If specified, must be in same AZ as Console subnet. **
  RegisterRoute53:
    Type: String
    Default: "No"
    AllowedValues: ["Yes", "No"]
    Description: Pick Yes if you would like to add a dns entry in Route53. This is only for when creating a load balancer.
  HostedZoneName:
    Type: String
    Default: domain-for-your-ssl-cert.com
    Description: Enter the hosted zone domain name for adding an entry to Route53. Only needed if registering dns in Route53.
  HostedZoneId:
    Type: String
    Default: ZXXXXDEFAULTXXXXXXXXX
    Description: Enter the hosted zone ID for adding an entry to Route53. Only needed if registering dns in Route53 (Optional, only needed if you have multiple zones with the same name).
  HostedSubdomain:
    Type: String
    Default: subdomain
    Description: Enter the subdomain for adding an entry to Route53. Only needed if registering dns in Route53.
  InfoOptOut:
    Type: String
    Default: "No"
    AllowedValues: ["Yes", "No"]
    Description: Would you like to opt-out from sending information about your deployment? Selecting "Yes" will cause custom DNS registration and trial eligiblity checks to not work. Given this, you must use your own Load Balancer in order to opt-out. If you opt-out and would still like a trial, please contact support@cloudstoragesec.com.
  CustomEcrAccount:
    Type: String
    Default: "default"
    Description: If you would like to host the container images yourself in ECR, enter the AWS account ID here. Ensure you have copied the images to your repositories. Repository names are required to be cloudstoragesecurity/console and cloudstoragesecurity/agent.
  BucketsToProtect:
    Type: String
    Default: ""
    Description: Enter any pre-existing buckets that you would like to automatically enable event-based protection on. Bucket names must be separated by commas (e.g. bucket1,bucket2,bucket3). Protected buckets can be managed after deployment in the CSS Console.
  S3BucketPrefixesRestrictedAccess:
    Type: String
    Description: "This is an optional parameter. Please enter any S3 bucket prefixes that you wish to restrict the application's access to. Note that any buckets not matching the specified prefixes won't work. Use a comma-separated list in the format: arn:{AWSPartition}:s3:::{BucketPrefix}*."
    Default: "*"
  EventBridgeNotificationsEnabled:
    Type: String
    Default: "No"
    AllowedValues: ["Yes", "No"]
    Description: Should Proactive Notifications also be sent to AWS EventBridge?
  EventBridgeNotificationsBusName:
    Type: String
    Default: "default"
    Description: Enter the EventBridge bus name to use for notifications, if desired to be one other than default.
  DynamoTableNamePrefix:
    Type: String
    Default: "7-character-application-id."
    Description: Prefix for dynamo db tables.
  DynamoPointInTimeRecoveryEnabled:
    Type: String
    Default: "No"
    AllowedValues: ["Yes", "No"]
    Description: Would you like to enable point in time recovery (PTIR) for DynamoDB tables?
  EnableGuardDutyS3MalwareIntegration:
    Type: String
    Default: "No"
    AllowedValues: ["Yes", "No"]
    Description: "Would you like to perform additional processing on GuardDuty S3 Malware findings?"
  GuardDutyS3MalwareResultTypes:
    Type: String
    Default: "All Scan Results"
    AllowedValues: ["All Scan Results", "Infected Only"]
    Description: "Which result types would you like us to process?"
  GuardDutyS3MalwareAdditionalScanning:
    Type: String
    Default: "Yes"
    AllowedValues: ["Yes", "No"]
    Description: "Would you like to perform an additional scan on files using the configured CSS engine(s)?"
  RetroScanOnDetectedInfection:
    Type: String
    Default: "No"
    AllowedValues: ["Yes", "No"]
    Description: "Would you like us to perform a scan on existing unscanned files in the bucket where an infected file is found?"
  LogGroupRetentionPolicy:
    Type: String
    Default: "Yes"
    AllowedValues: ["Yes", "No"]
    Description: "Would you like us to set a retention policy on CSS Log groups to limit CloudWatch costs? Note: AWS Landing Zone Accelerator environments should choose 'No'"
  UseFipsEndpoints:
    Type: String
    Default: "No"
    AllowedValues: ["Yes", "No"]
    Description: "Would you like us to use AWS FIPS endpoints (Note: US Regions only)?"
  QuarantineBucketNamePrefix:
    Type: String
    Default: "cloudstoragesecquarantine-"
    Description: Prefix for the quarantine bucket names.
    MinLength: 4
    MaxLength: 27
  ApplicationBucketNamePrefix:
    Type: String
    Default: "cloudstoragesec-"
    Description: Prefix for the main application bucket name.
  AppConfigApplicationPrefix:
    Type: String
    Default: "CloudStorageSec-"
    Description: Prefix for the AWS AppConfig application.
  AppConfigEnvironmentPrefix:
    Type: String
    Default: "CloudStorageSecEnv-"
    Description: Prefix for the AWS AppConfig Environment.
  AppConfigDeploymentStrategyPrefix:
    Type: String
    Default: "CloudStorageSecConfigDeploy-"
    Description: Prefix for the AWS AppConfig Deployment Strategy.
  AppConfigDocumentPrefix:
    Type: String
    Default: "CloudStorageSecConfig-"
    Description: Prefix for the AWS AppConfig Configuration Document.
  AppConfigDocumentSchemaPrefix:
    Type: String
    Default: "IGNORED"
    Description: Deprecated parameter persisted for backwards compatibility.
  AppConfigDocumentRolePrefix:
    Type: String
    Default: "AppConfigAgentConfigurationDocumentRole-"
    Description: Prefix for the AWS AppConfig Configuration Document IAM Role.
  AppConfigDocumentPolicyPrefix:
    Type: String
    Default: "AppConfigAgentConfigurationDocumentPolicy-"
    Description: Prefix for the AWS AppConfig Configuration Document IAM Policy.
  UserPoolPrefix:
    Type: String
    Default: "CloudStorageSecUserPool-"
    Description: Prefix for the AWS Cognito User Pool.
  UserPoolClientPrefix:
    Type: String
    Default: "CloudStorageSecUserPoolClient-"
    Description: Prefix for the AWS Cognito User Pool Client.
  UserPoolRolePrefix:
    Type: String
    Default: "CloudStorageSecUserPoolRole-"
    Description: Prefix for the AWS Cognito User Pool IAM Role.
  UserPoolPolicyPrefix:
    Type: String
    Default: "CloudStorageSecUserPoolPolicy-"
    Description: Prefix for the AWS Cognito User Pool IAM Policy.
  ConsoleTaskRolePrefix:
    Type: String
    Default: "CloudStorageSecConsoleRole-"
    Description: Prefix for the Console ECS Task IAM Role.
  ConsoleTaskPolicyPrefix:
    Type: String
    Default: "CloudStorageSecConsolePolicy-"
    Description: Prefix for the Console ECS Task IAM Policy.
  AgentTaskRolePrefix:
    Type: String
    Default: "CloudStorageSecAgentRole-"
    Description: Prefix for the Agent ECS Task IAM Role.
  AgentTaskPolicyPrefix:
    Type: String
    Default: "CloudStorageSecAgentPolicy-"
    Description: Prefix for the Agent ECS Task IAM Policy.
  CrossAccountRolePrefix:
    Type: String
    Default: "CloudStorageSecRemoteRole-"
    Description: Prefix for the Cross-Account Scanning Role.
  OrganizationsRolePrefix:
    Type: String
    Default: "CloudStorageSecOrganizationsRole-"
    Description: Prefix for the AWS Organizations Integration Role.
  OrganizationsPolicyPrefix:
    Type: String
    Default: "CloudStorageSecOrganizationsPolicy-"
    Description: Prefix for the AWS Organizations Integration Policy.
  CrossAccountPolicyPrefix:
    Type: String
    Default: "CloudStorageSecRemotePolicy-"
    Description: Prefix for the Cross-Account Scanning Policy.
  CrossAccountEventBridgeRolePrefix:
    Type: String
    Default: "CloudStorageSecEventBridgeRole-"
    Description: Prefix for the Cross-Account Event Bridge Scanning Role.
  CrossAccountEventBridgePolicyPrefix:
    Type: String
    Default: "CloudStorageSecEventBridgePolicy-"
    Description: Prefix for the Cross-Account Event Bridge Scanning Policy.
  ExecutionRolePrefix:
    Type: String
    Default: "CloudStorageSecExecutionRole-"
    Description: Prefix for the ECS Execution Role.
  Ec2ContainerRolePrefix:
    Type: String
    Default: "CloudStorageSecEc2ContainerRole-"
    Description: Prefix for the EC2 ECS Container Role.
  Ec2ContainerPolicyPrefix:
    Type: String
    Default: "CloudStorageSecEc2ContainerPolicy-"
    Description: Prefix for the EC2 ECS Container Policy.
  ClusterPrefix:
    Type: String
    Default: "CloudStorageSecCluster-"
    Description: Prefix for the ECS Cluster.
  ServicePrefix:
    Type: String
    Default: "CloudStorageSecConsoleService-"
    Description: Prefix for the ECS Console Service.
  TaskDefinitionPrefix:
    Type: String
    Default: "CloudStorageSecConsole-"
    Description: Prefix for the ECS Console Task Definition.
  ConsoleSecurityGroupPrefix:
    Type: String
    Default: "CloudStorageSecConsoleSecurityGroup-"
    Description: Prefix for the Console Security Group.
  LoadBalancerPrefix:
    Type: String
    Default: "CloudStorageSecLB-"
    Description: Prefix for the Load Balancer (if using a Load Balancer).
  TargetGroupPrefix:
    Type: String
    Default: "CloudStorageSecTG-"
    Description: Prefix for the Load Balancer Target Group (if using a Load Balancer).
  LoadBalancerGroupPrefix:
    Type: String
    Default: "CloudStorageSecLBSecurityGroup-"
    Description: Prefix for the Load Balancer Security Group (if using a Load Balancer).
  ApiLoadBalancerPrefix:
    Type: String
    Default: "CloudStorageSecApiLB-"
    Description: Prefix for the API Load Balancer.
  ApiTargetGroupPrefix:
    Type: String
    Default: "CloudStorageSecApiTG-"
    Description: Prefix for the API Load Balancer Target Group.
  ParametersPrefix:
    Type: String
    Default: "CloudStorageSecConsole-"
    Description: Prefix for the Systems Manager Parameters.
  NotificationsTopicPrefix:
    Type: String
    Default: "CloudStorageSecNotificationsTopic-"
    Description: Prefix for the notifications topic.
  EventBasedScanTopicPrefix:
    Type: String
    Default: "CloudStorageSecTopic-"
    Description: Prefix for the event based scanning SNS Topic.
  EventBasedScanQueuePrefix:
    Type: String
    Default: "CloudStorageSecQueue-"
    Description: Prefix for the event based scanning SQS Queue.
  DcEventBasedScanQueuePrefix:
    Type: String
    Default: "CloudStorageSecQueue-DC-"
    Description: Prefix for the Data Classification event based scanning SQS Queue.
  RetroScanQueuePrefix:
    Type: String
    Default: "CloudStorageSecRetroQueue-"
    Description: Prefix for the retro-active scanning SQS Queue.
  EfsScanQueuePrefix:
    Type: String
    Default: "CloudStorageSecQueue-EFS-"
    Description: Prefix for the EFS based scanning SQS Queue.
  FsxScanQueuePrefix:
    Type: String
    Default: "CloudStorageSecQueue-FSx-"
    Description: Prefix for the FSx based scanning SQS Queue.
  ScannedItemsQueuePrefix:
    Type: String
    Default: "CloudStorageSecQueue-ScannedItems-"
    Description: Prefix for the scanned items SQS Queue.
  EventAgentTaskPrefix:
    Type: String
    Default: "CloudStorageSecAgent-"
    Description: Prefix for the ECS Event Agent Task.
  EventAgentServicePrefix:
    Type: String
    Default: "CloudStorageSecAgentService-"
    Description: Prefix for the ECS Event Agent Service.
  DcEventAgentTaskPrefix:
    Type: String
    Default: "CloudStorageSecAgent-DC-"
    Description: Prefix for the ECS Data Classification Event Agent Task.
  DcEventAgentServicePrefix:
    Type: String
    Default: "CloudStorageSecAgentService-DC-"
    Description: Prefix for the ECS Data Classification Event Agent Service.
  LargeFileAgentTaskPrefix:
    Type: String
    Default: "CloudStorageSecLargeFileAgent-"
    Description: Prefix for the ECS Large File Agent Task
  EfsAgentTaskPrefix:
    Type: String
    Default: "CloudStorageSecAgent-EFS-"
    Description: Prefix for the EFS Agent Task.
  EbsAgentTaskPrefix:
    Type: String
    Default: "CloudStorageSecAgent-EBS-"
    Description: Prefix for the EBS Agent Task.
  DcEbsAgentTaskPrefix:
    Type: String
    Default: "CloudStorageSecAgent-EBS-DC-"
    Description: Prefix for the DC EBS Agent Task.
  Ec2ScanTaskPrefix:
    Type: String
    Default: "CloudStorageSec-EC2Scan-"
    Description: Prefix for the EC2 Based Scan Task.
  ApiAgentTaskPrefix:
    Type: String
    Default: "CloudStorageSecApiAgent-"
    Description: Prefix for the ECS API Agent Task.
  ApiAgentServicePrefix:
    Type: String
    Default: "CloudStorageSecApiAgentService-"
    Description: Prefix for the ECS API Agent Service.
  EfsAgentServicePrefix:
    Type: String
    Default: "CloudStorageSecEfsAgentService-"
    Description: Prefix for the ECS EFS Agent Service.
  RetroAgentTaskPrefix:
    Type: String
    Default: "CloudStorageSecRetroAgent-"
    Description: Prefix for the ECS Retro Agent Task.
  RetroAgentServicePrefix:
    Type: String
    Default: "CloudStorageSecRetroAgentService-"
    Description: Prefix for the ECS Retro Agent Service.
  LargeEventQueueAlarmPrefix:
    Type: String
    Default: "CloudStorageSecLargeQueue-"
    Description: Prefix for the Alarm triggered when event queue is backed up.
  SmallEventQueueAlarmPrefix:
    Type: String
    Default: "CloudStorageSecSmallQueue-"
    Description: Prefix for the Alarm triggered when event queue is within normal range.
  DecreaseAgentsScalingPolicyPrefix:
    Type: String
    Default: "DecreaseAgents-"
    Description: Prefix for the AutoScaling policy to decrease running agent count.
  IncreaseAgentsScalingPolicyPrefix:
    Type: String
    Default: "IncreaseAgents-"
    Description: Prefix for the AutoScaling policy to increase running agent count.
  LargeDcEventQueueAlarmPrefix:
    Type: String
    Default: "CloudStorageSecLargeQueue-DC-"
    Description: Prefix for the Alarm triggered when Data Classification event queue is backed up.
  SmallDcEventQueueAlarmPrefix:
    Type: String
    Default: "CloudStorageSecSmallQueue-DC-"
    Description: Prefix for the Alarm triggered when Data Classification event queue is within normal range.
  DecreaseDcAgentsScalingPolicyPrefix:
    Type: String
    Default: "DecreaseAgents-DC-"
    Description: Prefix for the AutoScaling policy to decrease running Data Classification agent count.
  IncreaseDcAgentsScalingPolicyPrefix:
    Type: String
    Default: "IncreaseAgents-DC-"
    Description: Prefix for the AutoScaling policy to increase running Data Classification agent count.
  ApiRequestScalingPolicyPrefix:
    Type: String
    Default: "ApiServiceRequestScaling-"
    Description: Prefix for the AutoScaling policy for the API Service.
  ApiCpuScalingPolicyPrefix:
    Type: String
    Default: "ApiServiceCpuScaling-"
    Description: Prefix for the AutoScaling policy for the API Service.
  RetroQueueNotEmptyAlarmPrefix:
    Type: String
    Default: "CloudStorageSecRetroQueueNotEmpty-"
    Description: Prefix for the Alarm triggered when retro queue is not empty.
  RetroQueueEmptyAlarmPrefix:
    Type: String
    Default: "CloudStorageSecRetroQueueEmpty-"
    Description: Prefix for the Alarm triggered when retro queue is empty.
  RemoveRetroAgentsScalingPolicyPrefix:
    Type: String
    Default: "RemoveRetroAgents-"
    Description: Prefix for the AutoScaling policy to stop running retro agents.
  SetRetroAgentsScalingPolicyPrefix:
    Type: String
    Default: "SetRetroAgents-"
    Description: Prefix for the AutoScaling policy to set running retro agent count.
  AgentSecurityGroupPrefix:
    Type: String
    Default: "CloudStorageSecAgentSecurityGroup-"
    Description: Prefix for the security group used by scanning agents.
  EfsScanSecurityGroupPrefix:
    Type: String
    Default: "CloudStorageSecEFSScan-"
    Description: Prefix for the security group used to scan EFS volumes.
  EbsScanSecurityGroupPrefix:
    Type: String
    Default: "CloudStorageSecEBSScan-"
    Description: Prefix for the security group used to scan EBS volumes.
  FsxScanSecurityGroupPrefix:
    Type: String
    Default: "CloudStorageSecFSxScan-"
    Description: Prefix for the security group used to scan FSx volumes.
  CloudTrailLakeEventDataStorePrefix:
    Type: String
    Default: "CloudStorageSecCloudTrailLake-"
    Description: Prefix for the event data store for CloudTrail Lake -- only used if you don't specify your own data store above.
  CloudTrailLakeChannelPrefix:
    Type: String
    Default: "CloudStorageSecCloudTrailLake-"
    Description: Prefix for the ingestion channel for CloudTrail Lake.
  QuarantineBucketDaysToExpire:
    Type: Number
    Default: 0
    MinValue: 0
    MaxValue: 1000
    Description: Number of days the quarantined files will be retained before deletion. For infinite retention, leave it at zero.
  # EfsCrossVpcNetworking:
  #   Type: String
  #   Default: "VpcPeering"
  #   AllowedValues: ["Disabled", "VpcPeering"]
  #   Description: How the app should set up infrastructure to enable communication between a scan task in one VPC and an EFS volume in another VPC.
  AutoProtectBucketTagKey:
    Type: String
    Default: "default"
    Description: Key of the bucket tag that indicates that protection must be automatically turned on for the bucket ("default" = CloudStorageSecAutoProtect-{7 character application id})
  ConsoleTaskRoleArn:
    Type: String
    Default: "Created by CFT"
    Description: Role ARN for the Console ECS Task
  ConsoleEc2ManagementPolicyArn:
    Type: String
    Default: "Created by CFT"
    Description: Role ARN for the Console EC2 Management Policy
  ConsoleInfrastructureManagementPolicyArn:
    Type: String
    Default: "Created by CFT"
    Description: Role ARN for the Infrastructure and Management Policy
  ConsoleLoggingAndMonitoringPolicyArn:
    Type: String
    Default: "Created by CFT"
    Description: Role ARN for the Logging and Monitoring Policy
  ConsoleApplicationResourcesPolicyArn:
    Type: String
    Default: "Created by CFT"
    Description: Role ARN for the Console Application Resources Policy
  ConsoleSecurityAndAccessPolicyArn:
    Type: String
    Default: "Created by CFT"
    Description: Role ARN for the Security and Access Policy
  ConsoleTaskRoleName:
    Type: String
    Default: "Created by CFT"
    Description: Role name for the Console ECS Task
  AgentTaskRoleName:
    Type: String
    Default: "Created by CFT"
    Description: Role name for the Agent ECS Task
  AgentTaskRoleArn:
    Type: String
    Default: "Created by CFT"
    Description: Role ARN for the Agent ECS Task
  EventBridgeRoleArn:
    Type: String
    Default: "Created by CFT"
    Description: Role ARN for AWS Event Bridge execution
  EventBridgeRoleName:
    Type: String
    Default: "Created by CFT"
    Description: Role name for the AWS AWS Event Bridge execution
  ExecutionRoleArn:
    Type: String
    Default: "Created by CFT"
    Description: Role ARN for AWS ECS execution
  Ec2ContainerInstanceProfileArn:
    Type: String
    Default: "Created by CFT"
    Description: Instance Profile ARN for AWS ECS EC2 execution
  Ec2ContainerInstanceRoleName:
    Type: String
    Default: "Created by CFT"
    Description: Role Name for AWS ECS EC2 execution
  AppConfigAgentConfigurationDocumentRoleName:
    Type: String
    Default: "Created by CFT"
    Description: Role name for the AWS AppConfig Config Document
  AppConfigAgentConfigurationDocumentRoleArn:
    Type: String
    Default: "Created by CFT"
    Description: Role ARN for the AWS AppConfig Config Document
  UserPoolSnsRoleName:
    Type: String
    Default: "IGNORED"
    Description: Deprecated parameter persisted for backwards compatibility.
  UserPoolSnsRoleArn:
    Type: String
    Default: "Created by CFT"
    Description: Role ARN for the AWS Cognito User Pool SNS for MFA
  EnsureAutoScalingRoleExists:
    Type: String
    Default: "Yes"
    AllowedValues: ["Yes", "No"]
    Description: Would you like us to ensure the ECS Autoscaling Role exists (by registering the console as an AutoScalingGroup)?
  ProxyHost:
    Type: String
    Default: "none"
    Description: URL for proxy server
  ProxyPort:
    Type: String
    Default: "none"
    Description: Port for proxy server
  ProxyForce:
    Type: String
    Default: "No"
    AllowedValues: ["Yes", "No"]
    Description: Do you want AWS Service requests to use the proxy instead of VPC endpoints?
  ProductMode:
    Type: String
    Default: "AV"
    AllowedValues: ["AV", "Classification", "Both"]
    Description: Initial product mode for this deployment. Do not modify this value.
  TemplateVariation:
    Type: String
    Default: "default"
    Description: Do not modify this value, it is for specialized template use only.
  ParentStackName:
    Type: String
    Default: "default"
    Description: Do not modify this value, it is for specialized template use only.
  ProductListing:
    Type: String
    Default: "AV"
    AllowedValues: ["AV", "DC", "BYOL", "EFS", "MFT"]
    Description: Product Listing subscribed for this deployment. Do not modify this value.
Rules:
  SubnetsInVPC:
    Assertions:
      - AssertDescription: All subnets must belong to the VPC selected
        Assert: !EachMemberIn [!ValueOfAll ["AWS::EC2::Subnet::Id", "VpcId"], !RefAll "AWS::EC2::VPC::Id"]
  SubnetsMustDiffer:
    RuleCondition: !Equals [!Ref DeploymentType, "ECS"]
    Assertions:
      - AssertDescription: Subnet A and Subnet B must be different
        Assert: !Not [!Equals [!Ref SubnetA, !Ref SubnetB]]
  CheckConsoleCPUAndMem:
    Assertions:
      - AssertDescription: Console Memory needs to be in range (2x to 8x) of Console vCPU. If you select 0.5vCPU, then memory must be set between 1GB and 4GB.
        Assert:
          !Or [
            !And [!Equals [!Ref ConsoleCpu, "0.5vCPU"], !Contains [["1GB", "2GB", "3GB", "4GB"], !Ref ConsoleMemory]],
            !And [
              !Equals [!Ref ConsoleCpu, "1vCPU"],
              !Contains [["2GB", "3GB", "4GB", "5GB", "6GB", "7GB", "8GB"], !Ref ConsoleMemory],
            ],
            !And [
              !Equals [!Ref ConsoleCpu, "2vCPU"],
              !Contains [
                ["4GB", "5GB", "6GB", "7GB", "8GB", "9GB", "10GB", "11GB", "12GB", "13GB", "14GB", "15GB", "16GB"],
                !Ref ConsoleMemory,
              ],
            ],
            !And [
              !Equals [!Ref ConsoleCpu, "4vCPU"],
              !Contains [
                [
                  "8GB",
                  "9GB",
                  "10GB",
                  "11GB",
                  "12GB",
                  "13GB",
                  "14GB",
                  "15GB",
                  "16GB",
                  "17GB",
                  "18GB",
                  "19GB",
                  "20GB",
                  "21GB",
                  "22GB",
                  "23GB",
                  "24GB",
                  "25GB",
                  "26GB",
                  "27GB",
                  "28GB",
                  "29GB",
                  "30GB",
                ],
                !Ref ConsoleMemory,
              ],
            ],
          ]
  CheckAgentCPUAndMem:
    Assertions:
      - AssertDescription: Agent Memory needs to be in range (2x to 8x) of Agent vCPU. If you select 2vCPU, then memory must be set between 4GB and 16GB.
        Assert:
          !Or [
            !And [
              !Equals [!Ref AgentCpu, "1vCPU"],
              !Contains [["2GB", "3GB", "4GB", "5GB", "6GB", "7GB", "8GB"], !Ref AgentMemory],
            ],
            !And [
              !Equals [!Ref AgentCpu, "2vCPU"],
              !Contains [
                ["4GB", "5GB", "6GB", "7GB", "8GB", "9GB", "10GB", "11GB", "12GB", "13GB", "14GB", "15GB", "16GB"],
                !Ref AgentMemory,
              ],
            ],
            !And [
              !Equals [!Ref AgentCpu, "4vCPU"],
              !Contains [
                [
                  "8GB",
                  "9GB",
                  "10GB",
                  "11GB",
                  "12GB",
                  "13GB",
                  "14GB",
                  "15GB",
                  "16GB",
                  "17GB",
                  "18GB",
                  "19GB",
                  "20GB",
                  "21GB",
                  "22GB",
                  "23GB",
                  "24GB",
                  "25GB",
                  "26GB",
                  "27GB",
                  "28GB",
                  "29GB",
                  "30GB",
                ],
                !Ref AgentMemory,
              ],
            ],
          ]
  CheckApiAgentCPUAndMem:
    RuleCondition: !Equals [!Ref DeployApiAgent, "Yes"]
    Assertions:
      - AssertDescription: API Agent Memory needs to be in range (2x to 8x) of API Agent vCPU. If you select 1vCPU, then memory must be set between 2GB and 8GB.
        Assert:
          !Or [
            !And [
              !Equals [!Ref ApiAgentCpu, "1vCPU"],
              !Contains [["2GB", "3GB", "4GB", "5GB", "6GB", "7GB", "8GB"], !Ref ApiAgentMemory],
            ],
            !And [
              !Equals [!Ref ApiAgentCpu, "2vCPU"],
              !Contains [
                ["4GB", "5GB", "6GB", "7GB", "8GB", "9GB", "10GB", "11GB", "12GB", "13GB", "14GB", "15GB", "16GB"],
                !Ref ApiAgentMemory,
              ],
            ],
            !And [
              !Equals [!Ref ApiAgentCpu, "4vCPU"],
              !Contains [
                [
                  "8GB",
                  "9GB",
                  "10GB",
                  "11GB",
                  "12GB",
                  "13GB",
                  "14GB",
                  "15GB",
                  "16GB",
                  "17GB",
                  "18GB",
                  "19GB",
                  "20GB",
                  "21GB",
                  "22GB",
                  "23GB",
                  "24GB",
                  "25GB",
                  "26GB",
                  "27GB",
                  "28GB",
                  "29GB",
                  "30GB",
                ],
                !Ref ApiAgentMemory,
              ],
            ],
          ]
  CheckMinAgentsWhenScanningOnlyWhenQueueThresholdExceeded:
    Assertions:
      - AssertDescription: Minimum Number of Agents must be 0 when only scanning when queue threshold is exceeded, or greater than 0 otherwise
        Assert:
          !Or [
            !And [!Equals [!Ref OnlyScanWhenQueueThresholdExceeded, "Yes"], !Equals [!Ref MinRunningAgents, "0"]],
            !And [!Equals [!Ref OnlyScanWhenQueueThresholdExceeded, "No"], !Not [!Equals [!Ref MinRunningAgents, "0"]]],
          ]
  CheckAzureMinAgentsWhenScanningAzureOnlyWhenQueueThresholdExceeded:
    Assertions:
      - AssertDescription: Minimum Number of Azure Agents must be 0 when only scanning when queue threshold is exceeded, or greater than 0 otherwise
        Assert:
          !Or [
            !And [
              !Equals [!Ref AzureOnlyScanWhenQueueThresholdExceeded, "Yes"],
              !Equals [!Ref AzureMinRunningAgents, "0"],
            ],
            !And [
              !Equals [!Ref AzureOnlyScanWhenQueueThresholdExceeded, "No"],
              !Not [!Equals [!Ref AzureMinRunningAgents, "0"]],
            ],
          ]
  CheckSslCertWhenUsingLoadBalancer:
    Assertions:
      - AssertDescription: SSL Certificate ARN must be specified when using a Load Balancer
        Assert:
          !Or [
            !Equals [!Ref UseLoadBalancer, "No"],
            !Not [
              !Equals [
                !Ref Certificate,
                "arn:aws:acm:region:123456789012:certificate/00000000-0000-0000-0000-000000000000",
              ],
            ],
          ]
  LBSubnetsMustDiffer:
    Assertions:
      - AssertDescription: Load Balancer Subnet A and Subnet B must be different
        Assert:
          !Or [
            !Equals [!Ref UseLoadBalancer, "No"],
            !Or [!Equals [!Ref LBSubnetA, "enter-subnet-id"], !Not [!Equals [!Ref LBSubnetA, !Ref LBSubnetB]]],
          ]
  OptOutOnlyWithLB:
    Assertions:
      - AssertDescription: Cannot opt-out from sending info if you are not using a Load Balancer
        Assert: !Or [!Equals [!Ref UseLoadBalancer, "Yes"], !Equals [!Ref InfoOptOut, "No"]]
  CheckHostedZoneNameWhenUsingRoute53:
    Assertions:
      - AssertDescription: Must specify a hosted zone name or ID when using Route53
        Assert:
          !Or [
            !Equals [!Ref RegisterRoute53, "No"],
            !And [
              !Not [!Equals [!Ref HostedZoneName, "domain-for-your-ssl-cert.com"]],
              !Not [!Equals [!Ref HostedZoneId, "ZXXXXDEFAULTXXXXXXXXX"]],
            ],
            !And [
              !Not [!Equals [!Ref HostedZoneName, "domain-for-your-ssl-cert.com"]],
              !Equals [!Ref HostedZoneId, "ZXXXXDEFAULTXXXXXXXXX"],
            ],
          ]
  CheckSubdomainWhenUsingRoute53:
    Assertions:
      - AssertDescription: Must specify a hosted subdomain when using Route53
        Assert: !Or [!Equals [!Ref RegisterRoute53, "No"], !Not [!Equals [!Ref HostedSubdomain, "subdomain"]]]
  CheckUsingSophosIfEc2ScanningEnabled:
    Assertions:
      - AssertDescription: Must use Sophos or CSS Premium engine to enable EC2 large file scanning
        Assert:
          !Or [
            !And [
              !Equals [!Ref EnableLargeFileScanning, "Yes"],
              !Or [!Equals [!Ref AgentScanningEngine, "Sophos"], !Equals [!Ref AgentScanningEngine, "Bitdefender"]],
            ],
            !Equals [!Ref EnableLargeFileScanning, "No"],
          ]
  EnsureUSRegionIfUsingFips:
    Assertions:
      - AssertDescription: Must be deploying to a US region if enabling FIPS endpoints
        Assert:
          !Or [
            !Equals [!Ref UseFipsEndpoints, "No"],
            !Contains [
              ["us-east-1", "us-east-2", "us-west-1", "us-west-2", "us-gov-west-1", "us-gov-east-1"],
              !Ref AWS::Region,
            ],
          ]
  ValidateEKSClusterName:
    Assertions:
      - AssertDescription: EKS Cluster Name is required when DeploymentType is set to EKS
        Assert:
          !Or [
            !Not [!Equals [!Ref DeploymentType, "EKS"]],
            !Not [!Equals [!Ref EksClusterName, ""]]
          ]
  ValidateEKSNamespace:
    Assertions:
      - AssertDescription: EKS Namespace is required when DeploymentType is set to EKS
        Assert:
          !Or [
            !Not [!Equals [!Ref DeploymentType, "EKS"]],
            !Not [!Equals [!Ref EksNamespace, ""]]
          ]
  ValidateEKSConsoleServiceAccount:
    Assertions:
      - AssertDescription: EKS Console Service Account Name is required when DeploymentType is set to EKS
        Assert:
          !Or [
            !Not [!Equals [!Ref DeploymentType, "EKS"]],
            !Not [!Equals [!Ref EksConsoleServiceAccountName, ""]]
          ]
  ValidateEKSAgentServiceAccount:
    Assertions:
      - AssertDescription: EKS Agent Service Account Name is required when DeploymentType is set to EKS
        Assert:
          !Or [
            !Not [!Equals [!Ref DeploymentType, "EKS"]],
            !Not [!Equals [!Ref EksAgentServiceAccountName, ""]]
          ]
  ValidateIamOidcProvider:
    Assertions:
      - AssertDescription: IAM OIDC Provider Name is required when DeploymentType is set to EKS
        Assert:
          !Or [
            !Not [!Equals [!Ref DeploymentType, "EKS"]],
            !Not [!Equals [!Ref IamOidcProviderName, ""]]
          ]
  ApiAgentVpcRequiredWhenDeploying:
    RuleCondition: !Equals [!Ref DeployApiAgent, "Yes"]
    Assertions:
      - AssertDescription: API Agent VPC ID is required when Deploy API Agent is Yes
        Assert: !Not [!Equals [!Ref ApiAgentVpc, ""]]
  ApiAgentInboundCidrRequiredWhenDeploying:
    RuleCondition: !Equals [!Ref DeployApiAgent, "Yes"]
    Assertions:
      - AssertDescription: API Agent Inbound CIDR is required when Deploy API Agent is Yes
        Assert: !Not [!Equals [!Ref ApiAgentInboundCidr, ""]]
  ApiAgentSubnetsRequiredWhenDeploying:
    RuleCondition: !Equals [!Ref DeployApiAgent, "Yes"]
    Assertions:
      - AssertDescription: API Agent Subnets are required when Deploy API Agent is Yes
        Assert: !Not [!Equals [!Ref ApiAgentSubnets, ""]]
  ApiAgentLBSubnetsRequiredWhenDeploying:
    RuleCondition: !Equals [!Ref DeployApiAgent, "Yes"]
    Assertions:
      - AssertDescription: API Agent Load Balancer Subnets are required when Deploy API Agent is Yes
        Assert: !Not [!Equals [!Ref ApiAgentLBSubnets, ""]]
  ApiAgentSslCertArnRequiredWhenDeploying:
    RuleCondition: !Equals [!Ref DeployApiAgent, "Yes"]
    Assertions:
      - AssertDescription: API Agent SSL Certificate ARN must be specified when deploying API Agent
        Assert: !Not [!Equals [!Ref ApiAgentSslCertArn, "arn:aws:acm:region:123456789012:certificate/00000000-0000-0000-0000-000000000000"]]

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Parameters:
          - DeploymentType
        Label:
          default: Deployment Type
      - Parameters:
          - VPC
          - SubnetA
          - SubnetB
          - ConsoleSecurityGroup
          - ConsoleSecurityGroupCidrBlock
        Label:
          default: Network Configuration
      - Parameters:
          - ConsoleCpu
          - ConsoleMemory
          - UserName
          - Email
          - ConsoleAutoAssignPublicIp
          - DynamoPointInTimeRecoveryEnabled
          - StorageAssessmentEnabled
          - BucketsToProtect
          - S3BucketPrefixesRestrictedAccess
          - EventBridgeNotificationsEnabled
          - EventBridgeNotificationsBusName
        Label:
          default: Console Configuration
      - Parameters:
          - DeployApiAgent
          - ApiAgentVpc
          - ApiAgentSubnets
          - ApiAgentLBSubnets
          - ApiAgentInboundCidr
          - ApiAgentSslCertArn
          - ApiAgentInternetFacingLB
          - ApiAgentAllowedOrigins
          - ApiAgentMinAgents
          - ApiAgentMaxAgents
          - ApiAgentCpu
          - ApiAgentMemory
          - ApiAgentDiskSize
          - ApiAgentScanningEngine
          - ApiAgentEnableAsynchronousScanning
        Label:
          default: API Agent Configuration
      - Parameters:
          - AgentCpu
          - AgentMemory
          - AgentScanningEngine
          - MultiEngineScanningMode
          - LargeFileEngine
          - AgentDiskSize
          - RetroScanOnDetectedInfection
          - EnableLargeFileScanning
          - LargeFileDiskSize
          - LargeFileEC2Tags
          - EbsVolumeEncryption
          - EbsVolumeEncryptionKmsKeyId
          - S3KmsKeyId
          - AllowAccessToAllKmsKeys
          - CustomDynamoDBKmsKey
          - CustomSnsConsoleKmsKey
          - CustomSnsAgentKmsKeys
          - CustomSqsConsoleKmsKey
          - CustomSqsAgentKmsKeys
          - AgentAutoAssignPublicIp
          - QuarantineInPrimaryAccount
          - QuarantineBucketDaysToExpire
          - AutoProtectBucketTagKey
        Label:
          default: Agent Configuration
      - Parameters:
          - OnlyScanWhenQueueThresholdExceeded
          - MinRunningAgents
          - MaxRunningAgents
          - NumMessagesInQueueScalingThreshold
        Label:
          default: Agent Auto-Scaling Configuration
      - Parameters:
          - AzureOnlyScanWhenQueueThresholdExceeded
          - AzureMinRunningAgents
          - AzureMaxRunningAgents
          - AzureNumMessagesInQueueScalingThreshold
        Label:
          default: Azure Agent Auto-Scaling Configuration
      - Parameters:
          - EnableGuardDutyS3MalwareIntegration
          - GuardDutyS3MalwareResultTypes
          - GuardDutyS3MalwareAdditionalScanning
          - EnableCloudTrailLake
          - CloudTrailLakeDataStoreName
          - CloudTrailLakeChannelName
          - DisableEBSScanning
          - DisableEFSScanning
          - DisableFSxScanning
          - UseFipsEndpoints
        Label:
          default: AWS Integration Configuration
      - Parameters:
          - UseLoadBalancer
          - TrustedLoadBalancerNetwork
          - ExistingTargetGroup
          - ContainerSecurityGroupLB
          - Certificate
          - LBScheme
          - LBSubnetA
          - LBSubnetB
          - RegisterRoute53
          - HostedZoneName
          - HostedZoneId
          - HostedSubdomain
          - InfoOptOut
        Label:
          default: Optional Load Balancer Configuration
      - Parameters:
          - CustomEcrAccount
        Label:
          default: Optional custom hosting of docker container images
      - Parameters:
          - EksClusterName
          - EksNamespace
          - EksConsoleServiceAccountName
          - EksAgentServiceAccountName
          - IamOidcProviderName
        Label:
          default: EKS Configuration
      - Parameters:
          - DynamoTableNamePrefix
          - QuarantineBucketNamePrefix
          - AppConfigApplicationPrefix
          - AppConfigEnvironmentPrefix
          - AppConfigDeploymentStrategyPrefix
          - AppConfigDocumentPrefix
          - AppConfigDocumentSchemaPrefix
          - AppConfigDocumentRolePrefix
          - AppConfigDocumentPolicyPrefix
          - UserPoolPrefix
          - UserPoolClientPrefix
          - UserPoolRolePrefix
          - UserPoolPolicyPrefix
          - ConsoleTaskRolePrefix
          - ConsoleTaskPolicyPrefix
          - AgentTaskRolePrefix
          - AgentTaskPolicyPrefix
          - CrossAccountRolePrefix
          - OrganizationsRolePrefix
          - OrganizationsPolicyPrefix
          - CrossAccountPolicyPrefix
          - CrossAccountEventBridgeRolePrefix
          - CrossAccountEventBridgePolicyPrefix
          - ExecutionRolePrefix
          - Ec2ContainerRolePrefix
          - Ec2ContainerPolicyPrefix
          - ClusterPrefix
          - ServicePrefix
          - TaskDefinitionPrefix
          - ConsoleSecurityGroupPrefix
          - LoadBalancerPrefix
          - TargetGroupPrefix
          - LoadBalancerGroupPrefix
          - ApiLoadBalancerPrefix
          - ApiTargetGroupPrefix
          - ParametersPrefix
          - NotificationsTopicPrefix
          - EventBasedScanTopicPrefix
          - EventBasedScanQueuePrefix
          - DcEventBasedScanQueuePrefix
          - RetroScanQueuePrefix
          - EventAgentTaskPrefix
          - EventAgentServicePrefix
          - DcEventAgentTaskPrefix
          - DcEventAgentServicePrefix
          - EfsAgentTaskPrefix
          - EfsScanQueuePrefix
          - EfsScanSecurityGroupPrefix
          - EbsScanSecurityGroupPrefix
          - FsxScanSecurityGroupPrefix
          - EbsAgentTaskPrefix
          - LargeFileAgentTaskPrefix
          - ApiAgentTaskPrefix
          - ApiAgentServicePrefix
          - EfsAgentServicePrefix
          - RetroAgentTaskPrefix
          - RetroAgentServicePrefix
          - LargeEventQueueAlarmPrefix
          - SmallEventQueueAlarmPrefix
          - DecreaseAgentsScalingPolicyPrefix
          - IncreaseAgentsScalingPolicyPrefix
          - LargeDcEventQueueAlarmPrefix
          - SmallDcEventQueueAlarmPrefix
          - DecreaseDcAgentsScalingPolicyPrefix
          - IncreaseDcAgentsScalingPolicyPrefix
          - ApiRequestScalingPolicyPrefix
          - ApiCpuScalingPolicyPrefix
          - RetroQueueNotEmptyAlarmPrefix
          - RetroQueueEmptyAlarmPrefix
          - RemoveRetroAgentsScalingPolicyPrefix
          - SetRetroAgentsScalingPolicyPrefix
          - AgentSecurityGroupPrefix
          - CloudTrailLakeEventDataStorePrefix
          - CloudTrailLakeChannelPrefix
        Label:
          default: "Optional AWS Resource Renaming (WARNING: do not change after initial deployment)"
      - Parameters:
          - ConsoleTaskRoleArn
          - ConsoleTaskRoleName
          - AgentTaskRoleArn
          - AgentTaskRoleName
          - ConsoleEc2ManagementPolicyArn
          - ConsoleInfrastructureManagementPolicyArn
          - ConsoleLoggingAndMonitoringPolicyArn
          - ConsoleApplicationResourcesPolicyArn
          - ConsoleSecurityAndAccessPolicyArn
          - ExecutionRoleArn
          - Ec2ContainerInstanceProfileArn
          - EventBridgeRoleArn
          - EventBridgeRoleName
          - Ec2ContainerInstanceRoleName
          - AppConfigAgentConfigurationDocumentRoleArn
          - AppConfigAgentConfigurationDocumentRoleName
          - UserPoolSnsRoleArn
          - UserPoolSnsRoleName
          - EnsureAutoScalingRoleExists
        Label:
          default: "Optional pre-existing role specification. These roles must exist before deployment and the trust relationships must match those in this template. Do not change these values if you would like the deployment to create roles"
      - Parameters:
          - ProxyHost
          - ProxyPort
          - ProxyForce
        Label:
          default: "Optional proxy configuration for AWS services that do not have available VPC Endpoints."
      - Parameters:
          - ProductMode
          - TemplateVariation
          - ParentStackName
          - LogGroupRetentionPolicy
          - ProductListing
        Label:
          default: "Deployment specific settings. These should generally be left at default values."
    ParameterLabels:
      DeploymentType:
        default: "Deployment Type"
      EksClusterName:
        default: "EKS Cluster Name"
      EksNamespace:
        default: "EKS Namespace"
      EksConsoleServiceAccountName:
        default: "EKS Console Service Account"
      EksAgentServiceAccountName:
        default: "EKS Agent Service Account Name"
      IamOidcProviderName:
        default: "IAM OIDC Provider Name"
      VPC:
        default: Virtual Private Cloud (VPC) ID
      SubnetA:
        default: Subnet A ID
      SubnetB:
        default: Subnet B ID
      ConsoleSecurityGroup:
        default: Console Security Group ID
      ConsoleSecurityGroupCidrBlock:
        default: Console Security Group CIDR Block
      ConsoleCpu:
        default: Console vCPU
      ConsoleMemory:
        default: Console Memory
      ConsoleAutoAssignPublicIp:
        default: Console Auto Assign Public IP
      BucketsToProtect:
        default: Buckets to Protect
      S3BucketPrefixesRestrictedAccess:
        default: Restrict Bucket Access by Prefixes
      EventBridgeNotificationsEnabled:
        default: Enable EventBridge Proactive Notifications
      EventBridgeNotificationsBusName:
        default: Bus name for EventBridge Proactive Notifications
      EnableCloudTrailLake:
        default: Enable CloudTrail Lake
      DisableEBSScanning:
        default: Disable EBS Scanning
      DisableEFSScanning:
        default: Disable EFS Scanning
      DisableFSxScanning:
        default: Disable FSx Scanning
      EnableGuardDutyS3MalwareIntegration:
        default: Enable GuardDuty S3 Malware Integration
      GuardDutyS3MalwareResultTypes:
        default: Result Types to Process
      GuardDutyS3MalwareAdditionalScanning:
        default: Perform Additional Scanning
      RetroScanOnDetectedInfection:
        default: Infected Results Trigger Existing File Scan
      CloudTrailLakeDataStoreName:
        default: CloudTrail Lake DataStore Name
      CloudTrailLakeChannelName:
        default: CloudTrail Lake Channel Name
      CrossAccountEventBridgeRolePrefix:
        default: Prefix for the Event Bridge Role
      CrossAccountEventBridgePolicyPrefix:
        default: Prefix for the Event Bridge Policy
      DeployApiAgent:
        default: Deploy API Agent
      ApiAgentVpc:
        default: API Agent VPC
      ApiAgentSubnets:
        default: API Agent Subnets
      ApiAgentLBSubnets:
        default: API Agent Load Balancer Subnets
      ApiAgentInboundCidr:
        default: API Agent Inbound Access CIDR
      ApiAgentSslCertArn:
        default: API Agent SSL Certificate ARN
      ApiAgentInternetFacingLB:
        default: API Agent Internet-Facing Load Balancer
      ApiAgentAllowedOrigins:
        default: API Agent Allowed Request Origins
      ApiAgentMinAgents:
        default: API Agent Minimum Running Agents
      ApiAgentMaxAgents:
        default: API Agent Maximum Running Agents
      ApiAgentCpu:
        default: API Agent vCPU
      ApiAgentMemory:
        default: API Agent Memory
      ApiAgentDiskSize:
        default: API Agent Disk Size
      ApiAgentScanningEngine:
        default: API Agent Scanning Engine
      ApiAgentEnableAsynchronousScanning:
        default: API Agent Enable Asynchronous Scanning
      AgentCpu:
        default: Agent vCPU
      AgentMemory:
        default: Agent Memory
      AgentScanningEngine:
        default: Agent Scanning Engine
      MultiEngineScanningMode:
        default: Multi-Engine Scanning Mode
      LargeFileEngine:
        default: Large File Engine
      AgentDiskSize:
        default: Agent Disk Size
      EnableLargeFileScanning:
        default: Enable Large File Scanning
      LargeFileDiskSize:
        default: Extra Large File Disk Size
      EbsVolumeEncryption:
        default: Enable EBS Volume Encryption
      EbsVolumeEncryptionKmsKeyId:
        default: EBS Volume Encryption KMS Key Id, ARN or Alias
      S3KmsKeyId:
        default: S3 Encryption KMS Key Id, ARN or Alias
      LargeFileEC2Tags:
        default: Extra Large File EC2 Tags
      AgentAutoAssignPublicIp:
        default: Agent Auto Assign Public IP
      MinRunningAgents:
        default: Minimum Number of Running Agents Per Region
      MaxRunningAgents:
        default: Maximum Number of Running Agents Per Region
      AzureMinRunningAgents:
        default: Minimum Number of Running Azure Agents
      AzureMaxRunningAgents:
        default: Maximum Number of Running Azure Agents
      NumMessagesInQueueScalingThreshold:
        default: Number of Messages in Queue to Trigger Agent Auto-Scaling
      AzureNumMessagesInQueueScalingThreshold:
        default: Number of Messages in Queue to Trigger Azure Agent Auto-Scaling
      OnlyScanWhenQueueThresholdExceeded:
        default: Only Run Scanning Agents When Files Are In Queue?
      AzureOnlyScanWhenQueueThresholdExceeded:
        default: Only Run Azure Scanning Agents When Files Are In Queue?
      QuarantineInPrimaryAccount:
        default: Quarantine objects into the primary account for infections in linked accounts?
      QuarantineBucketDaysToExpire:
        default: Expire (delete) quarantined objects after a specified number of days?
      AutoProtectBucketTagKey:
        default: Bucket auto protection tag key
      DynamoPointInTimeRecoveryEnabled:
        default: DynamoDB Point In Time Recovery
      AllowAccessToAllKmsKeys:
        default: Allow Access To All KMS Keys?
      CustomDynamoDBKmsKey:
        default: Custom KMS Key for DynamoDB
      CustomSnsConsoleKmsKey:
        default: Custom Console Region KMS Key for SNS
      CustomSqsConsoleKmsKey:
        default: Custom Console Region KMS Key for SQS
      CustomSqsAgentKmsKeys:
        default: Custom Agent KMS Keys for SQS
      CustomSnsAgentKmsKeys:
        default: Custom Agent KMS Keys for SNS
      StorageAssessmentEnabled:
        default: Allow Console To Run Storage Assessment?
      UseLoadBalancer:
        default: Use a Load Balancer for the Console?
      TrustedLoadBalancerNetwork:
        default: Trusted Custom Load Balancer Network
      ExistingTargetGroup:
        default: Existing Target Group
      ContainerSecurityGroupLB:
        default: Container Security Group ID
      Certificate:
        default: SSL Certificate ARN
      LBScheme:
        default: Load Balancer Scheme
      LBSubnetA:
        default: Load Balancer Subnet A ID
      LBSubnetB:
        default: Load Balancer Subnet B ID
      RegisterRoute53:
        default: Register a subdomain on Route53?
      HostedZoneName:
        default: Hosted Zone Name
      HostedZoneId:
        default: Hosted Zone ID
      HostedSubdomain:
        default: Subdomain
      InfoOptOut:
        default: Info Opt-Out
      CustomEcrAccount:
        default: Custom ECR Account
      ProxyHost:
        default: Proxy Host
      ProxyPort:
        default: Proxy Port
      ProxyForce:
        default: Use Proxy For All Requests
      ProductMode:
        default: Product Mode
      TemplateVariation:
        default: Template Variation
      ParentStackName:
        default: Parent Stack Name
      LogGroupRetentionPolicy:
        default: Set Log Group Retention Policy?
      UseFipsEndpoints:
        default: Use FIPS Endpoints?
  cfn-lint:
    config:
      ignore_checks:
        - W2001
Conditions:
  UseApiAgent: !Equals [!Ref DeployApiAgent, "Yes"]
  HasApiAgentAllowedOrigins: !Not [!Equals [!Ref ApiAgentAllowedOrigins, ""]]
  ApiAgentScanningEngineIsAll: !And
    - Condition: UseApiAgent
    - !Equals [!Ref ApiAgentScanningEngine, "All"]
  ApiAgentScanningEngineIsDefault: !And
    - Condition: UseApiAgent
    - !Equals [!Ref ApiAgentScanningEngine, "Default"]
  BlanketKmsAccess: !Equals [!Ref AllowAccessToAllKmsKeys, "Yes"]
  HasCustomDynamoDBKmsKey: !Not [!Equals [!Ref CustomDynamoDBKmsKey, ""]]
  HasCustomSqsConsoleKmsKey: !Not [!Equals [!Ref CustomSqsConsoleKmsKey, ""]]
  HasCustomSnsConsoleKmsKey: !Not [!Equals [!Ref CustomSnsConsoleKmsKey, ""]]
  HasCustomSqsAgentKmsKeys: !Not [!Equals [!Ref CustomSqsAgentKmsKeys, ""]]
  HasCustomSnsAgentKmsKeys: !Not [!Equals [!Ref CustomSnsAgentKmsKeys, ""]]
  HasCustomS3KmsKey: !Not [!Equals [!Ref S3KmsKeyId, "default"]]
  HasCustomEbsKmsKeys: !Not [!Equals [!Ref EbsVolumeEncryptionKmsKeyId, "default"]]
  HasAnyCustomKmsKey:
    Fn::Or:
      - Condition: HasCustomDynamoDBKmsKey
      - Condition: HasCustomSqsConsoleKmsKey
      - Condition: HasCustomSnsConsoleKmsKey
      - Condition: HasCustomSqsAgentKmsKeys
      - Condition: HasCustomSnsAgentKmsKeys
      - Condition: HasCustomEbsKmsKeys
  UseLB: !Equals [!Ref UseLoadBalancer, "Yes"]

  CreateLB: !And
    - Condition: UseLB
    - !Equals [!Ref ExistingTargetGroup, ""]
  ExistingLB: !And
    - Condition: UseLB
    - !Not [!Equals [!Ref ExistingTargetGroup, ""]]
  DontUseLB: !Equals [!Ref UseLoadBalancer, "No"]
  UseRoute53: !And
    - Condition: CreateLB
    - !Equals [!Ref RegisterRoute53, "Yes"]
  UseHostedZoneId: !And
    - Condition: UseRoute53
    - !Not [!Equals [!Ref HostedZoneId, "ZXXXXDEFAULTXXXXXXXXX"]]
  UseHostedZoneName: !And
    - Condition: UseRoute53
    - !Equals [!Ref HostedZoneId, "ZXXXXDEFAULTXXXXXXXXX"]
  UseLBSubnetA: !Not [!Equals [!Ref LBSubnetA, "enter-subnet-id"]]
  UseLBSubnetB: !Not [!Equals [!Ref LBSubnetB, "enter-subnet-id"]]
  UseDefaultDynamoPrefix: !Equals [!Ref DynamoTableNamePrefix, "7-character-application-id."]
  IsGovCloud: !Equals [!Ref AWS::Partition, "aws-us-gov"]
  IsPrivateDeployment: !Equals [!Ref TemplateVariation, "PrivateDeployment"]
  UseDefaultEcrAccount: !Equals [!Ref CustomEcrAccount, "default"]
  UseProxy: !Not [!Equals [!Ref ProxyHost, "none"]]
  CreateConsoleRole: !Equals [!Ref ConsoleTaskRoleArn, "Created by CFT"]
  CreateConsoleEc2ManagementPolicy: !Equals [!Ref ConsoleEc2ManagementPolicyArn, "Created by CFT"]
  CreateConsoleInfrastructureManagementPolicy: !Equals [!Ref ConsoleInfrastructureManagementPolicyArn, "Created by CFT"]
  CreateConsoleLoggingAndMonitoringPolicy: !Equals [!Ref ConsoleLoggingAndMonitoringPolicyArn, "Created by CFT"]
  CreateConsoleApplicationResourcesPolicy: !Equals [!Ref ConsoleApplicationResourcesPolicyArn, "Created by CFT"]
  CreateConsoleSecurityAndAccessPolicy: !Equals [!Ref ConsoleSecurityAndAccessPolicyArn, "Created by CFT"]
  CreateConsoleSecurityGroup: !Equals [!Ref ConsoleSecurityGroup, "Created by CFT"]
  UseExistingConsoleSecurityGroup: !Not [!Equals [!Ref ConsoleSecurityGroup, "Created by CFT"]]
  CreateConsoleSecurityGroupNoLB: !And
    - Condition: IsECSDeployment
    - Condition: DontUseLB
    - Condition: CreateConsoleSecurityGroup
  CreateConsoleSecurityGroupLB: !And
    - Condition: IsECSDeployment
    - Condition: UseLB
    - Condition: CreateConsoleSecurityGroup
  CreateContainerSecurityGroupLB: !And
    - Condition: IsECSDeployment
    - Condition: UseLB
    - !Equals [!Ref ContainerSecurityGroupLB, "Created by CFT"]
  UseExistingContainerSecurityGroupLB: !And
    - Condition: UseLB
    - !Not [!Equals [!Ref ContainerSecurityGroupLB, "Created by CFT"]]
  CreateAgentRole: !Equals [!Ref AgentTaskRoleArn, "Created by CFT"]
  CreateEventBridgeRole: !Equals [!Ref EventBridgeRoleArn, "Created by CFT"]
  CreateExecutionRole: !Equals [!Ref ExecutionRoleArn, "Created by CFT"]
  CreateEc2ContainerRole: !Equals [!Ref Ec2ContainerInstanceProfileArn, "Created by CFT"]
  CreateAppConfigDocRole: !Equals [!Ref AppConfigAgentConfigurationDocumentRoleArn, "Created by CFT"]
  CreateUserPoolSnsRole: !Equals [!Ref UserPoolSnsRoleArn, "Created by CFT"]
  CreateAutoScalingRole: !Equals [!Ref EnsureAutoScalingRoleExists, "Yes"]
  CreateAutoScalingRoleWithLb: !And [!Condition CreateAutoScalingRole, !Condition UseLB]
  CreateAutoScalingRoleWithoutLb: !And [!Condition CreateAutoScalingRole, !Condition DontUseLB]
  UseDefaultS3BucketPrefixesRestrictedAccess: !Equals [!Ref S3BucketPrefixesRestrictedAccess, "*"]
  UseDefaultAutoProtectBucketTagKey: !Equals [!Ref AutoProtectBucketTagKey, "default"]
  UseDefaultCloudTrailLakeEventDataStoreName: !Equals [!Ref CloudTrailLakeDataStoreName, "default"]
  UseDefaultCloudTrailLakeChannelName: !Equals [!Ref CloudTrailLakeChannelName, "default"]
  UseCurrentRegionForGuardDutyS3Integration: !Equals [!Ref EnableGuardDutyS3MalwareIntegration, "Yes"]
  CreateCustomEventBridgeBus:
    !And [
      !Equals [!Ref EventBridgeNotificationsEnabled, "Yes"],
      !Not [!Equals [!Ref EventBridgeNotificationsBusName, "default"]],
    ]
  EventBridgeNotificationsEnabledYes: !Equals [!Ref EventBridgeNotificationsEnabled, "Yes"]
  SetLogGroupRetentionPolicy: !Equals [!Ref LogGroupRetentionPolicy, "Yes"]
  HasParentStack: !Not [!Equals [!Ref ParentStackName, "default"]]
  IsECSDeployment: !Equals [!Ref DeploymentType, "ECS"]
  IsEKSDeployment: !Equals [!Ref DeploymentType, "EKS"]
  IsEKSDeploymentWithTrustedNetwork: !And [!Condition IsEKSDeployment, !Not [!Equals [!Ref TrustedLoadBalancerNetwork, ""]]]
  IsEKSDeploymentWithSqsKms: !And [!Condition IsEKSDeployment, !Condition HasCustomSqsConsoleKmsKey]
  IsEKSDeploymentWithSnsKms: !And [!Condition IsEKSDeployment, !Condition HasCustomSnsConsoleKmsKey]
  IsEKSDeploymentWithSqsAgentKms: !And [!Condition IsEKSDeployment, !Condition HasCustomSqsAgentKmsKeys]
  IsEKSDeploymentWithSnsAgentKms: !And [!Condition IsEKSDeployment, !Condition HasCustomSnsAgentKmsKeys]
  IsEKSDeploymentWithProxy: !And [!Condition IsEKSDeployment, !Condition UseProxy]
  IsEKSDeploymentWithBucketsToProtect: !And [!Condition IsEKSDeployment, !Not [!Equals [!Ref BucketsToProtect, ""]]]
  IsECSDeploymentDontUseLB: !And [!Condition IsECSDeployment, !Condition DontUseLB]
  IsECSDeploymentCreateLB: !And [!Condition IsECSDeployment, !Condition CreateLB]
  IsECSDeploymentExistingLB: !And [!Condition IsECSDeployment, !Condition ExistingLB]
  IsECSDeploymentCreateAutoScalingRoleWithLb: !And [!Condition IsECSDeployment, !Condition CreateAutoScalingRoleWithLb]
  IsECSDeploymentCreateAutoScalingRoleWithoutLb: !And [!Condition IsECSDeployment, !Condition CreateAutoScalingRoleWithoutLb]
  IsECSDeploymentUseHostedZoneName: !And [!Condition IsECSDeployment, !Condition UseHostedZoneName]
  IsECSDeploymentUseHostedZoneId: !And [!Condition IsECSDeployment, !Condition UseHostedZoneId]
  IsECSDeploymentWithService: !Or [!Condition IsECSDeploymentDontUseLB, !Condition IsECSDeploymentCreateLB, !Condition IsECSDeploymentExistingLB]
  IsPrivateOrEksDeployment: !Or
    - !Condition IsPrivateDeployment
    - !Condition IsEKSDeployment
Mappings:
  Constants:
    Version:
      ImageVersionConsole: v9.09.000
      ImageVersionAgent: v9.09.000
  yesNoToBool:
    "Yes":
      "value": true
    "No":
      "value": false
  vCPUvalues:
    "0.5vCPU":
      "size": 512
    "1vCPU":
      "size": 1024
    "2vCPU":
      "size": 2048
    "4vCPU":
      "size": 4096
  MemValues:
    "1GB":
      "size": 1024
    "2GB":
      "size": 2048
    "3GB":
      "size": 3072
    "4GB":
      "size": 4096
    "5GB":
      "size": 5120
    "6GB":
      "size": 6144
    "7GB":
      "size": 7168
    "8GB":
      "size": 8192
    "9GB":
      "size": 9216
    "10GB":
      "size": 10240
    "11GB":
      "size": 11264
    "12GB":
      "size": 12288
    "13GB":
      "size": 13312
    "14GB":
      "size": 14336
    "15GB":
      "size": 15360
    "16GB":
      "size": 16384
    "17GB":
      "size": 17408
    "18GB":
      "size": 18432
    "19GB":
      "size": 19456
    "20GB":
      "size": 20480
    "21GB":
      "size": 21504
    "22GB":
      "size": 22528
    "23GB":
      "size": 23552
    "24GB":
      "size": 24576
    "25GB":
      "size": 25600
    "26GB":
      "size": 26624
    "27GB":
      "size": 27648
    "28GB":
      "size": 28672
    "29GB":
      "size": 29696
    "30GB":
      "size": 30720
  Strings:
    AV:
      "WelcomeMessage": "Antivirus for Amazon S3 - Console Account Information"
    DC:
      "WelcomeMessage": "Data Classification for Amazon S3 - Console Account Information"
    BYOL:
      "WelcomeMessage": "Antivirus for Amazon S3 - Console Account Information"
    S3:
      "WelcomeMessage": "Malware protection for Amazon S3 - Console Account Information"
    EFS:
      "WelcomeMessage": "Malware protection and Data Loss Prevention for EFS - Console Account Information"
    MFT:
      "WelcomeMessage": "Antivirus for Managed File Transfers - Console Account Information"
  ProductListingToProductCode:
    AV:
      code: "5fntfbsg62pj9xsg3zl5w0oop"
    BYOL:
      code: "uovf396zk0znco1qeohh29c5"
    DC:
      code: "dzklggufqavoho21d3aoxret2"
    MFT:
      code: "17wmgxm8as21zwy5bj8nagnvc"
    EFS:
      code: "5r373esgftdq1eb3rauhloapb"
Resources:
  AppConfigAgentApplication:
    Type: AWS::AppConfig::Application
    Properties:
      Description: AppConfig Application for CloudStorageSec Agents
      Name: !Join
        - ""
        - - !Ref AppConfigApplicationPrefix
          - !Select
            - 0
            - !Split
              - "-"
              - !Select
                - 2
                - !Split
                  - "/"
                  - !Ref AWS::StackId
  AppConfigAgentEnvironment:
    Type: AWS::AppConfig::Environment
    Properties:
      ApplicationId: !Ref AppConfigAgentApplication
      Name: !Sub "${AppConfigEnvironmentPrefix}${AppConfigAgentApplication}"
      Description: "AppConfig Environment for CloudStorageSec Agents"
  AppConfigAgentConfigurationDocumentRole:
    Type: AWS::IAM::Role
    Condition: CreateAppConfigDocRole
    Properties:
      RoleName: !Sub "${AppConfigDocumentRolePrefix}${AppConfigAgentApplication}"
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service: "appconfig.amazonaws.com"
            Action: "sts:AssumeRole"
  AppConfigAgentConfigurationDocumentPolicy:
    Type: "AWS::IAM::Policy"
    Properties:
      PolicyName: !Sub "${AppConfigDocumentPolicyPrefix}${AppConfigAgentApplication}"
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Action:
              - ssm:GetDocument
            Resource:
              - !Sub "arn:${AWS::Partition}:ssm:*:*:document/${AppConfigDocument}"
      Roles:
        - !If [
            CreateAppConfigDocRole,
            !Ref AppConfigAgentConfigurationDocumentRole,
            !Ref AppConfigAgentConfigurationDocumentRoleName,
          ]
  AppConfigAgentDeploymentStrategy:
    Type: AWS::AppConfig::DeploymentStrategy
    Properties:
      Name: !Sub "${AppConfigDeploymentStrategyPrefix}${AppConfigAgentApplication}"
      Description: "AppConfig Deployment Strategy for CloudStorageSec Agents"
      DeploymentDurationInMinutes: 0
      FinalBakeTimeInMinutes: 0
      GrowthFactor: 100
      GrowthType: LINEAR
      ReplicateTo: NONE
  AppConfigDocumentSchema:
    Type: "AWS::SSM::Document"
    DependsOn: ConsoleIAMPolicy
    Properties:
      DocumentType: ApplicationConfigurationSchema
      DocumentFormat: JSON
      Content: '{"$schema": "http://json-schema.org/draft-07/schema#","description": "Configuration for CloudStorageScan","type": "object","required": ["objectTagKeys","quarantine","scanList","skipList","classifyList","classifySkipList","scanTaggingEnabled","scanTagsExcluded","classificationTaggingEnabled","classificationTagsExcluded"],"properties": {"consoleUrl": {"type": "string","description": "URL of the Console."},"scanTaggingEnabled": {"type": "boolean","description": "Indicates whether tags should be added to the scanned objects."},"classificationCustomRulesLastUpdated": {"type": "string","description": "Last time a Classification Custom Rule was updated."},"scanTagsExcluded": {"type": "array","description": "Scan tags to not be added to scanned objects","items": {"type": "string"},"uniqueItems": true,"additionalProperties": false},"classificationTaggingEnabled": {"type": "boolean","description": "Indicates whether tags should be added to the classified objects."},"classificationTagsExcluded": {"type": "array","description": "Classification tags to not be added to classified objects","items": {"type": "string"},"uniqueItems": true,"additionalProperties": false},"avEventProtectedBuckets": {"type": "array","items": {"type": "string"},"uniqueItems": true,"additionalProperties": false},"avScheduledBuckets": {"type": "array","items": {"type": "string"},"uniqueItems": true,"additionalProperties": false},"efsClassificationRuleSets": {"type": "object","patternProperties": {"^[a-zA-Z]+$": {"type": "array","items": {"type": "string"},"additionalProperties": false}}},"dcEventBucketRuleSets": {"type": "object","patternProperties": {"^[a-zA-Z]+$": {"type": "array","items": {"type": "string"},"additionalProperties": false}}},"dcScheduledBucketRuleSets": {"type": "object","patternProperties": {"^[a-zA-Z]+$": {"type": "array","items": {"type": "string"},"additionalProperties": false}}},"ebsClassificationRuleSets": {"type": "object","patternProperties": {"^[a-zA-Z]+$": {"type": "array","items": {"type": "string"},"additionalProperties": false}}},"fsxClassificationRuleSets": {"type": "object","patternProperties": {"^[a-zA-Z]+$": {"type": "array","items": {"type": "string"},"additionalProperties": false}}},"classificationRuleSets": {"type": "object","patternProperties": {"^[a-zA-Z]+$": {"type": "array","items": {"type": "string"},"additionalProperties": false}}},"objectTagKeys": {"type": "object","required": ["result","dateScanned","virusName","virusUploadedBy","errorMessage","classificationResult","dateClassified","classificationMatches","classificationErrorMessage"],"properties": {"result": {"type": "string","description": "The tag key for scan results."},"dateScanned": {"type": "string","description": "The tag key for the scan date."},"virusName": {"type": "string","description": "The tag key for the virus name."},"virusUploadedBy": {"type": "string","description": "The tag key for who uploaded the virus."},"errorMessage": {"type": "string","description": "The tag key for the error message."},"classificationResult": {"type": "string","description": "The tag key for classification results."},"dateClassified": {"type": "string","description": "The tag key for the classification date."},"classificationMatches": {"type": "string","description": "The tag key for the list of classification matches found."},"classificationErrorMessage": {"type": "string","description": "The tag key for the classification error message."}}},"quarantine": {"type": "object","required": ["action","moveBucketPrefix"],"properties": {"action": {"type": "string","pattern": "Keep|Move|Delete","description": "Action to take on an object upon a virus being detected."},"moveBucketPrefix": {"type": "string","description": "Bucket to move infected objects to."}}},"scanList": {"type": "object","patternProperties": {"^[a-zA-Z]+$": {"type": "array","items": {"type": "string"},"additionalProperties": false}}},"skipList": {"type": "object","patternProperties": {"^[a-zA-Z]+$": {"type": "array","items": {"type": "string"},"additionalProperties": false}}},"classifyList": {"type": "object","patternProperties": {"^[a-zA-Z]+$": {"type": "array","items": {"type": "string"},"additionalProperties": false}}},"classifySkipList": {"type": "object","patternProperties": {"^[a-zA-Z]+$": {"type": "array","items": {"type": "string"},"additionalProperties": false}}},"twoBucketConfig": {"type": "object","properties": {"regions": {"type": "object","patternProperties": {"^(us(-gov)?|af|ap|ca|cn|eu|me|sa)-(central|(north|south)?(east|west)?)-[1-9]$": {"type": "object","properties": {"destinationBucket": {"type": "string","description": "The bucket to move files to"},"destinationPrefix": {"type": "string","description": "The prefix to use within the destination bucket"}},"additionalProperties": false}},"additionalProperties": false},"buckets": {"type": "object","patternProperties": {"^[a-zA-Z0-9-._]{1,255}$": {"type": "object","properties": {"destinationBucket": {"type": "string","description": "The bucket to move files to"},"destinationPrefix": {"type": "string","description": "The prefix to use within the destination bucket"}},"additionalProperties": false}},"additionalProperties": false}},"additionalProperties": false}},"additionalProperties": false}'
      Name: !Sub "${AppConfigDocumentPrefix}Schema-${AppConfigAgentApplication}"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "ConfigSchema"
      UpdateMethod: NewVersion
    Metadata:
      cfn-lint:
        config:
          ignore_checks: [E1101,E3051] # The content string IS a string, but cfn-lint blows up on it
  AppConfigDocument:
    Type: "AWS::SSM::Document"
    Properties:
      DocumentType: ApplicationConfiguration
      DocumentFormat: JSON
      Content: !Sub '{"scanTaggingEnabled":true,"scanTagsExcluded":[],"classificationTaggingEnabled":true,"classificationTagsExcluded":[],"objectTagKeys":{"result":"scan-result","dateScanned":"date-scanned","virusName":"virus-name","virusUploadedBy":"uploaded-by","errorMessage":"message","classificationResult":"classification-result","dateClassified":"date-classified","classificationMatches":"classification-matches","classificationErrorMessage":"classification-message"},"quarantine":{"action":"Move","moveBucketPrefix":"${QuarantineBucketNamePrefix}${AppConfigAgentApplication}"},"scanList":{},"skipList":{},"classifyList":{},"classifySkipList":{}}'
      Name: !Sub "${AppConfigDocumentPrefix}Doc-${AppConfigAgentApplication}"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "ConfigDoc"
      Requires:
        - Name: !Ref AppConfigDocumentSchema
          Version: $LATEST
      UpdateMethod: NewVersion
  AppConfigProfile:
    Type: "AWS::AppConfig::ConfigurationProfile"
    DependsOn: AppConfigAgentConfigurationDocumentPolicy
    Properties:
      ApplicationId: !Ref AppConfigAgentApplication
      Description: "AppConfig profile for CloudStorageSec Agents"
      Name: !Sub "${AppConfigDocumentPrefix}Profile-${AppConfigAgentApplication}"
      LocationUri: !Sub "ssm-document://${AppConfigDocument}"
      RetrievalRoleArn:
        !If [
          CreateAppConfigDocRole,
          !GetAtt AppConfigAgentConfigurationDocumentRole.Arn,
          !Ref AppConfigAgentConfigurationDocumentRoleArn,
        ]
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "ConfigProfile"
      Type: AWS.Freeform
  AppConfigAgentDeployment:
    Type: AWS::AppConfig::Deployment
    Properties:
      ApplicationId: !Ref AppConfigAgentApplication
      EnvironmentId: !Ref AppConfigAgentEnvironment
      ConfigurationProfileId: !Ref AppConfigProfile
      DeploymentStrategyId: !Ref AppConfigAgentDeploymentStrategy
      ConfigurationVersion: 1
      Description: "AppConfig Deployment for CloudStorageSec Agents"
  ProactiveMonitorStatusesTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "Name"
          AttributeType: "S"
        - AttributeName: "Region"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "Name"
          KeyType: "HASH"
        - AttributeName: "Region"
          KeyType: "RANGE"
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}ProactiveMonitorStatuses"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  BucketsTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "Name"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "Name"
          KeyType: "HASH"
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}Buckets"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  ClassificationCustomRulesTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "Id"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "Id"
          KeyType: "HASH"
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}ClassificationCustomRules"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  DashboardReportsTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "PK"
          AttributeType: "S"
        - AttributeName: "SK"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "PK"
          KeyType: "HASH"
        - AttributeName: "SK"
          KeyType: "RANGE"
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}DashboardReports"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  EfsVolumesTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "Id"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "Id"
          KeyType: "HASH"
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}EfsVolumes"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  EbsVolumesTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "Id"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "Id"
          KeyType: "HASH"
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}EbsVolumes"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  EmailTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "PK"
          AttributeType: "S"
        - AttributeName: "SK"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "PK"
          KeyType: "HASH"
        - AttributeName: "SK"
          KeyType: "RANGE"
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}Email"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  FsxVolumesTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "Id"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "Id"
          KeyType: "HASH"
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}FsxVolumes"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  SubnetsTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "Region"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "Region"
          KeyType: "HASH"
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}Subnets"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  JobNetworkingTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "PK"
          AttributeType: "S"
        - AttributeName: "SK"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "PK"
          KeyType: "HASH"
        - AttributeName: "SK"
          KeyType: "RANGE"
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}JobNetworking"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  StorageAnalysisTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "BucketName"
          AttributeType: "S"
        - AttributeName: "ScanDate"
          AttributeType: "S"
        - AttributeName: "TrackerFlag"
          AttributeType: "N"
      KeySchema:
        - AttributeName: "BucketName"
          KeyType: "HASH"
        - AttributeName: "ScanDate"
          KeyType: "RANGE"
      GlobalSecondaryIndexes:
        - IndexName: DateIndex
          KeySchema:
            - AttributeName: "TrackerFlag"
              KeyType: "HASH"
            - AttributeName: "ScanDate"
              KeyType: "RANGE"
          Projection:
            ProjectionType: ALL
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}StorageAnalysis"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  FileCountTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "ScanDate"
          AttributeType: "S"
        - AttributeName: "Guid"
          AttributeType: "S"
        - AttributeName: "TrackerFlag"
          AttributeType: "N"
      KeySchema:
        - AttributeName: "ScanDate"
          KeyType: "HASH"
        - AttributeName: "Guid"
          KeyType: "RANGE"
      GlobalSecondaryIndexes:
        - IndexName: DateIndex
          KeySchema:
            - AttributeName: "TrackerFlag"
              KeyType: "HASH"
            - AttributeName: "ScanDate"
              KeyType: "RANGE"
          Projection:
            ProjectionType: ALL
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}FileCount"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  ConsoleTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "ApplicationId"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "ApplicationId"
          KeyType: "HASH"
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}Console"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  AgentsTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "AgentId"
          AttributeType: "S"
        - AttributeName: "DeactivationDate"
          AttributeType: "S"
        - AttributeName: "Active"
          AttributeType: "N"
      KeySchema:
        - AttributeName: "AgentId"
          KeyType: "HASH"
      GlobalSecondaryIndexes:
        - IndexName: ActiveAndDeactivationDateIndex
          KeySchema:
            - AttributeName: Active
              KeyType: HASH
            - AttributeName: DeactivationDate
              KeyType: RANGE
          Projection:
            ProjectionType: ALL
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}Agents"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  AgentDataTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "AgentId"
          AttributeType: "S"
        - AttributeName: "Tstp"
          AttributeType: "N"
        - AttributeName: "TrackerFlag"
          AttributeType: "N"
      KeySchema:
        - AttributeName: "AgentId"
          KeyType: "HASH"
        - AttributeName: "Tstp"
          KeyType: "RANGE"
      GlobalSecondaryIndexes:
        - IndexName: TstpIndex
          KeySchema:
            - AttributeName: TrackerFlag
              KeyType: HASH
            - AttributeName: Tstp
              KeyType: RANGE
          Projection:
            ProjectionType: ALL
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}AgentData"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  BucketScanStatisticsTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "BucketName"
          AttributeType: "S"
        - AttributeName: "Date"
          AttributeType: "S"
        - AttributeName: "TrackerFlag"
          AttributeType: "N"
      KeySchema:
        - AttributeName: "BucketName"
          KeyType: "HASH"
        - AttributeName: "Date"
          KeyType: "RANGE"
      GlobalSecondaryIndexes:
        - IndexName: DateIndex
          KeySchema:
            - AttributeName: TrackerFlag
              KeyType: HASH
            - AttributeName: Date
              KeyType: RANGE
          Projection:
            ProjectionType: ALL
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}BucketScanStatistics"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  BucketClassificationStatisticsTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "BucketName"
          AttributeType: "S"
        - AttributeName: "Date"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "BucketName"
          KeyType: "HASH"
        - AttributeName: "Date"
          KeyType: "RANGE"
      GlobalSecondaryIndexes:
        - IndexName: DateIndex
          KeySchema:
            - AttributeName: Date
              KeyType: HASH
          Projection:
            ProjectionType: ALL
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}BucketClassificationStatistics"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  SophosTapDataTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "Date"
          AttributeType: "S"
        - AttributeName: "Tstp"
          AttributeType: "N"
      KeySchema:
        - AttributeName: "Date"
          KeyType: "HASH"
        - AttributeName: "Tstp"
          KeyType: "RANGE"
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}SophosTapData"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  DailyScanStatisticsTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "AccountId"
          AttributeType: "S"
        - AttributeName: "Date"
          AttributeType: "S"
        - AttributeName: "ScanType"
          AttributeType: "S"
        - AttributeName: "ScanEngine"
          AttributeType: "S"
        - AttributeName: "TrackerFlag"
          AttributeType: "N"
      KeySchema:
        - AttributeName: "AccountId"
          KeyType: "HASH"
        - AttributeName: "Date"
          KeyType: "RANGE"
      GlobalSecondaryIndexes:
        - IndexName: ScanTypeAndScanEngine
          KeySchema:
            - AttributeName: ScanType
              KeyType: HASH
            - AttributeName: ScanEngine
              KeyType: RANGE
          Projection:
            ProjectionType: ALL
        - IndexName: LastRecordDate
          KeySchema:
            - AttributeName: TrackerFlag
              KeyType: HASH
            - AttributeName: Date
              KeyType: RANGE
          Projection:
            ProjectionType: ALL
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}DailyScanStatistics"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  MonthlyScanStatisticsTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "AccountId"
          AttributeType: "S"
        - AttributeName: "Date"
          AttributeType: "S"
        - AttributeName: "TrackerFlag"
          AttributeType: "N"
        - AttributeName: "ScanType"
          AttributeType: "S"
        - AttributeName: "ScanEngine"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "AccountId"
          KeyType: "HASH"
        - AttributeName: "Date"
          KeyType: "RANGE"
      GlobalSecondaryIndexes:
        - IndexName: ScanTypeAndScanEngine
          KeySchema:
            - AttributeName: ScanType
              KeyType: HASH
            - AttributeName: ScanEngine
              KeyType: RANGE
          Projection:
            ProjectionType: ALL
        - IndexName: LastRecordDate
          KeySchema:
            - AttributeName: TrackerFlag
              KeyType: HASH
            - AttributeName: Date
              KeyType: RANGE
          Projection:
            ProjectionType: ALL
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}MonthlyScanStatistics"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  ProblemFilesTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "Guid"
          AttributeType: "S"
        - AttributeName: "DateScanned"
          AttributeType: "S"
        - AttributeName: "AccountId"
          AttributeType: "S"
        - AttributeName: "AccountIdResult"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "Guid"
          KeyType: "HASH"
        - AttributeName: "DateScanned"
          KeyType: "RANGE"
      GlobalSecondaryIndexes:
        - IndexName: AccountIdAndDateScanned
          KeySchema:
            - AttributeName: AccountId
              KeyType: HASH
            - AttributeName: DateScanned
              KeyType: RANGE
          Projection:
            ProjectionType: ALL
        - IndexName: AccountIdResultAndDateScanned
          KeySchema:
            - AttributeName: AccountIdResult
              KeyType: HASH
            - AttributeName: DateScanned
              KeyType: RANGE
          Projection:
            ProjectionType: ALL
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}ProblemFiles"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  ClassificationResultsTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "Date"
          AttributeType: "S"
        - AttributeName: "DateTime"
          AttributeType: "S"
        - AttributeName: "Guid"
          AttributeType: "S"
        - AttributeName: "AccountId"
          AttributeType: "S"
        - AttributeName: "AccountIdResultType"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "Date"
          KeyType: "HASH"
        - AttributeName: "Guid"
          KeyType: "RANGE"
      GlobalSecondaryIndexes:
        - IndexName: AccountIdResultTypeAndDateTime
          KeySchema:
            - AttributeName: AccountIdResultType
              KeyType: HASH
            - AttributeName: DateTime
              KeyType: RANGE
          Projection:
            ProjectionType: ALL
        - IndexName: AccountIdAndGuid # To be removed in the release after v8.01
          KeySchema:
            - AttributeName: AccountId
              KeyType: HASH
            - AttributeName: Guid
              KeyType: RANGE
          Projection:
            ProjectionType: ALL
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}ClassificationResults"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  AllowedInfectedFilesTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "BucketAndKey"
          AttributeType: "S"
        - AttributeName: "VirusName"
          AttributeType: "S"
        - AttributeName: "DateAdded"
          AttributeType: "S"
        - AttributeName: "Active"
          AttributeType: "N"
      KeySchema:
        - AttributeName: "BucketAndKey"
          KeyType: "HASH"
        - AttributeName: "VirusName"
          KeyType: "RANGE"
      GlobalSecondaryIndexes:
        - IndexName: ActiveAndDateAdded
          KeySchema:
            - AttributeName: Active
              KeyType: HASH
            - AttributeName: DateAdded
              KeyType: RANGE
          Projection:
            ProjectionType: ALL
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}AllowedInfectedFiles"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  LinkedAccountsTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "AccountId"
          AttributeType: "S"
        - AttributeName: "CloudProvider"
          AttributeType: "N"
      KeySchema:
        - AttributeName: "AccountId"
          KeyType: "HASH"
      GlobalSecondaryIndexes:
        - IndexName: CloudProvider
          KeySchema:
            - AttributeName: CloudProvider
              KeyType: HASH
            - AttributeName: AccountId
              KeyType: RANGE
          Projection:
            ProjectionType: ALL
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}LinkedAccounts"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  LinkedOrganizationsTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "OrganizationId"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "OrganizationId"
          KeyType: "HASH"
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}LinkedOrganizations"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  GroupsTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "Id"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "Id"
          KeyType: "HASH"
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}Groups"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  GroupMembershipTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "ParentGroupId"
          AttributeType: "S"
        - AttributeName: "ChildGroupId"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "ParentGroupId"
          KeyType: "HASH"
        - AttributeName: "ChildGroupId"
          KeyType: "RANGE"
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}GroupMembership"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  JobsTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "Type"
          AttributeType: "S"
        - AttributeName: "Date"
          AttributeType: "S"
        - AttributeName: "EndDate"
          AttributeType: "S"
        - AttributeName: "Status"
          AttributeType: "N"
        - AttributeName: "ParentJobId"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "Type"
          KeyType: "HASH"
        - AttributeName: "Date"
          KeyType: "RANGE"
      GlobalSecondaryIndexes:
        - IndexName: Status
          KeySchema:
            - AttributeName: Status
              KeyType: HASH
          Projection:
            ProjectionType: ALL
        - IndexName: TypeAndParentJobId
          KeySchema:
            - AttributeName: Type
              KeyType: HASH
            - AttributeName: ParentJobId
              KeyType: RANGE
          Projection:
            ProjectionType: ALL
        - IndexName: TypeAndEndDate
          KeySchema:
            - AttributeName: Type
              KeyType: HASH
            - AttributeName: EndDate
              KeyType: RANGE
          Projection:
            ProjectionType: ALL
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}Jobs"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  LinkedAccountMembershipTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "GroupId"
          AttributeType: "S"
        - AttributeName: "AccountId"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "GroupId"
          KeyType: "HASH"
        - AttributeName: "AccountId"
          KeyType: "RANGE"
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}LinkedAccountMembership"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  VisibleGroupsTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "Username"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "Username"
          KeyType: "HASH"
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}VisibleGroups"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  ScheduledScansTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "ScheduleName"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "ScheduleName"
          KeyType: "HASH"
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}ScheduledScans"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  ScheduledClassificationsTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "Name"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "Name"
          KeyType: "HASH"
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}ScheduledClassifications"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  LicenseFileHistoryTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "Type"
          AttributeType: "S"
        - AttributeName: "DateApplied"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "Type"
          KeyType: "HASH"
        - AttributeName: "DateApplied"
          KeyType: "RANGE"
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}LicenseFileHistory"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  DeploymentStatusTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "Region"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "Region"
          KeyType: "HASH"
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}DeploymentStatus"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  NotificationsTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "Guid"
          AttributeType: "S"
        - AttributeName: "Date"
          AttributeType: "S"
        - AttributeName: "AccountId"
          AttributeType: "S"
        - AttributeName: "Read"
          AttributeType: "N"
      KeySchema:
        - AttributeName: "Guid"
          KeyType: "HASH"
        - AttributeName: "Date"
          KeyType: "RANGE"
      GlobalSecondaryIndexes:
        - IndexName: AccountIdAndDate
          KeySchema:
            - AttributeName: AccountId
              KeyType: HASH
            - AttributeName: Date
              KeyType: RANGE
          Projection:
            ProjectionType: ALL
        - IndexName: ReadAndDate
          KeySchema:
            - AttributeName: Read
              KeyType: HASH
            - AttributeName: Date
              KeyType: RANGE
          Projection:
            ProjectionType: ALL
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}Notifications"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  MalwareDetectionTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "PK"
          AttributeType: "S"
        - AttributeName: "SK"
          AttributeType: "S"
        - AttributeName: "GSI1PK"
          AttributeType: "S"
        - AttributeName: "GSI1SK"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "PK"
          KeyType: "HASH"
        - AttributeName: "SK"
          KeyType: "RANGE"
      GlobalSecondaryIndexes:
        - IndexName: GSI1
          KeySchema:
            - AttributeName: "GSI1PK"
              KeyType: "HASH"
            - AttributeName: "GSI1SK"
              KeyType: "RANGE"
          Projection:
            ProjectionType: ALL
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}MalwareDetection"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  AzureTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "PK"
          AttributeType: "S"
        - AttributeName: "SK"
          AttributeType: "S"
        - AttributeName: "GSI1PK"
          AttributeType: "S"
        - AttributeName: "GSI1SK"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "PK"
          KeyType: "HASH"
        - AttributeName: "SK"
          KeyType: "RANGE"
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}Azure"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
      GlobalSecondaryIndexes:
        - IndexName: GSI1
          KeySchema:
            - AttributeName: GSI1PK
              KeyType: HASH
            - AttributeName: GSI1SK
              KeyType: RANGE
          Projection:
            ProjectionType: ALL
  GCPTable:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "PK"
          AttributeType: "S"
        - AttributeName: "SK"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "PK"
          KeyType: "HASH"
        - AttributeName: "SK"
          KeyType: "RANGE"
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}GCP"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  ScanRequests:
    Type: AWS::DynamoDB::Table
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AttributeDefinitions:
        - AttributeName: "PK"
          AttributeType: "S"
        - AttributeName: "SK"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "PK"
          KeyType: "HASH"
        - AttributeName: "SK"
          KeyType: "RANGE"
      BillingMode: PAY_PER_REQUEST
      TableName: !Sub "${DynamoTableNamePrefixParameter.Value}ScanRequests"
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: !GetAtt DynamoPointInTimeRecoveryEnabledParameter.Value
      SSESpecification: !If
        - HasCustomDynamoDBKmsKey
        - SSEEnabled: true
          SSEType: KMS
          KMSMasterKeyId: !Ref CustomDynamoDBKmsKey
        - !Ref "AWS::NoValue"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "DynamoTable"
  UserPoolSnsRole:
    Type: AWS::IAM::Role
    Metadata:
      cfn_nag:
        rules_to_suppress:
          - id: W11
            reason: "we need resource * on the policy for publishing to sns as there is not a known resource arn"
    Condition: CreateUserPoolSnsRole
    Properties:
      RoleName: !Sub "${UserPoolRolePrefix}${AppConfigAgentApplication}"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: "Allow"
            Principal:
              Service:
                - "cognito-idp.amazonaws.com"
            Action:
              - "sts:AssumeRole"
      Policies:
        - PolicyName: !Sub "${UserPoolPolicyPrefix}${AppConfigAgentApplication}"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: "Allow"
                Action: "sns:publish"
                Resource: "*"
  UserPool:
    Type: AWS::Cognito::UserPool
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      AdminCreateUserConfig:
        AllowAdminCreateUserOnly: true
        InviteMessageTemplate:
          EmailSubject: !FindInMap [Strings, !Ref ProductListing, WelcomeMessage]
          EmailMessage: !Sub
            - |
              <html>
              <body style="font-family: Arial, sans-serif;">
                <div style="width: 600px; background-color: #fff; line-height: 19px;">
                  <div style="padding: 20px;">
                    <div style="margin-bottom: 20px;" align="center">
                      <a href="https://www.cloudstoragesec.com/aws">
                        <img alt="Cloud_Storage_Security_Logo_Full Color"
                          src="https://cloudstoragesecurity.com/hubfs/Logos/CSS%20Logos/CSS_Logo_Welcome_Ex.png"
                          width="150" align="middle">
                      </a>
                    </div>
                    <hr>
                    <div style="font-size: 16px; margin-top: 24px; margin-bottom: 30px;">
                      <p style="line-height: 24px; margin-bottom: 20px;">
                        A new account has been created for you in Cloud Storage Security's Console.<br />Your account credentials are
                        provided below:<br />
                      </p>
                      <p style="margin-bottom: 20px;">
                        <b>User Name: {username}</b>
                      </p>
                      <p>
                        <b>Temporary Password: {####}</b>
                      </p>
                      <p style="margin-top: 20px;">
                        This temporary password will expire in 7 days.<br /><br /> Sign in at
                        ${URL} to change your password.<br />
                      </p>
                      <p style="margin-top: 20px; font-size: 14px;">
                        <b>To ensure you receive critical security updates, we highly recommend that you complete the form titled
                          "Stay Connected" upon logging in.</b>
                      </p>
                      <p style="margin-top: 20px;">
                        Have Fun,<br />Cloud Storage Security<br />support@cloudstoragesec.com<br />801-410-0408<br />
                      </p>
                    </div>
                    <hr>
                    <div style="padding-top: 14px;" align="center">
                      <a href="https://www.linkedin.com/company/cloud-storage-security/" style="text-decoration: none; margin-right:5px;"
                        target="_blank">
                        <img
                          src="https://cloudstoragesecurity.com/hubfs/Logos/Social%20Network%20Logos/linkedin_original_black.png"
                          alt="LinkedIn" height="25">
                      </a>
                      <a href="https://twitter.com/CloudStorageSec/" style="text-decoration: none; margin-right:5px;" target="_blank">
                        <img
                          src="https://cloudstoragesecurity.com/hubfs/Logos/Social%20Network%20Logos/twitter_original_black.png"
                          alt="Twitter" height="25">
                      </a>
                      <a href="https://www.youtube.com/channel/UCZyPwq0OKaqJQluGRctLcKw" style="text-decoration: none;"
                        target="_blank">
                        <img
                          src="https://cloudstoragesecurity.com/hubfs/Logos/Social%20Network%20Logos/youtube_original_black.png"
                          alt="YouTube" height="25">
                      </a>
                    </div>
                  </div>
                </div>
              </body>
              </html>
            - URL:
                !If [
                  IsEKSDeployment,
                  "the address provided by your application administrator",
                  !If [
                    UseLB,
                    !If [
                      UseRoute53,
                      !Sub "https://${HostedSubdomain}.${HostedZoneName}",
                      "the address provided by your application administrator",
                    ],
                    !Sub "https://${SubdomainParameter.Value}.cloudstoragesecapp.com",
                  ]
                ]
      UserPoolName: !Sub "${UserPoolPrefix}${AppConfigAgentApplication}"
      MfaConfiguration: OPTIONAL
      EnabledMfas: [SOFTWARE_TOKEN_MFA, SMS_MFA]
      AccountRecoverySetting:
        RecoveryMechanisms:
          - Name: verified_email
            Priority: 1
      AutoVerifiedAttributes:
        - phone_number
        - email
      SmsConfiguration:
        ExternalId: !Join ["-", [CloudStorageSecUserPoolExternal, !Ref AppConfigAgentApplication]]
        SnsCallerArn: !If [CreateUserPoolSnsRole, !GetAtt UserPoolSnsRole.Arn, !Ref UserPoolSnsRoleArn]
      Policies:
        PasswordPolicy:
          MinimumLength: 12
          RequireLowercase: true
          RequireUppercase: true
          RequireNumbers: true
          RequireSymbols: true
          TemporaryPasswordValidityDays: 7
      Schema:
        - AttributeDataType: Number
          Mutable: true
          Name: hide_welcome_msg
          NumberAttributeConstraints:
            MinValue: 0
            MaxValue: 1
        - AttributeDataType: Number
          Mutable: true
          Name: hide_trial_msg
          NumberAttributeConstraints:
            MinValue: 0
            MaxValue: 1
        - AttributeDataType: Number
          Mutable: true
          Name: user_disabled
          NumberAttributeConstraints:
            MinValue: 0
            MaxValue: 1
        - AttributeDataType: String
          Mutable: true
          Name: aws_account_id
          StringAttributeConstraints:
            MinLength: 12
            MaxLength: 12
        - AttributeDataType: Number
          Mutable: true
          Name: hide_contact_form
          NumberAttributeConstraints:
            MinValue: 0
            MaxValue: 1
  UserPoolClient:
    Type: AWS::Cognito::UserPoolClient
    Properties:
      ClientName: !Sub "${UserPoolClientPrefix}${AppConfigAgentApplication}"
      GenerateSecret: true
      UserPoolId: !Ref UserPool
  UserPoolAdminGroup:
    Type: AWS::Cognito::UserPoolGroup
    Properties:
      Description: Accounts with Admin level access
      GroupName: Admins
      UserPoolId: !Ref UserPool
  UserPoolUserGroup:
    Type: AWS::Cognito::UserPoolGroup
    Properties:
      Description: Accounts with user level access
      GroupName: Users
      UserPoolId: !Ref UserPool
  UserPoolApiGroup:
    Type: AWS::Cognito::UserPoolGroup
    Properties:
      Description: Accounts with API level access
      GroupName: Api
      UserPoolId: !Ref UserPool
  UserPoolReadOnlyGroup:
    Type: AWS::Cognito::UserPoolGroup
    Properties:
      Description: Accounts with ReadOnly level access
      GroupName: ReadOnly
      UserPoolId: !Ref UserPool
  UserPoolPrimaryGroup:
    Type: AWS::Cognito::UserPoolGroup
    Properties:
      Description: Accounts with access to the Primary group
      GroupName: Primary
      UserPoolId: !Ref UserPool
  UserPoolUser:
    Type: AWS::Cognito::UserPoolUser
    Properties:
      DesiredDeliveryMediums: [EMAIL]
      Username: !Ref UserName
      UserPoolId: !Ref UserPool
      UserAttributes:
        - Name: email
          Value: !Ref Email
        - Name: email_verified
          Value: true
  UserPoolUserAdminGroupAttachment:
    Type: AWS::Cognito::UserPoolUserToGroupAttachment
    DependsOn:
      - UserPoolUserGroup
      - UserPoolUser
    Properties:
      GroupName: Admins
      Username: !Ref UserName
      UserPoolId: !Ref UserPool
  ConsoleTaskRole:
    Type: AWS::IAM::Role
    Condition: CreateConsoleRole
    Properties:
      RoleName: !Sub "${ConsoleTaskRolePrefix}${AppConfigAgentApplication}"
      AssumeRolePolicyDocument: !If
        - IsECSDeployment
        - !Sub |
          {
            "Version": "2012-10-17",
            "Statement": [
              {
                "Effect": "Allow",
                "Principal": {
                  "Service": [ "ecs.amazonaws.com", "ecs-tasks.amazonaws.com" ]
                },
                "Action": "sts:AssumeRole"
              },
              {
                "Sid": "AllowSelfAssume",
                "Effect": "Allow",
                "Principal": { "AWS": "arn:${AWS::Partition}:iam::${AWS::AccountId}:root" },
                "Action": "sts:AssumeRole",
                "Condition": {
                  "StringEquals": {
                    "aws:PrincipalArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${ConsoleTaskRolePrefix}${AppConfigAgentApplication}"
                  }
                }
              }
            ]
          }
        - !Sub
            - |
              {
                "Version": "2012-10-17",
                "Statement": [
                  {
                    "Effect": "Allow",
                    "Principal": {
                      "Federated": "arn:${AWS::Partition}:iam::${AWS::AccountId}:oidc-provider/${IamOidcProviderName}"
                    },
                    "Action": "sts:AssumeRoleWithWebIdentity",
                    "Condition": {
                      "StringEquals": {
                        "${OidcVar}": [
                            "system:serviceaccount:${EksNamespace}:${EksConsoleServiceAccountName}"
                        ]
                      }
                    }
                  },
                  {
                      "Sid": "AllowSelfAssume",
                      "Effect": "Allow",
                      "Principal": { "AWS": "arn:${AWS::Partition}:iam::${AWS::AccountId}:root" },
                      "Action": "sts:AssumeRole",
                      "Condition": {
                        "StringEquals": {
                          "aws:PrincipalArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${ConsoleTaskRolePrefix}${AppConfigAgentApplication}"
                        }
                      }
                  }
                ]
              }
            - OidcVar: !Sub "${IamOidcProviderName}:sub"
      ManagedPolicyArns:
        - !If [
            IsGovCloud,
            !Ref AWS::NoValue,
            arn:aws:iam::aws:policy/service-role/AmazonECSInfrastructureRolePolicyForVolumes,
          ]
        - !If [ CreateConsoleEc2ManagementPolicy, !Ref AWS::NoValue, !Ref ConsoleEc2ManagementPolicyArn ]
        - !If [ CreateConsoleInfrastructureManagementPolicy, !Ref AWS::NoValue, !Ref ConsoleInfrastructureManagementPolicyArn ]
        - !If [ CreateConsoleLoggingAndMonitoringPolicy, !Ref AWS::NoValue, !Ref ConsoleLoggingAndMonitoringPolicyArn ]
        - !If [ CreateConsoleApplicationResourcesPolicy, !Ref AWS::NoValue, !Ref ConsoleApplicationResourcesPolicyArn ]
        - !If [ CreateConsoleSecurityAndAccessPolicy, !Ref AWS::NoValue, !Ref ConsoleSecurityAndAccessPolicyArn ]
    Metadata:
      cfn-lint:
        config:
          ignore_checks: [W1028]
  ConsoleEc2ManagementPolicy:
    Type: AWS::IAM::ManagedPolicy
    DependsOn: ConsoleIAMPolicy
    Condition: CreateConsoleEc2ManagementPolicy
    Properties:
      ManagedPolicyName: !Sub "${ConsoleTaskPolicyPrefix}${AppConfigAgentApplication}-EC2-Management-Policy"
      PolicyDocument: !Sub |
        {
          "Version": "2012-10-17",
          "Statement": [
              {
                  "Condition": {
                      "StringEquals": {
                          "ec2:ResourceTag/CloudStorageSecExtraLargeFileScanning": "ExtraLargeFileScanning"
                      }
                  },
                  "Action": [
                      "ec2:DeleteVolume",
                      "ec2:TerminateInstances"
                  ],
                  "Resource": "arn:${AWS::Partition}:ec2:*:*:*",
                  "Effect": "Allow",
                  "Sid": "DeleteLargeFileScanningVolumes"
              },
              {
                  "Condition": {
                      "StringEquals": {
                          "aws:RequestTag/CloudStorageSec-${AppConfigAgentApplication}": "Snapshot"
                      }
                  },
                  "Action": [
                      "ec2:CreateTags",
                      "ec2:CreateSnapshot"
                  ],
                  "Resource": [
                      "arn:${AWS::Partition}:ec2:*::snapshot/*"
                  ],
                  "Effect": "Allow",
                  "Sid": "EC2CreateSnapshot"
              },
              {
                  "Action": [
                      "ec2:CreateSnapshot"
                  ],
                  "Resource": [
                      "arn:${AWS::Partition}:ec2:*:*:volume/*"
                  ],
                  "Effect": "Allow",
                  "Sid": "EC2CreateSnapshotForAnyVolume"
              },
              {
                  "Condition": {
                      "StringEquals": {
                          "aws:ResourceTag/CloudStorageSec-${AppConfigAgentApplication}": "Snapshot"
                      }
                  },
                  "Action": [
                      "ec2:DeleteSnapshot"
                  ],
                  "Resource": [
                      "arn:${AWS::Partition}:ec2:*::snapshot/*"
                  ],
                  "Effect": "Allow",
                  "Sid": "EC2DeleteSnapshot"
              },
              {
                  "Condition": {
                      "StringEquals": {
                          "aws:RequestTag/CloudStorageSec-${AppConfigAgentApplication}": "Volume"
                      }
                  },
                  "Action": [
                      "ec2:CreateTags",
                      "ec2:CreateVolume"
                  ],
                  "Resource": [
                      "arn:${AWS::Partition}:ec2:*:*:volume/*"
                  ],
                  "Effect": "Allow",
                  "Sid": "EC2VolumeCreate"
              },
              {
                  "Condition": {
                      "StringEquals": {
                          "ec2:ResourceTag/CloudStorageSec-${AppConfigAgentApplication}": "Volume"
                      }
                  },
                  "Action": [
                      "ec2:DeleteVolume"
                  ],
                  "Resource": [
                      "arn:${AWS::Partition}:ec2:*:*:volume/*"
                  ],
                  "Effect": "Allow",
                  "Sid": "EC2VolumeDelete"
              },
              {
                  "Condition": {
                      "StringEquals": {
                          "aws:RequestTag/CloudStorageSec-${AppConfigAgentApplication}": "SecurityGroupRule"
                      }
                  },
                  "Action": [
                      "ec2:CreateTags",
                      "ec2:AuthorizeSecurityGroupIngress"
                  ],
                  "Resource": [
                      "arn:${AWS::Partition}:ec2:*:${AWS::AccountId}:security-group-rule/*"
                  ],
                  "Effect": "Allow",
                  "Sid": "EC2CreateSecurityGroupRule"
              },
              {
                  "Action": [
                      "ec2:CreateTags",
                      "ec2:DeleteTags",
                      "ec2:AuthorizeSecurityGroupIngress",
                      "ec2:ModifyNetworkInterfaceAttribute",
                      "ec2:RevokeSecurityGroupIngress"
                  ],
                  "Resource": [
                      "arn:${AWS::Partition}:ec2:*:${AWS::AccountId}:security-group/*",
                      "arn:${AWS::Partition}:ec2:*:${AWS::AccountId}:network-interface/*"
                  ],
                  "Effect": "Allow",
                  "Sid": "EC2CreateSecurityGroupRuleIngress"
              },
              {
                  "Condition": {
                      "StringEquals": {
                          "aws:RequestTag/CloudStorageSec-${AppConfigAgentApplication}": "SecurityGroup"
                      }
                  },
                  "Action": [
                      "ec2:CreateTags",
                      "ec2:CreateSecurityGroup"
                  ],
                  "Resource": [
                      "arn:${AWS::Partition}:ec2:*:${AWS::AccountId}:security-group/*"
                  ],
                  "Effect": "Allow",
                  "Sid": "EC2CreateSecurityGroup"
              },
              {
                  "Action": [
                      "ec2:CreateTags",
                      "ec2:CreateSecurityGroup"
                  ],
                  "Resource": [
                      "arn:${AWS::Partition}:ec2:*:${AWS::AccountId}:vpc/*"
                  ],
                  "Effect": "Allow",
                  "Sid": "EC2CreateSecurityGroupVPC"
              },
              {
                  "Action": [
                      "ec2:RunInstances"
                  ],
                  "Resource": [
                      "arn:${AWS::Partition}:ec2:*:${AWS::AccountId}:security-group/*",
                      "arn:${AWS::Partition}:ec2:*:${AWS::AccountId}:subnet/*",
                      "arn:${AWS::Partition}:ec2:*::image/*"
                  ],
                  "Effect": "Allow",
                  "Sid": "EC2RunInstanceInfrastructure"
              },
              {
                  "Condition": {
                      "StringEquals": {
                          "aws:RequestTag/CloudStorageSec-${AppConfigAgentApplication}": "EC2Instance"
                      }
                  },
                  "Action": [
                      "ec2:RunInstances",
                      "ec2:CreateTags",
                      "iam:PassRole",
                      "ssm:GetParameters"
                  ],
                  "Resource": [
                      "arn:${AWS::Partition}:ec2:*:${AWS::AccountId}:instance/*",
                      "arn:${AWS::Partition}:ec2:*:${AWS::AccountId}:network-interface/*",
                      "arn:${AWS::Partition}:ec2:*:${AWS::AccountId}:volume/*"
                  ],
                  "Effect": "Allow",
                  "Sid": "EC2RunInstance"
              },
              {
                  "Condition": {
                      "StringEquals": {
                          "ec2:ResourceTag/CloudStorageSec-${AppConfigAgentApplication}": "EC2Instance"
                      }
                  },
                  "Action": [
                      "ec2:TerminateInstances"
                  ],
                  "Resource": [
                      "arn:${AWS::Partition}:ec2:*:${AWS::AccountId}:instance/*"
                  ],
                  "Effect": "Allow",
                  "Sid": "EC2TerminateInstance"
              }
          ]
        }
      Roles:
        - !If [CreateConsoleRole, !Ref ConsoleTaskRole, !Ref ConsoleTaskRoleName]
  ConsoleInfrastructureManagementPolicy:
    Type: AWS::IAM::ManagedPolicy
    DependsOn: ConsoleIAMPolicy
    Condition: CreateConsoleInfrastructureManagementPolicy
    Properties:
      ManagedPolicyName: !Sub "${ConsoleTaskPolicyPrefix}${AppConfigAgentApplication}-Infrastructure-Management-Policy"
      PolicyDocument: !Sub
        - |
          {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Action": [
                        "cloudformation:DescribeStacks",
                        "cloudformation:UpdateStack"
                    ],
                    "Resource": [
                        ${StackArns}
                        "arn:${AWS::Partition}:cloudformation:${AWS::Region}:*:stack/${AWS::StackName}/*"
                    ],
                    "Effect": "Allow",
                    "Sid": "CloudFormation"
                },
                {
                    "Action": [
                        "ecs:TagResource",
                        "ecs:ListTagsForResource",
                        "ecs:UntagResource",
                        "ecs:CreateCluster",
                        "ecs:DeleteCluster",
                        "ecs:DescribeClusters",
                        "ecs:ListContainerInstances",
                        "ecs:CreateService",
                        "ecs:DeleteService",
                        "ecs:DescribeServices",
                        "ecs:UpdateService",
                        "ecs:ListTasks",
                        "ecs:DescribeTasks",
                        "ecs:StopTask"
                    ],
                    "Resource": [
                        "arn:${AWS::Partition}:ecs:*:${AWS::AccountId}:cluster/${ClusterPrefix}${AppConfigAgentApplication}",
                        "arn:${AWS::Partition}:ecs:*:${AWS::AccountId}:service/${ClusterPrefix}${AppConfigAgentApplication}/*",
                        "arn:${AWS::Partition}:ecs:*:${AWS::AccountId}:container-instance/${ClusterPrefix}${AppConfigAgentApplication}/*",
                        "arn:${AWS::Partition}:ecs:*:${AWS::AccountId}:task/${ClusterPrefix}${AppConfigAgentApplication}/*"
                    ],
                    "Effect": "Allow",
                    "Sid": "ECSCluster"
                },
                {
                    "Condition": {
                        "ForAnyValue:StringEquals": {
                            "aws:RequestTag/CloudStorageSec-${AppConfigAgentApplication}": ["TaskDefinition","ConsoleTaskDefinition"]
                        }
                    },
                    "Action": [
                        "ecs:TagResource",
                        "ecs:RegisterTaskDefinition"
                    ],
                    "Resource": "*",
                    "Effect": "Allow",
                    "Sid": "ECSRegisterTask"
                },
                {
                    "Condition": {
                        "ForAnyValue:StringEquals": {
                            "aws:ResourceTag/CloudStorageSec-${AppConfigAgentApplication}": ["TaskDefinition","ConsoleTaskDefinition"]
                        }
                    },
                    "Action": [
                        "ecs:TagResource",
                        "ecs:ListTagsForResource",
                        "ecs:UntagResource",
                        "ecs:RunTask",
                        "ecs:DeleteTaskDefinitions"
                    ],
                    "Resource": "arn:${AWS::Partition}:ecs:*:${AWS::AccountId}:task-definition/*${AppConfigAgentApplication}:*",
                    "Effect": "Allow",
                    "Sid": "ECSRunDeleteTask"
                },
                {
                    "Condition": {
                        "StringEquals": {
                            "application-autoscaling:scalable-dimension": "ecs:service:DesiredCount"
                        }
                    },
                    "Action": [
                        "application-autoscaling:DeregisterScalableTarget",
                        "application-autoscaling:PutScalingPolicy",
                        "application-autoscaling:RegisterScalableTarget"
                    ],
                    "Resource": [
                        "arn:${AWS::Partition}:application-autoscaling:*:${AWS::AccountId}:scalable-target/*"
                    ],
                    "Effect": "Allow",
                    "Sid": "ApplicationAutoscaling"
                },
                {
                    "Condition": {
                        "ForAllValues:StringEquals": {"aws:TagKeys": "CloudStorageSec-${AppConfigAgentApplication}"}
                    },
                    "Action": [
                        "application-autoscaling:TagResource",
                        "application-autoscaling:UntagResource"
                    ],
                    "Resource": [
                        "arn:${AWS::Partition}:application-autoscaling:*:${AWS::AccountId}:scalable-target/*"
                    ],
                    "Effect": "Allow",
                    "Sid": "ApplicationAutoscalingTagging"
                },
                {
                    "Action": [
                      "appconfig:DeleteConfigurationProfile",
                      "appconfig:GetLatestConfiguration",
                      "appconfig:ListConfigurationProfiles",
                      "appconfig:StartDeployment",
                      "appconfig:StartConfigurationSession",
                      "appconfig:TagResource",
                      "appconfig:UpdateApplication",
                      "appconfig:UpdateConfigurationProfile",
                      "appconfig:UpdateDeploymentStrategy",
                      "appconfig:UpdateEnvironment",
                      "appconfig:UntagResource"
                    ],
                    "Resource": [
                      "arn:${AWS::Partition}:appconfig:*:${AWS::AccountId}:application/${AppConfigAgentApplication}/*",
                      "arn:${AWS::Partition}:appconfig:*:${AWS::AccountId}:application/${AppConfigAgentApplication}",
                      "arn:${AWS::Partition}:appconfig:*:${AWS::AccountId}:deploymentstrategy/${AppConfigAgentDeploymentStrategy}"
                    ],
                    "Effect": "Allow",
                    "Sid": "AppConfig"
                },
                {
                    "Action": [
                        "ssm:AddTagsToResource",
                        "ssm:ListTagsForResource",
                        "ssm:RemoveTagsFromResource",
                        "ssm:CreateDocument",
                        "ssm:DeleteDocument",
                        "ssm:DescribeDocument",
                        "ssm:DescribeDocumentParameters",
                        "ssm:DescribeDocumentPermission",
                        "ssm:ModifyDocumentPermission",
                        "ssm:GetDocument",
                        "ssm:ListDocuments",
                        "ssm:UpdateDocument",
                        "ssm:UpdateDocumentDefaultVersion",
                        "ssm:UpdateDocumentMetadata",
                        "ssm:DeleteParameter",
                        "ssm:DeleteParameters",
                        "ssm:DescribeParameters",
                        "ssm:GetParameter",
                        "ssm:GetParameterHistory",
                        "ssm:GetParameters",
                        "ssm:GetParametersByPath",
                        "ssm:LabelParameterVersion",
                        "ssm:PutParameter",
                        "ssm:UnlabelParameterVersion",
                        "secretsmanager:CreateSecret",
                        "secretsmanager:DeleteSecret",
                        "secretsmanager:DescribeSecret",
                        "secretsmanager:GetSecretValue",
                        "secretsmanager:PutSecretValue",
                        "secretsmanager:RestoreSecret",
                        "secretsmanager:TagResource"
                    ],
                    "Resource": [
                        "arn:${AWS::Partition}:ssm:*:${AWS::AccountId}:parameter/aws/service/ecs/optimized-ami/amazon-linux*/recommended/image_id",
                        "arn:${AWS::Partition}:ssm:*:${AWS::AccountId}:document/*${AppConfigAgentApplication}",
                        "arn:${AWS::Partition}:ssm:*:${AWS::AccountId}:parameter/*${AppConfigAgentApplication}/*",
                        "arn:${AWS::Partition}:ssm:*:${AWS::AccountId}:parameter/*${AppConfigAgentApplication}",
                        "arn:${AWS::Partition}:ssm:*::parameter/aws/service/ecs/optimized-ami/amazon-linux-2/recommended/image_id",
                        "arn:${AWS::Partition}:secretsmanager:${AWS::Region}:*:secret:cloudstoragesec/*"
                    ],
                    "Effect": "Allow",
                    "Sid": "SSMActions"
                },
                {
                    "Action": [
                      "events:CreateEventBus",
                      "events:DeleteEventBus",
                      "events:DeleteRule",
                      "events:DescribeEventBus",
                      "events:DescribeRule",
                      "events:DisableRule",
                      "events:EnableRule",
                      "events:ListRuleNamesByTarget",
                      "events:ListRules",
                      "events:ListTagsForResource",
                      "events:PutPermission",
                      "events:PutRule",
                      "events:PutTargets",
                      "events:RemovePermission",
                      "events:RemoveTargets",
                      "events:TagResource",
                      "events:UntagResource",
                      "events:UpdateEventBus"
                    ],
                    "Resource": [
                        "arn:${AWS::Partition}:events:*:*:*/*${AppConfigAgentApplication}*",
                        "arn:${AWS::Partition}:events:*:*:*/default",
                        ${CustomEventBridgeNotification}
                        "arn:${AWS::Partition}:events:*:*:rule/*"

                    ],
                    "Effect": "Allow",
                    "Sid": "EventBridgeActions"
                }
            ]
          }
        - StackArns: !If
            - HasParentStack
            - !Sub '"arn:${AWS::Partition}:cloudformation:${AWS::Region}:*:stack/${StackNameParameter.Value}/*",'
            - ""
          CustomEventBridgeNotification: !If
            - CreateCustomEventBridgeBus
            - !Sub '"arn:${AWS::Partition}:events:*:*:event-bus/${EventBridgeNotificationsBusName}",'
            - ""
      Roles:
        - !If [CreateConsoleRole, !Ref ConsoleTaskRole, !Ref ConsoleTaskRoleName]
  ConsoleLoggingAndMonitoringPolicy:
    Type: AWS::IAM::ManagedPolicy
    DependsOn: ConsoleIAMPolicy
    Condition: CreateConsoleLoggingAndMonitoringPolicy
    Metadata:
      cfn_nag:
        rules_to_suppress:
          - id: W13
            reason: "The action cloudwatch:PutMetricData requires using a wildcard"
    Properties:
      ManagedPolicyName: !Sub "${ConsoleTaskPolicyPrefix}${AppConfigAgentApplication}-Logging-And-Monitoring-Policy"
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Action:
              - logs:CreateLogStream
              - logs:GetLogEvents
              - logs:PutLogEvents
            Resource: !Sub "arn:${AWS::Partition}:logs:*:${AWS::AccountId}:log-group:CloudStorageSecurity.*:log-stream:*"
            Effect: Allow
            Sid: CloudWatchLogStream
          - Action:
              - logs:ListTagsForResource
              - logs:TagResource
              - logs:DescribeLogStreams
              - logs:FilterLogEvents
              - logs:CreateLogGroup
              - logs:DeleteLogGroup
              - logs:PutRetentionPolicy
              - logs:TagLogGroup
              - logs:UntagLogGroup
              - logs:UntagResource
            Resource:
              - !Sub "arn:${AWS::Partition}:logs:*:${AWS::AccountId}:log-group:CloudStorageSecurity.*"
            Effect: Allow
            Sid: CloudWatchLog
          - Action:
              - logs:StartQuery
              - logs:GetQueryResults
            Resource:
              - !Sub "arn:${AWS::Partition}:logs:*:${AWS::AccountId}:log-group:CloudStorageSecurity.Console.*:*"
              - !Sub "arn:${AWS::Partition}:logs:*:${AWS::AccountId}:log-group:CloudStorageSecurity.Agent.Jobs:*"
              - !Sub "arn:${AWS::Partition}:logs:*:${AWS::AccountId}:log-group:CloudStorageSecurity.Agent.ScanStatistics:*"
              - !Sub "arn:${AWS::Partition}:logs:*:${AWS::AccountId}:log-group:CloudStorageSecurity.Agent.ClassificationStatistics:*"
              - !Sub "arn:${AWS::Partition}:logs:*:${AWS::AccountId}:log-group:CloudStorageSecurity.Agent.SystemEvents:*"
              - !Sub "arn:${AWS::Partition}:logs:*:${AWS::AccountId}:log-group:CloudStorageSecurity.Agent.ScanResults:*"
              - !Sub "arn:${AWS::Partition}:logs:*:${AWS::AccountId}:log-group:CloudStorageSecurity.Agent.ClassificationResults:*"
            Effect: Allow
            Sid: CloudWatchLogQuery
          - Action:
              - cloudwatch:DeleteAlarms
              - cloudwatch:DescribeAlarms
              - cloudwatch:PutMetricAlarm
            Resource:
              - !Sub "arn:${AWS::Partition}:cloudwatch:*:${AWS::AccountId}:alarm:${LargeEventQueueAlarmPrefix}${AppConfigAgentApplication}"
              - !Sub "arn:${AWS::Partition}:cloudwatch:*:${AWS::AccountId}:alarm:${SmallEventQueueAlarmPrefix}${AppConfigAgentApplication}"
              - !Sub "arn:${AWS::Partition}:cloudwatch:*:${AWS::AccountId}:alarm:${LargeDcEventQueueAlarmPrefix}${AppConfigAgentApplication}"
              - !Sub "arn:${AWS::Partition}:cloudwatch:*:${AWS::AccountId}:alarm:${SmallDcEventQueueAlarmPrefix}${AppConfigAgentApplication}"
              - !Sub "arn:${AWS::Partition}:cloudwatch:*:${AWS::AccountId}:alarm:${TaskDefinitionPrefix}HealthCheck-Alarm-${AppConfigAgentApplication}"
              - !Sub "arn:${AWS::Partition}:cloudwatch:*:${AWS::AccountId}:alarm:TargetTracking-service/${ClusterPrefix}${AppConfigAgentApplication}/${ApiAgentServicePrefix}${AppConfigAgentApplication}*"
            Effect: Allow
            Sid: CloudWatchAlarm
          - Action:
              - securityhub:GetFindings
              - securityhub:DisableImportFindingsForProduct
              - securityhub:BatchImportFindings
              - securityhub:EnableImportFindingsForProduct
            Resource:
              - !Sub "arn:${AWS::Partition}:securityhub:${AWS::Region}:*:product/cloud-storage-security/antivirus-for-amazon-s3"
              - !Sub "arn:${AWS::Partition}:securityhub:${AWS::Region}:${AWS::AccountId}:product-subscription/cloud-storage-security/antivirus-for-amazon-s3"
              - !Sub "arn:${AWS::Partition}:securityhub:${AWS::Region}:${AWS::AccountId}:hub/default"
            Effect: Allow
            Sid: SecurityHubActions
          - Action: cloudwatch:PutMetricData
            Resource: "*"
            Effect: Allow
            Condition:
              StringEquals:
                cloudwatch:Namespace: "AWS/ECS"
            Sid: "PutECSMetricData"
          - Action:
              - sns:Subscribe
              - sns:AddPermission
              - sns:CreateTopic
              - sns:DeleteTopic
              - sns:SetTopicAttributes
              - sns:GetTopicAttributes
              - sns:GetSubscriptionAttributes
              - sns:SetSubscriptionAttributes
              - sns:ListSubscriptionsByTopic
              - sns:Publish
              - sns:TagResource
              - sns:UnTagResource
            Resource:
              - !Sub "arn:${AWS::Partition}:sns:*:${AWS::AccountId}:${NotificationsTopicPrefix}${AppConfigAgentApplication}"
              - !Sub "arn:${AWS::Partition}:sns:*:${AWS::AccountId}:${EventBasedScanTopicPrefix}${AppConfigAgentApplication}"
            Effect: Allow
            Sid: SNS
          - Action:
              - servicequotas:GetServiceQuota
            Resource:
              - !Sub "arn:${AWS::Partition}:servicequotas:*:${AWS::AccountId}:ebs/L-D18FCD1D"
              - !Sub "arn:${AWS::Partition}:servicequotas:*:${AWS::AccountId}:ebs/L-7A658B76"
            Effect: Allow
            Sid: ServiceQuotas
          - Action:
              - budgets:ViewBudget
              - budgets:ModifyBudget
            Resource:
              - !Sub "arn:${AWS::Partition}:budgets::${AWS::AccountId}:budget/Cloud Storage Security Application Cost Budget - Application ${AppConfigAgentApplication}"
            Effect: Allow
            Sid: Budgets
      Roles:
        - !If [CreateConsoleRole, !Ref ConsoleTaskRole, !Ref ConsoleTaskRoleName]
  ConsoleApplicationResourcesPolicy:
    Type: AWS::IAM::ManagedPolicy
    DependsOn: ConsoleIAMPolicy
    Condition: CreateConsoleApplicationResourcesPolicy
    Properties:
      ManagedPolicyName: !Sub "${ConsoleTaskPolicyPrefix}${AppConfigAgentApplication}-Application-Resources-Policy"
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Action:
              - s3:CreateBucket
              - s3:PutObject
              - s3:PutObjectTagging
              - s3:DeleteBucket
              - s3:ListBucket
              - s3:DeleteObject
              - s3:DeleteObjectTagging
              - s3:PutBucketTagging
              - s3:GetBucketTagging
            Resource:
              - !Sub "arn:${AWS::Partition}:s3:::${ApplicationBucket}"
              - !Sub "arn:${AWS::Partition}:s3:::${ApplicationBucket}/*"
            Effect: Allow
            Sid: CloudStorageSecS3Bucket
          - Action:
              - s3:CreateBucket
              - s3:DeleteBucket
              - s3:ListBucket
              - s3:PutLifecycleConfiguration
              - s3:PutEncryptionConfiguration
              - s3:PutBucketTagging
              - s3:GetBucketTagging
              - s3:GetObject
              - s3:GetObjectTagging
              - s3:GetObjectAttributes
              - s3:PutObject
              - s3:PutObjectAcl
              - s3:PutObjectTagging
              - s3:PutObjectVersionAcl
              - s3:PutObjectVersionTagging
              - s3:PutBucketPolicy
              - s3:DeleteObject
              - s3:DeleteObjectTagging
              - s3:DeleteObjectVersion
              - s3:DeleteObjectVersionTagging
              - s3:DeleteBucketPolicy
            Resource:
              - !Sub "arn:${AWS::Partition}:s3:::${QuarantineBucketNamePrefix}${AppConfigAgentApplication}-*"
              - !Sub "arn:${AWS::Partition}:s3:::${QuarantineBucketNamePrefix}${AppConfigAgentApplication}-*/*"
            Effect: Allow
            Sid: CloudStorageSecS3QuarantineBucket
          - Action:
              - dynamodb:BatchWriteItem
              - dynamodb:CreateTable
              - dynamodb:DeleteItem
              - dynamodb:DeleteTable
              - dynamodb:DescribeContinuousBackups
              - dynamodb:DescribeTable
              - dynamodb:GetItem
              - dynamodb:ListTagsOfResource
              - dynamodb:PutItem
              - dynamodb:Query
              - dynamodb:Scan
              - dynamodb:TagResource
              - dynamodb:UntagResource
              - dynamodb:UpdateContinuousBackups
              - dynamodb:UpdateItem
              - dynamodb:UpdateTable
            Resource:
              - !Sub "arn:${AWS::Partition}:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoTableNamePrefixParameter.Value}*"
            Effect: Allow
            Sid: DynamoDb
          - Action:
              - sqs:CreateQueue
              - sqs:DeleteQueue
              - sqs:DeleteMessage
              - sqs:GetQueueAttributes
              - sqs:GetQueueUrl
              - sqs:ListQueueTags
              - sqs:ListQueues
              - sqs:SetQueueAttributes
              - sqs:SendMessage
              - sqs:TagQueue
              - sqs:ReceiveMessage
              - sqs:UntagQueue
            Resource:
              - !Sub "arn:${AWS::Partition}:sqs:*:${AWS::AccountId}:${EventBasedScanQueuePrefix}${AppConfigAgentApplication}*"
              - !Sub "arn:${AWS::Partition}:sqs:*:${AWS::AccountId}:${DcEventBasedScanQueuePrefix}${AppConfigAgentApplication}*"
              - !Sub "arn:${AWS::Partition}:sqs:*:${AWS::AccountId}:${EfsScanQueuePrefix}${AppConfigAgentApplication}*"
              - !Sub "arn:${AWS::Partition}:sqs:*:${AWS::AccountId}:${FsxScanQueuePrefix}${AppConfigAgentApplication}*"
              - !Sub "arn:${AWS::Partition}:sqs:*:${AWS::AccountId}:${ScannedItemsQueuePrefix}${AppConfigAgentApplication}*"
              - !Sub "arn:${AWS::Partition}:sqs:*:${AWS::AccountId}:${RetroScanQueuePrefix}${AppConfigAgentApplication}*"
            Effect: Allow
            Sid: SQS
          - Action:
              - elasticfilesystem:CreateTags
              - elasticfilesystem:CreateMountTarget
              - elasticfilesystem:CreateAccessPoint
              - elasticfilesystem:DescribeFileSystems
              - elasticfilesystem:DescribeMountTargets
              - elasticfilesystem:DescribeMountTargetSecurityGroups
              - elasticfilesystem:DescribeTags
              - elasticfilesystem:TagResource
              - elasticfilesystem:UntagResource
              - elasticfilesystem:ListTagsForResource
              - elasticfilesystem:ModifyMountTargetSecurityGroups
            Resource:
              - !Sub "arn:${AWS::Partition}:elasticfilesystem:*:*:file-system/*"
            Effect: Allow
            Sid: EFSActions
          - Action:
              - elasticfilesystem:DeleteAccessPoint
              - elasticfilesystem:DescribeAccessPoints
            Resource:
              - !Sub "arn:${AWS::Partition}:elasticfilesystem:*:*:file-system/*"
              - !Sub "arn:${AWS::Partition}:elasticfilesystem:*:*:access-point/*"
            Effect: Allow
            Sid: EFSAccessPointsActions
          - Action:
              - ecr:ListImages
            Resource:
              - !Sub "arn:${AWS::Partition}:ecr:${AWS::Region}:${EcrAccountIdParameter.Value}:repository/cloudstoragesecurity/*"
            Effect: Allow
            Sid: ECR
          - Action:
              - bedrock:InvokeModel
              - bedrock:GetFoundationModel
              - bedrock:ListFoundationModels
            Resource: !Sub "arn:${AWS::Partition}:bedrock:*::foundation-model/*"
            Effect: Allow
            Sid: Bedrock
      Roles:
        - !If [CreateConsoleRole, !Ref ConsoleTaskRole, !Ref ConsoleTaskRoleName]
  ConsoleSecurityAndAccessPolicy:
    Type: AWS::IAM::ManagedPolicy
    DependsOn: ConsoleIAMPolicy
    Condition: CreateConsoleSecurityAndAccessPolicy
    Metadata:
      cfn_nag:
        rules_to_suppress:
          - id: W13
            reason: "Few actions require a wildcard for the application to properly work. For other actions AWS enforces its usage."
    Properties:
      ManagedPolicyName: !Sub "${ConsoleTaskPolicyPrefix}${AppConfigAgentApplication}-Security-And-Access-Policy"
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Action:
              - cognito-idp:AdminGetUser
              - cognito-idp:AdminCreateUser
              - cognito-idp:AdminAddUserToGroup
              - cognito-idp:AdminDeleteUser
              - cognito-idp:AdminDeleteUserAttributes
              - cognito-idp:AdminDisableUser
              - cognito-idp:AdminEnableUser
              - cognito-idp:AdminRemoveUserFromGroup
              - cognito-idp:AdminListGroupsForUser
              - cognito-idp:AdminUpdateUserAttributes
              - cognito-idp:ListTagsForResource
              - cognito-idp:ListUsers
              - cognito-idp:ListUsersInGroup
              - cognito-idp:CreateGroup
              - cognito-idp:DeleteGroup
              - cognito-idp:DescribeUserPoolClient
              - cognito-idp:DescribeUserPool
              - cognito-idp:UpdateUserPool
              - cognito-idp:ListIdentityProviders
              - cognito-idp:SetUserPoolMfaConfig
              - cognito-idp:AdminSetUserMFAPreference
            Resource:
              - !Sub "arn:${AWS::Partition}:cognito-idp:${AWS::Region}:${AWS::AccountId}:userpool/${UserPool}"
            Effect: Allow
            Sid: Cognito
          - Action:
              - iam:AddRoleToInstanceProfile
              - iam:CreateInstanceProfile
              - iam:DeleteInstanceProfile
              - iam:GetInstanceProfile
              - iam:RemoveRoleFromInstanceProfile
              - iam:TagInstanceProfile
              - iam:UntagInstanceProfile
              - iam:UpdateAssumeRolePolicy
              - iam:AttachRolePolicy
              - iam:DeleteRolePolicy
              - iam:DetachRolePolicy
              - iam:GetRolePolicy
              - iam:PutRolePolicy
              - iam:CreateRole
              - iam:DeleteRole
              - iam:GetRole
              - iam:PassRole
              - iam:TagRole
              - iam:UntagRole
            Resource:
              - !Sub "arn:${AWS::Partition}:iam::*:role/${UserPoolRolePrefix}${AppConfigAgentApplication}"
              - !If [
                  CreateAppConfigDocRole,
                  !GetAtt AppConfigAgentConfigurationDocumentRole.Arn,
                  !Ref AppConfigAgentConfigurationDocumentRoleArn,
                ]
              - !If [CreateExecutionRole, !GetAtt ExecutionRole.Arn, !Ref ExecutionRoleArn]
              - !If [CreateConsoleRole, !GetAtt ConsoleTaskRole.Arn, !Ref ConsoleTaskRoleArn]
              - !If [CreateAgentRole, !GetAtt AgentTaskRole.Arn, !Ref AgentTaskRoleArn]
              - !If [
                  CreateEc2ContainerRole,
                  !Sub "arn:${AWS::Partition}:iam::*:role/${Ec2ContainerRolePrefix}${AppConfigAgentApplication}",
                  !Ref Ec2ContainerInstanceProfileArn,
                ]
              - !If [
                  CreateEc2ContainerRole,
                  !Sub "arn:${AWS::Partition}:iam::*:instance-profile/${Ec2ContainerRolePrefix}${AppConfigAgentApplication}",
                  !Ref Ec2ContainerInstanceProfileArn,
                ]
              - !If [
                  CreateEventBridgeRole,
                  !Sub "arn:${AWS::Partition}:iam::*:role/${CrossAccountEventBridgeRolePrefix}${AppConfigAgentApplication}",
                  !Ref EventBridgeRoleArn,
                ]
            Effect: Allow
            Sid: IAMAction
          - Action:
              - sts:AssumeRole
            Resource: !Sub "arn:${AWS::Partition}:iam::*:role/*${AppConfigAgentApplication}"
            Effect: Allow
            Sid: CrossAccountAssumeRole
          - Action:
              - kms:Decrypt
              - kms:Encrypt
              - kms:GenerateDataKey
            Resource: !If [BlanketKmsAccess, !Sub "arn:${AWS::Partition}:kms:*:${AWS::AccountId}:key/*", !Sub "arn:${AWS::Partition}:kms:::key/no-blanket-kms-access"]
            Effect: Allow
            Condition:
              StringLike:
                kms:ViaService: !Sub s3.*.${AWS::URLSuffix}
            Sid: KmsConsole
          - Action:
              - application-autoscaling:DescribeScalableTargets
              - aws-marketplace:MeterUsage
              - acm:DescribeCertificate
              - acm:RequestCertificate
              - cloudformation:GetTemplateSummary
              - cloudwatch:GetMetricStatistics
              - ec2:DescribeTags
              - ec2:DescribeInternetGateways
              - ec2:DescribeInstances
              - ec2:DescribeNetworkAcls
              - ec2:DescribeNetworkInterfaces
              - ec2:DescribeRegions
              - ec2:DescribeRouteTables
              - ec2:DescribeSecurityGroups
              - ec2:DescribeSubnets
              - ec2:DescribeVolumes
              - ec2:DescribeVpcs
              - ec2:DescribeVpcPeeringConnections
              - ec2:DescribeInstanceTypeOfferings
              - ec2:DescribeSnapshots
              - ecs:DescribeTaskDefinition
              - ecs:DeregisterTaskDefinition
              - ecs:ListTaskDefinitions
              - fsx:DescribeFileSystems
              - fsx:DescribeVolumes
              - fsx:DescribeStorageVirtualMachines
              - logs:DescribeLogGroups
              - sns:ListSubscriptions
              - sns:ListSubscriptionsByTopic
              - sns:ListTopics
              - sns:Unsubscribe
              - sqs:ListQueues
            Resource: "*"
            Effect: Allow
            Sid: ReadOnlyGlobal
          - Action:
              - s3:GetBucketAcl
              - s3:GetBucketLocation
              - s3:GetBucketLogging
              - s3:GetBucketNotification
              - s3:GetBucketPolicy
              - s3:GetBucketPolicyStatus
              - s3:GetBucketPublicAccessBlock
              - s3:GetInventoryConfiguration
              - s3:GetEncryptionConfiguration
              - s3:GetBucketTagging
              - s3:GetBucketVersioning
              - s3:GetBucketWebsite
              - s3:GetLifecycleConfiguration
              - s3:GetObject
              - s3:GetObjectTagging
              - s3:ListAllMyBuckets
            Resource: !Sub "arn:${AWS::Partition}:s3:::*"
            Effect: Allow
            Sid: S3ReadOnly
          - Action:
              - s3:PutObject
              - s3:PutObjectTagging
              - s3:PutBucketLogging
              - s3:PutBucketNotification
              - s3:PutBucketPolicy
              - s3:PutBucketPublicAccessBlock
              - s3:PutInventoryConfiguration
            Resource:
              !If [
                UseDefaultS3BucketPrefixesRestrictedAccess,
                !Sub "arn:${AWS::Partition}:s3:::*",
                !Split [",", !Ref S3BucketPrefixesRestrictedAccess],
              ]
            Effect: Allow
            Sid: S3Write
          - !If
            - HasAnyCustomKmsKey
            - Sid: "CustomKms"
              Effect: Allow
              Action:
                - kms:CreateGrant
                - kms:Decrypt
                - kms:Encrypt
                - kms:GenerateDataKey
                - kms:DescribeKey
                - kms:ReEncryptFrom
                - kms:ReEncryptTo
                - kms:GetKeyPolicy
              Resource: !Split
                - ","
                - !Join
                  - ","
                  - - !If [HasCustomDynamoDBKmsKey, !Ref CustomDynamoDBKmsKey, !Ref "AWS::NoValue"]
                    - !If [HasCustomSqsConsoleKmsKey, !Ref CustomSqsConsoleKmsKey, !Ref "AWS::NoValue"]
                    - !If [HasCustomSnsConsoleKmsKey, !Ref CustomSnsConsoleKmsKey, !Ref "AWS::NoValue"]
                    - !If [HasCustomSqsAgentKmsKeys, !Ref CustomSqsAgentKmsKeys, !Ref "AWS::NoValue"]
                    - !If [HasCustomSnsAgentKmsKeys, !Ref CustomSnsAgentKmsKeys, !Ref "AWS::NoValue"]
                    - !If [HasCustomEbsKmsKeys, !Ref EbsVolumeEncryptionKmsKeyId, !Ref "AWS::NoValue"]
                    - !If [HasCustomS3KmsKey, !Ref S3KmsKeyId, !Ref "AWS::NoValue"]
            - !Ref AWS::NoValue
      Roles:
        - !If [CreateConsoleRole, !Ref ConsoleTaskRole, !Ref ConsoleTaskRoleName]
  ConsoleIAMPolicy:
    Type: AWS::IAM::Policy
    Metadata:
      cfn-lint:
        config:
          ignore_checks: [EIAMPolicyActionWildcard]
          ignore_reasons:
            EIAMPolicyActionWildcard: >
              not using wildcards will cause the overall role size to be too large
    Properties:
      PolicyName: !Sub "${ConsoleTaskPolicyPrefix}${AppConfigAgentApplication}-PoliciesCreation"
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Action:
              - iam:TagPolicy
              - iam:UntagPolicy
              - iam:CreatePolicy
              - iam:DeletePolicy
              - iam:DeletePolicyVersion
              - iam:ListPolicyVersions
              - iam:CreatePolicyVersion
            Resource:
              - !If [
                  CreateConsoleEc2ManagementPolicy,
                  !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/${ConsoleTaskPolicyPrefix}${AppConfigAgentApplication}-EC2-Management-Policy",
                  !Ref ConsoleEc2ManagementPolicyArn,
                ]
              - !If [
                  CreateConsoleInfrastructureManagementPolicy,
                  !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/${ConsoleTaskPolicyPrefix}${AppConfigAgentApplication}-Infrastructure-Management-Policy",
                  !Ref ConsoleInfrastructureManagementPolicyArn,
                ]
              - !If [
                  CreateConsoleLoggingAndMonitoringPolicy,
                  !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/${ConsoleTaskPolicyPrefix}${AppConfigAgentApplication}-Logging-And-Monitoring-Policy",
                  !Ref ConsoleLoggingAndMonitoringPolicyArn,
                ]
              - !If [
                  CreateConsoleApplicationResourcesPolicy,
                  !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/${ConsoleTaskPolicyPrefix}${AppConfigAgentApplication}-Application-Resources-Policy",
                  !Ref ConsoleApplicationResourcesPolicyArn,
                ]
              - !If [
                  CreateConsoleSecurityAndAccessPolicy,
                  !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/${ConsoleTaskPolicyPrefix}${AppConfigAgentApplication}-Security-And-Access-Policy",
                  !Ref ConsoleSecurityAndAccessPolicyArn,
                ]
            Effect: Allow
            Sid: IAMCSSPoliciesAction
      Roles:
        - !If [CreateConsoleRole, !Ref ConsoleTaskRole, !Ref ConsoleTaskRoleName]
  ConsoleTaskPolicyApiLb:
    Type: AWS::IAM::Policy
    Metadata:
      cfn_nag:
        rules_to_suppress:
          - id: W12
            reason: "we need resource * on some resources as we do not know their IDs but need access for our application to secure them"
      cfn-lint:
        config:
          ignore_checks: [EIAMPolicyActionWildcard]
          ignore_reasons:
            EIAMPolicyActionWildcard: >
              not using wildcards will cause the overall role size to be too large
    DependsOn: ConsoleIAMPolicy
    Properties:
      PolicyName: !Sub "${ConsoleTaskPolicyPrefix}${AppConfigAgentApplication}-ApiLb"
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Sid: !Sub "AllResources${AppConfigAgentApplication}"
            Effect: Allow
            Action:
              - ec2:DescribeAccountAttributes
              - elasticloadbalancing:DescribeListeners
              - elasticloadbalancing:DescribeLoadBalancers
              - elasticloadbalancing:DescribeTargetGroups
            Resource: "*"
          - Sid: !Sub "RestrictedResources${AppConfigAgentApplication}"
            Effect: Allow
            Action:
              - elasticloadbalancing:Create*
              - elasticloadbalancing:Delete*
              - elasticloadbalancing:Modify*
              - elasticloadbalancing:*Tags
              - elasticloadbalancing:SetSubnets
              - iam:CreateServiceLinkedRole
            Resource:
              - !Sub "arn:${AWS::Partition}:elasticloadbalancing:*:*:listener/*/*${AppConfigAgentApplication}/*"
              - !Sub "arn:${AWS::Partition}:elasticloadbalancing:*:*:loadbalancer/*/*${AppConfigAgentApplication}/*"
              - !Sub "arn:${AWS::Partition}:elasticloadbalancing:*:*:targetgroup/*${AppConfigAgentApplication}/*"
              - !Sub "arn:${AWS::Partition}:iam::*:role/aws-service-role/elasticloadbalancing.amazonaws.com/AWSServiceRoleForElasticLoadBalancing"
      Roles:
        - !If [CreateConsoleRole, !Ref ConsoleTaskRole, !Ref ConsoleTaskRoleName]
  ConsoleTaskPolicyAwsLicensing:
    Type: AWS::IAM::Policy
    Metadata:
      cfn_nag:
        rules_to_suppress:
          - id: W12
            reason: "we need resource * on some resources as we do not know their IDs but need access for our application to secure them"
      cfn-lint:
        config:
          ignore_checks: [EIAMPolicyActionWildcard]
          ignore_reasons:
            EIAMPolicyActionWildcard: >
              not using wildcards will cause the overall role size to be too large
    DependsOn: ConsoleIAMPolicy
    Properties:
      PolicyName: !Sub "${ConsoleTaskPolicyPrefix}${AppConfigAgentApplication}-AwsLicensing"
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Sid: !Sub "AllResources${AppConfigAgentApplication}"
            Effect: Allow
            Action:
              - license-manager:CheckoutLicense
              - license-manager:ListReceivedLicenses
            Resource: "*"
      Roles:
        - !If [CreateConsoleRole, !Ref ConsoleTaskRole, !Ref ConsoleTaskRoleName]
  CloudTrailLakePolicy:
    Type: AWS::IAM::Policy
    Metadata:
      cfn_nag:
        rules_to_suppress:
          - id: F39
            reason: "resource: * on iam:PassRole being passed to CloudTrail is required for the CloudTrail Lake integration."
          - id: W12
            reason: "we need resource * on some resources as we do not know their IDs but need access for our application to secure them"
    DependsOn: ConsoleIAMPolicy
    Properties:
      PolicyName: !Sub "${ConsoleTaskPolicyPrefix}${AppConfigAgentApplication}-CloudTrailLake"
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Sid: CloudTrail
            Effect: Allow
            Action:
              - cloudtrail:*DataStore*
              - cloudtrail:*Quer*
              - cloudtrail:*Channel*
              - cloudtrail-data:*Audit*
              - iam:ListRoles
              - iam:GetRolePolicy
              - iam:GetUser
            Resource: "*"
          - Sid: PassRole
            Effect: Allow
            Action:
              - iam:PassRole
            Resource: "*"
            Condition:
              StringEquals:
                iam:PassedToService: cloudtrail.amazonaws.com
      Roles:
        - !If [CreateConsoleRole, !Ref ConsoleTaskRole, !Ref ConsoleTaskRoleName]
  ProactiveNotificationsEventBridgePolicy:
    Type: AWS::IAM::Policy
    Condition: EventBridgeNotificationsEnabledYes
    DependsOn: ConsoleIAMPolicy
    Properties:
      PolicyName: !Sub "ProactiveNotificationsEventBridgePolicy-${AppConfigAgentApplication}"
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Sid: !Sub PutEvents${AppConfigAgentApplication}
            Effect: Allow
            Action:
              - events:PutEvents
              - events:DescribeEventBus
            Resource:
              - !Sub "arn:${AWS::Partition}:events:*:${AWS::AccountId}:event-bus/${EventBridgeNotificationsBusName}"
      Roles:
        - !If [CreateConsoleRole, !Ref ConsoleTaskRole, !Ref ConsoleTaskRoleName]
        - !If [CreateAgentRole, !Ref AgentTaskRole, !Ref AgentTaskRoleName]
  AgentTaskRole:
    Type: AWS::IAM::Role
    Condition: CreateAgentRole
    Properties:
      RoleName: !Sub "${AgentTaskRolePrefix}${AppConfigAgentApplication}"
      AssumeRolePolicyDocument: !If
        - IsECSDeployment
        - !Sub
            - |
              {
                "Version": "2012-10-17",
                "Statement": [
                  {
                    "Effect": "Allow",
                    "Principal": {
                      "Service": "ecs-tasks.amazonaws.com",
                      "AWS": "${ResolvedConsoleTaskRoleArn}"
                    },
                    "Action": "sts:AssumeRole"
                  }
                ]
              }
            - ResolvedConsoleTaskRoleArn: !If [CreateConsoleRole, !GetAtt ConsoleTaskRole.Arn, !Ref ConsoleTaskRoleArn]
        - !Sub
            - |
              {
                "Version": "2012-10-17",
                "Statement": [
                  {
                    "Effect": "Allow",
                    "Principal": {
                      "Federated": "arn:${AWS::Partition}:iam::${AWS::AccountId}:oidc-provider/${IamOidcProviderName}"
                    },
                    "Action": "sts:AssumeRoleWithWebIdentity",
                    "Condition": {
                      "StringEquals": {
                        "${OidcVar}": [
                            "system:serviceaccount:${EksNamespace}:${EksAgentServiceAccountName}",
                            "system:serviceaccount:keda:keda-operator"
                        ]
                      }
                    }
                  }
                ]
              }
            - OidcVar: !Sub "${IamOidcProviderName}:sub"
  AgentTaskPolicy:
    Type: "AWS::IAM::Policy"
    Metadata:
      cfn_nag:
        rules_to_suppress:
          - id: F4
            reason: "not using wildcards on actions will cause the overall role size to be too large."
          - id: W12
            reason: "we need resource * on some resources as we do not know their IDs but need access for our application to secure them"
          - id: W76
            reason: "the policy is complex due to the nature of the application"
      cfn-lint:
        config:
          ignore_checks: [EIAMPolicyActionWildcard, EIAMPolicyWildcardResource]
          ignore_reasons:
            EIAMPolicyActionWildcard: >
              not using wildcards will cause the overall role size to be too large
            EIAMPolicyWildcardResource: >
              we need resource * on some resources as we do not know their IDs but need access for our application to secure them
    Properties:
      PolicyName: !Sub "${AgentTaskPolicyPrefix}${AppConfigAgentApplication}"
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Sid: "AllResources"
            Effect: Allow
            Action:
              - aws-marketplace:MeterUsage
              - ec2:DescribeVpcs
              - ec2:DescribeAvailabilityZones
              - elasticfilesystem:DescribeMountTargets
            Resource: "*"
          - Sid: "ListActions"
            Effect: Allow
            Action:
              - appconfig:ListApplications
              - appconfig:ListDeploymentStrategies
              - ssm:ListDocuments
            Resource:
              - !Sub "arn:${AWS::Partition}:appconfig:*:*:*"
              - !Sub "arn:${AWS::Partition}:ssm:*:*:*"
          - Sid: "S3ReadOnly"
            Effect: Allow
            Action:
              - s3:GetBucketAcl
              - s3:GetBucketLocation
              - s3:GetObject*
              - s3:GetEncryptionConfiguration
              - s3:ListBucket
            Resource: !Sub "arn:${AWS::Partition}:s3:::*"
          - Sid: "S3Write"
            Effect: Allow
            Action:
              - s3:DeleteObject
              - s3:DeleteObjectVersion
              - s3:PutObject*
              - s3:PutEncryptionConfiguration
            Resource:
              !If [
                UseDefaultS3BucketPrefixesRestrictedAccess,
                !Sub "arn:${AWS::Partition}:s3:::*",
                !Split [",", !Ref S3BucketPrefixesRestrictedAccess],
              ]
          - Sid: CloudStorageSecS3AgentQuarantineBucket
            Effect: Allow
            Action:
              - s3:ListBucket
              - s3:PutLifecycleConfiguration
              - s3:PutEncryptionConfiguration
              - s3:PutBucketTagging
              - s3:GetBucketTagging
              - s3:GetObject
              - s3:GetObjectTagging
              - s3:GetObjectAttributes
              - s3:PutObject
              - s3:PutObjectAcl
              - s3:PutObjectTagging
              - s3:PutObjectVersionAcl
              - s3:PutObjectVersionTagging
              - s3:DeleteObject
              - s3:DeleteObjectTagging
              - s3:DeleteObjectVersion
              - s3:DeleteObjectVersionTagging
            Resource:
              - !Sub "arn:${AWS::Partition}:s3:::${QuarantineBucketNamePrefix}${AppConfigAgentApplication}-*"
              - !Sub "arn:${AWS::Partition}:s3:::${QuarantineBucketNamePrefix}${AppConfigAgentApplication}-*/*"
          - Sid: "RestrictedResources"
            Effect: Allow
            Action:
              - appconfig:GetApplication
              - appconfig:StartConfigurationSession
              - appconfig:GetLatestConfiguration
              - appconfig:GetConfiguration*
              - appconfig:GetDeploymentStrategy
              - appconfig:GetEnvironment
              - appconfig:ListConfigurationProfiles
              - appconfig:ListDeployments
              - appconfig:ListEnvironments
              - cognito-idp:*
              - dynamodb:DeleteItem
              - dynamodb:DescribeTable
              - dynamodb:GetItem
              - dynamodb:PutItem
              - dynamodb:BatchGetItem
              - dynamodb:BatchWriteItem
              - dynamodb:Query
              - dynamodb:Scan
              - dynamodb:UpdateItem
              - logs:CreateLogStream
              - logs:DescribeLogGroups
              - logs:PutLogEvents
              - secretsmanager:GetSecretValue
              - secretsmanager:DescribeSecret
              - securityhub:BatchImportFindings
              - sns:ConfirmSubscription
              - sns:Publish
              - sns:GetSubscriptionAttributes
              - sns:ListSubscriptionsByTopic
              - sqs:*Message
              - sqs:GetQueueAttributes
              - ssm:GetDocument
              - ssm:GetParameters
              - ssm:GetParametersByPath
            Resource:
              - !Sub "arn:${AWS::Partition}:appconfig:*:*:application/${AppConfigAgentApplication}/configurationprofile/*"
              - !Sub "arn:${AWS::Partition}:appconfig:*:*:application/${AppConfigAgentApplication}/environment/${AppConfigAgentEnvironment}"
              - !Sub "arn:${AWS::Partition}:appconfig:*:*:application/${AppConfigAgentApplication}/environment/${AppConfigAgentEnvironment}/configuration/${AppConfigProfile}"
              - !Sub "arn:${AWS::Partition}:appconfig:*:*:application/${AppConfigAgentApplication}"
              - !Sub "arn:${AWS::Partition}:appconfig:*:*:deploymentstrategy/${AppConfigAgentDeploymentStrategy}"
              - !Sub "arn:${AWS::Partition}:cognito-idp:*:*:userpool/${UserPool}"
              - !Sub "arn:${AWS::Partition}:dynamodb:${AWS::Region}:*:table/${DynamoTableNamePrefixParameter.Value}*"
              - !Sub "arn:${AWS::Partition}:logs:*:*:*"
              - !Sub "arn:${AWS::Partition}:securityhub:${AWS::Region}::product/cloud-storage-security/antivirus-for-amazon-s3"
              - !Sub "arn:${AWS::Partition}:sns:*:*:*${AppConfigAgentApplication}"
              - !Sub "arn:${AWS::Partition}:sqs:*:*:*${AppConfigAgentApplication}*"
              - !Sub "arn:${AWS::Partition}:ssm:*:*:document/*${AppConfigAgentApplication}"
              - !Sub "arn:${AWS::Partition}:ssm:*:*:parameter/*${AppConfigAgentApplication}/*"
              - !Sub "arn:${AWS::Partition}:ssm:*:*:parameter/*${AppConfigAgentApplication}"
              - !Sub "arn:${AWS::Partition}:secretsmanager:${AWS::Region}:*:secret:cloudstoragesec/*"
          - Sid: "Logs"
            Effect: Allow
            Action: logs:CreateLogGroup
            Resource: !Sub "arn:${AWS::Partition}:logs:*:*:*"
          - Sid: "CrossAccount"
            Effect: Allow
            Action: sts:AssumeRole
            Resource:
              - !Sub "arn:${AWS::Partition}:iam::*:role/*${AppConfigAgentApplication}"
          - Sid: "Kms"
            Effect: Allow
            Condition:
              StringLike:
                kms:ViaService: !Sub s3.*.${AWS::URLSuffix}
            Action:
              - kms:Decrypt
              - kms:Encrypt
              - kms:GenerateDataKey
            Resource: !If [BlanketKmsAccess, "*", !Sub "arn:${AWS::Partition}:kms:::key/no-blanket-kms-access"]
          - !If
            - HasAnyCustomKmsKey
            - Sid: "CustomKms"
              Effect: Allow
              Action:
                - kms:CreateGrant
                - kms:Decrypt
                - kms:Encrypt
                - kms:GenerateDataKey
                - kms:DescribeKey
                - kms:ReEncryptFrom
                - kms:ReEncryptTo
                - kms:GetKeyPolicy
              Resource: !Split
                - ","
                - !Join
                  - ","
                  - - !If [HasCustomDynamoDBKmsKey, !Ref CustomDynamoDBKmsKey, !Ref "AWS::NoValue"]
                    - !If [HasCustomSqsConsoleKmsKey, !Ref CustomSqsConsoleKmsKey, !Ref "AWS::NoValue"]
                    - !If [HasCustomSnsConsoleKmsKey, !Ref CustomSnsConsoleKmsKey, !Ref "AWS::NoValue"]
                    - !If [HasCustomSqsAgentKmsKeys, !Ref CustomSqsAgentKmsKeys, !Ref "AWS::NoValue"]
                    - !If [HasCustomSnsAgentKmsKeys, !Ref CustomSnsAgentKmsKeys, !Ref "AWS::NoValue"]
                    - !If [HasCustomEbsKmsKeys, !Ref EbsVolumeEncryptionKmsKeyId, !Ref "AWS::NoValue"]
                    - !If [HasCustomS3KmsKey, !Ref S3KmsKeyId, !Ref "AWS::NoValue"]
            - !Ref AWS::NoValue
      Roles:
        - !If [CreateAgentRole, !Ref AgentTaskRole, !Ref AgentTaskRoleName]
  ExecutionRole:
    Type: AWS::IAM::Role
    Condition: CreateExecutionRole
    Properties:
      RoleName: !Sub "${ExecutionRolePrefix}${AppConfigAgentApplication}"
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service: ecs-tasks.amazonaws.com
            Action: "sts:AssumeRole"
      ManagedPolicyArns:
        - !Sub "arn:${AWS::Partition}:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
  EventBridgeRole:
    Type: AWS::IAM::Role
    DependsOn: ConsoleIAMPolicy
    Condition: CreateEventBridgeRole
    Properties:
      RoleName: !Sub "${CrossAccountEventBridgeRolePrefix}${AppConfigAgentApplication}"
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service: events.amazonaws.com
            Action: sts:AssumeRole
  EventBridgePolicy:
    Type: AWS::IAM::Policy
    DependsOn: ConsoleIAMPolicy
    Properties:
      PolicyName: !Sub "${CrossAccountEventBridgePolicyPrefix}${AppConfigAgentApplication}"
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Sid: !Sub PutEvents${AppConfigAgentApplication}
            Effect: Allow
            Action:
              - events:PutEvents
            Resource:
              - !Sub "arn:${AWS::Partition}:events:*:${AWS::AccountId}:event-bus/*${AppConfigAgentApplication}"
      Roles:
        - !If [CreateEventBridgeRole, !Ref EventBridgeRole, !Ref EventBridgeRoleName]
  Ec2ContainerRole:
    Type: AWS::IAM::Role
    DependsOn: ConsoleIAMPolicy
    Condition: CreateEc2ContainerRole
    Properties:
      RoleName: !Sub "${Ec2ContainerRolePrefix}${AppConfigAgentApplication}"
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service: ec2.amazonaws.com
            Action: "sts:AssumeRole"
      ManagedPolicyArns:
        - !Sub "arn:${AWS::Partition}:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role"
  Ec2ContainerPolicy:
    Type: "AWS::IAM::Policy"
    Metadata:
      cfn_nag:
        rules_to_suppress:
          - id: W12
            reason: "Wildcards specifications are enforced by AWS."
    DependsOn: ConsoleIAMPolicy
    Properties:
      PolicyName: !Sub "${Ec2ContainerPolicyPrefix}${AppConfigAgentApplication}"
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Sid: TagRestrictedResources
            Effect: Allow
            Condition:
              StringEquals:
                ec2:ResourceTag/CloudStorageSecExtraLargeFileScanning: "ExtraLargeFileScanning"
            Action:
              - ec2:TerminateInstances
              - ec2:DeleteSnapshot
              - ec2:DeleteVolume
              - ec2:DescribeVolumeAttribute
              - ec2:DetachVolume
              - ec2:ModifySnapshotAttribute
              - ec2:ModifyVolumeAttribute
              - ec2:ModifyInstanceAttribute
            Resource:
              - !Sub "arn:${AWS::Partition}:ec2:*:${AWS::AccountId}:*"
              - !Sub "arn:${AWS::Partition}:ec2:*:${AWS::AccountId}:volume/*"
              - !Sub "arn:${AWS::Partition}:ec2:*::snapshot/*"
          - Sid: TagResources
            Effect: Allow
            Action:
              - ec2:CreateTags
            Resource:
              - !Sub "arn:${AWS::Partition}:ec2:*:${AWS::AccountId}:*"
              - !Sub "arn:${AWS::Partition}:ec2:*::image/*"
              - !Sub "arn:${AWS::Partition}:ec2:*::snapshot/*"
              - !Sub "arn:${AWS::Partition}:ec2:*:${AWS::AccountId}:volume/*"
          - Sid: AllResources
            Effect: Allow
            Action:
              - ec2:AttachVolume
              - ec2:CopySnapshot
              - ec2:CreateSnapshot
              - ec2:CreateVolume
              - ec2:DescribeAvailabilityZones
              - ec2:DescribeInstances
              - ec2:DescribeSnapshotAttribute
              - ec2:DescribeSnapshots
              - ec2:DescribeTags
              - ec2:DescribeVolumes
              - ec2:DescribeVolumeStatus
            Resource: "*"
          - Sid: KmsAccess
            Effect: Allow
            Condition:
              StringLike:
                kms:ViaService: !Sub ec2.*.${AWS::URLSuffix}
            Action:
              - kms:CreateGrant
            Resource: !If [BlanketKmsAccess, "*", !Sub "arn:${AWS::Partition}:kms:::key/no-blanket-kms-access"]
      Roles:
        - !If [CreateEc2ContainerRole, !Ref Ec2ContainerRole, !Ref Ec2ContainerInstanceRoleName]
  Ec2ContainerInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    DependsOn: ConsoleIAMPolicy
    Condition: CreateEc2ContainerRole
    Properties:
      InstanceProfileName: !Sub "${Ec2ContainerRolePrefix}${AppConfigAgentApplication}"
      Roles:
        - !Ref Ec2ContainerRole
  ContainerSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Metadata:
      cfn-lint:
        config:
          ignore_checks: [W3687]
      cfn_nag:
        rules_to_suppress:
          - id: W5
            reason: "we are explicitly specifying the default egress"
          - id: W40
            reason: "we are explicitly specifying the default egress"
    Condition: CreateConsoleSecurityGroupNoLB
    DependsOn: ConsoleIAMPolicy
    Properties:
      GroupDescription: !Sub "${ConsoleSecurityGroupPrefix}${AppConfigAgentApplication}"
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: !Ref ConsoleSecurityGroupCidrBlock
          Description: CloudStorageSec Console port 80 ingress
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: !Ref ConsoleSecurityGroupCidrBlock
          Description: CloudStorageSec Console port 443 ingress
      SecurityGroupEgress:
        - IpProtocol: "-1"
          FromPort: 0
          ToPort: 0
          CidrIp: 0.0.0.0/0
          Description: CloudStorageSec Console default egress to internet
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "SecurityGroup"
  ExistingConsoleSecurityGroupIngressPort80:
    Type: "AWS::EC2::SecurityGroupIngress"
    Condition: UseExistingConsoleSecurityGroup
    Properties:
      Description: CloudStorageSec Ingress Rule for User provided SG
      GroupId: !Ref ConsoleSecurityGroup
      IpProtocol: tcp
      FromPort: 80
      ToPort: 80
      CidrIp: !Ref ConsoleSecurityGroupCidrBlock
  ExistingConsoleSecurityGroupIngressPort443:
    Type: "AWS::EC2::SecurityGroupIngress"
    Condition: UseExistingConsoleSecurityGroup
    Properties:
      Description: CloudStorageSec Ingress Rule for User provided SG
      GroupId: !Ref ConsoleSecurityGroup
      IpProtocol: tcp
      FromPort: 443
      ToPort: 443
      CidrIp: !Ref ConsoleSecurityGroupCidrBlock
  ContainerSecurityGroupWithLB:
    Type: AWS::EC2::SecurityGroup
    Metadata:
      cfn-lint:
        config:
          ignore_checks: [W1030, W3687]
      cfn_nag:
        rules_to_suppress:
          - id: W5
            reason: "we are explicitly specifying the default egress"
          - id: W40
            reason: "we are explicitly specifying the default egress"
    Condition: CreateContainerSecurityGroupLB
    DependsOn: ConsoleIAMPolicy
    Properties:
      GroupDescription: !Sub "${ConsoleSecurityGroupPrefix}${AppConfigAgentApplication}"
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          SourceSecurityGroupId:
            !If [CreateConsoleSecurityGroupLB, !Ref LoadBalancerSecurityGroup, !Ref ConsoleSecurityGroup]
          Description: CloudStorageSec Console port 80 ingress
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          SourceSecurityGroupId:
            !If [CreateConsoleSecurityGroupLB, !Ref LoadBalancerSecurityGroup, !Ref ConsoleSecurityGroup]
          Description: CloudStorageSec Console port 443 ingress
      SecurityGroupEgress:
        - IpProtocol: "-1"
          FromPort: 0
          ToPort: 0
          CidrIp: 0.0.0.0/0
          Description: CloudStorageSec Console default egress to internet
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "SecurityGroup"
  ExistingContainerSecurityGroupIngressPort80:
    Type: "AWS::EC2::SecurityGroupIngress"
    Condition: UseExistingContainerSecurityGroupLB
    Properties:
      Description: CloudStorageSec Console port 80 ingress
      GroupId: !Ref ContainerSecurityGroupLB
      IpProtocol: tcp
      FromPort: 80
      ToPort: 80
      SourceSecurityGroupId:
        !If [CreateConsoleSecurityGroupLB, !Ref LoadBalancerSecurityGroup, !Ref ConsoleSecurityGroup]
    Metadata:
      cfn-lint:
        config:
          ignore_checks: [W1030]
  ExistingContainerSecurityGroupIngressPort443:
    Type: "AWS::EC2::SecurityGroupIngress"
    Condition: UseExistingContainerSecurityGroupLB
    Properties:
      Description: CloudStorageSec Console port 443 ingress
      GroupId: !Ref ContainerSecurityGroupLB
      IpProtocol: tcp
      FromPort: 443
      ToPort: 443
      SourceSecurityGroupId:
        !If [CreateConsoleSecurityGroupLB, !Ref LoadBalancerSecurityGroup, !Ref ConsoleSecurityGroup]
    Metadata:
      cfn-lint:
        config:
          ignore_checks: [W1030]
  LoadBalancerSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Metadata:
      cfn-lint:
        config:
          ignore_checks: [W1030, W3687]
      cfn_nag:
        rules_to_suppress:
          - id: W5
            reason: "we are explicitly specifying the default egress"
          - id: W40
            reason: "we are explicitly specifying the default egress"
    Condition: CreateConsoleSecurityGroupLB
    DependsOn: ConsoleIAMPolicy
    Properties:
      GroupDescription: !Sub "${LoadBalancerGroupPrefix}${AppConfigAgentApplication}"
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: !Ref ConsoleSecurityGroupCidrBlock
          Description: CloudStorageSec Console port 80 ingress
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: !Ref ConsoleSecurityGroupCidrBlock
          Description: CloudStorageSec Console port 443 ingress
      SecurityGroupEgress:
        - IpProtocol: "-1"
          FromPort: 0
          ToPort: 0
          CidrIp: 0.0.0.0/0
          Description: CloudStorageSec Console default egress to internet
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "SecurityGroup"
  CloudwatchLogsGroup:
    Type: "AWS::Logs::LogGroup"
    Metadata:
      cfn_nag:
        rules_to_suppress:
          - id: W84
            reason: "to avoid complication we do not force user to supply CMK, but they may apply this after deployment"
    DependsOn: ConsoleIAMPolicy
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Properties:
      LogGroupName: !Sub "CloudStorageSecurity.ECS.${AppConfigAgentApplication}.Console"
      RetentionInDays: !If [SetLogGroupRetentionPolicy, 7, !Ref AWS::NoValue]
  Cluster:
    Type: AWS::ECS::Cluster
    Condition: IsECSDeployment
    DependsOn: ConsoleIAMPolicy
    Properties:
      ClusterName: !Sub "${ClusterPrefix}${AppConfigAgentApplication}"
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "ConsoleCluster"
  Service:
    Type: AWS::ECS::Service
    Condition: IsECSDeploymentDontUseLB
    Properties:
      ServiceName: !Sub "${ServicePrefix}${AppConfigAgentApplication}"
      Cluster: !Ref Cluster
      TaskDefinition: !Ref TaskDefinition
      DeploymentConfiguration:
        MinimumHealthyPercent: 100
        MaximumPercent: 200
      DesiredCount: 1
      LaunchType: FARGATE
      PlatformVersion: 1.4.0
      NetworkConfiguration:
        AwsvpcConfiguration:
          AssignPublicIp: !Ref ConsoleAutoAssignPublicIp
          Subnets:
            - !Ref SubnetA
            - !Ref SubnetB
          SecurityGroups:
            - !If [CreateConsoleSecurityGroupNoLB, !Ref ContainerSecurityGroup, !Ref ConsoleSecurityGroup]
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "ConsoleService"
      PropagateTags: "SERVICE"
    Metadata:
      cfn-lint:
        config:
          ignore_checks: [W1030]
  ServiceWithLB:
    Type: AWS::ECS::Service
    Condition: IsECSDeploymentCreateLB
    DependsOn:
      - Listener
      - ConsoleTaskPolicyApiLb
    Properties:
      ServiceName: !Sub "${ServicePrefix}LB-${AppConfigAgentApplication}"
      Cluster: !Ref Cluster
      TaskDefinition: !Ref TaskDefinition
      DeploymentConfiguration:
        MinimumHealthyPercent: 100
        MaximumPercent: 200
      DesiredCount: 1
      LaunchType: FARGATE
      PlatformVersion: 1.4.0
      NetworkConfiguration:
        AwsvpcConfiguration:
          AssignPublicIp: !Ref ConsoleAutoAssignPublicIp
          Subnets:
            - !Ref SubnetA
            - !Ref SubnetB
          SecurityGroups:
            - !If [CreateContainerSecurityGroupLB, !Ref ContainerSecurityGroupWithLB, !Ref ContainerSecurityGroupLB]
      LoadBalancers:
        - ContainerName: !Sub "${TaskDefinitionPrefix}${AppConfigAgentApplication}"
          ContainerPort: 443
          TargetGroupArn: !Ref TargetGroup
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "ConsoleService"
      PropagateTags: "SERVICE"
    Metadata:
      cfn-lint:
        config:
          ignore_checks: [W1030]
  ServiceWithExistingLB:
    Type: AWS::ECS::Service
    Condition: IsECSDeploymentExistingLB
    DependsOn:
      - ConsoleTaskPolicyApiLb
    Properties:
      ServiceName: !Sub "${ServicePrefix}LB-${AppConfigAgentApplication}"
      Cluster: !Ref Cluster
      TaskDefinition: !Ref TaskDefinition
      DeploymentConfiguration:
        MinimumHealthyPercent: 100
        MaximumPercent: 200
      DesiredCount: 1
      LaunchType: FARGATE
      PlatformVersion: 1.4.0
      NetworkConfiguration:
        AwsvpcConfiguration:
          AssignPublicIp: !Ref ConsoleAutoAssignPublicIp
          Subnets:
            - !Ref SubnetA
            - !Ref SubnetB
          SecurityGroups:
            - !If [CreateContainerSecurityGroupLB, !Ref ContainerSecurityGroupWithLB, !Ref ContainerSecurityGroupLB]
      LoadBalancers:
        - ContainerName: !Sub "${TaskDefinitionPrefix}${AppConfigAgentApplication}"
          ContainerPort: 443
          TargetGroupArn: !Ref ExistingTargetGroup
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "ConsoleService"
      PropagateTags: "SERVICE"
    Metadata:
      cfn-lint:
        config:
          ignore_checks: [W1030]
  TaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Condition: IsECSDeployment
    DependsOn: ConsoleIAMPolicy
    Properties:
      Family: !Sub "${TaskDefinitionPrefix}${AppConfigAgentApplication}"
      NetworkMode: awsvpc
      RequiresCompatibilities:
        - FARGATE
      Cpu: !FindInMap [vCPUvalues, !Ref ConsoleCpu, size]
      Memory: !FindInMap [MemValues, !Ref ConsoleMemory, size]
      ExecutionRoleArn: !If [CreateExecutionRole, !GetAtt ExecutionRole.Arn, !Ref ExecutionRoleArn]
      TaskRoleArn: !If [CreateConsoleRole, !GetAtt ConsoleTaskRole.Arn, !Ref ConsoleTaskRoleArn]
      RuntimePlatform:
        CpuArchitecture: X86_64
        OperatingSystemFamily: LINUX
      ContainerDefinitions:
        - Name: !Sub "${TaskDefinitionPrefix}${AppConfigAgentApplication}"
          User: "1001"
          Privileged: false
          Image: !Sub
            - ${EcrAccountIdParameter.Value}.dkr.ecr.${AWS::Region}.amazonaws.com/cloudstoragesecurity/console:${version}
            - { version: !FindInMap [Constants, Version, ImageVersionConsole] }
          Cpu: !FindInMap [vCPUvalues, !Ref ConsoleCpu, size]
          Memory: !FindInMap [MemValues, !Ref ConsoleMemory, size]
          MemoryReservation: !FindInMap [MemValues, !Ref ConsoleMemory, size]
          Environment:
            - Name: IMAGE_VERSION_CONSOLE
              Value: !FindInMap [Constants, Version, ImageVersionConsole]
            - Name: IMAGE_VERSION_AGENT
              Value: !FindInMap [Constants, Version, ImageVersionAgent]
            - Name: AGENT_TASK_DEFINITION_ROLE_ARN
              Value: !If [CreateAgentRole, !GetAtt AgentTaskRole.Arn, !Ref AgentTaskRoleArn]
            - Name: APP_CONFIG_AGENT_APPLICATION_ID
              Value: !Ref AppConfigAgentApplication
            - Name: APP_CONFIG_AGENT_CONFIGURATION_PROFILE_ROLE_ARN
              Value:
                !If [
                  CreateAppConfigDocRole,
                  !GetAtt AppConfigAgentConfigurationDocumentRole.Arn,
                  !Ref AppConfigAgentConfigurationDocumentRoleArn,
                ]
            - Name: APP_CONFIG_AGENT_DEPLOYMENT_STRATEGY_ID
              Value: !Ref AppConfigAgentDeploymentStrategy
            - Name: APP_CONFIG_AGENT_ENVIRONMENT_ID
              Value: !Ref AppConfigAgentEnvironment
            - Name: EXECUTION_ROLE_ARN
              Value: !If [CreateExecutionRole, !GetAtt ExecutionRole.Arn, !Ref ExecutionRoleArn]
            - Name: EC2_CONTAINER_ROLE_ARN
              Value:
                !If [
                  CreateEc2ContainerRole,
                  !GetAtt Ec2ContainerInstanceProfile.Arn,
                  !Ref Ec2ContainerInstanceProfileArn,
                ]
            - Name: VPC_ID
              Value: !Ref VPC
            - Name: SUBNETS
              Value: !Join [",", [!Ref SubnetA, !Ref SubnetB]]
            - Name: PARAMETER_STORE_NAME_PREFIX
              Value: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}"
            - Name: CONSOLE_SECURITY_GROUP_ID
              Value:
                !If [
                  CreateConsoleSecurityGroup,
                  !If [UseLB, !GetAtt LoadBalancerSecurityGroup.GroupId, !GetAtt ContainerSecurityGroup.GroupId],
                  !Ref ConsoleSecurityGroup,
                ]
            - Name: AGENT_AUTO_ASSIGN_PUBLIC_IP
              Value: !Ref AgentAutoAssignPublicIp
            - Name: BLANKET_KMS_ACCESS
              Value: !If [BlanketKmsAccess, True, False]
            - Name: HAS_LOAD_BALANCER
              Value: !If [UseLB, True, False]
            - Name: TRUSTED_LOAD_BALANCER_NETWORK
              Value: !Ref TrustedLoadBalancerNetwork
            - Name: INFO_OPT_OUT
              Value: !FindInMap [yesNoToBool, !Ref InfoOptOut, value]
            - Name: QUARANTINE_BUCKET_NAME_PREFIX
              Value: !Sub "${QuarantineBucketNamePrefix}${AppConfigAgentApplication}"
            - Name: DYNAMO_DB_TABLE_NAME_PREFIX
              Value: !GetAtt DynamoTableNamePrefixParameter.Value
            - Name: CLUSTER_NAME
              Value: !Sub "${ClusterPrefix}${AppConfigAgentApplication}"
            - Name: NOTIFICATIONS_TOPIC_NAME
              Value: !Sub "${NotificationsTopicPrefix}${AppConfigAgentApplication}"
            - Name: APP_CONFIG_DOCUMENT_NAME
              Value: !Ref AppConfigDocument
            - Name: APP_CONFIG_DOCUMENT_SCHEMA_NAME
              Value: !Ref AppConfigDocumentSchema
            - Name: APP_CONFIG_PROFILE_ID
              Value: !Ref AppConfigProfile
            - Name: SCANNED_ITEMS_QUEUE_NAME
              Value: !GetAtt ScannedItemsQueue.QueueName
            - Name: EVENT_BASED_SCAN_TOPIC_NAME
              Value: !Sub "${EventBasedScanTopicPrefix}${AppConfigAgentApplication}"
            - Name: EVENT_BASED_SCAN_QUEUE_NAME
              Value: !Sub "${EventBasedScanQueuePrefix}${AppConfigAgentApplication}"
            - Name: DC_EVENT_BASED_SCAN_QUEUE_NAME
              Value: !Sub "${DcEventBasedScanQueuePrefix}${AppConfigAgentApplication}"
            - Name: EFS_SCAN_QUEUE_NAME
              Value: !Sub "${EfsScanQueuePrefix}${AppConfigAgentApplication}"
            - Name: RETRO_SCAN_QUEUE_NAME
              Value: !Sub "${RetroScanQueuePrefix}${AppConfigAgentApplication}"
            - Name: CONSOLE_TASK_NAME
              Value: !Sub "${TaskDefinitionPrefix}${AppConfigAgentApplication}"
            - Name: CONSOLE_SERVICE_NAME
              Value:
                !If [
                  UseLB,
                  !Sub "${ServicePrefix}LB-${AppConfigAgentApplication}",
                  !Sub "${ServicePrefix}${AppConfigAgentApplication}",
                ]
            - Name: CONSOLE_ROLE_ARN
              Value: !If [CreateConsoleRole, !GetAtt ConsoleTaskRole.Arn, !Ref ConsoleTaskRoleArn]
            - Name: EVENT_AGENT_TASK_NAME
              Value: !Sub "${EventAgentTaskPrefix}${AppConfigAgentApplication}"
            - Name: DC_EVENT_AGENT_TASK_NAME
              Value: !Sub "${DcEventAgentTaskPrefix}${AppConfigAgentApplication}"
            - Name: EVENT_AGENT_SERVICE_NAME
              Value: !Sub "${EventAgentServicePrefix}${AppConfigAgentApplication}"
            - Name: DC_EVENT_AGENT_SERVICE_NAME
              Value: !Sub "${DcEventAgentServicePrefix}${AppConfigAgentApplication}"
            - Name: EFS_AGENT_TASK_NAME
              Value: !Sub "${EfsAgentTaskPrefix}${AppConfigAgentApplication}"
            - Name: EBS_AGENT_TASK_NAME
              Value: !Sub "${EbsAgentTaskPrefix}${AppConfigAgentApplication}"
            - Name: EBS_DC_AGENT_TASK_NAME
              Value: !Sub "${DcEbsAgentTaskPrefix}${AppConfigAgentApplication}"
            - Name: EC2_SCAN_TASK_NAME
              Value: !Sub "${Ec2ScanTaskPrefix}${AppConfigAgentApplication}"
            - Name: LARGE_FILE_AGENT_TASK_NAME
              Value: !Sub "${LargeFileAgentTaskPrefix}${AppConfigAgentApplication}"
            - Name: API_AGENT_TASK_NAME
              Value: !Sub "${ApiAgentTaskPrefix}${AppConfigAgentApplication}"
            - Name: API_AGENT_SERVICE_NAME
              Value: !Sub "${ApiAgentServicePrefix}${AppConfigAgentApplication}"
            - Name: EFS_AGENT_SERVICE_NAME
              Value: !Sub "${EfsAgentServicePrefix}${AppConfigAgentApplication}"
            - Name: API_LB_NAME
              Value: !Sub "${ApiLoadBalancerPrefix}${AppConfigAgentApplication}"
            - Name: API_LB_TG_NAME
              Value: !Sub "${ApiTargetGroupPrefix}${AppConfigAgentApplication}"
            - Name: RETRO_AGENT_TASK_NAME
              Value: !Sub "${RetroAgentTaskPrefix}${AppConfigAgentApplication}"
            - Name: RETRO_AGENT_SERVICE_NAME
              Value: !Sub "${RetroAgentServicePrefix}${AppConfigAgentApplication}"
            - Name: LARGE_EVENT_QUEUE_ALARM_NAME
              Value: !Sub "${LargeEventQueueAlarmPrefix}${AppConfigAgentApplication}"
            - Name: SMALL_EVENT_QUEUE_ALARM_NAME
              Value: !Sub "${SmallEventQueueAlarmPrefix}${AppConfigAgentApplication}"
            - Name: DECREASE_AGENTS_SCALING_POLICY_NAME
              Value: !Sub "${DecreaseAgentsScalingPolicyPrefix}${AppConfigAgentApplication}"
            - Name: INCREASE_AGENTS_SCALING_POLICY_NAME
              Value: !Sub "${IncreaseAgentsScalingPolicyPrefix}${AppConfigAgentApplication}"
            - Name: LARGE_DC_EVENT_QUEUE_ALARM_NAME
              Value: !Sub "${LargeDcEventQueueAlarmPrefix}${AppConfigAgentApplication}"
            - Name: SMALL_DC_EVENT_QUEUE_ALARM_NAME
              Value: !Sub "${SmallDcEventQueueAlarmPrefix}${AppConfigAgentApplication}"
            - Name: DECREASE_DC_AGENTS_SCALING_POLICY_NAME
              Value: !Sub "${DecreaseDcAgentsScalingPolicyPrefix}${AppConfigAgentApplication}"
            - Name: INCREASE_DC_AGENTS_SCALING_POLICY_NAME
              Value: !Sub "${IncreaseDcAgentsScalingPolicyPrefix}${AppConfigAgentApplication}"
            - Name: API_REQUEST_SCALING_POLICY_NAME
              Value: !Sub "${ApiRequestScalingPolicyPrefix}${AppConfigAgentApplication}"
            - Name: API_CPU_SCALING_POLICY_NAME
              Value: !Sub "${ApiCpuScalingPolicyPrefix}${AppConfigAgentApplication}"
            - Name: RETRO_QUEUE_NOT_EMPTY_ALARM_NAME
              Value: !Sub "${RetroQueueNotEmptyAlarmPrefix}${AppConfigAgentApplication}"
            - Name: RETRO_QUEUE_EMPTY_ALARM_NAME
              Value: !Sub "${RetroQueueEmptyAlarmPrefix}${AppConfigAgentApplication}"
            - Name: REMOVE_RETRO_AGENTS_SCALING_POLICY_NAME
              Value: !Sub "${RemoveRetroAgentsScalingPolicyPrefix}${AppConfigAgentApplication}"
            - Name: SET_RETRO_AGENTS_SCALING_POLICY_NAME
              Value: !Sub "${SetRetroAgentsScalingPolicyPrefix}${AppConfigAgentApplication}"
            - Name: AGENT_SECURITY_GROUP_NAME
              Value: !Sub "${AgentSecurityGroupPrefix}${AppConfigAgentApplication}"
            - Name: EFS_SCAN_SECURITY_GROUP_NAME
              Value: !Sub "${EfsScanSecurityGroupPrefix}${AppConfigAgentApplication}"
            - Name: EBS_SCAN_SECURITY_GROUP_NAME
              Value: !Sub "${EbsScanSecurityGroupPrefix}${AppConfigAgentApplication}"
            - Name: FSX_SCAN_SECURITY_GROUP_NAME
              Value: !Sub "${FsxScanSecurityGroupPrefix}${AppConfigAgentApplication}"
            - Name: CROSS_ACCOUNT_ROLE_NAME
              Value: !Sub "${CrossAccountRolePrefix}${AppConfigAgentApplication}"
            - Name: ORGANIZATIONS_ROLE_NAME
              Value: !Sub "${OrganizationsRolePrefix}${AppConfigAgentApplication}"
            - Name: ORGANIZATIONS_POLICY_NAME
              Value: !Sub "${OrganizationsPolicyPrefix}${AppConfigAgentApplication}"
            - Name: CROSS_ACCOUNT_POLICY_NAME
              Value: !Sub "${CrossAccountPolicyPrefix}${AppConfigAgentApplication}"
            - Name: CROSS_ACCOUNT_EVENT_BRIDGE_ROLE_NAME
              Value: !Sub "${CrossAccountEventBridgeRolePrefix}${AppConfigAgentApplication}"
            - Name: CROSS_ACCOUNT_EVENT_BRIDGE_POLICY_NAME
              Value: !Sub "${CrossAccountEventBridgePolicyPrefix}${AppConfigAgentApplication}"
            - Name: DLP_CCL_DIR
              Value: "/cssdlp"
            - Name: DLP_CCL_FILE_NAME
              Value: "PredefinedContentControlLists.xml"
            - Name: PROXY_HOST
              Value: !If [UseProxy, !Ref ProxyHost, ""]
            - Name: PROXY_PORT
              Value: !If [UseProxy, !Ref ProxyPort, ""]
            - Name: PROXY_FORCE
              Value: !If [UseProxy, !FindInMap [yesNoToBool, !Ref ProxyForce, value], ""]
            - Name: PRODUCT_MODE
              Value: !Ref ProductMode
            - Name: TEMPLATE_VARIATION
              Value: !Ref TemplateVariation
            - Name: BUCKETS_TO_PROTECT
              Value: !Ref BucketsToProtect
            - Name: LOG_LEVEL
              Value: Info
            - Name: APPLICATION_BUCKET_NAME
              Value: !Ref ApplicationBucket
            - Name: RETRY_COUNT
              Value: "5"
            - Name: RETRY_MEDIAN_JITTER_DELAY
              Value: "1"
            - Name: ENABLED_REGIONS
              Value: !If [IsPrivateOrEksDeployment, !Ref AWS::Region, ""]
            - Name: SQS_CUSTOM_CONSOLE_KMS_KEY
              Value: !Ref CustomSqsConsoleKmsKey
            - Name: SNS_CUSTOM_CONSOLE_KMS_KEY
              Value: !Ref CustomSnsConsoleKmsKey
            - Name: SQS_CUSTOM_AGENT_KMS_KEYS
              Value: !Ref CustomSqsAgentKmsKeys
            - Name: SNS_CUSTOM_AGENT_KMS_KEYS
              Value: !Ref CustomSnsAgentKmsKeys
            - Name: CUSTOM_RESOURCE_TAGS
              Value: !Sub
                - "aws-apn-id=pc:${ProductCode}"
                - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
          PortMappings:
            - ContainerPort: 80
            - ContainerPort: 443
          ReadonlyRootFilesystem: yes
          LogConfiguration:
            LogDriver: awslogs
            Options:
              awslogs-group: !Ref CloudwatchLogsGroup
              awslogs-region: !Ref AWS::Region
              awslogs-stream-prefix: ecs
          HealthCheck:
            Command:
              - CMD-SHELL
              - curl -k -f https://localhost/api/health || exit 1
            Interval: 30
            Timeout: 5
            Retries: 3
            StartPeriod: 60
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "ConsoleTaskDefinition"
  TargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Condition: IsECSDeploymentCreateLB
    DependsOn: ConsoleTaskPolicyApiLb
    Properties:
      Name: !Sub "${TargetGroupPrefix}LB-${AppConfigAgentApplication}"
      Port: 443
      Protocol: HTTPS
      HealthCheckProtocol: HTTPS
      HealthCheckPort: 443
      HealthCheckPath: /Account/SignIn
      HealthCheckIntervalSeconds: 300
      HealthCheckTimeoutSeconds: 120
      TargetGroupAttributes:
        - Key: deregistration_delay.timeout_seconds
          Value: 60 # default is 300
      TargetType: ip
      VpcId: !Ref VPC
  Listener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Condition: IsECSDeploymentCreateLB
    Properties:
      DefaultActions:
        - TargetGroupArn: !Ref TargetGroup
          Type: forward
      LoadBalancerArn: !Ref LoadBalancer
      Port: 443
      Protocol: HTTPS
      SslPolicy: ELBSecurityPolicy-TLS13-1-3-2021-06
      Certificates:
        - CertificateArn: !Ref Certificate
  LoadBalancer:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Condition: IsECSDeploymentCreateLB
    Properties:
      LoadBalancerAttributes:
        # this is the default, but is specified here in case it needs to be changed
        - Key: idle_timeout.timeout_seconds
          Value: 60
        - Key: routing.http.drop_invalid_header_fields.enabled
          Value: "true"
      Name: !Sub "${LoadBalancerPrefix}${AppConfigAgentApplication}"
      # "internal" is also an option
      Scheme: !Ref LBScheme
      SecurityGroups:
        - !If [CreateConsoleSecurityGroupLB, !Ref LoadBalancerSecurityGroup, !Ref ConsoleSecurityGroup]
      Subnets:
        - !If [UseLBSubnetA, !Ref LBSubnetA, !Ref SubnetA]
        - !If [UseLBSubnetB, !Ref LBSubnetB, !Ref SubnetB]
    Metadata:
      cfn-lint:
        config:
          ignore_checks: [W1030]
      cfn_nag:
        rules_to_suppress:
          - id: W52
            reason: "to avoid unexpected AWS charges, access logging is not turned on, but may be enabled post-deployment."
  ProactiveNotificationsEventBridgeBus:
    Type: AWS::Events::EventBus
    Condition: CreateCustomEventBridgeBus
    DependsOn: ProactiveNotificationsEventBridgePolicy
    Properties:
      Name: !Ref EventBridgeNotificationsBusName
      Tags:
        - Key: aws-apn-id
          Value: !Sub
            - "pc:${ProductCode}"
            - ProductCode: !FindInMap [ProductListingToProductCode, !Ref ProductListing, code]
        - Key: !Join ["-", [CloudStorageSec, !Ref AppConfigAgentApplication]]
          Value: "ProactiveNotificationsEventBridgeBus"
  DynamoTableNamePrefixParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/DynamoTableNamePrefix"
      Value: !If [UseDefaultDynamoPrefix, !Sub "${AppConfigAgentApplication}.", !Ref DynamoTableNamePrefix]
  DynamoPointInTimeRecoveryEnabledParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/DynamoPointInTimeRecoveryEnabled"
      Value: !FindInMap [yesNoToBool, !Ref DynamoPointInTimeRecoveryEnabled, value]
  AgentEcrImageUrlParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/AgentEcrImageUrl"
      Value: !Sub
        - ${EcrAccountIdParameter.Value}.dkr.ecr.<region>.amazonaws.com/cloudstoragesecurity/agent:${version}
        - { version: !FindInMap [Constants, Version, ImageVersionAgent] }
  MaxNumAgentsParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/MaxNumAgents"
      Value: !Ref MaxRunningAgents
  MinNumAgentsParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/MinNumAgents"
      Value: !Ref MinRunningAgents
  QueueScalingThresholdParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/QueueScalingThreshold"
      Value: !Ref NumMessagesInQueueScalingThreshold
  DeployApiAgentParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/DeployApiAgent"
      Value: !Ref DeployApiAgent
  ApiAgentVpcParameter:
    Type: AWS::SSM::Parameter
    Condition: UseApiAgent
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/ApiAgentVpc"
      Value: !Ref ApiAgentVpc
  ApiAgentSubnetsParameter:
    Type: AWS::SSM::Parameter
    Condition: UseApiAgent
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/ApiAgentSubnets"
      Value: !Ref ApiAgentSubnets
  ApiAgentLBSubnetsParameter:
    Type: AWS::SSM::Parameter
    Condition: UseApiAgent
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/ApiAgentLBSubnets"
      Value: !Ref ApiAgentLBSubnets
  ApiAgentInboundCidrParameter:
    Type: AWS::SSM::Parameter
    Condition: UseApiAgent
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/ApiAgentInboundCidr"
      Value: !Ref ApiAgentInboundCidr
  ApiAgentSslCertArnParameter:
    Type: AWS::SSM::Parameter
    Condition: UseApiAgent
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/ApiAgentSslCertArn"
      Value: !Ref ApiAgentSslCertArn
  ApiAgentInternetFacingLBParameter:
    Type: AWS::SSM::Parameter
    Condition: UseApiAgent
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/ApiAgentInternetFacingLB"
      Value: !FindInMap [yesNoToBool, !Ref ApiAgentInternetFacingLB, value]
  ApiAgentAllowedOriginsParameter:
    Type: AWS::SSM::Parameter
    Condition: UseApiAgent
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/ApiAgentAllowedOrigins"
      Value: !If [HasApiAgentAllowedOrigins, !Ref ApiAgentAllowedOrigins, "none"]
  ApiAgentMinAgentsParameter:
    Type: AWS::SSM::Parameter
    Condition: UseApiAgent
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/ApiAgentMinAgents"
      Value: !Ref ApiAgentMinAgents
  ApiAgentMaxAgentsParameter:
    Type: AWS::SSM::Parameter
    Condition: UseApiAgent
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/ApiAgentMaxAgents"
      Value: !Ref ApiAgentMaxAgents
  ApiAgentCpuParameter:
    Type: AWS::SSM::Parameter
    Condition: UseApiAgent
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/ApiAgentCpu"
      Value: !FindInMap [vCPUvalues, !Ref ApiAgentCpu, size]
  ApiAgentMemoryParameter:
    Type: AWS::SSM::Parameter
    Condition: UseApiAgent
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/ApiAgentMemory"
      Value: !FindInMap [MemValues, !Ref ApiAgentMemory, size]
  ApiAgentDiskSizeParameter:
    Type: AWS::SSM::Parameter
    Condition: UseApiAgent
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/ApiAgentDiskSize"
      Value: !Ref ApiAgentDiskSize
  ApiAgentScanningEngineParameter:
    Type: AWS::SSM::Parameter
    DependsOn: ConsoleIAMPolicy
    Condition: UseApiAgent
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/ApiAgentScanningEngine"
      Value: !If
        - ApiAgentScanningEngineIsDefault
        - "Unknown"
        - !If
          - ApiAgentScanningEngineIsAll
          - "ClamAV, Sophos, Bitdefender"
          - !Ref ApiAgentScanningEngine
  ApiAgentMultiEngineScanningModeParameter:
    Type: AWS::SSM::Parameter
    DependsOn: ConsoleIAMPolicy
    Condition: UseApiAgent
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/ApiAgentMultiEngineScanningMode"
      Value: !If [ApiAgentScanningEngineIsAll, "All", "Disabled"]
  ApiAgentEnableAsynchronousScanningParameter:
    Type: AWS::SSM::Parameter
    Condition: UseApiAgent
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/ApiAgentEnableAsynchronousScanning"
      Value: !FindInMap [yesNoToBool, !Ref ApiAgentEnableAsynchronousScanning, value]
  AgentCpuParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/AgentCpu"
      Value: !FindInMap [vCPUvalues, !Ref AgentCpu, size]
  AgentMemoryParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/AgentMemory"
      Value: !FindInMap [MemValues, !Ref AgentMemory, size]
  AgentDiskSizeParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/AgentDiskSize"
      Value: !Ref AgentDiskSize
  EnableLargeFileScanningParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/EnableLargeFileScanning"
      Value: !FindInMap [yesNoToBool, !Ref EnableLargeFileScanning, value]
  StorageAssessmentEnabledParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/StorageAssessmentEnabled"
      Value: !FindInMap [yesNoToBool, !Ref StorageAssessmentEnabled, value]
  LargeFileDiskSizeParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/LargeFileDiskSize"
      Value: !Ref LargeFileDiskSize
  EbsVolumeEncryptionParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/ScanEbsEncryption"
      Value: !FindInMap [yesNoToBool, !Ref EbsVolumeEncryption, value]
  EbsVolumeEncryptionKmsKeyIdParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/ScanEbsKmsKeyIdEncryption"
      Value: !Ref EbsVolumeEncryptionKmsKeyId
  S3KmsKeyIdParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/S3KmsKeyId"
      Value: !Ref S3KmsKeyId
  LargeFileEC2TagsParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: StringList
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/LargeFileEC2Tags"
      Value: !Ref LargeFileEC2Tags
  SubdomainParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/Subdomain"
      Value: !Join ["-", [!Ref "AWS::AccountId", !Ref AppConfigAgentApplication]]
  ConsoleDomainURLParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/ConsoleDomainURL"
      Value:
        !If [
          UseLB,
          !If [UseRoute53, !Sub "https://${HostedSubdomain}.${HostedZoneName}", !Sub "https://${LoadBalancer.DNSName}"],
          !Sub "https://${SubdomainParameter.Value}.cloudstoragesecapp.com",
        ]
    Metadata:
      cfn-lint:
        config:
          ignore_checks: [W1001]
  EmailParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/Email"
      Value: !Ref Email
  UserNameParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/UserName"
      Value: !Ref UserName
  StackNameParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/StackName"
      Value: !If [HasParentStack, !Ref ParentStackName, !Ref AWS::StackName]
  PrivateMirrorParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/PrivateMirror"
      Value: "!!none_chosen!!"
  LastUpgradeNotesSeenParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/LastUpgradeNotesSeen"
      Value: "v1.00.000"
  LastPostUpgradeProcedureParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/LastPostUpgradeProcedure"
      Value: "v1.00.000"
  RegionParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/AWS/Region"
      Value: !Ref AWS::Region
  UserPoolClientIdParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/AWS/UserPoolClientId"
      Value: !Ref UserPoolClient
  UserPoolClientSecretParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/AWS/UserPoolClientSecret"
      Value: "AWS:UserPoolClientSecret"
  UserPoolIdParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/AWS/UserPoolId"
      Value: !Ref UserPool
  OnlyScanWhenQueueThresholdExceededParameter:
    Type: AWS::SSM::Parameter
    DependsOn: ConsoleIAMPolicy
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/OnlyScanWhenQueueThresholdExceeded"
      Value: !FindInMap [yesNoToBool, !Ref OnlyScanWhenQueueThresholdExceeded, value]
  QuarantineInPrimaryAccountParameter:
    Type: AWS::SSM::Parameter
    DependsOn: ConsoleIAMPolicy
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/QuarantineInPrimaryAccount"
      Value: !FindInMap [yesNoToBool, !Ref QuarantineInPrimaryAccount, value]
  SecurityHubEnabledParameter:
    Type: AWS::SSM::Parameter
    DependsOn: ConsoleIAMPolicy
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/SecurityHubEnabled"
      Value: "False"
  AgentScanningEngineParameter:
    Type: AWS::SSM::Parameter
    DependsOn: ConsoleIAMPolicy
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/AgentScanningEngine"
      Value: !Ref AgentScanningEngine
  ProductListingParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/ProductListing"
      Value: !Ref ProductListing
  MultiEngineScanningModeParameter:
    Type: AWS::SSM::Parameter
    DependsOn: ConsoleIAMPolicy
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/MultiEngineScanningMode"
      Value: !Ref MultiEngineScanningMode
  LargeFileEngineParameter:
    Type: AWS::SSM::Parameter
    DependsOn: ConsoleIAMPolicy
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/LargeFileEngine"
      Value: !Ref LargeFileEngine
  EcrAccountIdParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/EcrAccountId"
      Value: !If [UseDefaultEcrAccount, !If [IsGovCloud, "822167061992", "564477214187"], !Ref CustomEcrAccount]
  QuarantineBucketDaysToExpireParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/QuarantineBucketDaysToExpire"
      Value: !Ref QuarantineBucketDaysToExpire
  # EfsCrossVpcNetworkingParameter:
  #   Type: AWS::SSM::Parameter
  #   DependsOn: ConsoleTaskPolicy
  #   Properties:
  #     Type: String
  #     Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/EfsCrossVpcNetworking"
  #     Value: !Ref EfsCrossVpcNetworking
  AutoProtectBucketTagKeyParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/AutoProtectBucketTagKey"
      Value:
        !If [
          UseDefaultAutoProtectBucketTagKey,
          !Sub "CloudStorageSecAutoProtect-${AppConfigAgentApplication}",
          !Ref AutoProtectBucketTagKey,
        ]
  CloudTrailLakeEnabledParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/CloudTrailLakeEnabled"
      Value: !FindInMap [yesNoToBool, !Ref EnableCloudTrailLake, value]
  CloudTrailLakeEventDataStoreNameParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/CloudTrailLakeEventDataStoreName"
      Value:
        !If [
          UseDefaultCloudTrailLakeEventDataStoreName,
          !Sub "${CloudTrailLakeEventDataStorePrefix}${AppConfigAgentApplication}",
          !Ref CloudTrailLakeDataStoreName,
        ]
  CloudTrailLakeChannelNameParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/CloudTrailLakeChannelName"
      Value:
        !If [
          UseDefaultCloudTrailLakeChannelName,
          !Sub "${CloudTrailLakeChannelPrefix}${AppConfigAgentApplication}",
          !Ref CloudTrailLakeChannelName,
        ]
  CloudTrailLakeChannelArnParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/CloudTrailLakeArn"
      Value: "unknown"
  EBSDisabledParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/EbsDisabled"
      Value: !FindInMap [yesNoToBool, !Ref DisableEBSScanning, value]
  EFSDisabledParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/EfsDisabled"
      Value: !FindInMap [yesNoToBool, !Ref DisableEFSScanning, value]
  FSxDisabledParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/FsxDisabled"
      Value: !FindInMap [yesNoToBool, !Ref DisableFSxScanning, value]
  GuardDutyS3IntegrationEnabledRegionsParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/GuardDutyS3IntegrationEnabledRegions"
      Value: !If [UseCurrentRegionForGuardDutyS3Integration, !Ref AWS::Region, "DISABLED"]
  GuardDutyS3MalwareResultTypesParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/GuardDutyS3MalwareResultTypes"
      Value: !Ref GuardDutyS3MalwareResultTypes
  GuardDutyS3MalwareAdditionalScanningParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/GuardDutyS3MalwareAdditionalScanning"
      Value: !FindInMap [yesNoToBool, !Ref GuardDutyS3MalwareAdditionalScanning, value]
  RetroScanOnDetectedInfectionParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/RetroScanOnDetectedInfection"
      Value: !FindInMap [yesNoToBool, !Ref RetroScanOnDetectedInfection, value]
  EventBridgeNotificationsEnabledParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/EventBridgeNotificationsEnabled"
      Value: !FindInMap [yesNoToBool, !Ref EventBridgeNotificationsEnabled, value]
  EventBridgeNotificationsBusNameParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/EventBridgeNotificationsBusName"
      Value: !Ref EventBridgeNotificationsBusName
  SetLogGroupRetentionPolicyParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/SetLogGroupRetentionPolicy"
      Value: !FindInMap [yesNoToBool, !Ref LogGroupRetentionPolicy, value]
  UseFipsEndpointsParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/UseFipsEndpoints"
      Value: !FindInMap [yesNoToBool, !Ref UseFipsEndpoints, value]
  AzureMaxNumAgentsParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/AzureMaxNumAgents"
      Value: !Ref AzureMaxRunningAgents
  AzureMinNumAgentsParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/AzureMinNumAgents"
      Value: !Ref AzureMinRunningAgents
  AzureQueueScalingThresholdParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/AzureQueueScalingThreshold"
      Value: !Ref AzureNumMessagesInQueueScalingThreshold
  AzureOnlyScanWhenQueueThresholdExceededParameter:
    Type: AWS::SSM::Parameter
    DependsOn: ConsoleIAMPolicy
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/AzureOnlyScanWhenQueueThresholdExceeded"
      Value: !FindInMap [yesNoToBool, !Ref AzureOnlyScanWhenQueueThresholdExceeded, value]
  AzureBicepTemplateLatestVersionParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/Config/AzureBicepTemplateLatestVersion"
      Value: "TO_BE_SET"
  # EKS Environment Variables SSM Parameters
  EksImageVersionConsoleParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/IMAGE_VERSION_CONSOLE"
      Value: !FindInMap [Constants, Version, ImageVersionConsole]
      Description: Console image version for EKS deployment
  EksImageVersionAgentParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/IMAGE_VERSION_AGENT"
      Value: !FindInMap [Constants, Version, ImageVersionAgent]
      Description: Agent image version for EKS deployment
  EksAgentTaskDefinitionRoleArnParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/AGENT_TASK_DEFINITION_ROLE_ARN"
      Value: !If [CreateAgentRole, !GetAtt AgentTaskRole.Arn, !Ref AgentTaskRoleArn]
      Description: Agent task role ARN for EKS deployment
  EksAppConfigAgentApplicationIdParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/APP_CONFIG_AGENT_APPLICATION_ID"
      Value: !Ref AppConfigAgentApplication
      Description: AppConfig agent application ID for EKS deployment
  EksAppConfigAgentConfigurationProfileRoleArnParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/APP_CONFIG_AGENT_CONFIGURATION_PROFILE_ROLE_ARN"
      Value: !If [CreateAppConfigDocRole, !GetAtt AppConfigAgentConfigurationDocumentRole.Arn, !Ref AppConfigAgentConfigurationDocumentRoleArn]
      Description: AppConfig configuration profile role ARN for EKS deployment
# New parameters
  EksAppConfigAgentDeploymentStrategyIdParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/APP_CONFIG_AGENT_DEPLOYMENT_STRATEGY_ID"
      Value: !Ref AppConfigAgentDeploymentStrategy
      Description: AppConfig deployment strategy ID for EKS deployment
  EksAppConfigAgentEnvironmentIdParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/APP_CONFIG_AGENT_ENVIRONMENT_ID"
      Value: !Ref AppConfigAgentEnvironment
      Description: AppConfig environment ID for EKS deployment
  EksExecutionRoleArnParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/EXECUTION_ROLE_ARN"
      Value: !If [CreateExecutionRole, !GetAtt ExecutionRole.Arn, !Ref ExecutionRoleArn]
      Description: Execution role ARN for EKS deployment
  EksEc2ContainerRoleArnParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/EC2_CONTAINER_ROLE_ARN"
      Value: !If [CreateEc2ContainerRole, !GetAtt Ec2ContainerInstanceProfile.Arn, !Ref Ec2ContainerInstanceProfileArn]
      Description: EC2 container role ARN for EKS deployment
  EksParameterStoreNamePrefixParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/PARAMETER_STORE_NAME_PREFIX"
      Value: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}"
      Description: Parameter store name prefix for EKS deployment
  EksConsoleSecurityGroupIdParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/CONSOLE_SECURITY_GROUP_ID"
      Value: !Ref ConsoleSecurityGroup
      Description: Console security group ID for EKS deployment
  EksAgentAutoAssignPublicIpParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/AGENT_AUTO_ASSIGN_PUBLIC_IP"
      Value: !Ref AgentAutoAssignPublicIp
      Description: Agent auto assign public IP setting for EKS deployment
  EksBlanketKmsAccessParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/BLANKET_KMS_ACCESS"
      Value: !If [BlanketKmsAccess, "True", "False"]
      Description: Blanket KMS access setting for EKS deployment
  EksHasLoadBalancerParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/HAS_LOAD_BALANCER"
      Value: !If [UseLB, "True", "False"]
      Description: Load balancer usage setting for EKS deployment
  EksTrustedLoadBalancerNetworkParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeploymentWithTrustedNetwork
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/TRUSTED_LOAD_BALANCER_NETWORK"
      Value: !Ref TrustedLoadBalancerNetwork
      Description: Trusted load balancer network for EKS deployment
  EksInfoOptOutParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/INFO_OPT_OUT"
      Value: !FindInMap [yesNoToBool, !Ref InfoOptOut, value]
      Description: Info opt-out setting for EKS deployment
  EksQuarantineBucketNamePrefixParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/QUARANTINE_BUCKET_NAME_PREFIX"
      Value: !Sub "${QuarantineBucketNamePrefix}${AppConfigAgentApplication}"
      Description: Quarantine bucket name prefix for EKS deployment
  EksDynamoDbTableNamePrefixParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/DYNAMO_DB_TABLE_NAME_PREFIX"
      Value: !GetAtt DynamoTableNamePrefixParameter.Value
      Description: DynamoDB table name prefix for EKS deployment
  EksClusterNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/CLUSTER_NAME"
      Value: !Sub "${EksClusterName}"
      Description: Cluster name for EKS deployment
  EksNotificationsTopicNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/NOTIFICATIONS_TOPIC_NAME"
      Value: !Sub "${NotificationsTopicPrefix}${AppConfigAgentApplication}"
      Description: Notifications topic name for EKS deployment
  EksAppConfigDocumentNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/APP_CONFIG_DOCUMENT_NAME"
      Value: !Ref AppConfigDocument
      Description: AppConfig document name for EKS deployment
  EksAppConfigDocumentSchemaNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/APP_CONFIG_DOCUMENT_SCHEMA_NAME"
      Value: !Ref AppConfigDocumentSchema
      Description: AppConfig document schema name for EKS deployment
  EksAppConfigProfileIdParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/APP_CONFIG_PROFILE_ID"
      Value: !Ref AppConfigProfile
      Description: AppConfig profile ID for EKS deployment
  EksScannedItemsQueueNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/SCANNED_ITEMS_QUEUE_NAME"
      Value: !GetAtt ScannedItemsQueue.QueueName
      Description: Scanned items queue name for EKS deployment
  EksEventBasedScanTopicNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/EVENT_BASED_SCAN_TOPIC_NAME"
      Value: !Sub "${EventBasedScanTopicPrefix}${AppConfigAgentApplication}"
      Description: Event-based scan topic name for EKS deployment
  EksEventBasedScanQueueNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/EVENT_BASED_SCAN_QUEUE_NAME"
      Value: !Sub "${EventBasedScanQueuePrefix}${AppConfigAgentApplication}"
      Description: Event-based scan queue name for EKS deployment
  EksDcEventBasedScanQueueNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/DC_EVENT_BASED_SCAN_QUEUE_NAME"
      Value: !Sub "${DcEventBasedScanQueuePrefix}${AppConfigAgentApplication}"
      Description: DC event-based scan queue name for EKS deployment
  EksEfsScanQueueNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/EFS_SCAN_QUEUE_NAME"
      Value: !Sub "${EfsScanQueuePrefix}${AppConfigAgentApplication}"
      Description: EFS scan queue name for EKS deployment
  EksRetroScanQueueNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/RETRO_SCAN_QUEUE_NAME"
      Value: !Sub "${RetroScanQueuePrefix}${AppConfigAgentApplication}"
      Description: Retro scan queue name for EKS deployment
  EksConsoleTaskNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/CONSOLE_TASK_NAME"
      Value: !Sub "${TaskDefinitionPrefix}${AppConfigAgentApplication}"
      Description: Console task name for EKS deployment
  EksConsoleServiceNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/CONSOLE_SERVICE_NAME"
      Value: !If [UseLB, !Sub "${ServicePrefix}LB-${AppConfigAgentApplication}", !Sub "${ServicePrefix}${AppConfigAgentApplication}"]
      Description: Console service name for EKS deployment
  EksConsoleRoleArnParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/CONSOLE_ROLE_ARN"
      Value: !If [CreateConsoleRole, !GetAtt ConsoleTaskRole.Arn, !Ref ConsoleTaskRoleArn]
      Description: Console role ARN for EKS deployment
  EksEventAgentTaskNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/EVENT_AGENT_TASK_NAME"
      Value: !Sub "${EventAgentTaskPrefix}${AppConfigAgentApplication}"
      Description: Event agent task name for EKS deployment
  EksDcEventAgentTaskNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/DC_EVENT_AGENT_TASK_NAME"
      Value: !Sub "${DcEventAgentTaskPrefix}${AppConfigAgentApplication}"
      Description: DC event agent task name for EKS deployment
  EksEventAgentServiceNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/EVENT_AGENT_SERVICE_NAME"
      Value: !Sub "${EventAgentServicePrefix}${AppConfigAgentApplication}"
      Description: Event agent service name for EKS deployment
  EksDcEventAgentServiceNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/DC_EVENT_AGENT_SERVICE_NAME"
      Value: !Sub "${DcEventAgentServicePrefix}${AppConfigAgentApplication}"
      Description: DC event agent service name for EKS deployment
  EksEfsAgentTaskNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/EFS_AGENT_TASK_NAME"
      Value: !Sub "${EfsAgentTaskPrefix}${AppConfigAgentApplication}"
      Description: EFS agent task name for EKS deployment
  EksEbsAgentTaskNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/EBS_AGENT_TASK_NAME"
      Value: !Sub "${EbsAgentTaskPrefix}${AppConfigAgentApplication}"
      Description: EBS agent task name for EKS deployment
  EksEbsDcAgentTaskNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/EBS_DC_AGENT_TASK_NAME"
      Value: !Sub "${DcEbsAgentTaskPrefix}${AppConfigAgentApplication}"
      Description: EBS DC agent task name for EKS deployment
  EksEc2ScanTaskNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/EC2_SCAN_TASK_NAME"
      Value: !Sub "${Ec2ScanTaskPrefix}${AppConfigAgentApplication}"
      Description: EC2 scan task name for EKS deployment
  EksLargeFileAgentTaskNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/LARGE_FILE_AGENT_TASK_NAME"
      Value: !Sub "${LargeFileAgentTaskPrefix}${AppConfigAgentApplication}"
      Description: Large file agent task name for EKS deployment
  EksApiAgentTaskNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/API_AGENT_TASK_NAME"
      Value: !Sub "${ApiAgentTaskPrefix}${AppConfigAgentApplication}"
      Description: API agent task name for EKS deployment
  EksApiAgentServiceNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/API_AGENT_SERVICE_NAME"
      Value: !Sub "${ApiAgentServicePrefix}${AppConfigAgentApplication}"
      Description: API agent service name for EKS deployment
  EksEfsAgentServiceNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/EFS_AGENT_SERVICE_NAME"
      Value: !Sub "${EfsAgentServicePrefix}${AppConfigAgentApplication}"
      Description: EFS agent service name for EKS deployment
  EksApiLbNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/API_LB_NAME"
      Value: !Sub "${ApiLoadBalancerPrefix}${AppConfigAgentApplication}"
      Description: API load balancer name for EKS deployment
  EksApiLbTgNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/API_LB_TG_NAME"
      Value: !Sub "${ApiTargetGroupPrefix}${AppConfigAgentApplication}"
      Description: API load balancer target group name for EKS deployment
  EksRetroAgentTaskNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/RETRO_AGENT_TASK_NAME"
      Value: !Sub "${RetroAgentTaskPrefix}${AppConfigAgentApplication}"
      Description: Retro agent task name for EKS deployment
  EksRetroAgentServiceNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/RETRO_AGENT_SERVICE_NAME"
      Value: !Sub "${RetroAgentServicePrefix}${AppConfigAgentApplication}"
      Description: Retro agent service name for EKS deployment
  EksLargeEventQueueAlarmNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/LARGE_EVENT_QUEUE_ALARM_NAME"
      Value: !Sub "${LargeEventQueueAlarmPrefix}${AppConfigAgentApplication}"
      Description: Large event queue alarm name for EKS deployment
  EksSmallEventQueueAlarmNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/SMALL_EVENT_QUEUE_ALARM_NAME"
      Value: !Sub "${SmallEventQueueAlarmPrefix}${AppConfigAgentApplication}"
      Description: Small event queue alarm name for EKS deployment
  EksDecreaseAgentsScalingPolicyNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/DECREASE_AGENTS_SCALING_POLICY_NAME"
      Value: !Sub "${DecreaseAgentsScalingPolicyPrefix}${AppConfigAgentApplication}"
      Description: Decrease agents scaling policy name for EKS deployment
  EksIncreaseAgentsScalingPolicyNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/INCREASE_AGENTS_SCALING_POLICY_NAME"
      Value: !Sub "${IncreaseAgentsScalingPolicyPrefix}${AppConfigAgentApplication}"
      Description: Increase agents scaling policy name for EKS deployment
  EksLargeDcEventQueueAlarmNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/LARGE_DC_EVENT_QUEUE_ALARM_NAME"
      Value: !Sub "${LargeDcEventQueueAlarmPrefix}${AppConfigAgentApplication}"
      Description: Large DC event queue alarm name for EKS deployment
  EksSmallDcEventQueueAlarmNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/SMALL_DC_EVENT_QUEUE_ALARM_NAME"
      Value: !Sub "${SmallDcEventQueueAlarmPrefix}${AppConfigAgentApplication}"
      Description: Small DC event queue alarm name for EKS deployment
  EksDecreaseDcAgentsScalingPolicyNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/DECREASE_DC_AGENTS_SCALING_POLICY_NAME"
      Value: !Sub "${DecreaseDcAgentsScalingPolicyPrefix}${AppConfigAgentApplication}"
      Description: Decrease DC agents scaling policy name for EKS deployment
  EksIncreaseDcAgentsScalingPolicyNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/INCREASE_DC_AGENTS_SCALING_POLICY_NAME"
      Value: !Sub "${IncreaseDcAgentsScalingPolicyPrefix}${AppConfigAgentApplication}"
      Description: Increase DC agents scaling policy name for EKS deployment
  EksApiRequestScalingPolicyNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/API_REQUEST_SCALING_POLICY_NAME"
      Value: !Sub "${ApiRequestScalingPolicyPrefix}${AppConfigAgentApplication}"
      Description: API request scaling policy name for EKS deployment
  EksApiCpuScalingPolicyNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/API_CPU_SCALING_POLICY_NAME"
      Value: !Sub "${ApiCpuScalingPolicyPrefix}${AppConfigAgentApplication}"
      Description: API CPU scaling policy name for EKS deployment
  EksRetroQueueNotEmptyAlarmNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/RETRO_QUEUE_NOT_EMPTY_ALARM_NAME"
      Value: !Sub "${RetroQueueNotEmptyAlarmPrefix}${AppConfigAgentApplication}"
      Description: Retro queue not empty alarm name for EKS deployment
  EksRetroQueueEmptyAlarmNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/RETRO_QUEUE_EMPTY_ALARM_NAME"
      Value: !Sub "${RetroQueueEmptyAlarmPrefix}${AppConfigAgentApplication}"
      Description: Retro queue empty alarm name for EKS deployment
  EksRemoveRetroAgentsScalingPolicyNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/REMOVE_RETRO_AGENTS_SCALING_POLICY_NAME"
      Value: !Sub "${RemoveRetroAgentsScalingPolicyPrefix}${AppConfigAgentApplication}"
      Description: Remove retro agents scaling policy name for EKS deployment
  EksSetRetroAgentsScalingPolicyNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/SET_RETRO_AGENTS_SCALING_POLICY_NAME"
      Value: !Sub "${SetRetroAgentsScalingPolicyPrefix}${AppConfigAgentApplication}"
      Description: Set retro agents scaling policy name for EKS deployment
  EksAgentSecurityGroupNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/AGENT_SECURITY_GROUP_NAME"
      Value: !Sub "${AgentSecurityGroupPrefix}${AppConfigAgentApplication}"
      Description: Agent security group name for EKS deployment
  EksEfsScanSecurityGroupNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/EFS_SCAN_SECURITY_GROUP_NAME"
      Value: !Sub "${EfsScanSecurityGroupPrefix}${AppConfigAgentApplication}"
      Description: EFS scan security group name for EKS deployment
  EksEbsScanSecurityGroupNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/EBS_SCAN_SECURITY_GROUP_NAME"
      Value: !Sub "${EbsScanSecurityGroupPrefix}${AppConfigAgentApplication}"
      Description: EBS scan security group name for EKS deployment
  EksFsxScanSecurityGroupNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/FSX_SCAN_SECURITY_GROUP_NAME"
      Value: !Sub "${FsxScanSecurityGroupPrefix}${AppConfigAgentApplication}"
      Description: FSX scan security group name for EKS deployment
  EksOrganizationsRoleNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/ORGANIZATIONS_ROLE_NAME"
      Value: !Sub "${OrganizationsRolePrefix}${AppConfigAgentApplication}"
      Description: AWS Organizations integration role name for EKS deployment
  EksOrganizationsPolicyNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/ORGANIZATIONS_POLICY_NAME"
      Value: !Sub "${OrganizationsPolicyPrefix}${AppConfigAgentApplication}"
      Description: AWS Organizations integration policy name for EKS deployment
  EksCrossAccountRoleNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/CROSS_ACCOUNT_ROLE_NAME"
      Value: !Sub "${CrossAccountRolePrefix}${AppConfigAgentApplication}"
      Description: Cross account role name for EKS deployment
  EksCrossAccountPolicyNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/CROSS_ACCOUNT_POLICY_NAME"
      Value: !Sub "${CrossAccountPolicyPrefix}${AppConfigAgentApplication}"
      Description: Cross account policy name for EKS deployment
  EksCrossAccountEventBridgeRoleNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/CROSS_ACCOUNT_EVENT_BRIDGE_ROLE_NAME"
      Value: !Sub "${CrossAccountEventBridgeRolePrefix}${AppConfigAgentApplication}"
      Description: Cross account EventBridge role name for EKS deployment
  EksCrossAccountEventBridgePolicyNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/CROSS_ACCOUNT_EVENT_BRIDGE_POLICY_NAME"
      Value: !Sub "${CrossAccountEventBridgePolicyPrefix}${AppConfigAgentApplication}"
      Description: Cross account EventBridge policy name for EKS deployment
  EksDlpCclDirParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/DLP_CCL_DIR"
      Value: "/cssdlp"
      Description: DLP CCL directory for EKS deployment
  EksDlpCclFileNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/DLP_CCL_FILE_NAME"
      Value: "PredefinedContentControlLists.xml"
      Description: DLP CCL file name for EKS deployment
  EksProxyHostParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeploymentWithProxy
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/PROXY_HOST"
      Value: !Ref ProxyHost
      Description: Proxy host for EKS deployment
  EksProxyPortParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeploymentWithProxy
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/PROXY_PORT"
      Value: !Ref ProxyPort
      Description: Proxy port for EKS deployment
  EksProxyForceParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeploymentWithProxy
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/PROXY_FORCE"
      Value: !Ref ProxyForce
      Description: Proxy Force for EKS deployment
  EksProductModeParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/PRODUCT_MODE"
      Value: !Ref ProductMode
      Description: Product mode for EKS deployment
  EksTemplateVariationParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/TEMPLATE_VARIATION"
      Value: !Ref TemplateVariation
      Description: Template variation for EKS deployment
  EksBucketsToProtectParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeploymentWithBucketsToProtect
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/BUCKETS_TO_PROTECT"
      Value: !Ref BucketsToProtect
      Description: Buckets to protect for EKS deployment
  EksLogLevelParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/LOG_LEVEL"
      Value: "Info"
      Description: Log level for EKS deployment
  EksApplicationBucketNameParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/APPLICATION_BUCKET_NAME"
      Value: !Ref ApplicationBucket
      Description: Application bucket name for EKS deployment
  EksRetryCountParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/RETRY_COUNT"
      Value: "5"
      Description: Retry count for EKS deployment
  EksRetryMedianJitterDelayParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/RETRY_MEDIAN_JITTER_DELAY"
      Value: "1"
      Description: Retry median jitter delay for EKS deployment
  EksEnabledRegionsParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeployment
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/ENABLED_REGIONS"
      Value: !If [IsPrivateOrEksDeployment, !Ref AWS::Region, ""]
      Description: Enabled regions for EKS deployment
  EksSqsCustomConsoleKmsKeyParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeploymentWithSqsKms
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/SQS_CUSTOM_CONSOLE_KMS_KEY"
      Value: !Ref CustomSqsConsoleKmsKey
      Description: SQS custom console KMS key for EKS deployment
  EksSnsCustomConsoleKmsKeyParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeploymentWithSnsKms
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/SNS_CUSTOM_CONSOLE_KMS_KEY"
      Value: !Ref CustomSnsConsoleKmsKey
      Description: SNS custom console KMS key for EKS deployment
  EksSqsCustomAgentKmsKeysParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeploymentWithSqsAgentKms
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/SQS_CUSTOM_AGENT_KMS_KEYS"
      Value: !Ref CustomSqsAgentKmsKeys
      Description: SQS custom agent KMS keys for EKS deployment
  EksSnsCustomAgentKmsKeysParameter:
    Type: AWS::SSM::Parameter
    Condition: IsEKSDeploymentWithSnsAgentKms
    Properties:
      Type: String
      Name: !Sub "/${ParametersPrefix}${AppConfigAgentApplication}/EKS/SNS_CUSTOM_AGENT_KMS_KEYS"
      Value: !Ref CustomSnsAgentKmsKeys
      Description: SNS custom agent KMS keys for EKS deployment
# end parameters eks
  SQSPermissionCreationReady:
    Type: AWS::CloudFormation::WaitConditionHandle
    Metadata:
      ApplicationResourcesPolicy:
        !If [CreateConsoleApplicationResourcesPolicy, !Ref ConsoleApplicationResourcesPolicy, ""]
  ScannedItemsQueue:
    Type: AWS::SQS::Queue
    DependsOn: SQSPermissionCreationReady
    Properties:
      QueueName: !Sub "${ScannedItemsQueuePrefix}${AppConfigAgentApplication}"
      MessageRetentionPeriod: 1209600
      VisibilityTimeout: 1200
      ReceiveMessageWaitTimeSeconds: 20
      MaximumMessageSize: 262144
      KmsMasterKeyId: !If
        - HasCustomSqsConsoleKmsKey
        - !Ref CustomSqsConsoleKmsKey
        - !Ref "AWS::NoValue"
  NotificationsTopic:
    Type: AWS::SNS::Topic
    Metadata:
      cfn_nag:
        rules_to_suppress:
          - id: W47
            reason: "to avoid complication we do not force user to supply a custom KMS key, but they may apply this after deployment"
    DependsOn: ConsoleIAMPolicy
    Properties:
      TopicName: !Sub "${NotificationsTopicPrefix}${AppConfigAgentApplication}"
      KmsMasterKeyId: !If
        - HasCustomSnsConsoleKmsKey
        - !Ref CustomSnsConsoleKmsKey
        - !Ref "AWS::NoValue"
  NotificationsTopicPolicy:
    Type: AWS::SNS::TopicPolicy
    DependsOn: ConsoleIAMPolicy
    Properties:
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              AWS:
                - !If [CreateConsoleRole, !GetAtt ConsoleTaskRole.Arn, !Ref ConsoleTaskRoleArn]
                - !If [CreateAgentRole, !GetAtt AgentTaskRole.Arn, !Ref AgentTaskRoleArn]
              Service:
                - cloudwatch.amazonaws.com
            Action: sns:Publish
            Resource: !Ref NotificationsTopic
      Topics:
        - !Ref NotificationsTopic
  # This AutoScaling setup is only to cause creation of ECS Autoscaling Role
  AutoScalingTarget:
    Type: AWS::ApplicationAutoScaling::ScalableTarget
    Condition: IsECSDeploymentCreateAutoScalingRoleWithoutLb
    Properties:
      MinCapacity: 1
      MaxCapacity: 1
      ResourceId: !Join ["/", [service, !Ref Cluster, !GetAtt Service.Name]]
      RoleARN: !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService"
      ScalableDimension: ecs:service:DesiredCount
      ServiceNamespace: ecs
  AutoScalingTargetWithLb:
    Type: AWS::ApplicationAutoScaling::ScalableTarget
    Condition: IsECSDeploymentCreateAutoScalingRoleWithLb
    Properties:
      MinCapacity: 1
      MaxCapacity: 1
      ResourceId:
        !Join [
          "/",
          [service, !Ref Cluster, !If [CreateLB, !GetAtt ServiceWithLB.Name, !GetAtt ServiceWithExistingLB.Name]],
        ]
      RoleARN: !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService"
      ScalableDimension: ecs:service:DesiredCount
      ServiceNamespace: ecs
  DNSRecord:
    Type: AWS::Route53::RecordSet
    Condition: IsECSDeploymentUseHostedZoneName
    Properties:
      HostedZoneName: !Sub "${HostedZoneName}."
      Name: !Sub "${HostedSubdomain}.${HostedZoneName}."
      Type: A
      AliasTarget:
        DNSName: !GetAtt LoadBalancer.DNSName
        HostedZoneId: !GetAtt LoadBalancer.CanonicalHostedZoneID
  DNSRecordByZoneId:
    Type: AWS::Route53::RecordSet
    Condition: IsECSDeploymentUseHostedZoneId
    Properties:
      HostedZoneId: !Ref HostedZoneId
      Name: !Sub "${HostedSubdomain}.${HostedZoneName}."
      Type: A
      AliasTarget:
        DNSName: !GetAtt LoadBalancer.DNSName
        HostedZoneId: !GetAtt LoadBalancer.CanonicalHostedZoneID
  HealthCheckConsoleAlarm:
    Type: AWS::CloudWatch::Alarm
    Condition: IsECSDeploymentWithService
    DependsOn: ConsoleIAMPolicy
    Properties:
      AlarmName: !Sub "${TaskDefinitionPrefix}HealthCheck-Alarm-${AppConfigAgentApplication}"
      AlarmDescription: Alarm triggered if there is no data in the last 5 minutes
      ComparisonOperator: LessThanThreshold
      EvaluationPeriods: 1
      DatapointsToAlarm: 1
      Threshold: 3
      MetricName: ConsoleStatus
      Namespace: AWS/ECS
      Period: 300
      Statistic: Sum
      TreatMissingData: breaching
      Dimensions:
        - Name: ClusterName
          Value: !Ref Cluster
        - Name: ServiceName
          Value:
            !If [
              DontUseLB,
              !GetAtt Service.Name,
              !If [CreateLB, !GetAtt ServiceWithLB.Name, !GetAtt ServiceWithExistingLB.Name],
            ]
        - Name: Version
          Value: !FindInMap [Constants, Version, ImageVersionConsole]
      AlarmActions:
        - Ref: NotificationsTopic
      InsufficientDataActions:
        - Ref: NotificationsTopic
      OKActions:
        - Ref: NotificationsTopic
  HealthCheckConsoleAlarmSubscription:
    Type: AWS::SNS::Subscription
    Condition: IsECSDeploymentWithService
    DependsOn: ConsoleIAMPolicy
    Properties:
      Protocol: email-json
      Endpoint: !Ref Email
      TopicArn: !Ref NotificationsTopic
      FilterPolicyScope: MessageBody
      FilterPolicy:
        AlarmName:
          - !Ref HealthCheckConsoleAlarm
  ApplicationBucket:
    Type: "AWS::S3::Bucket"
    DependsOn: ConsoleIAMPolicy
    Properties:
      BucketName: !Sub "${ApplicationBucketNamePrefix}${AppConfigAgentApplication}"
      AccessControl: Private
      BucketEncryption: !If
        - HasCustomS3KmsKey
        - ServerSideEncryptionConfiguration:
            - ServerSideEncryptionByDefault:
                SSEAlgorithm: aws:kms
                KMSMasterKeyID: !Ref S3KmsKeyId
        - !Ref AWS::NoValue
    Metadata:
      cfn-lint:
        config:
          ignore_checks: [W3045]
  ApplicationBucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref ApplicationBucket
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Sid: AllowSSLRequestsOnly
            Action:
              - "s3:*"
            Effect: Deny
            Resource:
              - !GetAtt ApplicationBucket.Arn
              - !Sub "${ApplicationBucket.Arn}/*"
            Principal: "*"
            Condition:
              Bool:
                "aws:SecureTransport": "false"
Outputs:
  ConsoleWebAddress:
    Condition: DontUseLB
    Description: Public DNS address of Console Web Interface
    Value: !Sub "https://${SubdomainParameter.Value}.cloudstoragesecapp.com"
  LBWebAddress:
    Condition: IsECSDeploymentCreateLB
    Description: Public DNS address of Console Web Interface
    Value: !If [UseRoute53, !Sub "https://${HostedSubdomain}.${HostedZoneName}", !Sub "https://${LoadBalancer.DNSName}"]
  UserName:
    Description: User Name used to log in to console
    Value: !Ref UserName
  Password:
    Description: Temporary password used to log in to console
    Value: !Sub "Password was emailed to ${Email}"
  ProactiveNotificationsTopicArn:
    Description: ARN for the proactive notifications topic
    Value: !Ref NotificationsTopic
    Export:
      Name: !Sub "${AWS::StackName}-proactive-notifications-sns-topic"
  ApplicationId:
    Description: Unique Application ID of this installation
    Value: !Ref AppConfigAgentApplication
  SsmParametersPrefix:
    Description: Prefix used for created SSM Parameters
    Value: !Ref ParametersPrefix
  ConsoleTaskRoleArn:
    Description: ARN of the Console Task Role
    Value: !If [CreateConsoleRole, !GetAtt ConsoleTaskRole.Arn, !Ref ConsoleTaskRoleArn]
  AgentTaskRoleArn:
    Description: ARN of the Agent Task Role
    Value: !If [CreateAgentRole, !GetAtt AgentTaskRole.Arn, !Ref AgentTaskRoleArn]
  ConsoleImageTag:
    Description: Console image tag version
    Value: !FindInMap [Constants, Version, ImageVersionConsole]
