AWSTemplateFormatVersion: "2010-09-09"
Description: "JFrog Artifactory Quick Start Deployment into an Existing VPC (qs-1q037efj0)"
Parameters:
  LogicalId:
    Description: Logical Id of the MODULE
    Type: String
  AvailabilityZone1:
    Description: Availability Zone 1 to use for the subnets in the VPC. Two
      Availability Zones are used for this deployment.
    Type: AWS::EC2::AvailabilityZone::Name
  AvailabilityZone2:
    Description: Availability Zone 2 to use for the subnets in the VPC. Two
      Availability Zones are used for this deployment.
    Type: AWS::EC2::AvailabilityZone::Name
  KeyPairName:
    Description: Name of an existing key pair,
      which allows you to connect securely to your instance after it launches.
      This is the key pair you created in your preferred Region.
    Type: String
  VpcId:
    Description: ID of your existing VPC (e.g., vpc-0343606e).
    Type: "AWS::EC2::VPC::Id"
  VpcCidr:
    Description: CIDR block for the VPC.
    AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([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: CIDR block parameter must be in the form x.x.x.x/16-28
    Default: 10.0.0.0/16
    Type: String
  PrivateSubnet2Id:
    Description: ID of the private subnet in Availability Zone 2 of your existing VPC (e.g., subnet-z0376dab).
    Type: AWS::EC2::Subnet::Id
  PrivateSubnet1Id:
    Description: ID of the private subnet in Availability Zone 1 of your existing VPC (e.g., subnet-z0376dab).
    Type: AWS::EC2::Subnet::Id
  PublicSubnet1Id:
    Description: ID of the public subnet in Availability Zone 1 of your existing VPC (e.g., subnet-z0376dab).
    Type: AWS::EC2::Subnet::Id
  PublicSubnet2Id:
    Description: ID of the public subnet in Availability Zone 1 of your existing VPC (e.g., subnet-z0376dab).
    Type: AWS::EC2::Subnet::Id
  PrivateSubnet1Cidr:
    Description: CIDR of the private subnet in Availability Zone 1 of your existing VPC (e.g., 10.0.0.0/19).
    AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([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: CIDR block parameter must be in the form x.x.x.x/16-28
    Default: 10.0.0.0/19
    Type: String
  PrivateSubnet2Cidr:
    Description: CIDR of the private subnet in Availability Zone 2 of your existing VPC (e.g., 10.0.32.0/19).
    AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([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: CIDR block parameter must be in the form x.x.x.x/16-28
    Default: 10.0.32.0/19
    Type: String
  AccessCidr:
    Description: CIDR IP range that is permitted to access Artifactory.
      We recommend that you set this value to a trusted IP range.
      For example, you might want to grant only your corporate network access to the software.
    AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$
    Type: String
  RemoteAccessCidr:
    Description:
      Remote CIDR range that allows you to connect to the bastion instance by using SSH.
      We recommend that you set this value to a trusted IP range.
      For example, you might want to grant specific ranges inside your corporate network SSH access.
    AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$
    Type: String
  ELBScheme:
    Description: Choose whether this is internet facing or internal.
    AllowedValues:
      - internal
      - internet-facing
    Default: internet-facing
    Type: String
  EnableBastion:
    Description: If set to true, a bastion host will be created.
    Default: "true"
    Type: String
    AllowedValues:
      - "true"
      - "false"
  BastionInstanceType:
    Description: Size of the bastion instances.
    AllowedValues:
      - t3.nano
      - t3.micro
      - t3.small
      - t3.medium
      - t3.large
      - m5.large
      - m5.xlarge
      - m5.2xlarge
      - m5.4xlarge
    Default: "t3.micro"
    Type: String
  BastionRootVolumeSize:
    Description: Size of the root volume on the bastion instances.
    Default: 10
    Type: Number
  BastionEnableTcpForwarding:
    Description:
      Choose whether to enable TCPForwarding via the bootstrapping of the bastion instance
      or not.
    AllowedValues:
      - "true"
      - "false"
    Default: "true"
    Type: String
  BastionEnableX11Forwarding:
    Description:
      Choose true to enable X11 via the bootstrapping of the bastion host.
      Setting this value to true will enable X Windows over SSH.
      X11 forwarding can be useful, but it is also a security risk, so it's recommended
      that you keep the default (false) setting.
    AllowedValues:
      - "true"
      - "false"
    Default: "false"
    Type: String
  BastionOs:
    Description: Linux distribution for the Amazon Machine Image (AMI) to be used for the bastion instances.
    AllowedValues:
      - "Amazon-Linux2-HVM"
      - "CentOS-7-HVM"
      - "Ubuntu-Server-20.04-LTS-HVM"
      - "SUSE-SLES-15-HVM"
    Default: "Amazon-Linux2-HVM"
    Type: String
  NumBastionHosts:
    Description: Number of bastion instances to create.
    AllowedValues:
      - "1"
      - "2"
      - "3"
      - "4"
    Default: "1"
    Type: String
  VolumeSize:
    Description:
      Size in gigabytes of the available storage (min 10GB); the Quick Start will create an
      Amazon Elastic Block Store (Amazon EBS) volumes of this size.
    Default: 200
    Type: Number
  InstanceType:
    Description: EC2 type for the Artifactory instances.
    AllowedValues:
      - m5.large
      - m5.xlarge
      - m5.2xlarge
      - m5.4xlarge
      - m5.8xlarge
      - m5.12xlarge
      - m5.16xlarge
      - m5.24xlarge
      - m5.metal
      - m5d.large
      - m5d.xlarge
      - m5d.2xlarge
      - m5d.4xlarge
      - m5d.8xlarge
      - m5d.12xlarge
      - m5d.16xlarge
      - m5d.24xlarge
      - m5d.metal
      - m5a.large
      - m5a.xlarge
      - m5a.2xlarge
      - m5a.4xlarge
      - m5a.8xlarge
      - m5a.12xlarge
      - m5a.16xlarge
      - m5a.24xlarge
    ConstraintDescription: Must contain valid instance type.
    Default: m5.xlarge
    Type: String
  NumberOfSecondary:
    Description: Number of secondary Artifactory servers to complete your
      HA deployment. To align with Artifactory best practices, the minimum number
      is two and the maximum is seven. Do not select more instances than you
      have licenses for.
    AllowedValues:
      - 0
      - 1
      - 2
      - 3
      - 4
      - 5
      - 6
      - 7
    Default: 2
    Type: Number
  ArtifactoryProduct:
    Description: JFrog Artifactory product you want to install into an AMI.
    AllowedValues:
      - JFrog-Artifactory-Pro
      - JFrog-Artifactory-Enterprise
      - JFrog-Container-Registry
    Default: JFrog-Artifactory-Enterprise
    Type: String
  ArtifactoryVersion:
    Description:
      Version of Artifactory that you want to deploy into the Quick Start.
      See the release notes to select the version you want to deploy at
      https://www.jfrog.com/confluence/display/RTF/Release+Notes.
    AllowedPattern: ^(([0-9]|[1-9][0-9])\.){2}([1-9][0-9]|[0-9])$
    ConstraintDescription: A version that matches X.X.X per Artifactory releases
    Default: 7.27.10
    Type: String
  SmLicenseName:
    Description: Secret name created in AWS Secrets Manager, which contains the Artifactory licenses.
    Default: ""
    Type: String
  SmCertName:
    Description: Secret name created in AWS Secrets Manager, which contains the SSL certificate and certificate key.
    Default: ""
    Type: String
  ArtifactoryServerName:
    Description: Name of your Artifactory server. Ensure that this matches your certificate.
    Type: String
  MasterKey:
    Description: Master key for the Artifactory cluster. Generate a master key by using the command '$openssl rand -hex 16'.
    AllowedPattern: ^[a-zA-Z0-9]+$
    MinLength: "1"
    MaxLength: "64"
    ConstraintDescription: Only capital or lowercase letters and numbers, with a Max of 64 characters.
    NoEcho: "true"
    Type: String
  ExtraJavaOptions:
    Description:
      Set Java options to pass to the JVM for Artifactory. For more information, see the Artifactory
      system requirements at https://www.jfrog.com/confluence/display/RTF/System+Requirements#SystemRequirements-RecommendedHardware.
      Do not add Xms or Xmx settings without disabling DefaultJavaMemSettings.
    Default: -Xss256k -XX:+UseG1GC
    Type: String
  DefaultJavaMemSettings:
    Description:
      Choose false to overwrite the standard memory-calculation options to pass to the Artifactory JVM.
      If you plan to overwrite them, ensure they are added to the ExtraJavaOptions to prevent the stack provision from failing.
    ConstraintDescription: True or False
    AllowedValues:
      - "true"
      - "false"
    Default: "true"
    Type: String
  DatabaseName:
    Description:
      Name of your database instance. The name must be unique across all instances
      owned by your AWS account in the current Region. The database instance identifier is case-insensitive,
      but it's stored in lowercase (as in "mydbinstance").
    AllowedPattern: ^[a-zA-Z]([a-zA-Z0-9])+$
    MinLength: "1"
    MaxLength: "60"
    ConstraintDescription: 1 to 60 alphanumeric characters First character must be a letter.
    Default: artdb
    Type: String
  DatabaseEngine:
    Description: Database engine that you want to run, which is currently locked to MySQL.
    AllowedValues:
      - Postgres
    Default: Postgres
    Type: String
  DatabaseUser:
    Description: Login ID for the master user of your database instance.
    MinLength: "1"
    MaxLength: "16"
    AllowedPattern: ^[a-zA-Z]([a-zA-Z0-9])+$
    ConstraintDescription: 1 to 16 alphanumeric characters. First character must be a letter.
    Default: artifactory
    Type: String
  DatabasePassword:
    Description: Password for the Artifactory database user.
    AllowedPattern: ^[^ \\']+$
    MinLength: "8"
    MaxLength: "12"
    ConstraintDescription: Must be at least 8 and no more than
      12 characters containing letters and (minimum 1 capital letter), numbers and
      symbols.
    NoEcho: "true"
    Type: String
  DatabaseInstance:
    Description: Size of the database to be deployed as part of the Quick Start.
    AllowedValues:
      - db.m5.large
      - db.m5.xlarge
      - db.m5.2xlarge
      - db.m5.10xlarge
      - db.m5.16xlarge
      - db.m5.large
      - db.m5.xlarge
      - db.m5.2xlarge
      - db.m5.4xlarge
      - db.m5.12xlarge
      - db.m5.24xlarge
    ConstraintDescription: Must be a valid database Instance Type.
    Default: db.m5.large
    Type: String
  DatabaseAllocatedStorage:
    Description: Size in gigabytes of the available storage for the database instance.
    MinValue: 5
    MaxValue: 1024
    Default: 10
    Type: Number
  DatabasePreferredAz:
    Description: Preferred availability zone for Amazon RDS primary instance
    Type: String
  MultiAzDatabase:
    Description: Choose false to create an Amazon RDS instance in a single Availability Zone.
    ConstraintDescription: True or False
    AllowedValues:
      - "true"
      - "false"
    Default: "true"
    Type: String
  QsS3BucketName:
    Description:
      S3 bucket name for the Quick Start assets. This string can include
      numbers, lowercase letters, and hyphens (-). It cannot start
      or end with a hyphen (-).
    AllowedPattern: ^[0-9a-z]+([0-9a-z-]*[0-9a-z])*$
    ConstraintDescription:
      Quick Start bucket name can include numbers, lowercase
      letters, and hyphens (-). It cannot start or end with a hyphen (-).
    Default: aws-quickstart
    Type: String
  QsS3KeyPrefix:
    Description:
      S3 key prefix for the Quick Start assets. Quick Start key prefix
      can include numbers, lowercase letters, uppercase letters, hyphens (-), and
      forward slash (/).
    AllowedPattern: ^[0-9a-zA-Z-/]*$
    ConstraintDescription:
      Quick Start key prefix can include numbers, lowercase letters,
      uppercase letters, hyphens (-), and forward slash (/).
    Default: quickstart-jfrog-artifactory/
    Type: String
  QsS3BucketRegion:
    Default: "us-east-1"
    Description: AWS Region where the Quick Start S3 bucket (QSS3BucketName) is hosted. If you use your own bucket, you must specify your own value.
    Type: String
  InstallXray:
    Description: Choose true to install JFrog Xray instance(s).
    ConstraintDescription: True or False
    AllowedValues:
      - "true"
      - "false"
    Default: "true"
    Type: String
  XrayVersion:
    Description: The version of Xray that you want to deploy into the Quick Start.
    AllowedPattern: ^(([0-9]|[1-9][0-9])\.){2}([1-9][0-9]|[0-9])$
    ConstraintDescription: A version that matches X.X.X per Xray releases.
    Default: 3.35.0
    Type: String
  XrayNumberOfInstances:
    Description: The number of Xray instances servers to complete your
      HA deployment. The minimum number is one; the maximum is seven.
      Do not select more than instances than you have licenses for.
    MinValue: 1
    MaxValue: 7
    Default: 1
    Type: Number
  XrayInstanceType:
    Description: The EC2 instance type for the Xray instances.
    AllowedValues:
      - c5.2xlarge
      - c5.4xlarge
    ConstraintDescription: Must contain valid instance type.
    Default: c5.2xlarge
    Type: String
  XrayDatabaseUser:
    Description: The login ID for the Xray database user.
    MinLength: "1"
    MaxLength: "16"
    AllowedPattern: ^[a-zA-Z]([a-zA-Z0-9])+$
    ConstraintDescription: 1 to 16 alphanumeric characters. First character must be a letter.
    Default: xray
    Type: String
  XrayDatabasePassword:
    Description: The password for the Xray database user.
    AllowedPattern: ^[^ \\']+$
    MinLength: "8"
    MaxLength: "12"
    ConstraintDescription: Must be at least 8 and no more than
      12 characters containing letters and (minimum 1 capital letter), numbers and
      symbols.
    NoEcho: "true"
    Type: String

Conditions:
  EnableBastion: !Equals [!Ref "EnableBastion", "true"]
  IsArtifactory:
    !Not [!Equals [!Ref ArtifactoryProduct, "JFrog-Container-Registry"]]
  HasSecondaryNodes: !Not [!Equals [!Ref NumberOfSecondary, "0"]]
  DefaultJava: !Equals [!Ref DefaultJavaMemSettings, "true"]
  UsingDefaultBucket: !Equals [!Ref QsS3BucketName, "aws-quickstart"]
  EnableXray: !Equals [!Ref InstallXray, "true"]
  SmCertNameNotExists: !Equals [!Ref "SmCertName", ""]
  SmCertNameExists: !Not [!Equals [!Ref "SmCertName", ""]]

Mappings:
  DatabaseMap:
    Postgres:
      Name: postgresql
      DatabaseVersion: 11.5
      Driver: "org.postgresql.Driver"
      Plugin: postgresql-42.2.9.jar
      PluginURL: https://jdbc.postgresql.org/download/
      port: "5432"
      extraDatabaseOps: ""
  JavaOptionstoInstance:
    c5.2xlarge:
      Min: 8
      Max: 12
      DeploymentSize: Small
    c5.4xlarge:
      Min: 16
      Max: 24
      DeploymentSize: Large
    m5.large:
      Min: 4
      Max: 4
      DeploymentSize: xxSmall
    m5.xlarge:
      Min: 8
      Max: 12
      DeploymentSize: xSmall
    m5.2xlarge:
      Min: 16
      Max: 24
      DeploymentSize: Small
    m5.4xlarge:
      Min: 32
      Max: 48
      DeploymentSize: Medium
    m5.8xlarge:
      Min: 64
      Max: 96
      DeploymentSize: Large
    m5.12xlarge:
      Min: 96
      Max: 144
      DeploymentSize: xLarge
    m5.16xlarge:
      Min: 128
      Max: 192
      DeploymentSize: xxLarge
    m5.24xlarge:
      Min: 192
      Max: 288
      DeploymentSize: xxxLarge
    m5.metal:
      Min: 192
      Max: 288
      DeploymentSize: xxxLarge
    m5d.large:
      Min: 4
      Max: 4
      DeploymentSize: xxSmall
    m5d.xlarge:
      Min: 8
      Max: 12
      DeploymentSize: xSmall
    m5d.2xlarge:
      Min: 16
      Max: 24
      DeploymentSize: Small
    m5d.4xlarge:
      Min: 32
      Max: 48
      DeploymentSize: Medium
    m5d.8xlarge:
      Min: 64
      Max: 96
      DeploymentSize: Large
    m5d.12xlarge:
      Min: 96
      Max: 144
      DeploymentSize: xLarge
    m5d.16xlarge:
      Min: 128
      Max: 192
      DeploymentSize: xxLarge
    m5d.24xlarge:
      Min: 192
      Max: 288
      DeploymentSize: xxxLarge
    m5d.metal:
      Min: 192
      Max: 288
      DeploymentSize: xxxLarge
    m5a.large:
      Min: 4
      Max: 4
      DeploymentSize: xxSmall
    m5a.xlarge:
      Min: 8
      Max: 12
      DeploymentSize: xSmall
    m5a.2xlarge:
      Min: 16
      Max: 24
      DeploymentSize: Small
    m5a.4xlarge:
      Min: 32
      Max: 48
      DeploymentSize: Medium
    m5a.8xlarge:
      Min: 64
      Max: 96
      DeploymentSize: Large
    m5a.12xlarge:
      Min: 96
      Max: 144
      DeploymentSize: xLarge
    m5a.16xlarge:
      Min: 128
      Max: 192
      DeploymentSize: xxLarge
    m5a.24xlarge:
      Min: 192
      Max: 288
      DeploymentSize: xxxLarge
    m5ad.large:
      Min: 4
      Max: 4
      DeploymentSize: xxSmall
    m5ad.xlarge:
      Min: 8
      Max: 12
      DeploymentSize: xSmall
    m5ad.2xlarge:
      Min: 16
      Max: 24
      DeploymentSize: Small
    m5ad.4xlarge:
      Min: 32
      Max: 48
      DeploymentSize: Medium
    m5ad.12xlarge:
      Min: 96
      Max: 144
      DeploymentSize: xLarge
    m5ad.24xlarge:
      Min: 192
      Max: 288
      DeploymentSize: xxxLarge
Resources:
  BastionStack:
    Condition: EnableBastion
    Type: JFrog::Linux::Bastion::MODULE
    Metadata:
      {
        PublisherId: "06ff50c2e47f57b381f874871d9fac41796c9522",
        SupportedMajorVersions: [1],
      }
    Properties:
      LogicalId: !Sub ${LogicalId}BastionStack
      VPCID: !Ref VpcId
      PublicSubnet1Id: !Ref PublicSubnet1Id
      PublicSubnet2Id: !Ref PublicSubnet2Id
      KeyPairName: !Ref KeyPairName
      QSS3BucketName: !Ref QsS3BucketName
      QSS3KeyPrefix: !Sub "${QsS3KeyPrefix}submodules/quickstart-linux-bastion/"
      QSS3BucketRegion: !Ref QsS3BucketRegion
      RemoteAccessCIDR: !Ref RemoteAccessCidr
      BastionInstanceType: !Ref BastionInstanceType
      RootVolumeSize: !Ref BastionRootVolumeSize
      BastionAMIOS: !Ref BastionOs
      EnableTCPForwarding: !Ref BastionEnableTcpForwarding
      EnableX11Forwarding: !Ref BastionEnableX11Forwarding
      NumBastionHosts: !Ref NumBastionHosts
  ArtifactoryCoreInfraStack:
    Type: JFrog::Artifactory::Core::MODULE
    Metadata:
      {
        PublisherId: "06ff50c2e47f57b381f874871d9fac41796c9522",
        SupportedMajorVersions: [1],
      }
    Properties:
      AvailabilityZone1: !Ref AvailabilityZone1
      AvailabilityZone2: !Ref AvailabilityZone2
      VpcId: !Ref VpcId
      VpcCidr: !Ref VpcCidr
      PrivateSubnet1Cidr: !Ref PrivateSubnet1Cidr
      PrivateSubnet2Cidr: !Ref PrivateSubnet2Cidr
      PrivateSubnet3Cidr: !Ref PrivateSubnet2Cidr # This should end up in no new rule but required for EKS
      PrivateSubnet1Id: !Ref PrivateSubnet1Id
      PrivateSubnet2Id: !Ref PrivateSubnet2Id
      DatabaseAllocatedStorage: !Ref DatabaseAllocatedStorage
      DatabasePreferredAz: !Ref DatabasePreferredAz
      MultiAzDatabase: !Ref MultiAzDatabase
      DatabaseEngine: !Ref DatabaseEngine
      DatabaseUser: !Ref DatabaseUser
      DatabasePassword: !Ref DatabasePassword
      DatabaseInstance: !Ref DatabaseInstance
      DatabaseName: !Ref DatabaseName
      InstanceType: !Ref InstanceType
      ArtifactoryHostRole: !Ref ArtifactoryHostRole
      VolumeSize: !Ref VolumeSize
  ArtifactoryElb:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      IpAddressType: ipv4
      Scheme: !Ref ELBScheme
      Subnets:
        - !Ref PublicSubnet1Id
        - !Ref PublicSubnet2Id
      Type: network
      # Type: application
  ArtifactorySslTargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      HealthCheckEnabled: True
      HealthCheckIntervalSeconds: 30
      HealthCheckProtocol: TCP
      HealthCheckTimeoutSeconds: 10
      HealthyThresholdCount: 3
      HealthCheckPort: "8082"
      Port: 443
      Protocol: TCP
      TargetType: instance
      UnhealthyThresholdCount: 3
      VpcId: !Ref VpcId
  ArtifactoryTargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      HealthCheckEnabled: True
      HealthCheckIntervalSeconds: 30
      HealthCheckProtocol: TCP
      HealthCheckTimeoutSeconds: 10
      HealthyThresholdCount: 3
      HealthCheckPort: "8082"
      Port: 80
      Protocol: TCP
      TargetType: instance
      UnhealthyThresholdCount: 3
      VpcId: !Ref VpcId
  ArtifactorySslElbListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions:
        - TargetGroupArn: !Ref ArtifactorySslTargetGroup
          Type: forward
      LoadBalancerArn: !Ref ArtifactoryElb
      Port: 443
      Protocol: TCP
  ArtifactoryElbListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Condition: SmCertNameNotExists
    Properties:
      DefaultActions:
        - TargetGroupArn: !Ref ArtifactoryTargetGroup
          Type: forward
      LoadBalancerArn: !Ref ArtifactoryElb
      Port: 80
      Protocol: TCP
  ArtifactoryInternalElb:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      IpAddressType: ipv4
      # Name: ArtifactoryInternal-ELB
      Scheme: internal
      Subnets:
        - !Ref PrivateSubnet1Id
        - !Ref PrivateSubnet2Id
      Type: network
  ArtifactoryInternalTargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      HealthCheckEnabled: True
      HealthCheckIntervalSeconds: 30
      HealthCheckProtocol: TCP
      HealthCheckTimeoutSeconds: 10
      HealthyThresholdCount: 3
      HealthCheckPort: "8082"
      # Name: artifactory-internal-http
      Port: 80
      Protocol: TCP
      TargetType: instance
      UnhealthyThresholdCount: 3
      VpcId: !Ref VpcId
  ArtifactoryInternalElbListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions:
        - TargetGroupArn: !Ref ArtifactoryInternalTargetGroup
          Type: forward
      LoadBalancerArn: !Ref ArtifactoryInternalElb
      Port: 80
      Protocol: TCP
  ArtifactoryEc2Sg:
    Type: AWS::EC2::SecurityGroup
    Properties:
      Tags:
        - Key: Name
          Value: !Sub ${ArtifactoryProduct}-ec2-instances-sg
      GroupDescription: SG for EC2 instances (also permits access using SSH from the bastion host)
      VpcId: !Ref VpcId
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: !Ref VpcCidr
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: !Ref VpcCidr
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: !Ref AccessCidr
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: !Ref AccessCidr
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: !Ref VpcCidr
        - IpProtocol: tcp
          FromPort: 8081
          ToPort: 8082
          CidrIp: !Ref VpcCidr
        - IpProtocol: tcp
          FromPort: 8046
          ToPort: 8046
          CidrIp: !Ref VpcCidr
      SecurityGroupEgress:
        - IpProtocol: "-1"
          CidrIp: 0.0.0.0/0
  ArtifactoryHostRole:
    Type: AWS::IAM::Role
    Properties:
      Path: /
      AssumeRolePolicyDocument:
        Statement:
          - Action:
              - "sts:AssumeRole"
            Principal:
              Service:
                - ec2.amazonaws.com
            Effect: Allow
        Version: 2012-10-17
      ManagedPolicyArns:
        - !Sub "arn:${AWS::Partition}:iam::aws:policy/service-role/AmazonEC2RoleforSSM"
      Policies:
        - PolicyName: "JFrogAMI-policy"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: "Allow"
                Action: "ec2:Describe*"
                Resource: "*"
              - Effect: "Allow"
                Action: "ec2:AttachVolume"
                Resource: "*"
              - Effect: "Allow"
                Action: "ec2:DetachVolume"
                Resource: "*"
              - Effect: "Allow"
                Action:
                  - "s3:GetObject"
                  - "s3:ListObject"
                  - "s3:ListBucket"
                Resource: "*"
        - PolicyName: "CloudWatch-policy"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: "Allow"
                Action:
                  - "logs:CreateLogGroup"
                  - "logs:CreateLogStream"
                  - "logs:PutLogEvents"
                  - "logs:DescribeLogStreams"
                Resource: "arn:aws:logs:*:*:*"
              - Effect: "Allow"
                Action:
                  - "s3:GetObject"
                Resource: "*"
        - PolicyName: "SecretsMaanger-policy"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: "Allow"
                Action:
                  - "secretsmanager:GetSecretValue"
                Resource: "arn:aws:secretsmanager:*:*:secret:*"
  ArtifactoryHostProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      InstanceProfileName: !Ref ArtifactoryHostRole
      Roles:
        - !Ref ArtifactoryHostRole
      Path: /
  ArtifactoryPrimary:
    Type: JFrog::Artifactory::EC2Instance::MODULE
    Metadata:
      {
        PublisherId: "06ff50c2e47f57b381f874871d9fac41796c9522",
        SupportedMajorVersions: [1],
      }
    Properties:
      LogicalId: !Sub ${LogicalId}ArtifactoryPrimary
      PrivateSubnet1Id: !Ref PrivateSubnet1Id
      PrivateSubnet2Id: !Ref PrivateSubnet2Id
      MinScalingNodes: "1" # Always have 1 PrimaryNode
      MaxScalingNodes: "1" # Always have 1 PrimaryNode
      DeploymentTag: !If [IsArtifactory, "ArtifactoryPrimary", "JcrPrimary"]
      HostRole: !Ref ArtifactoryHostRole
      QsS3BucketName: !Ref QsS3BucketName
      QsS3KeyPrefix: !Ref QsS3KeyPrefix
      QsS3Uri: !Sub
        - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QsS3KeyPrefix}
        - S3Bucket: !If
            - UsingDefaultBucket
            - !Sub "aws-quickstart-${AWS::Region}"
            - !Ref "QsS3BucketName"
          S3Region: !If
            - UsingDefaultBucket
            - !Ref "AWS::Region"
            - !Ref "QsS3BucketRegion"
      ArtifactoryProduct: !Ref ArtifactoryProduct
      ArtifactoryLicensesSecretName: !Ref SmLicenseName
      ArtifactoryServerName: !Ref ArtifactoryServerName
      SmCertName: !Ref SmCertName
      ArtifactoryS3Bucket: !Ref ArtifactoryCoreInfraStack.ArtifactoryS3Bucket
      DatabaseUrl: !Sub
        - "jdbc:${DatabaseType}://${ArtifactoryDatabaseEndpointAddress}:${port}/${DatabaseName}${extraDatabaseOps}"
        - {
            DatabaseType: !FindInMap [DatabaseMap, !Ref DatabaseEngine, Name],
            ArtifactoryDatabaseEndpointAddress: !GetAtt ArtifactoryCoreInfraStack.ArtifactoryDatabase.Endpoint.Address,
            port: !FindInMap [DatabaseMap, !Ref DatabaseEngine, port],
            extraDatabaseOps:
              !FindInMap [DatabaseMap, !Ref DatabaseEngine, extraDatabaseOps],
          }
      DatabaseDriver: !FindInMap [DatabaseMap, !Ref DatabaseEngine, Driver]
      DatabasePlugin: !FindInMap [DatabaseMap, !Ref DatabaseEngine, Plugin]
      DatabasePluginUrl: !Sub
        - "${MainURL}${PluginVersion}"
        - {
            MainURL: !FindInMap [DatabaseMap, !Ref DatabaseEngine, PluginURL],
            PluginVersion:
              !FindInMap [DatabaseMap, !Ref DatabaseEngine, Plugin],
          }
      DatabaseType: !FindInMap [DatabaseMap, !Ref DatabaseEngine, Name]
      DatabaseUser: !Ref DatabaseUser
      DatabasePassword: !Ref DatabasePassword
      ArtifactoryPrimary: true
      MasterKey: !Ref MasterKey
      ExtraJavaOptions: !If
        - DefaultJava
        - !Sub
          - "-Xms${min}g -Xmx${max}g"
          - {
              min: !FindInMap [JavaOptionstoInstance, !Ref InstanceType, Min],
              max: !FindInMap [JavaOptionstoInstance, !Ref InstanceType, Max],
            }
        - !Ref ExtraJavaOptions
      ArtifactoryVersion: !Ref ArtifactoryVersion
      KeyPairName: !Ref KeyPairName
      HostProfile: !Ref ArtifactoryHostProfile
      SecurityGroups: !Ref ArtifactoryEc2Sg
      InstanceType: !Ref InstanceType
      PrimaryVolume: !Ref ArtifactoryCoreInfraStack.ArtifactoryEbsVolume
      VolumeSize: !Ref VolumeSize
      TargetGroupARN: !Ref ArtifactoryTargetGroup
      SSLTargetGroupARN: !Ref ArtifactorySslTargetGroup
      InternalTargetGroupARN: !Ref ArtifactoryInternalTargetGroup

  ArtifactorySecondary:
    Condition: HasSecondaryNodes
    #DependsOn: ArtifactoryPrimary
    Type: JFrog::Artifactory::EC2Instance::MODULE
    Metadata:
      {
        PublisherId: "06ff50c2e47f57b381f874871d9fac41796c9522",
        SupportedMajorVersions: [1],
      }
    Properties:
      LogicalId: !Sub ${LogicalId}ArtifactorySecondary
      PrivateSubnet1Id: !Ref PrivateSubnet1Id
      PrivateSubnet2Id: !Ref PrivateSubnet2Id
      MinScalingNodes: !Ref NumberOfSecondary
      MaxScalingNodes: !Ref NumberOfSecondary
      DeploymentTag: ArtifactorySecondary
      HostRole: !Ref ArtifactoryHostRole
      ArtifactoryProduct: !Ref ArtifactoryProduct
      ArtifactoryLicensesSecretName: !Ref SmLicenseName
      ArtifactoryServerName: !Ref ArtifactoryServerName
      SmCertName: !Ref SmCertName
      ArtifactoryS3Bucket: !Ref ArtifactoryCoreInfraStack.ArtifactoryS3Bucket
      DatabaseUrl: !Sub
        - "jdbc:${DatabaseType}://${ArtifactoryDatabaseEndpointAddress}:${port}/${DatabaseName}${extraDatabaseOps}"
        - {
            DatabaseType: !FindInMap [DatabaseMap, !Ref DatabaseEngine, Name],
            ArtifactoryDatabaseEndpointAddress: !GetAtt ArtifactoryCoreInfraStack.ArtifactoryDatabase.Endpoint.Address,
            port: !FindInMap [DatabaseMap, !Ref DatabaseEngine, port],
            extraDatabaseOps:
              !FindInMap [DatabaseMap, !Ref DatabaseEngine, extraDatabaseOps],
          }
      DatabaseDriver: !FindInMap [DatabaseMap, !Ref DatabaseEngine, Driver]
      DatabasePlugin: !FindInMap [DatabaseMap, !Ref DatabaseEngine, Plugin]
      DatabasePluginUrl: !Sub
        - "${MainURL}${PluginVersion}"
        - {
            MainURL: !FindInMap [DatabaseMap, !Ref DatabaseEngine, PluginURL],
            PluginVersion:
              !FindInMap [DatabaseMap, !Ref DatabaseEngine, Plugin],
          }
      DatabaseType: !FindInMap [DatabaseMap, !Ref DatabaseEngine, Name]
      DatabaseUser: !Ref DatabaseUser
      DatabasePassword: !Ref DatabasePassword
      ArtifactoryPrimary: false
      MasterKey: !Ref MasterKey
      ExtraJavaOptions: !If
        - DefaultJava
        - !Sub
          - "-Xms${min}g -Xmx${max}g"
          - {
              min: !FindInMap [JavaOptionstoInstance, !Ref InstanceType, Min],
              max: !FindInMap [JavaOptionstoInstance, !Ref InstanceType, Max],
            }
        - !Ref ExtraJavaOptions
      ArtifactoryVersion: !Ref ArtifactoryVersion
      KeyPairName: !Ref KeyPairName
      HostProfile: !Ref ArtifactoryHostProfile
      SecurityGroups: !Ref ArtifactoryEc2Sg
      InstanceType: !Ref InstanceType
      PrimaryVolume: !Ref ArtifactoryCoreInfraStack.ArtifactoryEbsVolume
      VolumeSize: !Ref VolumeSize
      TargetGroupARN: !Ref ArtifactoryTargetGroup
      SSLTargetGroupARN: !Ref ArtifactorySslTargetGroup
      InternalTargetGroupARN: !Ref ArtifactoryInternalTargetGroup
      QsS3BucketName: !Ref QsS3BucketName
      QsS3KeyPrefix: !Ref QsS3KeyPrefix
      QsS3Uri: !Sub
        - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QsS3KeyPrefix}
        - S3Bucket: !If
            - UsingDefaultBucket
            - !Sub "aws-quickstart-${AWS::Region}"
            - !Ref "QsS3BucketName"
          S3Region: !If
            - UsingDefaultBucket
            - !Ref "AWS::Region"
            - !Ref "QsS3BucketRegion"
  XrayHostRole:
    Condition: EnableXray
    Type: AWS::IAM::Role
    Properties:
      Path: /
      AssumeRolePolicyDocument:
        Statement:
          - Action:
              - "sts:AssumeRole"
            Principal:
              Service:
                - ec2.amazonaws.com
            Effect: Allow
        Version: 2012-10-17
      ManagedPolicyArns:
        - !Sub "arn:${AWS::Partition}:iam::aws:policy/service-role/AmazonEC2RoleforSSM"
      Policies:
        - PolicyName: "JFrogAMI-policy"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: "Allow"
                Action: "ec2:Describe*"
                Resource: "*"
              - Effect: "Allow"
                Action: "ec2:AttachVolume"
                Resource: "*"
              - Effect: "Allow"
                Action: "ec2:DetachVolume"
                Resource: "*"
              - Effect: "Allow"
                Action:
                  - "s3:GetObject"
                  - "s3:ListObject"
                  - "s3:ListBucket"
                Resource: "*"
        - PolicyName: "CloudWatch-policy"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: "Allow"
                Action:
                  - "logs:CreateLogGroup"
                  - "logs:CreateLogStream"
                  - "logs:PutLogEvents"
                  - "logs:DescribeLogStreams"
                Resource: "arn:aws:logs:*:*:*"
              - Effect: "Allow"
                Action:
                  - "s3:GetObject"
                Resource: "*"
  XrayHostProfile:
    Condition: EnableXray
    Type: AWS::IAM::InstanceProfile
    Properties:
      InstanceProfileName: !Ref XrayHostRole
      Roles:
        - !Ref XrayHostRole
      Path: /
  XrayExistingVpcStack:
    Condition: EnableXray
    # DependsOn: ArtifactoryPrimary
    Type: JFrog::Xray::EC2Instance::MODULE
    Metadata:
      {
        PublisherId: "06ff50c2e47f57b381f874871d9fac41796c9522",
        SupportedMajorVersions: [1],
      }
    Properties:
      LogicalId: !Sub ${LogicalId}XrayExistingVpcStack
      PrivateSubnet1Id: !Ref PrivateSubnet1Id
      PrivateSubnet2Id: !Ref PrivateSubnet2Id
      KeyPairName: !Ref KeyPairName
      MinScalingNodes: !Ref XrayNumberOfInstances
      MaxScalingNodes: !Ref XrayNumberOfInstances
      DeploymentTag: "xray"
      ArtifactoryProduct: !Ref ArtifactoryProduct
      QsS3BucketName: !Ref QsS3BucketName
      QsS3KeyPrefix: !Ref QsS3KeyPrefix
      QsS3Uri: !Sub
        - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QsS3KeyPrefix}
        - S3Bucket: !If
            - UsingDefaultBucket
            - !Sub "aws-quickstart-${AWS::Region}"
            - !Ref "QsS3BucketName"
          S3Region: !If
            - UsingDefaultBucket
            - !Ref "AWS::Region"
            - !Ref "QsS3BucketRegion"
      DatabaseDriver: !FindInMap [DatabaseMap, !Ref DatabaseEngine, Driver]
      DatabaseType: !FindInMap [DatabaseMap, !Ref DatabaseEngine, Name]
      DatabaseUser: !Ref DatabaseUser
      DatabasePassword: !Ref DatabasePassword
      MasterKey: !Ref MasterKey
      SecurityGroups: !Ref ArtifactoryEc2Sg
      VolumeSize: !Ref VolumeSize
      ExtraJavaOptions: !Sub
        - "-Xms${min}g -Xmx${max}g"
        - {
            min: !FindInMap [JavaOptionstoInstance, !Ref InstanceType, Min],
            max: !FindInMap [JavaOptionstoInstance, !Ref InstanceType, Max],
          }
      XrayInstanceType: !Ref XrayInstanceType
      JfrogInternalUrl: !Sub "http://${ArtifactoryInternalElb.DNSName}"
      XrayDatabaseUser: !Ref XrayDatabaseUser
      XrayDatabasePassword: !Ref XrayDatabasePassword
      XrayMasterDatabaseUrl: !Sub
        - "${ArtifactoryDatabaseEndpointAddress}:${port}/${DatabaseName}?sslmode=disable"
        - {
            ArtifactoryDatabaseEndpointAddress: !GetAtt ArtifactoryCoreInfraStack.ArtifactoryDatabase.Endpoint.Address,
            port: !FindInMap [DatabaseMap, !Ref DatabaseEngine, port],
          }
      XrayDatabaseUrl: !Sub
        - "${ArtifactoryDatabaseEndpointAddress}:${port}/xraydb?sslmode=disable"
        - {
            ArtifactoryDatabaseEndpointAddress: !GetAtt ArtifactoryCoreInfraStack.ArtifactoryDatabase.Endpoint.Address,
            port: !FindInMap [DatabaseMap, !Ref DatabaseEngine, port],
          }
      XrayVersion: !Ref XrayVersion
      XrayHostRole: !Ref XrayHostRole
      XrayHostProfile: !Ref XrayHostProfile
Outputs:
  ArtifactoryUrl:
    Description: URL of the ELB to access Artifactory
    Value:
      !If [
        SmCertNameExists,
        !Sub "https://${ArtifactoryElb.DNSName}",
        !Sub "http://${ArtifactoryElb.DNSName}",
      ]
  ArtifactoryInternalUrl:
    Description: URL of the internal ELB to access Artifactory
    Value: !Sub "http://${ArtifactoryInternalElb.DNSName}"
  DatabaseType:
    Description: Type of database
    Value: !FindInMap [DatabaseMap, !Ref DatabaseEngine, Name]
  DatabaseDriver:
    Description: Database driver
    Value: !FindInMap [DatabaseMap, !Ref DatabaseEngine, Driver]
  DatabaseUrl:
    Description: Database driver
    Value: !Sub
      - "${ArtifactoryDatabaseEndpointAddress}:${port}/${DatabaseName}?sslmode=disable"
      - {
          ArtifactoryDatabaseEndpointAddress: !GetAtt ArtifactoryCoreInfraStack.ArtifactoryDatabase.Endpoint.Address,
          port: !FindInMap [DatabaseMap, !Ref DatabaseEngine, port],
        }
  ArtifactoryTargetGroup:
    Description: Artifactory target group
    Value: !Ref ArtifactoryTargetGroup
  ArtifactorySslTargetGroup:
    Description: Artifactory SSL target group
    Value: !Ref ArtifactorySslTargetGroup
  ArtifactoryEc2Sg:
    Description: Artifactory EC2 sercurity group
    Value: !Ref ArtifactoryEc2Sg
  BastionIp:
    Value: !If
      - EnableBastion
      - !Ref BastionStack.EIP1
      - ""
  XrayMasterDatabaseUrl:
    Description: Database driver
    Value: !Sub
      - "${ArtifactoryDatabaseEndpointAddress}:${port}/${DatabaseName}?sslmode=disable"
      - {
          ArtifactoryDatabaseEndpointAddress: !GetAtt ArtifactoryCoreInfraStack.ArtifactoryDatabase.Endpoint.Address,
          port: !FindInMap [DatabaseMap, !Ref DatabaseEngine, port],
        }
  XrayDatabaseUrl:
    Description: Database driver
    Value: !Sub
      - "${ArtifactoryDatabaseEndpointAddress}:${port}/xraydb?sslmode=disable"
      - {
          ArtifactoryDatabaseEndpointAddress: !GetAtt ArtifactoryCoreInfraStack.ArtifactoryDatabase.Endpoint.Address,
          port: !FindInMap [DatabaseMap, !Ref DatabaseEngine, port],
        }
