# This Cloudformation stack template was generated by
# https://github.com/caktus/aws-web-stacks
# at 2024-11-21 21:39:22.941186
# with parameters:
#	USE_EKS = on

Conditions:
  AssetsCloudFrontCertArnCondition: !Not
    - !Equals
      - !Ref 'AssetsCloudFrontCertArn'
      - ''
  AssetsCloudFrontDomainCondition: !Not
    - !Equals
      - !Ref 'AssetsCloudFrontDomain'
      - ''
  AssetsCreateCertificateCondition: !And
    - !Not
      - !Equals
        - !Ref 'AssetsCloudFrontDomain'
        - ''
    - !Equals
      - !Ref 'AWS::Region'
      - us-east-1
    - !Equals
      - !Ref 'AssetsCloudFrontCertArn'
      - ''
  AssetsUseCloudFrontCondition: !Equals
    - !Ref 'AssetsUseCloudFront'
    - 'true'
  AuthTokenCondition: !Not
    - !Equals
      - !Ref 'RedisAuthToken'
      - DO_NOT_CREATE_AUTH_TOKEN
  CmkArnCondition: !Not
    - !Equals
      - !Ref 'CustomerManagedCmkArn'
      - ''
  DatabaseCondition: !Not
    - !Equals
      - !Ref 'DatabaseClass'
      - (none)
  DatabaseLoggingCondition: !Not
    - !Equals
      - !Join
        - ','
        - !Ref 'DatabaseCloudWatchLogTypes'
      - ''
  DatabaseReplicationCondition: !And
    - !Condition 'DatabaseCondition'
    - !Equals
      - !Ref 'DatabaseReplication'
      - 'true'
  EitherCacheCondition: !Or
    - !Condition 'UsingMemcached'
    - !Condition 'UsingRedis'
  Elasticsearch: !Not
    - !Equals
      - !Ref 'ElasticsearchInstanceType'
      - (none)
  EnableEksEncryptionConfigCond: !And
    - !Equals
      - !Ref 'EnableEksEncryptionConfig'
      - 'true'
    - !Not
      - !Equals
        - !Ref 'CustomerManagedCmkArn'
        - ''
  InGovCloudRegion: !Equals
    - !Ref 'AWS::Region'
    - us-gov-west-1
  NoAlternateDomains: !Equals
    - !Join
      - ''
      - !Ref 'DomainNameAlternates'
    - ''
  RedisAutomaticFailoverCondition: !Equals
    - !Ref 'RedisAutomaticFailover'
    - 'true'
  RestrictEksApiAccessCond: !Not
    - !Equals
      - !Join
        - ''
        - !Ref 'EksPublicAccessCidrs'
      - ''
  SecureRedisCondition: !And
    - !Condition 'UsingRedis'
    - !Condition 'UseAES256EncryptionCond'
  UseAES256EncryptionCond: !Equals
    - !Ref 'UseAES256Encryption'
    - 'true'
  UseSFTPServerCondition: !Equals
    - !Ref 'UseSFTPServer'
    - 'true'
  UseSFTPWithKMSCondition: !And
    - !Equals
      - !Ref 'UseSFTPServer'
      - 'true'
    - !Condition 'UseAES256EncryptionCond'
    - !Condition 'CmkArnCondition'
  UseSFTPWithoutKMSCondition: !And
    - !Equals
      - !Ref 'UseSFTPServer'
      - 'true'
    - !Not
      - !Condition 'CmkArnCondition'
  UsingMemcached: !Not
    - !Equals
      - !Ref 'CacheNodeType'
      - (none)
  UsingRedis: !Not
    - !Equals
      - !Ref 'RedisNodeType'
      - (none)
Mappings:
  RdsEngineMap:
    aurora:
      Port: '3306'
    mariadb:
      Port: '3306'
    mysql:
      Port: '3306'
    oracle-ee:
      Port: '1521'
    oracle-se:
      Port: '1521'
    oracle-se1:
      Port: '1521'
    oracle-se2:
      Port: '1521'
    postgres:
      Port: '5432'
    sqlserver-ee:
      Port: '1433'
    sqlserver-ex:
      Port: '1433'
    sqlserver-se:
      Port: '1433'
    sqlserver-web:
      Port: '1433'
Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: Global
        Parameters:
          - UseAES256Encryption
          - CustomerManagedCmkArn
          - DomainName
          - DomainNameAlternates
          - PrimaryAZ
          - SecondaryAZ
          - VpcCidr
          - PublicSubnetACidr
          - PublicSubnetBCidr
          - PrivateSubnetACidr
          - PrivateSubnetBCidr
      - Label:
          default: Application Server
        Parameters:
          - AdministratorIPAddress
          - DesiredScale
          - MaxScale
          - ContainerVolumeSize
          - ContainerInstanceType
      - Label:
          default: Static Media
        Parameters:
          - AssetsBucketAccessControl
          - AssetsUseCloudFront
          - AssetsCloudFrontDomain
          - AssetsCloudFrontCertArn
      - Label:
          default: Database
        Parameters:
          - DatabaseClass
          - DatabaseReplication
          - DatabaseEngine
          - DatabaseEngineVersion
          - DatabaseParameterGroupFamily
          - DatabaseName
          - DatabaseUser
          - DatabasePassword
          - DatabaseAllocatedStorage
          - DatabaseMultiAZ
          - DatabaseBackupRetentionDays
          - DatabaseCloudWatchLogTypes
      - Label:
          default: Elasticsearch
        Parameters:
          - ElasticsearchInstanceType
          - ElasticsearchVersion
          - ElasticsearchVolumeSize
      - Label:
          default: SFTP
        Parameters:
          - UseSFTPServer
      - Label:
          default: Memcached
        Parameters:
          - CacheNodeType
      - Label:
          default: Redis
        Parameters:
          - RedisNodeType
          - RedisAuthToken
          - RedisVersion
          - RedisNumCacheClusters
          - RedisSnapshotRetentionLimit
          - RedisAutomaticFailover
      - Label:
          default: Elastic Kubernetes Service (EKS)
        Parameters:
          - EnableEksEncryptionConfig
          - EksPublicAccessCidrs
          - EksClusterName
    ParameterLabels:
      AdministratorIPAddress:
        default: Admin IP Address
      AssetsBucketAccessControl:
        default: Assets Bucket ACL
      AssetsCloudFrontCertArn:
        default: CloudFront SSL Certificate ARN
      AssetsCloudFrontDomain:
        default: CloudFront Custom Domain
      AssetsUseCloudFront:
        default: Enable CloudFront
      CacheNodeType:
        default: Instance Type
      ContainerInstanceType:
        default: Instance Type
      ContainerVolumeSize:
        default: Root Volume Size
      CustomerManagedCmkArn:
        default: Customer managed key ARN
      DatabaseAllocatedStorage:
        default: Storage (GB)
      DatabaseBackupRetentionDays:
        default: Backup Retention Days
      DatabaseClass:
        default: Instance Type
      DatabaseCloudWatchLogTypes:
        default: Database Log Types
      DatabaseEngine:
        default: Engine
      DatabaseEngineVersion:
        default: Engine Version
      DatabaseMultiAZ:
        default: Enable MultiAZ
      DatabaseName:
        default: Database Name
      DatabaseParameterGroupFamily:
        default: Parameter Group Family
      DatabasePassword:
        default: Password
      DatabaseReplication:
        default: Database replication
      DatabaseUser:
        default: Username
      DesiredScale:
        default: Desired Instance Count
      DomainName:
        default: Domain Name
      DomainNameAlternates:
        default: Alternate Domain Names
      EksClusterName:
        default: Cluster name
      EksPublicAccessCidrs:
        default: Kubernetes API public access CIDRs
      ElasticsearchInstanceType:
        default: Instance Type
      ElasticsearchVersion:
        default: Version
      ElasticsearchVolumeSize:
        default: Storage (GB)
      EnableEksEncryptionConfig:
        default: Enable EKS EncryptionConfig
      MaxScale:
        default: Maximum Instance Count
      PrimaryAZ:
        default: Primary Availability Zone
      PrivateSubnetACidr:
        default: Private Subnet A CIDR Block
      PrivateSubnetBCidr:
        default: Private Subnet B CIDR Block
      PublicSubnetACidr:
        default: Public Subnet A CIDR Block
      PublicSubnetBCidr:
        default: Public Subnet B CIDR Block
      RedisAuthToken:
        default: AuthToken
      RedisAutomaticFailover:
        default: Enable automatic failover
      RedisNodeType:
        default: Instance Type
      RedisNumCacheClusters:
        default: Number of node groups
      RedisSnapshotRetentionLimit:
        default: Snapshow retention limit
      RedisVersion:
        default: Redis Version
      SecondaryAZ:
        default: Secondary Availability Zone
      UseAES256Encryption:
        default: Enable Encryption
      UseSFTPServer:
        default: Enable SFTP Server
      VpcCidr:
        default: VPC IPv4 CIDR Block
Outputs:
  AssetsBucketDomainName:
    Description: Assets bucket domain name
    Value: !GetAtt 'AssetsBucket.DomainName'
  AssetsDistributionDomainName:
    Condition: AssetsUseCloudFrontCondition
    Description: The assets CDN domain name
    Value: !GetAtt 'AssetsDistribution.DomainName'
  CacheAddress:
    Condition: UsingMemcached
    Description: The DNS address for the cache node/cluster.
    Value: !If
      - UsingMemcached
      - !GetAtt 'CacheCluster.ConfigurationEndpoint.Address'
      - ''
  CachePort:
    Condition: UsingMemcached
    Description: The port number for the cache node/cluster.
    Value: !GetAtt 'CacheCluster.ConfigurationEndpoint.Port'
  CacheURL:
    Condition: UsingMemcached
    Description: URL to connect to the cache node/cluster.
    Value: !If
      - UsingMemcached
      - !Join
        - ''
        - - memcached://
          - !If
            - UsingMemcached
            - !GetAtt 'CacheCluster.ConfigurationEndpoint.Address'
            - ''
          - ':'
          - !If
            - UsingMemcached
            - !GetAtt 'CacheCluster.ConfigurationEndpoint.Port'
            - ''
      - ''
  ClusterEndpoint:
    Description: The connection endpoint for the EKS cluster API.
    Value: !GetAtt 'EksCluster.Endpoint'
  DatabaseAddress:
    Condition: DatabaseCondition
    Description: The connection endpoint for the database.
    Value: !GetAtt 'DatabaseInstance.Endpoint.Address'
  DatabasePort:
    Condition: DatabaseCondition
    Description: The port number on which the database accepts connections.
    Value: !GetAtt 'DatabaseInstance.Endpoint.Port'
  DatabaseReplicaAddress:
    Condition: DatabaseReplicationCondition
    Description: The connection endpoint for the database replica.
    Value: !GetAtt 'DatabaseReplica.Endpoint.Address'
  DatabaseReplicaURL:
    Condition: DatabaseReplicationCondition
    Description: URL to connect (without the password) to the database replica.
    Value: !If
      - DatabaseReplicationCondition
      - !Join
        - ''
        - - !Ref 'DatabaseEngine'
          - ://
          - !Ref 'DatabaseUser'
          - :_PASSWORD_@
          - !GetAtt 'DatabaseReplica.Endpoint.Address'
          - ':'
          - !GetAtt 'DatabaseReplica.Endpoint.Port'
          - /
          - !Ref 'DatabaseName'
      - ''
  DatabaseURL:
    Condition: DatabaseCondition
    Description: URL to connect (without the password) to the database.
    Value: !If
      - DatabaseCondition
      - !Join
        - ''
        - - !Ref 'DatabaseEngine'
          - ://
          - !Ref 'DatabaseUser'
          - :_PASSWORD_@
          - !GetAtt 'DatabaseInstance.Endpoint.Address'
          - ':'
          - !GetAtt 'DatabaseInstance.Endpoint.Port'
          - /
          - !Ref 'DatabaseName'
      - ''
  ElasticsearchDomainArn:
    Condition: Elasticsearch
    Description: Elasticsearch domain ARN
    Value: !GetAtt 'ElasticsearchDomain.DomainArn'
  ElasticsearchDomainEndpoint:
    Condition: Elasticsearch
    Description: Elasticsearch domain endpoint
    Value: !GetAtt 'ElasticsearchDomain.DomainEndpoint'
  PrivateAssetsBucketDomainName:
    Description: Private assets bucket domain name
    Value: !GetAtt 'PrivateAssetsBucket.DomainName'
  RedisAddress:
    Condition: UsingRedis
    Description: The DNS address for the Redis node/cluster.
    Value: !If
      - UsingRedis
      - !GetAtt 'RedisReplicationGroup.PrimaryEndPoint.Address'
      - ''
  RedisPort:
    Condition: UsingRedis
    Description: The port number for the Redis node/cluster.
    Value: !If
      - UsingRedis
      - !GetAtt 'RedisReplicationGroup.PrimaryEndPoint.Port'
      - ''
  RedisURL:
    Condition: UsingRedis
    Description: URL to connect to the Redis node/cluster.
    Value: !If
      - UsingRedis
      - !Join
        - ''
        - - redis
          - !If
            - SecureRedisCondition
            - s
            - ''
          - ://
          - !If
            - AuthTokenCondition
            - :_PASSWORD_@
            - ''
          - !If
            - UsingRedis
            - !GetAtt 'RedisReplicationGroup.PrimaryEndPoint.Address'
            - ''
          - ':'
          - !If
            - UsingRedis
            - !GetAtt 'RedisReplicationGroup.PrimaryEndPoint.Port'
            - ''
      - ''
  RepositoryURL:
    Description: The docker repository URL
    Value: !Join
      - ''
      - - !Ref 'AWS::AccountId'
        - .dkr.ecr.
        - !Ref 'AWS::Region'
        - .amazonaws.com/
        - !Ref 'ApplicationRepository'
  SFTPBucketDomainName:
    Condition: UseSFTPServerCondition
    Description: SFTP bucket domain name
    Value: !GetAtt 'SFTPAssetsBucket.DomainName'
Parameters:
  AdministratorIPAddress:
    Default: 192.0.2.0/24
    Description: The IP address allowed to access containers. Defaults to TEST-NET-1 (ie, no valid IP)
    Type: String
  AssetsBucketAccessControl:
    AllowedValues:
      - PublicRead
      - Private
    ConstraintDescription: Must be PublicRead or Private.
    Default: PublicRead
    Description: Canned ACL for the public S3 bucket. Private is recommended; it allows for objects to be make publicly readable, but prevents listing of the bucket contents.
    Type: String
  AssetsCloudFrontCertArn:
    Default: ''
    Description: >-
      If (1) you specified a custom static media domain, (2) your stack is NOT in the us-east-1 region, and (3) you wish to serve static media over HTTPS, you must manually create an ACM certificate in
      the us-east-1 region and provide its ARN here.
    Type: String
  AssetsCloudFrontDomain:
    Default: ''
    Description: A custom domain name (CNAME) for your CloudFront distribution, e.g., "static.example.com" (optional).
    Type: String
  AssetsUseCloudFront:
    AllowedValues:
      - 'true'
      - 'false'
    Default: 'true'
    Description: Whether or not to create a CloudFront distribution tied to the S3 assets bucket.
    Type: String
  CacheNodeType:
    AllowedValues:
      - (none)
      - cache.t2.micro
      - cache.t2.small
      - cache.t2.medium
      - cache.t3.micro
      - cache.t3.small
      - cache.t3.medium
      - cache.m3.medium
      - cache.m3.large
      - cache.m3.xlarge
      - cache.m3.2xlarge
      - cache.m4.large
      - cache.m4.xlarge
      - cache.m4.2xlarge
      - cache.m4.4xlarge
      - cache.m4.10xlarge
      - cache.r4.large
      - cache.r4.xlarge
      - cache.r4.2xlarge
      - cache.r4.4xlarge
      - cache.r4.8xlarge
      - cache.r4.16xlarge
      - cache.r3.large
      - cache.r3.xlarge
      - cache.r3.2xlarge
      - cache.r3.4xlarge
      - cache.r3.8xlarge
    ConstraintDescription: must select a valid cache node type.
    Default: (none)
    Description: Cache instance type
    Type: String
  ContainerInstanceType:
    AllowedValues:
      - t3a.nano
      - t3a.micro
      - t3a.small
      - t3a.medium
      - t3a.large
      - t3a.xlarge
      - t3a.2xlarge
      - t3.nano
      - t3.micro
      - t3.small
      - t3.medium
      - t3.large
      - t3.xlarge
      - t3.2xlarge
      - t2.nano
      - t2.micro
      - t2.small
      - t2.medium
      - t2.large
      - t2.xlarge
      - t2.2xlarge
      - m5.large
      - m5.xlarge
      - m5.2xlarge
      - m5.4xlarge
      - m5.12xlarge
      - m5.24xlarge
      - m5d.large
      - m5d.xlarge
      - m5d.2xlarge
      - m5d.4xlarge
      - m5d.12xlarge
      - m5d.24xlarge
      - m4.large
      - m4.xlarge
      - m4.2xlarge
      - m4.4xlarge
      - m4.10xlarge
      - m4.16xlarge
      - m3.medium
      - m3.large
      - m3.xlarge
      - m3.2xlarge
      - c5.large
      - c5.xlarge
      - c5.2xlarge
      - c5.4xlarge
      - c5.9xlarge
      - c5.18xlarge
      - c5d.large
      - c5d.xlarge
      - c5d.2xlarge
      - c5d.4xlarge
      - c5d.9xlarge
      - c5d.18xlarge
      - c4.large
      - c4.xlarge
      - c4.2xlarge
      - c4.4xlarge
      - c4.8xlarge
      - c3.large
      - c3.xlarge
      - c3.2xlarge
      - c3.4xlarge
      - c3.8xlarge
      - p2.xlarge
      - p2.8xlarge
      - p2.16xlarge
      - g2.2xlarge
      - g2.8xlarge
      - x1.16large
      - x1.32xlarge
      - r5.large
      - r5.xlarge
      - r5.2xlarge
      - r5.4xlarge
      - r5.12xlarge
      - r5.24xlarge
      - r4.large
      - r4.xlarge
      - r4.2xlarge
      - r4.4xlarge
      - r4.8xlarge
      - r4.16xlarge
      - r3.large
      - r3.xlarge
      - r3.2xlarge
      - r3.4xlarge
      - r3.8xlarge
      - i3.large
      - i3.xlarge
      - i3.2xlarge
      - i3.4xlarge
      - i3.8xlarge
      - i3.16large
      - d2.xlarge
      - d2.2xlarge
      - d2.4xlarge
      - d2.8xlarge
      - f1.2xlarge
      - f1.16xlarge
    Default: t3a.micro
    Description: The application server instance type
    Type: String
  ContainerVolumeSize:
    Default: '20'
    Description: Size of instance EBS root volume (in GB)
    Type: Number
  CustomerManagedCmkArn:
    Default: ''
    Description: KMS CMK ARN to encrypt stack resources (except for public buckets).
    Type: String
  DatabaseAllocatedStorage:
    ConstraintDescription: must be between 5 and 1024Gb.
    Default: '20'
    Description: The size of the database (Gb)
    MaxValue: '1024'
    MinValue: '5'
    Type: Number
  DatabaseBackupRetentionDays:
    AllowedValues:
      - '0'
      - '1'
      - '2'
      - '3'
      - '4'
      - '5'
      - '6'
      - '7'
      - '8'
      - '9'
      - '10'
      - '11'
      - '12'
      - '13'
      - '14'
      - '15'
      - '16'
      - '17'
      - '18'
      - '19'
      - '20'
      - '21'
      - '22'
      - '23'
      - '24'
      - '25'
      - '26'
      - '27'
      - '28'
      - '29'
      - '30'
      - '31'
      - '32'
      - '33'
      - '34'
      - '35'
    Default: '30'
    Description: The number of days for which automated backups are retained. Setting to 0 disables automated backups.
    Type: Number
  DatabaseClass:
    AllowedValues:
      - (none)
      - db.r3.large
      - db.r3.xlarge
      - db.r3.2xlarge
      - db.r3.4xlarge
      - db.r3.8xlarge
      - db.r4.large
      - db.r4.xlarge
      - db.r4.2xlarge
      - db.r4.4xlarge
      - db.r4.8xlarge
      - db.r4.16xlarge
      - db.r5.large
      - db.r5.xlarge
      - db.r5.2xlarge
      - db.r5.4xlarge
      - db.r5.8xlarge
      - db.r5.12xlarge
      - db.r5.16xlarge
      - db.r5.24xlarge
      - db.t2.micro
      - db.t2.small
      - db.t2.medium
      - db.t2.large
      - db.t4g.micro
      - db.t4g.small
      - db.t4g.medium
      - db.t4g.large
      - db.t4g.xlarge
      - db.t4g.2xlarge
      - db.t3.micro
      - db.t3.small
      - db.t3.medium
      - db.t3.large
      - db.t3.xlarge
      - db.t3.2xlarge
      - db.m1.small
      - db.m1.medium
      - db.m1.large
      - db.m1.xlarge
      - db.m2.xlarge
      - db.m2.2xlarge
      - db.m2.4xlarge
      - db.m3.medium
      - db.m3.large
      - db.m3.xlarge
      - db.m3.2xlarge
      - db.m4.large
      - db.m4.xlarge
      - db.m4.2xlarge
      - db.m4.4xlarge
      - db.m4.10xlarge
      - db.m4.16xlarge
      - db.m5.large
      - db.m5.xlarge
      - db.m5.2xlarge
      - db.m5.4xlarge
      - db.m5.8xlarge
      - db.m5.12xlarge
      - db.m5.16xlarge
      - db.m5.24xlarge
    ConstraintDescription: must select a valid database instance type.
    Default: db.t3.micro
    Description: Database instance class
    Type: String
  DatabaseCloudWatchLogTypes:
    Default: ''
    Description: A comma-separated list of the RDS log types (if any) to publish to CloudWatch Logs. Note that log types are database engine-specific.
    Type: CommaDelimitedList
  DatabaseEngine:
    AllowedValues:
      - aurora
      - mariadb
      - mysql
      - oracle-ee
      - oracle-se2
      - oracle-se1
      - oracle-se
      - postgres
      - sqlserver-ee
      - sqlserver-se
      - sqlserver-ex
      - sqlserver-web
    ConstraintDescription: must select a valid database engine.
    Default: postgres
    Description: Database engine to use
    Type: String
  DatabaseEngineVersion:
    Default: ''
    Description: Database version to use
    Type: String
  DatabaseMultiAZ:
    AllowedValues:
      - 'true'
      - 'false'
    ConstraintDescription: must choose true or false.
    Default: 'false'
    Description: Whether or not to create a MultiAZ database
    Type: String
  DatabaseName:
    AllowedPattern: '[a-zA-Z][a-zA-Z0-9_]*'
    ConstraintDescription: must begin with a letter and contain only alphanumeric characters.
    Default: app
    Description: Name of the database to create in the database server
    MaxLength: '64'
    MinLength: '1'
    Type: String
  DatabaseParameterGroupFamily:
    AllowedValues:
      - aurora-mysql5.7
      - docdb3.6
      - neptune1
      - aurora-postgresql9.6
      - aurora-postgresql10
      - mariadb10.0
      - mariadb10.1
      - mariadb10.2
      - mariadb10.3
      - mysql5.5
      - mysql5.6
      - mysql5.7
      - mysql8.0
      - oracle-ee-11.2
      - oracle-ee-12.1
      - oracle-ee-12.2
      - oracle-se-11.2
      - oracle-se1-11.2
      - oracle-se2-12.1
      - oracle-se2-12.2
      - aurora5.6
      - postgres10
      - postgres11
      - postgres12
      - postgres13
      - postgres14
      - sqlserver-ee-11.0
      - sqlserver-ee-12.0
      - sqlserver-ee-13.0
      - sqlserver-ee-14.0
      - sqlserver-ex-11.0
      - sqlserver-ex-12.0
      - sqlserver-ex-13.0
      - sqlserver-ex-14.0
      - sqlserver-se-11.0
      - sqlserver-se-12.0
      - sqlserver-se-13.0
      - sqlserver-se-14.0
      - sqlserver-web-11.0
      - sqlserver-web-12.0
      - sqlserver-web-13.0
      - sqlserver-web-14.0
    Description: Database parameter group family name; must match the engine and version of the RDS instance.
    Type: String
  DatabasePassword:
    AllowedPattern: '[ !#-.0-?A-~]*'
    ConstraintDescription: must consist of 10-41 printable ASCII characters except "/", """, or "@".
    Description: The database admin account password must consist of 10-41 printableASCII characters *except* "/", """, or "@".
    MaxLength: '41'
    MinLength: '10'
    NoEcho: true
    Type: String
  DatabaseReplication:
    AllowedValues:
      - 'true'
      - 'false'
    Default: 'false'
    Description: Whether to create a database server replica - WARNING this will fail if DatabaseBackupRetentionDays is 0.
    Type: String
  DatabaseUser:
    AllowedPattern: '[a-zA-Z][a-zA-Z0-9_]*'
    ConstraintDescription: must begin with a letter and contain only alphanumeric characters and underscores.
    Default: app
    Description: The database admin account username
    MaxLength: '63'
    MinLength: '1'
    Type: String
  DesiredScale:
    Default: '2'
    Description: Desired container instances count
    Type: Number
  DomainName:
    Description: The fully-qualified domain name for the application.
    Type: String
  DomainNameAlternates:
    Description: A comma-separated list of Alternate FQDNs to be included in the Subject Alternative Name extension of the SSL certificate.
    Type: CommaDelimitedList
  EksClusterName:
    Description: The unique name to give to your cluster.
    Type: String
  EksPublicAccessCidrs:
    Default: ''
    Description: The CIDR blocks that are allowed access to your cluster's public Kubernetes API server endpoint.
    Type: CommaDelimitedList
  ElasticsearchInstanceType:
    AllowedValues:
      - (none)
      - t2.micro.elasticsearch
      - t2.small.elasticsearch
      - t2.medium.elasticsearch
      - m3.medium.elasticsearch
      - m3.large.elasticsearch
      - m3.xlarge.elasticsearch
      - m3.2xlarge.elasticsearch
      - m4.large.elasticsearch
      - m4.xlarge.elasticsearch
      - m4.2xlarge.elasticsearch
      - m4.4xlarge.elasticsearch
      - m4.10xlarge.elasticsearch
      - c4.large.elasticsearch
      - c4.xlarge.elasticsearch
      - c4.2xlarge.elasticsearch
      - c4.4xlarge.elasticsearch
      - c4.8xlarge.elasticsearch
      - r3.large.elasticsearch
      - r3.xlarge.elasticsearch
      - r3.2xlarge.elasticsearch
      - r3.4xlarge.elasticsearch
      - r3.8xlarge.elasticsearch
      - r4.large.elasticsearch
      - r4.xlarge.elasticsearch
      - r4.2xlarge.elasticsearch
      - r4.4xlarge.elasticsearch
      - r4.8xlarge.elasticsearch
      - r4.16xlarge.elasticsearch
      - i2.xlarge.elasticsearch
      - i2.2xlarge.elasticsearch
    ConstraintDescription: must select a valid Elasticsearch instance type.
    Default: (none)
    Description: 'Elasticsearch instance type. Note: not all types are supported in all regions; see: http://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/aes-supported-instance-types.html'
    Type: String
  ElasticsearchVersion:
    AllowedValues:
      - '1.5'
      - '2.3'
      - '5.1'
      - '5.3'
    ConstraintDescription: must select a valid Elasticsearch version.
    Default: '2.3'
    Description: 'Elasticsearch version. Note: t2.micro.elasticsearch instances support only versions 2.3 and 1.5.'
    Type: String
  ElasticsearchVolumeSize:
    Default: '10'
    Description: 'Elasticsearch EBS volume size, in GB. Note: maximum volume size varies by instance type; see: http://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/aes-limits.html#ebsresource.'
    MaxValue: '1536'
    MinValue: '10'
    Type: Number
  EnableEksEncryptionConfig:
    AllowedValues:
      - 'true'
      - 'false'
    Default: 'false'
    Description: Use AWS Key Management Service (KMS) keys to provide envelope encryption of Kubernetes secrets. Depends on Customer managed key ARN.
    Type: String
  MaxScale:
    Default: '4'
    Description: Maximum container instances count
    Type: Number
  PrimaryAZ:
    Description: The primary availability zone for creating resources.
    Type: AWS::EC2::AvailabilityZone::Name
  PrivateSubnetACidr:
    AllowedPattern: >-
      ^((10\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.)|(172\.(1[6-9]|2[0-9]|3[0-1])\.)|192\.168\.)(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.)([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$
    ConstraintDescription: Must be a private IPv4 range with size /16 and /28.
    Default: 10.0.8.0/22
    Description: IPv4 CIDR block for the private subnet in the primary AZ. [Possibly not modifiable after stack creation]
    Type: String
  PrivateSubnetBCidr:
    AllowedPattern: >-
      ^((10\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.)|(172\.(1[6-9]|2[0-9]|3[0-1])\.)|192\.168\.)(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.)([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$
    ConstraintDescription: Must be a private IPv4 range with size /16 and /28.
    Default: 10.0.12.0/22
    Description: IPv4 CIDR block for the private subnet in the secondary AZ. [Possibly not modifiable after stack creation]
    Type: String
  PublicSubnetACidr:
    AllowedPattern: >-
      ^((10\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.)|(172\.(1[6-9]|2[0-9]|3[0-1])\.)|192\.168\.)(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.)([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$
    ConstraintDescription: Must be a private IPv4 range with size /16 and /28.
    Default: 10.0.0.0/22
    Description: IPv4 CIDR block for the public subnet in the primary AZ. [Possibly not modifiable after stack creation]
    Type: String
  PublicSubnetBCidr:
    AllowedPattern: >-
      ^((10\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.)|(172\.(1[6-9]|2[0-9]|3[0-1])\.)|192\.168\.)(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.)([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$
    ConstraintDescription: Must be a private IPv4 range with size /16 and /28.
    Default: 10.0.4.0/22
    Description: IPv4 CIDR block for the public subnet in the secondary AZ. [Possibly not modifiable after stack creation]
    Type: String
  RedisAuthToken:
    AllowedPattern: '[ !#-.0-?A-~]*'
    ConstraintDescription: must consist of 16-128 printable ASCII characters except "/", """, or "@".
    Default: DO_NOT_CREATE_AUTH_TOKEN
    Description: The password used to access a Redis ReplicationGroup (required for HIPAA).
    MaxLength: '128'
    MinLength: '16'
    NoEcho: true
    Type: String
  RedisAutomaticFailover:
    AllowedValues:
      - 'true'
      - 'false'
    Default: 'false'
    Description: Specifies whether a read-only replica is automatically promoted to read/write primary if the existing primary fails.
    Type: String
  RedisNodeType:
    AllowedValues:
      - (none)
      - cache.t2.micro
      - cache.t2.small
      - cache.t2.medium
      - cache.t3.micro
      - cache.t3.small
      - cache.t3.medium
      - cache.m3.medium
      - cache.m3.large
      - cache.m3.xlarge
      - cache.m3.2xlarge
      - cache.m4.large
      - cache.m4.xlarge
      - cache.m4.2xlarge
      - cache.m4.4xlarge
      - cache.m4.10xlarge
      - cache.r4.large
      - cache.r4.xlarge
      - cache.r4.2xlarge
      - cache.r4.4xlarge
      - cache.r4.8xlarge
      - cache.r4.16xlarge
      - cache.r3.large
      - cache.r3.xlarge
      - cache.r3.2xlarge
      - cache.r3.4xlarge
      - cache.r3.8xlarge
    ConstraintDescription: must select a valid cache node type.
    Default: (none)
    Description: Redis instance type
    Type: String
  RedisNumCacheClusters:
    Default: '1'
    Description: The number of clusters this replication group initially has.
    Type: Number
  RedisSnapshotRetentionLimit:
    Default: '0'
    Description: >-
      The number of days for which ElastiCache retains automatic snapshots before deleting them.For example, if you set SnapshotRetentionLimit to 5, a snapshot that was taken today is retained for 5 days
      before being deleted. 0 = automatic backups are disabled for this cluster.
    Type: Number
  RedisVersion:
    Default: ''
    Description: 'Redis version to use. See available versions: aws elasticache describe-cache-engine-versions'
    Type: String
  SecondaryAZ:
    Description: The secondary availability zone for creating resources. Must differ from primary zone.
    Type: AWS::EC2::AvailabilityZone::Name
  UseAES256Encryption:
    AllowedValues:
      - 'true'
      - 'false'
    Default: 'false'
    Description: Whether or not to use server side encryption for S3, EBS, and RDS. When true, encryption is enabled for all resources.
    Type: String
  UseSFTPServer:
    AllowedValues:
      - 'true'
      - 'false'
    Default: 'false'
    Description: Whether or not to set up an SFTP service.  If 'true', this will set up a transfer server and add an S3 bucket for its use, along with a role and policies for use when adding users.
    Type: String
  VpcCidr:
    AllowedPattern: >-
      ^((10\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.)|(172\.(1[6-9]|2[0-9]|3[0-1])\.)|192\.168\.)(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.)([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$
    ConstraintDescription: Must be a private IPv4 range with size /16 and /28.
    Default: 10.0.0.0/20
    Description: The primary IPv4 CIDR block for the VPC. [Possibly not modifiable after stack creation]
    Type: String
Resources:
  ApplicationRepository:
    Properties:
      ImageScanningConfiguration:
        ScanOnPush: true
      RepositoryPolicyText:
        Statement:
          - Action:
              - ecr:GetDownloadUrlForLayer
              - ecr:BatchGetImage
              - ecr:BatchCheckLayerAvailability
              - ecr:PutImage
              - ecr:InitiateLayerUpload
              - ecr:UploadLayerPart
              - ecr:CompleteLayerUpload
            Effect: Allow
            Principal:
              AWS:
                - !Join
                  - ''
                  - - !If
                      - InGovCloudRegion
                      - arn:aws-us-gov
                      - arn:aws
                    - ':iam::'
                    - !Ref 'AWS::AccountId'
                    - :root
            Sid: AllowPushPull
        Version: '2008-10-17'
      Tags:
        - Key: aws-web-stacks:stack-name
          Value: !Ref 'AWS::StackName'
    Type: AWS::ECR::Repository
  AssetsBucket:
    DeletionPolicy: Retain
    Properties:
      AccessControl: !Ref 'AssetsBucketAccessControl'
      BucketEncryption: !If
        - UseAES256EncryptionCond
        - ServerSideEncryptionConfiguration:
            - ServerSideEncryptionByDefault:
                SSEAlgorithm: AES256
        - !Ref 'AWS::NoValue'
      CorsConfiguration:
        CorsRules:
          - AllowedHeaders:
              - '*'
            AllowedMethods:
              - POST
              - PUT
              - HEAD
              - GET
            AllowedOrigins: !Split
              - ;
              - !Join
                - ''
                - - https://
                  - !Join
                    - ;https://
                    - !Split
                      - ;
                      - !Join
                        - ''
                        - - !Ref 'DomainName'
                          - !If
                            - NoAlternateDomains
                            - ''
                            - ;
                          - !Join
                            - ;
                            - !Ref 'DomainNameAlternates'
      Tags:
        - Key: aws-web-stacks:stack-name
          Value: !Ref 'AWS::StackName'
      VersioningConfiguration:
        Status: Enabled
    Type: AWS::S3::Bucket
  AssetsCertificate:
    Condition: AssetsCreateCertificateCondition
    Properties:
      DomainName: !Ref 'AssetsCloudFrontDomain'
      DomainValidationOptions:
        - DomainName: !Ref 'AssetsCloudFrontDomain'
          ValidationDomain: !Ref 'AssetsCloudFrontDomain'
      Tags:
        - Key: aws-web-stacks:stack-name
          Value: !Ref 'AWS::StackName'
    Type: AWS::CertificateManager::Certificate
  AssetsDistribution:
    Condition: AssetsUseCloudFrontCondition
    Properties:
      DistributionConfig:
        Aliases: !If
          - AssetsCloudFrontDomainCondition
          - - !Ref 'AssetsCloudFrontDomain'
          - !Ref 'AWS::NoValue'
        DefaultCacheBehavior:
          ForwardedValues:
            Headers:
              - Origin
              - Access-Control-Request-Headers
              - Access-Control-Request-Method
            QueryString: true
          TargetOriginId: Assets
          ViewerProtocolPolicy: allow-all
        Enabled: true
        Origins:
          - DomainName: !GetAtt 'AssetsBucket.DomainName'
            Id: Assets
            S3OriginConfig:
              OriginAccessIdentity: ''
        ViewerCertificate: !If
          - AssetsCreateCertificateCondition
          - AcmCertificateArn: !Ref 'AssetsCertificate'
            SslSupportMethod: sni-only
          - !If
            - AssetsCloudFrontCertArnCondition
            - AcmCertificateArn: !Ref 'AssetsCloudFrontCertArn'
              SslSupportMethod: sni-only
            - !Ref 'AWS::NoValue'
      Tags:
        - Key: aws-web-stacks:stack-name
          Value: !Ref 'AWS::StackName'
    Type: AWS::CloudFront::Distribution
  CacheCluster:
    Condition: UsingMemcached
    Properties:
      CacheNodeType: !Ref 'CacheNodeType'
      CacheSubnetGroupName: !Ref 'CacheSubnetGroup'
      Engine: memcached
      NumCacheNodes: 1
      Port: 11211
      Tags:
        - Key: aws-web-stacks:stack-name
          Value: !Ref 'AWS::StackName'
        - Key: Name
          Value: !Join
            - '-'
            - - !Ref 'AWS::StackName'
              - cache
      VpcSecurityGroupIds:
        - !Ref 'CacheSecurityGroup'
    Type: AWS::ElastiCache::CacheCluster
  CacheSecurityGroup:
    Condition: EitherCacheCondition
    Properties:
      GroupDescription: Cache security group.
      SecurityGroupIngress:
        - !If
          - UsingMemcached
          - CidrIp: !Ref 'PrivateSubnetACidr'
            FromPort: 11211
            IpProtocol: tcp
            ToPort: 11211
          - !Ref 'AWS::NoValue'
        - !If
          - UsingMemcached
          - CidrIp: !Ref 'PrivateSubnetBCidr'
            FromPort: 11211
            IpProtocol: tcp
            ToPort: 11211
          - !Ref 'AWS::NoValue'
        - !If
          - UsingRedis
          - CidrIp: !Ref 'PrivateSubnetACidr'
            FromPort: 6379
            IpProtocol: tcp
            ToPort: 6379
          - !Ref 'AWS::NoValue'
        - !If
          - UsingRedis
          - CidrIp: !Ref 'PrivateSubnetBCidr'
            FromPort: 6379
            IpProtocol: tcp
            ToPort: 6379
          - !Ref 'AWS::NoValue'
      Tags:
        - Key: aws-web-stacks:stack-name
          Value: !Ref 'AWS::StackName'
        - Key: Name
          Value: !Join
            - '-'
            - - !Ref 'AWS::StackName'
              - cache
      VpcId: !Ref 'Vpc'
    Type: AWS::EC2::SecurityGroup
  CacheSubnetGroup:
    Condition: EitherCacheCondition
    Properties:
      Description: Subnets available for the cache instance
      SubnetIds:
        - !Ref 'PrivateSubnetA'
        - !Ref 'PrivateSubnetB'
      Tags:
        - Key: aws-web-stacks:stack-name
          Value: !Ref 'AWS::StackName'
    Type: AWS::ElastiCache::SubnetGroup
  ContainerInstanceProfile:
    Properties:
      Path: /
      Roles:
        - !Ref 'ContainerInstanceRole'
    Type: AWS::IAM::InstanceProfile
  ContainerInstanceRole:
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action:
              - sts:AssumeRole
            Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy
        - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
        - arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy
      Path: /
      Policies:
        - PolicyDocument:
            Statement: !If
              - UseSFTPServerCondition
              - - Action:
                    - s3:ListBucket
                  Effect: Allow
                  Resource: !Join
                    - ''
                    - - !If
                        - InGovCloudRegion
                        - arn:aws-us-gov
                        - arn:aws
                      - ':s3:::'
                      - !Ref 'AssetsBucket'
                - Action:
                    - s3:*
                  Effect: Allow
                  Resource: !Join
                    - ''
                    - - !If
                        - InGovCloudRegion
                        - arn:aws-us-gov
                        - arn:aws
                      - ':s3:::'
                      - !Ref 'AssetsBucket'
                      - /*
                - Action:
                    - s3:ListBucket
                  Effect: Allow
                  Resource: !Join
                    - ''
                    - - !If
                        - InGovCloudRegion
                        - arn:aws-us-gov
                        - arn:aws
                      - ':s3:::'
                      - !Ref 'PrivateAssetsBucket'
                - Action:
                    - s3:*
                  Effect: Allow
                  Resource: !Join
                    - ''
                    - - !If
                        - InGovCloudRegion
                        - arn:aws-us-gov
                        - arn:aws
                      - ':s3:::'
                      - !Ref 'PrivateAssetsBucket'
                      - /*
                - Action:
                    - s3:ListBucket
                  Effect: Allow
                  Resource: !Join
                    - ''
                    - - !If
                        - InGovCloudRegion
                        - arn:aws-us-gov
                        - arn:aws
                      - ':s3:::'
                      - !Ref 'SFTPAssetsBucket'
                - Action:
                    - s3:*
                  Effect: Allow
                  Resource: !Join
                    - ''
                    - - !If
                        - InGovCloudRegion
                        - arn:aws-us-gov
                        - arn:aws
                      - ':s3:::'
                      - !Ref 'SFTPAssetsBucket'
                      - /*
              - - Action:
                    - s3:ListBucket
                  Effect: Allow
                  Resource: !Join
                    - ''
                    - - !If
                        - InGovCloudRegion
                        - arn:aws-us-gov
                        - arn:aws
                      - ':s3:::'
                      - !Ref 'AssetsBucket'
                - Action:
                    - s3:*
                  Effect: Allow
                  Resource: !Join
                    - ''
                    - - !If
                        - InGovCloudRegion
                        - arn:aws-us-gov
                        - arn:aws
                      - ':s3:::'
                      - !Ref 'AssetsBucket'
                      - /*
                - Action:
                    - s3:ListBucket
                  Effect: Allow
                  Resource: !Join
                    - ''
                    - - !If
                        - InGovCloudRegion
                        - arn:aws-us-gov
                        - arn:aws
                      - ':s3:::'
                      - !Ref 'PrivateAssetsBucket'
                - Action:
                    - s3:*
                  Effect: Allow
                  Resource: !Join
                    - ''
                    - - !If
                        - InGovCloudRegion
                        - arn:aws-us-gov
                        - arn:aws
                      - ':s3:::'
                      - !Ref 'PrivateAssetsBucket'
                      - /*
          PolicyName: AssetsManagementPolicy
        - PolicyDocument:
            Statement:
              - Action:
                  - logs:Create*
                  - logs:PutLogEvents
                  - logs:DescribeLogGroups
                  - logs:DescribeLogStreams
                Effect: Allow
                Resource: !Join
                  - ''
                  - - !If
                      - InGovCloudRegion
                      - arn:aws-us-gov
                      - arn:aws
                    - :logs:*:*:*
          PolicyName: LoggingPolicy
      Tags:
        - Key: aws-web-stacks:stack-name
          Value: !Ref 'AWS::StackName'
    Type: AWS::IAM::Role
  ContainerLogs:
    DeletionPolicy: Retain
    Properties:
      RetentionInDays: 365
      Tags:
        - Key: aws-web-stacks:stack-name
          Value: !Ref 'AWS::StackName'
    Type: AWS::Logs::LogGroup
  DatabaseInstance:
    Condition: DatabaseCondition
    DeletionPolicy: Snapshot
    Properties:
      AllocatedStorage: !Ref 'DatabaseAllocatedStorage'
      BackupRetentionPeriod: !Ref 'DatabaseBackupRetentionDays'
      DBInstanceClass: !Ref 'DatabaseClass'
      DBName: !Ref 'DatabaseName'
      DBParameterGroupName: !Ref 'DatabaseParameterGroup'
      DBSubnetGroupName: !Ref 'DatabaseSubnetGroup'
      EnableCloudwatchLogsExports: !If
        - DatabaseLoggingCondition
        - !Ref 'DatabaseCloudWatchLogTypes'
        - !Ref 'AWS::NoValue'
      Engine: !Ref 'DatabaseEngine'
      EngineVersion: !Ref 'DatabaseEngineVersion'
      KmsKeyId: !If
        - CmkArnCondition
        - !Ref 'CustomerManagedCmkArn'
        - !Ref 'AWS::NoValue'
      MasterUserPassword: !Ref 'DatabasePassword'
      MasterUsername: !Ref 'DatabaseUser'
      MultiAZ: !Ref 'DatabaseMultiAZ'
      StorageEncrypted: !Ref 'UseAES256Encryption'
      StorageType: gp2
      Tags:
        - Key: aws-web-stacks:stack-name
          Value: !Ref 'AWS::StackName'
      VPCSecurityGroups:
        - !Ref 'DatabaseSecurityGroup'
    Type: AWS::RDS::DBInstance
  DatabaseParameterGroup:
    Condition: DatabaseCondition
    Properties:
      Description: Database parameter group.
      Family: !Ref 'DatabaseParameterGroupFamily'
      Parameters: {}
      Tags:
        - Key: aws-web-stacks:stack-name
          Value: !Ref 'AWS::StackName'
    Type: AWS::RDS::DBParameterGroup
  DatabaseReplica:
    Condition: DatabaseReplicationCondition
    Properties:
      DBInstanceClass: !Ref 'DatabaseClass'
      Engine: !Ref 'DatabaseEngine'
      SourceDBInstanceIdentifier: !Ref 'DatabaseInstance'
      Tags:
        - Key: aws-web-stacks:stack-name
          Value: !Ref 'AWS::StackName'
      VPCSecurityGroups:
        - !Ref 'DatabaseSecurityGroup'
    Type: AWS::RDS::DBInstance
  DatabaseSecurityGroup:
    Condition: DatabaseCondition
    Properties:
      GroupDescription: Database security group.
      SecurityGroupIngress:
        - CidrIp: !Ref 'PrivateSubnetACidr'
          FromPort: !FindInMap
            - RdsEngineMap
            - !Ref 'DatabaseEngine'
            - Port
          IpProtocol: tcp
          ToPort: !FindInMap
            - RdsEngineMap
            - !Ref 'DatabaseEngine'
            - Port
        - CidrIp: !Ref 'PrivateSubnetBCidr'
          FromPort: !FindInMap
            - RdsEngineMap
            - !Ref 'DatabaseEngine'
            - Port
          IpProtocol: tcp
          ToPort: !FindInMap
            - RdsEngineMap
            - !Ref 'DatabaseEngine'
            - Port
      Tags:
        - Key: aws-web-stacks:stack-name
          Value: !Ref 'AWS::StackName'
        - Key: Name
          Value: !Join
            - '-'
            - - !Ref 'AWS::StackName'
              - rds
      VpcId: !Ref 'Vpc'
    Type: AWS::EC2::SecurityGroup
  DatabaseSubnetGroup:
    Condition: DatabaseCondition
    Properties:
      DBSubnetGroupDescription: Subnets available for the RDS DB Instance
      SubnetIds:
        - !Ref 'PrivateSubnetA'
        - !Ref 'PrivateSubnetB'
      Tags:
        - Key: aws-web-stacks:stack-name
          Value: !Ref 'AWS::StackName'
    Type: AWS::RDS::DBSubnetGroup
  EksCluster:
    Properties:
      EncryptionConfig: !If
        - EnableEksEncryptionConfigCond
        - - Provider:
              KeyArn: !Ref 'CustomerManagedCmkArn'
            Resources:
              - secrets
        - !Ref 'AWS::NoValue'
      Logging:
        ClusterLogging:
          EnabledTypes:
            - Type: api
            - Type: audit
            - Type: authenticator
      Name: !Ref 'EksClusterName'
      ResourcesVpcConfig:
        EndpointPrivateAccess: !If
          - RestrictEksApiAccessCond
          - true
          - false
        EndpointPublicAccess: true
        PublicAccessCidrs: !If
          - RestrictEksApiAccessCond
          - !Ref 'EksPublicAccessCidrs'
          - !Ref 'AWS::NoValue'
        SecurityGroupIds:
          - !Ref 'EksClusterSecurityGroup'
        SubnetIds:
          - !Ref 'PublicSubnetA'
          - !Ref 'PublicSubnetB'
          - !Ref 'PrivateSubnetA'
          - !Ref 'PrivateSubnetB'
      RoleArn: !GetAtt 'EksServiceRole.Arn'
      Tags:
        - Key: aws-web-stacks:stack-name
          Value: !Ref 'AWS::StackName'
    Type: AWS::EKS::Cluster
  EksClusterSecurityGroup:
    Properties:
      GroupDescription: EKS control plane security group.
      Tags:
        - Key: aws-web-stacks:stack-name
          Value: !Ref 'AWS::StackName'
        - Key: Name
          Value: !Join
            - '-'
            - - !Ref 'AWS::StackName'
              - eks-cluster
      VpcId: !Ref 'Vpc'
    Type: AWS::EC2::SecurityGroup
  EksServiceRole:
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action:
              - sts:AssumeRole
            Effect: Allow
            Principal:
              Service:
                - eks.amazonaws.com
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonEKSClusterPolicy
        - arn:aws:iam::aws:policy/AmazonEKSServicePolicy
      Path: /
      Tags:
        - Key: aws-web-stacks:stack-name
          Value: !Ref 'AWS::StackName'
    Type: AWS::IAM::Role
  ElasticsearchDomain:
    Condition: Elasticsearch
    Properties:
      AccessPolicies:
        Statement:
          - Action:
              - es:*
            Effect: Allow
            Principal:
              AWS:
                - !GetAtt 'ContainerInstanceRole.Arn'
      EBSOptions:
        EBSEnabled: true
        VolumeSize: !Ref 'ElasticsearchVolumeSize'
      ElasticsearchClusterConfig:
        InstanceType: !Ref 'ElasticsearchInstanceType'
      ElasticsearchVersion: !Ref 'ElasticsearchVersion'
      Tags:
        - Key: aws-web-stacks:stack-name
          Value: !Ref 'AWS::StackName'
    Type: AWS::Elasticsearch::Domain
  GatewayAttachement:
    Properties:
      InternetGatewayId: !Ref 'InternetGateway'
      VpcId: !Ref 'Vpc'
    Type: AWS::EC2::VPCGatewayAttachment
  InternetGateway:
    Properties:
      Tags:
        - Key: aws-web-stacks:stack-name
          Value: !Ref 'AWS::StackName'
        - Key: Name
          Value: !Join
            - '-'
            - - !Ref 'AWS::StackName'
              - igw
    Type: AWS::EC2::InternetGateway
  Nodegroup:
    DependsOn:
      - EksCluster
    Properties:
      ClusterName: !Ref 'EksCluster'
      LaunchTemplate:
        Id: !Ref 'NodegroupLaunchTemplate'
      NodeRole: !GetAtt 'ContainerInstanceRole.Arn'
      ScalingConfig:
        DesiredSize: !Ref 'DesiredScale'
        MaxSize: !Ref 'MaxScale'
        MinSize: 2
      Subnets:
        - !Ref 'PrivateSubnetA'
        - !Ref 'PrivateSubnetB'
      Tags:
        aws-web-stacks:stack-name: !Ref 'AWS::StackName'
    Type: AWS::EKS::Nodegroup
  NodegroupLaunchTemplate:
    Properties:
      LaunchTemplateData:
        BlockDeviceMappings:
          - DeviceName: /dev/xvda
            Ebs:
              DeleteOnTermination: true
              Encrypted: !Ref 'UseAES256Encryption'
              KmsKeyId: !If
                - CmkArnCondition
                - !Ref 'CustomerManagedCmkArn'
                - !Ref 'AWS::NoValue'
              VolumeSize: !Ref 'ContainerVolumeSize'
              VolumeType: gp2
        InstanceType: !Ref 'ContainerInstanceType'
        MetadataOptions:
          HttpPutResponseHopLimit: 3
          HttpTokens: required
    Type: AWS::EC2::LaunchTemplate
  PrivateAssetsBucket:
    DeletionPolicy: Retain
    Properties:
      AccessControl: Private
      BucketEncryption: !If
        - UseAES256EncryptionCond
        - ServerSideEncryptionConfiguration:
            - ServerSideEncryptionByDefault:
                KMSMasterKeyID: !If
                  - CmkArnCondition
                  - !Ref 'CustomerManagedCmkArn'
                  - !Ref 'AWS::NoValue'
                SSEAlgorithm: !If
                  - CmkArnCondition
                  - aws:kms
                  - AES256
        - !Ref 'AWS::NoValue'
      CorsConfiguration:
        CorsRules:
          - AllowedHeaders:
              - '*'
            AllowedMethods:
              - POST
              - PUT
              - HEAD
              - GET
            AllowedOrigins: !Split
              - ;
              - !Join
                - ''
                - - https://
                  - !Join
                    - ;https://
                    - !Split
                      - ;
                      - !Join
                        - ''
                        - - !Ref 'DomainName'
                          - !If
                            - NoAlternateDomains
                            - ''
                            - ;
                          - !Join
                            - ;
                            - !Ref 'DomainNameAlternates'
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
      Tags:
        - Key: aws-web-stacks:stack-name
          Value: !Ref 'AWS::StackName'
      VersioningConfiguration:
        Status: Enabled
    Type: AWS::S3::Bucket
  PrivateSubnetA:
    Properties:
      AvailabilityZone: !Ref 'PrimaryAZ'
      CidrBlock: !Ref 'PrivateSubnetACidr'
      MapPublicIpOnLaunch: true
      Tags:
        - Key: aws-web-stacks:stack-name
          Value: !Ref 'AWS::StackName'
        - Key: Name
          Value: !Join
            - '-'
            - - !Ref 'AWS::StackName'
              - private-a
        - Key: kubernetes.io/role/internal-elb
          Value: '1'
      VpcId: !Ref 'Vpc'
    Type: AWS::EC2::Subnet
  PrivateSubnetARouteTableAssociation:
    Properties:
      RouteTableId: !Ref 'PublicRouteTable'
      SubnetId: !Ref 'PrivateSubnetA'
    Type: AWS::EC2::SubnetRouteTableAssociation
  PrivateSubnetB:
    Properties:
      AvailabilityZone: !Ref 'SecondaryAZ'
      CidrBlock: !Ref 'PrivateSubnetBCidr'
      MapPublicIpOnLaunch: true
      Tags:
        - Key: aws-web-stacks:stack-name
          Value: !Ref 'AWS::StackName'
        - Key: Name
          Value: !Join
            - '-'
            - - !Ref 'AWS::StackName'
              - private-b
        - Key: kubernetes.io/role/internal-elb
          Value: '1'
      VpcId: !Ref 'Vpc'
    Type: AWS::EC2::Subnet
  PrivateSubnetBRouteTableAssociation:
    Properties:
      RouteTableId: !Ref 'PublicRouteTable'
      SubnetId: !Ref 'PrivateSubnetB'
    Type: AWS::EC2::SubnetRouteTableAssociation
  PublicRoute:
    Properties:
      DestinationCidrBlock: '0.0.0.0/0'
      GatewayId: !Ref 'InternetGateway'
      RouteTableId: !Ref 'PublicRouteTable'
    Type: AWS::EC2::Route
  PublicRouteTable:
    Properties:
      Tags:
        - Key: aws-web-stacks:stack-name
          Value: !Ref 'AWS::StackName'
        - Key: Name
          Value: !Join
            - '-'
            - - !Ref 'AWS::StackName'
              - public
      VpcId: !Ref 'Vpc'
    Type: AWS::EC2::RouteTable
  PublicSubnetA:
    Properties:
      AvailabilityZone: !Ref 'PrimaryAZ'
      CidrBlock: !Ref 'PublicSubnetACidr'
      Tags:
        - Key: aws-web-stacks:stack-name
          Value: !Ref 'AWS::StackName'
        - Key: Name
          Value: !Join
            - '-'
            - - !Ref 'AWS::StackName'
              - public-a
        - Key: kubernetes.io/role/elb
          Value: '1'
      VpcId: !Ref 'Vpc'
    Type: AWS::EC2::Subnet
  PublicSubnetARouteTableAssociation:
    Properties:
      RouteTableId: !Ref 'PublicRouteTable'
      SubnetId: !Ref 'PublicSubnetA'
    Type: AWS::EC2::SubnetRouteTableAssociation
  PublicSubnetB:
    Properties:
      AvailabilityZone: !Ref 'SecondaryAZ'
      CidrBlock: !Ref 'PublicSubnetBCidr'
      Tags:
        - Key: aws-web-stacks:stack-name
          Value: !Ref 'AWS::StackName'
        - Key: Name
          Value: !Join
            - '-'
            - - !Ref 'AWS::StackName'
              - public-b
        - Key: kubernetes.io/role/elb
          Value: '1'
      VpcId: !Ref 'Vpc'
    Type: AWS::EC2::Subnet
  PublicSubnetBRouteTableAssociation:
    Properties:
      RouteTableId: !Ref 'PublicRouteTable'
      SubnetId: !Ref 'PublicSubnetB'
    Type: AWS::EC2::SubnetRouteTableAssociation
  RedisReplicationGroup:
    Condition: UsingRedis
    Properties:
      AtRestEncryptionEnabled: !Ref 'UseAES256Encryption'
      AuthToken: !If
        - AuthTokenCondition
        - !Ref 'RedisAuthToken'
        - !Ref 'AWS::NoValue'
      AutomaticFailoverEnabled: !Ref 'RedisAutomaticFailover'
      CacheNodeType: !Ref 'RedisNodeType'
      CacheSubnetGroupName: !Ref 'CacheSubnetGroup'
      Engine: redis
      EngineVersion: !Ref 'RedisVersion'
      KmsKeyId: !If
        - CmkArnCondition
        - !Ref 'CustomerManagedCmkArn'
        - !Ref 'AWS::NoValue'
      MultiAZEnabled: !Ref 'RedisAutomaticFailover'
      NumCacheClusters: !Ref 'RedisNumCacheClusters'
      Port: 6379
      PreferredCacheClusterAZs: !If
        - RedisAutomaticFailoverCondition
        - - !Ref 'PrimaryAZ'
          - !Ref 'SecondaryAZ'
        - !Ref 'AWS::NoValue'
      ReplicationGroupDescription: Redis ReplicationGroup
      SecurityGroupIds:
        - !Ref 'CacheSecurityGroup'
      SnapshotRetentionLimit: !Ref 'RedisSnapshotRetentionLimit'
      Tags:
        - Key: aws-web-stacks:stack-name
          Value: !Ref 'AWS::StackName'
        - Key: Name
          Value: !Join
            - '-'
            - - !Ref 'AWS::StackName'
              - redis
      TransitEncryptionEnabled: !Ref 'UseAES256Encryption'
    Type: AWS::ElastiCache::ReplicationGroup
  SFTPAssetsBucket:
    DeletionPolicy: Retain
    Properties:
      AccessControl: Private
      BucketEncryption: !If
        - UseAES256EncryptionCond
        - ServerSideEncryptionConfiguration:
            - ServerSideEncryptionByDefault:
                KMSMasterKeyID: !If
                  - CmkArnCondition
                  - !Ref 'CustomerManagedCmkArn'
                  - !Ref 'AWS::NoValue'
                SSEAlgorithm: !If
                  - CmkArnCondition
                  - aws:kms
                  - AES256
        - !Ref 'AWS::NoValue'
      CorsConfiguration:
        CorsRules:
          - AllowedHeaders:
              - '*'
            AllowedMethods:
              - POST
              - PUT
              - HEAD
              - GET
            AllowedOrigins: !Split
              - ;
              - !Join
                - ''
                - - https://
                  - !Join
                    - ;https://
                    - !Split
                      - ;
                      - !Join
                        - ''
                        - - !Ref 'DomainName'
                          - !If
                            - NoAlternateDomains
                            - ''
                            - ;
                          - !Join
                            - ;
                            - !Ref 'DomainNameAlternates'
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
      Tags:
        - Key: aws-web-stacks:stack-name
          Value: !Ref 'AWS::StackName'
      VersioningConfiguration:
        Status: Enabled
    Type: AWS::S3::Bucket
  SFTPUserRole:
    Condition: UseSFTPServerCondition
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action:
              - sts:AssumeRole
            Effect: Allow
            Principal:
              Service:
                - transfer.amazonaws.com
      Policies:
        - PolicyDocument:
            Statement: !If
              - UseSFTPWithKMSCondition
              - - Action:
                    - s3:ListBucket
                    - s3:GetBucketLocation
                  Effect: Allow
                  Resource: !Join
                    - ''
                    - - !If
                        - InGovCloudRegion
                        - arn:aws-us-gov
                        - arn:aws
                      - ':s3:::'
                      - !Ref 'SFTPAssetsBucket'
                - Action:
                    - s3:PutObject
                    - s3:GetObject
                    - s3:DeleteObject
                    - s3:DeleteObjectVersion
                    - s3:GetObjectVersion
                    - s3:GetObjectACL
                    - s3:PutObjectACL
                  Effect: Allow
                  Resource: !Join
                    - ''
                    - - !If
                        - InGovCloudRegion
                        - arn:aws-us-gov
                        - arn:aws
                      - ':s3:::'
                      - !Ref 'SFTPAssetsBucket'
                      - /*
                - Action:
                    - kms:DescribeKey
                    - kms:GenerateDataKey
                    - kms:Encrypt
                    - kms:Decrypt
                  Effect: Allow
                  Resource: !Ref 'CustomerManagedCmkArn'
              - - Action:
                    - s3:ListBucket
                    - s3:GetBucketLocation
                  Effect: Allow
                  Resource: !Join
                    - ''
                    - - !If
                        - InGovCloudRegion
                        - arn:aws-us-gov
                        - arn:aws
                      - ':s3:::'
                      - !Ref 'SFTPAssetsBucket'
                - Action:
                    - s3:PutObject
                    - s3:GetObject
                    - s3:DeleteObject
                    - s3:DeleteObjectVersion
                    - s3:GetObjectVersion
                    - s3:GetObjectACL
                    - s3:PutObjectACL
                  Effect: Allow
                  Resource: !Join
                    - ''
                    - - !If
                        - InGovCloudRegion
                        - arn:aws-us-gov
                        - arn:aws
                      - ':s3:::'
                      - !Ref 'SFTPAssetsBucket'
                      - /*
            Version: '2012-10-17'
          PolicyName: SFTPSUserRolePolicy
      RoleName: !Join
        - '-'
        - - !Ref 'AWS::StackName'
          - SFTPUserRole
      Tags:
        - Key: aws-web-stacks:stack-name
          Value: !Ref 'AWS::StackName'
    Type: AWS::IAM::Role
  SFTPUserScopeDownPolicy:
    Condition: UseSFTPServerCondition
    Properties:
      PolicyDocument:
        Statement: !If
          - UseSFTPWithKMSCondition
          - - Action:
                - s3:ListBucket
              Condition:
                StringLike:
                  s3:prefix:
                    - ${transfer:UserName}/*
                    - ${transfer:UserName}
              Effect: Allow
              Resource:
                - arn:aws:s3:::${transfer:HomeBucket}
              Sid: AllowListingOfSFTPUserFolder
            - Action:
                - s3:PutObject
                - s3:GetObject
                - s3:DeleteObjectVersion
                - s3:DeleteObject
                - s3:GetObjectVersion
              Effect: Allow
              Resource:
                - !Join
                  - /
                  - - !GetAtt 'SFTPAssetsBucket.Arn'
                    - ${transfer:UserName}
                - !Join
                  - /
                  - - !GetAtt 'SFTPAssetsBucket.Arn'
                    - ${transfer:UserName}/*
              Sid: HomeDirObjectAccess
            - Action:
                - kms:DescribeKey
                - kms:GenerateDataKey
                - kms:Encrypt
                - kms:Decrypt
              Effect: Allow
              Resource: !Ref 'CustomerManagedCmkArn'
          - - Action:
                - s3:ListBucket
              Condition:
                StringLike:
                  s3:prefix:
                    - ${transfer:UserName}/*
                    - ${transfer:UserName}
              Effect: Allow
              Resource:
                - arn:aws:s3:::${transfer:HomeBucket}
              Sid: AllowListingOfSFTPUserFolder
            - Action:
                - s3:PutObject
                - s3:GetObject
                - s3:DeleteObjectVersion
                - s3:DeleteObject
                - s3:GetObjectVersion
              Effect: Allow
              Resource:
                - !Join
                  - /
                  - - !GetAtt 'SFTPAssetsBucket.Arn'
                    - ${transfer:UserName}
                - !Join
                  - /
                  - - !GetAtt 'SFTPAssetsBucket.Arn'
                    - ${transfer:UserName}/*
              Sid: HomeDirObjectAccess
        Version: '2012-10-17'
    Type: AWS::IAM::ManagedPolicy
  TransferServer:
    Condition: UseSFTPServerCondition
    Properties:
      EndpointType: PUBLIC
      IdentityProviderType: SERVICE_MANAGED
      Tags:
        - Key: aws-web-stacks:stack-name
          Value: !Ref 'AWS::StackName'
        - Key: Name
          Value: !Join
            - '-'
            - - !Ref 'AWS::StackName'
              - sftp
    Type: AWS::Transfer::Server
  Vpc:
    Properties:
      CidrBlock: !Ref 'VpcCidr'
      EnableDnsHostnames: true
      EnableDnsSupport: true
      Tags:
        - Key: aws-web-stacks:stack-name
          Value: !Ref 'AWS::StackName'
        - Key: Name
          Value: !Join
            - '-'
            - - !Ref 'AWS::StackName'
              - vpc
    Type: AWS::EC2::VPC

