AWSTemplateFormatVersion: '2010-09-09' Description: 'JFrog Product AMI creation into an existing VPC (qs-xxx)' Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: Security configuration Parameters: - KeyPairName - RemoteAccessCidr - Label: default: Network Configuration Parameters: - VpcId - PublicSubnet1Id - Label: default: JFrog Product AMI info Parameters: - InstanceType - ArtifactoryVersion - Label: default: AWS Quick Start Configuration Parameters: - QsS3BucketName - QsS3KeyPrefix - QsS3BucketRegion ParameterLabels: KeyPairName: default: SSH key name RemoteAccessCidr: default: Remote access CIDR VpcId: default: VPC ID PublicSubnet1Id: default: Public subnet 1 ID InstanceType: default: EC2 instance type ArtifactoryVersion: default: Artifactory version QsS3BucketName: default: Quick Start S3 bucket name QsS3KeyPrefix: default: Quick Start S3 key prefix QsS3BucketRegion: default: Quick Start S3 bucket region Parameters: KeyPairName: Description: The name of an existing public/private key pair, which allows you to securely connect to your instance after it launches. Type: AWS::EC2::KeyPair::KeyName RemoteAccessCidr: Description: The remote CIDR range for allowing SSH into the Bastion instance. 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 VpcId: Description: The ID of your existing VPC (e.g., vpc-0343606e). Type: "AWS::EC2::VPC::Id" PublicSubnet1Id: Description: The ID of the public subnet in Availability Zone 1 in your existing VPC (e.g., subnet-z0376dab). Type: "AWS::EC2::Subnet::Id" ArtifactoryVersion: Description: The version of the Jfrog product line that you want to deploy into an AMI. Please see the release notes to select the version you want to deploy. https://www.jfrog.com/confluence/display/RTF/Release+Notes AllowedPattern: ^(([0-9]|[1-9][0-9])\.){2}([1-9][0-9]|[0-9])(-([a-z][0-9][0-9][0-9]))?$ ConstraintDescription: A version that matches X.X.X per Artifactory releases. Default: 7.15.3 Type: String InstanceType: Description: The EC2 instance type for the AMI. AllowedValues: - m5.xlarge - m5.2xlarge - m5.4xlarge - m5.8xlarge ConstraintDescription: Must contain valid instance type. Default: m5.xlarge Type: String QsS3BucketName: Description: S3 bucket name for the Quick Start assets. This string can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-). AllowedPattern: ^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$ ConstraintDescription: Quick Start bucket name can include numbers, lowercase letters, uppercase 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: The AWS Region where the Quick Start S3 bucket (QSS3BucketName) is hosted. When using your own bucket, you must specify this value. Type: String Mappings: AWSAMIRegionMap: us-west-1: AMI: "ami-098f55b4287a885ba" us-west-2: AMI: "ami-0bc06212a56393ee1" us-east-1: AMI: "ami-0affd4508a5d2481b" us-east-2: AMI: "ami-01e36b7901e884a10" us-gov-east-1: AMI: "ami-00e30c71" us-gov-west-1: AMI: "ami-bbba86da" Conditions: UsingDefaultBucket: !Equals [!Ref QsS3BucketName, 'aws-quickstart'] Resources: JFrogAMIIamRole: Type: AWS::IAM::Role Metadata: cfn-lint: config: ignore_checks: - EIAMPolicyWildcardResource - EIAMPolicyActionWildcard - EIAMPolicyWildcardPrincipal ignore_reasons: - EIAMPolicyWildcardResource: excluding for s3:Get*, s3:Put*, s3:List* Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Principal: Service: - "ec2.amazonaws.com" Action: - "sts:AssumeRole" Path: "/" Policies: - PolicyName: "JFrogAMI-policy" PolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Action: "ec2:Describe*" Resource: "*" - Effect: "Allow" Action: - "s3:GetObject" - "s3:ListObject" - "s3:ListBucket" Resource: "*" JFrogAMIInstanceProfile: Type: AWS::IAM::InstanceProfile Properties: Path: "/" Roles: - Ref: "JFrogAMIIamRole" JFrogAMISecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: AMI Bootstrap Security Group SecurityGroupIngress: - IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: !Ref RemoteAccessCidr VpcId: !Ref VpcId JFrogAMIInstance: Type: AWS::EC2::Instance Metadata: AWS::CloudFormation::Init: configSets: jfrog_ami_setup: - "config-ansible-art-ami" config-ansible-art-ami: files: /root/.jfrog_ami/jfrog-ami-setup.yml: content: !Sub | # Base install for JFrogAMIInstance - import_playbook: artifactory-ami.yml vars: ami_creation: true artifactory_version: ${ArtifactoryVersion} artifactory_ha_enabled: true db_download_url: "https://jdbc.postgresql.org/download/postgresql-42.2.12.jar" db_type: "postgresql" db_driver: "org.postgresql.Driver" artifactory_tar: "https://releases.jfrog.io/artifactory/artifactory-pro/org/artifactory/pro/jfrog-artifactory-pro/${ArtifactoryVersion}/jfrog-artifactory-pro-${ArtifactoryVersion}-linux.tar.gz" product_id: CloudFormation_MP_EC2/1.0.0 mode: "0400" Properties: KeyName: !Ref KeyPairName ImageId: !FindInMap - AWSAMIRegionMap - !Ref AWS::Region - AMI IamInstanceProfile: !Ref JFrogAMIInstanceProfile InstanceType: !Ref InstanceType NetworkInterfaces: - AssociatePublicIpAddress: True DeviceIndex: "0" GroupSet: - !Ref "JFrogAMISecurityGroup" SubnetId: !Ref "PublicSubnet1Id" UserData: Fn::Base64: !Sub - | #!/bin/bash -x #CFN Functions function cfn_fail { cfn-signal -e 1 --stack ${AWS::StackName} --region ${AWS::Region} --resource JFrogAMIInstance exit 1 } function cfn_success { cfn-signal -e 0 --stack ${AWS::StackName} --region ${AWS::Region} --resource JFrogAMIInstance exit 0 } S3URI=https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QsS3KeyPrefix} # Update OS yum update -y # Install git, policycoreutils python yum install -y git policycoreutils-python jq yum update --security -y 2>&1 | tee /var/log/userdata.yum_security_update.log yum install -y python3 libselinux-python3 echo $PATH PATH=/opt/aws/bin:$PATH echo $PATH # Create virtual env and activate python3 -m venv ~/venv --system-site-packages source ~/venv/bin/activate pip install --upgrade pip pip install wheel # Install Cloudformation helper scripts pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz 2>&1 | tee /var/log/userdata.aws_cfn_bootstrap_install.log cfn-init -v --stack ${AWS::StackName} --resource JFrogAMIInstance --configsets jfrog_ami_setup --region ${AWS::Region} || cfn_fail pip install awscli &> /var/log/userdata.awscli_install.log || cfn_fail pip install ansible &> /var/log/userdata.ansible_install.log || cfn_fail mkdir -p ~/.jfrog_ami aws s3 --region ${AWS::Region} sync s3://${QsS3BucketName}/${QsS3KeyPrefix}cloudInstallerScripts/ ~/.jfrog_ami/ setsebool httpd_can_network_connect 1 -P ansible-playbook /root/.jfrog_ami/jfrog-ami-setup.yml 2>&1 | tee /var/log/jfrog-ami.log || cfn_fail cfn_success &> /var/log/cfn_success.log || cfn_fail - S3Bucket: !If [UsingDefaultBucket, !Sub '{QsS3BucketName}-${AWS::Region}', !Ref 'QsS3BucketName'] S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref 'QsS3BucketRegion'] Tags: - Key: Name Value: !Sub ${AWS::StackName}-jfrog-artifactory-pro-${ArtifactoryVersion}