diff --git a/CloudFormation/README.md b/CloudFormation/README.md new file mode 100644 index 0000000..5b85ff7 --- /dev/null +++ b/CloudFormation/README.md @@ -0,0 +1,71 @@ +# CloudFormation Template For Artifactory Enterprise + +### Steps to Deploy Artifactory Enterprise using CloudFormation template + +1. Go to AWS Console and Select CloudFormation. Then click on Create Stack. + You will see following window. +![screenshot](images/1.png) + +2. Upload Artifactory-enterprise.json (Artifactory Enterprise template) and click next. +![screenshot](images/2.png) + +3. Provide required information like stack name, DBAllocatedStorage, DBInstanceClass, DBName, DBPassword, + DBUser, InstanceType, InstanceStorage, MasterKey, ArtifactoryVersion, KeyName, ArtifactoryLicense1-5, MultiAZDatabase, SSHLocation, Certificate, CertificateKey, SecondaryNodeCount. Then click next. +![screenshot](images/3.png) + +4. Mark on checkbox to allow CloudFormation to create IAM user for Artifactory to access S3 bucket. +![screenshot](images/4.png) + +5. Once Stack in deployed you will see Artifactory Load Balancer URL in output as showed in screenshot. +![screenshot](images/5.png) + +6. Open Artifactory URL and you will be able to see Artifactory UI. +![screenshot](images/6.png) + +7. Let's make sure that Artifactory is running in High Availability mode. Go to Admin -> High Availability in Artifactory UI to see this table. +![screenshot](images/8.png) + +8. Now let's add 2 more nodes to Artifactory Enterprise cluster. Go to CloudFormation UI in AWS console and select newly deployed Artifactory Enterprise Stack. + Click on Action -> Update Stack. +![screenshot](images/9.png) + +9. Increase SecondaryNodeCount from 0 to 2. Then update the Stack. +![screenshot](images/10.png) + +10. It will take few minutes to update stack. +![screenshot](images/11.png) + +11. Once Stack is updated. +![screenshot](images/12.png) + +12. You will be able to see 3 nodes in High Availability table in Artifactory UI as part of Enterprise cluster. +![screenshot](images/13.png) + +### Note: +1. This template only supports Artifactory version 5.8.x and above. +2. Turn off daily backups. Read Documentation provided [here](https://www.jfrog.com/confluence/display/RTF/Managing+Backups) +3. Use SSL Certificate with valid wild card to you artifactory as docker registry with subdomain method. + +### Steps to setup Artifactory as secure docker registry +considering you have SSL certificate for `*.jfrog.team` +1. Pass your SSL Certificate in parameter `Certificate` as string +2. Pass your SSL Certificate Key in parameter `CertificateKey` as string +3. Set `CertificateDomain` as `jfrog.team` +4. Set `ArtifactoryServerName` as `artifactory` if you want to access artifactory with `https://artifactory.jfrog.team` +5. Create Rout53 with entry `artifactory.jfrog.team` pointing to ELB value provided as output in CloudFormation Stack. +6. Create Rout53 with entry `*.jfrog.team` pointing to ELB value provided as output in CloudFormation Stack. +7. If you have virtual docker registry with name `docker-virtual` in artifactory. You can access it via `docker-virtual.jfrog.team` + e.g ```docker pull docker-virtual.jfrog.team/nginx``` + +### Steps to upgrade Artifactory Version + +1. Go to AWS Console and Select CloudFormation Artifactory Stack you want to upgrade. Then click on Update Stack. + +2. Change Artifactory version in parameters from old version to version you want to deploy. + for e.g. 5.8.1 to 5.8.2 + + ![screenshot](images/14.png) + +3. You will see instances will get upgraded one by one. Depending on your cluster size it will take 20-30 minutes to update stack. + +![screenshot](images/15.png) \ No newline at end of file diff --git a/CloudFormation/artifactory-enterprise.json b/CloudFormation/artifactory-enterprise.json new file mode 100644 index 0000000..a15ba84 --- /dev/null +++ b/CloudFormation/artifactory-enterprise.json @@ -0,0 +1,1343 @@ +{ + "AWSTemplateFormatVersion" : "2010-09-09", + + "Description" : "AWS CloudFormation Template to setup Artifactory Enterprise.", + + "Parameters" : { + + "InstanceType" : { + "Description" : "Artifactory EC2 instance type", + "Type" : "String", + "Default" : "m4.xlarge", + "AllowedValues" : [ "t1.micro","m1.small","m1.medium","m1.large","m1.xlarge","m2.xlarge","m2.2xlarge","m2.4xlarge","m3.xlarge","m3.2xlarge", "m4.xlarge", "c1.medium","c1.xlarge","cc1.4xlarge","cc2.8xlarge","cg1.4xlarge"], + "ConstraintDescription" : "must be a valid EC2 instance type." + }, + + "ExtraJavaOptions":{ + "Description": "Setting Java Memory Parameters for Artifactory", + "Default" : "-server -Xms2g -Xmx14g -Xss256k -XX:+UseG1GC -XX:OnOutOfMemoryError=\\\\\\\"kill -9 %p\\\\\\\"", + "Type" : "String" + }, + + "InstanceStorage":{ + "Description": "Artifactory instances storage size in (Gb)", + "Type": "Number", + "Default" : "250", + "MinValue": "250", + "ConstraintDescription" : "must be more then 250 Gb." + }, + + "SecondaryNodeCount": { + "Description" : "Number of Artifactory Secondary instances to launch", + "Type" : "Number", + "Default" : "0", + "MinValue" : "0", + "MaxValue": "9" + }, + + "KeyName": { + "Description" : "Name of an existing EC2 KeyPair to enable SSH access to the instances", + "Type": "AWS::EC2::KeyPair::KeyName", + "ConstraintDescription" : "must be the name of an existing EC2 KeyPair." + }, + + "MasterKey": { + "NoEcho": "true", + "Description" : "Master key for Artifactory cluster. Generate master.key using command '$openssl rand -hex 16'", + "Type": "String", + "MinLength": "1", + "MaxLength": "64", + "AllowedPattern" : "[a-zA-Z0-9][a-zA-Z0-9]*", + "Default": "1ce2be4490ca2c662cb79636cf9b7b8e" + }, + + "ArtifactoryVersion": { + "Description": "Artifactory version to deploy", + "Type": "String", + "Default": "5.8.1" + }, + + "ArtifactoryLicense1": { + "Description": "Artifactory Enterprise License. Providing one license is mandatory", + "Type": "String" + }, + + "ArtifactoryLicense2": { + "Description": "Artifactory Enterprise License", + "Type": "String" + }, + + "ArtifactoryLicense3": { + "Description": "Artifactory Enterprise License", + "Type": "String" + }, + + "ArtifactoryLicense4": { + "Description": "Artifactory Enterprise License", + "Type": "String" + }, + + "ArtifactoryLicense5": { + "Description": "Artifactory Enterprise License", + "Type": "String" + }, + + "Certificate": { + "Description": "To use Artifactory as docker registry you need to provide wild card valid Certificate. Provide your SSL Certificate.", + "Type": "String", + "Default": "-----BEGIN CERTIFICATE----- MIIFhzCCA2+gAwIBAgIJALC4r5BQWZE4MA0GCSqGSIb3DQEBCwUAMFoxCzAJBgNV BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRMwEQYDVQQHDApTYW50YUNsYXJh MQswCQYDVQQKDAJJVDEUMBIGA1UEAwwLKi5sb2NhbGhvc3QwHhcNMTgwMTE3MTk0 NjI4WhcNMTkwMTA4MTk0NjI4WjBaMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2Fs aWZvcm5pYTETMBEGA1UEBwwKU2FudGFDbGFyYTELMAkGA1UECgwCSVQxFDASBgNV BAMMCyoubG9jYWxob3N0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA 7KfOWDQlov8cMa8r/lcJqiWZaH9myQC74Vbe0HXsntQbcvljkjG2P7ebm5dd9Bzc sauNOJpbKf5AhFK1iwJUAkciGc1LR4k8wfWmQM3NPS8hrqrtH20zqNpdFRpNYjja JofwccPNm030GhhZkZ95TpruvmswMDwspl3jfqdcc/eiQsHcKyGnV2a+UAeoqe7J mHhmhRy1MLqAjF5U1GrUYUONA+22iRDJb4c9B91QoWvsnXpdA9NKV/mmA3/rIdx6 Ld2IPRdrIw2K5sAnXsh3bx2oCSvSfussf0x+4XDrnsaHVfjwvfNL8ECOuac2Oi/E WOp9528gOohpFAuwEt63Vl5p8/CC9m0HJDTZBKm2l5eD1kdPIj4PvP9Sn9CxGXKQ E1bxWoFxGX8EyRW0b0NK31N7b8JPZ1SoFNiB5amOMNLvR26a7cQrKumTuJeYK9Ja JaxhMXM7R0DA0Ev8ZG2xmyCygox+1KPSmJOIEpT70BFbj3rKLNqP22ET+zvPuh+2 DdgyrpHFeYkGWjMbWPjK7wJsD2zM8ccoJQfepPz8I4rT0JfrKAQgCGuGOggneaNJ KTVGNOFbj5AXdZ/Q+GvNommyRdq4J7EnqY6L+P25fo5qZ6UZ/iS0tPcvxgn0Fdhs pUPbQyQIDZyxZd3Q1lUIE38ol8P66mS2zbzf8EeOCoUCAwEAAaNQME4wHQYDVR0O BBYEFETAQM/5P7XJ8kevHFj6BPndQOFaMB8GA1UdIwQYMBaAFETAQM/5P7XJ8kev HFj6BPndQOFaMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIBAJ1TepKv LWYhFmVQcgZwZf/qt1a1cohzJSm6da9RCnnAWC7WC/U117bgSomtrH1v0OysHFhB zBBUeBqI7+OmzAX8dhj+roKkcnFUM/IwlK1eueIIA//CWvEf/o0XExilVS2yCc9d PTpOQBXwk9QinxK36kHdBiGxa7dW0JPnOEEmuMgGORKeLy4J6Ik8iSeFY1SZVcOI +6WWvoKciPlmIeccC+6YVmkeBwhP2o5r5w/UAaO2hSnGvmm4UIj/VJv4VQu7xTUp cIfFz5NtIr80DbqcyPiEMS2ETJ4L/kO4MS5FfeEXyQuXCzmiIDVY6tE3C7+kZmK4 JzPLuWm9ndQoyQySOGfQqvlUR1+YxUdvmu3LrOS5dOA354Q36wHa4wEGUoHU/7GV fYQmmmDSDaNSpXW5PFey6scFyDBS/yYJ0H9EjYb/11HeWYj8Yv5xTWj8nhzJONC8 D6Y5ydlU4PifM2pOf88pTYpmogNwLJWXbql5I9cvMa8APo4yLVqcISU5ynsvFke+ Non+T0mHpJai/hrA9NK+s6EGC1dAX58jy61h6FhOPI1d4s/mov/KMa2t3SfZp5SF 81aR6dHvO56teiK5M1xMkrqG75zh3TMFJJLRFe9XxeB4JeN76URB3mgADOUqkBxd ibSgVqfKwOw4IujEcqMUc5mqSnbLY1Dv+oby -----END CERTIFICATE-----" + }, + + "CertificateKey": { + "Description": "Provide your SSL Certificate key", + "Type": "String", + "Default": "-----BEGIN PRIVATE KEY----- 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 S+j1+iUKGGhwVmhqh75q5do3+VF3XlAh -----END PRIVATE KEY-----" + }, + + "CertificateDomain":{ + "Description": "Provide your Certificate Domain Name. For e.g jfrog.team for certificate with *.jfrog.team", + "Type": "String", + "Default": "artifactory" + }, + + "ArtifactoryServerName":{ + "Description": "Provide artifactory server name to be used in Nginx. e.g artifactory for artifactory.jfrog.team", + "Type": "String", + "Default": "artifactory" + }, + + "DBName": { + "Default": "artdb", + "Description" : "MySQL database name", + "Type": "String", + "MinLength": "1", + "MaxLength": "64", + "AllowedPattern" : "[a-zA-Z][a-zA-Z0-9]*", + "ConstraintDescription" : "must begin with a letter and contain only alphanumeric characters." + }, + + "DBUser": { + "NoEcho": "true", + "Default": "artifactory", + "Description" : "Username for MySQL database access", + "Type": "String", + "MinLength": "1", + "MaxLength": "16", + "AllowedPattern" : "[a-zA-Z][a-zA-Z0-9]*", + "ConstraintDescription" : "must begin with a letter and contain only alphanumeric characters." + }, + + "DBPassword": { + "NoEcho": "true", + "Default": "password", + "Description" : "Password for MySQL database access", + "Type": "String", + "MinLength": "8", + "MaxLength": "41", + "AllowedPattern" : "[a-zA-Z0-9]*", + "ConstraintDescription" : "must contain only alphanumeric characters." + }, + + "DBAllocatedStorage": { + "Default": "5", + "Description" : "The size of the database (Gb)", + "Type": "Number", + "MinValue": "5", + "MaxValue": "1024", + "ConstraintDescription" : "must be between 5 and 1024Gb." + }, + + "DBInstanceClass": { + "Description" : "The database instance type", + "Type": "String", + "Default": "db.t2.small", + "AllowedValues" : [ "db.t1.micro", "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.r3.large", "db.r3.xlarge", "db.r3.2xlarge", "db.r3.4xlarge", "db.r3.8xlarge", "db.m2.xlarge", "db.m2.2xlarge", "db.m2.4xlarge", "db.cr1.8xlarge", "db.t2.micro", "db.t2.small", "db.t2.medium", "db.t2.large"], + "ConstraintDescription" : "must select a valid database instance type." + }, + + "MultiAZDatabase": { + "Default": "false", + "Description" : "Create a Multi-AZ MySQL Amazon RDS database instance", + "Type": "String", + "AllowedValues" : [ "true", "false" ], + "ConstraintDescription" : "must be either true or false." + }, + + "SSHLocation" : { + "Description" : " The IP address range that can be used to SSH to the EC2 instances", + "Type": "String", + "MinLength": "9", + "MaxLength": "18", + "Default": "0.0.0.0/0", + "AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})", + "ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x." + } + }, + + "Mappings" : { + "AWSInstanceType2Arch" : { + "t1.micro" : { "Arch" : "PV64" }, + "t2.nano" : { "Arch" : "HVM64" }, + "t2.micro" : { "Arch" : "HVM64" }, + "t2.small" : { "Arch" : "HVM64" }, + "t2.medium" : { "Arch" : "HVM64" }, + "t2.large" : { "Arch" : "HVM64" }, + "m1.small" : { "Arch" : "PV64" }, + "m1.medium" : { "Arch" : "PV64" }, + "m1.large" : { "Arch" : "PV64" }, + "m1.xlarge" : { "Arch" : "PV64" }, + "m2.xlarge" : { "Arch" : "PV64" }, + "m2.2xlarge" : { "Arch" : "PV64" }, + "m2.4xlarge" : { "Arch" : "PV64" }, + "m3.medium" : { "Arch" : "HVM64" }, + "m3.large" : { "Arch" : "HVM64" }, + "m3.xlarge" : { "Arch" : "HVM64" }, + "m3.2xlarge" : { "Arch" : "HVM64" }, + "m4.large" : { "Arch" : "HVM64" }, + "m4.xlarge" : { "Arch" : "HVM64" }, + "m4.2xlarge" : { "Arch" : "HVM64" }, + "m4.4xlarge" : { "Arch" : "HVM64" }, + "m4.10xlarge" : { "Arch" : "HVM64" }, + "c1.medium" : { "Arch" : "PV64" }, + "c1.xlarge" : { "Arch" : "PV64" }, + "c3.large" : { "Arch" : "HVM64" }, + "c3.xlarge" : { "Arch" : "HVM64" }, + "c3.2xlarge" : { "Arch" : "HVM64" }, + "c3.4xlarge" : { "Arch" : "HVM64" }, + "c3.8xlarge" : { "Arch" : "HVM64" }, + "c4.large" : { "Arch" : "HVM64" }, + "c4.xlarge" : { "Arch" : "HVM64" }, + "c4.2xlarge" : { "Arch" : "HVM64" }, + "c4.4xlarge" : { "Arch" : "HVM64" }, + "c4.8xlarge" : { "Arch" : "HVM64" }, + "g2.2xlarge" : { "Arch" : "HVMG2" }, + "g2.8xlarge" : { "Arch" : "HVMG2" }, + "r3.large" : { "Arch" : "HVM64" }, + "r3.xlarge" : { "Arch" : "HVM64" }, + "r3.2xlarge" : { "Arch" : "HVM64" }, + "r3.4xlarge" : { "Arch" : "HVM64" }, + "r3.8xlarge" : { "Arch" : "HVM64" }, + "i2.xlarge" : { "Arch" : "HVM64" }, + "i2.2xlarge" : { "Arch" : "HVM64" }, + "i2.4xlarge" : { "Arch" : "HVM64" }, + "i2.8xlarge" : { "Arch" : "HVM64" }, + "d2.xlarge" : { "Arch" : "HVM64" }, + "d2.2xlarge" : { "Arch" : "HVM64" }, + "d2.4xlarge" : { "Arch" : "HVM64" }, + "d2.8xlarge" : { "Arch" : "HVM64" }, + "hi1.4xlarge" : { "Arch" : "HVM64" }, + "hs1.8xlarge" : { "Arch" : "HVM64" }, + "cr1.8xlarge" : { "Arch" : "HVM64" }, + "cc2.8xlarge" : { "Arch" : "HVM64" } + }, + + "AWSRegionArch2AMI" : { + "us-east-1" : {"PV64" : "ami-2a69aa47", "HVM64" : "ami-6869aa05", "HVMG2" : "ami-61e27177"}, + "us-west-2" : {"PV64" : "ami-7f77b31f", "HVM64" : "ami-7172b611", "HVMG2" : "ami-60aa3700"}, + "us-west-1" : {"PV64" : "ami-a2490dc2", "HVM64" : "ami-31490d51", "HVMG2" : "ami-4b694d2b"}, + "eu-west-1" : {"PV64" : "ami-4cdd453f", "HVM64" : "ami-f9dd458a", "HVMG2" : "ami-2955524f"}, + "eu-west-2" : {"PV64" : "NOT_SUPPORTED", "HVM64" : "ami-886369ec", "HVMG2" : "NOT_SUPPORTED"}, + "eu-central-1" : {"PV64" : "ami-6527cf0a", "HVM64" : "ami-ea26ce85", "HVMG2" : "ami-81ac71ee"}, + "ap-northeast-1" : {"PV64" : "ami-3e42b65f", "HVM64" : "ami-374db956", "HVMG2" : "ami-46220c21"}, + "ap-northeast-2" : {"PV64" : "NOT_SUPPORTED", "HVM64" : "ami-2b408b45", "HVMG2" : "NOT_SUPPORTED"}, + "ap-southeast-1" : {"PV64" : "ami-df9e4cbc", "HVM64" : "ami-a59b49c6", "HVMG2" : "ami-c212aba1"}, + "ap-southeast-2" : {"PV64" : "ami-63351d00", "HVM64" : "ami-dc361ebf", "HVMG2" : "ami-0ad2db69"}, + "ap-south-1" : {"PV64" : "NOT_SUPPORTED", "HVM64" : "ami-ffbdd790", "HVMG2" : "ami-ca3042a5"}, + "us-east-2" : {"PV64" : "NOT_SUPPORTED", "HVM64" : "ami-f6035893", "HVMG2" : "NOT_SUPPORTED"}, + "ca-central-1" : {"PV64" : "NOT_SUPPORTED", "HVM64" : "ami-730ebd17", "HVMG2" : "NOT_SUPPORTED"}, + "sa-east-1" : {"PV64" : "ami-1ad34676", "HVM64" : "ami-6dd04501", "HVMG2" : "NOT_SUPPORTED"}, + "cn-north-1" : {"PV64" : "ami-77559f1a", "HVM64" : "ami-8e6aa0e3", "HVMG2" : "NOT_SUPPORTED"} + } + }, + + "Resources" : { + + "IAMUser": { + "Type": "AWS::IAM::User" + }, + + "IAMAcessKey": { + "Type": "AWS::IAM::AccessKey", + "Properties": { "UserName": { "Ref": "IAMUser" } } + }, + + "S3Bucket" : { + "Type": "AWS::S3::Bucket", + "Properties": { "AccessControl": "Private"} + }, + + "IAMPolicy": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyName": "S3BucketPermissions", + "PolicyDocument" : { + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "S3BucketPermissions", + "Effect": "Allow", + "Action": ["s3:*"], + "Resource": [ + { "Fn::Join": [ "", [ "arn:aws:s3:::", { "Ref": "S3Bucket" } ] ] }, + { "Fn::Join": [ "", [ "arn:aws:s3:::", { "Ref": "S3Bucket" }, "/*" ] ] } + ] + } + ] + }, + "Users": [ { "Ref": "IAMUser" } ] + } + }, + + "VPC" : { + "Type" : "AWS::EC2::VPC", + "Properties" : { + "CidrBlock" : "10.0.0.0/16", + "Tags" : [ + {"Key" : "Application", "Value" : { "Ref" : "AWS::StackId"} }, + {"Key" : "Network", "Value" : "Public" } + ] + } + }, + + "PublicSubnet1" : { + "Type" : "AWS::EC2::Subnet", + "Properties" : { + "VpcId" : { "Ref" : "VPC" }, + "CidrBlock" : "10.0.1.0/24", + "MapPublicIpOnLaunch" :"true", + "AvailabilityZone" : { + "Fn::Select" : [ "0", { "Fn::GetAZs" : "" } ] + }, + "Tags" : [ + {"Key" : "Application", "Value" : { "Ref" : "AWS::StackId"} }, + {"Key" : "Network", "Value" : "Public" } + ] + } + }, + + "PublicSubnet2" : { + "Type" : "AWS::EC2::Subnet", + "Properties" : { + "VpcId" : { "Ref" : "VPC" }, + "CidrBlock" : "10.0.2.0/24", + "MapPublicIpOnLaunch" :"true", + "AvailabilityZone" : { + "Fn::Select" : [ "1", { "Fn::GetAZs" : "" } ] + }, + "Tags" : [ + {"Key" : "Application", "Value" : { "Ref" : "AWS::StackId"} }, + {"Key" : "Network", "Value" : "Public" } + ] + } + }, + + "InternetGateway" : { + "Type" : "AWS::EC2::InternetGateway", + "Properties" : { + "Tags" : [ + {"Key" : "Application", "Value" : { "Ref" : "AWS::StackId"} }, + {"Key" : "Network", "Value" : "Public" } + ] + } + }, + + "AttachGateway" : { + "Type" : "AWS::EC2::VPCGatewayAttachment", + "Properties" : { + "VpcId" : { "Ref" : "VPC" }, + "InternetGatewayId" : { "Ref" : "InternetGateway" } + } + }, + + "PublicRouteTable" : { + "Type" : "AWS::EC2::RouteTable", + "Properties" : { + "VpcId" : {"Ref" : "VPC"}, + "Tags" : [ + {"Key" : "Application", "Value" : { "Ref" : "AWS::StackId"} }, + {"Key" : "Network", "Value" : "Public" } + ] + } + }, + + "PublicRoute" : { + "Type" : "AWS::EC2::Route", + "DependsOn" : "AttachGateway", + "Properties" : { + "RouteTableId" : { "Ref" : "PublicRouteTable" }, + "DestinationCidrBlock" : "0.0.0.0/0", + "GatewayId" : { "Ref" : "InternetGateway" } + } + }, + + "PublicSubnetRouteTableAssociation1" : { + "Type" : "AWS::EC2::SubnetRouteTableAssociation", + "Properties" : { + "SubnetId" : { "Ref" : "PublicSubnet1" }, + "RouteTableId" : { "Ref" : "PublicRouteTable" } + } + }, + + "PublicSubnetRouteTableAssociation2" : { + "Type" : "AWS::EC2::SubnetRouteTableAssociation", + "Properties" : { + "SubnetId" : { "Ref" : "PublicSubnet2" }, + "RouteTableId" : { "Ref" : "PublicRouteTable" } + } + }, + + + "PublicNetworkAcl" : { + "Type" : "AWS::EC2::NetworkAcl", + "Properties" : { + "VpcId" : {"Ref" : "VPC"}, + "Tags" : [ + {"Key" : "Application", "Value" : { "Ref" : "AWS::StackId"} }, + {"Key" : "Network", "Value" : "Public" } + ] + } + }, + + "InboundHTTPPublicNetworkAclEntry" : { + "Type" : "AWS::EC2::NetworkAclEntry", + "Properties" : { + "NetworkAclId" : {"Ref" : "PublicNetworkAcl"}, + "RuleNumber" : "100", + "Protocol" : "6", + "RuleAction" : "allow", + "Egress" : "false", + "CidrBlock" : "0.0.0.0/0", + "PortRange" : {"From" : "0", "To" : "65535"} + } + }, + + "InboundDynamicPortsPublicNetworkAclEntry" : { + "Type" : "AWS::EC2::NetworkAclEntry", + "Properties" : { + "NetworkAclId" : {"Ref" : "PublicNetworkAcl"}, + "RuleNumber" : "101", + "Protocol" : "6", + "RuleAction" : "allow", + "Egress" : "false", + "CidrBlock" : "0.0.0.0/0", + "PortRange" : {"From" : "0", "To" : "65535"} + } + }, + + "OutboundHTTPPublicNetworkAclEntry" : { + "Type" : "AWS::EC2::NetworkAclEntry", + "Properties" : { + "NetworkAclId" : {"Ref" : "PublicNetworkAcl"}, + "RuleNumber" : "100", + "Protocol" : "6", + "RuleAction" : "allow", + "Egress" : "true", + "CidrBlock" : "0.0.0.0/0", + "PortRange" : {"From" : "0", "To" : "65535"} + } + }, + + "OutBoundDynamicPortPublicNetworkAclEntry" : { + "Type" : "AWS::EC2::NetworkAclEntry", + "Properties" : { + "NetworkAclId" : {"Ref" : "PublicNetworkAcl"}, + "RuleNumber" : "101", + "Protocol" : "6", + "RuleAction" : "allow", + "Egress" : "true", + "CidrBlock" : "0.0.0.0/0", + "PortRange" : {"From" : "0", "To" : "65535"} + } + }, + + "PublicSubnetNetworkAclAssociation1" : { + "Type" : "AWS::EC2::SubnetNetworkAclAssociation", + "Properties" : { + "SubnetId" : { "Ref" : "PublicSubnet1" }, + "NetworkAclId" : { "Ref" : "PublicNetworkAcl" } + } + }, + + "PublicSubnetNetworkAclAssociation2" : { + "Type" : "AWS::EC2::SubnetNetworkAclAssociation", + "Properties" : { + "SubnetId" : { "Ref" : "PublicSubnet2" }, + "NetworkAclId" : { "Ref" : "PublicNetworkAcl" } + } + }, + + "PrivateSubnet" : { + "Type" : "AWS::EC2::Subnet", + "Properties" : { + "VpcId" : { "Ref" : "VPC" }, + "CidrBlock" : "10.0.3.0/24", + "AvailabilityZone" : { + "Fn::Select" : [ "1", { "Fn::GetAZs" : "" } ] + }, + "Tags" : [ + {"Key" : "Application", "Value" : { "Ref" : "AWS::StackId"} }, + {"Key" : "Network", "Value" : "Private" } + ] + } + }, + + "PrivateRouteTable" : { + "Type" : "AWS::EC2::RouteTable", + "Properties" : { + "VpcId" : {"Ref" : "VPC"}, + "Tags" : [ + {"Key" : "Application", "Value" : { "Ref" : "AWS::StackId"} }, + {"Key" : "Network", "Value" : "Private" } + ] + } + }, + + "PrivateSubnetRouteTableAssociation" : { + "Type" : "AWS::EC2::SubnetRouteTableAssociation", + "Properties" : { + "SubnetId" : { "Ref" : "PrivateSubnet" }, + "RouteTableId" : { "Ref" : "PrivateRouteTable" } + } + }, + + "PrivateNetworkAcl" : { + "Type" : "AWS::EC2::NetworkAcl", + "Properties" : { + "VpcId" : {"Ref" : "VPC"}, + "Tags" : [ + {"Key" : "Application", "Value" : { "Ref" : "AWS::StackId"} }, + {"Key" : "Network", "Value" : "Private" } + ] + } + }, + + "InboundPrivateNetworkAclEntry" : { + "Type" : "AWS::EC2::NetworkAclEntry", + "Properties" : { + "NetworkAclId" : {"Ref" : "PrivateNetworkAcl"}, + "RuleNumber" : "100", + "Protocol" : "6", + "RuleAction" : "allow", + "Egress" : "false", + "CidrBlock" : "0.0.0.0/0", + "PortRange" : {"From" : "0", "To" : "65535"} + } + }, + + "OutBoundPrivateNetworkAclEntry" : { + "Type" : "AWS::EC2::NetworkAclEntry", + "Properties" : { + "NetworkAclId" : {"Ref" : "PrivateNetworkAcl"}, + "RuleNumber" : "100", + "Protocol" : "6", + "RuleAction" : "allow", + "Egress" : "true", + "CidrBlock" : "0.0.0.0/0", + "PortRange" : {"From" : "0", "To" : "65535"} + } + }, + + "PrivateSubnetNetworkAclAssociation" : { + "Type" : "AWS::EC2::SubnetNetworkAclAssociation", + "Properties" : { + "SubnetId" : { "Ref" : "PrivateSubnet" }, + "NetworkAclId" : { "Ref" : "PrivateNetworkAcl" } + } + }, + + "ElasticLoadBalancer" : { + "Type" : "AWS::ElasticLoadBalancing::LoadBalancer", + "Properties" : { + "SecurityGroups" : [ { "Ref" : "ArtifactorySecurityGroup" } ], + "Subnets" : [ { "Ref" : "PublicSubnet1" }, { "Ref" : "PublicSubnet2" } ], + "AppCookieStickinessPolicy" : + [ { + "PolicyName" : "HTTPSCookieStickinessPolicy", + "CookieName" : "connect.sid" + } ], + "Listeners" : [ { + "LoadBalancerPort" : "80", + "InstancePort" : "80", + "InstanceProtocol": "HTTP", + "Protocol" : "HTTP" + }, + { + "Protocol": "TCP", + "InstanceProtocol": "TCP", + "LoadBalancerPort": "443", + "InstancePort": "443" + } ], + "HealthCheck" : { + "Target" : { "Fn::Join" : [ "", ["HTTP:80/artifactory/webapp/#/login"]]}, + "HealthyThreshold" : "3", + "UnhealthyThreshold" : "3", + "Interval" : "30", + "Timeout" : "15" + } + } + }, + + "PrimaryGroup" : { + "Type" : "AWS::AutoScaling::AutoScalingGroup", + "Properties" : { + "AvailabilityZones" : [{ "Fn::GetAtt" : [ "PublicSubnet1", "AvailabilityZone" ] },{ "Fn::GetAtt" : [ "PublicSubnet2", "AvailabilityZone" ] }], + "VPCZoneIdentifier" : [{ "Ref" : "PublicSubnet1" }, { "Ref" : "PublicSubnet2" }], + "LaunchConfigurationName" : { "Ref" : "PrimaryLaunchConfig" }, + "MinSize" : "1", + "MaxSize" : "2", + "DesiredCapacity" : "1", + "LoadBalancerNames" : [ { "Ref" : "ElasticLoadBalancer" } ], + "HealthCheckGracePeriod" : "480", + "HealthCheckType" : "ELB" + }, + "UpdatePolicy": { + "AutoScalingRollingUpdate": { + "MinInstancesInService": "0", + "MaxBatchSize": "1", + "PauseTime": "PT7M" + } + } + }, + + "PrimaryLaunchConfig": { + "Type" : "AWS::AutoScaling::LaunchConfiguration", + "Metadata" : { + "Comment1" : "Configure the bootstrap helpers to install the Artifactory Server", + + "AWS::CloudFormation::Init" : { + "config" : { + "packages" : { + "yum" : { + "wget" : [], + "curl" : [] + } + }, + + "files" : { + + "/etc/nginx/nginx.conf" : { + "content" : { "Fn::Join" : ["", [ + "#user nobody;\n", + "worker_processes 1;\n", + "error_log /var/log/nginx/error.log info;\n", + "#pid logs/nginx.pid;\n", + "events {\n", + " worker_connections 1024;\n", + "}\n", + "http {\n", + " include mime.types;\n", + " include /etc/nginx/conf.d/*.conf;\n", + " default_type application/octet-stream;\n", + " log_format main '$remote_addr - $remote_user [$time_local] \"$request\" '\n", + "'$status $body_bytes_sent \"$http_referer\" '\n", + "'\"$http_user_agent\" \"$http_x_forwarded_for\"';\n", + " access_log /var/log/nginx/access.log main;\n", + " sendfile on;\n", + " #tcp_nopush on;\n", + " #keepalive_timeout 0;\n", + " keepalive_timeout 65;\n", + "}\n" + ]]}, + "mode" : "000755", + "owner" : "root", + "group" : "root" + }, + + "/var/opt/jfrog/artifactory/etc/db.properties" : { + "content" : { "Fn::Join" : ["", [ + "type=mysql\n", + "driver=com.mysql.jdbc.Driver\n", + "url=jdbc:mysql://", {"Fn::GetAtt" : ["MySQLDatabase", "Endpoint.Address"]},":3306/", { "Ref" : "DBName" },"?characterEncoding=UTF-8&elideSetAutoCommits=true\n", + "username=", {"Ref" : "DBUser"}, "\n", + "password=", {"Ref" : "DBPassword"}, "\n" + ]]}, + "mode" : "000755", + "owner" : "artifactory", + "group" : "artifactory" + }, + + "/var/opt/jfrog/artifactory/etc/binarystore.xml" : { + "content" : { "Fn::Join" : ["", [ + "\n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + " \n", + "\n", + "\n", + "crossNetworkStrategy\n", + "crossNetworkStrategy\n", + "2\n", + "1\n", + "\n", + "\n", + "\n", + "\n", + " remote\n", + "\n", + "\n", + "\n", + " local\n", + "\n", + "\n", + "\n", + "",{ "Fn::Join": [ "", [ "s3.dualstack.", { "Ref": "AWS::Region" }, ".amazonaws.com" ] ] },"\n", + "", {"Ref" : "IAMAcessKey"}, "\n", + "", { "Fn::GetAtt": [ "IAMAcessKey", "SecretAccessKey" ] }, "\n", + "", { "Ref": "S3Bucket" }, "\n", + "\n", + "\n" + ]]}, + "mode" : "000755", + "owner" : "artifactory", + "group" : "artifactory" + }, + + "/var/opt/jfrog/artifactory/etc/ha-node.properties" : { + "content" : { "Fn::Join" : ["", [ + "node.id=art1\n", + "artifactory.ha.data.dir=/var/opt/jfrog/artifactory/data\n", + "context.url=http://127.0.0.1:8081/artifactory\n", + "membership.port=10001\n", + "hazelcast.interface=172.25.0.3\n", + "primary=true\n" + ]]}, + "mode" : "000755", + "owner" : "artifactory", + "group" : "artifactory" + }, + + "/var/opt/jfrog/artifactory/etc/security/master.key" : { + "content" : { "Fn::Join" : ["", [ + {"Ref" : "MasterKey"} + ]]}, + "mode" : "000755", + "owner" : "artifactory", + "group" : "artifactory" + }, + + "/etc/pki/tls/certs/result.pem" : { + "content" : { "Fn::Join" : ["", [ + {"Ref" : "Certificate"} + ]]}, + "mode" : "000777", + "owner" : "root", + "group" : "root" + }, + + "/etc/pki/tls/private/result.key" : { + "content" : { "Fn::Join" : ["", [ + {"Ref" : "CertificateKey"} + ]]}, + "mode" : "000777", + "owner" : "root", + "group" : "root" + }, + + "/var/opt/jfrog/artifactory/etc/plugins/inactiveServerCleaner.groovy" : { + "content" : { "Fn::Join" : ["", [ + "import org.artifactory.state.ArtifactoryServerState\n", + "import org.artifactory.storage.db.servers.service.ArtifactoryServersCommonService\n", + "import org.artifactory.common.ConstantValues\n", + "import org.slf4j.Logger\n", + "import java.util.concurrent.TimeUnit\n", + + "jobs {\n", + " clean(cron: \"0 0/1 * * * ?\") {\n", + " def artifactoryServersCommonService = ctx.beanForType(ArtifactoryServersCommonService)\n", + " def artifactoryInactiveServerCleaner = new ArtifactoryInactiveServersCleaner(artifactoryServersCommonService, log)\n", + " artifactoryInactiveServerCleaner.cleanInactiveArtifactoryServers()\n", + " }\n", + "}\n", + + "public class ArtifactoryInactiveServersCleaner {\n", + + " private ArtifactoryServersCommonService artifactoryServersCommonService\n", + " private Logger log\n", + + " ArtifactoryInactiveServersCleaner(ArtifactoryServersCommonService artifactoryServersCommonService, Logger log) {\n", + " this.artifactoryServersCommonService = artifactoryServersCommonService\n", + " this.log = log\n", + " }\n", + + " def cleanInactiveArtifactoryServers() {\n", + " List allMembers = artifactoryServersCommonService.getAllArtifactoryServers()\n", + " for (member in allMembers) {\n", + " def heartbeat = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - member.getLastHeartbeat())\n", + " def noheartbeat = heartbeat > ConstantValues.haHeartbeatStaleIntervalSecs.getInt()\n", + " if (member.getServerState() == ArtifactoryServerState.UNAVAILABLE || noheartbeat) {\n", + " log.info \"Running inactive artifactory servers cleaning task, found ${member.serverId} inactive servers to remove\"\n", + " artifactoryServersCommonService.removeServer(member.serverId)\n", + " }\n", + " }\n", + " }\n", + "}\n" + ]]}, + "mode" : "000777", + "owner" : "artifactory", + "group" : "artifactory" + }, + + "/var/opt/jfrog/artifactory/etc/artifactory.cluster.license" : { + "content" : { "Fn::Join" : ["", [ + "", { "Ref" : "ArtifactoryLicense1" }, "\n", + "\n", + "", { "Ref" : "ArtifactoryLicense2" }, "\n", + "\n", + "", { "Ref" : "ArtifactoryLicense3" }, "\n", + "\n", + "", { "Ref" : "ArtifactoryLicense4" }, "\n", + "\n", + "", { "Ref" : "ArtifactoryLicense5" }, "\n" + ]]}, + "mode" : "000755", + "owner" : "artifactory", + "group" : "artifactory" + }, + + "/etc/nginx/conf.d/artifactory.conf" : { + "content" : { "Fn::Join" : ["", [ + "ssl_certificate /etc/pki/tls/certs/cert.pem;\n", + "ssl_certificate_key /etc/pki/tls/private/cert.key;\n", + "ssl_session_cache shared:SSL:1m;\n", + "ssl_prefer_server_ciphers on;\n", + "## server configuration\n", + "server {\n", + " listen 443 ssl;\n", + " listen 80 ;\n", + " server_name ",{ "Ref" : "ArtifactoryServerName" },".",{ "Ref" : "CertificateDomain" }," ~(?.+)\\.",{ "Ref" : "CertificateDomain" },";\n", + " if ($http_x_forwarded_proto = '') {\n", + " set $http_x_forwarded_proto $scheme;\n", + " }\n", + " ## Application specific logs\n", + " ## access_log /var/log/nginx/artifactory-access.log timing;\n", + " ## error_log /var/log/nginx/artifactory-error.log;\n", + " rewrite ^/$ /artifactory/webapp/ redirect;\n", + " rewrite ^/artifactory/?(/webapp)?$ /artifactory/webapp/ redirect;\n", + " rewrite ^/(v1|v2)/(.*) /artifactory/api/docker/$repo/$1/$2;\n", + " chunked_transfer_encoding on;\n", + " client_max_body_size 0;\n", + " location /artifactory/ {\n", + " proxy_read_timeout 900;\n", + " proxy_pass_header Server;\n", + " proxy_cookie_path ~*^/.* /;\n", + " proxy_pass http://127.0.0.1:8081/artifactory/;\n", + " proxy_set_header X-Artifactory-Override-Base-Url $http_x_forwarded_proto://$host:$server_port/artifactory;\n", + " proxy_set_header X-Forwarded-Port $server_port;\n", + " proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;\n", + " proxy_set_header Host $http_host;\n", + " proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n", + " }\n", + "}\n", + "\n" + ]]}, + "mode" : "000755", + "owner" : "root", + "group" : "root" + }, + + "/etc/cfn/cfn-hup.conf" : { + "content" : { "Fn::Join" : ["", [ + "[main]\n", + "stack=", { "Ref" : "AWS::StackId" }, "\n", + "region=", { "Ref" : "AWS::Region" }, "\n" + ]]}, + "mode" : "000400", + "owner" : "root", + "group" : "root" + }, + + "/etc/cfn/hooks.d/cfn-auto-reloader.conf" : { + "content": { "Fn::Join" : ["", [ + "[cfn-auto-reloader-hook]\n", + "triggers=post.update\n", + "path=Resources.PrimaryLaunchConfig.Metadata.AWS::CloudFormation::Init\n", + "action=/opt/aws/bin/cfn-init -v ", + " --stack ", { "Ref" : "AWS::StackName" }, + " --resource PrimaryLaunchConfig ", + " --region ", { "Ref" : "AWS::Region" }, "\n", + "runas=root\n" + ]]} + } + }, + + "commands" : { + "set_artifactory_node_id" : { + "command" : { "Fn::Join" : ["", ["sed -i -e \"s/art1/art-$(date +%s$RANDOM)/\" /var/opt/jfrog/artifactory/etc/ha-node.properties"]]} + }, + "set_artifactory_context" : { + "command" : { "Fn::Join" : ["", ["sed -i -e \"s/127.0.0.1/$(curl http://169.254.169.254/latest/meta-data/public-ipv4)/\" /var/opt/jfrog/artifactory/etc/ha-node.properties"]]} + }, + "set_hazelcast_interface" : { + "command" : { "Fn::Join" : ["", ["sed -i -e \"s/172.25.0.3/$(curl http://169.254.169.254/latest/meta-data/local-ipv4)/\" /var/opt/jfrog/artifactory/etc/ha-node.properties"]]} + }, + "allow_ping_anonymous" : { + "command" : { "Fn::Join" : ["", ["echo \"artifactory.ping.allowUnauthenticated=true\" >> /var/opt/jfrog/artifactory/etc/artifactory.system.properties"]]} + }, + "set_extra_java_options" : { + "command" : { "Fn::Join" : ["", ["echo \"export JAVA_OPTIONS=", "\\\"", { "Ref" : "ExtraJavaOptions" }, "\\\"", "\" >> /var/opt/jfrog/artifactory/etc/default"]]} + }, + "set_permissions" : { + "command" : { "Fn::Join" : ["", ["chown artifactory:artifactory -R /var/opt/jfrog/artifactory/etc/* && chown artifactory:artifactory -R /var/opt/jfrog/artifactory/* && chown artifactory:artifactory -R /var/opt/jfrog/artifactory/etc/security"]]} + }, + "generate_self_signed_cert" : { + "command" : { "Fn::Join" : ["", ["openssl req -nodes -x509 -newkey rsa:4096 -keyout /etc/pki/tls/private/example.key -out /etc/pki/tls/certs/example.pem -days 356 -subj \"/C=US/ST=California/L=SantaClara/O=IT/CN=*.localhost\""]]} + }, + "format_ssl_certificate" : { + "command" : { "Fn::Join" : ["", ["cat /etc/pki/tls/certs/result.pem | sed 's/CERTIFICATE----- /CERTIFICATE-----\\n/g' | sed 's/-----END/\\n-----END/' > temp.pem | mv -f temp.pem /etc/pki/tls/certs/cert.pem"]]} + }, + "format_ssl_certificate_key" : { + "command" : { "Fn::Join" : ["", ["cat /etc/pki/tls/private/result.key | sed 's/KEY----- /KEY-----\\n/g' | sed 's/-----END/\\n-----END/' > temp.key | mv -f temp.key /etc/pki/tls/private/cert.key"]]} + } + }, + + "services" : { + "sysvinit" : { + "artifactory" : { "enabled" : "true", "ensureRunning" : "true" }, + "nginx" : { "enabled" : "true", "ensureRunning" : "true"}, + "cfn-hup" : { "enabled" : "true", "ensureRunning" : "true", + "files" : ["/etc/cfn/cfn-hup.conf", "/etc/cfn/hooks.d/cfn-auto-reloader.conf"]} + } + } + } + } + }, + "Properties": { + "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" }, + { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] }, + "InstanceType" : { "Ref" : "InstanceType" }, + "SecurityGroups" : [ {"Ref" : "ArtifactorySecurityGroup"} ], + "KeyName" : { "Ref" : "KeyName" }, + "BlockDeviceMappings" : [ + { + "DeviceName" : "/dev/xvda", + "Ebs" : { "VolumeSize" : { "Ref" : "InstanceStorage" }, "VolumeType" : "gp2", "DeleteOnTermination" : "true"} + } + ], + "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [ + "#!/bin/bash -xe\n", + "yum update -y aws-cfn-bootstrap\n", + + "yum install -y java-1.8.0>> /tmp/yum-java8.log 2>&1\n", + + "alternatives --set java /usr/lib/jvm/jre-1.8.0-openjdk.x86_64/bin/java\n", + + "yum -y remove java-1.7.0-openjdk>> /tmp/yum-java7.log 2>&1\n", + + "##Install Artifactory\n", + "wget https://bintray.com/jfrog/artifactory-pro-rpms/rpm -O bintray-jfrog-artifactory-pro-rpms.repo\n", + "mv bintray-jfrog-artifactory-pro-rpms.repo /etc/yum.repos.d/\n", + "sleep 10\n", + "yum install -y jfrog-artifactory-pro-", { "Ref": "ArtifactoryVersion" }, ">> /tmp/yum-artifactory.log 2>&1\n", + "yum install -y nginx>> /tmp/yum-nginx.log 2>&1\n", + "curl -L -o /opt/jfrog/artifactory/tomcat/lib/mysql-connector-java-5.1.38.jar https://bintray.com/artifact/download/bintray/jcenter/mysql/mysql-connector-java/5.1.38/mysql-connector-java-5.1.38.jar\n", + + "# Install the files and packages from the metadata\n", + "/opt/aws/bin/cfn-init -v ", + " --stack ", { "Ref" : "AWS::StackName" }, + " --resource PrimaryLaunchConfig ", + " --region ", { "Ref" : "AWS::Region" }, "\n", + + "# Signal the status from cfn-init\n", + "/opt/aws/bin/cfn-signal -e $? ", + " --stack ", { "Ref" : "AWS::StackName" }, + " --resource PrimaryGroup ", + " --region ", { "Ref" : "AWS::Region" }, "\n" + ]]}} + } + }, + + "SecondaryGroup" : { + "Type" : "AWS::AutoScaling::AutoScalingGroup", + "Properties" : { + "AvailabilityZones" : [{ "Fn::GetAtt" : [ "PublicSubnet1", "AvailabilityZone" ] },{ "Fn::GetAtt" : [ "PublicSubnet2", "AvailabilityZone" ] }], + "VPCZoneIdentifier" : [{ "Ref" : "PublicSubnet1" }, { "Ref" : "PublicSubnet2" }], + "LaunchConfigurationName" : { "Ref" : "SecondaryLaunchConfig" }, + "MinSize" : "0", + "MaxSize" : "9", + "DesiredCapacity" : { "Ref" : "SecondaryNodeCount" }, + "LoadBalancerNames" : [ { "Ref" : "ElasticLoadBalancer" } ], + "HealthCheckGracePeriod" : "480", + "HealthCheckType" : "ELB" + }, + "UpdatePolicy": { + "AutoScalingRollingUpdate": { + "MinInstancesInService": "1", + "MaxBatchSize": "1", + "PauseTime": "PT7M" + } + } + }, + + "SecondaryLaunchConfig": { + "Type" : "AWS::AutoScaling::LaunchConfiguration", + "Metadata" : { + "Comment1" : "Configure the bootstrap helpers to install the Artifactory Secondary Server", + + "AWS::CloudFormation::Init" : { + "config" : { + "packages" : { + "yum" : { + "wget" : [], + "curl" : [] + } + }, + + "files" : { + + "/etc/nginx/nginx.conf" : { + "content" : { "Fn::Join" : ["", [ + "#user nobody;\n", + "worker_processes 1;\n", + "error_log /var/log/nginx/error.log info;\n", + "#pid logs/nginx.pid;\n", + "events {\n", + " worker_connections 1024;\n", + "}\n", + "http {\n", + " include mime.types;\n", + " include /etc/nginx/conf.d/*.conf;\n", + " default_type application/octet-stream;\n", + " log_format main '$remote_addr - $remote_user [$time_local] \"$request\" '\n", + "'$status $body_bytes_sent \"$http_referer\" '\n", + "'\"$http_user_agent\" \"$http_x_forwarded_for\"';\n", + " access_log /var/log/nginx/access.log main;\n", + " sendfile on;\n", + " #tcp_nopush on;\n", + " #keepalive_timeout 0;\n", + " keepalive_timeout 65;\n", + "}\n" + ]]}, + "mode" : "000755", + "owner" : "root", + "group" : "root" + }, + + "/var/opt/jfrog/artifactory/etc/db.properties" : { + "content" : { "Fn::Join" : ["", [ + "type=mysql\n", + "driver=com.mysql.jdbc.Driver\n", + "url=jdbc:mysql://", {"Fn::GetAtt" : ["MySQLDatabase", "Endpoint.Address"]},":3306/", { "Ref" : "DBName" },"?characterEncoding=UTF-8&elideSetAutoCommits=true\n", + "username=", {"Ref" : "DBUser"}, "\n", + "password=", {"Ref" : "DBPassword"}, "\n" + ]]}, + "mode" : "000755", + "owner" : "artifactory", + "group" : "artifactory" + }, + + "/var/opt/jfrog/artifactory/etc/binarystore.xml" : { + "content" : { "Fn::Join" : ["", [ + "\n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + " \n", + "\n", + "\n", + "crossNetworkStrategy\n", + "crossNetworkStrategy\n", + "2\n", + "1\n", + "\n", + "\n", + "\n", + "\n", + " remote\n", + "\n", + "\n", + "\n", + " local\n", + "\n", + "\n", + "\n", + "",{ "Fn::Join": [ "", [ "s3.dualstack.", { "Ref": "AWS::Region" }, ".amazonaws.com" ] ] },"\n", + "", {"Ref" : "IAMAcessKey"}, "\n", + "", { "Fn::GetAtt": [ "IAMAcessKey", "SecretAccessKey" ] }, "\n", + "", { "Ref": "S3Bucket" }, "\n", + "\n", + "\n" + ]]}, + "mode" : "000755", + "owner" : "artifactory", + "group" : "artifactory" + }, + + "/var/opt/jfrog/artifactory/etc/ha-node.properties" : { + "content" : { "Fn::Join" : ["", [ + "node.id=art1\n", + "artifactory.ha.data.dir=/var/opt/jfrog/artifactory/data\n", + "context.url=http://127.0.0.1:8081/artifactory\n", + "membership.port=10001\n", + "hazelcast.interface=172.25.0.3\n", + "primary=false\n" + ]]}, + "mode" : "000755", + "owner" : "artifactory", + "group" : "artifactory" + }, + + "/var/opt/jfrog/artifactory/etc/security/master.key" : { + "content" : { "Fn::Join" : ["", [ + {"Ref" : "MasterKey"} + ]]}, + "mode" : "000755", + "owner" : "artifactory", + "group" : "artifactory" + }, + + "/etc/pki/tls/certs/result.pem" : { + "content" : { "Fn::Join" : ["", [ + {"Ref" : "Certificate"} + ]]}, + "mode" : "000777", + "owner" : "root", + "group" : "root" + }, + + "/etc/pki/tls/private/result.key" : { + "content" : { "Fn::Join" : ["", [ + {"Ref" : "CertificateKey"} + ]]}, + "mode" : "000777", + "owner" : "root", + "group" : "root" + }, + + "/var/opt/jfrog/artifactory/etc/artifactory.cluster.license" : { + "content" : { "Fn::Join" : ["", [ + "", { "Ref" : "ArtifactoryLicense1" }, "\n", + "\n", + "", { "Ref" : "ArtifactoryLicense2" }, "\n", + "\n", + "", { "Ref" : "ArtifactoryLicense3" }, "\n", + "\n", + "", { "Ref" : "ArtifactoryLicense4" }, "\n", + "\n", + "", { "Ref" : "ArtifactoryLicense5" }, "\n" + ]]}, + "mode" : "000755", + "owner" : "artifactory", + "group" : "artifactory" + }, + + "/etc/nginx/conf.d/artifactory.conf" : { + "content" : { "Fn::Join" : ["", [ + "ssl_certificate /etc/pki/tls/certs/cert.pem;\n", + "ssl_certificate_key /etc/pki/tls/private/cert.key;\n", + "ssl_session_cache shared:SSL:1m;\n", + "ssl_prefer_server_ciphers on;\n", + "## server configuration\n", + "server {\n", + " listen 443 ssl;\n", + " listen 80 ;\n", + " server_name ",{ "Ref" : "ArtifactoryServerName" },".",{ "Ref" : "CertificateDomain" }," ~(?.+)\\.",{ "Ref" : "CertificateDomain" },";\n", + " if ($http_x_forwarded_proto = '') {\n", + " set $http_x_forwarded_proto $scheme;\n", + " }\n", + " ## Application specific logs\n", + " ## access_log /var/log/nginx/artifactory-access.log timing;\n", + " ## error_log /var/log/nginx/artifactory-error.log;\n", + " rewrite ^/$ /artifactory/webapp/ redirect;\n", + " rewrite ^/artifactory/?(/webapp)?$ /artifactory/webapp/ redirect;\n", + " rewrite ^/(v1|v2)/(.*) /artifactory/api/docker/$repo/$1/$2;\n", + " chunked_transfer_encoding on;\n", + " client_max_body_size 0;\n", + " location /artifactory/ {\n", + " proxy_read_timeout 900;\n", + " proxy_pass_header Server;\n", + " proxy_cookie_path ~*^/.* /;\n", + " proxy_pass http://127.0.0.1:8081/artifactory/;\n", + " proxy_set_header X-Artifactory-Override-Base-Url $http_x_forwarded_proto://$host:$server_port/artifactory;\n", + " proxy_set_header X-Forwarded-Port $server_port;\n", + " proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;\n", + " proxy_set_header Host $http_host;\n", + " proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n", + " }\n", + "}\n", + "\n" + ]]}, + "mode" : "000755", + "owner" : "root", + "group" : "root" + }, + + "/etc/cfn/cfn-hup.conf" : { + "content" : { "Fn::Join" : ["", [ + "[main]\n", + "stack=", { "Ref" : "AWS::StackId" }, "\n", + "region=", { "Ref" : "AWS::Region" }, "\n" + ]]}, + "mode" : "000400", + "owner" : "root", + "group" : "root" + }, + + "/etc/cfn/hooks.d/cfn-auto-reloader.conf" : { + "content": { "Fn::Join" : ["", [ + "[cfn-auto-reloader-hook]\n", + "triggers=post.update\n", + "path=Resources.SecondaryLaunchConfig.Metadata.AWS::CloudFormation::Init\n", + "action=/opt/aws/bin/cfn-init -v ", + " --stack ", { "Ref" : "AWS::StackName" }, + " --resource SecondaryLaunchConfig ", + " --region ", { "Ref" : "AWS::Region" }, "\n", + "runas=root\n" + ]]} + } + }, + + "commands" : { + "set_artifactory_node_id" : { + "command" : { "Fn::Join" : ["", ["sed -i -e \"s/art1/art-$(date +%s$RANDOM)/\" /var/opt/jfrog/artifactory/etc/ha-node.properties"]]} + }, + "set_artifactory_context" : { + "command" : { "Fn::Join" : ["", ["sed -i -e \"s/127.0.0.1/$(curl http://169.254.169.254/latest/meta-data/public-ipv4)/\" /var/opt/jfrog/artifactory/etc/ha-node.properties"]]} + }, + "set_hazelcast_interface" : { + "command" : { "Fn::Join" : ["", ["sed -i -e \"s/172.25.0.3/$(curl http://169.254.169.254/latest/meta-data/local-ipv4)/\" /var/opt/jfrog/artifactory/etc/ha-node.properties"]]} + }, + "allow_ping_anonymous" : { + "command" : { "Fn::Join" : ["", ["echo \"artifactory.ping.allowUnauthenticated=true\" >> /var/opt/jfrog/artifactory/etc/artifactory.system.properties"]]} + }, + "set_extra_java_options" : { + "command" : { "Fn::Join" : ["", ["echo \"export JAVA_OPTIONS=", "\\\"", { "Ref" : "ExtraJavaOptions" }, "\\\"", "\" >> /var/opt/jfrog/artifactory/etc/default"]]} + }, + "set_permissions" : { + "command" : { "Fn::Join" : ["", ["chown artifactory:artifactory -R /var/opt/jfrog/artifactory/* && chown artifactory:artifactory -R /var/opt/jfrog/artifactory/etc/security"]]} + }, + "generate_self_signed_cert" : { + "command" : { "Fn::Join" : ["", ["openssl req -nodes -x509 -newkey rsa:4096 -keyout /etc/pki/tls/private/example.key -out /etc/pki/tls/certs/example.pem -days 356 -subj \"/C=US/ST=California/L=SantaClara/O=IT/CN=*.localhost\""]]} + }, + "format_ssl_certificate" : { + "command" : { "Fn::Join" : ["", ["cat /etc/pki/tls/certs/result.pem | sed 's/CERTIFICATE----- /CERTIFICATE-----\\n/g' | sed 's/-----END/\\n-----END/' > temp.pem | mv -f temp.pem /etc/pki/tls/certs/cert.pem"]]} + }, + "format_ssl_certificate_key" : { + "command" : { "Fn::Join" : ["", ["cat /etc/pki/tls/private/result.key | sed 's/KEY----- /KEY-----\\n/g' | sed 's/-----END/\\n-----END/' > temp.key | mv -f temp.key /etc/pki/tls/private/cert.key"]]} + }, + "sleep_for_minute" : { + "command" : { "Fn::Join" : ["", ["sleep 120"]]} + } + }, + + "services" : { + "sysvinit" : { + "artifactory" : { "enabled" : "true", "ensureRunning" : "true" }, + "nginx" : { "enabled" : "true", "ensureRunning" : "true"}, + "cfn-hup" : { "enabled" : "true", "ensureRunning" : "true", + "files" : ["/etc/cfn/cfn-hup.conf", "/etc/cfn/hooks.d/cfn-auto-reloader.conf"]} + } + } + } + } + }, + "Properties": { + "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" }, + { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] }, + "InstanceType" : { "Ref" : "InstanceType" }, + "SecurityGroups" : [ {"Ref" : "ArtifactorySecurityGroup"} ], + "KeyName" : { "Ref" : "KeyName" }, + "BlockDeviceMappings" : [ + { + "DeviceName" : "/dev/xvda", + "Ebs" : { "VolumeSize" : { "Ref" : "InstanceStorage" }, "VolumeType" : "gp2", "DeleteOnTermination" : "true"} + } + ], + "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [ + "#!/bin/bash -xe\n", + "yum update -y aws-cfn-bootstrap\n", + + "yum install -y java-1.8.0>> /tmp/yum-java8.log 2>&1\n", + + "alternatives --set java /usr/lib/jvm/jre-1.8.0-openjdk.x86_64/bin/java\n", + + "yum -y remove java-1.7.0-openjdk>> /tmp/yum-java7.log 2>&1\n", + + "##Install Artifactory\n", + "wget https://bintray.com/jfrog/artifactory-pro-rpms/rpm -O bintray-jfrog-artifactory-pro-rpms.repo\n", + "mv bintray-jfrog-artifactory-pro-rpms.repo /etc/yum.repos.d/\n", + "sleep 10\n", + "yum install -y jfrog-artifactory-pro-", { "Ref": "ArtifactoryVersion" }, ">> /tmp/yum-artifactory.log 2>&1\n", + "yum install -y nginx>> /tmp/yum-nginx.log 2>&1\n", + "curl -L -o /opt/jfrog/artifactory/tomcat/lib/mysql-connector-java-5.1.38.jar https://bintray.com/artifact/download/bintray/jcenter/mysql/mysql-connector-java/5.1.38/mysql-connector-java-5.1.38.jar\n", + + "# Install the files and packages from the metadata\n", + "/opt/aws/bin/cfn-init -v ", + " --stack ", { "Ref" : "AWS::StackName" }, + " --resource SecondaryLaunchConfig ", + " --region ", { "Ref" : "AWS::Region" }, "\n", + + "# Signal the status from cfn-init\n", + "/opt/aws/bin/cfn-signal -e $? ", + " --stack ", { "Ref" : "AWS::StackName" }, + " --resource SecondaryGroup ", + " --region ", { "Ref" : "AWS::Region" }, "\n" + ]]}} + } + }, + + + "ArtifactorySecurityGroup" : { + "Type" : "AWS::EC2::SecurityGroup", + "Properties" : { + "GroupDescription" : "Enable HTTP access via port 80 locked down to the ELB and SSH access", + "SecurityGroupIngress" : [ + {"IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", "CidrIp" : "0.0.0.0/0"}, + {"IpProtocol" : "tcp", "FromPort" : "443", "ToPort" : "443", "CidrIp" : "0.0.0.0/0"}, + {"IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "CidrIp" : { "Ref" : "SSHLocation"}}, + {"IpProtocol" : "tcp", "FromPort" : "10001", "ToPort" : "10001", "CidrIp" : "0.0.0.0/0"}, + {"IpProtocol" : "tcp", "FromPort" : "3306", "ToPort" : "3306", "CidrIp" : "0.0.0.0/0"}, + {"IpProtocol" : "tcp", "FromPort" : "8081", "ToPort" : "8081", "CidrIp" : "0.0.0.0/0"} + ], + "VpcId" : { "Ref" : "VPC" } + } + }, + + "MyDBSubnetGroup" : { + "Type" : "AWS::RDS::DBSubnetGroup", + "Properties" : { + "DBSubnetGroupDescription" : "Subnets available for the RDS DB Instance", + "SubnetIds" : [{ "Ref" : "PrivateSubnet" },{ "Ref" : "PublicSubnet1" }, { "Ref" : "PublicSubnet2" }] + } + }, + + "MySQLDatabase": { + "Type": "AWS::RDS::DBInstance", + "Properties": { + "Engine" : "MySQL", + "EngineVersion" : "5.5", + "DBName" : { "Ref": "DBName" }, + "MultiAZ" : { "Ref": "MultiAZDatabase" }, + "MasterUsername": { "Ref": "DBUser" }, + "MasterUserPassword": { "Ref" : "DBPassword" }, + "DBInstanceClass": { "Ref" : "DBInstanceClass" }, + "AllocatedStorage": { "Ref" : "DBAllocatedStorage" }, + "DBSubnetGroupName" : { "Ref" : "MyDBSubnetGroup" }, + "VPCSecurityGroups": [ { "Ref" : "ArtifactorySecurityGroup" } ] + } + } + }, + + "Outputs" : { + "URL" : { + "Description" : "URL of the Artifactory", + "Value" : { "Fn::Join" : [ "", [ "http://", { "Fn::GetAtt" : [ "ElasticLoadBalancer", "DNSName" ]}]]} + } + } +} \ No newline at end of file diff --git a/CloudFormation/images/10.png b/CloudFormation/images/10.png new file mode 100644 index 0000000..4291a97 Binary files /dev/null and b/CloudFormation/images/10.png differ diff --git a/CloudFormation/images/11.png b/CloudFormation/images/11.png new file mode 100644 index 0000000..7884700 Binary files /dev/null and b/CloudFormation/images/11.png differ diff --git a/CloudFormation/images/12.png b/CloudFormation/images/12.png new file mode 100644 index 0000000..8440a73 Binary files /dev/null and b/CloudFormation/images/12.png differ diff --git a/CloudFormation/images/13.png b/CloudFormation/images/13.png new file mode 100644 index 0000000..b72f43b Binary files /dev/null and b/CloudFormation/images/13.png differ diff --git a/CloudFormation/images/14.png b/CloudFormation/images/14.png new file mode 100644 index 0000000..cd45337 Binary files /dev/null and b/CloudFormation/images/14.png differ diff --git a/CloudFormation/images/15.png b/CloudFormation/images/15.png new file mode 100644 index 0000000..097d632 Binary files /dev/null and b/CloudFormation/images/15.png differ diff --git a/CloudFormation/images/2.png b/CloudFormation/images/2.png new file mode 100644 index 0000000..2dee95c Binary files /dev/null and b/CloudFormation/images/2.png differ diff --git a/CloudFormation/images/3.png b/CloudFormation/images/3.png new file mode 100644 index 0000000..e9ee659 Binary files /dev/null and b/CloudFormation/images/3.png differ diff --git a/CloudFormation/images/4.png b/CloudFormation/images/4.png new file mode 100644 index 0000000..2463feb Binary files /dev/null and b/CloudFormation/images/4.png differ diff --git a/CloudFormation/images/5.png b/CloudFormation/images/5.png new file mode 100644 index 0000000..8007b3a Binary files /dev/null and b/CloudFormation/images/5.png differ diff --git a/CloudFormation/images/6.png b/CloudFormation/images/6.png new file mode 100644 index 0000000..23d1030 Binary files /dev/null and b/CloudFormation/images/6.png differ diff --git a/CloudFormation/images/7.png b/CloudFormation/images/7.png new file mode 100644 index 0000000..d723eac Binary files /dev/null and b/CloudFormation/images/7.png differ diff --git a/CloudFormation/images/8.png b/CloudFormation/images/8.png new file mode 100644 index 0000000..07eda99 Binary files /dev/null and b/CloudFormation/images/8.png differ diff --git a/CloudFormation/images/9.png b/CloudFormation/images/9.png new file mode 100644 index 0000000..0fd1fb1 Binary files /dev/null and b/CloudFormation/images/9.png differ diff --git a/README.md b/README.md index 4122d4d..cd0c83d 100644 --- a/README.md +++ b/README.md @@ -1 +1,6 @@ -# JFrog-Cloud-Installers \ No newline at end of file +# JFrog-Cloud-Installers + +Template to deploy/manage JFrog Artifactory enterprise cluster on various cloud providers. + +[Terraform](Terraform/README.md) +[CloudFormation](CloudFormation/README.md) \ No newline at end of file diff --git a/Terraform/README.md b/Terraform/README.md new file mode 100644 index 0000000..22b6947 --- /dev/null +++ b/Terraform/README.md @@ -0,0 +1,84 @@ +# Terraform Template For Artifactory Enterprise + +### Prerequisites: +* AWS account +* Basic knowledge to AWS +* Pre created Keys +* Basic knowledge of Artifactory + +### Steps to Deploy Artifactory Enterprise using Terraform template + +1. Set your AWS account credentials. + Easy way to do it is by setting environment variables. + ``` + export AWS_ACCESS_KEY_ID="your_access_key" + export AWS_SECRET_ACCESS_KEY="your_secret_key" + export AWS_DEFAULT_REGION="aws_region" + ``` + To learn more about Terraform aws provider follow there documentation. + https://www.terraform.io/docs/providers/aws/index.html + +2. Make Changes in `variables.tf` file to change default values to desired once. Also pass Artifactory Enterprise licenses as string in Variables `artifactory_license_1-5`." + e.g Change disk space to 500Gb: + ``` + variable "volume_size" { + description = "Disk size for each EC2 instances" + default = 500 + } + ``` + +3. Run command `terraform init -var 'key_name=myAwsKey'` + This is install required plugin for AWS provider. + +4. Run command `terraform plan -var 'key_name=myAwsKey'`. + +5. Run command `terraform apply -var 'key_name=myAwsKey'` to deploy Artifactory Enterprise cluster on AWS. + + It will take approximately 15 min to bring up cluster. + + You will get ELB Url to access Artifactory.By default This template will start only 1 node in Artifactory cluster. + ``` + Outputs: + + address = artifactory-elb-265664219.us-west-2.elb.amazonaws.com + ``` + +6. Access Artifactory UI using ELB Url provided in outputs. + +7. Scale your cluster using following command: + + `terraform apply -var 'key_name=myAwsKey' -var 'secondary_node_count=2'` + + In this example we are scaling artifactory cluster to 2 nodes. + + Note: You can only scale nodes to number of artifactory licenses you have available for cluster. + +8. SSH into Artifactory primary instance and write [inactiveServerCleaner](inactiveServerCleaner.groovy) plugin in '/var/opt/jfrog/artifactory/etc/plugins' directory. + +9. Command to destroy cluster: + `terraform destroy -var 'key_name=myAwsKey'` + +### Note: +1. This template only supports Artifactory version 5.8.x and above. +2. Turn off daily backups. Read Documentation provided [here](https://www.jfrog.com/confluence/display/RTF/Managing+Backups) +3. Use SSL Certificate with valid wild card to you artifactory as docker registry with subdomain method. + +### Steps to setup Artifactory as secure docker registry +considering you have SSL certificate for `*.jfrog.team` +1. Pass your SSL Certificate in variable `ssl_certificate` as string +2. Pass your SSL Certificate Key in variable `ssl_certificate_key` as string +3. Set `certificate_domain` as `jfrog.team` +4. Set `artifactory_server_name` as `artifactory` if you want to access artifactory with `https://artifactory.jfrog.team` +5. Create Rout53 with entry `artifactory.jfrog.team` pointing to ELB value provided as output in CloudFormation Stack. +6. Create Rout53 with entry `*.jfrog.team` pointing to ELB value provided as output in CloudFormation Stack. +7. If you have virtual docker registry with name `docker-virtual` in artifactory. You can access it via `docker-virtual.jfrog.team` + e.g ```docker pull docker-virtual.jfrog.team/nginx``` + + +### Steps to upgrade Artifactory Version +1. Change value of `artifactory_version` from old version to new Artifactory version you want to deploy. + for e.g. 5.8.1 to 5.8.2 + Run command `terraform apply -var 'key_name=myAwsKey' -var 'secondary_node_count=2' -ver 'artifactory_version=5.8.2'`. + +2. You will see instances will get upgraded one by one. Depending on your cluster size it will take 20-30 minutes to update stack. + \ No newline at end of file diff --git a/Terraform/inactiveServerCleaner.groovy b/Terraform/inactiveServerCleaner.groovy new file mode 100644 index 0000000..6f85566 --- /dev/null +++ b/Terraform/inactiveServerCleaner.groovy @@ -0,0 +1,37 @@ +import org.artifactory.state.ArtifactoryServerState +import org.artifactory.storage.db.servers.service.ArtifactoryServersCommonService +import org.artifactory.common.ConstantValues +import org.slf4j.Logger +import java.util.concurrent.TimeUnit + +jobs { + clean(cron: "* 0/1 * * * ?") { + def artifactoryServersCommonService = ctx.beanForType(ArtifactoryServersCommonService) + def artifactoryInactiveServerCleaner = new ArtifactoryInactiveServersCleaner(artifactoryServersCommonService, log) + artifactoryInactiveServerCleaner.cleanInactiveArtifactoryServers() + } +} + +public class ArtifactoryInactiveServersCleaner { + + private ArtifactoryServersCommonService artifactoryServersCommonService + private Logger log + + ArtifactoryInactiveServersCleaner(ArtifactoryServersCommonService artifactoryServersCommonService, Logger log) { + this.artifactoryServersCommonService = artifactoryServersCommonService + this.log = log + } + + def cleanInactiveArtifactoryServers() { + List allMembers = artifactoryServersCommonService.getAllArtifactoryServers() + for (member in allMembers) { + def heartbeat = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - member.getLastHeartbeat()) + def noheartbeat = heartbeat > ConstantValues.haHeartbeatStaleIntervalSecs.getInt() + if (member.getServerState() == ArtifactoryServerState.UNAVAILABLE || noheartbeat) { + log.info "Running inactive artifactory servers cleaning task, found ${member.serverId} inactive servers to " + + "remove" + artifactoryServersCommonService.removeServer(member.serverId) + } + } + } +} diff --git a/Terraform/main.tf b/Terraform/main.tf new file mode 100644 index 0000000..4bf0eb4 --- /dev/null +++ b/Terraform/main.tf @@ -0,0 +1,447 @@ +# Specify the provider and access details +provider "aws" { + region = "${var.aws_region}" +} + +# Create a VPC to launch our instances into +resource "aws_vpc" "default" { + cidr_block = "10.0.0.0/16" +} + +# Create an internet gateway to give our subnet access to the outside world +resource "aws_internet_gateway" "default" { + vpc_id = "${aws_vpc.default.id}" +} + +# Grant the VPC internet access on its main route table +resource "aws_route" "internet_access" { + route_table_id = "${aws_vpc.default.main_route_table_id}" + destination_cidr_block = "0.0.0.0/0" + gateway_id = "${aws_internet_gateway.default.id}" +} + +# Declare the data source +data "aws_availability_zones" "available" {} + +# Create a subnet to launch our instances into +resource "aws_subnet" "default" { + vpc_id = "${aws_vpc.default.id}" + cidr_block = "10.0.1.0/24" + map_public_ip_on_launch = true +} + +# Create a subnet to launch our instances into +resource "aws_subnet" "default_2" { + vpc_id = "${aws_vpc.default.id}" + cidr_block = "10.0.2.0/24" + map_public_ip_on_launch = true + availability_zone = "${data.aws_availability_zones.available.names[0]}" +} + +resource "aws_subnet" "default_3" { + vpc_id = "${aws_vpc.default.id}" + cidr_block = "10.0.3.0/24" + map_public_ip_on_launch = true + availability_zone = "${data.aws_availability_zones.available.names[1]}" +} + +# A security group for the ELB so it is accessible via the web +resource "aws_security_group" "elb" { + name = "artifactory_elb" + description = "Used in the terraform" + vpc_id = "${aws_vpc.default.id}" + + # HTTP access from anywhere + ingress { + from_port = 80 + to_port = 80 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + # HTTPS access from anywhere + ingress { + from_port = 443 + to_port = 443 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + # outbound internet access + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } +} + + +#IAM user for S3 +resource "aws_iam_user" "s3" { + name = "s3-access" +} + +#IAM access key for S3 +resource "aws_iam_access_key" "s3" { + user = "${aws_iam_user.s3.name}" +} + +# S3 bucket +resource "aws_s3_bucket" "b" { + bucket = "${var.bucket_name}" + acl = "private" +} + +#IAM Policy +resource "aws_iam_user_policy" "lb_ro" { + user = "${aws_iam_user.s3.name}" + + policy = <> /tmp/yum-java8.log +alternatives --set java /usr/lib/jvm/jre-1.8.0-openjdk.x86_64/bin/java +yum -y remove java-1.7.0-openjdk>> /tmp/yum-java7.log 2>&1 + +##Install Artifactory +wget https://bintray.com/jfrog/artifactory-pro-rpms/rpm -O bintray-jfrog-artifactory-pro-rpms.repo +mv bintray-jfrog-artifactory-pro-rpms.repo /etc/yum.repos.d/ +sleep 10 +yum install -y jfrog-artifactory-pro-${artifactory_version}>> /tmp/yum-artifactory.log 2>&1 +yum install -y nginx>> /tmp/yum-nginx.log 2>&1 +curl -L -o /opt/jfrog/artifactory/tomcat/lib/mysql-connector-java-5.1.38.jar https://bintray.com/artifact/download/bintray/jcenter/mysql/mysql-connector-java/5.1.38/mysql-connector-java-5.1.38.jar +openssl req -nodes -x509 -newkey rsa:4096 -keyout /etc/pki/tls/private/example.key -out /etc/pki/tls/certs/example.pem -days 356 -subj "/C=US/ST=California/L=SantaClara/O=IT/CN=*.localhost" + +cat </var/opt/jfrog/artifactory/etc/binarystore.xml + + + + + + + + + + + + + + + + crossNetworkStrategy + crossNetworkStrategy + 2 + + + + + remote + + + + local + + + s3.dualstack.${s3_bucket_region}.amazonaws.com + ${s3_access_key} + ${s3_secret_key} + ${s3_bucket_name} + + +EOF + +cat </var/opt/jfrog/artifactory/etc/db.properties + type=mysql + driver=com.mysql.jdbc.Driver + url=jdbc:mysql://${db_url}/${db_name}??characterEncoding=UTF-8&elideSetAutoCommits=true + username=${db_user} + password=${db_password} +EOF + +mkdir -p /var/opt/jfrog/artifactory/etc/security + +cat </var/opt/jfrog/artifactory/etc/security/master.key +${master_key} +EOF + +cat </var/opt/jfrog/artifactory/etc/artifactory.cluster.license +${artifactory_license_1} + +${artifactory_license_2} + +${artifactory_license_3} + +${artifactory_license_4} + +${artifactory_license_5} +EOF + +cat </var/opt/jfrog/artifactory/etc/ha-node.properties + node.id=art1 + artifactory.ha.data.dir=/var/opt/jfrog/artifactory/data + context.url=http://127.0.0.1:8081/artifactory + membership.port=10001 + hazelcast.interface=172.25.0.3 + primary=true +EOF + +cat </etc/pki/tls/certs/result.pem +${ssl_certificate} +EOF + +cat </etc/pki/tls/private/result.key +${ssl_certificate_key} +EOF + +cat </etc/nginx/nginx.conf + #user nobody; + worker_processes 1; + error_log /var/log/nginx/error.log info; + #pid logs/nginx.pid; + events { + worker_connections 1024; + } + + http { + include mime.types; + include /etc/nginx/conf.d/*.conf; + default_type application/octet-stream; + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + access_log /var/log/nginx/access.log main; + sendfile on; + #tcp_nopush on; + #keepalive_timeout 0; + keepalive_timeout 65; + } +EOF + +cat </etc/nginx/conf.d/artifactory.conf +ssl_certificate /etc/pki/tls/certs/cert.pem; +ssl_certificate_key /etc/pki/tls/private/cert.key; +ssl_session_cache shared:SSL:1m; +ssl_prefer_server_ciphers on; +## server configuration +server { + listen 443 ssl; + listen 80 ; + server_name ~(?.+)\\.${certificate_domain} ${artifactory_server_name}.${certificate_domain}; + if (\$http_x_forwarded_proto = '') { + set \$http_x_forwarded_proto \$scheme; + } + ## Application specific logs + ## access_log /var/log/nginx/artifactory-access.log timing; + ## error_log /var/log/nginx/artifactory-error.log; + rewrite ^/$ /artifactory/webapp/ redirect; + rewrite ^/artifactory/?(/webapp)?$ /artifactory/webapp/ redirect; + rewrite ^/(v1|v2)/(.*) /artifactory/api/docker/\$repo/\$1/\$2; + chunked_transfer_encoding on; + client_max_body_size 0; + location /artifactory/ { + proxy_read_timeout 900; + proxy_pass_header Server; + proxy_cookie_path ~*^/.* /; + proxy_pass http://127.0.0.1:8081/artifactory/; + proxy_set_header X-Artifactory-Override-Base-Url \$http_x_forwarded_proto://\$host:\$server_port/artifactory; + proxy_set_header X-Forwarded-Port \$server_port; + proxy_set_header X-Forwarded-Proto \$http_x_forwarded_proto; + proxy_set_header Host \$http_host; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + } +} +EOF + +cat /etc/pki/tls/certs/result.pem | sed 's/CERTIFICATE----- /CERTIFICATE-----\n/g' | sed 's/-----END/\n-----END/' > temp.pem +mv -f temp.pem /etc/pki/tls/certs/cert.pem +cat /etc/pki/tls/private/result.key | sed 's/KEY----- /KEY-----\n/g' | sed 's/-----END/\n-----END/' > temp.key +mv -f temp.key /etc/pki/tls/private/cert.key +echo "artifactory.ping.allowUnauthenticated=true" >> /var/opt/jfrog/artifactory/etc/artifactory.system.properties +echo "export JAVA_OPTIONS=\"${EXTRA_JAVA_OPTS}\"" >> /var/opt/jfrog/artifactory/etc/default +sed -i -e "s/art1/art-$(date +%s$RANDOM)/" /var/opt/jfrog/artifactory/etc/ha-node.properties +sed -i -e "s/127.0.0.1/$(curl http://169.254.169.254/latest/meta-data/public-ipv4)/" /var/opt/jfrog/artifactory/etc/ha-node.properties +sed -i -e "s/172.25.0.3/$(curl http://169.254.169.254/latest/meta-data/local-ipv4)/" /var/opt/jfrog/artifactory/etc/ha-node.properties +chown artifactory:artifactory -R /var/opt/jfrog/artifactory/etc/* && chown artifactory:artifactory -R /var/opt/jfrog/artifactory/* && chown artifactory:artifactory -R /var/opt/jfrog/artifactory/etc/security +service artifactory start +service nginx start \ No newline at end of file diff --git a/Terraform/userdata_secondary.sh b/Terraform/userdata_secondary.sh new file mode 100644 index 0000000..9b55efd --- /dev/null +++ b/Terraform/userdata_secondary.sh @@ -0,0 +1,172 @@ +#!/bin/bash + +yum update -y +yum install -y java-1.8.0>> /tmp/yum-java8.log +alternatives --set java /usr/lib/jvm/jre-1.8.0-openjdk.x86_64/bin/java +yum -y remove java-1.7.0-openjdk>> /tmp/yum-java7.log 2>&1 + +##Install Artifactory +wget https://bintray.com/jfrog/artifactory-pro-rpms/rpm -O bintray-jfrog-artifactory-pro-rpms.repo +mv bintray-jfrog-artifactory-pro-rpms.repo /etc/yum.repos.d/ +sleep 10 +yum install -y jfrog-artifactory-pro-${artifactory_version}>> /tmp/yum-artifactory.log 2>&1 +yum install -y nginx>> /tmp/yum-nginx.log 2>&1 +curl -L -o /opt/jfrog/artifactory/tomcat/lib/mysql-connector-java-5.1.38.jar https://bintray.com/artifact/download/bintray/jcenter/mysql/mysql-connector-java/5.1.38/mysql-connector-java-5.1.38.jar +openssl req -nodes -x509 -newkey rsa:4096 -keyout /etc/pki/tls/private/example.key -out /etc/pki/tls/certs/example.pem -days 356 -subj "/C=US/ST=California/L=SantaClara/O=IT/CN=*.localhost" + + +cat </var/opt/jfrog/artifactory/etc/binarystore.xml + + + + + + + + + + + + + + + + crossNetworkStrategy + crossNetworkStrategy + 2 + + + + + remote + + + + local + + + s3.dualstack.${s3_bucket_region}.amazonaws.com + ${s3_access_key} + ${s3_secret_key} + ${s3_bucket_name} + + +EOF + +cat </var/opt/jfrog/artifactory/etc/db.properties + type=mysql + driver=com.mysql.jdbc.Driver + url=jdbc:mysql://${db_url}/${db_name}??characterEncoding=UTF-8&elideSetAutoCommits=true + username=${db_user} + password=${db_password} +EOF + +mkdir -p /var/opt/jfrog/artifactory/etc/security + +cat </var/opt/jfrog/artifactory/etc/security/master.key +${master_key} +EOF + +cat </var/opt/jfrog/artifactory/etc/artifactory.cluster.license +${artifactory_license_1} + +${artifactory_license_2} + +${artifactory_license_3} + +${artifactory_license_4} + +${artifactory_license_5} +EOF + +cat </var/opt/jfrog/artifactory/etc/ha-node.properties + node.id=art1 + artifactory.ha.data.dir=/var/opt/jfrog/artifactory/data + context.url=http://127.0.0.1:8081/artifactory + membership.port=10001 + hazelcast.interface=172.25.0.3 + primary=false +EOF + +cat </etc/pki/tls/certs/result.pem +${ssl_certificate} +EOF + +cat </etc/pki/tls/private/result.key +${ssl_certificate_key} +EOF + +cat </etc/nginx/nginx.conf + #user nobody; + worker_processes 1; + error_log /var/log/nginx/error.log info; + #pid logs/nginx.pid; + events { + worker_connections 1024; + } + + http { + include mime.types; + include /etc/nginx/conf.d/*.conf; + default_type application/octet-stream; + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + access_log /var/log/nginx/access.log main; + sendfile on; + #tcp_nopush on; + #keepalive_timeout 0; + keepalive_timeout 65; + } +EOF + +cat </etc/nginx/conf.d/artifactory.conf +ssl_certificate /etc/pki/tls/certs/cert.pem; +ssl_certificate_key /etc/pki/tls/private/cert.key; +ssl_session_cache shared:SSL:1m; +ssl_prefer_server_ciphers on; +## server configuration +server { + listen 443 ssl; + listen 80 ; + server_name ~(?.+)\\.${certificate_domain} ${artifactory_server_name}.${certificate_domain}; + if (\$http_x_forwarded_proto = '') { + set \$http_x_forwarded_proto \$scheme; + } + ## Application specific logs + ## access_log /var/log/nginx/artifactory-access.log timing; + ## error_log /var/log/nginx/artifactory-error.log; + rewrite ^/$ /artifactory/webapp/ redirect; + rewrite ^/artifactory/?(/webapp)?$ /artifactory/webapp/ redirect; + rewrite ^/(v1|v2)/(.*) /artifactory/api/docker/\$repo/\$1/\$2; + chunked_transfer_encoding on; + client_max_body_size 0; + location /artifactory/ { + proxy_read_timeout 900; + proxy_pass_header Server; + proxy_cookie_path ~*^/.* /; + proxy_pass http://127.0.0.1:8081/artifactory/; + proxy_set_header X-Artifactory-Override-Base-Url \$http_x_forwarded_proto://\$host:\$server_port/artifactory; + proxy_set_header X-Forwarded-Port \$server_port; + proxy_set_header X-Forwarded-Proto \$http_x_forwarded_proto; + proxy_set_header Host \$http_host; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + } +} +EOF + +cat /etc/pki/tls/certs/result.pem | sed 's/CERTIFICATE----- /CERTIFICATE-----\n/g' | sed 's/-----END/\n-----END/' > temp.pem +mv -f temp.pem /etc/pki/tls/certs/cert.pem +cat /etc/pki/tls/private/result.key | sed 's/KEY----- /KEY-----\n/g' | sed 's/-----END/\n-----END/' > temp.key +mv -f temp.key /etc/pki/tls/private/cert.key +echo "artifactory.ping.allowUnauthenticated=true" >> /var/opt/jfrog/artifactory/etc/artifactory.system.properties +echo "export JAVA_OPTIONS=\"${EXTRA_JAVA_OPTS}\"" >> /var/opt/jfrog/artifactory/etc/default +sed -i -e "s/art1/art-$(date +%s$RANDOM)/" /var/opt/jfrog/artifactory/etc/ha-node.properties +sed -i -e "s/127.0.0.1/$(curl http://169.254.169.254/latest/meta-data/public-ipv4)/" /var/opt/jfrog/artifactory/etc/ha-node.properties +sed -i -e "s/172.25.0.3/$(curl http://169.254.169.254/latest/meta-data/local-ipv4)/" /var/opt/jfrog/artifactory/etc/ha-node.properties +chown artifactory:artifactory -R /var/opt/jfrog/artifactory/etc/* && chown artifactory:artifactory -R /var/opt/jfrog/artifactory/* && chown artifactory:artifactory -R /var/opt/jfrog/artifactory/etc/security + +## Sleep 2 minute to avoid race condition +sleep 120 +service artifactory start +service nginx start \ No newline at end of file diff --git a/Terraform/variables.tf b/Terraform/variables.tf new file mode 100644 index 0000000..852705f --- /dev/null +++ b/Terraform/variables.tf @@ -0,0 +1,133 @@ +variable "aws_region" { + description = "AWS region to launch servers." + default = "us-west-1" +} + +variable "key_name" { + description = "Desired name of AWS key pair" +} + +variable "artifactory_version" { + description = "Artifactory version to deploy" + default = "5.8.1" +} + +variable "artifactory_license_1" { + description = "Artifactory Enterprise License" +} + +variable "artifactory_license_2" { + description = "Artifactory Enterprise License" +} + +variable "artifactory_license_3" { + description = "Artifactory Enterprise License" + default = "" +} + +variable "artifactory_license_4" { + description = "Artifactory Enterprise License" + default = "" +} + +variable "artifactory_license_5" { + description = "Artifactory Enterprise License" + default = "" +} + +variable "volume_size" { + description = "Disk size for each EC2 instances" + default = 250 +} + +variable "artifactory_instance_type" { + default = "m4.xlarge" + description = "Artifactory EC2 instance type" +} + +variable "extra_java_options" { + default = "-server -Xms2g -Xmx14g -Xss256k -XX:+UseG1GC -XX:OnOutOfMemoryError=\\\\\\\"kill -9 %p\\\\\\\"" + description = "Setting Java Memory Parameters for Artifactory" +} + +variable "bucket_name" { + description = "AWS S3 Buket name" + default = "artifactory-enterprise-bucket" +} + +variable "db_name" { + description = "MySQL database name" + default = "artdb" +} + +variable "db_user" { + description = "Database user name" + default = "artifactory" +} + +variable "db_instance_class" { + description = "The database instance type" + default = "db.t2.small" +} + +variable "db_password" { + description = "Database password" + default = "password" +} + +variable "db_allocated_storage" { + description = "The size of the database (Gb)" + default = "5" +} + +variable "master_key" { + description = "Master key for Artifactory cluster. Generate master.key using command '$openssl rand -hex 16'" + default = "35767fa0164bac66b6cccb8880babefb" +} + +variable "secondary_node_count" { + description = "Desired number of Artifactory secondary nodes" + default = 0 +} + +variable "ssl_certificate" { + description = "To use Artifactory as docker registry you need to provide wild card valid Certificate. Provide your SSL Certificate." + default = "-----BEGIN CERTIFICATE----- MIIFhzCCA2+gAwIBAgIJALC4r5BQWZE4MA0GCSqGSIb3DQEBCwUAMFoxCzAJBgNV BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRMwEQYDVQQHDApTYW50YUNsYXJh MQswCQYDVQQKDAJJVDEUMBIGA1UEAwwLKi5sb2NhbGhvc3QwHhcNMTgwMTE3MTk0 NjI4WhcNMTkwMTA4MTk0NjI4WjBaMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2Fs aWZvcm5pYTETMBEGA1UEBwwKU2FudGFDbGFyYTELMAkGA1UECgwCSVQxFDASBgNV BAMMCyoubG9jYWxob3N0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA 7KfOWDQlov8cMa8r/lcJqiWZaH9myQC74Vbe0HXsntQbcvljkjG2P7ebm5dd9Bzc sauNOJpbKf5AhFK1iwJUAkciGc1LR4k8wfWmQM3NPS8hrqrtH20zqNpdFRpNYjja JofwccPNm030GhhZkZ95TpruvmswMDwspl3jfqdcc/eiQsHcKyGnV2a+UAeoqe7J mHhmhRy1MLqAjF5U1GrUYUONA+22iRDJb4c9B91QoWvsnXpdA9NKV/mmA3/rIdx6 Ld2IPRdrIw2K5sAnXsh3bx2oCSvSfussf0x+4XDrnsaHVfjwvfNL8ECOuac2Oi/E WOp9528gOohpFAuwEt63Vl5p8/CC9m0HJDTZBKm2l5eD1kdPIj4PvP9Sn9CxGXKQ E1bxWoFxGX8EyRW0b0NK31N7b8JPZ1SoFNiB5amOMNLvR26a7cQrKumTuJeYK9Ja JaxhMXM7R0DA0Ev8ZG2xmyCygox+1KPSmJOIEpT70BFbj3rKLNqP22ET+zvPuh+2 DdgyrpHFeYkGWjMbWPjK7wJsD2zM8ccoJQfepPz8I4rT0JfrKAQgCGuGOggneaNJ KTVGNOFbj5AXdZ/Q+GvNommyRdq4J7EnqY6L+P25fo5qZ6UZ/iS0tPcvxgn0Fdhs pUPbQyQIDZyxZd3Q1lUIE38ol8P66mS2zbzf8EeOCoUCAwEAAaNQME4wHQYDVR0O BBYEFETAQM/5P7XJ8kevHFj6BPndQOFaMB8GA1UdIwQYMBaAFETAQM/5P7XJ8kev HFj6BPndQOFaMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIBAJ1TepKv LWYhFmVQcgZwZf/qt1a1cohzJSm6da9RCnnAWC7WC/U117bgSomtrH1v0OysHFhB zBBUeBqI7+OmzAX8dhj+roKkcnFUM/IwlK1eueIIA//CWvEf/o0XExilVS2yCc9d PTpOQBXwk9QinxK36kHdBiGxa7dW0JPnOEEmuMgGORKeLy4J6Ik8iSeFY1SZVcOI +6WWvoKciPlmIeccC+6YVmkeBwhP2o5r5w/UAaO2hSnGvmm4UIj/VJv4VQu7xTUp cIfFz5NtIr80DbqcyPiEMS2ETJ4L/kO4MS5FfeEXyQuXCzmiIDVY6tE3C7+kZmK4 JzPLuWm9ndQoyQySOGfQqvlUR1+YxUdvmu3LrOS5dOA354Q36wHa4wEGUoHU/7GV fYQmmmDSDaNSpXW5PFey6scFyDBS/yYJ0H9EjYb/11HeWYj8Yv5xTWj8nhzJONC8 D6Y5ydlU4PifM2pOf88pTYpmogNwLJWXbql5I9cvMa8APo4yLVqcISU5ynsvFke+ Non+T0mHpJai/hrA9NK+s6EGC1dAX58jy61h6FhOPI1d4s/mov/KMa2t3SfZp5SF 81aR6dHvO56teiK5M1xMkrqG75zh3TMFJJLRFe9XxeB4JeN76URB3mgADOUqkBxd ibSgVqfKwOw4IujEcqMUc5mqSnbLY1Dv+oby -----END CERTIFICATE-----" +} + +variable "ssl_certificate_key" { + description = "Provide your SSL Certificate key" + default = "-----BEGIN PRIVATE KEY----- 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 S+j1+iUKGGhwVmhqh75q5do3+VF3XlAh -----END PRIVATE KEY-----" +} + +variable "certificate_domain" { + description = "Provide your Certificate Domain Name. For e.g jfrog.team for certificate with *.jfrog.team" + default = "artifactory" +} + +variable "artifactory_server_name" { + description = "Provide artifactory server name to be used in Nginx. e.g artifactory for artifactory.jfrog.team" + default = "artifactory" +} + +variable "aws_amis" { + type = "map" + default = { + us-east-1 = "ami-6869aa05" + us-west-2 = "ami-7172b611" + us-west-1 = "ami-31490d51" + us-west-2 = "ami-7172b611" + eu-west-1 = "ami-f9dd458a" + eu-west-2 = "ami-886369ec" + eu-central-1 = "ami-ea26ce85" + ap-northeast-1 = "ami-374db956" + ap-northeast-2 = "ami-2b408b45" + ap-southeast-1 = "ami-a59b49c6" + ap-southeast-2 = "ami-dc361ebf" + ap-south-1 = "ami-ffbdd790" + us-east-2 = "ami-f6035893" + ca-central-1 ="ami-730ebd17" + sa-east-1 = "ami-6dd04501" + cn-north-1 = "ami-8e6aa0e3" + } +} \ No newline at end of file