AWSTemplateFormatVersion: "2010-09-09"
Description: "Deploys the EC2 Autoscaling, LaunchConfig and Instance for Artifactory (qs-1qpmmjh5o)"
Parameters:
  PrivateSubnet1Id:
    Type: 'AWS::EC2::Subnet::Id'
  PrivateSubnet2Id:
    Type: 'AWS::EC2::Subnet::Id'
  MinScalingNodes:
    Type: Number
  MaxScalingNodes:
    Type: Number
  DeploymentTag:
    Type: String
  HostRole:
    Type: String
  AmiId:
    Type: String
  ArtifactoryProduct:
    Type: String
  QsS3BucketName:
    Type: String
  QsS3KeyPrefix:
    Type: String
  QsS3Uri:
    Type: String
  ArtifactoryLicense1:
    Type: String
  ArtifactoryLicense2:
    Type: String
  ArtifactoryLicense3:
    Type: String
  ArtifactoryLicense4:
    Type: String
  ArtifactoryLicense5:
    Type: String
  ArtifactoryLicense6:
    Type: String
  ArtifactoryServerName:
    Type: String
  Certificate:
    Type: String
  CertificateKey:
    Type: String
    NoEcho: 'true'
  CertificateDomain:
    Type: String
  EnableSSL:
    Type: String
  ArtifactoryIamAcessKey:
    Type: String
    NoEcho: 'true'
  SecretAccessKey:
    Type: String
    NoEcho: 'true'
  ArtifactoryS3Bucket:
    Type: String
  DatabaseUrl:
    Type: String
  DatabaseDriver:
    Type: String
  DatabasePluginUrl:
    Type: String
  DatabasePlugin:
    Type: String
  DatabaseType:
    Type: String
  DatabaseUser:
    Type: String
  DatabasePassword:
    Type: String
    NoEcho: 'true'
  ArtifactoryPrimary:
    Type: String
  MasterKey:
    Type: String
    NoEcho: 'true'
  ExtraJavaOptions:
    Type: String
  ArtifactoryVersion:
    Type: String
  KeyPairName:
    Type: AWS::EC2::KeyPair::KeyName
  TargetGroupARN:
    Type: String
  SSLTargetGroupARN:
    Type: String
  InternalTargetGroupARN:
    Type: String
  HostProfile:
    Type: String
  SecurityGroups:
    Type: String
  InstanceType:
    Type: String
  VolumeSize:
    Type: Number
  KeystorePassword:
    Description: Default Keystore from Java in which we upgrade.
    Type: String
    NoEcho: 'true'
  AnsibleVaultPass:
    Description: Ansiblevault Password to secure the artifactory.yml
    Type: String
    NoEcho: 'true'
# To populate additional mappings use the following with the desired --region
# aws --region us-west-2 ec2 describe-images --owners amazon --filters 'Name=name,Values=amzn-ami-hvm-2018.03.0.20181129-x86_64-gp2' 'Name=state,Values=available' --output json | jq -r '.Images | sort_by(.CreationDate) | last(.[]).ImageId'
Mappings:
  AWSAMIRegionMap:
    ap-northeast-1:
      AMZNLINUXHVM: ami-079e6fb1e856e80c1
      "Artifactory721": ami-09dfb20a591375d09
      "Artifactory755": ami-09dfb20a591375d09 # TODO: Get correct ami
      "Jcr721": ami-0d87bf5404e186c90
    ap-northeast-2:
      AMZNLINUXHVM: ami-0e4a253fb5f082688
      "Artifactory721": ami-0eb86b82de93a34fb
      "Artifactory755": ami-0eb86b82de93a34fb # TODO: Get correct ami
      "Jcr721": ami-047275320dc0101df
    ap-south-1:
      AMZNLINUXHVM: ami-01e074f40dfb9999d
      "Artifactory721": ami-01b828aa6cc99a322
      "Artifactory755": ami-01b828aa6cc99a322 # TODO: Get correct ami
      "Jcr721": ami-003e20ccb4b8b1efc
    ap-southeast-1:
      AMZNLINUXHVM: ami-0d9233e8ce73df7b2
      "Artifactory721": ami-04a94cc4dc0d08c98
      "Artifactory755": ami-04a94cc4dc0d08c98 # TODO: Get correct ami
      "Jcr721": ami-016d81f9a055d84f7
    ap-southeast-2:
      AMZNLINUXHVM: ami-0c91f97cadcc8499e
      "Artifactory721": ami-030871aa8d1f0689e
      "Artifactory755": ami-030871aa8d1f0689e # TODO: Get correct ami
      "Jcr721": ami-0a257f38f4e17b489
    ca-central-1:
      AMZNLINUXHVM: ami-003a0ba7ea76b2785
      "Artifactory721": ami-0148cebea7bea4aaf
      "Artifactory755": ami-0148cebea7bea4aaf # TODO: Get correct ami
      "Jcr721": ami-0366fde97d0c9c63c
    eu-central-1:
      AMZNLINUXHVM: ami-0ab838eeee7f316eb
      "Artifactory721": ami-07961f7c210143a42
      "Artifactory755": ami-07961f7c210143a42 # TODO: Get correct ami
      "Jcr721": ami-025ce18f43dbbee65
    eu-west-1:
      AMZNLINUXHVM: ami-071f4ce599deff521
      "Artifactory721": ami-0171b8d46941b4ca1
      "Artifactory755": ami-0171b8d46941b4ca1 # TODO: Get correct ami
      "Jcr721": ami-0a0c02357d264c397
    sa-east-1:
      AMZNLINUXHVM: ami-04b202bf877b5027b
      "Artifactory721": ami-0596f196b273bb8a6
      "Artifactory755": ami-0596f196b273bb8a6 # TODO: Get correct ami
      "Jcr721": ami-0f5f29385fc7cf6a9
    us-east-1:
      AMZNLINUXHVM: ami-09d069a04349dc3cb
      "Artifactory700": ami-06baee01fb2ef01d2
      "Artifactory702": ami-085b1acc8e8b5b039
      "Artifactory721": ami-0d4d4252cdc2b6f11
      "Artifactory755": ami-07c0a3d7663fcafb9  # TODO: Get correct ami
      "Artifactory773": ami-0e1639df4df532641  # partnership account + seller account
      "Artifactory7102": ami-0d3aaf4303a264d04 # seller account (shared with partnership account)
      "Jcr720": ami-05aa02eddf5f692b7
      "Jcr721": ami-04fed5fc210272dfe
      "Jcr7102": ami-0508370f82ef2e50d
      "Artifactory7112": ami-06347e9dbfce687da # seller account (shared with partnership account)
      "Jcr7112": ami-0a3b81d0aa82189e2 # seller account (shared with partnership account)
    us-east-2:
      AMZNLINUXHVM: ami-0d542ef84ec55d71c
      "Artifactory721": ami-0a913af05ccdaa522
      "Artifactory755": ami-05071c07a672ddf54 # TODO: Get correct ami - using ami generated by myself
      "Jcr721": ami-0d50790b8fb747584
      "Artifactory7112": ami-0f3dcf9fd88a904bc # seller account (shared with partnership account)
      "Jcr7112": ami-0336bdc0bc6e84abd # seller account (shared with partnership account)
    us-west-1:
      AMZNLINUXHVM: ami-04bc3da8f14823e88
      "Artifactory721": ami-068cd684b4d3a3a86
      "Artifactory755": ami-068cd684b4d3a3a86 # TODO: Get correct ami
      "Jcr721": ami-0e1cef33ea2778bd5
      "Artifactory7112": ami-0882ea734a2fa8b73 # seller account (shared with partnership account)
      "Jcr7112": ami-0210d128df9b0bc6a # seller account (shared with partnership account)
    us-west-2:
      AMZNLINUXHVM: ami-01460aa81365561fe
      "700": ami-000937e944ea194bf
      "Artifactory721": ami-0c132dd3640519a35
      "Artifactory755": ami-0007155f7b7de9386 # TODO: Get correct ami
      "Artifactory773": ami-0a1b8c5bd6ea279b0  # partnership account + seller account
      "Jcr721": ami-083542bb4f8afa3db
      "Artifactory7112": ami-0474ab36192013bbd # seller account (shared with partnership account)
      "Jcr7112": ami-0f6670c5db60d15b0 # seller account (shared with partnership account)
    us-gov-east-1:
      AMZNLINUX2: ami-7c2bc80d
      "Artifactory755": ami-0732b9134b39caf5c
      "Artifactory7102": ami-0f5ce3b2c087a8098
      "Artifactory7112":  ami-0bd6c2a94850b75f0
    us-gov-west-1:
      AMZNLINUX2: ami-a03768c1
      "Artifactory755": ami-0b9d3e9ee5ffdc491
  ArtifactoryProductMap:
    JFrog-Container-Registry:
      "720": "Jcr720"
      "721": "Jcr721"
      "743": "Jcr743"
      "7102": "Jcr7102"
      "7112": "Jcr7112"
      product: "jcr"
    JFrog-Artifactory-Pro:
      "700": "Artifactory700"
      "702": "Artifactory702"
      "721": "Artifactory721"
      "755": "Artifactory755"
      "773": "Artifactory773"
      "7102": "Artifactory7102"
      "7112": "Artifactory7112"
      product: "artifactory"
Resources:
  ArtifactoryScalingGroup:
    Type: 'AWS::AutoScaling::AutoScalingGroup'
    Properties:
      LaunchConfigurationName: !Ref ArtifactoryLaunchConfiguration
      VPCZoneIdentifier:
        - !Ref PrivateSubnet1Id
        - !Ref PrivateSubnet2Id
      MinSize: !Ref MinScalingNodes
      MaxSize: !Ref MaxScalingNodes
      Cooldown: '300'
      DesiredCapacity: !Ref MinScalingNodes
      TargetGroupARNs:
        - !Ref TargetGroupARN
        - !Ref SSLTargetGroupARN
        - !Ref InternalTargetGroupARN
      HealthCheckType: ELB
      HealthCheckGracePeriod: 900
      Tags:
        - Key: Name
          Value: !Ref DeploymentTag
          PropagateAtLaunch: true
    CreationPolicy:
      ResourceSignal:
        Count: 1
        Timeout: PT30M

  ArtifactoryLaunchConfiguration:
    Type: 'AWS::AutoScaling::LaunchConfiguration'
    Metadata:
      'AWS::CloudFormation::Authentication':
        S3AccessCreds:
          type: S3
          roleName:
            - !Ref HostRole  # !Ref ArtifactoryHostRole
          buckets:
            - !Ref QsS3BucketName
      'AWS::CloudFormation::Init':
        configSets:
          artifactory_install:
            - "config-artifactory-master"
            - "secure-artifactory"
        config-artifactory-master:
          files:
            /root/.jfrog_ami/artifactory.yml:
              content: !Sub
                - |
                  # Base install for Artifactory
                  - import_playbook: site-artifactory.yml
                    vars:
                      artifactory_license1: ${ArtifactoryLicense1}
                      artifactory_license2: ${ArtifactoryLicense2}
                      artifactory_license3: ${ArtifactoryLicense3}
                      artifactory_license4: ${ArtifactoryLicense4}
                      artifactory_license5: ${ArtifactoryLicense5}
                      artifactory_license6: ${ArtifactoryLicense6}
                      artifactory_product: ${product}
                      artifactory_flavour: "{{ 'pro' if '${product}' == 'artifactory' else 'jcr' if '${product}' == 'jcr' }}"
                      artifactory_server_name: ${ArtifactoryServerName}
                      server_name: ${ArtifactoryServerName}.${CertificateDomain}
                      s3_region: ${AWS::Region}
                      s3_access_key: ${ArtifactoryIamAcessKey}
                      s3_access_secret_key: ${SecretAccessKey}
                      s3_bucket: ${ArtifactoryS3Bucket}
                      certificate: ${Certificate}
                      certificate_key: ${CertificateKey}
                      certificate_domain: ${CertificateDomain}
                      enable_ssl: ${EnableSSL}
                      ssl_dir: /etc/pki/tls/certs
                      db_type: ${DatabaseType}
                      db_driver: ${DatabaseDriver}
                      db_url: ${DatabaseUrl}
                      db_user: ${DatabaseUser}
                      db_password: ${DatabasePassword}
                      # db_download_url: https://jdbc.postgresql.org/download/postgresql-42.2.12.jar
                      art_primary: ${ArtifactoryPrimary}
                      master_key: ${MasterKey}
                      join_key: ${MasterKey}
                      extra_java_opts: ${ExtraJavaOptions}
                      artifactory_version: ${ArtifactoryVersion}
                      artifactory_keystore:
                        path: /opt/jfrog/artifactory/app/third-party/java/lib/security/cacerts
                        default_password: changeit
                        new_keystore_pass: ${KeystorePassword}
                      artifactory_java_db_drivers:
                        - name: ${DatabasePlugin}
                          url: ${DatabasePluginUrl}
                          owner: artifactory
                          group: artifactory
                - {
                  product: !FindInMap [ArtifactoryProductMap, !Ref ArtifactoryProduct, product]
                }
              mode: "0400"
            /root/.vault_pass.txt:
              content: !Sub |
                ${AnsibleVaultPass}
              mode: "0400"
            /root/.secureit.sh:
              content:
                ansible-vault encrypt /root/.jfrog_ami/artifactory.yml --vault-id /root/.vault_pass.txt
              mode: "0770"
        secure-artifactory:
          commands:
            'secure ansible playbook':
              command: '/root/.secureit.sh'
              ignoreErrors: 'false'
    Properties:
      AssociatePublicIpAddress: false
      KeyName: !Ref KeyPairName
      IamInstanceProfile: !Ref HostProfile
      ImageId: !FindInMap
        - AWSAMIRegionMap
        - !Ref 'AWS::Region'
        - !FindInMap
          - ArtifactoryProductMap
          - !Ref ArtifactoryProduct
          - !Ref AmiId
      SecurityGroups:
        - !Ref SecurityGroups
      InstanceType: !Ref InstanceType
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            VolumeSize: !Ref VolumeSize
            VolumeType: gp2
            DeleteOnTermination: true
      UserData:
        'Fn::Base64':
          !Sub |
            #!/bin/bash -x

            #CFN Functions

            function cfn_fail

            {

            cfn-signal -e 1 --stack ${AWS::StackName} --region ${AWS::Region} --resource ArtifactoryScalingGroup

            exit 1

            }

            function cfn_success

            {

            cfn-signal -e 0 --stack ${AWS::StackName} --region ${AWS::Region} --resource ArtifactoryScalingGroup

            exit 0

            }

            S3URI=${QsS3Uri}

            # yum install -y git

            echo $PATH

            PATH=/opt/aws/bin:$PATH

            echo $PATH
            echo \'[Cloning: Load QuickStart Common Utils]\'

            # git clone https://github.com/aws-quickstart/quickstart-linux-utilities.git

            source /quickstart-linux-utilities/quickstart-cfn-tools.source

            echo \'[Loaded: Load QuickStart Common Utils]\'

            echo \'[Update Operating System]\'

            qs_update-os || qs_err

            qs_bootstrap_pip || qs_err

            qs_aws-cfn-bootstrap || qs_err

            source ~/venv/bin/activate &> /var/log/userdata.activate_venv.log || qs_err " activate venv failed "

            # CentOS cloned virtual machines do not create a new machine id
            # https://www.thegeekdiary.com/centos-rhel-7-how-to-change-the-machine-id/
            rm -f /etc/machine-id
            systemd-machine-id-setup

            # mkdir ~/.artifactory_ansible

            # aws s3 --region ${AWS::Region} sync s3://${QsS3BucketName}/${QsS3KeyPrefix}cloudInstallerScripts/ ~/.artifactory_ansible/

            cfn-init -v --stack ${AWS::StackName} --resource ArtifactoryLaunchConfiguration --configsets artifactory_install --region ${AWS::Region} || cfn_fail

            export ANSIBLE_VAULT_PASSWORD_FILE="/root/.vault_pass.txt"

            setsebool httpd_can_network_connect 1 -P

            ansible-playbook /root/.jfrog_ami/artifactory.yml || qs_err " ansible execution failed "

            rm -rf /root/.secureit.sh

            [ $(qs_status) == 0 ] && cfn_success || cfn_fail