From c0dc59a972cd0e506229bbfc396e41606c5aff87 Mon Sep 17 00:00:00 2001 From: Vinay Aggarwal Date: Thu, 1 Apr 2021 21:15:28 -0700 Subject: [PATCH] Checking in code for rt 7.17.4 version --- .../cloudInstallerScripts/artifactory-ami.yml | 5 + .../roles/artifactory-ami/.travis.yml | 29 + .../roles/artifactory-ami/defaults/main.yml | 60 + .../roles/artifactory-ami/handlers/main.yml | 10 + .../roles/artifactory-ami/meta/exception.yml | 6 + .../roles/artifactory-ami/meta/main.yml | 35 + .../artifactory-ami/meta/preferences.yml | 2 + .../roles/artifactory-ami/meta/version.yml | 6 + .../roles/artifactory-ami/tasks/main.yml | 82 + .../templates/artifactory.cluster.license.j2 | 37 + .../templates/binarystore.xml.j2 | 4 + .../templates/installer-info.json.j2 | 12 + .../artifactory-ami/templates/join.key.j2 | 1 + .../artifactory-ami/templates/master.key.j2 | 1 + .../artifactory-ami/templates/system.yaml.j2 | 38 + .../roles/artifactory-ami/vars/main.yml | 2 + .../roles/artifactory-nginx-ami/.travis.yml | 29 + .../artifactory-nginx-ami/defaults/main.yml | 2 + .../artifactory-nginx-ami/files/nginx.conf | 37 + .../artifactory-nginx-ami/handlers/main.yml | 2 + .../roles/artifactory-nginx-ami/meta/main.yml | 53 + .../artifactory-nginx-ami/tasks/main.yml | 30 + .../templates/artifactory.conf.j2 | 43 + .../artifactory-nginx-ami/tests/inventory | 2 + .../artifactory-nginx-ami/tests/test.yml | 5 + .../roles/artifactory-nginx-ami/vars/main.yml | 2 + .../roles/artifactory-nginx-ssl/.travis.yml | 29 + .../artifactory-nginx-ssl/defaults/main.yml | 2 + .../artifactory-nginx-ssl/handlers/main.yml | 2 + .../roles/artifactory-nginx-ssl/meta/main.yml | 53 + .../artifactory-nginx-ssl/tasks/main.yml | 54 + .../templates/artifactory.conf.j2 | 49 + .../templates/certificate.key.j2 | 1 + .../templates/certificate.pem.j2 | 1 + .../artifactory-nginx-ssl/tests/inventory | 2 + .../artifactory-nginx-ssl/tests/test.yml | 5 + .../roles/artifactory-nginx-ssl/vars/main.yml | 2 + .../roles/artifactory-nginx/.travis.yml | 29 + .../roles/artifactory-nginx/defaults/main.yml | 2 + .../roles/artifactory-nginx/files/nginx.conf | 37 + .../roles/artifactory-nginx/handlers/main.yml | 2 + .../roles/artifactory-nginx/meta/main.yml | 53 + .../roles/artifactory-nginx/tasks/main.yml | 34 + .../templates/artifactory.conf.j2 | 43 + .../roles/artifactory-nginx/tests/inventory | 2 + .../roles/artifactory-nginx/tests/test.yml | 5 + .../roles/artifactory-nginx/vars/main.yml | 2 + .../roles/artifactory/.travis.yml | 29 + .../roles/artifactory/defaults/main.yml | 52 + .../roles/artifactory/handlers/main.yml | 10 + .../roles/artifactory/meta/exception.yml | 6 + .../roles/artifactory/meta/main.yml | 35 + .../roles/artifactory/meta/preferences.yml | 2 + .../roles/artifactory/meta/version.yml | 6 + .../artifactory/tasks/configure-licenses.yml | 43 + .../tasks/custom-data-directory.yml | 44 + .../roles/artifactory/tasks/main.yml | 132 + .../templates/artifactory.cluster.license.j2 | 6 + .../templates/artifactory.pro.license.j2 | 8 + .../artifactory/templates/binarystore.xml.j2 | 14 + .../templates/installer-info.json.j2 | 11 + .../roles/artifactory/templates/join.key.j2 | 1 + .../roles/artifactory/templates/master.key.j2 | 1 + .../artifactory/templates/system.yaml.j2 | 40 + .../roles/artifactory/vars/main.yml | 2 + .../roles/xray-ami/.travis.yml | 29 + .../roles/xray-ami/defaults/main.yml | 26 + .../roles/xray-ami/handlers/main.yml | 2 + .../roles/xray-ami/meta/main.yml | 53 + .../roles/xray-ami/tasks/Debian.yml | 37 + .../roles/xray-ami/tasks/RedHat.yml | 21 + .../roles/xray-ami/tasks/main.yml | 60 + .../xray-ami/templates/installer-info.json.j2 | 11 + .../roles/xray-ami/templates/join.key.j2 | 1 + .../roles/xray-ami/templates/master.key.j2 | 1 + .../roles/xray-ami/templates/system.yaml.j2 | 36 + .../roles/xray-ami/tests/inventory | 2 + .../roles/xray-ami/tests/test.yml | 5 + .../roles/xray-ami/vars/main.yml | 2 + .../roles/xray/.travis.yml | 29 + .../roles/xray/defaults/main.yml | 29 + .../roles/xray/handlers/main.yml | 2 + .../roles/xray/meta/main.yml | 53 + .../roles/xray/tasks/Debian.yml | 37 + .../roles/xray/tasks/RedHat.yml | 21 + .../xray/tasks/custom-data-directory.yml | 44 + .../roles/xray/tasks/initialize-pg-db.yml | 52 + .../roles/xray/tasks/main.yml | 80 + .../xray/templates/installer-info.json.j2 | 11 + .../roles/xray/templates/join.key.j2 | 1 + .../roles/xray/templates/master.key.j2 | 1 + .../roles/xray/templates/system.yaml.j2 | 39 + .../roles/xray/tests/inventory | 2 + .../roles/xray/tests/test.yml | 5 + .../roles/xray/vars/main.yml | 2 + .../site-artifactory.yml | 12 + .../cloudInstallerScripts/site-xray.yml | 5 + .../latest/cloudInstallerScripts/xray-ami.yml | 5 + .../.github/workflows/master-docs-build.yml | 37 + .../submodules/quickstart-aws-vpc/.gitmodules | 4 + .../submodules/quickstart-aws-vpc/.nojekyll | 0 .../quickstart-aws-vpc/.taskcat.yml | 354 ++ .../submodules/quickstart-aws-vpc/LICENSE.txt | 201 + .../submodules/quickstart-aws-vpc/NOTICE.txt | 7 + .../submodules/quickstart-aws-vpc/README.md | 9 + .../ci/aws-vpc-3az-complete.json | 74 + .../ci/aws-vpc-3az-public.json | 74 + .../quickstart-aws-vpc/ci/aws-vpc-3az.json | 74 + .../ci/aws-vpc-4az-complete.json | 74 + .../ci/aws-vpc-4az-public.json | 74 + .../quickstart-aws-vpc/ci/aws-vpc-4az.json | 74 + .../ci/aws-vpc-complete.json | 74 + .../ci/aws-vpc-dedicated.json | 74 + .../ci/aws-vpc-defaults.json | 74 + .../quickstart-aws-vpc/ci/aws-vpc-public.json | 74 + .../ci/aws-vpc-sa-east-1.json | 74 + .../quickstart-aws-vpc/ci/taskcat.yml | 70 + .../docs/generated/parameters/index.adoc | 1 + .../docs/generated/regions/index.adoc | 1 + .../docs/generated/services/index.adoc | 1 + .../docs/generated/services/metadata.adoc | 1 + .../docs/images/architecture_diagram.png | Bin 0 -> 90606 bytes .../docs/images/aws-quickstart-graphic.png | Bin 0 -> 26468 bytes .../docs/images/cfn_outputs.png | Bin 0 -> 201384 bytes .../docs/partner_editable/_settings.adoc | 14 + .../partner_editable/additional_info.adoc | 323 ++ .../docs/partner_editable/architecture.adoc | 35 + .../docs/partner_editable/deploy_steps.adoc | 52 + .../partner_editable/deployment_options.adoc | 5 + .../partner_editable/faq_troubleshooting.adoc | 33 + .../docs/partner_editable/licenses.adoc | 3 + .../overview_target_and_usage.adoc | 11 + .../docs/partner_editable/pre-reqs.adoc | 1 + .../partner_editable/product_description.adoc | 18 + .../docs/partner_editable/regions.adoc | 29 + .../docs/partner_editable/service_limits.adoc | 7 + .../specialized_knowledge.adoc | 6 + .../templates/aws-vpc.template | 3591 +++++++++++++++++ .../templates/aws-vpc.template.yaml | 1809 +++++++++ .../quickstart-linux-bastion/.gitignore | 3 + .../quickstart-linux-bastion/.gitmodules | 4 + .../quickstart-linux-bastion/.taskcat.yml | 94 + .../quickstart-linux-bastion/LICENSE.txt | 202 + .../quickstart-linux-bastion/NOTICE.txt | 7 + .../quickstart-linux-bastion/README.md | 16 + .../scripts/auditing_configure.sh | 32 + .../scripts/banner_message.txt | 12 + .../scripts/bastion_bootstrap.sh | 380 ++ .../templates/linux-bastion-master.template | 299 ++ .../templates/linux-bastion.template | 725 ++++ ...ifactory-core-infrastructure.template.yaml | 425 ++ ...artifactory-ec2-existing-vpc.template.yaml | 1109 +++++ ...rog-artifactory-ec2-instance.template.yaml | 433 ++ ...jfrog-artifactory-ec2-master.template.yaml | 612 +++ ...-pro-ec2-existing-vpc-master.template.yaml | 355 ++ ...ctory-pro-ec2-new-vpc-master.template.yaml | 300 ++ .../jfrog-xray-ec2-instance.template.yaml | 326 ++ .../cloudInstallerScripts/artifactory-ami.yml | 5 + .../roles/artifactory-ami/.travis.yml | 29 + .../roles/artifactory-ami/defaults/main.yml | 60 + .../roles/artifactory-ami/handlers/main.yml | 10 + .../roles/artifactory-ami/meta/exception.yml | 6 + .../roles/artifactory-ami/meta/main.yml | 35 + .../artifactory-ami/meta/preferences.yml | 2 + .../roles/artifactory-ami/meta/version.yml | 6 + .../roles/artifactory-ami/tasks/main.yml | 82 + .../templates/artifactory.cluster.license.j2 | 37 + .../templates/binarystore.xml.j2 | 4 + .../templates/installer-info.json.j2 | 12 + .../artifactory-ami/templates/join.key.j2 | 1 + .../artifactory-ami/templates/master.key.j2 | 1 + .../artifactory-ami/templates/system.yaml.j2 | 38 + .../roles/artifactory-ami/vars/main.yml | 2 + .../roles/artifactory-nginx-ami/.travis.yml | 29 + .../artifactory-nginx-ami/defaults/main.yml | 2 + .../artifactory-nginx-ami/files/nginx.conf | 37 + .../artifactory-nginx-ami/handlers/main.yml | 2 + .../roles/artifactory-nginx-ami/meta/main.yml | 53 + .../artifactory-nginx-ami/tasks/main.yml | 30 + .../templates/artifactory.conf.j2 | 43 + .../artifactory-nginx-ami/tests/inventory | 2 + .../artifactory-nginx-ami/tests/test.yml | 5 + .../roles/artifactory-nginx-ami/vars/main.yml | 2 + .../roles/artifactory-nginx-ssl/.travis.yml | 29 + .../artifactory-nginx-ssl/defaults/main.yml | 2 + .../artifactory-nginx-ssl/handlers/main.yml | 2 + .../roles/artifactory-nginx-ssl/meta/main.yml | 53 + .../artifactory-nginx-ssl/tasks/main.yml | 54 + .../templates/artifactory.conf.j2 | 49 + .../templates/certificate.key.j2 | 1 + .../templates/certificate.pem.j2 | 1 + .../artifactory-nginx-ssl/tests/inventory | 2 + .../artifactory-nginx-ssl/tests/test.yml | 5 + .../roles/artifactory-nginx-ssl/vars/main.yml | 2 + .../roles/artifactory-nginx/.travis.yml | 29 + .../roles/artifactory-nginx/defaults/main.yml | 2 + .../roles/artifactory-nginx/files/nginx.conf | 37 + .../roles/artifactory-nginx/handlers/main.yml | 2 + .../roles/artifactory-nginx/meta/main.yml | 53 + .../roles/artifactory-nginx/tasks/main.yml | 34 + .../templates/artifactory.conf.j2 | 43 + .../roles/artifactory-nginx/tests/inventory | 2 + .../roles/artifactory-nginx/tests/test.yml | 5 + .../roles/artifactory-nginx/vars/main.yml | 2 + .../roles/artifactory/.travis.yml | 29 + .../roles/artifactory/defaults/main.yml | 52 + .../roles/artifactory/handlers/main.yml | 10 + .../roles/artifactory/meta/exception.yml | 6 + .../roles/artifactory/meta/main.yml | 35 + .../roles/artifactory/meta/preferences.yml | 2 + .../roles/artifactory/meta/version.yml | 6 + .../artifactory/tasks/configure-licenses.yml | 43 + .../tasks/custom-data-directory.yml | 44 + .../roles/artifactory/tasks/main.yml | 132 + .../templates/artifactory.cluster.license.j2 | 6 + .../templates/artifactory.pro.license.j2 | 8 + .../artifactory/templates/binarystore.xml.j2 | 14 + .../templates/installer-info.json.j2 | 11 + .../roles/artifactory/templates/join.key.j2 | 1 + .../roles/artifactory/templates/master.key.j2 | 1 + .../artifactory/templates/system.yaml.j2 | 40 + .../roles/artifactory/vars/main.yml | 2 + .../roles/xray-ami/.travis.yml | 29 + .../roles/xray-ami/defaults/main.yml | 26 + .../roles/xray-ami/handlers/main.yml | 2 + .../roles/xray-ami/meta/main.yml | 53 + .../roles/xray-ami/tasks/Debian.yml | 37 + .../roles/xray-ami/tasks/RedHat.yml | 21 + .../roles/xray-ami/tasks/main.yml | 60 + .../xray-ami/templates/installer-info.json.j2 | 11 + .../roles/xray-ami/templates/join.key.j2 | 1 + .../roles/xray-ami/templates/master.key.j2 | 1 + .../roles/xray-ami/templates/system.yaml.j2 | 36 + .../roles/xray-ami/tests/inventory | 2 + .../roles/xray-ami/tests/test.yml | 5 + .../roles/xray-ami/vars/main.yml | 2 + .../roles/xray/.travis.yml | 29 + .../roles/xray/defaults/main.yml | 29 + .../roles/xray/handlers/main.yml | 2 + .../roles/xray/meta/main.yml | 53 + .../roles/xray/tasks/Debian.yml | 37 + .../roles/xray/tasks/RedHat.yml | 21 + .../xray/tasks/custom-data-directory.yml | 44 + .../roles/xray/tasks/initialize-pg-db.yml | 52 + .../roles/xray/tasks/main.yml | 80 + .../xray/templates/installer-info.json.j2 | 11 + .../roles/xray/templates/join.key.j2 | 1 + .../roles/xray/templates/master.key.j2 | 1 + .../roles/xray/templates/system.yaml.j2 | 39 + .../roles/xray/tests/inventory | 2 + .../roles/xray/tests/test.yml | 5 + .../roles/xray/vars/main.yml | 2 + .../site-artifactory.yml | 12 + .../v7174/cloudInstallerScripts/site-xray.yml | 5 + .../v7174/cloudInstallerScripts/xray-ami.yml | 5 + .../.github/workflows/master-docs-build.yml | 37 + .../submodules/quickstart-aws-vpc/.gitmodules | 4 + .../submodules/quickstart-aws-vpc/.nojekyll | 0 .../quickstart-aws-vpc/.taskcat.yml | 354 ++ .../submodules/quickstart-aws-vpc/LICENSE.txt | 201 + .../submodules/quickstart-aws-vpc/NOTICE.txt | 7 + .../submodules/quickstart-aws-vpc/README.md | 9 + .../ci/aws-vpc-3az-complete.json | 74 + .../ci/aws-vpc-3az-public.json | 74 + .../quickstart-aws-vpc/ci/aws-vpc-3az.json | 74 + .../ci/aws-vpc-4az-complete.json | 74 + .../ci/aws-vpc-4az-public.json | 74 + .../quickstart-aws-vpc/ci/aws-vpc-4az.json | 74 + .../ci/aws-vpc-complete.json | 74 + .../ci/aws-vpc-dedicated.json | 74 + .../ci/aws-vpc-defaults.json | 74 + .../quickstart-aws-vpc/ci/aws-vpc-public.json | 74 + .../ci/aws-vpc-sa-east-1.json | 74 + .../quickstart-aws-vpc/ci/taskcat.yml | 70 + .../docs/generated/parameters/index.adoc | 1 + .../docs/generated/regions/index.adoc | 1 + .../docs/generated/services/index.adoc | 1 + .../docs/generated/services/metadata.adoc | 1 + .../docs/images/architecture_diagram.png | Bin 0 -> 90606 bytes .../docs/images/aws-quickstart-graphic.png | Bin 0 -> 26468 bytes .../docs/images/cfn_outputs.png | Bin 0 -> 201384 bytes .../docs/partner_editable/_settings.adoc | 14 + .../partner_editable/additional_info.adoc | 323 ++ .../docs/partner_editable/architecture.adoc | 35 + .../docs/partner_editable/deploy_steps.adoc | 52 + .../partner_editable/deployment_options.adoc | 5 + .../partner_editable/faq_troubleshooting.adoc | 33 + .../docs/partner_editable/licenses.adoc | 3 + .../overview_target_and_usage.adoc | 11 + .../docs/partner_editable/pre-reqs.adoc | 1 + .../partner_editable/product_description.adoc | 18 + .../docs/partner_editable/regions.adoc | 29 + .../docs/partner_editable/service_limits.adoc | 7 + .../specialized_knowledge.adoc | 6 + .../templates/aws-vpc.template | 3591 +++++++++++++++++ .../templates/aws-vpc.template.yaml | 1809 +++++++++ .../quickstart-linux-bastion/.gitignore | 3 + .../quickstart-linux-bastion/.gitmodules | 4 + .../quickstart-linux-bastion/.taskcat.yml | 94 + .../quickstart-linux-bastion/LICENSE.txt | 202 + .../quickstart-linux-bastion/NOTICE.txt | 7 + .../quickstart-linux-bastion/README.md | 16 + .../scripts/auditing_configure.sh | 32 + .../scripts/banner_message.txt | 12 + .../scripts/bastion_bootstrap.sh | 380 ++ .../templates/linux-bastion-master.template | 299 ++ .../templates/linux-bastion.template | 725 ++++ ...ifactory-core-infrastructure.template.yaml | 425 ++ ...artifactory-ec2-existing-vpc.template.yaml | 1109 +++++ ...rog-artifactory-ec2-instance.template.yaml | 433 ++ ...jfrog-artifactory-ec2-master.template.yaml | 612 +++ ...-pro-ec2-existing-vpc-master.template.yaml | 355 ++ ...ctory-pro-ec2-new-vpc-master.template.yaml | 300 ++ .../jfrog-xray-ec2-instance.template.yaml | 326 ++ ...ifactory-core-infrastructure.template.yaml | 360 ++ ...artifactory-ec2-existing-vpc.template.yaml | 802 ++++ ...rog-artifactory-ec2-instance.template.yaml | 367 ++ .../jfrog-xray-ec2-instance.template.yaml | 255 ++ 318 files changed, 31530 insertions(+) create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/artifactory-ami.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/.travis.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/defaults/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/handlers/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/meta/exception.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/meta/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/meta/preferences.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/meta/version.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/tasks/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/templates/artifactory.cluster.license.j2 create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/templates/binarystore.xml.j2 create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/templates/installer-info.json.j2 create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/templates/join.key.j2 create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/templates/master.key.j2 create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/templates/system.yaml.j2 create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/vars/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/.travis.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/defaults/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/files/nginx.conf create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/handlers/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/meta/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/tasks/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/templates/artifactory.conf.j2 create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/tests/inventory create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/tests/test.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/vars/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/.travis.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/defaults/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/handlers/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/meta/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/tasks/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/templates/artifactory.conf.j2 create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/templates/certificate.key.j2 create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/templates/certificate.pem.j2 create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/tests/inventory create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/tests/test.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/vars/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/.travis.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/defaults/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/files/nginx.conf create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/handlers/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/meta/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/tasks/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/templates/artifactory.conf.j2 create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/tests/inventory create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/tests/test.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/vars/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/.travis.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/defaults/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/handlers/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/meta/exception.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/meta/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/meta/preferences.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/meta/version.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/tasks/configure-licenses.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/tasks/custom-data-directory.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/tasks/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/templates/artifactory.cluster.license.j2 create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/templates/artifactory.pro.license.j2 create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/templates/binarystore.xml.j2 create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/templates/installer-info.json.j2 create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/templates/join.key.j2 create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/templates/master.key.j2 create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/templates/system.yaml.j2 create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/vars/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/.travis.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/defaults/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/handlers/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/meta/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/tasks/Debian.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/tasks/RedHat.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/tasks/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/templates/installer-info.json.j2 create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/templates/join.key.j2 create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/templates/master.key.j2 create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/templates/system.yaml.j2 create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/tests/inventory create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/tests/test.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/vars/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/.travis.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/defaults/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/handlers/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/meta/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/tasks/Debian.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/tasks/RedHat.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/tasks/custom-data-directory.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/tasks/initialize-pg-db.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/tasks/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/templates/installer-info.json.j2 create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/templates/join.key.j2 create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/templates/master.key.j2 create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/templates/system.yaml.j2 create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/tests/inventory create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/tests/test.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/vars/main.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/site-artifactory.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/site-xray.yml create mode 100644 Amazon/artifactory7/latest/cloudInstallerScripts/xray-ami.yml create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/.github/workflows/master-docs-build.yml create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/.gitmodules create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/.nojekyll create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/.taskcat.yml create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/LICENSE.txt create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/NOTICE.txt create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/README.md create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-3az-complete.json create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-3az-public.json create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-3az.json create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-4az-complete.json create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-4az-public.json create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-4az.json create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-complete.json create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-dedicated.json create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-defaults.json create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-public.json create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-sa-east-1.json create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/taskcat.yml create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/generated/parameters/index.adoc create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/generated/regions/index.adoc create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/generated/services/index.adoc create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/generated/services/metadata.adoc create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/images/architecture_diagram.png create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/images/aws-quickstart-graphic.png create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/images/cfn_outputs.png create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/partner_editable/_settings.adoc create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/partner_editable/additional_info.adoc create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/partner_editable/architecture.adoc create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/partner_editable/deploy_steps.adoc create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/partner_editable/deployment_options.adoc create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/partner_editable/faq_troubleshooting.adoc create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/partner_editable/licenses.adoc create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/partner_editable/overview_target_and_usage.adoc create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/partner_editable/pre-reqs.adoc create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/partner_editable/product_description.adoc create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/partner_editable/regions.adoc create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/partner_editable/service_limits.adoc create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/partner_editable/specialized_knowledge.adoc create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/templates/aws-vpc.template create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/templates/aws-vpc.template.yaml create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/.gitignore create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/.gitmodules create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/.taskcat.yml create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/LICENSE.txt create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/NOTICE.txt create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/README.md create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/scripts/auditing_configure.sh create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/scripts/banner_message.txt create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/scripts/bastion_bootstrap.sh create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/templates/linux-bastion-master.template create mode 100644 Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/templates/linux-bastion.template create mode 100644 Amazon/artifactory7/latest/templates/jfrog-artifactory-core-infrastructure.template.yaml create mode 100644 Amazon/artifactory7/latest/templates/jfrog-artifactory-ec2-existing-vpc.template.yaml create mode 100644 Amazon/artifactory7/latest/templates/jfrog-artifactory-ec2-instance.template.yaml create mode 100644 Amazon/artifactory7/latest/templates/jfrog-artifactory-ec2-master.template.yaml create mode 100644 Amazon/artifactory7/latest/templates/jfrog-artifactory-pro-ec2-existing-vpc-master.template.yaml create mode 100644 Amazon/artifactory7/latest/templates/jfrog-artifactory-pro-ec2-new-vpc-master.template.yaml create mode 100644 Amazon/artifactory7/latest/templates/jfrog-xray-ec2-instance.template.yaml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/artifactory-ami.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/.travis.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/defaults/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/handlers/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/meta/exception.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/meta/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/meta/preferences.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/meta/version.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/tasks/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/templates/artifactory.cluster.license.j2 create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/templates/binarystore.xml.j2 create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/templates/installer-info.json.j2 create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/templates/join.key.j2 create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/templates/master.key.j2 create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/templates/system.yaml.j2 create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/vars/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/.travis.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/defaults/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/files/nginx.conf create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/handlers/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/meta/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/tasks/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/templates/artifactory.conf.j2 create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/tests/inventory create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/tests/test.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/vars/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/.travis.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/defaults/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/handlers/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/meta/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/tasks/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/templates/artifactory.conf.j2 create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/templates/certificate.key.j2 create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/templates/certificate.pem.j2 create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/tests/inventory create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/tests/test.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/vars/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/.travis.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/defaults/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/files/nginx.conf create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/handlers/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/meta/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/tasks/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/templates/artifactory.conf.j2 create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/tests/inventory create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/tests/test.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/vars/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/.travis.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/defaults/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/handlers/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/meta/exception.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/meta/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/meta/preferences.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/meta/version.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/tasks/configure-licenses.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/tasks/custom-data-directory.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/tasks/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/templates/artifactory.cluster.license.j2 create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/templates/artifactory.pro.license.j2 create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/templates/binarystore.xml.j2 create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/templates/installer-info.json.j2 create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/templates/join.key.j2 create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/templates/master.key.j2 create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/templates/system.yaml.j2 create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/vars/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/.travis.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/defaults/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/handlers/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/meta/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/tasks/Debian.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/tasks/RedHat.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/tasks/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/templates/installer-info.json.j2 create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/templates/join.key.j2 create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/templates/master.key.j2 create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/templates/system.yaml.j2 create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/tests/inventory create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/tests/test.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/vars/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/.travis.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/defaults/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/handlers/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/meta/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/tasks/Debian.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/tasks/RedHat.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/tasks/custom-data-directory.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/tasks/initialize-pg-db.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/tasks/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/templates/installer-info.json.j2 create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/templates/join.key.j2 create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/templates/master.key.j2 create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/templates/system.yaml.j2 create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/tests/inventory create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/tests/test.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/vars/main.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/site-artifactory.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/site-xray.yml create mode 100644 Amazon/artifactory7/v7174/cloudInstallerScripts/xray-ami.yml create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/.github/workflows/master-docs-build.yml create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/.gitmodules create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/.nojekyll create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/.taskcat.yml create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/LICENSE.txt create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/NOTICE.txt create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/README.md create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-3az-complete.json create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-3az-public.json create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-3az.json create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-4az-complete.json create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-4az-public.json create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-4az.json create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-complete.json create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-dedicated.json create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-defaults.json create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-public.json create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-sa-east-1.json create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/taskcat.yml create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/generated/parameters/index.adoc create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/generated/regions/index.adoc create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/generated/services/index.adoc create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/generated/services/metadata.adoc create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/images/architecture_diagram.png create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/images/aws-quickstart-graphic.png create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/images/cfn_outputs.png create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/partner_editable/_settings.adoc create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/partner_editable/additional_info.adoc create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/partner_editable/architecture.adoc create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/partner_editable/deploy_steps.adoc create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/partner_editable/deployment_options.adoc create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/partner_editable/faq_troubleshooting.adoc create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/partner_editable/licenses.adoc create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/partner_editable/overview_target_and_usage.adoc create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/partner_editable/pre-reqs.adoc create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/partner_editable/product_description.adoc create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/partner_editable/regions.adoc create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/partner_editable/service_limits.adoc create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/partner_editable/specialized_knowledge.adoc create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/templates/aws-vpc.template create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/templates/aws-vpc.template.yaml create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/.gitignore create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/.gitmodules create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/.taskcat.yml create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/LICENSE.txt create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/NOTICE.txt create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/README.md create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/scripts/auditing_configure.sh create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/scripts/banner_message.txt create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/scripts/bastion_bootstrap.sh create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/templates/linux-bastion-master.template create mode 100644 Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/templates/linux-bastion.template create mode 100644 Amazon/artifactory7/v7174/templates/jfrog-artifactory-core-infrastructure.template.yaml create mode 100644 Amazon/artifactory7/v7174/templates/jfrog-artifactory-ec2-existing-vpc.template.yaml create mode 100644 Amazon/artifactory7/v7174/templates/jfrog-artifactory-ec2-instance.template.yaml create mode 100644 Amazon/artifactory7/v7174/templates/jfrog-artifactory-ec2-master.template.yaml create mode 100644 Amazon/artifactory7/v7174/templates/jfrog-artifactory-pro-ec2-existing-vpc-master.template.yaml create mode 100644 Amazon/artifactory7/v7174/templates/jfrog-artifactory-pro-ec2-new-vpc-master.template.yaml create mode 100644 Amazon/artifactory7/v7174/templates/jfrog-xray-ec2-instance.template.yaml create mode 100644 Amazon/marketplace-jfrog-artifactory/v7174/templates/jfrog-artifactory-core-infrastructure.template.yaml create mode 100644 Amazon/marketplace-jfrog-artifactory/v7174/templates/jfrog-artifactory-ec2-existing-vpc.template.yaml create mode 100644 Amazon/marketplace-jfrog-artifactory/v7174/templates/jfrog-artifactory-ec2-instance.template.yaml create mode 100644 Amazon/marketplace-jfrog-artifactory/v7174/templates/jfrog-xray-ec2-instance.template.yaml diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/artifactory-ami.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/artifactory-ami.yml new file mode 100644 index 0000000..1e115c9 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/artifactory-ami.yml @@ -0,0 +1,5 @@ +- hosts: localhost + gather_facts: true + become: true + roles: + - name: artifactory-ami diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/.travis.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/.travis.yml new file mode 100644 index 0000000..36bbf62 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/.travis.yml @@ -0,0 +1,29 @@ +--- +language: python +python: "2.7" + +# Use the new container infrastructure +sudo: false + +# Install ansible +addons: + apt: + packages: + - python-pip + +install: + # Install ansible + - pip install ansible + + # Check ansible version + - ansible --version + + # Create ansible.cfg with correct roles_path + - printf '[defaults]\nroles_path=../' >ansible.cfg + +script: + # Basic role syntax check + - ansible-playbook tests/test.yml -i tests/inventory --syntax-check + +notifications: + webhooks: https://galaxy.ansible.com/api/v1/notifications/ \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/defaults/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/defaults/main.yml new file mode 100644 index 0000000..6d2c6f9 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/defaults/main.yml @@ -0,0 +1,60 @@ +--- +# defaults file for artifactory +# indicates were this collection was downlaoded from (galaxy, automation_hub, standalone) +ansible_marketplace: standalone + +# whether we are creating a AMI for Marketplace or just for configuring EC2 instance +ami_creation: false + +# The version of Artifactory to install +artifactory_version: 7.15.3 + +# licenses file - specify a licenses file or specify up to 5 licenses +artifactory_license1: +artifactory_license2: +artifactory_license3: +artifactory_license4: +artifactory_license5: +artifactory_license6: + +# whether to enable HA +artifactory_ha_enabled: true + +# value for whether a host is primary. this should be set in host vars +artifactory_is_primary: true + +# The location where Artifactory should install. +artifactory_download_directory: /opt/jfrog + +# The location where Artifactory should store data. +artifactory_file_store_dir: /data + +extra_java_opts: -server -Xms2g -Xmx14g -Xss256k -XX:+UseG1GC + + + +# Pick the Artifactory flavour to install, can be also cpp-ce, jcr, pro. +# for Artifactory, use following values +artifactory_flavour: pro +artifactory_tar: https://releases.jfrog.io/artifactory/artifactory-pro/org/artifactory/{{ artifactory_flavour }}/jfrog-artifactory-{{ artifactory_flavour }}/{{ artifactory_version }}/jfrog-artifactory-{{ artifactory_flavour }}-{{ artifactory_version }}-linux.tar.gz + +# for JCR, use following values +# artifactory_flavour: jcr +# artifactory_tar: https://dl.bintray.com/jfrog/artifactory/org/artifactory/{{ artifactory_flavour }}/jfrog-artifactory-{{ artifactory_flavour }}/{{ artifactory_version }}/jfrog-artifactory-{{ artifactory_flavour }}-{{ artifactory_version }}-linux.tar.gz + +artifactory_home: "{{ artifactory_download_directory }}/artifactory-{{ artifactory_flavour }}-{{ artifactory_version }}" +db_download_url: "https://jdbc.postgresql.org/download/postgresql-42.2.12.jar" + +artifactory_user: artifactory +artifactory_group: artifactory + +# Set the parameters required for the service. +service_list: + - name: artifactory + description: Start script for Artifactory + start_command: "{{ artifactory_home }}/bin/artifactory.sh start" + stop_command: "{{ artifactory_home }}/bin/artifactory.sh stop" + type: forking + status_pattern: artifactory + user_name: "{{ artifactory_user }}" + group_name: "{{ artifactory_group }}" diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/handlers/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/handlers/main.yml new file mode 100644 index 0000000..6f8fcda --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/handlers/main.yml @@ -0,0 +1,10 @@ +--- +# handlers file for artifactory +- name: systemctl daemon-reload + systemd: + daemon_reload: yes + +- name: restart artifactory + service: + name: artifactory + state: restarted diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/meta/exception.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/meta/exception.yml new file mode 100644 index 0000000..7de46df --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/meta/exception.yml @@ -0,0 +1,6 @@ +--- +exceptions: + - variation: Alpine + reason: Artifactory start/stop scripts don't properly work. + - variation: amazonlinux:1 + reason: "Shutting down artifactory: /usr/bin/java\nfinding\nUsing the default catalina management port (8015) to test shutdown\nArtifactory Tomcat already stopped" diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/meta/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/meta/main.yml new file mode 100644 index 0000000..0dc573a --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/meta/main.yml @@ -0,0 +1,35 @@ +--- +galaxy_info: + author: Robert de Bock + role_name: artifactory + description: Install and configure artifactory on your system. + license: Apache-2.0 + company: none + min_ansible_version: 2.8 + + platforms: + - name: Debian + versions: + - all + - name: EL + versions: + - 7 + - 8 + - name: Fedora + versions: + - all + - name: OpenSUSE + versions: + - all + - name: Ubuntu + versions: + - bionic + + galaxy_tags: + - artifactory + - centos + - redhat + - server + - system + +dependencies: [] diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/meta/preferences.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/meta/preferences.yml new file mode 100644 index 0000000..e7fdebf --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/meta/preferences.yml @@ -0,0 +1,2 @@ +--- +tox_parallel: yes diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/meta/version.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/meta/version.yml new file mode 100644 index 0000000..024188d --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/meta/version.yml @@ -0,0 +1,6 @@ +--- +project_name: JFrog +reference: "https://github.com/robertdebock/ansible-role-artifactory/blob/master/defaults/main.yml" +versions: + - name: Artifactory + url: "https://releases.jfrog.io/artifactory/" diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/tasks/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/tasks/main.yml new file mode 100644 index 0000000..68dc835 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/tasks/main.yml @@ -0,0 +1,82 @@ +--- +# tasks file for artifactory +- name: install nginx + include_role: + name: artifactory-nginx-ami + +- name: create group for artifactory + group: + name: "{{ artifactory_group }}" + state: present + become: yes + +- name: create user for artifactory + user: + name: "{{ artifactory_user }}" + group: "{{ artifactory_group }}" + system: yes + become: yes + +- name: ensure artifactory_download_directory exists + file: + path: "{{ artifactory_download_directory }}" + state: directory + become: yes + +- name: download artifactory + unarchive: + src: "{{ artifactory_tar }}" + dest: "{{ artifactory_download_directory }}" + remote_src: yes + owner: "{{ artifactory_user }}" + group: "{{ artifactory_group }}" + creates: "{{ artifactory_home }}" + become: yes + register: downloadartifactory + until: downloadartifactory is succeeded + retries: 3 + +- name: ensure artifactory_file_store_dir exists + file: + path: "{{ artifactory_file_store_dir }}" + state: directory + owner: "{{ artifactory_user }}" + group: "{{ artifactory_group }}" + become: yes + +- name: ensure data subdirectories exist + file: + path: "{{ artifactory_home }}/var/{{ item }}" + state: directory + owner: "{{ artifactory_user }}" + group: "{{ artifactory_group }}" + loop: + - "bootstrap" + - "etc" + become: yes + +- name: download database driver + get_url: + url: "{{ db_download_url }}" + dest: "{{ artifactory_home }}/var/bootstrap/artifactory/tomcat/lib" + owner: "{{ artifactory_user }}" + group: "{{ artifactory_group }}" + become: yes + +- name: clean up after creating ami + block: + - name: Remove SSH keys + file: + path: "{{ ssh_keys.dir }}" + state: absent + loop: + - dir: "/home/.jfrog_ami/.ssh/authorized_keys" + - dir: "/root/.ssh/authorized_keys" + - dir: "/home/centos/.ssh/authorized_keys" + loop_control: + loop_var: ssh_keys + + - name: shutdown VM + command: /sbin/shutdown -h now + ignore_errors: 'yes' + when: ami_creation diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/templates/artifactory.cluster.license.j2 b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/templates/artifactory.cluster.license.j2 new file mode 100644 index 0000000..ec2993b --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/templates/artifactory.cluster.license.j2 @@ -0,0 +1,37 @@ +{% if artifactory_license1 %} +{% if artifactory_license1|length %} +{{ artifactory_license1 }} +{% endif %} +{% endif %} +{% if artifactory_license2 %} + + +{% if artifactory_license2|length %} +{{ artifactory_license2 }} +{% endif %} +{% endif %} +{% if artifactory_license3 %} + + +{% if artifactory_license3|length %} +{{ artifactory_license3 }} +{% endif %} +{% endif %} +{% if artifactory_license4 %} + +{% if artifactory_license4|length %} +{{ artifactory_license4 }} +{% endif %} +{% endif %} +{% if artifactory_license5 %} + +{% if artifactory_license5|length %} +{{ artifactory_license5 }} +{% endif %} +{% endif %} +{% if artifactory_license6 %} + +{% if artifactory_license6|length %} +{{ artifactory_license6 }} +{% endif %} +{% endif %} diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/templates/binarystore.xml.j2 b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/templates/binarystore.xml.j2 new file mode 100644 index 0000000..f85f16f --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/templates/binarystore.xml.j2 @@ -0,0 +1,4 @@ + + + + diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/templates/installer-info.json.j2 b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/templates/installer-info.json.j2 new file mode 100644 index 0000000..f475256 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/templates/installer-info.json.j2 @@ -0,0 +1,12 @@ +{ + "productId": "Ansible_artifactory/1.0.0", + "features": [ + { + "featureId": "Partner/ACC-006973" + }, + { + "featureId": "Channel/{{ ansible_marketplace }}" + } + ] +} + diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/templates/join.key.j2 b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/templates/join.key.j2 new file mode 100644 index 0000000..17d05d2 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/templates/join.key.j2 @@ -0,0 +1 @@ +{{ join_key }} \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/templates/master.key.j2 b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/templates/master.key.j2 new file mode 100644 index 0000000..0462a64 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/templates/master.key.j2 @@ -0,0 +1 @@ +{{ master_key }} \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/templates/system.yaml.j2 b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/templates/system.yaml.j2 new file mode 100644 index 0000000..419a0c3 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/templates/system.yaml.j2 @@ -0,0 +1,38 @@ +## @formatter:off +## JFROG ARTIFACTORY SYSTEM CONFIGURATION FILE +## HOW TO USE: comment-out any field and keep the correct yaml indentation by deleting only the leading '#' character. +configVersion: 1 + +## NOTE: JFROG_HOME is a place holder for the JFrog root directory containing the deployed product, the home directory for all JFrog products. +## Replace JFROG_HOME with the real path! For example, in RPM install, JFROG_HOME=/opt/jfrog + +## NOTE: Sensitive information such as passwords and join key are encrypted on first read. +## NOTE: The provided commented key and value is the default. + +## SHARED CONFIGURATIONS +## A shared section for keys across all services in this config +shared: + + ## Node Settings + node: + ## A unique id to identify this node. + ## Default: auto generated at startup. + id: {{ ansible_machine_id }} + + ## Sets this node as primary in HA installation + primary: {{ artifactory_is_primary }} + + ## Sets this node as part of HA installation + haEnabled: {{ artifactory_ha_enabled }} + + ## Database Configuration + database: + ## One of: mysql, oracle, mssql, postgresql, mariadb + ## Default: Embedded derby + + ## Example for mysql/postgresql + type: "{{ db_type }}" + driver: "{{ db_driver }}" + url: "{{ db_url }}" + username: "{{ db_user }}" + password: "{{ db_password }}" \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/vars/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/vars/main.yml new file mode 100644 index 0000000..cd21505 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-ami/vars/main.yml @@ -0,0 +1,2 @@ +--- + diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/.travis.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/.travis.yml new file mode 100644 index 0000000..36bbf62 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/.travis.yml @@ -0,0 +1,29 @@ +--- +language: python +python: "2.7" + +# Use the new container infrastructure +sudo: false + +# Install ansible +addons: + apt: + packages: + - python-pip + +install: + # Install ansible + - pip install ansible + + # Check ansible version + - ansible --version + + # Create ansible.cfg with correct roles_path + - printf '[defaults]\nroles_path=../' >ansible.cfg + +script: + # Basic role syntax check + - ansible-playbook tests/test.yml -i tests/inventory --syntax-check + +notifications: + webhooks: https://galaxy.ansible.com/api/v1/notifications/ \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/defaults/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/defaults/main.yml new file mode 100644 index 0000000..6b28347 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/defaults/main.yml @@ -0,0 +1,2 @@ +--- +# defaults file for artifactory-nginx \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/files/nginx.conf b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/files/nginx.conf new file mode 100644 index 0000000..19f9422 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/files/nginx.conf @@ -0,0 +1,37 @@ +#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; + variables_hash_max_size 1024; + variables_hash_bucket_size 64; + server_names_hash_max_size 4096; + server_names_hash_bucket_size 128; + types_hash_max_size 2048; + types_hash_bucket_size 64; + proxy_read_timeout 2400s; + client_header_timeout 2400s; + client_body_timeout 2400s; + proxy_connect_timeout 75s; + proxy_send_timeout 2400s; + proxy_buffer_size 32k; + proxy_buffers 40 32k; + proxy_busy_buffers_size 64k; + proxy_temp_file_write_size 250m; + proxy_http_version 1.1; + client_body_buffer_size 128k; + 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; +} \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/handlers/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/handlers/main.yml new file mode 100644 index 0000000..d212386 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/handlers/main.yml @@ -0,0 +1,2 @@ +--- +# handlers file for artifactory-nginx \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/meta/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/meta/main.yml new file mode 100644 index 0000000..227ad9c --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/meta/main.yml @@ -0,0 +1,53 @@ +galaxy_info: + author: your name + description: your role description + company: your company (optional) + + # If the issue tracker for your role is not on github, uncomment the + # next line and provide a value + # issue_tracker_url: http://example.com/issue/tracker + + # Choose a valid license ID from https://spdx.org - some suggested licenses: + # - BSD-3-Clause (default) + # - MIT + # - GPL-2.0-or-later + # - GPL-3.0-only + # - Apache-2.0 + # - CC-BY-4.0 + license: license (GPL-2.0-or-later, MIT, etc) + + min_ansible_version: 2.9 + + # If this a Container Enabled role, provide the minimum Ansible Container version. + # min_ansible_container_version: + + # + # Provide a list of supported platforms, and for each platform a list of versions. + # If you don't wish to enumerate all versions for a particular platform, use 'all'. + # To view available platforms and versions (or releases), visit: + # https://galaxy.ansible.com/api/v1/platforms/ + # + # platforms: + # - name: Fedora + # versions: + # - all + # - 25 + # - name: SomePlatform + # versions: + # - all + # - 1.0 + # - 7 + # - 99.99 + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is a keyword that describes + # and categorizes the role. Users find roles by searching for tags. Be sure to + # remove the '[]' above, if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of alphanumeric characters. + # Maximum 20 tags per role. + +dependencies: [] + # List your role dependencies here, one per line. Be sure to remove the '[]' above, + # if you add dependencies to this list. + \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/tasks/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/tasks/main.yml new file mode 100644 index 0000000..abac794 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/tasks/main.yml @@ -0,0 +1,30 @@ +--- +- name: Add epel-release repo + yum: + name: epel-release + state: present + vars: + ansible_python_interpreter: /bin/python2 + +- name: Install nginx + yum: + name: nginx + state: present + vars: + ansible_python_interpreter: /bin/python2 + +- name: configure main nginx conf file. + copy: + src: nginx.conf + dest: /etc/nginx/nginx.conf + owner: root + group: root + mode: '0755' + become: yes + +- name: restart nginx + service: + name: nginx + state: restarted + enabled: yes + become: yes diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/templates/artifactory.conf.j2 b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/templates/artifactory.conf.j2 new file mode 100644 index 0000000..b36af22 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/templates/artifactory.conf.j2 @@ -0,0 +1,43 @@ +########################################################### +## this configuration was generated by JFrog Artifactory ## + ########################################################### + + ## add HA entries when ha is configure + upstream artifactory { + server 127.0.0.1:8082; +} + upstream artifactory-direct { + server 127.0.0.1:8081; +} + ## server configuration + server { + listen 80 ; + server_name _; + if ($http_x_forwarded_proto = '') { + set $http_x_forwarded_proto $scheme; + } + ## Application specific logs + access_log /var/log/nginx/artifactory-access.log; + error_log /var/log/nginx/artifactory-error.log; + rewrite ^/$ /ui/ redirect; + rewrite ^/ui$ /ui/ redirect; + chunked_transfer_encoding on; + client_max_body_size 0; + location / { + proxy_read_timeout 2400s; + proxy_pass_header Server; + proxy_cookie_path ~*^/.* /; + proxy_pass "http://artifactory"; + proxy_next_upstream error timeout non_idempotent; + proxy_next_upstream_tries 1; + proxy_set_header X-JFrog-Override-Base-Url $http_x_forwarded_proto://$host:$server_port; + 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; + + location ~ ^/artifactory/ { + proxy_pass http://artifactory-direct; + } + } +} \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/tests/inventory b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/tests/inventory new file mode 100644 index 0000000..878877b --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/tests/inventory @@ -0,0 +1,2 @@ +localhost + diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/tests/test.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/tests/test.yml new file mode 100644 index 0000000..7560bbb --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/tests/test.yml @@ -0,0 +1,5 @@ +--- +- hosts: localhost + remote_user: root + roles: + - artifactory-nginx \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/vars/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/vars/main.yml new file mode 100644 index 0000000..7465197 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ami/vars/main.yml @@ -0,0 +1,2 @@ +--- +# vars file for artifactory-nginx \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/.travis.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/.travis.yml new file mode 100644 index 0000000..36bbf62 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/.travis.yml @@ -0,0 +1,29 @@ +--- +language: python +python: "2.7" + +# Use the new container infrastructure +sudo: false + +# Install ansible +addons: + apt: + packages: + - python-pip + +install: + # Install ansible + - pip install ansible + + # Check ansible version + - ansible --version + + # Create ansible.cfg with correct roles_path + - printf '[defaults]\nroles_path=../' >ansible.cfg + +script: + # Basic role syntax check + - ansible-playbook tests/test.yml -i tests/inventory --syntax-check + +notifications: + webhooks: https://galaxy.ansible.com/api/v1/notifications/ \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/defaults/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/defaults/main.yml new file mode 100644 index 0000000..6b28347 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/defaults/main.yml @@ -0,0 +1,2 @@ +--- +# defaults file for artifactory-nginx \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/handlers/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/handlers/main.yml new file mode 100644 index 0000000..d212386 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/handlers/main.yml @@ -0,0 +1,2 @@ +--- +# handlers file for artifactory-nginx \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/meta/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/meta/main.yml new file mode 100644 index 0000000..227ad9c --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/meta/main.yml @@ -0,0 +1,53 @@ +galaxy_info: + author: your name + description: your role description + company: your company (optional) + + # If the issue tracker for your role is not on github, uncomment the + # next line and provide a value + # issue_tracker_url: http://example.com/issue/tracker + + # Choose a valid license ID from https://spdx.org - some suggested licenses: + # - BSD-3-Clause (default) + # - MIT + # - GPL-2.0-or-later + # - GPL-3.0-only + # - Apache-2.0 + # - CC-BY-4.0 + license: license (GPL-2.0-or-later, MIT, etc) + + min_ansible_version: 2.9 + + # If this a Container Enabled role, provide the minimum Ansible Container version. + # min_ansible_container_version: + + # + # Provide a list of supported platforms, and for each platform a list of versions. + # If you don't wish to enumerate all versions for a particular platform, use 'all'. + # To view available platforms and versions (or releases), visit: + # https://galaxy.ansible.com/api/v1/platforms/ + # + # platforms: + # - name: Fedora + # versions: + # - all + # - 25 + # - name: SomePlatform + # versions: + # - all + # - 1.0 + # - 7 + # - 99.99 + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is a keyword that describes + # and categorizes the role. Users find roles by searching for tags. Be sure to + # remove the '[]' above, if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of alphanumeric characters. + # Maximum 20 tags per role. + +dependencies: [] + # List your role dependencies here, one per line. Be sure to remove the '[]' above, + # if you add dependencies to this list. + \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/tasks/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/tasks/main.yml new file mode 100644 index 0000000..670c42d --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/tasks/main.yml @@ -0,0 +1,54 @@ +--- +# tasks file for artifactory-nginx +- name: configure the artifactory nginx conf + template: + src: artifactory.conf.j2 + dest: /etc/nginx/conf.d/artifactory.conf + owner: root + group: root + mode: '0755' + become: yes + +- name: ensure nginx dir exists + file: + path: "/var/opt/jfrog/nginx/ssl" + state: directory + become: yes + +- name: configure certificate + template: + src: certificate.pem.j2 + dest: "/var/opt/jfrog/nginx/ssl/cert.pem" + become: yes + +- name: ensure pki exists + file: + path: "/etc/pki/tls" + state: directory + become: yes + +- name: configure key + template: + src: certificate.key.j2 + dest: "/etc/pki/tls/cert.key" + become: yes + +- name: Allow apache to modify files in /srv/git_repos + sefcontext: + target: '/var/opt/jfrog/nginx/ssl/cert.pem' + setype: httpd_sys_content_t + state: present + vars: + ansible_python_interpreter: /bin/python2 + become: yes + +- name: Apply new SELinux file context to filesystem + command: restorecon -v /var/opt/jfrog/nginx/ssl/cert.pem + become: yes + +- name: restart nginx + service: + name: nginx + state: restarted + enabled: yes + become: yes diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/templates/artifactory.conf.j2 b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/templates/artifactory.conf.j2 new file mode 100644 index 0000000..13a2ac7 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/templates/artifactory.conf.j2 @@ -0,0 +1,49 @@ +########################################################### +## this configuration was generated by JFrog Artifactory ## + ########################################################### + + ## add HA entries when ha is configure + upstream artifactory { + server 127.0.0.1:8082; +} + upstream artifactory-direct { + server 127.0.0.1:8081; +} + ssl_protocols TLSv1.1 TLSv1.2; + ssl_certificate /var/opt/jfrog/nginx/ssl/cert.pem; + ssl_certificate_key /etc/pki/tls/cert.key; + ssl_session_cache shared:SSL:1m; + ssl_prefer_server_ciphers on; + ## server configuration + server { + listen 80; + listen 443 ssl http2; + server_name _; + if ($http_x_forwarded_proto = '') { + set $http_x_forwarded_proto $scheme; + } + ## Application specific logs + access_log /var/log/nginx/artifactory-access.log; + error_log /var/log/nginx/artifactory-error.log; + rewrite ^/$ /ui/ redirect; + rewrite ^/ui$ /ui/ redirect; + chunked_transfer_encoding on; + client_max_body_size 0; + location / { + proxy_read_timeout 2400s; + proxy_pass_header Server; + proxy_cookie_path ~*^/.* /; + proxy_pass "http://artifactory"; + proxy_next_upstream error timeout non_idempotent; + proxy_next_upstream_tries 1; + proxy_set_header X-JFrog-Override-Base-Url $http_x_forwarded_proto://$host:$server_port; + 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; + + location ~ ^/artifactory/ { + proxy_pass http://artifactory-direct; + } + } +} \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/templates/certificate.key.j2 b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/templates/certificate.key.j2 new file mode 100644 index 0000000..30f1d88 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/templates/certificate.key.j2 @@ -0,0 +1 @@ +{{ certificate_key | regex_replace('(-+(BEGIN|END) [A-Z ]*-+ ?|[A-Za-z0-9\+=/]* )', '\\1\n') }} diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/templates/certificate.pem.j2 b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/templates/certificate.pem.j2 new file mode 100644 index 0000000..d9dbd21 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/templates/certificate.pem.j2 @@ -0,0 +1 @@ +{{ certificate | regex_replace('(-+(BEGIN|END) [A-Z ]*-+ ?|[A-Za-z0-9\+=/]* )', '\\1\n') }} \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/tests/inventory b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/tests/inventory new file mode 100644 index 0000000..878877b --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/tests/inventory @@ -0,0 +1,2 @@ +localhost + diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/tests/test.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/tests/test.yml new file mode 100644 index 0000000..7560bbb --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/tests/test.yml @@ -0,0 +1,5 @@ +--- +- hosts: localhost + remote_user: root + roles: + - artifactory-nginx \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/vars/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/vars/main.yml new file mode 100644 index 0000000..7465197 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx-ssl/vars/main.yml @@ -0,0 +1,2 @@ +--- +# vars file for artifactory-nginx \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/.travis.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/.travis.yml new file mode 100644 index 0000000..36bbf62 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/.travis.yml @@ -0,0 +1,29 @@ +--- +language: python +python: "2.7" + +# Use the new container infrastructure +sudo: false + +# Install ansible +addons: + apt: + packages: + - python-pip + +install: + # Install ansible + - pip install ansible + + # Check ansible version + - ansible --version + + # Create ansible.cfg with correct roles_path + - printf '[defaults]\nroles_path=../' >ansible.cfg + +script: + # Basic role syntax check + - ansible-playbook tests/test.yml -i tests/inventory --syntax-check + +notifications: + webhooks: https://galaxy.ansible.com/api/v1/notifications/ \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/defaults/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/defaults/main.yml new file mode 100644 index 0000000..6b28347 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/defaults/main.yml @@ -0,0 +1,2 @@ +--- +# defaults file for artifactory-nginx \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/files/nginx.conf b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/files/nginx.conf new file mode 100644 index 0000000..19f9422 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/files/nginx.conf @@ -0,0 +1,37 @@ +#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; + variables_hash_max_size 1024; + variables_hash_bucket_size 64; + server_names_hash_max_size 4096; + server_names_hash_bucket_size 128; + types_hash_max_size 2048; + types_hash_bucket_size 64; + proxy_read_timeout 2400s; + client_header_timeout 2400s; + client_body_timeout 2400s; + proxy_connect_timeout 75s; + proxy_send_timeout 2400s; + proxy_buffer_size 32k; + proxy_buffers 40 32k; + proxy_busy_buffers_size 64k; + proxy_temp_file_write_size 250m; + proxy_http_version 1.1; + client_body_buffer_size 128k; + 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; +} \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/handlers/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/handlers/main.yml new file mode 100644 index 0000000..d212386 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/handlers/main.yml @@ -0,0 +1,2 @@ +--- +# handlers file for artifactory-nginx \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/meta/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/meta/main.yml new file mode 100644 index 0000000..227ad9c --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/meta/main.yml @@ -0,0 +1,53 @@ +galaxy_info: + author: your name + description: your role description + company: your company (optional) + + # If the issue tracker for your role is not on github, uncomment the + # next line and provide a value + # issue_tracker_url: http://example.com/issue/tracker + + # Choose a valid license ID from https://spdx.org - some suggested licenses: + # - BSD-3-Clause (default) + # - MIT + # - GPL-2.0-or-later + # - GPL-3.0-only + # - Apache-2.0 + # - CC-BY-4.0 + license: license (GPL-2.0-or-later, MIT, etc) + + min_ansible_version: 2.9 + + # If this a Container Enabled role, provide the minimum Ansible Container version. + # min_ansible_container_version: + + # + # Provide a list of supported platforms, and for each platform a list of versions. + # If you don't wish to enumerate all versions for a particular platform, use 'all'. + # To view available platforms and versions (or releases), visit: + # https://galaxy.ansible.com/api/v1/platforms/ + # + # platforms: + # - name: Fedora + # versions: + # - all + # - 25 + # - name: SomePlatform + # versions: + # - all + # - 1.0 + # - 7 + # - 99.99 + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is a keyword that describes + # and categorizes the role. Users find roles by searching for tags. Be sure to + # remove the '[]' above, if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of alphanumeric characters. + # Maximum 20 tags per role. + +dependencies: [] + # List your role dependencies here, one per line. Be sure to remove the '[]' above, + # if you add dependencies to this list. + \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/tasks/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/tasks/main.yml new file mode 100644 index 0000000..146ea79 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/tasks/main.yml @@ -0,0 +1,34 @@ +--- +- name: configure main nginx conf file. + copy: + src: nginx.conf + dest: /etc/nginx/nginx.conf + owner: root + group: root + mode: '0755' + become: yes + +- name: configure main nginx conf file. + copy: + src: nginx.conf + dest: /etc/nginx/nginx.conf + owner: root + group: root + mode: '0755' + become: yes + +- name: configure the artifactory nginx conf + template: + src: artifactory.conf.j2 + dest: /etc/nginx/conf.d/artifactory.conf + owner: root + group: root + mode: '0755' + become: yes + +- name: restart nginx + service: + name: nginx + state: restarted + enabled: yes + become: yes diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/templates/artifactory.conf.j2 b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/templates/artifactory.conf.j2 new file mode 100644 index 0000000..b36af22 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/templates/artifactory.conf.j2 @@ -0,0 +1,43 @@ +########################################################### +## this configuration was generated by JFrog Artifactory ## + ########################################################### + + ## add HA entries when ha is configure + upstream artifactory { + server 127.0.0.1:8082; +} + upstream artifactory-direct { + server 127.0.0.1:8081; +} + ## server configuration + server { + listen 80 ; + server_name _; + if ($http_x_forwarded_proto = '') { + set $http_x_forwarded_proto $scheme; + } + ## Application specific logs + access_log /var/log/nginx/artifactory-access.log; + error_log /var/log/nginx/artifactory-error.log; + rewrite ^/$ /ui/ redirect; + rewrite ^/ui$ /ui/ redirect; + chunked_transfer_encoding on; + client_max_body_size 0; + location / { + proxy_read_timeout 2400s; + proxy_pass_header Server; + proxy_cookie_path ~*^/.* /; + proxy_pass "http://artifactory"; + proxy_next_upstream error timeout non_idempotent; + proxy_next_upstream_tries 1; + proxy_set_header X-JFrog-Override-Base-Url $http_x_forwarded_proto://$host:$server_port; + 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; + + location ~ ^/artifactory/ { + proxy_pass http://artifactory-direct; + } + } +} \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/tests/inventory b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/tests/inventory new file mode 100644 index 0000000..878877b --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/tests/inventory @@ -0,0 +1,2 @@ +localhost + diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/tests/test.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/tests/test.yml new file mode 100644 index 0000000..7560bbb --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/tests/test.yml @@ -0,0 +1,5 @@ +--- +- hosts: localhost + remote_user: root + roles: + - artifactory-nginx \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/vars/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/vars/main.yml new file mode 100644 index 0000000..7465197 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory-nginx/vars/main.yml @@ -0,0 +1,2 @@ +--- +# vars file for artifactory-nginx \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/.travis.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/.travis.yml new file mode 100644 index 0000000..36bbf62 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/.travis.yml @@ -0,0 +1,29 @@ +--- +language: python +python: "2.7" + +# Use the new container infrastructure +sudo: false + +# Install ansible +addons: + apt: + packages: + - python-pip + +install: + # Install ansible + - pip install ansible + + # Check ansible version + - ansible --version + + # Create ansible.cfg with correct roles_path + - printf '[defaults]\nroles_path=../' >ansible.cfg + +script: + # Basic role syntax check + - ansible-playbook tests/test.yml -i tests/inventory --syntax-check + +notifications: + webhooks: https://galaxy.ansible.com/api/v1/notifications/ \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/defaults/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/defaults/main.yml new file mode 100644 index 0000000..bbcfe91 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/defaults/main.yml @@ -0,0 +1,52 @@ +--- +# defaults file for artifactory +# indicates were this collection was downlaoded from (galaxy, automation_hub, standalone) +ansible_marketplace: standalone + +# The version of Artifactory to install +artifactory_version: 7.15.3 + +# licenses - cluster license content in json +artifactory_licenses: + +# whether to enable HA +artifactory_ha_enabled: true + +# value for whether a host is primary. this should be set in host vars +artifactory_is_primary: true + +# The location where Artifactory should install. +artifactory_download_directory: /opt/jfrog + +# The location where Artifactory should store data. +artifactory_file_store_dir: /data + +# whether to customer data directory +use_custom_data_directory: false + +# location for customer directory. Will be symlink to as artifactory/var +custom_data_directory: /artifactory-user-data + +# Pick the Artifactory flavour to install, can be also cpp-ce, jcr, pro. +artifactory_flavour: pro + +extra_java_opts: -server -Xms2g -Xmx14g -Xss256k -XX:+UseG1GC + +artifactory_tar: https://releases.jfrog.io/artifactory/artifactory-pro/org/artifactory/{{ artifactory_flavour }}/jfrog-artifactory-{{ artifactory_flavour }}/{{ artifactory_version }}/jfrog-artifactory-{{ artifactory_flavour }}-{{ artifactory_version }}-linux.tar.gz +artifactory_home: "{{ artifactory_download_directory }}/artifactory-{{ artifactory_flavour }}-{{ artifactory_version }}" + +artifactory_user: artifactory +artifactory_group: artifactory + +# Set the parameters required for the service. +service_list: + - name: artifactory + description: Start script for Artifactory + start_command: "{{ artifactory_home }}/bin/artifactory.sh start" + stop_command: "{{ artifactory_home }}/bin/artifactory.sh stop" + type: forking + status_pattern: artifactory + user_name: "{{ artifactory_user }}" + group_name: "{{ artifactory_group }}" + +product_id: CloudFormation_QS_EC2/1.0.0 diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/handlers/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/handlers/main.yml new file mode 100644 index 0000000..6f8fcda --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/handlers/main.yml @@ -0,0 +1,10 @@ +--- +# handlers file for artifactory +- name: systemctl daemon-reload + systemd: + daemon_reload: yes + +- name: restart artifactory + service: + name: artifactory + state: restarted diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/meta/exception.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/meta/exception.yml new file mode 100644 index 0000000..7de46df --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/meta/exception.yml @@ -0,0 +1,6 @@ +--- +exceptions: + - variation: Alpine + reason: Artifactory start/stop scripts don't properly work. + - variation: amazonlinux:1 + reason: "Shutting down artifactory: /usr/bin/java\nfinding\nUsing the default catalina management port (8015) to test shutdown\nArtifactory Tomcat already stopped" diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/meta/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/meta/main.yml new file mode 100644 index 0000000..0dc573a --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/meta/main.yml @@ -0,0 +1,35 @@ +--- +galaxy_info: + author: Robert de Bock + role_name: artifactory + description: Install and configure artifactory on your system. + license: Apache-2.0 + company: none + min_ansible_version: 2.8 + + platforms: + - name: Debian + versions: + - all + - name: EL + versions: + - 7 + - 8 + - name: Fedora + versions: + - all + - name: OpenSUSE + versions: + - all + - name: Ubuntu + versions: + - bionic + + galaxy_tags: + - artifactory + - centos + - redhat + - server + - system + +dependencies: [] diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/meta/preferences.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/meta/preferences.yml new file mode 100644 index 0000000..e7fdebf --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/meta/preferences.yml @@ -0,0 +1,2 @@ +--- +tox_parallel: yes diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/meta/version.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/meta/version.yml new file mode 100644 index 0000000..024188d --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/meta/version.yml @@ -0,0 +1,6 @@ +--- +project_name: JFrog +reference: "https://github.com/robertdebock/ansible-role-artifactory/blob/master/defaults/main.yml" +versions: + - name: Artifactory + url: "https://releases.jfrog.io/artifactory/" diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/tasks/configure-licenses.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/tasks/configure-licenses.yml new file mode 100644 index 0000000..996f68e --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/tasks/configure-licenses.yml @@ -0,0 +1,43 @@ +- name: set license for Enterprise + block: + - name: use license file + copy: + src: "{{ artifactory_license_file }}" + dest: "{{ artifactory_home }}/var/etc/artifactory/artifactory.cluster.license" + force: no # only copy if file doesn't exist + become: yes + when: artifactory_license_file is defined and artifactory_is_primary == true + + - name: use license strings + vars: + artifactory_licenses_dict: "{{ artifactory_licenses | default('{}') }}" + + template: + src: artifactory.cluster.license.j2 + dest: "{{ artifactory_home }}/var/etc/artifactory/artifactory.cluster.license" + force: no # only create if file doesn't exist + become: yes + when: artifactory_license_file is not defined and artifactory_is_primary == true + when: artifactory_ha_enabled + +- name: set license for Pro + block: + - name: use license file + copy: + src: "{{ artifactory_license_file }}" + dest: "{{ artifactory_home }}/var/etc/artifactory/artifactory.lic" + force: no # only create if file doesn't exist + become: yes + when: artifactory_license_file is defined + + - name: use license strings + vars: + artifactory_licenses_dict: "{{ artifactory_licenses | default('{}') }}" + + template: + src: artifactory.pro.license.j2 + dest: "{{ artifactory_home }}/var/etc/artifactory/artifactory.lic" + force: no # only create if file doesn't exist + become: yes + when: artifactory_license_file is not defined + when: not artifactory_ha_enabled diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/tasks/custom-data-directory.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/tasks/custom-data-directory.yml new file mode 100644 index 0000000..4799a8b --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/tasks/custom-data-directory.yml @@ -0,0 +1,44 @@ +- name: setup directory symlink for using custom data directory/volume + block: + - name: Create a xfs filesystem on /dev/nvme1n1 + # First non-root device is always mapped to /dev/nvme1n1 + # See: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nvme-ebs-volumes.html + community.general.filesystem: + dev: /dev/nvme1n1 + fstype: xfs + + - name: ensure external data directory exists + file: + path: "{{ custom_data_directory }}" + state: directory + + - name: Mount the EBS volume + ansible.posix.mount: + path: "{{ custom_data_directory }}" + src: /dev/nvme1n1 + state: mounted + fstype: xfs + + - name: set custom data directory permission + file: + path: "{{ custom_data_directory }}" + state: directory + recurse: yes + owner: "{{ artifactory_user }}" + group: "{{ artifactory_group }}" + mode: "u=rwX,g=rwX,o=rwX" + + - name: remove var directory if exists + file: + path: "{{ artifactory_home }}/var" + state: absent + + - name: symlink custom data directory to var + file: + src: "{{ custom_data_directory }}" + path: "{{ artifactory_home }}/var" + state: link + owner: "{{ artifactory_user }}" + group: "{{ artifactory_group }}" + become: yes + when: use_custom_data_directory and custom_data_directory is defined diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/tasks/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/tasks/main.yml new file mode 100644 index 0000000..25b1143 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/tasks/main.yml @@ -0,0 +1,132 @@ +--- +# tasks file for artifactory +- name: Set artifactory major version + set_fact: + artifactory_major_verion: "{{ artifactory_version.split('.')[0] }}" + +- name: create group for artifactory + group: + name: "{{ artifactory_group }}" + state: present + become: yes + +- name: create user for artifactory + user: + name: "{{ artifactory_user }}" + group: "{{ artifactory_group }}" + system: yes + become: yes + +- name: ensure artifactory_download_directory exists + file: + path: "{{ artifactory_download_directory }}" + state: directory + become: yes + +- name: ensure artifactory_file_store_dir exists + file: + path: "{{ artifactory_file_store_dir }}" + state: directory + owner: "{{ artifactory_user }}" + group: "{{ artifactory_group }}" + become: yes + +- name: setup directory symlink for using custom data directory/volume + include_tasks: custom-data-directory.yml + when: use_custom_data_directory and custom_data_directory is defined + +- name: ensure data subdirectories exist and have correct ownership + file: + path: "{{ artifactory_home }}/var/{{ item }}" + state: directory + owner: "{{ artifactory_user }}" + group: "{{ artifactory_group }}" + loop: + - "bootstrap" + - "etc" + - "data" + - "etc/info" + - "etc/security" + - "etc/artifactory" + become: yes + +- name: check if system yaml file exits + stat: + path: "{{ artifactory_home }}/var/etc/system.yaml" + register: system_yaml + +- name: use specified system yaml + copy: + src: "{{ system_file }}" + dest: "{{ artifactory_home }}/var/etc/system.yaml" + become: yes + when: system_file is defined and not system_yaml.stat.exists + +- name: configure system yaml + template: + src: system.yaml.j2 + dest: "{{ artifactory_home }}/var/etc/system.yaml" + become: yes + when: system_file is not defined and not system_yaml.stat.exists + +- name: configure master key + template: + src: master.key.j2 + dest: "{{ artifactory_home }}/var/etc/security/master.key" + force: no # only create if file doesn't exist + become: yes + +- name: configure join key + template: + src: join.key.j2 + dest: "{{ artifactory_home }}/var/etc/security/join.key" + force: no # only create if file doesn't exist + become: yes + +- name: configure installer info + template: + src: installer-info.json.j2 + dest: "{{ artifactory_home }}/var/etc/info/installer-info.json" + become: yes + +- name: use specified binary store file + copy: + src: "{{ binary_store_file }}" + dest: "{{ artifactory_home }}/var/etc/artifactory/binarystore.xml" + force: no # only copy if file doesn't exist + become: yes + when: binary_store_file is defined + +- name: set default binary store + template: + src: binarystore.xml.j2 + dest: "{{ artifactory_home }}/var/etc/artifactory/binarystore.xml" + force: no # only create if file doesn't exist + become: yes + when: binary_store_file is not defined + +- name: configure licenses + include_tasks: configure-licenses.yml + +- name: create artifactory service + shell: "{{ artifactory_home }}/app/bin/installService.sh" + become: yes + +- name: start and enable the primary node + service: + name: artifactory + state: restarted + become: yes + when: artifactory_is_primary == true + +- name: random wait before restarting to prevent secondary nodes from hitting DB first + pause: + seconds: "{{ 120 | random + 10}}" + when: artifactory_is_primary == false + +- name: start and enable the secondary nodes + service: + name: artifactory + state: restarted + become: yes + when: artifactory_is_primary == false diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/templates/artifactory.cluster.license.j2 b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/templates/artifactory.cluster.license.j2 new file mode 100644 index 0000000..aa30261 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/templates/artifactory.cluster.license.j2 @@ -0,0 +1,6 @@ +{% if artifactory_licenses_dict %} +{% for key in (artifactory_licenses_dict.keys() | select('match', '^ArtifactoryLicense\d$')) %} +{{ artifactory_licenses_dict[key] }} + +{% endfor %} +{% endif %} diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/templates/artifactory.pro.license.j2 b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/templates/artifactory.pro.license.j2 new file mode 100644 index 0000000..f6881c9 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/templates/artifactory.pro.license.j2 @@ -0,0 +1,8 @@ +{% if artifactory_licenses_dict %} +{% for key in (artifactory_licenses_dict.keys() | select('match', '^ArtifactoryLicense\d$')) %} +{% if loop.first %} + {{ artifactory_licenses_dict[key] }} +{% endif %} + +{% endfor %} +{% endif %} diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/templates/binarystore.xml.j2 b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/templates/binarystore.xml.j2 new file mode 100644 index 0000000..f12dba1 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/templates/binarystore.xml.j2 @@ -0,0 +1,14 @@ + + + + + + + + s3.{{ s3_region }}.amazonaws.com + {{ s3_bucket }} + artifactory/filestore + {{ s3_region }} + true + + diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/templates/installer-info.json.j2 b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/templates/installer-info.json.j2 new file mode 100644 index 0000000..9e78f0e --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/templates/installer-info.json.j2 @@ -0,0 +1,11 @@ +{ + "productId": "{{ product_id }}", + "features": [ + { + "featureId": "Partner/ACC-006973" + }, + { + "featureId": "Channel/{{ ansible_marketplace }}" + } + ] +} diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/templates/join.key.j2 b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/templates/join.key.j2 new file mode 100644 index 0000000..17d05d2 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/templates/join.key.j2 @@ -0,0 +1 @@ +{{ join_key }} \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/templates/master.key.j2 b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/templates/master.key.j2 new file mode 100644 index 0000000..0462a64 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/templates/master.key.j2 @@ -0,0 +1 @@ +{{ master_key }} \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/templates/system.yaml.j2 b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/templates/system.yaml.j2 new file mode 100644 index 0000000..dc58c2c --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/templates/system.yaml.j2 @@ -0,0 +1,40 @@ +## @formatter:off +## JFROG ARTIFACTORY SYSTEM CONFIGURATION FILE +## HOW TO USE: comment-out any field and keep the correct yaml indentation by deleting only the leading '#' character. +configVersion: 1 + +## NOTE: JFROG_HOME is a place holder for the JFrog root directory containing the deployed product, the home directory for all JFrog products. +## Replace JFROG_HOME with the real path! For example, in RPM install, JFROG_HOME=/opt/jfrog + +## NOTE: Sensitive information such as passwords and join key are encrypted on first read. +## NOTE: The provided commented key and value is the default. + +## SHARED CONFIGURATIONS +## A shared section for keys across all services in this config +shared: + ## Java options + extraJavaOpts: "{{ extra_java_opts }}" + + ## Node Settings + node: + ## A unique id to identify this node. + ## Default: auto generated at startup. + id: {{ ansible_machine_id }} + + ## Sets this node as primary in HA installation + primary: {{ artifactory_is_primary }} + + ## Sets this node as part of HA installation + haEnabled: {{ artifactory_ha_enabled }} + + ## Database Configuration + database: + ## One of: mysql, oracle, mssql, postgresql, mariadb + ## Default: Embedded derby + + ## Example for mysql/postgresql + type: "{{ db_type }}" + driver: "{{ db_driver }}" + url: "{{ db_url }}" + username: "{{ db_user }}" + password: "{{ db_password }}" diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/vars/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/vars/main.yml new file mode 100644 index 0000000..cd21505 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/artifactory/vars/main.yml @@ -0,0 +1,2 @@ +--- + diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/.travis.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/.travis.yml new file mode 100644 index 0000000..36bbf62 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/.travis.yml @@ -0,0 +1,29 @@ +--- +language: python +python: "2.7" + +# Use the new container infrastructure +sudo: false + +# Install ansible +addons: + apt: + packages: + - python-pip + +install: + # Install ansible + - pip install ansible + + # Check ansible version + - ansible --version + + # Create ansible.cfg with correct roles_path + - printf '[defaults]\nroles_path=../' >ansible.cfg + +script: + # Basic role syntax check + - ansible-playbook tests/test.yml -i tests/inventory --syntax-check + +notifications: + webhooks: https://galaxy.ansible.com/api/v1/notifications/ \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/defaults/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/defaults/main.yml new file mode 100644 index 0000000..f547a88 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/defaults/main.yml @@ -0,0 +1,26 @@ +--- +# defaults file for xray +# indicates were this collection was downlaoded from (galaxy, automation_hub, standalone) +ansible_marketplace: standalone + +# whether we are creating a AMI for Marketplace or just for configuring EC2 instance +ami_creation: false + +# The version of xray to install +xray_version: 3.17.4 + +# whether to enable HA +xray_ha_enabled: true + +# The location where xray should install. +xray_download_directory: /opt/jfrog + +# The remote xray download file +xray_tar: https://releases.jfrog.io/artifactory/jfrog-xray/xray-linux/{{ xray_version }}/jfrog-xray-{{ xray_version }}-linux.tar.gz + +#The xray install directory +xray_home: "{{ xray_download_directory }}/jfrog-xray-{{ xray_version }}-linux" + +#xray users and groups +xray_user: xray +xray_group: xray diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/handlers/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/handlers/main.yml new file mode 100644 index 0000000..f236fe3 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/handlers/main.yml @@ -0,0 +1,2 @@ +--- +# handlers file for xray \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/meta/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/meta/main.yml new file mode 100644 index 0000000..227ad9c --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/meta/main.yml @@ -0,0 +1,53 @@ +galaxy_info: + author: your name + description: your role description + company: your company (optional) + + # If the issue tracker for your role is not on github, uncomment the + # next line and provide a value + # issue_tracker_url: http://example.com/issue/tracker + + # Choose a valid license ID from https://spdx.org - some suggested licenses: + # - BSD-3-Clause (default) + # - MIT + # - GPL-2.0-or-later + # - GPL-3.0-only + # - Apache-2.0 + # - CC-BY-4.0 + license: license (GPL-2.0-or-later, MIT, etc) + + min_ansible_version: 2.9 + + # If this a Container Enabled role, provide the minimum Ansible Container version. + # min_ansible_container_version: + + # + # Provide a list of supported platforms, and for each platform a list of versions. + # If you don't wish to enumerate all versions for a particular platform, use 'all'. + # To view available platforms and versions (or releases), visit: + # https://galaxy.ansible.com/api/v1/platforms/ + # + # platforms: + # - name: Fedora + # versions: + # - all + # - 25 + # - name: SomePlatform + # versions: + # - all + # - 1.0 + # - 7 + # - 99.99 + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is a keyword that describes + # and categorizes the role. Users find roles by searching for tags. Be sure to + # remove the '[]' above, if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of alphanumeric characters. + # Maximum 20 tags per role. + +dependencies: [] + # List your role dependencies here, one per line. Be sure to remove the '[]' above, + # if you add dependencies to this list. + \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/tasks/Debian.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/tasks/Debian.yml new file mode 100644 index 0000000..420c2d0 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/tasks/Debian.yml @@ -0,0 +1,37 @@ +--- +- name: Install db5.3-util + apt: + deb: "{{ xray_home }}/app/third-party/misc/db5.3-util_5.3.28-3ubuntu3_amd64.deb" + ignore_errors: yes + become: yes + +- name: Install db-util + apt: + deb: "{{ xray_home }}/app/third-party/misc/db-util_1_3a5.3.21exp1ubuntu1_all.deb" + ignore_errors: yes + become: yes + +- name: Install libssl + apt: + deb: "{{ xray_home }}/app/third-party/rabbitmq/libssl1.1_1.1.0j-1_deb9u1_amd64.deb" + ignore_errors: yes + become: yes + +- name: Install socat + apt: + deb: "{{ xray_home }}/app/third-party/rabbitmq/socat_1.7.3.1-2+deb9u1_amd64.deb" + become: yes + +- name: Install libwxbase3.0-0v5 + apt: + name: libwxbase3.0-0v5 + update_cache: yes + state: present + ignore_errors: yes + become: yes + +- name: Install erlang + apt: + deb: "{{ xray_home }}/app/third-party/rabbitmq/esl-erlang_21.2.1-1~ubuntu~xenial_amd64.deb" + become: yes + diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/tasks/RedHat.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/tasks/RedHat.yml new file mode 100644 index 0000000..efdc081 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/tasks/RedHat.yml @@ -0,0 +1,21 @@ +--- +- name: Install db-utl + yum: + name: "{{ xray_home }}/app/third-party/misc/libdb-utils-5.3.21-19.el7.x86_64.rpm" + state: present + vars: + ansible_python_interpreter: /bin/python2 + +- name: Install socat + yum: + name: "{{ xray_home }}/app/third-party/rabbitmq/socat-1.7.3.2-2.el7.x86_64.rpm" + state: present + vars: + ansible_python_interpreter: /bin/python2 + +- name: Install erlang + yum: + name: "{{ xray_home }}/app/third-party/rabbitmq/erlang-22.3.4-1.el7.x86_64.rpm" + state: present + vars: + ansible_python_interpreter: /bin/python2 diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/tasks/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/tasks/main.yml new file mode 100644 index 0000000..6bf93a5 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/tasks/main.yml @@ -0,0 +1,60 @@ +--- +- name: create group for xray + group: + name: "{{ xray_group }}" + state: present + become: yes + +- name: create user for xray + user: + name: "{{ xray_user }}" + group: "{{ xray_group }}" + system: yes + become: yes + +- name: ensure xray_download_directory exists + file: + path: "{{ xray_download_directory }}" + state: directory + become: yes + +- name: download xray + unarchive: + src: "{{ xray_tar }}" + dest: "{{ xray_download_directory }}" + remote_src: yes + owner: "{{ xray_user }}" + group: "{{ xray_group }}" + creates: "{{ xray_home }}" + become: yes + register: downloadxray + until: downloadxray is succeeded + retries: 3 + +- name: perform prerequisite installation + include_tasks: "{{ ansible_os_family }}.yml" + +- name: ensure etc exists + file: + path: "{{ xray_home }}/var/etc" + state: directory + owner: "{{ xray_user }}" + group: "{{ xray_group }}" + become: yes + +- name: Remove SSH keys + file: + path: "{{ ssh_keys.dir }}" + state: absent + loop: + - dir: "/home/.xray_ami/.ssh/authorized_keys" + - dir: "/root/.ssh/authorized_keys" + - dir: "/home/centos/.ssh/authorized_keys" + loop_control: + loop_var: ssh_keys + when: ami_creation + +- name: shutdown VM + command: /sbin/shutdown -h now + ignore_errors: 'yes' + when: ami_creation diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/templates/installer-info.json.j2 b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/templates/installer-info.json.j2 new file mode 100644 index 0000000..a76c88c --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/templates/installer-info.json.j2 @@ -0,0 +1,11 @@ +{ + "productId": "Ansible_artifactory/1.0.0", + "features": [ + { + "featureId": "Partner/ACC-006973" + }, + { + "featureId": "Channel/{{ ansible_marketplace }}" + } + ] +} \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/templates/join.key.j2 b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/templates/join.key.j2 new file mode 100644 index 0000000..17d05d2 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/templates/join.key.j2 @@ -0,0 +1 @@ +{{ join_key }} \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/templates/master.key.j2 b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/templates/master.key.j2 new file mode 100644 index 0000000..0462a64 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/templates/master.key.j2 @@ -0,0 +1 @@ +{{ master_key }} \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/templates/system.yaml.j2 b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/templates/system.yaml.j2 new file mode 100644 index 0000000..206eb77 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/templates/system.yaml.j2 @@ -0,0 +1,36 @@ +## @formatter:off +## JFROG ARTIFACTORY SYSTEM CONFIGURATION FILE +## HOW TO USE: comment-out any field and keep the correct yaml indentation by deleting only the leading '#' character. +configVersion: 1 + +## NOTE: JFROG_HOME is a place holder for the JFrog root directory containing the deployed product, the home directory for all JFrog products. +## Replace JFROG_HOME with the real path! For example, in RPM install, JFROG_HOME=/opt/jfrog + +## NOTE: Sensitive information such as passwords and join key are encrypted on first read. +## NOTE: The provided commented key and value is the default. + +## SHARED CONFIGURATIONS +## A shared section for keys across all services in this config +shared: + ## Base URL of the JFrog Platform Deployment (JPD) + ## This is the URL to the machine where JFrog Artifactory is deployed, or the load balancer pointing to it. It is recommended to use DNS names rather than direct IPs. + ## Examples: "http://jfrog.acme.com" or "http://10.20.30.40:8082" + jfrogUrl: {{ jfrog_url }} + + ## Node Settings + node: + ## A unique id to identify this node. + ## Default: auto generated at startup. + id: {{ ansible_machine_id }} + + ## Database Configuration + database: + ## One of: mysql, oracle, mssql, postgresql, mariadb + ## Default: Embedded derby + + ## Example for mysql/postgresql + type: "{{ db_type }}" + driver: "{{ db_driver }}" + url: "{{ db_url }}" + username: "{{ db_user }}" + password: "{{ db_password }}" \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/tests/inventory b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/tests/inventory new file mode 100644 index 0000000..878877b --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/tests/inventory @@ -0,0 +1,2 @@ +localhost + diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/tests/test.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/tests/test.yml new file mode 100644 index 0000000..f296da6 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/tests/test.yml @@ -0,0 +1,5 @@ +--- +- hosts: localhost + remote_user: root + roles: + - xray \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/vars/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/vars/main.yml new file mode 100644 index 0000000..55363e6 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray-ami/vars/main.yml @@ -0,0 +1,2 @@ +--- +# vars file for xray \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/.travis.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/.travis.yml new file mode 100644 index 0000000..36bbf62 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/.travis.yml @@ -0,0 +1,29 @@ +--- +language: python +python: "2.7" + +# Use the new container infrastructure +sudo: false + +# Install ansible +addons: + apt: + packages: + - python-pip + +install: + # Install ansible + - pip install ansible + + # Check ansible version + - ansible --version + + # Create ansible.cfg with correct roles_path + - printf '[defaults]\nroles_path=../' >ansible.cfg + +script: + # Basic role syntax check + - ansible-playbook tests/test.yml -i tests/inventory --syntax-check + +notifications: + webhooks: https://galaxy.ansible.com/api/v1/notifications/ \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/defaults/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/defaults/main.yml new file mode 100644 index 0000000..77a3f0c --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/defaults/main.yml @@ -0,0 +1,29 @@ +--- +# defaults file for xray +# indicates were this collection was downlaoded from (galaxy, automation_hub, standalone) +ansible_marketplace: standalone + +# The version of xray to install +xray_version: 3.17.4 + +# whether to enable HA +xray_ha_enabled: true + +# The location where xray should install. +xray_download_directory: /opt/jfrog + +# whether to customer data directory +use_custom_data_directory: false + +# location for customer directory. Will be symlink to as artifactory/var +custom_data_directory: /xray-user-data + +# The remote xray download file +xray_tar: https://releases.jfrog.io/artifactory/jfrog-xray/xray-linux/{{ xray_version }}/jfrog-xray-{{ xray_version }}-linux.tar.gz + +#The xray install directory +xray_home: "{{ xray_download_directory }}/jfrog-xray-{{ xray_version }}-linux" + +#xray users and groups +xray_user: xray +xray_group: xray diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/handlers/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/handlers/main.yml new file mode 100644 index 0000000..f236fe3 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/handlers/main.yml @@ -0,0 +1,2 @@ +--- +# handlers file for xray \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/meta/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/meta/main.yml new file mode 100644 index 0000000..227ad9c --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/meta/main.yml @@ -0,0 +1,53 @@ +galaxy_info: + author: your name + description: your role description + company: your company (optional) + + # If the issue tracker for your role is not on github, uncomment the + # next line and provide a value + # issue_tracker_url: http://example.com/issue/tracker + + # Choose a valid license ID from https://spdx.org - some suggested licenses: + # - BSD-3-Clause (default) + # - MIT + # - GPL-2.0-or-later + # - GPL-3.0-only + # - Apache-2.0 + # - CC-BY-4.0 + license: license (GPL-2.0-or-later, MIT, etc) + + min_ansible_version: 2.9 + + # If this a Container Enabled role, provide the minimum Ansible Container version. + # min_ansible_container_version: + + # + # Provide a list of supported platforms, and for each platform a list of versions. + # If you don't wish to enumerate all versions for a particular platform, use 'all'. + # To view available platforms and versions (or releases), visit: + # https://galaxy.ansible.com/api/v1/platforms/ + # + # platforms: + # - name: Fedora + # versions: + # - all + # - 25 + # - name: SomePlatform + # versions: + # - all + # - 1.0 + # - 7 + # - 99.99 + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is a keyword that describes + # and categorizes the role. Users find roles by searching for tags. Be sure to + # remove the '[]' above, if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of alphanumeric characters. + # Maximum 20 tags per role. + +dependencies: [] + # List your role dependencies here, one per line. Be sure to remove the '[]' above, + # if you add dependencies to this list. + \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/tasks/Debian.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/tasks/Debian.yml new file mode 100644 index 0000000..420c2d0 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/tasks/Debian.yml @@ -0,0 +1,37 @@ +--- +- name: Install db5.3-util + apt: + deb: "{{ xray_home }}/app/third-party/misc/db5.3-util_5.3.28-3ubuntu3_amd64.deb" + ignore_errors: yes + become: yes + +- name: Install db-util + apt: + deb: "{{ xray_home }}/app/third-party/misc/db-util_1_3a5.3.21exp1ubuntu1_all.deb" + ignore_errors: yes + become: yes + +- name: Install libssl + apt: + deb: "{{ xray_home }}/app/third-party/rabbitmq/libssl1.1_1.1.0j-1_deb9u1_amd64.deb" + ignore_errors: yes + become: yes + +- name: Install socat + apt: + deb: "{{ xray_home }}/app/third-party/rabbitmq/socat_1.7.3.1-2+deb9u1_amd64.deb" + become: yes + +- name: Install libwxbase3.0-0v5 + apt: + name: libwxbase3.0-0v5 + update_cache: yes + state: present + ignore_errors: yes + become: yes + +- name: Install erlang + apt: + deb: "{{ xray_home }}/app/third-party/rabbitmq/esl-erlang_21.2.1-1~ubuntu~xenial_amd64.deb" + become: yes + diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/tasks/RedHat.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/tasks/RedHat.yml new file mode 100644 index 0000000..efdc081 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/tasks/RedHat.yml @@ -0,0 +1,21 @@ +--- +- name: Install db-utl + yum: + name: "{{ xray_home }}/app/third-party/misc/libdb-utils-5.3.21-19.el7.x86_64.rpm" + state: present + vars: + ansible_python_interpreter: /bin/python2 + +- name: Install socat + yum: + name: "{{ xray_home }}/app/third-party/rabbitmq/socat-1.7.3.2-2.el7.x86_64.rpm" + state: present + vars: + ansible_python_interpreter: /bin/python2 + +- name: Install erlang + yum: + name: "{{ xray_home }}/app/third-party/rabbitmq/erlang-22.3.4-1.el7.x86_64.rpm" + state: present + vars: + ansible_python_interpreter: /bin/python2 diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/tasks/custom-data-directory.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/tasks/custom-data-directory.yml new file mode 100644 index 0000000..8f359ca --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/tasks/custom-data-directory.yml @@ -0,0 +1,44 @@ +- name: setup directory symlink for using custom data directory/volume + block: + - name: Create a xfs filesystem on /dev/nvme1n1 + # First non-root device is always mapped to /dev/nvme1n1 + # See: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nvme-ebs-volumes.html + community.general.filesystem: + dev: /dev/nvme1n1 + fstype: xfs + + - name: ensure external data directory exists + file: + path: "{{ custom_data_directory }}" + state: directory + + - name: Mount the EBS volume + ansible.posix.mount: + path: "{{ custom_data_directory }}" + src: /dev/nvme1n1 + state: mounted + fstype: xfs + + - name: set custom data directory permission + file: + path: "{{ custom_data_directory }}" + state: directory + recurse: yes + owner: "{{ xray_user }}" + group: "{{ xray_group }}" + mode: "u=rwX,g=rwX,o=rwX" + + - name: remove var directory if exists + file: + path: "{{ xray_home }}/var" + state: absent + + - name: symlink custom data directory to var + file: + src: "{{ custom_data_directory }}" + path: "{{ xray_home }}/var" + state: link + owner: "{{ xray_user }}" + group: "{{ xray_group }}" + become: yes + when: use_custom_data_directory and custom_data_directory is defined diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/tasks/initialize-pg-db.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/tasks/initialize-pg-db.yml new file mode 100644 index 0000000..87334b7 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/tasks/initialize-pg-db.yml @@ -0,0 +1,52 @@ +- name: initialize Postgres DB + block: + - name: check if user/role exists + command: psql -A -t {{db_master_url}} -c "SELECT 1 FROM pg_roles WHERE rolname='{{db_user}}'" + register: user_exists + + - debug: + var: user_exists.stdout_lines + + - name: create user/role + command: psql {{db_master_url}} -c "CREATE USER {{db_user}} WITH PASSWORD '{{db_password}}'" + register: shell_output + when: user_exists.stdout != "1" + + - debug: + var: shell_output.stdout_lines + when: user_exists.stdout != "1" + + - name: grant membership role + command: psql {{db_master_url}} -c "GRANT {{db_user}} TO {{db_master_user}}" + register: shell_output + when: user_exists.stdout != "1" + + - debug: + var: shell_output.stdout_lines + when: user_exists.stdout != "1" + + - name: check if xraydb exists + command: psql -A -t {{db_master_url}} -c "SELECT 1 FROM pg_database WHERE datname='xraydb'" + register: db_exists + + - debug: + var: db_exists.stdout_lines + + - name: create xraydb database + command: psql {{db_master_url}} -c "CREATE DATABASE xraydb WITH OWNER={{db_user}} ENCODING='UTF8'" + register: shell_output + when: db_exists.stdout != "1" + + - debug: + var: shell_output.stdout_lines + when: db_exists.stdout != "1" + + - name: grant xraydb privileges to role + command: psql {{db_master_url}} -c "GRANT ALL PRIVILEGES ON DATABASE xraydb TO {{db_user}}" + register: shell_output + when: db_exists.stdout != "1" + + - debug: + var: shell_output.stdout_lines + when: db_exists.stdout != "1" + become: yes diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/tasks/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/tasks/main.yml new file mode 100644 index 0000000..4ae86d6 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/tasks/main.yml @@ -0,0 +1,80 @@ +--- +- name: initialize postgres database + include_tasks: initialize-pg-db.yml + +- name: create group for xray + group: + name: "{{ xray_group }}" + state: present + become: yes + +- name: create user for xray + user: + name: "{{ xray_user }}" + group: "{{ xray_group }}" + system: yes + become: yes + +- name: ensure xray_download_directory exists + file: + path: "{{ xray_download_directory }}" + state: directory + become: yes + +- name: perform prerequisite installation + include_tasks: "{{ ansible_os_family }}.yml" + +- name: setup directory symlink for using custom data directory/volume + include_tasks: custom-data-directory.yml + when: use_custom_data_directory and custom_data_directory is defined + +- name: ensure data subdirectories exist and have correct ownership + file: + path: "{{ xray_home }}/var/{{ item }}" + state: directory + owner: "{{ xray_user }}" + group: "{{ xray_group }}" + loop: + - "etc" + - "data" + - "etc/info" + - "etc/security" + become: yes + +- name: configure system yaml + template: + src: system.yaml.j2 + dest: "{{ xray_home }}/var/etc/system.yaml" + force: no # only create if file doesn't exist + become: yes + +- name: configure master key + template: + src: master.key.j2 + dest: "{{ xray_home }}/var/etc/security/master.key" + force: no # only create if file doesn't exist + become: yes + +- name: configure join key + template: + src: join.key.j2 + dest: "{{ xray_home }}/var/etc/security/join.key" + force: no # only create if file doesn't exist + become: yes + +- name: configure installer info + template: + src: installer-info.json.j2 + dest: "{{ xray_home }}/var/etc/info/installer-info.json" + force: no # only create if file doesn't exist + become: yes + +- name: create xray service + shell: "{{ xray_home }}/app/bin/installService.sh" + become: yes + +- name: start and enable xray + service: + name: xray + state: restarted + become: yes diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/templates/installer-info.json.j2 b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/templates/installer-info.json.j2 new file mode 100644 index 0000000..a76c88c --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/templates/installer-info.json.j2 @@ -0,0 +1,11 @@ +{ + "productId": "Ansible_artifactory/1.0.0", + "features": [ + { + "featureId": "Partner/ACC-006973" + }, + { + "featureId": "Channel/{{ ansible_marketplace }}" + } + ] +} \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/templates/join.key.j2 b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/templates/join.key.j2 new file mode 100644 index 0000000..17d05d2 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/templates/join.key.j2 @@ -0,0 +1 @@ +{{ join_key }} \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/templates/master.key.j2 b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/templates/master.key.j2 new file mode 100644 index 0000000..0462a64 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/templates/master.key.j2 @@ -0,0 +1 @@ +{{ master_key }} \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/templates/system.yaml.j2 b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/templates/system.yaml.j2 new file mode 100644 index 0000000..c6aca8d --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/templates/system.yaml.j2 @@ -0,0 +1,39 @@ +## @formatter:off +## JFROG ARTIFACTORY SYSTEM CONFIGURATION FILE +## HOW TO USE: comment-out any field and keep the correct yaml indentation by deleting only the leading '#' character. +configVersion: 1 + +## NOTE: JFROG_HOME is a place holder for the JFrog root directory containing the deployed product, the home directory for all JFrog products. +## Replace JFROG_HOME with the real path! For example, in RPM install, JFROG_HOME=/opt/jfrog + +## NOTE: Sensitive information such as passwords and join key are encrypted on first read. +## NOTE: The provided commented key and value is the default. + +## SHARED CONFIGURATIONS +## A shared section for keys across all services in this config +shared: + ## Base URL of the JFrog Platform Deployment (JPD) + ## This is the URL to the machine where JFrog Artifactory is deployed, or the load balancer pointing to it. It is recommended to use DNS names rather than direct IPs. + ## Examples: "http://jfrog.acme.com" or "http://10.20.30.40:8082" + jfrogUrl: {{ jfrog_url }} + + ## Java options + extraJavaOpts: "{{ extra_java_opts }}" + + ## Node Settings + node: + ## A unique id to identify this node. + ## Default: auto generated at startup. + id: {{ ansible_machine_id }} + + ## Database Configuration + database: + ## One of: mysql, oracle, mssql, postgresql, mariadb + ## Default: Embedded derby + + ## Example for mysql/postgresql + type: "{{ db_type }}" + driver: "{{ db_driver }}" + url: "{{ db_url }}" + username: "{{ db_user }}" + password: "{{ db_password }}" diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/tests/inventory b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/tests/inventory new file mode 100644 index 0000000..878877b --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/tests/inventory @@ -0,0 +1,2 @@ +localhost + diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/tests/test.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/tests/test.yml new file mode 100644 index 0000000..f296da6 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/tests/test.yml @@ -0,0 +1,5 @@ +--- +- hosts: localhost + remote_user: root + roles: + - xray \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/vars/main.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/vars/main.yml new file mode 100644 index 0000000..55363e6 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/roles/xray/vars/main.yml @@ -0,0 +1,2 @@ +--- +# vars file for xray \ No newline at end of file diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/site-artifactory.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/site-artifactory.yml new file mode 100644 index 0000000..f6b92cf --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/site-artifactory.yml @@ -0,0 +1,12 @@ +- hosts: localhost + gather_facts: true + become: true + tasks: + - include_role: + name: artifactory + - include_role: + name: artifactory-nginx + when: "enable_ssl != true" + - include_role: + name: artifactory-nginx-ssl + when: "enable_ssl == true" diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/site-xray.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/site-xray.yml new file mode 100644 index 0000000..fd761b9 --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/site-xray.yml @@ -0,0 +1,5 @@ +- hosts: localhost + gather_facts: true + become: true + roles: + - name: xray diff --git a/Amazon/artifactory7/latest/cloudInstallerScripts/xray-ami.yml b/Amazon/artifactory7/latest/cloudInstallerScripts/xray-ami.yml new file mode 100644 index 0000000..2921a0d --- /dev/null +++ b/Amazon/artifactory7/latest/cloudInstallerScripts/xray-ami.yml @@ -0,0 +1,5 @@ +- hosts: localhost + gather_facts: true + become: true + roles: + - name: xray-ami diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/.github/workflows/master-docs-build.yml b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/.github/workflows/master-docs-build.yml new file mode 100644 index 0000000..72d5634 --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/.github/workflows/master-docs-build.yml @@ -0,0 +1,37 @@ +name: main-documentation + +on: + push: + branches: + - master +jobs: + build-adocs: + runs-on: ubuntu-18.04 + name: asciidoc builder + steps: + - name: Checkout (master) + uses: actions/checkout@v2 + - name: Get new doc updates + run: | + wget https://raw.githubusercontent.com/aws-quickstart/quickstart-documentation-base-common/master/.utils/configure_git_env.sh + chmod +x configure_git_env.sh + ./configure_git_env.sh + - name: Setup python + uses: actions/setup-python@v2 + with: + python-version: 3.x + - name: Generate dynamic content. + run: ./docs/boilerplate/.utils/generate_dynamic_content.sh + - name: Run local actions + id: adoc + uses: ./docs/boilerplate/.actions/asciidoctor-action + with: + program: "./docs/boilerplate/.utils/build_docs.sh" + - name: Stage and Push changes to gh-pages branch. + run: ./docs/boilerplate/.utils/commit_and_push_to_ghpages.sh + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + - name: Configure gh-pages source and trigger build if necessary. + run: ./docs/boilerplate/.utils/config_and_trigger_gh-pages.sh + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/.gitmodules b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/.gitmodules new file mode 100644 index 0000000..0caba64 --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/.gitmodules @@ -0,0 +1,4 @@ +[submodule "docs/boilerplate"] + path = docs/boilerplate + url = https://github.com/aws-quickstart/quickstart-documentation-base-common.git + branch = main diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/.nojekyll b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/.taskcat.yml b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/.taskcat.yml new file mode 100644 index 0000000..2ca640c --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/.taskcat.yml @@ -0,0 +1,354 @@ +project: + name: quickstart-aws-vpc + owner: quickstart@amazon.com + package_lambda: false + regions: + - af-south-1 + - ap-east-1 + - ap-south-1 + - ap-northeast-3 + - ap-northeast-2 + - ap-southeast-1 + - ap-southeast-2 + - ap-northeast-1 + - ca-central-1 + - cn-north-1 + - cn-northwest-1 + - eu-central-1 + - eu-west-1 + - eu-west-2 + - eu-south-1 + - eu-west-3 + - eu-north-1 + - me-south-1 + - sa-east-1 + - us-east-1 + - us-east-2 + - us-west-1 + - us-west-2 + s3_bucket: '' +tests: + vpc-complete-all-possible-regions: + parameters: + AvailabilityZones: $[taskcat_getaz_2] + CreateAdditionalPrivateSubnets: 'true' + CreatePrivateSubnets: 'true' + NumberOfAZs: '2' + PrivateSubnet1ACIDR: 10.0.0.0/19 + PrivateSubnet1BCIDR: 10.0.192.0/21 + PrivateSubnet2ACIDR: 10.0.32.0/19 + PrivateSubnet2BCIDR: 10.0.200.0/21 + PrivateSubnet3ACIDR: 10.0.64.0/19 + PrivateSubnet3BCIDR: 10.0.208.0/21 + PrivateSubnet4ACIDR: 10.0.96.0/19 + PrivateSubnet4BCIDR: 10.0.216.0/21 + PublicSubnet1CIDR: 10.0.128.0/20 + PublicSubnet2CIDR: 10.0.144.0/20 + PublicSubnet3CIDR: 10.0.160.0/20 + PublicSubnet4CIDR: 10.0.176.0/20 + VPCCIDR: 10.0.0.0/16 + VPCTenancy: default + regions: + - af-south-1 + - ap-east-1 + - ap-south-1 + ## - ap-northeast-3 + - ap-northeast-2 + - ap-southeast-1 + - ap-southeast-2 + - ap-northeast-1 + - ca-central-1 + ## - cn-north-1 + ## - cn-northwest-1 + - eu-central-1 + - eu-west-1 + - eu-west-2 + - eu-south-1 + - eu-west-3 + - eu-north-1 + - me-south-1 + - sa-east-1 + - us-east-1 + - us-east-2 + - us-west-1 + - us-west-2 + s3_bucket: '' + template: templates/aws-vpc.template.yaml + vpc-defaults-all-possible-regions: + parameters: + AvailabilityZones: $[taskcat_getaz_2] + CreateAdditionalPrivateSubnets: 'false' + CreatePrivateSubnets: 'true' + NumberOfAZs: '2' + PrivateSubnet1ACIDR: 10.0.0.0/19 + PrivateSubnet1BCIDR: 10.0.192.0/21 + PrivateSubnet2ACIDR: 10.0.32.0/19 + PrivateSubnet2BCIDR: 10.0.200.0/21 + PrivateSubnet3ACIDR: 10.0.64.0/19 + PrivateSubnet3BCIDR: 10.0.208.0/21 + PrivateSubnet4ACIDR: 10.0.96.0/19 + PrivateSubnet4BCIDR: 10.0.216.0/21 + PublicSubnet1CIDR: 10.0.128.0/20 + PublicSubnet2CIDR: 10.0.144.0/20 + PublicSubnet3CIDR: 10.0.160.0/20 + PublicSubnet4CIDR: 10.0.176.0/20 + VPCCIDR: 10.0.0.0/16 + VPCTenancy: default + regions: + - af-south-1 + - ap-east-1 + - ap-south-1 + ## - ap-northeast-3 + - ap-northeast-2 + - ap-southeast-1 + - ap-southeast-2 + - ap-northeast-1 + - ca-central-1 + ## - cn-north-1 + ## - cn-northwest-1 + - eu-central-1 + - eu-west-1 + - eu-west-2 + - eu-south-1 + - eu-west-3 + - eu-north-1 + - me-south-1 + - sa-east-1 + - us-east-1 + - us-east-2 + - us-west-1 + - us-west-2 + s3_bucket: '' + template: templates/aws-vpc.template.yaml + vpc-public-all-possible-regions: + parameters: + AvailabilityZones: $[taskcat_getaz_2] + CreateAdditionalPrivateSubnets: 'false' + CreateNATGateways: 'false' + CreatePrivateSubnets: 'false' + NumberOfAZs: '2' + PrivateSubnet1ACIDR: 10.0.0.0/19 + PrivateSubnet1BCIDR: 10.0.192.0/21 + PrivateSubnet2ACIDR: 10.0.32.0/19 + PrivateSubnet2BCIDR: 10.0.200.0/21 + PrivateSubnet3ACIDR: 10.0.64.0/19 + PrivateSubnet3BCIDR: 10.0.208.0/21 + PrivateSubnet4ACIDR: 10.0.96.0/19 + PrivateSubnet4BCIDR: 10.0.216.0/21 + PublicSubnet1CIDR: 10.0.128.0/20 + PublicSubnet2CIDR: 10.0.144.0/20 + PublicSubnet3CIDR: 10.0.160.0/20 + PublicSubnet4CIDR: 10.0.176.0/20 + VPCCIDR: 10.0.0.0/16 + VPCTenancy: default + regions: + - af-south-1 + - ap-east-1 + - ap-south-1 + ## - ap-northeast-3 + - ap-northeast-2 + - ap-southeast-1 + - ap-southeast-2 + - ap-northeast-1 + - ca-central-1 + ## - cn-north-1 + ## - cn-northwest-1 + - eu-central-1 + - eu-west-1 + - eu-west-2 + - eu-south-1 + - eu-west-3 + - eu-north-1 + - me-south-1 + - sa-east-1 + - us-east-1 + - us-east-2 + - us-west-1 + - us-west-2 + s3_bucket: '' + template: templates/aws-vpc.template.yaml + vpc-private-all-possible-regions: + parameters: + AvailabilityZones: $[taskcat_getaz_2] + CreateAdditionalPrivateSubnets: 'false' + CreatePublicSubnets: 'false' + CreateNATGateways: 'false' + NumberOfAZs: '2' + PrivateSubnet1ACIDR: 10.0.0.0/19 + PrivateSubnet1BCIDR: 10.0.192.0/21 + PrivateSubnet2ACIDR: 10.0.32.0/19 + PrivateSubnet2BCIDR: 10.0.200.0/21 + PrivateSubnet3ACIDR: 10.0.64.0/19 + PrivateSubnet3BCIDR: 10.0.208.0/21 + PrivateSubnet4ACIDR: 10.0.96.0/19 + PrivateSubnet4BCIDR: 10.0.216.0/21 + PublicSubnet1CIDR: 10.0.128.0/20 + PublicSubnet2CIDR: 10.0.144.0/20 + PublicSubnet3CIDR: 10.0.160.0/20 + PublicSubnet4CIDR: 10.0.176.0/20 + VPCCIDR: 10.0.0.0/16 + VPCTenancy: default + regions: + - af-south-1 + - ap-east-1 + - ap-south-1 + ## - ap-northeast-3 + - ap-northeast-2 + - ap-southeast-1 + - ap-southeast-2 + - ap-northeast-1 + - ca-central-1 + ## - cn-north-1 + ## - cn-northwest-1 + - eu-central-1 + - eu-west-1 + - eu-west-2 + - eu-south-1 + - eu-west-3 + - eu-north-1 + - me-south-1 + - sa-east-1 + - us-east-1 + - us-east-2 + - us-west-1 + - us-west-2 + s3_bucket: '' + template: templates/aws-vpc.template.yaml + 3az-complete-all-possible-regions: + parameters: + AvailabilityZones: $[taskcat_getaz_3] + CreateAdditionalPrivateSubnets: 'true' + CreatePrivateSubnets: 'true' + NumberOfAZs: '3' + PrivateSubnet1ACIDR: 10.0.0.0/19 + PrivateSubnet1BCIDR: 10.0.192.0/21 + PrivateSubnet2ACIDR: 10.0.32.0/19 + PrivateSubnet2BCIDR: 10.0.200.0/21 + PrivateSubnet3ACIDR: 10.0.64.0/19 + PrivateSubnet3BCIDR: 10.0.208.0/21 + PrivateSubnet4ACIDR: 10.0.96.0/19 + PrivateSubnet4BCIDR: 10.0.216.0/21 + PublicSubnet1CIDR: 10.0.128.0/20 + PublicSubnet2CIDR: 10.0.144.0/20 + PublicSubnet3CIDR: 10.0.160.0/20 + PublicSubnet4CIDR: 10.0.176.0/20 + VPCCIDR: 10.0.0.0/16 + VPCTenancy: default + regions: + - af-south-1 + - ap-east-1 + - ap-south-1 + ## - ap-northeast-3 + - ap-northeast-2 + - ap-southeast-1 + - ap-southeast-2 + - ap-northeast-1 + ## - ca-central-1 + ## - cn-north-1 + ## - cn-northwest-1 + - eu-central-1 + - eu-west-1 + - eu-west-2 + - eu-south-1 + - eu-west-3 + - eu-north-1 + - me-south-1 + - sa-east-1 + - us-east-1 + - us-east-2 + ## - us-west-1 + - us-west-2 + s3_bucket: '' + template: templates/aws-vpc.template + 4az-complete-all-possible-regions: + parameters: + AvailabilityZones: $[taskcat_getaz_4] + CreateAdditionalPrivateSubnets: 'true' + CreatePrivateSubnets: 'true' + NumberOfAZs: '4' + PrivateSubnet1ACIDR: 10.0.0.0/19 + PrivateSubnet1BCIDR: 10.0.192.0/21 + PrivateSubnet2ACIDR: 10.0.32.0/19 + PrivateSubnet2BCIDR: 10.0.200.0/21 + PrivateSubnet3ACIDR: 10.0.64.0/19 + PrivateSubnet3BCIDR: 10.0.208.0/21 + PrivateSubnet4ACIDR: 10.0.96.0/19 + PrivateSubnet4BCIDR: 10.0.216.0/21 + PublicSubnet1CIDR: 10.0.128.0/20 + PublicSubnet2CIDR: 10.0.144.0/20 + PublicSubnet3CIDR: 10.0.160.0/20 + PublicSubnet4CIDR: 10.0.176.0/20 + VPCCIDR: 10.0.0.0/16 + VPCTenancy: default + regions: + ## - af-south-1 + ## - ap-east-1 + ## - ap-south-1 + ## - ap-northeast-3 + ## - ap-northeast-2 + ## - ap-southeast-1 + ## - ap-southeast-2 + ## - ap-northeast-1 + ## - ca-central-1 + ## - cn-north-1 + ## - cn-northwest-1 + ## - eu-central-1 + ## - eu-west-1 + ## - eu-west-2 + ## - eu-south-1 + ## - eu-west-3 + ## - eu-north-1 + ## - me-south-1 + ## - sa-east-1 + - us-east-1 + ## - us-east-2 + ## - us-west-1 + - us-west-2 + s3_bucket: '' + template: templates/aws-vpc.template + 4az-public-all-possible-regions: + parameters: + AvailabilityZones: $[taskcat_getaz_4] + CreateAdditionalPrivateSubnets: 'false' + CreatePrivateSubnets: 'false' + NumberOfAZs: '4' + PrivateSubnet1ACIDR: 10.0.0.0/19 + PrivateSubnet1BCIDR: 10.0.192.0/21 + PrivateSubnet2ACIDR: 10.0.32.0/19 + PrivateSubnet2BCIDR: 10.0.200.0/21 + PrivateSubnet3ACIDR: 10.0.64.0/19 + PrivateSubnet3BCIDR: 10.0.208.0/21 + PrivateSubnet4ACIDR: 10.0.96.0/19 + PrivateSubnet4BCIDR: 10.0.216.0/21 + PublicSubnet1CIDR: 10.0.128.0/20 + PublicSubnet2CIDR: 10.0.144.0/20 + PublicSubnet3CIDR: 10.0.160.0/20 + PublicSubnet4CIDR: 10.0.176.0/20 + VPCCIDR: 10.0.0.0/16 + VPCTenancy: default + regions: + ## - af-south-1 + ## - ap-east-1 + ## - ap-south-1 + ## - ap-northeast-3 + ## - ap-northeast-2 + ## - ap-southeast-1 + ## - ap-southeast-2 + ## - ap-northeast-1 + ## - ca-central-1 + ## - cn-north-1 + ## - cn-northwest-1 + ## - eu-central-1 + ## - eu-west-1 + ## - eu-west-2 + ## - eu-south-1 + ## - eu-west-3 + ## - eu-north-1 + ## - me-south-1 + ## - sa-east-1 + - us-east-1 + ## - us-east-2 + ## - us-west-1 + - us-west-2 + s3_bucket: '' + template: templates/aws-vpc.template \ No newline at end of file diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/LICENSE.txt b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/LICENSE.txt new file mode 100644 index 0000000..8dada3e --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/LICENSE.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/NOTICE.txt b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/NOTICE.txt new file mode 100644 index 0000000..c7169b4 --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/NOTICE.txt @@ -0,0 +1,7 @@ +Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with the License. A copy of the License is located at + + http://aws.amazon.com/apache2.0/ + +or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/README.md b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/README.md new file mode 100644 index 0000000..449de22 --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/README.md @@ -0,0 +1,9 @@ +# quickstart-aws-vpc + +This Quick Start provides a networking foundation for AWS Cloud infrastructures. It deploys an Amazon Virtual Private Cloud (Amazon VPC) according to AWS best practices and guidelines. + +The Amazon VPC architecture includes public and private subnets. The first set of private subnets share the default network access control list (ACL) from the Amazon VPC, and a second, optional set of private subnets include dedicated custom network ACLs per subnet. The Quick Start divides the Amazon VPC address space in a predictable manner across multiple Availability Zones, and deploys NAT gateways in each Availability Zone, which provide highly available outbound internet access for the private subnets. + +For architectural details, best practices, step-by-step instructions, and customization options, see the [deployment guide](https://fwd.aws/9VdxN). + +![Quick Start VPC Design Architecture](https://docs.aws.amazon.com/quickstart/latest/vpc/images/quickstart-vpc-design-fullscreen.png) diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-3az-complete.json b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-3az-complete.json new file mode 100644 index 0000000..58e2891 --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-3az-complete.json @@ -0,0 +1,74 @@ +[ + { + "ParameterKey": "AvailabilityZones", + "ParameterValue": "$[taskcat_getaz_3]" + }, + { + "ParameterKey": "CreateAdditionalPrivateSubnets", + "ParameterValue": "true" + }, + { + "ParameterKey": "CreatePrivateSubnets", + "ParameterValue": "true" + }, + { + "ParameterKey": "NumberOfAZs", + "ParameterValue": "3" + }, + { + "ParameterKey": "PrivateSubnet1ACIDR", + "ParameterValue": "10.0.0.0/19" + }, + { + "ParameterKey": "PrivateSubnet1BCIDR", + "ParameterValue": "10.0.192.0/21" + }, + { + "ParameterKey": "PrivateSubnet2ACIDR", + "ParameterValue": "10.0.32.0/19" + }, + { + "ParameterKey": "PrivateSubnet2BCIDR", + "ParameterValue": "10.0.200.0/21" + }, + { + "ParameterKey": "PrivateSubnet3ACIDR", + "ParameterValue": "10.0.64.0/19" + }, + { + "ParameterKey": "PrivateSubnet3BCIDR", + "ParameterValue": "10.0.208.0/21" + }, + { + "ParameterKey": "PrivateSubnet4ACIDR", + "ParameterValue": "10.0.96.0/19" + }, + { + "ParameterKey": "PrivateSubnet4BCIDR", + "ParameterValue": "10.0.216.0/21" + }, + { + "ParameterKey": "PublicSubnet1CIDR", + "ParameterValue": "10.0.128.0/20" + }, + { + "ParameterKey": "PublicSubnet2CIDR", + "ParameterValue": "10.0.144.0/20" + }, + { + "ParameterKey": "PublicSubnet3CIDR", + "ParameterValue": "10.0.160.0/20" + }, + { + "ParameterKey": "PublicSubnet4CIDR", + "ParameterValue": "10.0.176.0/20" + }, + { + "ParameterKey": "VPCCIDR", + "ParameterValue": "10.0.0.0/16" + }, + { + "ParameterKey": "VPCTenancy", + "ParameterValue": "default" + } +] diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-3az-public.json b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-3az-public.json new file mode 100644 index 0000000..bc07459 --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-3az-public.json @@ -0,0 +1,74 @@ +[ + { + "ParameterKey": "AvailabilityZones", + "ParameterValue": "$[taskcat_getaz_3]" + }, + { + "ParameterKey": "CreateAdditionalPrivateSubnets", + "ParameterValue": "false" + }, + { + "ParameterKey": "CreatePrivateSubnets", + "ParameterValue": "false" + }, + { + "ParameterKey": "NumberOfAZs", + "ParameterValue": "3" + }, + { + "ParameterKey": "PrivateSubnet1ACIDR", + "ParameterValue": "10.0.0.0/19" + }, + { + "ParameterKey": "PrivateSubnet1BCIDR", + "ParameterValue": "10.0.192.0/21" + }, + { + "ParameterKey": "PrivateSubnet2ACIDR", + "ParameterValue": "10.0.32.0/19" + }, + { + "ParameterKey": "PrivateSubnet2BCIDR", + "ParameterValue": "10.0.200.0/21" + }, + { + "ParameterKey": "PrivateSubnet3ACIDR", + "ParameterValue": "10.0.64.0/19" + }, + { + "ParameterKey": "PrivateSubnet3BCIDR", + "ParameterValue": "10.0.208.0/21" + }, + { + "ParameterKey": "PrivateSubnet4ACIDR", + "ParameterValue": "10.0.96.0/19" + }, + { + "ParameterKey": "PrivateSubnet4BCIDR", + "ParameterValue": "10.0.216.0/21" + }, + { + "ParameterKey": "PublicSubnet1CIDR", + "ParameterValue": "10.0.128.0/20" + }, + { + "ParameterKey": "PublicSubnet2CIDR", + "ParameterValue": "10.0.144.0/20" + }, + { + "ParameterKey": "PublicSubnet3CIDR", + "ParameterValue": "10.0.160.0/20" + }, + { + "ParameterKey": "PublicSubnet4CIDR", + "ParameterValue": "10.0.176.0/20" + }, + { + "ParameterKey": "VPCCIDR", + "ParameterValue": "10.0.0.0/16" + }, + { + "ParameterKey": "VPCTenancy", + "ParameterValue": "default" + } +] diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-3az.json b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-3az.json new file mode 100644 index 0000000..ee5548a --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-3az.json @@ -0,0 +1,74 @@ +[ + { + "ParameterKey": "AvailabilityZones", + "ParameterValue": "$[taskcat_getaz_3]" + }, + { + "ParameterKey": "CreateAdditionalPrivateSubnets", + "ParameterValue": "false" + }, + { + "ParameterKey": "CreatePrivateSubnets", + "ParameterValue": "true" + }, + { + "ParameterKey": "NumberOfAZs", + "ParameterValue": "3" + }, + { + "ParameterKey": "PrivateSubnet1ACIDR", + "ParameterValue": "10.0.0.0/19" + }, + { + "ParameterKey": "PrivateSubnet1BCIDR", + "ParameterValue": "10.0.192.0/21" + }, + { + "ParameterKey": "PrivateSubnet2ACIDR", + "ParameterValue": "10.0.32.0/19" + }, + { + "ParameterKey": "PrivateSubnet2BCIDR", + "ParameterValue": "10.0.200.0/21" + }, + { + "ParameterKey": "PrivateSubnet3ACIDR", + "ParameterValue": "10.0.64.0/19" + }, + { + "ParameterKey": "PrivateSubnet3BCIDR", + "ParameterValue": "10.0.208.0/21" + }, + { + "ParameterKey": "PrivateSubnet4ACIDR", + "ParameterValue": "10.0.96.0/19" + }, + { + "ParameterKey": "PrivateSubnet4BCIDR", + "ParameterValue": "10.0.216.0/21" + }, + { + "ParameterKey": "PublicSubnet1CIDR", + "ParameterValue": "10.0.128.0/20" + }, + { + "ParameterKey": "PublicSubnet2CIDR", + "ParameterValue": "10.0.144.0/20" + }, + { + "ParameterKey": "PublicSubnet3CIDR", + "ParameterValue": "10.0.160.0/20" + }, + { + "ParameterKey": "PublicSubnet4CIDR", + "ParameterValue": "10.0.176.0/20" + }, + { + "ParameterKey": "VPCCIDR", + "ParameterValue": "10.0.0.0/16" + }, + { + "ParameterKey": "VPCTenancy", + "ParameterValue": "default" + } +] diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-4az-complete.json b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-4az-complete.json new file mode 100644 index 0000000..b9929b4 --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-4az-complete.json @@ -0,0 +1,74 @@ +[ + { + "ParameterKey": "AvailabilityZones", + "ParameterValue": "$[taskcat_getaz_4]" + }, + { + "ParameterKey": "CreateAdditionalPrivateSubnets", + "ParameterValue": "true" + }, + { + "ParameterKey": "CreatePrivateSubnets", + "ParameterValue": "true" + }, + { + "ParameterKey": "NumberOfAZs", + "ParameterValue": "4" + }, + { + "ParameterKey": "PrivateSubnet1ACIDR", + "ParameterValue": "10.0.0.0/19" + }, + { + "ParameterKey": "PrivateSubnet1BCIDR", + "ParameterValue": "10.0.192.0/21" + }, + { + "ParameterKey": "PrivateSubnet2ACIDR", + "ParameterValue": "10.0.32.0/19" + }, + { + "ParameterKey": "PrivateSubnet2BCIDR", + "ParameterValue": "10.0.200.0/21" + }, + { + "ParameterKey": "PrivateSubnet3ACIDR", + "ParameterValue": "10.0.64.0/19" + }, + { + "ParameterKey": "PrivateSubnet3BCIDR", + "ParameterValue": "10.0.208.0/21" + }, + { + "ParameterKey": "PrivateSubnet4ACIDR", + "ParameterValue": "10.0.96.0/19" + }, + { + "ParameterKey": "PrivateSubnet4BCIDR", + "ParameterValue": "10.0.216.0/21" + }, + { + "ParameterKey": "PublicSubnet1CIDR", + "ParameterValue": "10.0.128.0/20" + }, + { + "ParameterKey": "PublicSubnet2CIDR", + "ParameterValue": "10.0.144.0/20" + }, + { + "ParameterKey": "PublicSubnet3CIDR", + "ParameterValue": "10.0.160.0/20" + }, + { + "ParameterKey": "PublicSubnet4CIDR", + "ParameterValue": "10.0.176.0/20" + }, + { + "ParameterKey": "VPCCIDR", + "ParameterValue": "10.0.0.0/16" + }, + { + "ParameterKey": "VPCTenancy", + "ParameterValue": "default" + } +] diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-4az-public.json b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-4az-public.json new file mode 100644 index 0000000..a34e72d --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-4az-public.json @@ -0,0 +1,74 @@ +[ + { + "ParameterKey": "AvailabilityZones", + "ParameterValue": "$[taskcat_getaz_4]" + }, + { + "ParameterKey": "CreateAdditionalPrivateSubnets", + "ParameterValue": "false" + }, + { + "ParameterKey": "CreatePrivateSubnets", + "ParameterValue": "false" + }, + { + "ParameterKey": "NumberOfAZs", + "ParameterValue": "4" + }, + { + "ParameterKey": "PrivateSubnet1ACIDR", + "ParameterValue": "10.0.0.0/19" + }, + { + "ParameterKey": "PrivateSubnet1BCIDR", + "ParameterValue": "10.0.192.0/21" + }, + { + "ParameterKey": "PrivateSubnet2ACIDR", + "ParameterValue": "10.0.32.0/19" + }, + { + "ParameterKey": "PrivateSubnet2BCIDR", + "ParameterValue": "10.0.200.0/21" + }, + { + "ParameterKey": "PrivateSubnet3ACIDR", + "ParameterValue": "10.0.64.0/19" + }, + { + "ParameterKey": "PrivateSubnet3BCIDR", + "ParameterValue": "10.0.208.0/21" + }, + { + "ParameterKey": "PrivateSubnet4ACIDR", + "ParameterValue": "10.0.96.0/19" + }, + { + "ParameterKey": "PrivateSubnet4BCIDR", + "ParameterValue": "10.0.216.0/21" + }, + { + "ParameterKey": "PublicSubnet1CIDR", + "ParameterValue": "10.0.128.0/20" + }, + { + "ParameterKey": "PublicSubnet2CIDR", + "ParameterValue": "10.0.144.0/20" + }, + { + "ParameterKey": "PublicSubnet3CIDR", + "ParameterValue": "10.0.160.0/20" + }, + { + "ParameterKey": "PublicSubnet4CIDR", + "ParameterValue": "10.0.176.0/20" + }, + { + "ParameterKey": "VPCCIDR", + "ParameterValue": "10.0.0.0/16" + }, + { + "ParameterKey": "VPCTenancy", + "ParameterValue": "default" + } +] diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-4az.json b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-4az.json new file mode 100644 index 0000000..a543251 --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-4az.json @@ -0,0 +1,74 @@ +[ + { + "ParameterKey": "AvailabilityZones", + "ParameterValue": "$[taskcat_getaz_4]" + }, + { + "ParameterKey": "CreateAdditionalPrivateSubnets", + "ParameterValue": "false" + }, + { + "ParameterKey": "CreatePrivateSubnets", + "ParameterValue": "true" + }, + { + "ParameterKey": "NumberOfAZs", + "ParameterValue": "4" + }, + { + "ParameterKey": "PrivateSubnet1ACIDR", + "ParameterValue": "10.0.0.0/19" + }, + { + "ParameterKey": "PrivateSubnet1BCIDR", + "ParameterValue": "10.0.192.0/21" + }, + { + "ParameterKey": "PrivateSubnet2ACIDR", + "ParameterValue": "10.0.32.0/19" + }, + { + "ParameterKey": "PrivateSubnet2BCIDR", + "ParameterValue": "10.0.200.0/21" + }, + { + "ParameterKey": "PrivateSubnet3ACIDR", + "ParameterValue": "10.0.64.0/19" + }, + { + "ParameterKey": "PrivateSubnet3BCIDR", + "ParameterValue": "10.0.208.0/21" + }, + { + "ParameterKey": "PrivateSubnet4ACIDR", + "ParameterValue": "10.0.96.0/19" + }, + { + "ParameterKey": "PrivateSubnet4BCIDR", + "ParameterValue": "10.0.216.0/21" + }, + { + "ParameterKey": "PublicSubnet1CIDR", + "ParameterValue": "10.0.128.0/20" + }, + { + "ParameterKey": "PublicSubnet2CIDR", + "ParameterValue": "10.0.144.0/20" + }, + { + "ParameterKey": "PublicSubnet3CIDR", + "ParameterValue": "10.0.160.0/20" + }, + { + "ParameterKey": "PublicSubnet4CIDR", + "ParameterValue": "10.0.176.0/20" + }, + { + "ParameterKey": "VPCCIDR", + "ParameterValue": "10.0.0.0/16" + }, + { + "ParameterKey": "VPCTenancy", + "ParameterValue": "default" + } +] diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-complete.json b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-complete.json new file mode 100644 index 0000000..d180084 --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-complete.json @@ -0,0 +1,74 @@ +[ + { + "ParameterKey": "AvailabilityZones", + "ParameterValue": "$[taskcat_getaz_2]" + }, + { + "ParameterKey": "CreateAdditionalPrivateSubnets", + "ParameterValue": "true" + }, + { + "ParameterKey": "CreatePrivateSubnets", + "ParameterValue": "true" + }, + { + "ParameterKey": "NumberOfAZs", + "ParameterValue": "2" + }, + { + "ParameterKey": "PrivateSubnet1ACIDR", + "ParameterValue": "10.0.0.0/19" + }, + { + "ParameterKey": "PrivateSubnet1BCIDR", + "ParameterValue": "10.0.192.0/21" + }, + { + "ParameterKey": "PrivateSubnet2ACIDR", + "ParameterValue": "10.0.32.0/19" + }, + { + "ParameterKey": "PrivateSubnet2BCIDR", + "ParameterValue": "10.0.200.0/21" + }, + { + "ParameterKey": "PrivateSubnet3ACIDR", + "ParameterValue": "10.0.64.0/19" + }, + { + "ParameterKey": "PrivateSubnet3BCIDR", + "ParameterValue": "10.0.208.0/21" + }, + { + "ParameterKey": "PrivateSubnet4ACIDR", + "ParameterValue": "10.0.96.0/19" + }, + { + "ParameterKey": "PrivateSubnet4BCIDR", + "ParameterValue": "10.0.216.0/21" + }, + { + "ParameterKey": "PublicSubnet1CIDR", + "ParameterValue": "10.0.128.0/20" + }, + { + "ParameterKey": "PublicSubnet2CIDR", + "ParameterValue": "10.0.144.0/20" + }, + { + "ParameterKey": "PublicSubnet3CIDR", + "ParameterValue": "10.0.160.0/20" + }, + { + "ParameterKey": "PublicSubnet4CIDR", + "ParameterValue": "10.0.176.0/20" + }, + { + "ParameterKey": "VPCCIDR", + "ParameterValue": "10.0.0.0/16" + }, + { + "ParameterKey": "VPCTenancy", + "ParameterValue": "default" + } +] diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-dedicated.json b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-dedicated.json new file mode 100644 index 0000000..14186af --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-dedicated.json @@ -0,0 +1,74 @@ +[ + { + "ParameterKey": "AvailabilityZones", + "ParameterValue": "$[taskcat_getaz_2]" + }, + { + "ParameterKey": "CreateAdditionalPrivateSubnets", + "ParameterValue": "false" + }, + { + "ParameterKey": "CreatePrivateSubnets", + "ParameterValue": "false" + }, + { + "ParameterKey": "NumberOfAZs", + "ParameterValue": "2" + }, + { + "ParameterKey": "PrivateSubnet1ACIDR", + "ParameterValue": "10.0.0.0/19" + }, + { + "ParameterKey": "PrivateSubnet1BCIDR", + "ParameterValue": "10.0.192.0/21" + }, + { + "ParameterKey": "PrivateSubnet2ACIDR", + "ParameterValue": "10.0.32.0/19" + }, + { + "ParameterKey": "PrivateSubnet2BCIDR", + "ParameterValue": "10.0.200.0/21" + }, + { + "ParameterKey": "PrivateSubnet3ACIDR", + "ParameterValue": "10.0.64.0/19" + }, + { + "ParameterKey": "PrivateSubnet3BCIDR", + "ParameterValue": "10.0.208.0/21" + }, + { + "ParameterKey": "PrivateSubnet4ACIDR", + "ParameterValue": "10.0.96.0/19" + }, + { + "ParameterKey": "PrivateSubnet4BCIDR", + "ParameterValue": "10.0.216.0/21" + }, + { + "ParameterKey": "PublicSubnet1CIDR", + "ParameterValue": "10.0.128.0/20" + }, + { + "ParameterKey": "PublicSubnet2CIDR", + "ParameterValue": "10.0.144.0/20" + }, + { + "ParameterKey": "PublicSubnet3CIDR", + "ParameterValue": "10.0.160.0/20" + }, + { + "ParameterKey": "PublicSubnet4CIDR", + "ParameterValue": "10.0.176.0/20" + }, + { + "ParameterKey": "VPCCIDR", + "ParameterValue": "10.0.0.0/16" + }, + { + "ParameterKey": "VPCTenancy", + "ParameterValue": "dedicated" + } +] diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-defaults.json b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-defaults.json new file mode 100644 index 0000000..aaca90c --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-defaults.json @@ -0,0 +1,74 @@ +[ + { + "ParameterKey": "AvailabilityZones", + "ParameterValue": "$[taskcat_getaz_2]" + }, + { + "ParameterKey": "CreateAdditionalPrivateSubnets", + "ParameterValue": "false" + }, + { + "ParameterKey": "CreatePrivateSubnets", + "ParameterValue": "true" + }, + { + "ParameterKey": "NumberOfAZs", + "ParameterValue": "2" + }, + { + "ParameterKey": "PrivateSubnet1ACIDR", + "ParameterValue": "10.0.0.0/19" + }, + { + "ParameterKey": "PrivateSubnet1BCIDR", + "ParameterValue": "10.0.192.0/21" + }, + { + "ParameterKey": "PrivateSubnet2ACIDR", + "ParameterValue": "10.0.32.0/19" + }, + { + "ParameterKey": "PrivateSubnet2BCIDR", + "ParameterValue": "10.0.200.0/21" + }, + { + "ParameterKey": "PrivateSubnet3ACIDR", + "ParameterValue": "10.0.64.0/19" + }, + { + "ParameterKey": "PrivateSubnet3BCIDR", + "ParameterValue": "10.0.208.0/21" + }, + { + "ParameterKey": "PrivateSubnet4ACIDR", + "ParameterValue": "10.0.96.0/19" + }, + { + "ParameterKey": "PrivateSubnet4BCIDR", + "ParameterValue": "10.0.216.0/21" + }, + { + "ParameterKey": "PublicSubnet1CIDR", + "ParameterValue": "10.0.128.0/20" + }, + { + "ParameterKey": "PublicSubnet2CIDR", + "ParameterValue": "10.0.144.0/20" + }, + { + "ParameterKey": "PublicSubnet3CIDR", + "ParameterValue": "10.0.160.0/20" + }, + { + "ParameterKey": "PublicSubnet4CIDR", + "ParameterValue": "10.0.176.0/20" + }, + { + "ParameterKey": "VPCCIDR", + "ParameterValue": "10.0.0.0/16" + }, + { + "ParameterKey": "VPCTenancy", + "ParameterValue": "default" + } +] diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-public.json b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-public.json new file mode 100644 index 0000000..86e37a2 --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-public.json @@ -0,0 +1,74 @@ +[ + { + "ParameterKey": "AvailabilityZones", + "ParameterValue": "$[taskcat_getaz_2]" + }, + { + "ParameterKey": "CreateAdditionalPrivateSubnets", + "ParameterValue": "false" + }, + { + "ParameterKey": "CreatePrivateSubnets", + "ParameterValue": "false" + }, + { + "ParameterKey": "NumberOfAZs", + "ParameterValue": "2" + }, + { + "ParameterKey": "PrivateSubnet1ACIDR", + "ParameterValue": "10.0.0.0/19" + }, + { + "ParameterKey": "PrivateSubnet1BCIDR", + "ParameterValue": "10.0.192.0/21" + }, + { + "ParameterKey": "PrivateSubnet2ACIDR", + "ParameterValue": "10.0.32.0/19" + }, + { + "ParameterKey": "PrivateSubnet2BCIDR", + "ParameterValue": "10.0.200.0/21" + }, + { + "ParameterKey": "PrivateSubnet3ACIDR", + "ParameterValue": "10.0.64.0/19" + }, + { + "ParameterKey": "PrivateSubnet3BCIDR", + "ParameterValue": "10.0.208.0/21" + }, + { + "ParameterKey": "PrivateSubnet4ACIDR", + "ParameterValue": "10.0.96.0/19" + }, + { + "ParameterKey": "PrivateSubnet4BCIDR", + "ParameterValue": "10.0.216.0/21" + }, + { + "ParameterKey": "PublicSubnet1CIDR", + "ParameterValue": "10.0.128.0/20" + }, + { + "ParameterKey": "PublicSubnet2CIDR", + "ParameterValue": "10.0.144.0/20" + }, + { + "ParameterKey": "PublicSubnet3CIDR", + "ParameterValue": "10.0.160.0/20" + }, + { + "ParameterKey": "PublicSubnet4CIDR", + "ParameterValue": "10.0.176.0/20" + }, + { + "ParameterKey": "VPCCIDR", + "ParameterValue": "10.0.0.0/16" + }, + { + "ParameterKey": "VPCTenancy", + "ParameterValue": "default" + } +] diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-sa-east-1.json b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-sa-east-1.json new file mode 100644 index 0000000..e8ee3b0 --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/aws-vpc-sa-east-1.json @@ -0,0 +1,74 @@ +[ + { + "ParameterKey": "AvailabilityZones", + "ParameterValue": "sa-east-1b,sa-east-1c" + }, + { + "ParameterKey": "CreateAdditionalPrivateSubnets", + "ParameterValue": "false" + }, + { + "ParameterKey": "CreatePrivateSubnets", + "ParameterValue": "true" + }, + { + "ParameterKey": "NumberOfAZs", + "ParameterValue": "2" + }, + { + "ParameterKey": "PrivateSubnet1ACIDR", + "ParameterValue": "10.0.0.0/19" + }, + { + "ParameterKey": "PrivateSubnet1BCIDR", + "ParameterValue": "10.0.192.0/21" + }, + { + "ParameterKey": "PrivateSubnet2ACIDR", + "ParameterValue": "10.0.32.0/19" + }, + { + "ParameterKey": "PrivateSubnet2BCIDR", + "ParameterValue": "10.0.200.0/21" + }, + { + "ParameterKey": "PrivateSubnet3ACIDR", + "ParameterValue": "10.0.64.0/19" + }, + { + "ParameterKey": "PrivateSubnet3BCIDR", + "ParameterValue": "10.0.208.0/21" + }, + { + "ParameterKey": "PrivateSubnet4ACIDR", + "ParameterValue": "10.0.96.0/19" + }, + { + "ParameterKey": "PrivateSubnet4BCIDR", + "ParameterValue": "10.0.216.0/21" + }, + { + "ParameterKey": "PublicSubnet1CIDR", + "ParameterValue": "10.0.128.0/20" + }, + { + "ParameterKey": "PublicSubnet2CIDR", + "ParameterValue": "10.0.144.0/20" + }, + { + "ParameterKey": "PublicSubnet3CIDR", + "ParameterValue": "10.0.160.0/20" + }, + { + "ParameterKey": "PublicSubnet4CIDR", + "ParameterValue": "10.0.176.0/20" + }, + { + "ParameterKey": "VPCCIDR", + "ParameterValue": "10.0.0.0/16" + }, + { + "ParameterKey": "VPCTenancy", + "ParameterValue": "default" + } +] diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/taskcat.yml b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/taskcat.yml new file mode 100644 index 0000000..57676dc --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/ci/taskcat.yml @@ -0,0 +1,70 @@ +global: + govcloud: true + marketplace-ami: false + owner: quickstart@amazon.com + qsname: quickstart-aws-vpc + regions: + - ap-northeast-1 + - ap-northeast-2 + - ap-south-1 + - ap-southeast-1 + - ap-southeast-2 + - ca-central-1 + - eu-central-1 + - eu-west-1 + - eu-west-2 + - us-east-1 + - us-east-2 + - us-west-1 + - us-west-2 + reporting: true +tests: + vpc-defaults: + parameter_input: aws-vpc-defaults.json + template_file: aws-vpc.template + vpc-complete: + parameter_input: aws-vpc-complete.json + template_file: aws-vpc.template + vpc-defaults-sa-east-1: + parameter_input: aws-vpc-sa-east-1.json + template_file: aws-vpc.template + regions: + - sa-east-1 + vpc-public: + parameter_input: aws-vpc-public.json + template_file: aws-vpc.template + 3az-eu-west-1: + parameter_input: aws-vpc-3az.json + regions: + - eu-west-1 + template_file: aws-vpc.template + 3az-complete-us-east-2: + parameter_input: aws-vpc-3az-complete.json + regions: + - us-east-2 + template_file: aws-vpc.template + 3az-public-us-west-2: + parameter_input: aws-vpc-3az-public.json + regions: + - us-west-2 + template_file: aws-vpc.template + 4az-us-east-1: + parameter_input: aws-vpc-4az.json + regions: + - us-east-1 + template_file: aws-vpc.template + 4az-complete-us-east-1: + parameter_input: aws-vpc-4az-complete.json + regions: + - us-east-1 + template_file: aws-vpc.template + 4az-public-us-east-1: + parameter_input: aws-vpc-4az-public.json + regions: + - us-east-1 + template_file: aws-vpc.template + dedicated-us-west-1: + parameter_input: aws-vpc-dedicated.json + regions: + - us-west-1 + template_file: aws-vpc.template diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/generated/parameters/index.adoc b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/generated/parameters/index.adoc new file mode 100644 index 0000000..ff7bd09 --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/generated/parameters/index.adoc @@ -0,0 +1 @@ +// placeholder diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/generated/regions/index.adoc b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/generated/regions/index.adoc new file mode 100644 index 0000000..ff7bd09 --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/generated/regions/index.adoc @@ -0,0 +1 @@ +// placeholder diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/generated/services/index.adoc b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/generated/services/index.adoc new file mode 100644 index 0000000..ff7bd09 --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/generated/services/index.adoc @@ -0,0 +1 @@ +// placeholder diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/generated/services/metadata.adoc b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/generated/services/metadata.adoc new file mode 100644 index 0000000..ff7bd09 --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/generated/services/metadata.adoc @@ -0,0 +1 @@ +// placeholder diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/images/architecture_diagram.png b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/images/architecture_diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..44926ab045ae41953d9550a1cbe4a16fb623b5f0 GIT binary patch literal 90606 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 literal 0 HcmV?d00001 diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/images/aws-quickstart-graphic.png b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/images/aws-quickstart-graphic.png new file mode 100644 index 0000000000000000000000000000000000000000..8efde67901a751e3324f90ec5eeb40463b11e5ed GIT binary patch literal 26468 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 M^0P$Qr>}nh2kB$5C;$Ke literal 0 HcmV?d00001 diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/images/cfn_outputs.png b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/images/cfn_outputs.png new file mode 100644 index 0000000000000000000000000000000000000000..15ac1591d582e0397d137df72285a17fb6734081 GIT binary patch literal 201384 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

*%k)*$8XKb(0$N4uIbE zRnusiERJvXML;?|j#;;Jk1g>F?|s z`1))jZV~QH64#^@GR#$7s0`fvS#ODlIySls>hI6M#97;(l=pB5o5lie+&i0%QTI6t z>9>3MO_Ve}Pp?i}QTtXNd81bW*W2B%mulRCJu4cRl{BsXO=&try`p7*~js3|!p&q;yYoesXqo$q;2#SA@-I(+a zOYVF#@!B572~iFMs5YNH8uF^H}B+uu8$dugNenWNGB{@Z0CE@v?t6io~h&Wx~q|}@AdZB7H z;>#ZM$0f5N`Ev%;!n^^w*?#QuTHzC@D5timaNpM}+>R8BF6&B*D$RUuvv)7jtQ3=( zx3GldFNQO$36DL&ywUI;Ej~qR?>FCzjT5F5Jw0?@_^{yUln$8lKc;%WLv?%0D{izC1xkb+I<(j}lINvjce90KV=6&3}Lr?el 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

`bW=<=<7KJxtYfhdkSOIs16jB65bR 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 uM +// Identify your target audience and explain how/why they would use this Quick Start. +//Avoid borrowing text from third-party websites (copying text from AWS service documentation is fine). Also, avoid marketing-speak, focusing instead on the technical aspect. + +This Quick Start provides a networking foundation for AWS Cloud infrastructures. It +deploys an Amazon Virtual Private Cloud (Amazon VPC) according to AWS best practices +and guidelines. Amazon VPC is the networking layer for Amazon Elastic Compute Cloud +(Amazon EC2) and provides a private, isolated section of the AWS Cloud where you can +launch AWS services and other resources in a virtual network. For a discussion of best +design practices for Amazon VPC environments, see the documentation and articles listed +in the link:#_other_useful_information[Other useful information] section. \ No newline at end of file diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/partner_editable/pre-reqs.adoc b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/partner_editable/pre-reqs.adoc new file mode 100644 index 0000000..8376035 --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/partner_editable/pre-reqs.adoc @@ -0,0 +1 @@ +// If no preperation is required, remove all content from here \ No newline at end of file diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/partner_editable/product_description.adoc b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/partner_editable/product_description.adoc new file mode 100644 index 0000000..9213cfa --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/partner_editable/product_description.adoc @@ -0,0 +1,18 @@ +// Replace the content in <> +// Briefly describe the software. Use consistent and clear branding. +// Include the benefits of using the software on AWS, and provide details on usage scenarios. + +The Amazon VPC architecture includes public and private subnets. The first set of private +subnets share the default network access control list (ACL) from the Amazon VPC, and a +second, optional set of private subnets includes dedicated custom network ACLs per subnet. + +Optionally you may choose to deploy a completely public VPC (no private subnets), or a completely private VPC (no public subnets). + +The Quick Start divides the Amazon VPC address space in a predictable manner across +multiple Availability Zones, and deploys either NAT instances or NAT gateways for +outbound Internet access, depending on the AWS Region you deploy the Quick Start in. + +You can use this Quick Start as a building block for your own deployments. You can scale it +up or down by adding or removing subnets and Availability Zones according to your needs, +and add other infrastructure components and software layers to complete your AWS +environment. diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/partner_editable/regions.adoc b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/partner_editable/regions.adoc new file mode 100644 index 0000000..8003267 --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/partner_editable/regions.adoc @@ -0,0 +1,29 @@ + +[cols=3*,options="header"] +|=== +|Code +|Name +| Opt-in Status + +|us-east-2 |US East (Ohio) |Not required +|us-east-1 |US East (N. Virginia) |Not required +|us-west-1 |US West (N. California) |Not required +|us-west-2 |US West (Oregon) |Not required +|af-south-1 |Africa (Cape Town) |Required +|ap-east-1 |Asia Pacific (Hong Kong) |Required +|ap-south-1 |Asia Pacific (Mumbai) |Not required +|ap-northeast-3 |Asia Pacific (Osaka-Local) |Not required +|ap-northeast-2 |Asia Pacific (Seoul) |Not required +|ap-southeast-1 |Asia Pacific (Singapore) |Not required +|ap-southeast-2 |Asia Pacific (Sydney) |Not required +|ap-northeast-1 |Asia Pacific (Tokyo) |Not required +|ca-central-1 |Canada (Central) |Not required +|eu-central-1 |Europe (Frankfurt) |Not required +|eu-west-1 |Europe (Ireland) |Not required +|eu-west-2 |Europe (London) |Not required +|eu-south-1 |Europe (Milan) |Required +|eu-west-3 |Europe (Paris) |Not required +|eu-north-1 |Europe (Stockholm) |Not required +|me-south-1 |Middle East (Bahrain) |Required +|sa-east-1 |South America (São Paulo) |Not required +|=== \ No newline at end of file diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/partner_editable/service_limits.adoc b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/partner_editable/service_limits.adoc new file mode 100644 index 0000000..d6b8b90 --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/partner_editable/service_limits.adoc @@ -0,0 +1,7 @@ +// Replace the in each row to specify the number of resources used in this deployment. Remove the rows for resources that aren’t used. +|=== +|Resource |This deployment uses + +// Space needed to maintain table headers +|VPCs |1 +|=== diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/partner_editable/specialized_knowledge.adoc b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/partner_editable/specialized_knowledge.adoc new file mode 100644 index 0000000..1bd75e1 --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/docs/partner_editable/specialized_knowledge.adoc @@ -0,0 +1,6 @@ +// Replace the content in <> +// Describe or link to specific knowledge requirements; for example: “familiarity with basic concepts in the areas of networking, database operations, and data encryption” or “familiarity with .” + +This Quick Start assumes familiarity with VPC architecure and CloudFormation. + + diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/templates/aws-vpc.template b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/templates/aws-vpc.template new file mode 100644 index 0000000..294117a --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/templates/aws-vpc.template @@ -0,0 +1,3591 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "This template creates a Multi-AZ, multi-subnet VPC infrastructure with managed NAT gateways in the public subnet for each Availability Zone. You can also create additional private subnets with dedicated custom network access control lists (ACLs). If you deploy the Quick Start in a region that doesn't support NAT gateways, NAT instances are deployed instead. **WARNING** This template creates AWS resources. You will be billed for the AWS resources used if you create a stack from this template. (qs-1qnnspaap)", + "Metadata": { + "AWS::CloudFormation::Interface": { + "ParameterGroups": [ + { + "Label": { + "default": "Availability Zone Configuration" + }, + "Parameters": [ + "AvailabilityZones", + "NumberOfAZs" + ] + }, + { + "Label": { + "default": "Network Configuration" + }, + "Parameters": [ + "VPCCIDR", + "PublicSubnet1CIDR", + "PublicSubnet2CIDR", + "PublicSubnet3CIDR", + "PublicSubnet4CIDR", + "PublicSubnetTag1", + "PublicSubnetTag2", + "PublicSubnetTag3", + "CreatePrivateSubnets", + "PrivateSubnet1ACIDR", + "PrivateSubnet2ACIDR", + "PrivateSubnet3ACIDR", + "PrivateSubnet4ACIDR", + "PrivateSubnetATag1", + "PrivateSubnetATag2", + "PrivateSubnetATag3", + "CreateAdditionalPrivateSubnets", + "PrivateSubnet1BCIDR", + "PrivateSubnet2BCIDR", + "PrivateSubnet3BCIDR", + "PrivateSubnet4BCIDR", + "PrivateSubnetBTag1", + "PrivateSubnetBTag2", + "PrivateSubnetBTag3", + "VPCTenancy" + ] + }, + { + "Label": { + "default": "Deprecated: NAT Instance Configuration" + }, + "Parameters": [ + "KeyPairName", + "NATInstanceType" + ] + } + ], + "ParameterLabels": { + "AvailabilityZones": { + "default": "Availability Zones" + }, + "CreateAdditionalPrivateSubnets": { + "default": "Create additional private subnets with dedicated network ACLs" + }, + "CreatePrivateSubnets": { + "default": "Create private subnets" + }, + "KeyPairName": { + "default": "Deprecated: Key pair name" + }, + "NATInstanceType": { + "default": "Deprecated: NAT instance type" + }, + "NumberOfAZs": { + "default": "Number of Availability Zones" + }, + "PrivateSubnet1ACIDR": { + "default": "Private subnet 1A CIDR" + }, + "PrivateSubnet1BCIDR": { + "default": "Private subnet 1B with dedicated network ACL CIDR" + }, + "PrivateSubnet2ACIDR": { + "default": "Private subnet 2A CIDR" + }, + "PrivateSubnet2BCIDR": { + "default": "Private subnet 2B with dedicated network ACL CIDR" + }, + "PrivateSubnet3ACIDR": { + "default": "Private subnet 3A CIDR" + }, + "PrivateSubnet3BCIDR": { + "default": "Private subnet 3B with dedicated network ACL CIDR" + }, + "PrivateSubnet4ACIDR": { + "default": "Private subnet 4A CIDR" + }, + "PrivateSubnet4BCIDR": { + "default": "Private subnet 4B with dedicated network ACL CIDR" + }, + "PrivateSubnetATag1": { + "default": "Tag for Private A Subnets" + }, + "PrivateSubnetATag2": { + "default": "Tag for Private A Subnets" + }, + "PrivateSubnetATag3": { + "default": "Tag for Private A Subnets" + }, + "PrivateSubnetBTag1": { + "default": "Tag for Private B Subnets" + }, + "PrivateSubnetBTag2": { + "default": "Tag for Private B Subnets" + }, + "PrivateSubnetBTag3": { + "default": "Tag for Private B Subnets" + }, + "PublicSubnet1CIDR": { + "default": "Public subnet 1 CIDR" + }, + "PublicSubnet2CIDR": { + "default": "Public subnet 2 CIDR" + }, + "PublicSubnet3CIDR": { + "default": "Public subnet 3 CIDR" + }, + "PublicSubnet4CIDR": { + "default": "Public subnet 4 CIDR" + }, + "PublicSubnetTag1": { + "default": "Tag for Public Subnets" + }, + "PublicSubnetTag2": { + "default": "Tag for Public Subnets" + }, + "PublicSubnetTag3": { + "default": "Tag for Public Subnets" + }, + "VPCCIDR": { + "default": "VPC CIDR" + }, + "VPCTenancy": { + "default": "VPC Tenancy" + } + } + } + }, + "Parameters": { + "AvailabilityZones": { + "Description": "List of Availability Zones to use for the subnets in the VPC. Note: The logical order is preserved.", + "Type": "List" + }, + "CreateAdditionalPrivateSubnets": { + "AllowedValues": [ + "true", + "false" + ], + "Default": "false", + "Description": "Set to true to create a network ACL protected subnet in each Availability Zone. If false, the CIDR parameters for those subnets will be ignored. If true, it also requires that the 'Create private subnets' parameter is also true to have any effect.", + "Type": "String" + }, + "CreatePrivateSubnets": { + "AllowedValues": [ + "true", + "false" + ], + "Default": "true", + "Description": "Set to false to create only public subnets. If false, the CIDR parameters for ALL private subnets will be ignored.", + "Type": "String" + }, + "KeyPairName": { + "Description": "Deprecated. NAT gateways are now supported in all regions.", + "Type": "String", + "Default": "deprecated" + }, + "NATInstanceType": { + "Default": "deprecated", + "Description": "Deprecated. NAT gateways are now supported in all regions.", + "Type": "String" + }, + "NumberOfAZs": { + "AllowedValues": [ + "2", + "3", + "4" + ], + "Default": "2", + "Description": "Number of Availability Zones to use in the VPC. This must match your selections in the list of Availability Zones parameter.", + "Type": "String" + }, + "PrivateSubnet1ACIDR": { + "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$", + "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28", + "Default": "10.0.0.0/19", + "Description": "CIDR block for private subnet 1A located in Availability Zone 1", + "Type": "String" + }, + "PrivateSubnet1BCIDR": { + "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$", + "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28", + "Default": "10.0.192.0/21", + "Description": "CIDR block for private subnet 1B with dedicated network ACL located in Availability Zone 1", + "Type": "String" + }, + "PrivateSubnet2ACIDR": { + "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$", + "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28", + "Default": "10.0.32.0/19", + "Description": "CIDR block for private subnet 2A located in Availability Zone 2", + "Type": "String" + }, + "PrivateSubnet2BCIDR": { + "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$", + "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28", + "Default": "10.0.200.0/21", + "Description": "CIDR block for private subnet 2B with dedicated network ACL located in Availability Zone 2", + "Type": "String" + }, + "PrivateSubnet3ACIDR": { + "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$", + "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28", + "Default": "10.0.64.0/19", + "Description": "CIDR block for private subnet 3A located in Availability Zone 3", + "Type": "String" + }, + "PrivateSubnet3BCIDR": { + "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$", + "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28", + "Default": "10.0.208.0/21", + "Description": "CIDR block for private subnet 3B with dedicated network ACL located in Availability Zone 3", + "Type": "String" + }, + "PrivateSubnet4ACIDR": { + "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$", + "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28", + "Default": "10.0.96.0/19", + "Description": "CIDR block for private subnet 4A located in Availability Zone 4", + "Type": "String" + }, + "PrivateSubnet4BCIDR": { + "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$", + "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28", + "Default": "10.0.216.0/21", + "Description": "CIDR block for private subnet 4B with dedicated network ACL located in Availability Zone 4", + "Type": "String" + }, + "PrivateSubnetATag1": { + "AllowedPattern": "^([a-zA-Z0-9+\\-._:/@]+=[a-zA-Z0-9+\\-.,_:/@ *\\\\\"'\\[\\]\\{\\}]*)?$", + "ConstraintDescription": "tags must be in format \"Key=Value\" keys can only contain [a-zA-Z0-9+\\-._:/@], values can contain [a-zA-Z0-9+\\-._:/@ *\\\\\"'\\[\\]\\{\\}]", + "Default": "Network=Private", + "Description": "tag to add to private subnets A, in format Key=Value (Optional)", + "Type": "String" + }, + "PrivateSubnetATag2": { + "AllowedPattern": "^([a-zA-Z0-9+\\-._:/@]+=[a-zA-Z0-9+\\-.,_:/@ *\\\\\"'\\[\\]\\{\\}]*)?$", + "ConstraintDescription": "tags must be in format \"Key=Value\" keys can only contain [a-zA-Z0-9+\\-._:/@], values can contain [a-zA-Z0-9+\\-._:/@ *\\\\\"'\\[\\]\\{\\}]", + "Default": "", + "Description": "tag to add to private subnets A, in format Key=Value (Optional)", + "Type": "String" + }, + "PrivateSubnetATag3": { + "AllowedPattern": "^([a-zA-Z0-9+\\-._:/@]+=[a-zA-Z0-9+\\-.,_:/@ *\\\\\"'\\[\\]\\{\\}]*)?$", + "ConstraintDescription": "tags must be in format \"Key=Value\" keys can only contain [a-zA-Z0-9+\\-._:/@], values can contain [a-zA-Z0-9+\\-._:/@ *\\\\\"'\\[\\]\\{\\}]", + "Default": "", + "Description": "tag to add to private subnets A, in format Key=Value (Optional)", + "Type": "String" + }, + "PrivateSubnetBTag1": { + "AllowedPattern": "^([a-zA-Z0-9+\\-._:/@]+=[a-zA-Z0-9+\\-.,_:/@ *\\\\\"'\\[\\]\\{\\}]*)?$", + "ConstraintDescription": "tags must be in format \"Key=Value\" keys can only contain [a-zA-Z0-9+\\-._:/@], values can contain [a-zA-Z0-9+\\-._:/@ *\\\\\"'\\[\\]\\{\\}]", + "Default": "Network=Private", + "Description": "tag to add to private subnets B, in format Key=Value (Optional)", + "Type": "String" + }, + "PrivateSubnetBTag2": { + "AllowedPattern": "^([a-zA-Z0-9+\\-._:/@]+=[a-zA-Z0-9+\\-.,_:/@ *\\\\\"'\\[\\]\\{\\}]*)?$", + "ConstraintDescription": "tags must be in format \"Key=Value\" keys can only contain [a-zA-Z0-9+\\-._:/@], values can contain [a-zA-Z0-9+\\-._:/@ *\\\\\"'\\[\\]\\{\\}]", + "Default": "", + "Description": "tag to add to private subnets B, in format Key=Value (Optional)", + "Type": "String" + }, + "PrivateSubnetBTag3": { + "AllowedPattern": "^([a-zA-Z0-9+\\-._:/@]+=[a-zA-Z0-9+\\-.,_:/@ *\\\\\"'\\[\\]\\{\\}]*)?$", + "ConstraintDescription": "tags must be in format \"Key=Value\" keys can only contain [a-zA-Z0-9+\\-._:/@], values can contain [a-zA-Z0-9+\\-._:/@ *\\\\\"'\\[\\]\\{\\}]", + "Default": "", + "Description": "tag to add to private subnets B, in format Key=Value (Optional)", + "Type": "String" + }, + "PublicSubnet1CIDR": { + "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$", + "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28", + "Default": "10.0.128.0/20", + "Description": "CIDR block for the public DMZ subnet 1 located in Availability Zone 1", + "Type": "String" + }, + "PublicSubnet2CIDR": { + "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$", + "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28", + "Default": "10.0.144.0/20", + "Description": "CIDR block for the public DMZ subnet 2 located in Availability Zone 2", + "Type": "String" + }, + "PublicSubnet3CIDR": { + "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$", + "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28", + "Default": "10.0.160.0/20", + "Description": "CIDR block for the public DMZ subnet 3 located in Availability Zone 3", + "Type": "String" + }, + "PublicSubnet4CIDR": { + "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$", + "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28", + "Default": "10.0.176.0/20", + "Description": "CIDR block for the public DMZ subnet 4 located in Availability Zone 4", + "Type": "String" + }, + "PublicSubnetTag1": { + "AllowedPattern": "^([a-zA-Z0-9+\\-._:/@]+=[a-zA-Z0-9+\\-.,_:/@ *\\\\\"'\\[\\]\\{\\}]*)?$", + "ConstraintDescription": "tags must be in format \"Key=Value\" keys can only contain [a-zA-Z0-9+\\-._:/@], values can contain [a-zA-Z0-9+\\-._:/@ *\\\\\"'\\[\\]\\{\\}]", + "Default": "Network=Public", + "Description": "tag to add to public subnets, in format Key=Value (Optional)", + "Type": "String" + }, + "PublicSubnetTag2": { + "AllowedPattern": "^([a-zA-Z0-9+\\-._:/@]+=[a-zA-Z0-9+\\-.,_:/@ *\\\\\"'\\[\\]\\{\\}]*)?$", + "ConstraintDescription": "tags must be in format \"Key=Value\" keys can only contain [a-zA-Z0-9+\\-._:/@], values can contain [a-zA-Z0-9+\\-._:/@ *\\\\\"'\\[\\]\\{\\}]", + "Default": "", + "Description": "tag to add to public subnets, in format Key=Value (Optional)", + "Type": "String" + }, + "PublicSubnetTag3": { + "AllowedPattern": "^([a-zA-Z0-9+\\-._:/@]+=[a-zA-Z0-9+\\-.,_:/@ *\\\\\"'\\[\\]\\{\\}]*)?$", + "ConstraintDescription": "tags must be in format \"Key=Value\" keys can only contain [a-zA-Z0-9+\\-._:/@], values can contain [a-zA-Z0-9+\\-._:/@ *\\\\\"'\\[\\]\\{\\}]", + "Default": "", + "Description": "tag to add to public subnets, in format Key=Value (Optional)", + "Type": "String" + }, + "VPCCIDR": { + "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$", + "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28", + "Default": "10.0.0.0/16", + "Description": "CIDR block for the VPC", + "Type": "String" + }, + "VPCTenancy": { + "AllowedValues": [ + "default", + "dedicated" + ], + "Default": "default", + "Description": "The allowed tenancy of instances launched into the VPC", + "Type": "String" + } + }, + "Conditions": { + "3AZCondition": { + "Fn::Or": [ + { + "Fn::Equals": [ + { + "Ref": "NumberOfAZs" + }, + "3" + ] + }, + { + "Condition": "4AZCondition" + } + ] + }, + "4AZCondition": { + "Fn::Equals": [ + { + "Ref": "NumberOfAZs" + }, + "4" + ] + }, + "AdditionalPrivateSubnetsCondition": { + "Fn::And": [ + { + "Fn::Equals": [ + { + "Ref": "CreatePrivateSubnets" + }, + "true" + ] + }, + { + "Fn::Equals": [ + { + "Ref": "CreateAdditionalPrivateSubnets" + }, + "true" + ] + } + ] + }, + "AdditionalPrivateSubnets&3AZCondition": { + "Fn::And": [ + { + "Condition": "AdditionalPrivateSubnetsCondition" + }, + { + "Condition": "3AZCondition" + } + ] + }, + "AdditionalPrivateSubnets&4AZCondition": { + "Fn::And": [ + { + "Condition": "AdditionalPrivateSubnetsCondition" + }, + { + "Condition": "4AZCondition" + } + ] + }, + "GovCloudCondition": { + "Fn::Equals": [ + { + "Ref": "AWS::Region" + }, + "us-gov-west-1" + ] + }, + "NVirginiaRegionCondition": { + "Fn::Equals": [ + { + "Ref": "AWS::Region" + }, + "us-east-1" + ] + }, + "PrivateSubnetsCondition": { + "Fn::Equals": [ + { + "Ref": "CreatePrivateSubnets" + }, + "true" + ] + }, + "PrivateSubnets&3AZCondition": { + "Fn::And": [ + { + "Condition": "PrivateSubnetsCondition" + }, + { + "Condition": "3AZCondition" + } + ] + }, + "PrivateSubnets&4AZCondition": { + "Fn::And": [ + { + "Condition": "PrivateSubnetsCondition" + }, + { + "Condition": "4AZCondition" + } + ] + }, + "PrivateSubnetATag1Condition": { + "Fn::Not": [ + { + "Fn::Equals": [ + { + "Ref": "PrivateSubnetATag1" + }, + "" + ] + } + ] + }, + "PrivateSubnetATag2Condition": { + "Fn::Not": [ + { + "Fn::Equals": [ + { + "Ref": "PrivateSubnetATag2" + }, + "" + ] + } + ] + }, + "PrivateSubnetATag3Condition": { + "Fn::Not": [ + { + "Fn::Equals": [ + { + "Ref": "PrivateSubnetATag3" + }, + "" + ] + } + ] + }, + "PrivateSubnetBTag1Condition": { + "Fn::Not": [ + { + "Fn::Equals": [ + { + "Ref": "PrivateSubnetBTag1" + }, + "" + ] + } + ] + }, + "PrivateSubnetBTag2Condition": { + "Fn::Not": [ + { + "Fn::Equals": [ + { + "Ref": "PrivateSubnetBTag2" + }, + "" + ] + } + ] + }, + "PrivateSubnetBTag3Condition": { + "Fn::Not": [ + { + "Fn::Equals": [ + { + "Ref": "PrivateSubnetBTag3" + }, + "" + ] + } + ] + }, + "PublicSubnetTag1Condition": { + "Fn::Not": [ + { + "Fn::Equals": [ + { + "Ref": "PublicSubnetTag1" + }, + "" + ] + } + ] + }, + "PublicSubnetTag2Condition": { + "Fn::Not": [ + { + "Fn::Equals": [ + { + "Ref": "PublicSubnetTag2" + }, + "" + ] + } + ] + }, + "PublicSubnetTag3Condition": { + "Fn::Not": [ + { + "Fn::Equals": [ + { + "Ref": "PublicSubnetTag3" + }, + "" + ] + } + ] + } + }, + "Resources": { + "DHCPOptions": { + "Type": "AWS::EC2::DHCPOptions", + "Properties": { + "DomainName": { + "Fn::If": [ + "NVirginiaRegionCondition", + "ec2.internal", + { + "Fn::Sub": "${AWS::Region}.compute.internal" + } + ] + }, + "DomainNameServers": [ + "AmazonProvidedDNS" + ] + } + }, + "VPC": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": { + "Ref": "VPCCIDR" + }, + "InstanceTenancy": { + "Ref": "VPCTenancy" + }, + "EnableDnsSupport": true, + "EnableDnsHostnames": true, + "Tags": [ + { + "Key": "Name", + "Value": { + "Ref": "AWS::StackName" + } + } + ] + } + }, + "VPCDHCPOptionsAssociation": { + "Type": "AWS::EC2::VPCDHCPOptionsAssociation", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "DhcpOptionsId": { + "Ref": "DHCPOptions" + } + } + }, + "InternetGateway": { + "Type": "AWS::EC2::InternetGateway", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": { + "Ref": "AWS::StackName" + } + } + ] + } + }, + "VPCGatewayAttachment": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "InternetGatewayId": { + "Ref": "InternetGateway" + } + } + }, + "PrivateSubnet1A": { + "Condition": "PrivateSubnetsCondition", + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "CidrBlock": { + "Ref": "PrivateSubnet1ACIDR" + }, + "AvailabilityZone": { + "Fn::Select": [ + "0", + { + "Ref": "AvailabilityZones" + } + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 1A" + }, + { + "Fn::If": [ + "PrivateSubnetATag1Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag1" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag1" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetATag2Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag2" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag2" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetATag3Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag3" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag3" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + } + ] + } + }, + "PrivateSubnet1B": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "CidrBlock": { + "Ref": "PrivateSubnet1BCIDR" + }, + "AvailabilityZone": { + "Fn::Select": [ + "0", + { + "Ref": "AvailabilityZones" + } + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 1B" + }, + { + "Fn::If": [ + "PrivateSubnetBTag1Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag1" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag1" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetBTag2Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag2" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag2" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetBTag3Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag3" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag3" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + } + ] + } + }, + "PrivateSubnet2A": { + "Condition": "PrivateSubnetsCondition", + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "CidrBlock": { + "Ref": "PrivateSubnet2ACIDR" + }, + "AvailabilityZone": { + "Fn::Select": [ + "1", + { + "Ref": "AvailabilityZones" + } + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 2A" + }, + { + "Fn::If": [ + "PrivateSubnetATag1Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag1" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag1" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetATag2Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag2" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag2" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetATag3Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag3" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag3" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + } + ] + } + }, + "PrivateSubnet2B": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "CidrBlock": { + "Ref": "PrivateSubnet2BCIDR" + }, + "AvailabilityZone": { + "Fn::Select": [ + "1", + { + "Ref": "AvailabilityZones" + } + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 2B" + }, + { + "Fn::If": [ + "PrivateSubnetBTag1Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag1" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag1" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetBTag2Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag2" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag2" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetBTag3Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag3" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag3" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + } + ] + } + }, + "PrivateSubnet3A": { + "Condition": "PrivateSubnets&3AZCondition", + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "CidrBlock": { + "Ref": "PrivateSubnet3ACIDR" + }, + "AvailabilityZone": { + "Fn::Select": [ + "2", + { + "Ref": "AvailabilityZones" + } + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 3A" + }, + { + "Fn::If": [ + "PrivateSubnetATag1Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag1" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag1" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetATag2Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag2" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag2" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetATag3Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag3" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag3" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + } + ] + } + }, + "PrivateSubnet3B": { + "Condition": "AdditionalPrivateSubnets&3AZCondition", + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "CidrBlock": { + "Ref": "PrivateSubnet3BCIDR" + }, + "AvailabilityZone": { + "Fn::Select": [ + "2", + { + "Ref": "AvailabilityZones" + } + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 3B" + }, + { + "Fn::If": [ + "PrivateSubnetBTag1Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag1" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag1" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetBTag2Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag2" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag2" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetBTag3Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag3" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag3" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + } + ] + } + }, + "PrivateSubnet4A": { + "Condition": "PrivateSubnets&4AZCondition", + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "CidrBlock": { + "Ref": "PrivateSubnet4ACIDR" + }, + "AvailabilityZone": { + "Fn::Select": [ + "3", + { + "Ref": "AvailabilityZones" + } + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 4A" + }, + { + "Fn::If": [ + "PrivateSubnetATag1Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag1" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag1" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetATag2Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag2" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag2" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetATag3Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag3" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag3" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + } + ] + } + }, + "PrivateSubnet4B": { + "Condition": "AdditionalPrivateSubnets&4AZCondition", + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "CidrBlock": { + "Ref": "PrivateSubnet4BCIDR" + }, + "AvailabilityZone": { + "Fn::Select": [ + "3", + { + "Ref": "AvailabilityZones" + } + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 4B" + }, + { + "Fn::If": [ + "PrivateSubnetBTag1Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag1" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag1" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetBTag2Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag2" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag2" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetBTag3Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag3" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag3" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + } + ] + } + }, + "PublicSubnet1": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "CidrBlock": { + "Ref": "PublicSubnet1CIDR" + }, + "AvailabilityZone": { + "Fn::Select": [ + "0", + { + "Ref": "AvailabilityZones" + } + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "Public subnet 1" + }, + { + "Fn::If": [ + "PublicSubnetTag1Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag1" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag1" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PublicSubnetTag2Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag2" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag2" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PublicSubnetTag3Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag3" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag3" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + } + ], + "MapPublicIpOnLaunch": true + } + }, + "PublicSubnet2": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "CidrBlock": { + "Ref": "PublicSubnet2CIDR" + }, + "AvailabilityZone": { + "Fn::Select": [ + "1", + { + "Ref": "AvailabilityZones" + } + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "Public subnet 2" + }, + { + "Fn::If": [ + "PublicSubnetTag1Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag1" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag1" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PublicSubnetTag2Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag2" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag2" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PublicSubnetTag3Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag3" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag3" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + } + ], + "MapPublicIpOnLaunch": true + } + }, + "PublicSubnet3": { + "Condition": "3AZCondition", + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "CidrBlock": { + "Ref": "PublicSubnet3CIDR" + }, + "AvailabilityZone": { + "Fn::Select": [ + "2", + { + "Ref": "AvailabilityZones" + } + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "Public subnet 3" + }, + { + "Fn::If": [ + "PublicSubnetTag1Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag1" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag1" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PublicSubnetTag2Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag2" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag2" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PublicSubnetTag3Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag3" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag3" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + } + ], + "MapPublicIpOnLaunch": true + } + }, + "PublicSubnet4": { + "Condition": "4AZCondition", + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "CidrBlock": { + "Ref": "PublicSubnet4CIDR" + }, + "AvailabilityZone": { + "Fn::Select": [ + "3", + { + "Ref": "AvailabilityZones" + } + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "Public subnet 4" + }, + { + "Fn::If": [ + "PublicSubnetTag1Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag1" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag1" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PublicSubnetTag2Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag2" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag2" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PublicSubnetTag3Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag3" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag3" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + } + ], + "MapPublicIpOnLaunch": true + } + }, + "PrivateSubnet1ARouteTable": { + "Condition": "PrivateSubnetsCondition", + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 1A" + }, + { + "Key": "Network", + "Value": "Private" + } + ] + } + }, + "PrivateSubnet1ARoute": { + "Condition": "PrivateSubnetsCondition", + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "PrivateSubnet1ARouteTable" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "NATGateway1" + } + } + }, + "PrivateSubnet1ARouteTableAssociation": { + "Condition": "PrivateSubnetsCondition", + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "SubnetId": { + "Ref": "PrivateSubnet1A" + }, + "RouteTableId": { + "Ref": "PrivateSubnet1ARouteTable" + } + } + }, + "PrivateSubnet2ARouteTable": { + "Condition": "PrivateSubnetsCondition", + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 2A" + }, + { + "Key": "Network", + "Value": "Private" + } + ] + } + }, + "PrivateSubnet2ARoute": { + "Condition": "PrivateSubnetsCondition", + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "PrivateSubnet2ARouteTable" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "NATGateway2" + } + } + }, + "PrivateSubnet2ARouteTableAssociation": { + "Condition": "PrivateSubnetsCondition", + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "SubnetId": { + "Ref": "PrivateSubnet2A" + }, + "RouteTableId": { + "Ref": "PrivateSubnet2ARouteTable" + } + } + }, + "PrivateSubnet3ARouteTable": { + "Condition": "PrivateSubnets&3AZCondition", + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 3A" + }, + { + "Key": "Network", + "Value": "Private" + } + ] + } + }, + "PrivateSubnet3ARoute": { + "Condition": "PrivateSubnets&3AZCondition", + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "PrivateSubnet3ARouteTable" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "NATGateway3" + } + } + }, + "PrivateSubnet3ARouteTableAssociation": { + "Condition": "PrivateSubnets&3AZCondition", + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "SubnetId": { + "Ref": "PrivateSubnet3A" + }, + "RouteTableId": { + "Ref": "PrivateSubnet3ARouteTable" + } + } + }, + "PrivateSubnet4ARouteTable": { + "Condition": "PrivateSubnets&4AZCondition", + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 4A" + }, + { + "Key": "Network", + "Value": "Private" + } + ] + } + }, + "PrivateSubnet4ARoute": { + "Condition": "PrivateSubnets&4AZCondition", + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "PrivateSubnet4ARouteTable" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "NATGateway4" + } + } + }, + "PrivateSubnet4ARouteTableAssociation": { + "Condition": "PrivateSubnets&4AZCondition", + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "SubnetId": { + "Ref": "PrivateSubnet4A" + }, + "RouteTableId": { + "Ref": "PrivateSubnet4ARouteTable" + } + } + }, + "PrivateSubnet1BRouteTable": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 1B" + }, + { + "Key": "Network", + "Value": "Private" + } + ] + } + }, + "PrivateSubnet1BRoute": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "PrivateSubnet1BRouteTable" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "NATGateway1" + } + } + }, + "PrivateSubnet1BRouteTableAssociation": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "SubnetId": { + "Ref": "PrivateSubnet1B" + }, + "RouteTableId": { + "Ref": "PrivateSubnet1BRouteTable" + } + } + }, + "PrivateSubnet1BNetworkAcl": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::NetworkAcl", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "Tags": [ + { + "Key": "Name", + "Value": "NACL Protected subnet 1" + }, + { + "Key": "Network", + "Value": "NACL Protected" + } + ] + } + }, + "PrivateSubnet1BNetworkAclEntryInbound": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::NetworkAclEntry", + "Properties": { + "CidrBlock": "0.0.0.0/0", + "Egress": false, + "NetworkAclId": { + "Ref": "PrivateSubnet1BNetworkAcl" + }, + "Protocol": -1, + "RuleAction": "allow", + "RuleNumber": 100 + } + }, + "PrivateSubnet1BNetworkAclEntryOutbound": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::NetworkAclEntry", + "Properties": { + "CidrBlock": "0.0.0.0/0", + "Egress": true, + "NetworkAclId": { + "Ref": "PrivateSubnet1BNetworkAcl" + }, + "Protocol": -1, + "RuleAction": "allow", + "RuleNumber": 100 + } + }, + "PrivateSubnet1BNetworkAclAssociation": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::SubnetNetworkAclAssociation", + "Properties": { + "SubnetId": { + "Ref": "PrivateSubnet1B" + }, + "NetworkAclId": { + "Ref": "PrivateSubnet1BNetworkAcl" + } + } + }, + "PrivateSubnet2BRouteTable": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 2B" + }, + { + "Key": "Network", + "Value": "Private" + } + ] + } + }, + "PrivateSubnet2BRoute": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "PrivateSubnet2BRouteTable" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "NATGateway2" + } + } + }, + "PrivateSubnet2BRouteTableAssociation": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "SubnetId": { + "Ref": "PrivateSubnet2B" + }, + "RouteTableId": { + "Ref": "PrivateSubnet2BRouteTable" + } + } + }, + "PrivateSubnet2BNetworkAcl": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::NetworkAcl", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "Tags": [ + { + "Key": "Name", + "Value": "NACL Protected subnet 2" + }, + { + "Key": "Network", + "Value": "NACL Protected" + } + ] + } + }, + "PrivateSubnet2BNetworkAclEntryInbound": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::NetworkAclEntry", + "Properties": { + "CidrBlock": "0.0.0.0/0", + "Egress": false, + "NetworkAclId": { + "Ref": "PrivateSubnet2BNetworkAcl" + }, + "Protocol": -1, + "RuleAction": "allow", + "RuleNumber": 100 + } + }, + "PrivateSubnet2BNetworkAclEntryOutbound": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::NetworkAclEntry", + "Properties": { + "CidrBlock": "0.0.0.0/0", + "Egress": true, + "NetworkAclId": { + "Ref": "PrivateSubnet2BNetworkAcl" + }, + "Protocol": -1, + "RuleAction": "allow", + "RuleNumber": 100 + } + }, + "PrivateSubnet2BNetworkAclAssociation": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::SubnetNetworkAclAssociation", + "Properties": { + "SubnetId": { + "Ref": "PrivateSubnet2B" + }, + "NetworkAclId": { + "Ref": "PrivateSubnet2BNetworkAcl" + } + } + }, + "PrivateSubnet3BRouteTable": { + "Condition": "AdditionalPrivateSubnets&3AZCondition", + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 3B" + }, + { + "Key": "Network", + "Value": "Private" + } + ] + } + }, + "PrivateSubnet3BRoute": { + "Condition": "AdditionalPrivateSubnets&3AZCondition", + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "PrivateSubnet3BRouteTable" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "NATGateway3" + } + } + }, + "PrivateSubnet3BRouteTableAssociation": { + "Condition": "AdditionalPrivateSubnets&3AZCondition", + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "SubnetId": { + "Ref": "PrivateSubnet3B" + }, + "RouteTableId": { + "Ref": "PrivateSubnet3BRouteTable" + } + } + }, + "PrivateSubnet3BNetworkAcl": { + "Condition": "AdditionalPrivateSubnets&3AZCondition", + "Type": "AWS::EC2::NetworkAcl", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "Tags": [ + { + "Key": "Name", + "Value": "NACL Protected subnet 3" + }, + { + "Key": "Network", + "Value": "NACL Protected" + } + ] + } + }, + "PrivateSubnet3BNetworkAclEntryInbound": { + "Condition": "AdditionalPrivateSubnets&3AZCondition", + "Type": "AWS::EC2::NetworkAclEntry", + "Properties": { + "CidrBlock": "0.0.0.0/0", + "Egress": false, + "NetworkAclId": { + "Ref": "PrivateSubnet3BNetworkAcl" + }, + "Protocol": -1, + "RuleAction": "allow", + "RuleNumber": 100 + } + }, + "PrivateSubnet3BNetworkAclEntryOutbound": { + "Condition": "AdditionalPrivateSubnets&3AZCondition", + "Type": "AWS::EC2::NetworkAclEntry", + "Properties": { + "CidrBlock": "0.0.0.0/0", + "Egress": true, + "NetworkAclId": { + "Ref": "PrivateSubnet3BNetworkAcl" + }, + "Protocol": -1, + "RuleAction": "allow", + "RuleNumber": 100 + } + }, + "PrivateSubnet3BNetworkAclAssociation": { + "Condition": "AdditionalPrivateSubnets&3AZCondition", + "Type": "AWS::EC2::SubnetNetworkAclAssociation", + "Properties": { + "SubnetId": { + "Ref": "PrivateSubnet3B" + }, + "NetworkAclId": { + "Ref": "PrivateSubnet3BNetworkAcl" + } + } + }, + "PrivateSubnet4BRouteTable": { + "Condition": "AdditionalPrivateSubnets&4AZCondition", + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 4B" + }, + { + "Key": "Network", + "Value": "Private" + } + ] + } + }, + "PrivateSubnet4BRoute": { + "Condition": "AdditionalPrivateSubnets&4AZCondition", + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "PrivateSubnet4BRouteTable" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "NATGateway4" + } + } + }, + "PrivateSubnet4BRouteTableAssociation": { + "Condition": "AdditionalPrivateSubnets&4AZCondition", + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "SubnetId": { + "Ref": "PrivateSubnet4B" + }, + "RouteTableId": { + "Ref": "PrivateSubnet4BRouteTable" + } + } + }, + "PrivateSubnet4BNetworkAcl": { + "Condition": "AdditionalPrivateSubnets&4AZCondition", + "Type": "AWS::EC2::NetworkAcl", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "Tags": [ + { + "Key": "Name", + "Value": "NACL Protected subnet 4" + }, + { + "Key": "Network", + "Value": "NACL Protected" + } + ] + } + }, + "PrivateSubnet4BNetworkAclEntryInbound": { + "Condition": "AdditionalPrivateSubnets&4AZCondition", + "Type": "AWS::EC2::NetworkAclEntry", + "Properties": { + "CidrBlock": "0.0.0.0/0", + "Egress": false, + "NetworkAclId": { + "Ref": "PrivateSubnet4BNetworkAcl" + }, + "Protocol": -1, + "RuleAction": "allow", + "RuleNumber": 100 + } + }, + "PrivateSubnet4BNetworkAclEntryOutbound": { + "Condition": "AdditionalPrivateSubnets&4AZCondition", + "Type": "AWS::EC2::NetworkAclEntry", + "Properties": { + "CidrBlock": "0.0.0.0/0", + "Egress": true, + "NetworkAclId": { + "Ref": "PrivateSubnet4BNetworkAcl" + }, + "Protocol": -1, + "RuleAction": "allow", + "RuleNumber": 100 + } + }, + "PrivateSubnet4BNetworkAclAssociation": { + "Condition": "AdditionalPrivateSubnets&4AZCondition", + "Type": "AWS::EC2::SubnetNetworkAclAssociation", + "Properties": { + "SubnetId": { + "Ref": "PrivateSubnet4B" + }, + "NetworkAclId": { + "Ref": "PrivateSubnet4BNetworkAcl" + } + } + }, + "PublicSubnetRouteTable": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "Tags": [ + { + "Key": "Name", + "Value": "Public Subnets" + }, + { + "Key": "Network", + "Value": "Public" + } + ] + } + }, + "PublicSubnetRoute": { + "DependsOn": "VPCGatewayAttachment", + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "PublicSubnetRouteTable" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "InternetGateway" + } + } + }, + "PublicSubnet1RouteTableAssociation": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "SubnetId": { + "Ref": "PublicSubnet1" + }, + "RouteTableId": { + "Ref": "PublicSubnetRouteTable" + } + } + }, + "PublicSubnet2RouteTableAssociation": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "SubnetId": { + "Ref": "PublicSubnet2" + }, + "RouteTableId": { + "Ref": "PublicSubnetRouteTable" + } + } + }, + "PublicSubnet3RouteTableAssociation": { + "Condition": "3AZCondition", + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "SubnetId": { + "Ref": "PublicSubnet3" + }, + "RouteTableId": { + "Ref": "PublicSubnetRouteTable" + } + } + }, + "PublicSubnet4RouteTableAssociation": { + "Condition": "4AZCondition", + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "SubnetId": { + "Ref": "PublicSubnet4" + }, + "RouteTableId": { + "Ref": "PublicSubnetRouteTable" + } + } + }, + "NAT1EIP": { + "Condition": "PrivateSubnetsCondition", + "DependsOn": "VPCGatewayAttachment", + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc" + } + }, + "NAT2EIP": { + "Condition": "PrivateSubnetsCondition", + "DependsOn": "VPCGatewayAttachment", + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc" + } + }, + "NAT3EIP": { + "Condition": "PrivateSubnets&3AZCondition", + "DependsOn": "VPCGatewayAttachment", + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc" + } + }, + "NAT4EIP": { + "Condition": "PrivateSubnets&4AZCondition", + "DependsOn": "VPCGatewayAttachment", + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc" + } + }, + "NATGateway1": { + "Condition": "PrivateSubnetsCondition", + "DependsOn": "VPCGatewayAttachment", + "Type": "AWS::EC2::NatGateway", + "Properties": { + "AllocationId": { + "Fn::GetAtt": [ + "NAT1EIP", + "AllocationId" + ] + }, + "SubnetId": { + "Ref": "PublicSubnet1" + } + } + }, + "NATGateway2": { + "Condition": "PrivateSubnetsCondition", + "DependsOn": "VPCGatewayAttachment", + "Type": "AWS::EC2::NatGateway", + "Properties": { + "AllocationId": { + "Fn::GetAtt": [ + "NAT2EIP", + "AllocationId" + ] + }, + "SubnetId": { + "Ref": "PublicSubnet2" + } + } + }, + "NATGateway3": { + "Condition": "PrivateSubnets&3AZCondition", + "DependsOn": "VPCGatewayAttachment", + "Type": "AWS::EC2::NatGateway", + "Properties": { + "AllocationId": { + "Fn::GetAtt": [ + "NAT3EIP", + "AllocationId" + ] + }, + "SubnetId": { + "Ref": "PublicSubnet3" + } + } + }, + "NATGateway4": { + "Condition": "PrivateSubnets&4AZCondition", + "DependsOn": "VPCGatewayAttachment", + "Type": "AWS::EC2::NatGateway", + "Properties": { + "AllocationId": { + "Fn::GetAtt": [ + "NAT4EIP", + "AllocationId" + ] + }, + "SubnetId": { + "Ref": "PublicSubnet4" + } + } + }, + "S3VPCEndpoint": { + "Condition": "PrivateSubnetsCondition", + "Type": "AWS::EC2::VPCEndpoint", + "Properties": { + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "*", + "Effect": "Allow", + "Resource": "*", + "Principal": "*" + } + ] + }, + "RouteTableIds": [ + { + "Ref": "PrivateSubnet1ARouteTable" + }, + { + "Ref": "PrivateSubnet2ARouteTable" + }, + { + "Fn::If": [ + "PrivateSubnets&3AZCondition", + { + "Ref": "PrivateSubnet3ARouteTable" + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnets&4AZCondition", + { + "Ref": "PrivateSubnet4ARouteTable" + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "AdditionalPrivateSubnetsCondition", + { + "Ref": "PrivateSubnet1BRouteTable" + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "AdditionalPrivateSubnetsCondition", + { + "Ref": "PrivateSubnet2BRouteTable" + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "AdditionalPrivateSubnets&3AZCondition", + { + "Ref": "PrivateSubnet3BRouteTable" + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "AdditionalPrivateSubnets&4AZCondition", + { + "Ref": "PrivateSubnet4BRouteTable" + }, + { + "Ref": "AWS::NoValue" + } + ] + } + ], + "ServiceName": { + "Fn::Sub": "com.amazonaws.${AWS::Region}.s3" + }, + "VpcId": { + "Ref": "VPC" + } + } + } + }, + "Outputs": { + "NAT1EIP": { + "Condition": "PrivateSubnetsCondition", + "Description": "NAT 1 IP address", + "Value": { + "Ref": "NAT1EIP" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-NAT1EIP" + } + } + }, + "NAT2EIP": { + "Condition": "PrivateSubnetsCondition", + "Description": "NAT 2 IP address", + "Value": { + "Ref": "NAT2EIP" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-NAT2EIP" + } + } + }, + "NAT3EIP": { + "Condition": "PrivateSubnets&3AZCondition", + "Description": "NAT 3 IP address", + "Value": { + "Ref": "NAT3EIP" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-NAT3EIP" + } + } + }, + "NAT4EIP": { + "Condition": "PrivateSubnets&4AZCondition", + "Description": "NAT 4 IP address", + "Value": { + "Ref": "NAT4EIP" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-NAT4EIP" + } + } + }, + "PrivateSubnet1ACIDR": { + "Condition": "PrivateSubnetsCondition", + "Description": "Private subnet 1A CIDR in Availability Zone 1", + "Value": { + "Ref": "PrivateSubnet1ACIDR" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet1ACIDR" + } + } + }, + "PrivateSubnet1AID": { + "Condition": "PrivateSubnetsCondition", + "Description": "Private subnet 1A ID in Availability Zone 1", + "Value": { + "Ref": "PrivateSubnet1A" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet1AID" + } + } + }, + "PrivateSubnet1BCIDR": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Description": "Private subnet 1B CIDR in Availability Zone 1", + "Value": { + "Ref": "PrivateSubnet1BCIDR" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet1BCIDR" + } + } + }, + "PrivateSubnet1BID": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Description": "Private subnet 1B ID in Availability Zone 1", + "Value": { + "Ref": "PrivateSubnet1B" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet1BID" + } + } + }, + "PrivateSubnet2ACIDR": { + "Condition": "PrivateSubnetsCondition", + "Description": "Private subnet 2A CIDR in Availability Zone 2", + "Value": { + "Ref": "PrivateSubnet2ACIDR" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet2ACIDR" + } + } + }, + "PrivateSubnet2AID": { + "Condition": "PrivateSubnetsCondition", + "Description": "Private subnet 2A ID in Availability Zone 2", + "Value": { + "Ref": "PrivateSubnet2A" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet2AID" + } + } + }, + "PrivateSubnet2BCIDR": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Description": "Private subnet 2B CIDR in Availability Zone 2", + "Value": { + "Ref": "PrivateSubnet2BCIDR" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet2BCIDR" + } + } + }, + "PrivateSubnet2BID": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Description": "Private subnet 2B ID in Availability Zone 2", + "Value": { + "Ref": "PrivateSubnet2B" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet2BID" + } + } + }, + "PrivateSubnet3ACIDR": { + "Condition": "PrivateSubnets&3AZCondition", + "Description": "Private subnet 3A CIDR in Availability Zone 3", + "Value": { + "Ref": "PrivateSubnet3ACIDR" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet3ACIDR" + } + } + }, + "PrivateSubnet3AID": { + "Condition": "PrivateSubnets&3AZCondition", + "Description": "Private subnet 3A ID in Availability Zone 3", + "Value": { + "Ref": "PrivateSubnet3A" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet3AID" + } + } + }, + "PrivateSubnet3BCIDR": { + "Condition": "AdditionalPrivateSubnets&3AZCondition", + "Description": "Private subnet 3B CIDR in Availability Zone 3", + "Value": { + "Ref": "PrivateSubnet3BCIDR" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet3BCIDR" + } + } + }, + "PrivateSubnet3BID": { + "Condition": "AdditionalPrivateSubnets&3AZCondition", + "Description": "Private subnet 3B ID in Availability Zone 3", + "Value": { + "Ref": "PrivateSubnet3B" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet3BID" + } + } + }, + "PrivateSubnet4ACIDR": { + "Condition": "PrivateSubnets&4AZCondition", + "Description": "Private subnet 4A CIDR in Availability Zone 4", + "Value": { + "Ref": "PrivateSubnet4ACIDR" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet4ACIDR" + } + } + }, + "PrivateSubnet4AID": { + "Condition": "PrivateSubnets&4AZCondition", + "Description": "Private subnet 4A ID in Availability Zone 4", + "Value": { + "Ref": "PrivateSubnet4A" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet4AID" + } + } + }, + "PrivateSubnet4BCIDR": { + "Condition": "AdditionalPrivateSubnets&4AZCondition", + "Description": "Private subnet 4B CIDR in Availability Zone 4", + "Value": { + "Ref": "PrivateSubnet4BCIDR" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet4BCIDR" + } + } + }, + "PrivateSubnet4BID": { + "Condition": "AdditionalPrivateSubnets&4AZCondition", + "Description": "Private subnet 4B ID in Availability Zone 4", + "Value": { + "Ref": "PrivateSubnet4B" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet4BID" + } + } + }, + "PublicSubnet1CIDR": { + "Description": "Public subnet 1 CIDR in Availability Zone 1", + "Value": { + "Ref": "PublicSubnet1CIDR" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PublicSubnet1CIDR" + } + } + }, + "PublicSubnet1ID": { + "Description": "Public subnet 1 ID in Availability Zone 1", + "Value": { + "Ref": "PublicSubnet1" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PublicSubnet1ID" + } + } + }, + "PublicSubnet2CIDR": { + "Description": "Public subnet 2 CIDR in Availability Zone 2", + "Value": { + "Ref": "PublicSubnet2CIDR" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PublicSubnet2CIDR" + } + } + }, + "PublicSubnet2ID": { + "Description": "Public subnet 2 ID in Availability Zone 2", + "Value": { + "Ref": "PublicSubnet2" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PublicSubnet2ID" + } + } + }, + "PublicSubnet3CIDR": { + "Condition": "3AZCondition", + "Description": "Public subnet 3 CIDR in Availability Zone 3", + "Value": { + "Ref": "PublicSubnet3CIDR" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PublicSubnet3CIDR" + } + } + }, + "PublicSubnet3ID": { + "Condition": "3AZCondition", + "Description": "Public subnet 3 ID in Availability Zone 3", + "Value": { + "Ref": "PublicSubnet3" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PublicSubnet3ID" + } + } + }, + "PublicSubnet4CIDR": { + "Condition": "4AZCondition", + "Description": "Public subnet 4 CIDR in Availability Zone 4", + "Value": { + "Ref": "PublicSubnet4CIDR" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PublicSubnet4CIDR" + } + } + }, + "PublicSubnet4ID": { + "Condition": "4AZCondition", + "Description": "Public subnet 4 ID in Availability Zone 4", + "Value": { + "Ref": "PublicSubnet4" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PublicSubnet4ID" + } + } + }, + "S3VPCEndpoint": { + "Condition": "PrivateSubnetsCondition", + "Description": "S3 VPC Endpoint", + "Value": { + "Ref": "S3VPCEndpoint" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-S3VPCEndpoint" + } + } + }, + "PrivateSubnet1ARouteTable": { + "Condition": "PrivateSubnetsCondition", + "Value": { + "Ref": "PrivateSubnet1ARouteTable" + }, + "Description": "Private subnet 1A route table", + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet1ARouteTable" + } + } + }, + "PrivateSubnet1BRouteTable": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Value": { + "Ref": "PrivateSubnet1BRouteTable" + }, + "Description": "Private subnet 1B route table", + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet1BRouteTable" + } + } + }, + "PrivateSubnet2ARouteTable": { + "Condition": "PrivateSubnetsCondition", + "Value": { + "Ref": "PrivateSubnet2ARouteTable" + }, + "Description": "Private subnet 2A route table", + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet2ARouteTable" + } + } + }, + "PrivateSubnet2BRouteTable": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Value": { + "Ref": "PrivateSubnet2BRouteTable" + }, + "Description": "Private subnet 2B route table", + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet2BRouteTable" + } + } + }, + "PrivateSubnet3ARouteTable": { + "Condition": "PrivateSubnets&3AZCondition", + "Value": { + "Ref": "PrivateSubnet3ARouteTable" + }, + "Description": "Private subnet 3A route table", + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet3ARouteTable" + } + } + }, + "PrivateSubnet3BRouteTable": { + "Condition": "AdditionalPrivateSubnets&3AZCondition", + "Value": { + "Ref": "PrivateSubnet3BRouteTable" + }, + "Description": "Private subnet 3B route table", + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet3BRouteTable" + } + } + }, + "PrivateSubnet4ARouteTable": { + "Condition": "PrivateSubnets&4AZCondition", + "Value": { + "Ref": "PrivateSubnet4ARouteTable" + }, + "Description": "Private subnet 4A route table", + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet4ARouteTable" + } + } + }, + "PrivateSubnet4BRouteTable": { + "Condition": "AdditionalPrivateSubnets&4AZCondition", + "Value": { + "Ref": "PrivateSubnet4BRouteTable" + }, + "Description": "Private subnet 4B route table", + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet4BRouteTable" + } + } + }, + "PublicSubnetRouteTable": { + "Value": { + "Ref": "PublicSubnetRouteTable" + }, + "Description": "Public subnet route table", + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PublicSubnetRouteTable" + } + } + }, + "VPCCIDR": { + "Value": { + "Ref": "VPCCIDR" + }, + "Description": "VPC CIDR", + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-VPCCIDR" + } + } + }, + "VPCID": { + "Value": { + "Ref": "VPC" + }, + "Description": "VPC ID", + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-VPCID" + } + } + } + } +} diff --git a/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/templates/aws-vpc.template.yaml b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/templates/aws-vpc.template.yaml new file mode 100644 index 0000000..f1292d8 --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-aws-vpc/templates/aws-vpc.template.yaml @@ -0,0 +1,1809 @@ +AWSTemplateFormatVersion: '2010-09-09' +Description: >- + This template creates a Multi-AZ, multi-subnet VPC infrastructure with managed NAT + gateways in the public subnet for each Availability Zone. You can also create additional + private subnets with dedicated custom network access control lists (ACLs). If you + deploy the Quick Start in a region that doesn't support NAT gateways, NAT instances + are deployed instead. **WARNING** This template creates AWS resources. You will + be billed for the AWS resources used if you create a stack from this template. (qs-1qnnspaap) +Metadata: + QuickStartDocumentation: + EntrypointName: "Launch a New VPC" + OptionalParameters: + - PrivateSubnetATag1 + - PrivateSubnetATag2 + - PrivateSubnetATag3 + - PrivateSubnetBTag1 + - PrivateSubnetBTag2 + - PrivateSubnetBTag3 + - PublicSubnetTag1 + - PublicSubnetTag2 + - PublicSubnetTag3 + AWS::CloudFormation::Interface: + ParameterGroups: + - Label: + default: Availability Zone Configuration + Parameters: + - AvailabilityZones + - NumberOfAZs + - Label: + default: Network Configuration + Parameters: + - VPCCIDR + - CreatePublicSubnets + - PublicSubnet1CIDR + - PublicSubnet2CIDR + - PublicSubnet3CIDR + - PublicSubnet4CIDR + - PublicSubnetTag1 + - PublicSubnetTag2 + - PublicSubnetTag3 + - CreatePrivateSubnets + - CreateNATGateways + - PrivateSubnet1ACIDR + - PrivateSubnet2ACIDR + - PrivateSubnet3ACIDR + - PrivateSubnet4ACIDR + - PrivateSubnetATag1 + - PrivateSubnetATag2 + - PrivateSubnetATag3 + - CreateAdditionalPrivateSubnets + - PrivateSubnet1BCIDR + - PrivateSubnet2BCIDR + - PrivateSubnet3BCIDR + - PrivateSubnet4BCIDR + - PrivateSubnetBTag1 + - PrivateSubnetBTag2 + - PrivateSubnetBTag3 + - VPCTenancy + - Label: + default: 'Deprecated: NAT Instance Configuration' + Parameters: + - KeyPairName + - NATInstanceType + ParameterLabels: + AvailabilityZones: + default: Availability Zones + CreateAdditionalPrivateSubnets: + default: Create additional private subnets with dedicated network ACLs + CreateNATGateways: + default: Create NAT Gateways + CreatePublicSubnets: + default: Create public subnets + CreatePrivateSubnets: + default: Create private subnets + KeyPairName: + default: 'Deprecated: Key pair name' + NATInstanceType: + default: 'Deprecated: NAT instance type' + NumberOfAZs: + default: Number of Availability Zones + PrivateSubnet1ACIDR: + default: Private subnet 1A CIDR + PrivateSubnet1BCIDR: + default: Private subnet 1B with dedicated network ACL CIDR + PrivateSubnet2ACIDR: + default: Private subnet 2A CIDR + PrivateSubnet2BCIDR: + default: Private subnet 2B with dedicated network ACL CIDR + PrivateSubnet3ACIDR: + default: Private subnet 3A CIDR + PrivateSubnet3BCIDR: + default: Private subnet 3B with dedicated network ACL CIDR + PrivateSubnet4ACIDR: + default: Private subnet 4A CIDR + PrivateSubnet4BCIDR: + default: Private subnet 4B with dedicated network ACL CIDR + PrivateSubnetATag1: + default: Tag for Private A Subnets + PrivateSubnetATag2: + default: Tag for Private A Subnets + PrivateSubnetATag3: + default: Tag for Private A Subnets + PrivateSubnetBTag1: + default: Tag for Private B Subnets + PrivateSubnetBTag2: + default: Tag for Private B Subnets + PrivateSubnetBTag3: + default: Tag for Private B Subnets + PublicSubnet1CIDR: + default: Public subnet 1 CIDR + PublicSubnet2CIDR: + default: Public subnet 2 CIDR + PublicSubnet3CIDR: + default: Public subnet 3 CIDR + PublicSubnet4CIDR: + default: Public subnet 4 CIDR + PublicSubnetTag1: + default: Tag for Public Subnets + PublicSubnetTag2: + default: Tag for Public Subnets + PublicSubnetTag3: + default: Tag for Public Subnets + VPCCIDR: + default: VPC CIDR + VPCTenancy: + default: VPC Tenancy +Parameters: + AvailabilityZones: + Description: 'List of Availability Zones to use for the subnets in the VPC. Note: + The logical order is preserved.' + Type: List + CreateAdditionalPrivateSubnets: + AllowedValues: + - 'true' + - 'false' + Default: 'false' + Description: >- + Set to true to create a network ACL protected subnet in each Availability Zone. + If false, the CIDR parameters for those subnets will be ignored. If true, it + also requires that the 'Create private subnets' parameter is also true to have + any effect. + Type: String + CreateNATGateways: + AllowedValues: + - 'true' + - 'false' + Default: 'true' + Description: Set to false when creating only private subnets. If True, both CreatePublicSubnets and CreatePrivateSubnets must also be true. + Type: String + CreatePublicSubnets: + AllowedValues: + - 'true' + - 'false' + Default: 'true' + Description: Set to false to create only private subnets. If false, CreatePrivateSubnets must be True and the CIDR parameters for ALL public subnets will be ignored + Type: String + CreatePrivateSubnets: + AllowedValues: + - 'true' + - 'false' + Default: 'true' + Description: Set to false to create only public subnets. If false, the CIDR parameters + for ALL private subnets will be ignored. + Type: String + KeyPairName: + Description: Deprecated. NAT gateways are now supported in all regions. + Type: String + Default: deprecated + NATInstanceType: + Default: deprecated + Description: Deprecated. NAT gateways are now supported in all regions. + Type: String + NumberOfAZs: + AllowedValues: + - '2' + - '3' + - '4' + Default: '2' + Description: Number of Availability Zones to use in the VPC. This must match your + selections in the list of Availability Zones parameter. + Type: String + PrivateSubnet1ACIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.0.0/19 + Description: CIDR block for private subnet 1A located in Availability Zone 1 + Type: String + PrivateSubnet1BCIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.192.0/21 + Description: CIDR block for private subnet 1B with dedicated network ACL located + in Availability Zone 1 + Type: String + PrivateSubnet2ACIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.32.0/19 + Description: CIDR block for private subnet 2A located in Availability Zone 2 + Type: String + PrivateSubnet2BCIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.200.0/21 + Description: CIDR block for private subnet 2B with dedicated network ACL located + in Availability Zone 2 + Type: String + PrivateSubnet3ACIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.64.0/19 + Description: CIDR block for private subnet 3A located in Availability Zone 3 + Type: String + PrivateSubnet3BCIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.208.0/21 + Description: CIDR block for private subnet 3B with dedicated network ACL located + in Availability Zone 3 + Type: String + PrivateSubnet4ACIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.96.0/19 + Description: CIDR block for private subnet 4A located in Availability Zone 4 + Type: String + PrivateSubnet4BCIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.216.0/21 + Description: CIDR block for private subnet 4B with dedicated network ACL located + in Availability Zone 4 + Type: String + PrivateSubnetATag1: + AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ + ConstraintDescription: tags must be in format "Key=Value" keys can only contain + [a-zA-Z0-9+\-._:/@], values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}] + Default: Network=Private + Description: tag to add to private subnets A, in format Key=Value (Optional) + Type: String + PrivateSubnetATag2: + AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ + ConstraintDescription: tags must be in format "Key=Value" keys can only contain + [a-zA-Z0-9+\-._:/@], values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}] + Default: '' + Description: tag to add to private subnets A, in format Key=Value (Optional) + Type: String + PrivateSubnetATag3: + AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ + ConstraintDescription: tags must be in format "Key=Value" keys can only contain + [a-zA-Z0-9+\-._:/@], values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}] + Default: '' + Description: tag to add to private subnets A, in format Key=Value (Optional) + Type: String + PrivateSubnetBTag1: + AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ + ConstraintDescription: tags must be in format "Key=Value" keys can only contain + [a-zA-Z0-9+\-._:/@], values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}] + Default: Network=Private + Description: tag to add to private subnets B, in format Key=Value (Optional) + Type: String + PrivateSubnetBTag2: + AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ + ConstraintDescription: tags must be in format "Key=Value" keys can only contain + [a-zA-Z0-9+\-._:/@], values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}] + Default: '' + Description: tag to add to private subnets B, in format Key=Value (Optional) + Type: String + PrivateSubnetBTag3: + AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ + ConstraintDescription: tags must be in format "Key=Value" keys can only contain + [a-zA-Z0-9+\-._:/@], values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}] + Default: '' + Description: tag to add to private subnets B, in format Key=Value (Optional) + Type: String + PublicSubnet1CIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.128.0/20 + Description: CIDR block for the public DMZ subnet 1 located in Availability Zone + 1 + Type: String + PublicSubnet2CIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.144.0/20 + Description: CIDR block for the public DMZ subnet 2 located in Availability Zone + 2 + Type: String + PublicSubnet3CIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.160.0/20 + Description: CIDR block for the public DMZ subnet 3 located in Availability Zone + 3 + Type: String + PublicSubnet4CIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.176.0/20 + Description: CIDR block for the public DMZ subnet 4 located in Availability Zone + 4 + Type: String + PublicSubnetTag1: + AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ + ConstraintDescription: tags must be in format "Key=Value" keys can only contain + [a-zA-Z0-9+\-._:/@], values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}] + Default: Network=Public + Description: tag to add to public subnets, in format Key=Value (Optional) + Type: String + PublicSubnetTag2: + AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ + ConstraintDescription: tags must be in format "Key=Value" keys can only contain + [a-zA-Z0-9+\-._:/@], values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}] + Default: '' + Description: tag to add to public subnets, in format Key=Value (Optional) + Type: String + PublicSubnetTag3: + AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ + ConstraintDescription: tags must be in format "Key=Value" keys can only contain + [a-zA-Z0-9+\-._:/@], values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}] + Default: '' + Description: tag to add to public subnets, in format Key=Value (Optional) + Type: String + VPCCIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.0.0/16 + Description: CIDR block for the VPC + Type: String + VPCTenancy: + AllowedValues: + - default + - dedicated + Default: default + Description: The allowed tenancy of instances launched into the VPC + Type: String +Rules: + NAT: + RuleCondition: !Equals [!Ref CreateNATGateways, 'true'] + Assertions: + - Assert: !And + - !Equals [!Ref CreatePrivateSubnets, 'true'] + - !Equals [!Ref CreatePublicSubnets, 'true'] + AssertDescription: To enable NAT gateways you must have both CreatePrivateSubnets and CreatePublicSubnets set to 'true' + Subnets: + Assertions: + - Assert: !Or + - !Equals [!Ref CreatePrivateSubnets, 'true'] + - !Equals [!Ref CreatePublicSubnets, 'true'] + AssertDescription: At least one of CreatePublicSubnets or CreatePrivateSubnets must be set to 'true' +Conditions: + 3AZCondition: !Or + - !Equals + - !Ref 'NumberOfAZs' + - '3' + - !Condition '4AZCondition' + 4AZCondition: !Equals + - !Ref 'NumberOfAZs' + - '4' + AdditionalPrivateSubnetsCondition: !And + - !Equals + - !Ref 'CreatePrivateSubnets' + - 'true' + - !Equals + - !Ref 'CreateAdditionalPrivateSubnets' + - 'true' + AdditionalPrivateSubnets&3AZCondition: !And + - !Condition 'AdditionalPrivateSubnetsCondition' + - !Condition '3AZCondition' + AdditionalPrivateSubnets&4AZCondition: !And + - !Condition 'AdditionalPrivateSubnetsCondition' + - !Condition '4AZCondition' + AdditionalPrivateSubnets&PublicSubnets&NatGatewaysCondition: !And + - !Condition 'AdditionalPrivateSubnetsCondition' + - !Condition 'PublicSubnetsCondition' + - !Condition 'NATGatewaysCondition' + AdditionalPrivateSubnets&PublicSubnets&NatGateways&3AZCondition: !And + - !Condition 'AdditionalPrivateSubnets&3AZCondition' + - !Condition 'PublicSubnetsCondition' + - !Condition 'NATGatewaysCondition' + AdditionalPrivateSubnets&PublicSubnets&NatGateways&4AZCondition: !And + - !Condition 'AdditionalPrivateSubnets&4AZCondition' + - !Condition 'PublicSubnetsCondition' + - !Condition 'NATGatewaysCondition' + GovCloudCondition: !Equals + - !Ref 'AWS::Region' + - us-gov-west-1 + NATGatewaysCondition: !Equals + - !Ref 'CreateNATGateways' + - 'true' + NATGateways&3AZCondition: !And + - !Condition 'NATGatewaysCondition' + - !Condition '3AZCondition' + NATGateways&4AZCondition: !And + - !Condition 'NATGatewaysCondition' + - !Condition '4AZCondition' + NVirginiaRegionCondition: !Equals + - !Ref 'AWS::Region' + - us-east-1 + PrivateSubnetsCondition: !Equals + - !Ref 'CreatePrivateSubnets' + - 'true' + PrivateSubnets&3AZCondition: !And + - !Condition 'PrivateSubnetsCondition' + - !Condition '3AZCondition' + PrivateSubnets&4AZCondition: !And + - !Condition 'PrivateSubnetsCondition' + - !Condition '4AZCondition' + PublicSubnetsCondition: !Equals + - !Ref 'CreatePublicSubnets' + - 'true' + PublicSubnets&3AZCondition: !And + - !Condition 'PublicSubnetsCondition' + - !Condition '3AZCondition' + PublicSubnets&4AZCondition: !And + - !Condition 'PublicSubnetsCondition' + - !Condition '4AZCondition' + PrivateSubnetATag1Condition: !Not + - !Equals + - !Ref 'PrivateSubnetATag1' + - '' + PrivateSubnetATag2Condition: !Not + - !Equals + - !Ref 'PrivateSubnetATag2' + - '' + PrivateSubnetATag3Condition: !Not + - !Equals + - !Ref 'PrivateSubnetATag3' + - '' + PrivateSubnetBTag1Condition: !Not + - !Equals + - !Ref 'PrivateSubnetBTag1' + - '' + PrivateSubnetBTag2Condition: !Not + - !Equals + - !Ref 'PrivateSubnetBTag2' + - '' + PrivateSubnetBTag3Condition: !Not + - !Equals + - !Ref 'PrivateSubnetBTag3' + - '' + PublicSubnetTag1Condition: !Not + - !Equals + - !Ref 'PublicSubnetTag1' + - '' + PublicSubnetTag2Condition: !Not + - !Equals + - !Ref 'PublicSubnetTag2' + - '' + PublicSubnetTag3Condition: !Not + - !Equals + - !Ref 'PublicSubnetTag3' + - '' +Resources: + DHCPOptions: + Type: AWS::EC2::DHCPOptions + Properties: + DomainName: !If + - NVirginiaRegionCondition + - ec2.internal + - !Sub '${AWS::Region}.compute.internal' + DomainNameServers: + - AmazonProvidedDNS + VPC: + Type: AWS::EC2::VPC + Properties: + CidrBlock: !Ref 'VPCCIDR' + InstanceTenancy: !Ref 'VPCTenancy' + EnableDnsSupport: true + EnableDnsHostnames: true + Tags: + - Key: Name + Value: !Ref 'AWS::StackName' + VPCDHCPOptionsAssociation: + Type: AWS::EC2::VPCDHCPOptionsAssociation + Properties: + VpcId: !Ref 'VPC' + DhcpOptionsId: !Ref 'DHCPOptions' + InternetGateway: + Condition: PublicSubnetsCondition + Type: AWS::EC2::InternetGateway + Properties: + Tags: + - Key: Name + Value: !Ref 'AWS::StackName' + VPCGatewayAttachment: + Condition: PublicSubnetsCondition + Type: AWS::EC2::VPCGatewayAttachment + Properties: + VpcId: !Ref 'VPC' + InternetGatewayId: !Ref 'InternetGateway' + PrivateSubnet1A: + Condition: PrivateSubnetsCondition + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref 'VPC' + CidrBlock: !Ref 'PrivateSubnet1ACIDR' + AvailabilityZone: !Select + - '0' + - !Ref 'AvailabilityZones' + Tags: + - Key: Name + Value: Private subnet 1A + - !If + - PrivateSubnetATag1Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetATag1' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetATag1' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetATag2Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetATag2' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetATag2' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetATag3Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetATag3' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetATag3' + - !Ref 'AWS::NoValue' + PrivateSubnet1B: + Condition: AdditionalPrivateSubnetsCondition + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref 'VPC' + CidrBlock: !Ref 'PrivateSubnet1BCIDR' + AvailabilityZone: !Select + - '0' + - !Ref 'AvailabilityZones' + Tags: + - Key: Name + Value: Private subnet 1B + - !If + - PrivateSubnetBTag1Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag1' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag1' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetBTag2Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag2' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag2' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetBTag3Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag3' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag3' + - !Ref 'AWS::NoValue' + PrivateSubnet2A: + Condition: PrivateSubnetsCondition + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref 'VPC' + CidrBlock: !Ref 'PrivateSubnet2ACIDR' + AvailabilityZone: !Select + - '1' + - !Ref 'AvailabilityZones' + Tags: + - Key: Name + Value: Private subnet 2A + - !If + - PrivateSubnetATag1Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetATag1' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetATag1' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetATag2Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetATag2' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetATag2' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetATag3Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetATag3' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetATag3' + - !Ref 'AWS::NoValue' + PrivateSubnet2B: + Condition: AdditionalPrivateSubnetsCondition + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref 'VPC' + CidrBlock: !Ref 'PrivateSubnet2BCIDR' + AvailabilityZone: !Select + - '1' + - !Ref 'AvailabilityZones' + Tags: + - Key: Name + Value: Private subnet 2B + - !If + - PrivateSubnetBTag1Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag1' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag1' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetBTag2Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag2' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag2' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetBTag3Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag3' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag3' + - !Ref 'AWS::NoValue' + PrivateSubnet3A: + Condition: PrivateSubnets&3AZCondition + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref 'VPC' + CidrBlock: !Ref 'PrivateSubnet3ACIDR' + AvailabilityZone: !Select + - '2' + - !Ref 'AvailabilityZones' + Tags: + - Key: Name + Value: Private subnet 3A + - !If + - PrivateSubnetATag1Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetATag1' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetATag1' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetATag2Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetATag2' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetATag2' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetATag3Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetATag3' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetATag3' + - !Ref 'AWS::NoValue' + PrivateSubnet3B: + Condition: AdditionalPrivateSubnets&3AZCondition + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref 'VPC' + CidrBlock: !Ref 'PrivateSubnet3BCIDR' + AvailabilityZone: !Select + - '2' + - !Ref 'AvailabilityZones' + Tags: + - Key: Name + Value: Private subnet 3B + - !If + - PrivateSubnetBTag1Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag1' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag1' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetBTag2Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag2' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag2' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetBTag3Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag3' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag3' + - !Ref 'AWS::NoValue' + PrivateSubnet4A: + Condition: PrivateSubnets&4AZCondition + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref 'VPC' + CidrBlock: !Ref 'PrivateSubnet4ACIDR' + AvailabilityZone: !Select + - '3' + - !Ref 'AvailabilityZones' + Tags: + - Key: Name + Value: Private subnet 4A + - !If + - PrivateSubnetATag1Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetATag1' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetATag1' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetATag2Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetATag2' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetATag2' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetATag3Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetATag3' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetATag3' + - !Ref 'AWS::NoValue' + PrivateSubnet4B: + Condition: AdditionalPrivateSubnets&4AZCondition + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref 'VPC' + CidrBlock: !Ref 'PrivateSubnet4BCIDR' + AvailabilityZone: !Select + - '3' + - !Ref 'AvailabilityZones' + Tags: + - Key: Name + Value: Private subnet 4B + - !If + - PrivateSubnetBTag1Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag1' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag1' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetBTag2Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag2' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag2' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetBTag3Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag3' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag3' + - !Ref 'AWS::NoValue' + PublicSubnet1: + Condition: PublicSubnetsCondition + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref 'VPC' + CidrBlock: !Ref 'PublicSubnet1CIDR' + AvailabilityZone: !Select + - '0' + - !Ref 'AvailabilityZones' + Tags: + - Key: Name + Value: Public subnet 1 + - !If + - PublicSubnetTag1Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PublicSubnetTag1' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PublicSubnetTag1' + - !Ref 'AWS::NoValue' + - !If + - PublicSubnetTag2Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PublicSubnetTag2' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PublicSubnetTag2' + - !Ref 'AWS::NoValue' + - !If + - PublicSubnetTag3Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PublicSubnetTag3' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PublicSubnetTag3' + - !Ref 'AWS::NoValue' + MapPublicIpOnLaunch: true + PublicSubnet2: + Condition: PublicSubnetsCondition + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref 'VPC' + CidrBlock: !Ref 'PublicSubnet2CIDR' + AvailabilityZone: !Select + - '1' + - !Ref 'AvailabilityZones' + Tags: + - Key: Name + Value: Public subnet 2 + - !If + - PublicSubnetTag1Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PublicSubnetTag1' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PublicSubnetTag1' + - !Ref 'AWS::NoValue' + - !If + - PublicSubnetTag2Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PublicSubnetTag2' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PublicSubnetTag2' + - !Ref 'AWS::NoValue' + - !If + - PublicSubnetTag3Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PublicSubnetTag3' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PublicSubnetTag3' + - !Ref 'AWS::NoValue' + MapPublicIpOnLaunch: true + PublicSubnet3: + Condition: PublicSubnets&3AZCondition + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref 'VPC' + CidrBlock: !Ref 'PublicSubnet3CIDR' + AvailabilityZone: !Select + - '2' + - !Ref 'AvailabilityZones' + Tags: + - Key: Name + Value: Public subnet 3 + - !If + - PublicSubnetTag1Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PublicSubnetTag1' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PublicSubnetTag1' + - !Ref 'AWS::NoValue' + - !If + - PublicSubnetTag2Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PublicSubnetTag2' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PublicSubnetTag2' + - !Ref 'AWS::NoValue' + - !If + - PublicSubnetTag3Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PublicSubnetTag3' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PublicSubnetTag3' + - !Ref 'AWS::NoValue' + MapPublicIpOnLaunch: true + PublicSubnet4: + Condition: PublicSubnets&4AZCondition + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref 'VPC' + CidrBlock: !Ref 'PublicSubnet4CIDR' + AvailabilityZone: !Select + - '3' + - !Ref 'AvailabilityZones' + Tags: + - Key: Name + Value: Public subnet 4 + - !If + - PublicSubnetTag1Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PublicSubnetTag1' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PublicSubnetTag1' + - !Ref 'AWS::NoValue' + - !If + - PublicSubnetTag2Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PublicSubnetTag2' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PublicSubnetTag2' + - !Ref 'AWS::NoValue' + - !If + - PublicSubnetTag3Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PublicSubnetTag3' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PublicSubnetTag3' + - !Ref 'AWS::NoValue' + MapPublicIpOnLaunch: true + PrivateSubnet1ARouteTable: + Condition: PrivateSubnetsCondition + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref 'VPC' + Tags: + - Key: Name + Value: Private subnet 1A + - Key: Network + Value: Private + PrivateSubnet1ARoute: + Condition: NATGatewaysCondition + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref 'PrivateSubnet1ARouteTable' + DestinationCidrBlock: '0.0.0.0/0' + NatGatewayId: !Ref 'NATGateway1' + PrivateSubnet1ARouteTableAssociation: + Condition: PrivateSubnetsCondition + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref 'PrivateSubnet1A' + RouteTableId: !Ref 'PrivateSubnet1ARouteTable' + PrivateSubnet2ARouteTable: + Condition: PrivateSubnetsCondition + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref 'VPC' + Tags: + - Key: Name + Value: Private subnet 2A + - Key: Network + Value: Private + PrivateSubnet2ARoute: + Condition: NATGatewaysCondition + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref 'PrivateSubnet2ARouteTable' + DestinationCidrBlock: '0.0.0.0/0' + NatGatewayId: !Ref 'NATGateway2' + PrivateSubnet2ARouteTableAssociation: + Condition: PrivateSubnetsCondition + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref 'PrivateSubnet2A' + RouteTableId: !Ref 'PrivateSubnet2ARouteTable' + PrivateSubnet3ARouteTable: + Condition: PrivateSubnets&3AZCondition + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref 'VPC' + Tags: + - Key: Name + Value: Private subnet 3A + - Key: Network + Value: Private + PrivateSubnet3ARoute: + Condition: NATGateways&3AZCondition + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref 'PrivateSubnet3ARouteTable' + DestinationCidrBlock: '0.0.0.0/0' + NatGatewayId: !Ref 'NATGateway3' + PrivateSubnet3ARouteTableAssociation: + Condition: PrivateSubnets&3AZCondition + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref 'PrivateSubnet3A' + RouteTableId: !Ref 'PrivateSubnet3ARouteTable' + PrivateSubnet4ARouteTable: + Condition: PrivateSubnets&4AZCondition + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref 'VPC' + Tags: + - Key: Name + Value: Private subnet 4A + - Key: Network + Value: Private + PrivateSubnet4ARoute: + Condition: NATGateways&4AZCondition + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref 'PrivateSubnet4ARouteTable' + DestinationCidrBlock: '0.0.0.0/0' + NatGatewayId: !Ref 'NATGateway4' + PrivateSubnet4ARouteTableAssociation: + Condition: PrivateSubnets&4AZCondition + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref 'PrivateSubnet4A' + RouteTableId: !Ref 'PrivateSubnet4ARouteTable' + PrivateSubnet1BRouteTable: + Condition: AdditionalPrivateSubnetsCondition + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref 'VPC' + Tags: + - Key: Name + Value: Private subnet 1B + - Key: Network + Value: Private + PrivateSubnet1BRoute: + Condition: AdditionalPrivateSubnets&PublicSubnets&NatGatewaysCondition + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref 'PrivateSubnet1BRouteTable' + DestinationCidrBlock: '0.0.0.0/0' + NatGatewayId: !Ref 'NATGateway1' + PrivateSubnet1BRouteTableAssociation: + Condition: AdditionalPrivateSubnetsCondition + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref 'PrivateSubnet1B' + RouteTableId: !Ref 'PrivateSubnet1BRouteTable' + PrivateSubnet1BNetworkAcl: + Condition: AdditionalPrivateSubnetsCondition + Type: AWS::EC2::NetworkAcl + Properties: + VpcId: !Ref 'VPC' + Tags: + - Key: Name + Value: NACL Protected subnet 1 + - Key: Network + Value: NACL Protected + PrivateSubnet1BNetworkAclEntryInbound: + Condition: AdditionalPrivateSubnetsCondition + Type: AWS::EC2::NetworkAclEntry + Properties: + CidrBlock: '0.0.0.0/0' + Egress: false + NetworkAclId: !Ref 'PrivateSubnet1BNetworkAcl' + Protocol: -1 + RuleAction: allow + RuleNumber: 100 + PrivateSubnet1BNetworkAclEntryOutbound: + Condition: AdditionalPrivateSubnetsCondition + Type: AWS::EC2::NetworkAclEntry + Properties: + CidrBlock: '0.0.0.0/0' + Egress: true + NetworkAclId: !Ref 'PrivateSubnet1BNetworkAcl' + Protocol: -1 + RuleAction: allow + RuleNumber: 100 + PrivateSubnet1BNetworkAclAssociation: + Condition: AdditionalPrivateSubnetsCondition + Type: AWS::EC2::SubnetNetworkAclAssociation + Properties: + SubnetId: !Ref 'PrivateSubnet1B' + NetworkAclId: !Ref 'PrivateSubnet1BNetworkAcl' + PrivateSubnet2BRouteTable: + Condition: AdditionalPrivateSubnetsCondition + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref 'VPC' + Tags: + - Key: Name + Value: Private subnet 2B + - Key: Network + Value: Private + PrivateSubnet2BRoute: + Condition: AdditionalPrivateSubnets&PublicSubnets&NatGatewaysCondition + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref 'PrivateSubnet2BRouteTable' + DestinationCidrBlock: '0.0.0.0/0' + NatGatewayId: !Ref 'NATGateway2' + PrivateSubnet2BRouteTableAssociation: + Condition: AdditionalPrivateSubnetsCondition + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref 'PrivateSubnet2B' + RouteTableId: !Ref 'PrivateSubnet2BRouteTable' + PrivateSubnet2BNetworkAcl: + Condition: AdditionalPrivateSubnetsCondition + Type: AWS::EC2::NetworkAcl + Properties: + VpcId: !Ref 'VPC' + Tags: + - Key: Name + Value: NACL Protected subnet 2 + - Key: Network + Value: NACL Protected + PrivateSubnet2BNetworkAclEntryInbound: + Condition: AdditionalPrivateSubnetsCondition + Type: AWS::EC2::NetworkAclEntry + Properties: + CidrBlock: '0.0.0.0/0' + Egress: false + NetworkAclId: !Ref 'PrivateSubnet2BNetworkAcl' + Protocol: -1 + RuleAction: allow + RuleNumber: 100 + PrivateSubnet2BNetworkAclEntryOutbound: + Condition: AdditionalPrivateSubnetsCondition + Type: AWS::EC2::NetworkAclEntry + Properties: + CidrBlock: '0.0.0.0/0' + Egress: true + NetworkAclId: !Ref 'PrivateSubnet2BNetworkAcl' + Protocol: -1 + RuleAction: allow + RuleNumber: 100 + PrivateSubnet2BNetworkAclAssociation: + Condition: AdditionalPrivateSubnetsCondition + Type: AWS::EC2::SubnetNetworkAclAssociation + Properties: + SubnetId: !Ref 'PrivateSubnet2B' + NetworkAclId: !Ref 'PrivateSubnet2BNetworkAcl' + PrivateSubnet3BRouteTable: + Condition: AdditionalPrivateSubnets&3AZCondition + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref 'VPC' + Tags: + - Key: Name + Value: Private subnet 3B + - Key: Network + Value: Private + PrivateSubnet3BRoute: + Condition: AdditionalPrivateSubnets&PublicSubnets&NatGateways&3AZCondition + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref 'PrivateSubnet3BRouteTable' + DestinationCidrBlock: '0.0.0.0/0' + NatGatewayId: !Ref 'NATGateway3' + PrivateSubnet3BRouteTableAssociation: + Condition: AdditionalPrivateSubnets&3AZCondition + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref 'PrivateSubnet3B' + RouteTableId: !Ref 'PrivateSubnet3BRouteTable' + PrivateSubnet3BNetworkAcl: + Condition: AdditionalPrivateSubnets&3AZCondition + Type: AWS::EC2::NetworkAcl + Properties: + VpcId: !Ref 'VPC' + Tags: + - Key: Name + Value: NACL Protected subnet 3 + - Key: Network + Value: NACL Protected + PrivateSubnet3BNetworkAclEntryInbound: + Condition: AdditionalPrivateSubnets&3AZCondition + Type: AWS::EC2::NetworkAclEntry + Properties: + CidrBlock: '0.0.0.0/0' + Egress: false + NetworkAclId: !Ref 'PrivateSubnet3BNetworkAcl' + Protocol: -1 + RuleAction: allow + RuleNumber: 100 + PrivateSubnet3BNetworkAclEntryOutbound: + Condition: AdditionalPrivateSubnets&3AZCondition + Type: AWS::EC2::NetworkAclEntry + Properties: + CidrBlock: '0.0.0.0/0' + Egress: true + NetworkAclId: !Ref 'PrivateSubnet3BNetworkAcl' + Protocol: -1 + RuleAction: allow + RuleNumber: 100 + PrivateSubnet3BNetworkAclAssociation: + Condition: AdditionalPrivateSubnets&3AZCondition + Type: AWS::EC2::SubnetNetworkAclAssociation + Properties: + SubnetId: !Ref 'PrivateSubnet3B' + NetworkAclId: !Ref 'PrivateSubnet3BNetworkAcl' + PrivateSubnet4BRouteTable: + Condition: AdditionalPrivateSubnets&4AZCondition + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref 'VPC' + Tags: + - Key: Name + Value: Private subnet 4B + - Key: Network + Value: Private + PrivateSubnet4BRoute: + Condition: AdditionalPrivateSubnets&PublicSubnets&NatGateways&4AZCondition + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref 'PrivateSubnet4BRouteTable' + DestinationCidrBlock: '0.0.0.0/0' + NatGatewayId: !Ref 'NATGateway4' + PrivateSubnet4BRouteTableAssociation: + Condition: AdditionalPrivateSubnets&4AZCondition + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref 'PrivateSubnet4B' + RouteTableId: !Ref 'PrivateSubnet4BRouteTable' + PrivateSubnet4BNetworkAcl: + Condition: AdditionalPrivateSubnets&4AZCondition + Type: AWS::EC2::NetworkAcl + Properties: + VpcId: !Ref 'VPC' + Tags: + - Key: Name + Value: NACL Protected subnet 4 + - Key: Network + Value: NACL Protected + PrivateSubnet4BNetworkAclEntryInbound: + Condition: AdditionalPrivateSubnets&4AZCondition + Type: AWS::EC2::NetworkAclEntry + Properties: + CidrBlock: '0.0.0.0/0' + Egress: false + NetworkAclId: !Ref 'PrivateSubnet4BNetworkAcl' + Protocol: -1 + RuleAction: allow + RuleNumber: 100 + PrivateSubnet4BNetworkAclEntryOutbound: + Condition: AdditionalPrivateSubnets&4AZCondition + Type: AWS::EC2::NetworkAclEntry + Properties: + CidrBlock: '0.0.0.0/0' + Egress: true + NetworkAclId: !Ref 'PrivateSubnet4BNetworkAcl' + Protocol: -1 + RuleAction: allow + RuleNumber: 100 + PrivateSubnet4BNetworkAclAssociation: + Condition: AdditionalPrivateSubnets&4AZCondition + Type: AWS::EC2::SubnetNetworkAclAssociation + Properties: + SubnetId: !Ref 'PrivateSubnet4B' + NetworkAclId: !Ref 'PrivateSubnet4BNetworkAcl' + PublicSubnetRouteTable: + Condition: PublicSubnetsCondition + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref 'VPC' + Tags: + - Key: Name + Value: Public Subnets + - Key: Network + Value: Public + PublicSubnetRoute: + Condition: PublicSubnetsCondition + DependsOn: VPCGatewayAttachment + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref 'PublicSubnetRouteTable' + DestinationCidrBlock: '0.0.0.0/0' + GatewayId: !Ref 'InternetGateway' + PublicSubnet1RouteTableAssociation: + Condition: PublicSubnetsCondition + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref 'PublicSubnet1' + RouteTableId: !Ref 'PublicSubnetRouteTable' + PublicSubnet2RouteTableAssociation: + Condition: PublicSubnetsCondition + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref 'PublicSubnet2' + RouteTableId: !Ref 'PublicSubnetRouteTable' + PublicSubnet3RouteTableAssociation: + Condition: PublicSubnets&3AZCondition + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref 'PublicSubnet3' + RouteTableId: !Ref 'PublicSubnetRouteTable' + PublicSubnet4RouteTableAssociation: + Condition: PublicSubnets&4AZCondition + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref 'PublicSubnet4' + RouteTableId: !Ref 'PublicSubnetRouteTable' + NAT1EIP: + Condition: NATGatewaysCondition + DependsOn: VPCGatewayAttachment + Type: AWS::EC2::EIP + Properties: + Domain: vpc + NAT2EIP: + Condition: NATGatewaysCondition + DependsOn: VPCGatewayAttachment + Type: AWS::EC2::EIP + Properties: + Domain: vpc + NAT3EIP: + Condition: NATGateways&3AZCondition + DependsOn: VPCGatewayAttachment + Type: AWS::EC2::EIP + Properties: + Domain: vpc + NAT4EIP: + Condition: NATGateways&4AZCondition + DependsOn: VPCGatewayAttachment + Type: AWS::EC2::EIP + Properties: + Domain: vpc + NATGateway1: + Condition: NATGatewaysCondition + DependsOn: VPCGatewayAttachment + Type: AWS::EC2::NatGateway + Properties: + AllocationId: !GetAtt 'NAT1EIP.AllocationId' + SubnetId: !Ref 'PublicSubnet1' + NATGateway2: + Condition: NATGatewaysCondition + DependsOn: VPCGatewayAttachment + Type: AWS::EC2::NatGateway + Properties: + AllocationId: !GetAtt 'NAT2EIP.AllocationId' + SubnetId: !Ref 'PublicSubnet2' + NATGateway3: + Condition: NATGateways&3AZCondition + DependsOn: VPCGatewayAttachment + Type: AWS::EC2::NatGateway + Properties: + AllocationId: !GetAtt 'NAT3EIP.AllocationId' + SubnetId: !Ref 'PublicSubnet3' + NATGateway4: + Condition: NATGateways&4AZCondition + DependsOn: VPCGatewayAttachment + Type: AWS::EC2::NatGateway + Properties: + AllocationId: !GetAtt 'NAT4EIP.AllocationId' + SubnetId: !Ref 'PublicSubnet4' + S3VPCEndpoint: + Condition: PrivateSubnetsCondition + Type: AWS::EC2::VPCEndpoint + Properties: + PolicyDocument: + Version: '2012-10-17' + Statement: + - Action: '*' + Effect: Allow + Resource: '*' + Principal: '*' + RouteTableIds: + - !Ref 'PrivateSubnet1ARouteTable' + - !Ref 'PrivateSubnet2ARouteTable' + - !If + - PrivateSubnets&3AZCondition + - !Ref 'PrivateSubnet3ARouteTable' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnets&4AZCondition + - !Ref 'PrivateSubnet4ARouteTable' + - !Ref 'AWS::NoValue' + - !If + - AdditionalPrivateSubnetsCondition + - !Ref 'PrivateSubnet1BRouteTable' + - !Ref 'AWS::NoValue' + - !If + - AdditionalPrivateSubnetsCondition + - !Ref 'PrivateSubnet2BRouteTable' + - !Ref 'AWS::NoValue' + - !If + - AdditionalPrivateSubnets&3AZCondition + - !Ref 'PrivateSubnet3BRouteTable' + - !Ref 'AWS::NoValue' + - !If + - AdditionalPrivateSubnets&4AZCondition + - !Ref 'PrivateSubnet4BRouteTable' + - !Ref 'AWS::NoValue' + ServiceName: !Sub 'com.amazonaws.${AWS::Region}.s3' + VpcId: !Ref 'VPC' +Outputs: + NAT1EIP: + Condition: NATGatewaysCondition + Description: NAT 1 IP address + Value: !Ref 'NAT1EIP' + Export: + Name: !Sub '${AWS::StackName}-NAT1EIP' + NAT2EIP: + Condition: NATGatewaysCondition + Description: NAT 2 IP address + Value: !Ref 'NAT2EIP' + Export: + Name: !Sub '${AWS::StackName}-NAT2EIP' + NAT3EIP: + Condition: NATGateways&3AZCondition + Description: NAT 3 IP address + Value: !Ref 'NAT3EIP' + Export: + Name: !Sub '${AWS::StackName}-NAT3EIP' + NAT4EIP: + Condition: NATGateways&4AZCondition + Description: NAT 4 IP address + Value: !Ref 'NAT4EIP' + Export: + Name: !Sub '${AWS::StackName}-NAT4EIP' + PrivateSubnet1ACIDR: + Condition: PrivateSubnetsCondition + Description: Private subnet 1A CIDR in Availability Zone 1 + Value: !Ref 'PrivateSubnet1ACIDR' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet1ACIDR' + PrivateSubnet1AID: + Condition: PrivateSubnetsCondition + Description: Private subnet 1A ID in Availability Zone 1 + Value: !Ref 'PrivateSubnet1A' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet1AID' + PrivateSubnet1BCIDR: + Condition: AdditionalPrivateSubnetsCondition + Description: Private subnet 1B CIDR in Availability Zone 1 + Value: !Ref 'PrivateSubnet1BCIDR' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet1BCIDR' + PrivateSubnet1BID: + Condition: AdditionalPrivateSubnetsCondition + Description: Private subnet 1B ID in Availability Zone 1 + Value: !Ref 'PrivateSubnet1B' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet1BID' + PrivateSubnet2ACIDR: + Condition: PrivateSubnetsCondition + Description: Private subnet 2A CIDR in Availability Zone 2 + Value: !Ref 'PrivateSubnet2ACIDR' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet2ACIDR' + PrivateSubnet2AID: + Condition: PrivateSubnetsCondition + Description: Private subnet 2A ID in Availability Zone 2 + Value: !Ref 'PrivateSubnet2A' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet2AID' + PrivateSubnet2BCIDR: + Condition: AdditionalPrivateSubnetsCondition + Description: Private subnet 2B CIDR in Availability Zone 2 + Value: !Ref 'PrivateSubnet2BCIDR' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet2BCIDR' + PrivateSubnet2BID: + Condition: AdditionalPrivateSubnetsCondition + Description: Private subnet 2B ID in Availability Zone 2 + Value: !Ref 'PrivateSubnet2B' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet2BID' + PrivateSubnet3ACIDR: + Condition: PrivateSubnets&3AZCondition + Description: Private subnet 3A CIDR in Availability Zone 3 + Value: !Ref 'PrivateSubnet3ACIDR' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet3ACIDR' + PrivateSubnet3AID: + Condition: PrivateSubnets&3AZCondition + Description: Private subnet 3A ID in Availability Zone 3 + Value: !Ref 'PrivateSubnet3A' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet3AID' + PrivateSubnet3BCIDR: + Condition: AdditionalPrivateSubnets&3AZCondition + Description: Private subnet 3B CIDR in Availability Zone 3 + Value: !Ref 'PrivateSubnet3BCIDR' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet3BCIDR' + PrivateSubnet3BID: + Condition: AdditionalPrivateSubnets&3AZCondition + Description: Private subnet 3B ID in Availability Zone 3 + Value: !Ref 'PrivateSubnet3B' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet3BID' + PrivateSubnet4ACIDR: + Condition: PrivateSubnets&4AZCondition + Description: Private subnet 4A CIDR in Availability Zone 4 + Value: !Ref 'PrivateSubnet4ACIDR' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet4ACIDR' + PrivateSubnet4AID: + Condition: PrivateSubnets&4AZCondition + Description: Private subnet 4A ID in Availability Zone 4 + Value: !Ref 'PrivateSubnet4A' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet4AID' + PrivateSubnet4BCIDR: + Condition: AdditionalPrivateSubnets&4AZCondition + Description: Private subnet 4B CIDR in Availability Zone 4 + Value: !Ref 'PrivateSubnet4BCIDR' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet4BCIDR' + PrivateSubnet4BID: + Condition: AdditionalPrivateSubnets&4AZCondition + Description: Private subnet 4B ID in Availability Zone 4 + Value: !Ref 'PrivateSubnet4B' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet4BID' + PublicSubnet1CIDR: + Condition: PublicSubnetsCondition + Description: Public subnet 1 CIDR in Availability Zone 1 + Value: !Ref 'PublicSubnet1CIDR' + Export: + Name: !Sub '${AWS::StackName}-PublicSubnet1CIDR' + PublicSubnet1ID: + Condition: PublicSubnetsCondition + Description: Public subnet 1 ID in Availability Zone 1 + Value: !Ref 'PublicSubnet1' + Export: + Name: !Sub '${AWS::StackName}-PublicSubnet1ID' + PublicSubnet2CIDR: + Condition: PublicSubnetsCondition + Description: Public subnet 2 CIDR in Availability Zone 2 + Value: !Ref 'PublicSubnet2CIDR' + Export: + Name: !Sub '${AWS::StackName}-PublicSubnet2CIDR' + PublicSubnet2ID: + Condition: PublicSubnetsCondition + Description: Public subnet 2 ID in Availability Zone 2 + Value: !Ref 'PublicSubnet2' + Export: + Name: !Sub '${AWS::StackName}-PublicSubnet2ID' + PublicSubnet3CIDR: + Condition: PublicSubnets&3AZCondition + Description: Public subnet 3 CIDR in Availability Zone 3 + Value: !Ref 'PublicSubnet3CIDR' + Export: + Name: !Sub '${AWS::StackName}-PublicSubnet3CIDR' + PublicSubnet3ID: + Condition: PublicSubnets&3AZCondition + Description: Public subnet 3 ID in Availability Zone 3 + Value: !Ref 'PublicSubnet3' + Export: + Name: !Sub '${AWS::StackName}-PublicSubnet3ID' + PublicSubnet4CIDR: + Condition: PublicSubnets&4AZCondition + Description: Public subnet 4 CIDR in Availability Zone 4 + Value: !Ref 'PublicSubnet4CIDR' + Export: + Name: !Sub '${AWS::StackName}-PublicSubnet4CIDR' + PublicSubnet4ID: + Condition: PublicSubnets&4AZCondition + Description: Public subnet 4 ID in Availability Zone 4 + Value: !Ref 'PublicSubnet4' + Export: + Name: !Sub '${AWS::StackName}-PublicSubnet4ID' + S3VPCEndpoint: + Condition: PrivateSubnetsCondition + Description: S3 VPC Endpoint + Value: !Ref 'S3VPCEndpoint' + Export: + Name: !Sub '${AWS::StackName}-S3VPCEndpoint' + PrivateSubnet1ARouteTable: + Condition: PrivateSubnetsCondition + Value: !Ref 'PrivateSubnet1ARouteTable' + Description: Private subnet 1A route table + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet1ARouteTable' + PrivateSubnet1BRouteTable: + Condition: AdditionalPrivateSubnetsCondition + Value: !Ref 'PrivateSubnet1BRouteTable' + Description: Private subnet 1B route table + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet1BRouteTable' + PrivateSubnet2ARouteTable: + Condition: PrivateSubnetsCondition + Value: !Ref 'PrivateSubnet2ARouteTable' + Description: Private subnet 2A route table + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet2ARouteTable' + PrivateSubnet2BRouteTable: + Condition: AdditionalPrivateSubnetsCondition + Value: !Ref 'PrivateSubnet2BRouteTable' + Description: Private subnet 2B route table + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet2BRouteTable' + PrivateSubnet3ARouteTable: + Condition: PrivateSubnets&3AZCondition + Value: !Ref 'PrivateSubnet3ARouteTable' + Description: Private subnet 3A route table + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet3ARouteTable' + PrivateSubnet3BRouteTable: + Condition: AdditionalPrivateSubnets&3AZCondition + Value: !Ref 'PrivateSubnet3BRouteTable' + Description: Private subnet 3B route table + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet3BRouteTable' + PrivateSubnet4ARouteTable: + Condition: PrivateSubnets&4AZCondition + Value: !Ref 'PrivateSubnet4ARouteTable' + Description: Private subnet 4A route table + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet4ARouteTable' + PrivateSubnet4BRouteTable: + Condition: AdditionalPrivateSubnets&4AZCondition + Value: !Ref 'PrivateSubnet4BRouteTable' + Description: Private subnet 4B route table + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet4BRouteTable' + PublicSubnetRouteTable: + Condition: PublicSubnetsCondition + Value: !Ref 'PublicSubnetRouteTable' + Description: Public subnet route table + Export: + Name: !Sub '${AWS::StackName}-PublicSubnetRouteTable' + VPCCIDR: + Value: !Ref 'VPCCIDR' + Description: VPC CIDR + Export: + Name: !Sub '${AWS::StackName}-VPCCIDR' + VPCID: + Value: !Ref 'VPC' + Description: VPC ID + Export: + Name: !Sub '${AWS::StackName}-VPCID' diff --git a/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/.gitignore b/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/.gitignore new file mode 100644 index 0000000..42e7431 --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +taskcat_outputs/* +packages/ \ No newline at end of file diff --git a/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/.gitmodules b/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/.gitmodules new file mode 100644 index 0000000..2bacf10 --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/.gitmodules @@ -0,0 +1,4 @@ +[submodule "submodules/quickstart-aws-vpc"] + path = submodules/quickstart-aws-vpc + url = https://github.com/aws-quickstart/quickstart-aws-vpc.git + branch = main diff --git a/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/.taskcat.yml b/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/.taskcat.yml new file mode 100644 index 0000000..d9a6c23 --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/.taskcat.yml @@ -0,0 +1,94 @@ +project: + name: quickstart-linux-bastion + owner: quickstart-eng@amazon.com + lambda_source_path: functions/source + lambda_zip_path: packages + s3_regional_buckets: true + regions: + - ap-northeast-1 + - ap-northeast-2 + - ap-south-1 + - ap-southeast-1 + - ap-southeast-2 + - ap-east-1 + - ca-central-1 + - eu-central-1 + - eu-west-1 + - eu-west-2 + - eu-west-3 + - me-south-1 + - sa-east-1 + - us-east-1 + - us-east-2 + - us-west-1 + - us-west-2 + - us-gov-east-1 + - us-gov-west-1 + template: templates/linux-bastion-master.template + parameters: + AvailabilityZones: $[taskcat_getaz_2] + BastionInstanceType: t3.medium + KeyPairName: $[taskcat_getkeypair] + PrivateSubnet1CIDR: 10.0.0.0/19 + PrivateSubnet2CIDR: 10.0.32.0/19 + PublicSubnet1CIDR: 10.0.128.0/20 + PublicSubnet2CIDR: 10.0.144.0/20 + QSS3BucketName: $[taskcat_autobucket] + RemoteAccessCIDR: 10.0.0.0/16 + VPCCIDR: 10.0.0.0/16 + QSS3BucketRegion: $[taskcat_current_region] +tests: + amznlinux2hvm: + parameters: + BastionAMIOS: Amazon-Linux2-HVM + regions: + - ap-northeast-1 + - ap-northeast-2 + - ap-south-1 + - ap-southeast-1 + - ap-southeast-2 + - ca-central-1 + - eu-central-1 + - eu-north-1 + - eu-west-1 + - eu-west-2 + - eu-west-3 + - sa-east-1 + - us-east-1 + - us-east-2 + - us-west-1 + - us-west-2 + - cn-north-1 + - cn-northwest-1 + - us-gov-east-1 + - us-gov-west-1 + centos7hvm: + parameters: + BastionAMIOS: CentOS-7-HVM + regions: + - ap-south-1 + - ca-central-1 + - eu-central-1 + - eu-north-1 + - eu-west-1 + - us-east-1 + sles15hvm: + parameters: + BastionAMIOS: SUSE-SLES-15-HVM + regions: + - ap-south-1 + - ca-central-1 + - eu-central-1 + - eu-north-1 + - eu-west-1 + - us-east-1 + us2004hvm: + parameters: + BastionAMIOS: Ubuntu-Server-20.04-LTS-HVM + regions: + - ap-south-1 + - ca-central-1 + - eu-central-1 + - eu-north-1 + - eu-west-1 + - us-east-1 diff --git a/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/LICENSE.txt b/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/LICENSE.txt new file mode 100644 index 0000000..8f71f43 --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/LICENSE.txt @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/NOTICE.txt b/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/NOTICE.txt new file mode 100644 index 0000000..9be841c --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/NOTICE.txt @@ -0,0 +1,7 @@ +Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with the License. A copy of the License is located at + + http://aws.amazon.com/apache2.0/ + +or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/README.md b/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/README.md new file mode 100644 index 0000000..a36ee37 --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/README.md @@ -0,0 +1,16 @@ +# quickstart-linux-bastion + +This Quick Start adds Linux bastion functionality to your AWS Cloud environment. It deploys Linux bastion hosts that provide secure access to your Linux instances in public or private subnets. Use this Quick Start as a building block for your Linux-based deployments on AWS. You can choose to create a new VPC environment for your Linux bastion hosts or deploy them into your existing VPC environment. After you deploy the Quick Start, you can add other AWS services, infrastructure components, and software layers to complete your test or production Linux environment on the AWS Cloud. + +![Quick Start Linux Bastion Design Architecture](https://docs.aws.amazon.com/quickstart/latest/linux-bastion/images/linux-bastion-hosts-on-aws-architecture.png ) + +Deployment steps: + +1. Sign up for an AWS account at https://aws.amazon.com, select a region, and create a key pair. +2. In the AWS CloudFormation console, launch one of the following templates to build a new stack: + * /templates/linux-bastion-master.template (to deploy bastion hosts into a new VPC) + * /templates/linux-bastion.template (to deploy bastion hosts into your existing VPC) +3. Add AWS services and other applications. + +The Quick Start provides parameters that you can set to customize your deployment. For architectural details, best practices, step-by-step instructions, and customization options, see the [deployment guide](https://fwd.aws/R9NRw). + diff --git a/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/scripts/auditing_configure.sh b/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/scripts/auditing_configure.sh new file mode 100644 index 0000000..2a25924 --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/scripts/auditing_configure.sh @@ -0,0 +1,32 @@ +#!/bin/bash +function install_stuff_ubuntu(){ + apt-get -y install auditd +} + +function add_the_rules(){ + cat /tmp/auditd.rules >> /etc/audit/rules.d/audit.rules + rm /tmp/auditd.rules +} + +function restart_services(){ + case "${BASTION_OS}" in + Amazon) + /usr/sbin/service auditd restart + ;; + CentOS|SUSE) + /sbin/service auditd restart + ;; + Ubuntu) + service auditd restart + ;; + esac +} + +case "${BASTION_OS}" in + Ubuntu) + install_stuff_ubuntu + ;; +esac + +add_the_rules +restart_services diff --git a/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/scripts/banner_message.txt b/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/scripts/banner_message.txt new file mode 100644 index 0000000..ad35b1b --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/scripts/banner_message.txt @@ -0,0 +1,12 @@ + +############################################################################### +# ___ ______ ___ _ _ ____ _ _ # +# / \ \ / / ___| / _ \ _ _(_) ___| | __ / ___|| |_ __ _ _ __| |_ # +# / _ \ \ /\ / /\___ \ | | | | | | | |/ __| |/ / \___ \| __/ _` | '__| __| # +# / ___ \ V V / ___) | | |_| | |_| | | (__| < ___) | || (_| | | | |_ # +# /_/ \_\_/\_/ |____/ \__\_\\__,_|_|\___|_|\_\ |____/ \__\__,_|_| \__| # +#-----------------------------------------------------------------------------# +# Authorized access only! # +# Disconnect IMMEDIATELY if you are not an authorized user!!! # +# All actions will be monitored and recorded. # +############################################################################### diff --git a/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/scripts/bastion_bootstrap.sh b/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/scripts/bastion_bootstrap.sh new file mode 100644 index 0000000..a79667d --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/scripts/bastion_bootstrap.sh @@ -0,0 +1,380 @@ +#!/bin/bash -e +# Bastion Bootstrapping +# authors: tonynv@amazon.com, sancard@amazon.com, ianhill@amazon.com +# NOTE: This requires GNU getopt. On Mac OS X and FreeBSD you must install GNU getopt and mod the checkos function so that it's supported + + +# Configuration +PROGRAM='Linux Bastion' + +##################################### Functions Definitions +function checkos () { + platform='unknown' + unamestr=`uname` + if [[ "${unamestr}" == 'Linux' ]]; then + platform='linux' + else + echo "[WARNING] This script is not supported on MacOS or FreeBSD" + exit 1 + fi + echo "${FUNCNAME[0]} Ended" +} + +function setup_environment_variables() { + REGION=$(curl -sq http://169.254.169.254/latest/meta-data/placement/availability-zone/) + #ex: us-east-1a => us-east-1 + REGION=${REGION: :-1} + + ETH0_MAC=$(/sbin/ip link show dev eth0 | /bin/egrep -o -i 'link/ether\ ([0-9a-z]{2}:){5}[0-9a-z]{2}' | /bin/sed -e 's,link/ether\ ,,g') + + _userdata_file="/var/lib/cloud/instance/user-data.txt" + + INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id) + EIP_LIST=$(grep EIP_LIST ${_userdata_file} | sed -e 's/EIP_LIST=//g' -e 's/\"//g') + + LOCAL_IP_ADDRESS=$(curl -sq 169.254.169.254/latest/meta-data/network/interfaces/macs/${ETH0_MAC}/local-ipv4s/) + + CWG=$(grep CLOUDWATCHGROUP ${_userdata_file} | sed 's/CLOUDWATCHGROUP=//g') + + + export REGION ETH0_MAC EIP_LIST CWG LOCAL_IP_ADDRESS INSTANCE_ID +} + +function verify_dependencies(){ + if [[ "a$(which aws)" == "a" ]]; then + pip install awscli + fi + echo "${FUNCNAME[0]} Ended" +} + +function usage() { + echo "$0 " + echo " " + echo "options:" + echo -e "--help \t Show options for this script" + echo -e "--banner \t Enable or Disable Bastion Message" + echo -e "--enable \t SSH Banner" + echo -e "--tcp-forwarding \t Enable or Disable TCP Forwarding" + echo -e "--x11-forwarding \t Enable or Disable X11 Forwarding" +} + +function chkstatus () { + if [[ $? -eq 0 ]] + then + echo "Script [PASS]" + else + echo "Script [FAILED]" >&2 + exit 1 + fi +} + +function osrelease () { + OS=`cat /etc/os-release | grep '^NAME=' | tr -d \" | sed 's/\n//g' | sed 's/NAME=//g'` + if [[ "${OS}" == "Ubuntu" ]]; then + echo "Ubuntu" + elif [[ "${OS}" == "Amazon Linux AMI" ]] || [[ "${OS}" == "Amazon Linux" ]]; then + echo "AMZN" + elif [[ "${OS}" == "CentOS Linux" ]]; then + echo "CentOS" + elif [[ "${OS}" == "SLES" ]]; then + echo "SLES" + else + echo "Operating System Not Found" + fi + echo "${FUNCNAME[0]} Ended" >> /var/log/cfn-init.log +} + +function setup_logs () { + + echo "${FUNCNAME[0]} Started" + URL_SUFFIX="${URL_SUFFIX:-amazonaws.com}" + + if [[ "${release}" == "SLES" ]]; then + curl "https://amazoncloudwatch-agent-${REGION}.s3.${REGION}.${URL_SUFFIX}/suse/amd64/latest/amazon-cloudwatch-agent.rpm" -O + zypper install --allow-unsigned-rpm -y ./amazon-cloudwatch-agent.rpm + rm ./amazon-cloudwatch-agent.rpm + elif [[ "${release}" == "CentOS" ]]; then + curl "https://amazoncloudwatch-agent-${REGION}.s3.${REGION}.${URL_SUFFIX}/centos/amd64/latest/amazon-cloudwatch-agent.rpm" -O + rpm -U ./amazon-cloudwatch-agent.rpm + rm ./amazon-cloudwatch-agent.rpm + elif [[ "${release}" == "Ubuntu" ]]; then + export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin + curl "https://amazoncloudwatch-agent-${REGION}.s3.${REGION}.${URL_SUFFIX}/ubuntu/amd64/latest/amazon-cloudwatch-agent.deb" -O + dpkg -i -E ./amazon-cloudwatch-agent.deb + rm ./amazon-cloudwatch-agent.deb + elif [[ "${release}" == "AMZN" ]]; then + curl "https://amazoncloudwatch-agent-${REGION}.s3.${REGION}.${URL_SUFFIX}/amazon_linux/amd64/latest/amazon-cloudwatch-agent.rpm" -O + rpm -U ./amazon-cloudwatch-agent.rpm + rm ./amazon-cloudwatch-agent.rpm + fi + + cat <> /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json +{ + "logs": { + "force_flush_interval": 5, + "logs_collected": { + "files": { + "collect_list": [ + { + "file_path": "/var/log/auditd/auditd.log", + "log_group_name": "${CWG}", + "log_stream_name": "{instance_id}", + "timestamp_format": "%Y-%m-%d %H:%M:%S", + "timezone": "UTC" + } + ] + } + } + } +} +EOF + + if [ -x /bin/systemctl ] || [ -x /usr/bin/systemctl ]; then + systemctl enable amazon-cloudwatch-agent.service + systemctl restart amazon-cloudwatch-agent.service + else + start amazon-cloudwatch-agent + fi +} + +function setup_os () { + + echo "${FUNCNAME[0]} Started" + + echo "Defaults env_keep += \"SSH_CLIENT\"" >> /etc/sudoers + + if [[ "${release}" == "Ubuntu" ]]; then + user_group="ubuntu" + elif [[ "${release}" == "CentOS" ]]; then + user_group="centos" + elif [[ "${release}" == "SLES" ]]; then + user_group="users" + else + user_group="ec2-user" + fi + + if [[ "${release}" == "CentOS" ]]; then + /sbin/restorecon -v /etc/ssh/sshd_config + systemctl restart sshd + fi + + if [[ "${release}" == "SLES" ]]; then + echo "0 0 * * * zypper patch --non-interactive" > ~/mycron + elif [[ "${release}" == "Ubuntu" ]]; then + apt-get install -y unattended-upgrades + echo "0 0 * * * unattended-upgrades -d" > ~/mycron + else + echo "0 0 * * * yum -y update --security" > ~/mycron + fi + + crontab ~/mycron + rm ~/mycron + + echo "${FUNCNAME[0]} Ended" +} + +function request_eip() { + + # Is the already-assigned Public IP an elastic IP? + _query_assigned_public_ip + + set +e + _determine_eip_assc_status ${PUBLIC_IP_ADDRESS} + set -e + + if [[ ${_eip_associated} -eq 0 ]]; then + echo "The Public IP address associated with eth0 (${PUBLIC_IP_ADDRESS}) is already an Elastic IP. Not proceeding further." + exit 1 + fi + + EIP_ARRAY=(${EIP_LIST//,/ }) + _eip_assigned_count=0 + + for eip in "${EIP_ARRAY[@]}"; do + + if [[ "${eip}" == "Null" ]]; then + echo "Detected a NULL Value, moving on." + continue + fi + + # Determine if the EIP has already been assigned. + set +e + _determine_eip_assc_status ${eip} + set -e + if [[ ${_eip_associated} -eq 0 ]]; then + echo "Elastic IP [${eip}] already has an association. Moving on." + let _eip_assigned_count+=1 + if [[ "${_eip_assigned_count}" -eq "${#EIP_ARRAY[@]}" ]]; then + echo "All of the stack EIPs have been assigned (${_eip_assigned_count}/${#EIP_ARRAY[@]}). I can't assign anything else. Exiting." + exit 1 + fi + continue + fi + + _determine_eip_allocation ${eip} + + # Attempt to assign EIP to the ENI. + set +e + aws ec2 associate-address --instance-id ${INSTANCE_ID} --allocation-id ${eip_allocation} --region ${REGION} + + rc=$? + set -e + + if [[ ${rc} -ne 0 ]]; then + + let _eip_assigned_count+=1 + continue + else + echo "The newly-assigned EIP is ${eip}. It is mapped under EIP Allocation ${eip_allocation}" + break + fi + done + echo "${FUNCNAME[0]} Ended" +} + +function _query_assigned_public_ip() { + # Note: ETH0 Only. + # - Does not distinguish between EIP and Standard IP. Need to cross-ref later. + echo "Querying the assigned public IP" + PUBLIC_IP_ADDRESS=$(curl -sq 169.254.169.254/latest/meta-data/public-ipv4/${ETH0_MAC}/public-ipv4s/) +} + +function _determine_eip_assc_status(){ + # Is the provided EIP associated? + # Also determines if an IP is an EIP. + # 0 => true + # 1 => false + echo "Determining EIP Association Status for [${1}]" + set +e + aws ec2 describe-addresses --public-ips ${1} --output text --region ${REGION} 2>/dev/null | grep -o -i eipassoc -q + rc=$? + set -e + if [[ ${rc} -eq 1 ]]; then + _eip_associated=1 + else + _eip_associated=0 + fi + +} + +function _determine_eip_allocation(){ + echo "Determining EIP Allocation for [${1}]" + resource_id_length=$(aws ec2 describe-addresses --public-ips ${1} --output text --region ${REGION} | head -n 1 | awk {'print $2'} | sed 's/.*eipalloc-//') + if [[ "${#resource_id_length}" -eq 17 ]]; then + eip_allocation=$(aws ec2 describe-addresses --public-ips ${1} --output text --region ${REGION}| egrep 'eipalloc-([a-z0-9]{17})' -o) + else + eip_allocation=$(aws ec2 describe-addresses --public-ips ${1} --output text --region ${REGION}| egrep 'eipalloc-([a-z0-9]{8})' -o) + fi +} + +function prevent_process_snooping() { + # Prevent bastion host users from viewing processes owned by other users. + mount -o remount,rw,hidepid=2 /proc + awk '!/proc/' /etc/fstab > temp && mv temp /etc/fstab + echo "proc /proc proc defaults,hidepid=2 0 0" >> /etc/fstab + echo "${FUNCNAME[0]} Ended" +} + +##################################### End Function Definitions + +# Call checkos to ensure platform is Linux +checkos +# Verify dependencies are installed. +verify_dependencies +# Assuming it is, setup environment variables. +setup_environment_variables + +## set an initial value +SSH_BANNER="LINUX BASTION" + +# Read the options from cli input +TEMP=`getopt -o h --longoptions help,banner:,enable:,tcp-forwarding:,x11-forwarding: -n $0 -- "$@"` +eval set -- "${TEMP}" + + +if [[ $# == 1 ]] ; then echo "No input provided! type ($0 --help) to see usage help" >&2 ; exit 1 ; fi + +# extract options and their arguments into variables. +while true; do + case "$1" in + -h | --help) + usage + exit 1 + ;; + --banner) + BANNER_PATH="$2"; + shift 2 + ;; + --enable) + ENABLE="$2"; + shift 2 + ;; + --tcp-forwarding) + TCP_FORWARDING="$2"; + shift 2 + ;; + --x11-forwarding) + X11_FORWARDING="$2"; + shift 2 + ;; + --) + break + ;; + *) + break + ;; + esac +done + +# BANNER CONFIGURATION +BANNER_FILE="/etc/ssh_banner" +if [[ ${ENABLE} == "true" ]];then + if [[ -z ${BANNER_PATH} ]];then + echo "BANNER_PATH is null skipping ..." + else + echo "BANNER_PATH = ${BANNER_PATH}" + echo "Creating Banner in ${BANNER_FILE}" + aws s3 cp "${BANNER_PATH}" "${BANNER_FILE}" --region ${BANNER_REGION} + if [[ -e ${BANNER_FILE} ]] ;then + echo "[INFO] Installing banner ... " + echo -e "\n Banner ${BANNER_FILE}" >>/etc/ssh/sshd_config + else + echo "[INFO] banner file is not accessible skipping ..." + exit 1; + fi + fi +else + echo "Banner message is not enabled!" +fi + +#Enable/Disable TCP forwarding +TCP_FORWARDING=`echo "${TCP_FORWARDING}" | sed 's/\\n//g'` + +#Enable/Disable X11 forwarding +X11_FORWARDING=`echo "${X11_FORWARDING}" | sed 's/\\n//g'` + +echo "Value of TCP_FORWARDING - ${TCP_FORWARDING}" +echo "Value of X11_FORWARDING - ${X11_FORWARDING}" +if [[ ${TCP_FORWARDING} == "false" ]];then + awk '!/AllowTcpForwarding/' /etc/ssh/sshd_config > temp && mv temp /etc/ssh/sshd_config + echo "AllowTcpForwarding no" >> /etc/ssh/sshd_config +fi + +if [[ ${X11_FORWARDING} == "false" ]];then + awk '!/X11Forwarding/' /etc/ssh/sshd_config > temp && mv temp /etc/ssh/sshd_config + echo "X11Forwarding no" >> /etc/ssh/sshd_config +fi + +release=$(osrelease) +if [[ "${release}" == "Operating System Not Found" ]]; then + echo "[ERROR] Unsupported Linux Bastion OS" + exit 1 +else + setup_os + setup_logs +fi + +prevent_process_snooping +request_eip + +echo "Bootstrap complete." diff --git a/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/templates/linux-bastion-master.template b/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/templates/linux-bastion-master.template new file mode 100644 index 0000000..3119956 --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/templates/linux-bastion-master.template @@ -0,0 +1,299 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: LinuxBastion+VPC Jul,30,2020 (qs-1qup6ra9p) (Please do not remove) +Metadata: + LICENSE: Apache License, Version 2.0 + 'AWS::CloudFormation::Interface': + ParameterGroups: + - Label: + default: Network configuration + Parameters: + - AvailabilityZones + - VPCCIDR + - PrivateSubnet1CIDR + - PrivateSubnet2CIDR + - PublicSubnet1CIDR + - PublicSubnet2CIDR + - RemoteAccessCIDR + - VPCTenancy + - Label: + default: Amazon EC2 configuration + Parameters: + - KeyPairName + - BastionAMIOS + - BastionInstanceType + - Label: + default: Linux bastion configuration + Parameters: + - NumBastionHosts + - BastionHostName + - BastionTenancy + - EnableBanner + - BastionBanner + - EnableTCPForwarding + - EnableX11Forwarding + - Label: + default: AWS Quick Start configuration + Parameters: + - QSS3BucketName + - QSS3KeyPrefix + - QSS3BucketRegion + ParameterLabels: + AvailabilityZones: + default: Availability Zones + BastionAMIOS: + default: Bastion AMI operating system + BastionHostName: + default: Bastion Host Name + BastionTenancy: + default: Bastion tenancy + BastionBanner: + default: Banner text + BastionInstanceType: + default: Bastion instance type + QSS3BucketRegion: + default: Quick Start S3 bucket region + EnableBanner: + default: Bastion banner + EnableTCPForwarding: + default: TCP forwarding + EnableX11Forwarding: + default: X11 forwarding + KeyPairName: + default: Key pair name + NumBastionHosts: + default: Number of bastion hosts + PrivateSubnet1CIDR: + default: Private subnet 1 CIDR + PrivateSubnet2CIDR: + default: Private subnet 2 CIDR + PublicSubnet1CIDR: + default: Public subnet 1 CIDR + PublicSubnet2CIDR: + default: Public subnet 2 CIDR + VPCTenancy: + default: VPC tenancy + QSS3BucketName: + default: Quick Start S3 bucket name + QSS3KeyPrefix: + default: Quick Start S3 key prefix + RemoteAccessCIDR: + default: Allowed bastion external access CIDR + VPCCIDR: + default: VPC CIDR + cfn-lint: { config: { ignore_checks: [E9007] } } +Parameters: + AvailabilityZones: + Description: 'List of Availability Zones to use for the subnets in the VPC. Note: ( The logical order is preserved and only 2 AZs are used for this deployment.' + Type: 'List' + BastionAMIOS: + AllowedValues: + - Amazon-Linux2-HVM + - CentOS-7-HVM + - Ubuntu-Server-20.04-LTS-HVM + - SUSE-SLES-15-HVM + Default: Amazon-Linux2-HVM + Description: The Linux distribution for the AMI to be used for the bastion instances. + Type: String + BastionHostName: + Default: 'LinuxBastion' + Description: The value used for the name tag of the bastion host + Type: String + BastionBanner: + Default: "" + Description: Banner text to display upon login. + Type: String + BastionTenancy: + Description: 'VPC tenancy to launch the bastion in. Options: ''dedicated'' or ''default''' + Type: String + Default: default + AllowedValues: + - dedicated + - default + BastionInstanceType: + Description: Amazon EC2 instance type for the bastion instances. + Type: String + Default: t2.micro + AllowedValues: + - t2.nano + - t2.micro + - t2.small + - t2.medium + - t2.large + - t3.micro + - t3.small + - t3.medium + - t3.large + - t3.xlarge + - t3.2xlarge + - m3.large + - m3.xlarge + - m3.2xlarge + - m4.large + - m4.xlarge + - m4.2xlarge + - m4.4xlarge + EnableBanner: + AllowedValues: + - 'true' + - 'false' + Default: 'false' + Description: To include a banner to be displayed when connecting via SSH to the + bastion, choose true. + Type: String + EnableTCPForwarding: + Type: String + Description: To enable TCP forwarding, choose true. + Default: 'false' + AllowedValues: + - 'true' + - 'false' + EnableX11Forwarding: + Type: String + Description: To enable X11 forwarding, choose true. + Default: 'false' + AllowedValues: + - 'true' + - 'false' + KeyPairName: + Description: 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' + NumBastionHosts: + AllowedValues: + - '1' + - '2' + - '3' + - '4' + Default: '1' + Description: The number of bastion hosts to create. The maximum number is four. + Type: String + PrivateSubnet1CIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.0.0/19 + Description: CIDR block for private subnet 1 located in Availability Zone 1. + Type: String + PrivateSubnet2CIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.32.0/19 + Description: CIDR block for private subnet 2 located in Availability Zone 2. + Type: String + PublicSubnet1CIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.128.0/20 + Description: CIDR Block for the public DMZ subnet 1 located in Availability Zone 1. + Type: String + PublicSubnet2CIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.144.0/20 + Description: CIDR Block for the public DMZ subnet 2 located in Availability Zone 2. + Type: String + VPCTenancy: + AllowedValues: + - default + - dedicated + Default: default + Description: The allowed tenancy of instances launched into the VPC. + Type: String + QSS3BucketName: + 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 + Description: S3 bucket name for the Quick Start assets. Quick Start bucket name can + include numbers, lowercase letters, uppercase letters, and hyphens (-). It + cannot start or end with a hyphen (-). + Type: String + QSS3KeyPrefix: + AllowedPattern: ^([0-9a-zA-Z-.]+/)*$ + ConstraintDescription: Quick Start key prefix can include numbers, lowercase letters, uppercase letters, hyphens (-), dots (.) and forward slash (/). The prefix should end with a forward slash (/). + Default: quickstart-linux-bastion/ + Description: S3 key prefix for the Quick Start assets. Quick Start key prefix can + include numbers, lowercase letters, uppercase letters, hyphens (-), dots + (.) and forward slash (/) and it should end with a forward slash (/). + 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 + RemoteAccessCIDR: + 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]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/x + Description: Allowed CIDR block for external SSH access to the bastions + Type: String + VPCCIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.0.0/16 + Description: CIDR Block for the VPC. + Type: String +Conditions: + UsingDefaultBucket: !Equals + - !Ref QSS3BucketName + - 'aws-quickstart' +Resources: + VPCStack: + Type: 'AWS::CloudFormation::Stack' + Properties: + TemplateURL: !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-aws-vpc/templates/aws-vpc.template + - S3Bucket: !If + - UsingDefaultBucket + - !Sub 'aws-quickstart-${AWS::Region}' + - !Ref 'QSS3BucketName' + S3Region: !If + - UsingDefaultBucket + - !Ref 'AWS::Region' + - !Ref 'QSS3BucketRegion' + Parameters: + AvailabilityZones: !Join + - ',' + - !Ref AvailabilityZones + KeyPairName: !Ref KeyPairName + NumberOfAZs: '2' + PrivateSubnet1ACIDR: !Ref PrivateSubnet1CIDR + PrivateSubnet2ACIDR: !Ref PrivateSubnet2CIDR + PublicSubnet1CIDR: !Ref PublicSubnet1CIDR + PublicSubnet2CIDR: !Ref PublicSubnet2CIDR + VPCCIDR: !Ref VPCCIDR + VPCTenancy: !Ref VPCTenancy + BastionStack: + Type: 'AWS::CloudFormation::Stack' + Properties: + TemplateURL: !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}templates/linux-bastion.template + - S3Bucket: !If + - UsingDefaultBucket + - !Sub 'aws-quickstart-${AWS::Region}' + - !Ref 'QSS3BucketName' + S3Region: !If + - UsingDefaultBucket + - !Ref 'AWS::Region' + - !Ref 'QSS3BucketRegion' + Parameters: + BastionAMIOS: !Ref BastionAMIOS + BastionHostName: !Ref BastionHostName + BastionBanner: !Ref BastionBanner + BastionInstanceType: !Ref BastionInstanceType + BastionTenancy: !Ref BastionTenancy + EnableBanner: !Ref EnableBanner + EnableTCPForwarding: !Ref EnableTCPForwarding + EnableX11Forwarding: !Ref EnableX11Forwarding + KeyPairName: !Ref KeyPairName + NumBastionHosts: !Ref NumBastionHosts + PublicSubnet1ID: !GetAtt + - VPCStack + - Outputs.PublicSubnet1ID + PublicSubnet2ID: !GetAtt + - VPCStack + - Outputs.PublicSubnet2ID + QSS3BucketRegion: !Ref QSS3BucketRegion + QSS3BucketName: !Ref QSS3BucketName + QSS3KeyPrefix: !Ref QSS3KeyPrefix + RemoteAccessCIDR: !Ref RemoteAccessCIDR + VPCID: !GetAtt + - VPCStack + - Outputs.VPCID + diff --git a/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/templates/linux-bastion.template b/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/templates/linux-bastion.template new file mode 100644 index 0000000..46046a9 --- /dev/null +++ b/Amazon/artifactory7/latest/submodules/quickstart-linux-bastion/templates/linux-bastion.template @@ -0,0 +1,725 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: LinuxBastion+VPC Jul,30,2020 (qs-1qup6ra99) (Please do not remove) +Metadata: + LICENSE: Apache License, Version 2.0 + 'AWS::CloudFormation::Interface': + ParameterGroups: + - Label: + default: Network configuration + Parameters: + - VPCID + - PublicSubnet1ID + - PublicSubnet2ID + - RemoteAccessCIDR + - Label: + default: Amazon EC2 configuration + Parameters: + - KeyPairName + - BastionAMIOS + - BastionInstanceType + - RootVolumeSize + - Label: + default: Linux bastion configuration + Parameters: + - NumBastionHosts + - BastionHostName + - BastionTenancy + - EnableBanner + - BastionBanner + - EnableTCPForwarding + - EnableX11Forwarding + - Label: + default: Alternative configurations + Parameters: + - AlternativeInitializationScript + - OSImageOverride + - AlternativeIAMRole + - EnvironmentVariables + - Label: + default: AWS Quick Start configuration + Parameters: + - QSS3BucketName + - QSS3KeyPrefix + - QSS3BucketRegion + ParameterLabels: + AlternativeIAMRole: + default: Alternative IAM role + AlternativeInitializationScript: + default: Alternative initialization script + BastionAMIOS: + default: Bastion AMI operating system + BastionHostName: + default: Bastion Host Name + BastionTenancy: + default: Bastion tenancy + BastionBanner: + default: Banner text + QSS3BucketRegion: + default: Quick Start S3 bucket region + BastionInstanceType: + default: Bastion instance type + EnableBanner: + default: Bastion banner + EnableTCPForwarding: + default: TCP forwarding + EnableX11Forwarding: + default: X11 forwarding + EnvironmentVariables: + default: Environment variables + KeyPairName: + default: Key pair name + NumBastionHosts: + default: Number of bastion hosts + OSImageOverride: + default: Operating system override + PublicSubnet1ID: + default: Public subnet 1 ID + PublicSubnet2ID: + default: Public subnet 2 ID + QSS3BucketName: + default: Quick Start S3 bucket name + QSS3KeyPrefix: + default: Quick Start S3 key prefix + RemoteAccessCIDR: + default: Allowed bastion external access CIDR + VPCID: + default: VPC ID + RootVolumeSize: + default: Root volume size + cfn-lint: { config: { ignore_checks: [E9007] } } +Parameters: + BastionAMIOS: + AllowedValues: + - Amazon-Linux2-HVM + - CentOS-7-HVM + - Ubuntu-Server-20.04-LTS-HVM + - SUSE-SLES-15-HVM + Default: Amazon-Linux2-HVM + Description: The Linux distribution for the AMI to be used for the bastion instances. + Type: String + BastionHostName: + Default: 'LinuxBastion' + Description: The value used for the name tag of the bastion host + Type: String + BastionBanner: + Default: "" + Description: Banner text to display upon login. + Type: String + BastionTenancy: + Description: 'VPC tenancy to launch the bastion in. Options: ''dedicated'' or ''default''' + Type: String + Default: default + AllowedValues: + - dedicated + - default + BastionInstanceType: + AllowedValues: + - t2.nano + - t2.micro + - t2.small + - t2.medium + - t2.large + - t3.micro + - t3.small + - t3.medium + - t3.large + - t3.xlarge + - t3.2xlarge + - m4.large + - m4.xlarge + - m4.2xlarge + - m4.4xlarge + Default: t2.micro + Description: Amazon EC2 instance type for the bastion instances. + Type: String + EnableBanner: + AllowedValues: + - 'true' + - 'false' + Default: 'false' + Description: To include a banner to be displayed when connecting via SSH to the + bastion, choose true. + Type: String + EnableTCPForwarding: + Type: String + Description: To enable TCP forwarding, choose true. + Default: 'false' + AllowedValues: + - 'true' + - 'false' + EnableX11Forwarding: + Type: String + Description: To enable X11 forwarding, choose true. + Default: 'false' + AllowedValues: + - 'true' + - 'false' + KeyPairName: + Description: Name of an existing public/private key pair. If you do not have one in this AWS Region, + please create it before continuing. + Type: 'AWS::EC2::KeyPair::KeyName' + NumBastionHosts: + AllowedValues: + - '1' + - '2' + - '3' + - '4' + Default: '1' + Description: The number of bastion hosts to create. The maximum number is four. + Type: String + PublicSubnet1ID: + Description: ID of the public subnet 1 that you want to provision the first bastion + into (e.g., subnet-a0246dcd). + Type: 'AWS::EC2::Subnet::Id' + PublicSubnet2ID: + Description: ID of the public subnet 2 that you want to provision the second bastion into + (e.g., subnet-e3246d8e). + Type: 'AWS::EC2::Subnet::Id' + QSS3BucketName: + 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 + Description: S3 bucket name for the Quick Start assets. Quick Start bucket name can + include numbers, lowercase letters, uppercase letters, and hyphens (-). It + cannot start or end with a hyphen (-). + 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 + QSS3KeyPrefix: + AllowedPattern: '^([0-9a-zA-Z-.]+/)*$' + ConstraintDescription: Quick Start key prefix can include numbers, lowercase letters, uppercase + letters, hyphens (-), dots (.) and forward slash (/). The prefix should + end with a forward slash (/). + Default: quickstart-linux-bastion/ + Description: S3 key prefix for the Quick Start assets. Quick Start key prefix can + include numbers, lowercase letters, uppercase letters, hyphens (-), dots + (.) and forward slash (/) and it should end with a forward slash (/). + Type: String + RemoteAccessCIDR: + 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]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/x + Description: Allowed CIDR block for external SSH access to the bastions. + Type: String + VPCID: + Description: 'ID of the VPC (e.g., vpc-0343606e).' + Type: 'AWS::EC2::VPC::Id' + AlternativeInitializationScript: + AllowedPattern: ^http.*|^$ + ConstraintDescription: URL must begin with http + Description: An alternative initialization script to run during setup. + Default: '' + Type: String + OSImageOverride: + Description: The Region-specific image to use for the instance. + Type: String + Default: '' + AlternativeIAMRole: + Description: An existing IAM Role name to attach to the bastion. If left blank, + a new role will be created. + Default: '' + Type: String + EnvironmentVariables: + Description: A comma-separated list of environment variables for use in + bootstrapping. Variables must be in the format KEY=VALUE. VALUE cannot + contain commas. + Type: String + Default: '' + RootVolumeSize: + Description: The size in GB for the root EBS volume. + Type: Number + Default: '10' +Rules: + SubnetsInVPC: + Assertions: + - Assert: + 'Fn::EachMemberIn': + - 'Fn::ValueOfAll': + - 'AWS::EC2::Subnet::Id' + - VpcId + - 'Fn::RefAll': 'AWS::EC2::VPC::Id' + AssertDescription: All subnets must exist in the VPC +Mappings: + AWSAMIRegionMap: + ap-northeast-1: + AMZNLINUX2: ami-0cc75a8978fbbc969 + US2004HVM: ami-0461b11e2fad8c14a + CENTOS7HVM: ami-06a46da680048c8ae + SLES15HVM: ami-056ac8ad44e6a7e1f + ap-northeast-2: + AMZNLINUX2: ami-0bd7691bf6470fe9c + US2004HVM: ami-0dbad3c7f731477cb + CENTOS7HVM: ami-06e83aceba2cb0907 + SLES15HVM: ami-0f81fff879bafe6b8 + ap-south-1: + AMZNLINUX2: ami-0ebc1ac48dfd14136 + US2004HVM: ami-0ebd654017556e025 + CENTOS7HVM: ami-026f33d38b6410e30 + SLES15HVM: ami-01be89269d32f2a16 + ap-southeast-1: + AMZNLINUX2: ami-0cd31be676780afa7 + US2004HVM: ami-0ba1d1f3433cd4c68 + CENTOS7HVM: ami-07f65177cb990d65b + SLES15HVM: ami-070356c21596ddc67 + ap-southeast-2: + AMZNLINUX2: ami-0ded330691a314693 + US2004HVM: ami-02be36619a83e9a16 + CENTOS7HVM: ami-0b2045146eb00b617 + SLES15HVM: ami-0c4245381c67efb39 + ca-central-1: + AMZNLINUX2: ami-013d1df4bcea6ba95 + US2004HVM: ami-071c33c681c9d4a00 + CENTOS7HVM: ami-04a25c39dc7a8aebb + SLES15HVM: ami-0c97d9b588207dad6 + eu-central-1: + AMZNLINUX2: ami-0c115dbd34c69a004 + US2004HVM: ami-0c2b1c303a2e4cb49 + CENTOS7HVM: ami-0e8286b71b81c3cc1 + SLES15HVM: ami-05dfd265ea534a3e9 + me-south-1: + AMZNLINUX2: ami-01f41d49c363da2ad + US2004HVM: ami-07f9fe3f7a8c82448 + CENTOS7HVM: ami-011c71a894b10f35b + SLES15HVM: ami-0252c6d3a59c7473b + ap-east-1: + AMZNLINUX2: ami-47317236 + US2004HVM: ami-545b1825 + CENTOS7HVM: ami-0e5c29e6c87a9644f + SLES15HVM: ami-0ad6e15bcbb2dbe38 + eu-north-1: + AMZNLINUX2: ami-039609244d2810a6b + US2004HVM: ami-08baf9e3c347b7092 + CENTOS7HVM: ami-05788af9005ef9a93 + SLES15HVM: ami-0741fa1a008af40ad + eu-west-1: + AMZNLINUX2: ami-07d9160fa81ccffb5 + US2004HVM: ami-0f1d11c92a9467c07 + CENTOS7HVM: ami-0b850cf02cc00fdc8 + SLES15HVM: ami-0a58a1b152ba55f1d + eu-west-2: + AMZNLINUX2: ami-0a13d44dccf1f5cf6 + US2004HVM: ami-082335b69bcfdb15b + CENTOS7HVM: ami-09e5afc68eed60ef4 + SLES15HVM: ami-01497522185aaa4ee + eu-west-3: + AMZNLINUX2: ami-093fa4c538885becf + US2004HVM: ami-00f6fb16625871821 + CENTOS7HVM: ami-0cb72d2e599cffbf9 + SLES15HVM: ami-0f238bd4c6fdbefb0 + sa-east-1: + AMZNLINUX2: ami-018ccfb6b4745882a + US2004HVM: ami-083aa2af86ff2bd11 + CENTOS7HVM: ami-0b30f38d939dd4b54 + SLES15HVM: ami-0772af912976aa692 + us-east-1: + AMZNLINUX2: ami-02354e95b39ca8dec + US2004HVM: ami-0758470213bdd23b1 + CENTOS7HVM: ami-0affd4508a5d2481b + SLES15HVM: ami-0b1764f3d7d2e2316 + us-gov-west-1: + AMZNLINUX2: ami-74c4f215 + SLES15HVM: ami-57c0ba36 + us-gov-east-1: + AMZNLINUX2: ami-30e00c41 + SLES15HVM: ami-05e4bedfad53425e9 + us-east-2: + AMZNLINUX2: ami-07c8bc5c1ce9598c3 + US2004HVM: ami-07fb7bd53bacdfc16 + CENTOS7HVM: ami-01e36b7901e884a10 + SLES15HVM: ami-05ea824317ffc0c20 + us-west-1: + AMZNLINUX2: ami-05655c267c89566dd + US2004HVM: ami-0cd230f950c3de5d8 + CENTOS7HVM: ami-098f55b4287a885ba + SLES15HVM: ami-00e34a7624e5a7107 + us-west-2: + AMZNLINUX2: ami-0873b46c45c11058d + US2004HVM: ami-056cb9ae6e2df09e8 + CENTOS7HVM: ami-0bc06212a56393ee1 + SLES15HVM: ami-0f1e3b3fb0fec0361 + cn-north-1: + AMZNLINUX2: ami-010e92a33d9d1fc40 + CENTOS7HVM: ami-0e02aaefeb74c3373 + SLES15HVM: ami-021392849b6221a81 + cn-northwest-1: + AMZNLINUX2: ami-0959f8e18a2aac0fb + CENTOS7HVM: ami-07183a7702633260b + SLES15HVM: ami-00e1de3ee6d0d28ea + LinuxAMINameMap: + Amazon-Linux2-HVM: + Code: AMZNLINUX2 + OS: Amazon + CentOS-7-HVM: + Code: CENTOS7HVM + OS: CentOS + Ubuntu-Server-18.04-LTS-HVM: + Code: US1804HVM + OS: Ubuntu + Ubuntu-Server-20.04-LTS-HVM: + Code: US2004HVM + OS: Ubuntu + SUSE-SLES-15-HVM: + Code: SLES15HVM + OS: SLES +Conditions: + 2BastionCondition: !Or + - !Equals + - !Ref NumBastionHosts + - '2' + - !Condition 3BastionCondition + - !Condition 4BastionCondition + 3BastionCondition: !Or + - !Equals + - !Ref NumBastionHosts + - '3' + - !Condition 4BastionCondition + 4BastionCondition: !Equals + - !Ref NumBastionHosts + - '4' + UseAlternativeInitialization: !Not + - !Equals + - !Ref AlternativeInitializationScript + - '' + CreateIAMRole: !Equals + - !Ref AlternativeIAMRole + - '' + UseOSImageOverride: !Not + - !Equals + - !Ref OSImageOverride + - '' + UsingDefaultBucket: !Equals + - !Ref QSS3BucketName + - 'aws-quickstart' + DefaultBanner: !Equals [!Ref BastionBanner, ""] +Resources: + BastionMainLogGroup: + Type: 'AWS::Logs::LogGroup' + SSHMetricFilter: + Type: 'AWS::Logs::MetricFilter' + Properties: + LogGroupName: !Ref BastionMainLogGroup + FilterPattern: ON FROM USER PWD + MetricTransformations: + - MetricName: SSHCommandCount + MetricValue: '1' + MetricNamespace: !Sub "AWSQuickStart/${AWS::StackName}" + BastionHostRole: + Condition: CreateIAMRole + Type: 'AWS::IAM::Role' + Properties: + Path: / + AssumeRolePolicyDocument: + Statement: + - Action: + - 'sts:AssumeRole' + Principal: + Service: + - !Sub 'ec2.${AWS::URLSuffix}' + Effect: Allow + Version: 2012-10-17 + ManagedPolicyArns: + - !Sub 'arn:${AWS::Partition}:iam::aws:policy/AmazonSSMManagedInstanceCore' + - !Sub 'arn:${AWS::Partition}:iam::aws:policy/CloudWatchAgentServerPolicy' + BastionHostPolicy: + Type: 'AWS::IAM::Policy' + Properties: + PolicyName: BastionPolicy + PolicyDocument: + Version: 2012-10-17 + Statement: + - Action: + - 's3:GetObject' + Resource: !Sub + - arn:${AWS::Partition}:s3:::${S3Bucket}/${QSS3KeyPrefix}* + - S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] + Effect: Allow + - Action: + - 'logs:CreateLogStream' + - 'logs:GetLogEvents' + - 'logs:PutLogEvents' + - 'logs:DescribeLogGroups' + - 'logs:DescribeLogStreams' + - 'logs:PutRetentionPolicy' + - 'logs:PutMetricFilter' + - 'logs:CreateLogGroup' + Resource: !Sub "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:${BastionMainLogGroup}:*" + Effect: Allow + - Action: + - 'ec2:AssociateAddress' + - 'ec2:DescribeAddresses' + Resource: '*' + Effect: Allow + Roles: + - !If + - CreateIAMRole + - !Ref BastionHostRole + - !Ref AlternativeIAMRole + BastionHostProfile: + DependsOn: BastionHostPolicy + Type: 'AWS::IAM::InstanceProfile' + Properties: + Roles: + - !If + - CreateIAMRole + - !Ref BastionHostRole + - !Ref AlternativeIAMRole + Path: / + EIP1: + Type: 'AWS::EC2::EIP' + Properties: + Domain: vpc + EIP2: + Type: 'AWS::EC2::EIP' + Condition: 2BastionCondition + Properties: + Domain: vpc + EIP3: + Type: 'AWS::EC2::EIP' + Condition: 3BastionCondition + Properties: + Domain: vpc + EIP4: + Type: 'AWS::EC2::EIP' + Condition: 4BastionCondition + Properties: + Domain: vpc + BastionAutoScalingGroup: + Type: 'AWS::AutoScaling::AutoScalingGroup' + Properties: + LaunchConfigurationName: !Ref BastionLaunchConfiguration + VPCZoneIdentifier: + - !Ref PublicSubnet1ID + - !Ref PublicSubnet2ID + MinSize: !Ref NumBastionHosts + MaxSize: !Ref NumBastionHosts + Cooldown: '900' + DesiredCapacity: !Ref NumBastionHosts + Tags: + - Key: Name + Value: !Ref BastionHostName + PropagateAtLaunch: true + CreationPolicy: + ResourceSignal: + Count: !Ref NumBastionHosts + Timeout: PT60M + AutoScalingCreationPolicy: + MinSuccessfulInstancesPercent: 100 + UpdatePolicy: + AutoScalingReplacingUpdate: + WillReplace: true + BastionLaunchConfiguration: + Type: 'AWS::AutoScaling::LaunchConfiguration' + Metadata: + 'AWS::CloudFormation::Authentication': + S3AccessCreds: + type: S3 + roleName: !If + - CreateIAMRole + - !Ref BastionHostRole + - !Ref AlternativeIAMRole + buckets: + - !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] + 'AWS::CloudFormation::Init': + config: + files: + /tmp/auditd.rules: + mode: '000550' + owner: root + group: root + content: | + -a exit,always -F arch=b64 -S execve + -a exit,always -F arch=b32 -S execve + /tmp/auditing_configure.sh: + source: !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/auditing_configure.sh + - S3Bucket: !If + - UsingDefaultBucket + - !Sub 'aws-quickstart-${AWS::Region}' + - !Ref 'QSS3BucketName' + S3Region: !If + - UsingDefaultBucket + - !Ref 'AWS::Region' + - !Ref 'QSS3BucketRegion' + mode: '000550' + owner: root + group: root + authentication: S3AccessCreds + /tmp/bastion_bootstrap.sh: + source: !If + - UseAlternativeInitialization + - !Ref AlternativeInitializationScript + - !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/bastion_bootstrap.sh + - S3Bucket: !If + - UsingDefaultBucket + - !Sub 'aws-quickstart-${AWS::Region}' + - !Ref 'QSS3BucketName' + S3Region: !If + - UsingDefaultBucket + - !Ref 'AWS::Region' + - !Ref 'QSS3BucketRegion' + mode: '000550' + owner: root + group: root + authentication: S3AccessCreds + commands: + a-add_auditd_rules: + cwd: '/tmp/' + env: + BASTION_OS: !FindInMap [LinuxAMINameMap, !Ref BastionAMIOS, OS] + command: "./auditing_configure.sh" + # command: + # - !If [ ] + # - "cat /tmp/auditd.rules >> /etc/audit/rules.d/audit.rules && service auditd restart" + b-bootstrap: + cwd: '/tmp/' + env: + REGION: !Sub ${AWS::Region} + URL_SUFFIX: !Sub ${AWS::URLSuffix} + BANNER_REGION: !If [ UsingDefaultBucket, !Ref 'AWS::Region', !Ref 'QSS3BucketRegion' ] + command: !Sub + - "./bastion_bootstrap.sh --banner ${BannerUrl} --enable ${EnableBanner} --tcp-forwarding ${EnableTCPForwarding} --x11-forwarding ${EnableX11Forwarding}" + - BannerUrl: !If + - DefaultBanner + - !Sub + - s3://${S3Bucket}/${QSS3KeyPrefix}scripts/banner_message.txt + - S3Bucket: !If [ UsingDefaultBucket, !Sub 'aws-quickstart-${AWS::Region}', !Ref 'QSS3BucketName' ] + - !Ref BastionBanner + Properties: + AssociatePublicIpAddress: true + PlacementTenancy: !Ref BastionTenancy + KeyName: !Ref KeyPairName + IamInstanceProfile: !Ref BastionHostProfile + ImageId: !If + - UseOSImageOverride + - !Ref OSImageOverride + - !FindInMap + - AWSAMIRegionMap + - !Ref 'AWS::Region' + - !FindInMap + - LinuxAMINameMap + - !Ref BastionAMIOS + - Code + SecurityGroups: + - !Ref BastionSecurityGroup + InstanceType: !Ref BastionInstanceType + BlockDeviceMappings: + - DeviceName: /dev/xvda + Ebs: + VolumeSize: !Ref RootVolumeSize + VolumeType: gp2 + Encrypted: true + DeleteOnTermination: true + UserData: + Fn::Base64: !Sub + - | + #!/bin/bash + set -x + for e in $(echo "${EnvironmentVariables}" | tr ',' ' '); do + export $e + done + export PATH=$PATH:/usr/local/bin + #cfn signaling functions + yum install git -y || apt-get install -y git || zypper -n install git + + function cfn_fail + { + cfn-signal -e 1 --stack ${AWS::StackName} --region ${AWS::Region} --resource BastionAutoScalingGroup + exit 1 + } + + function cfn_success + { + cfn-signal -e 0 --stack ${AWS::StackName} --region ${AWS::Region} --resource BastionAutoScalingGroup + exit 0 + } + + until git clone https://github.com/aws-quickstart/quickstart-linux-utilities.git ; do echo "Retrying"; done + cd /quickstart-linux-utilities; + source quickstart-cfn-tools.source; + qs_update-os || qs_err; + qs_bootstrap_pip || qs_err " pip bootstrap failed "; + qs_aws-cfn-bootstrap || qs_err " cfn bootstrap failed "; + + EIP_LIST="${EIP1},${EIP2},${EIP3},${EIP4}" + CLOUDWATCHGROUP=${BastionMainLogGroup} + cfn-init -v --stack '${AWS::StackName}' --resource BastionLaunchConfiguration --region ${AWS::Region} || cfn_fail + [ $(qs_status) == 0 ] && cfn_success || cfn_fail + - EIP2: + !If + - 2BastionCondition + - !Ref EIP2 + - 'Null' + EIP3: + !If + - 3BastionCondition + - !Ref EIP3 + - 'Null' + EIP4: + !If + - 4BastionCondition + - !Ref EIP4 + - 'Null' + BastionSecurityGroup: + Type: 'AWS::EC2::SecurityGroup' + Properties: + GroupDescription: Enables SSH Access to Bastion Hosts + VpcId: !Ref VPCID + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: 22 + ToPort: 22 + CidrIp: !Ref RemoteAccessCIDR + - IpProtocol: icmp + FromPort: -1 + ToPort: -1 + CidrIp: !Ref RemoteAccessCIDR +Outputs: + BastionAutoScalingGroup: + Description: Auto Scaling Group Reference ID + Value: !Ref BastionAutoScalingGroup + Export: + Name: !Sub '${AWS::StackName}-BastionAutoScalingGroup' + EIP1: + Description: Elastic IP 1 for Bastion + Value: !Ref EIP1 + Export: + Name: !Sub '${AWS::StackName}-EIP1' + EIP2: + Condition: 2BastionCondition + Description: Elastic IP 2 for Bastion + Value: !Ref EIP2 + Export: + Name: !Sub '${AWS::StackName}-EIP2' + EIP3: + Condition: 3BastionCondition + Description: Elastic IP 3 for Bastion + Value: !Ref EIP3 + Export: + Name: !Sub '${AWS::StackName}-EIP3' + EIP4: + Condition: 4BastionCondition + Description: Elastic IP 4 for Bastion + Value: !Ref EIP4 + Export: + Name: !Sub '${AWS::StackName}-EIP4' + CloudWatchLogs: + Description: CloudWatch Logs GroupName. Your SSH logs will be stored here. + Value: !Ref BastionMainLogGroup + Export: + Name: !Sub '${AWS::StackName}-CloudWatchLogs' + BastionSecurityGroupID: + Description: Bastion Security Group ID + Value: !Ref BastionSecurityGroup + Export: + Name: !Sub '${AWS::StackName}-BastionSecurityGroupID' + BastionHostRole: + Description: Bastion IAM Role name + Value: !If + - CreateIAMRole + - !Ref BastionHostRole + - !Ref AlternativeIAMRole + Export: + Name: !Sub '${AWS::StackName}-BastionHostRole' diff --git a/Amazon/artifactory7/latest/templates/jfrog-artifactory-core-infrastructure.template.yaml b/Amazon/artifactory7/latest/templates/jfrog-artifactory-core-infrastructure.template.yaml new file mode 100644 index 0000000..da6c649 --- /dev/null +++ b/Amazon/artifactory7/latest/templates/jfrog-artifactory-core-infrastructure.template.yaml @@ -0,0 +1,425 @@ +AWSTemplateFormatVersion: '2010-09-09' +Description: 'JFrog Artifactory Quick Start Deployment (qs-1qpmmjh61)' +Parameters: + AvailabilityZones: + Description: List of Availability Zones to use for the subnets in the VPC. Two + Availability Zones are used for this deployment. + Type: List + VpcId: + Type: AWS::EC2::VPC::Id + VpcCidr: + Description: CIDR block for the VPC + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.0.0/16 + Type: String + PrivateSubnet1Cidr: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.0.0/19 + Type: String + PrivateSubnet2Cidr: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.32.0/19 + Type: String + PrivateSubnet3Cidr: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.64.0/19 + Type: String + SubnetIds: + Type: List + DatabaseAllocatedStorage: + Type: Number + DatabasePreferredAz: + Type: String + MultiAzDatabase: + Description: Choose false to create an Amazon RDS instance in a single Availability Zone. + ConstraintDescription: True or False + AllowedValues: + - "true" + - "false" + Type: String + DatabaseEngine: + Type: String + DatabaseUser: + Type: String + DatabasePassword: + NoEcho: 'true' + Type: String + DatabaseInstance: + Type: String + DatabaseName: + Type: String + ArtifactoryProduct: + Default: JFrog-Artifactory-Pro + Type: String + ReleaseStage: + Default: GA + Type: String + InstanceType: + Default: m5.xlarge + Type: String + ArtifactoryHostRole: + Type: String + VolumeSize: + Type: Number + +Mappings: + DatabaseMap: + Postgres: + Name: postgresql + DatabaseVersion: 11.5 + Driver: "org.postgresql.Driver" + Plugin: postgresql-42.2.9.jar + PluginURL: https://jdbc.postgresql.org/download/ + port: "5432" + extraDatabaseOps: "" + ReleaseStageMap: + BETA: + ProDockerRepo: "earlyaccess-docker.jfrog.io/jfrog/artifactory-pro" + JcrDockerRepo: "earlyaccess-docker.jfrog.io/jfrog/artifactory-jcr" + NginxDockerRepo: "earlyaccess-docker.jfrog.io/jfrog/nginx-artifactory-pro" + GA: + ProDockerRepo: "docker.bintray.io/jfrog/artifactory-pro" + JcrDockerRepo: "docker.bintray.io/jfrog/artifactory-jcr" + NginxDockerRepo: "docker.bintray.io/jfrog/nginx-artifactory-pro" + ProductMap: + JFrog-Container-Registry: + RepoName: JcrDockerRepo + JFrog-Artifactory-Pro: + RepoName: ProDockerRepo + JavaOptionstoInstance: + c5.2xlarge: + Min: 8 + Max: 12 + DeploymentSize: Small + c5.4xlarge: + Min: 16 + Max: 24 + DeploymentSize: Large + m5.large: + Min: 4 + Max: 4 + DeploymentSize: xxSmall + m5.xlarge: + Min: 8 + Max: 12 + DeploymentSize: xSmall + m5.2xlarge: + Min: 16 + Max: 24 + DeploymentSize: Small + m5.4xlarge: + Min: 32 + Max: 48 + DeploymentSize: Medium + m5.8xlarge: + Min: 64 + Max: 96 + DeploymentSize: Large + m5.12xlarge: + Min: 96 + Max: 144 + DeploymentSize: xLarge + m5.16xlarge: + Min: 128 + Max: 192 + DeploymentSize: xxLarge + m5.24xlarge: + Min: 192 + Max: 288 + DeploymentSize: xxxLarge + m5.metal: + Min: 192 + Max: 288 + DeploymentSize: xxxLarge + m5d.large: + Min: 4 + Max: 4 + DeploymentSize: xxSmall + m5d.xlarge: + Min: 8 + Max: 12 + DeploymentSize: xSmall + m5d.2xlarge: + Min: 16 + Max: 24 + DeploymentSize: Small + m5d.4xlarge: + Min: 32 + Max: 48 + DeploymentSize: Medium + m5d.8xlarge: + Min: 64 + Max: 96 + DeploymentSize: Large + m5d.12xlarge: + Min: 96 + Max: 144 + DeploymentSize: xLarge + m5d.16xlarge: + Min: 128 + Max: 192 + DeploymentSize: xxLarge + m5d.24xlarge: + Min: 192 + Max: 288 + DeploymentSize: xxxLarge + m5d.metal: + Min: 192 + Max: 288 + DeploymentSize: xxxLarge + m5a.large: + Min: 4 + Max: 4 + DeploymentSize: xxSmall + m5a.xlarge: + Min: 8 + Max: 12 + DeploymentSize: xSmall + m5a.2xlarge: + Min: 16 + Max: 24 + DeploymentSize: Small + m5a.4xlarge: + Min: 32 + Max: 48 + DeploymentSize: Medium + m5a.8xlarge: + Min: 64 + Max: 96 + DeploymentSize: Large + m5a.12xlarge: + Min: 96 + Max: 144 + DeploymentSize: xLarge + m5a.16xlarge: + Min: 128 + Max: 192 + DeploymentSize: xxLarge + m5a.24xlarge: + Min: 192 + Max: 288 + DeploymentSize: xxxLarge + m5ad.large: + Min: 4 + Max: 4 + DeploymentSize: xxSmall + m5ad.xlarge: + Min: 8 + Max: 12 + DeploymentSize: xSmall + m5ad.2xlarge: + Min: 16 + Max: 24 + DeploymentSize: Small + m5ad.4xlarge: + Min: 32 + Max: 48 + DeploymentSize: Medium + m5ad.12xlarge: + Min: 96 + Max: 144 + DeploymentSize: xLarge + m5ad.24xlarge: + Min: 192 + Max: 288 + DeploymentSize: xxxLarge + +Conditions: + IsMultiAzDatabase: !Equals [!Ref MultiAzDatabase, 'true'] + +Resources: + ArtifactoryDatabaseSubnetGroup: + Type: AWS::RDS::DBSubnetGroup + Properties: + DBSubnetGroupDescription: Private Subnets available to the RDS Instance(s) + SubnetIds: !Ref SubnetIds + ArtifactoryDatabase: + Type: AWS::RDS::DBInstance + Properties: + AllocatedStorage: !Ref DatabaseAllocatedStorage + AvailabilityZone: !If [IsMultiAzDatabase, !Ref AWS::NoValue, !Ref DatabasePreferredAz] + BackupRetentionPeriod: 30 + DBInstanceClass: !Ref DatabaseInstance + DBName: !Ref DatabaseName + DBSubnetGroupName: !Ref ArtifactoryDatabaseSubnetGroup + Engine: !Ref DatabaseEngine + EngineVersion: !FindInMap + - DatabaseMap + - !Ref DatabaseEngine + - DatabaseVersion + MasterUsername: !Ref DatabaseUser + MasterUserPassword: !Ref DatabasePassword + MultiAZ: !Ref MultiAzDatabase + StorageEncrypted: true + VPCSecurityGroups: + - !Ref ArtifactoryDatabaseSG + ArtifactoryDatabaseSG: + Type: AWS::EC2::SecurityGroup + Properties: + Tags: + - Key: Name + Value: artifactory-rds-sg + GroupDescription: SG for RDS Instance to allow communication from the Bastion and Artifactory servers. + VpcId: !Ref VpcId + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: 22 + ToPort: 22 + CidrIp: !Ref VpcCidr + - IpProtocol: tcp + FromPort: !FindInMap + - DatabaseMap + - !Ref DatabaseEngine + - port + ToPort: !FindInMap + - DatabaseMap + - !Ref DatabaseEngine + - port + CidrIp: !Ref PrivateSubnet1Cidr + - IpProtocol: tcp + FromPort: !FindInMap + - DatabaseMap + - !Ref DatabaseEngine + - port + ToPort: !FindInMap + - DatabaseMap + - !Ref DatabaseEngine + - port + CidrIp: !Ref PrivateSubnet2Cidr + - IpProtocol: tcp + FromPort: !FindInMap + - DatabaseMap + - !Ref DatabaseEngine + - port + ToPort: !FindInMap + - DatabaseMap + - !Ref DatabaseEngine + - port + CidrIp: !Ref PrivateSubnet3Cidr + SecurityGroupEgress: + - IpProtocol: tcp + FromPort: 22 + ToPort: 22 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 80 + ToPort: 80 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 443 + ToPort: 443 + CidrIp: 0.0.0.0/0 + ArtifactoryS3Bucket: + Type: AWS::S3::Bucket + Properties: + AccessControl: Private + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: AES256 + ArtifactoryS3IAMPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyName: S3BucketPermissions + PolicyDocument: + Version: 2012-10-17 + Statement: + - Sid: S3BucketPermissions + Effect: Allow + Action: + - s3:* + Resource: + - Fn::Join: + - '' + - - !Sub "arn:${AWS::Partition}:s3:::" + - !Ref ArtifactoryS3Bucket + - Fn::Join: + - '' + - - !Sub "arn:${AWS::Partition}:s3:::" + - !Ref ArtifactoryS3Bucket + - "/*" + Roles: + - !Ref ArtifactoryHostRole + ArtifactoryEbsVolume: + Type: AWS::EC2::Volume + Properties: + AvailabilityZone: + !If + - IsMultiAzDatabase + - !Select + - '0' + - !Ref AvailabilityZones + - !Ref DatabasePreferredAz + Encrypted: false + Size: !Ref VolumeSize + Tags: + - Key: Name + Value: !Sub "Artifactory-${AWS::StackName}" + VolumeType: gp2 + DeletionPolicy: Snapshot + UpdateReplacePolicy: Snapshot +Outputs: + S3Bucket: + Value: !Ref ArtifactoryS3Bucket + Description: Actual S3 bucket created for Artifactory + DatabaseDriver: + Value: !FindInMap [DatabaseMap, !Ref DatabaseEngine, Driver] + DatabasePlugin: + Value: !FindInMap [DatabaseMap, !Ref DatabaseEngine, Plugin] + DatabasePluginUrl: + Value: !Sub + - "${MainURL}${PluginVersion}" + - { + MainURL: !FindInMap [DatabaseMap, !Ref DatabaseEngine, PluginURL], + PluginVersion: !FindInMap [DatabaseMap, !Ref DatabaseEngine, Plugin] + } + DatabaseType: + Value: !FindInMap [DatabaseMap, !Ref DatabaseEngine, Name] + DatabaseUrl: + Value: !Sub + - "jdbc:${DatabaseType}://${ArtifactoryDatabaseEndpointAddress}:${port}/${DatabaseName}${extraDatabaseOps}" + - { + DatabaseType: !FindInMap [DatabaseMap, !Ref DatabaseEngine, Name], + ArtifactoryDatabaseEndpointAddress: !GetAtt ArtifactoryDatabase.Endpoint.Address, + port: !FindInMap [DatabaseMap, !Ref DatabaseEngine, port], + extraDatabaseOps: !FindInMap [DatabaseMap, !Ref DatabaseEngine, extraDatabaseOps], + } + XrayMasterDatabaseUrl: + Value: !Sub + - "${ArtifactoryDatabaseEndpointAddress}:${port}/${DatabaseName}?sslmode=disable" + - { + ArtifactoryDatabaseEndpointAddress: !GetAtt ArtifactoryDatabase.Endpoint.Address, + port: !FindInMap [DatabaseMap, !Ref DatabaseEngine, port], + } + XrayDatabaseUrl: + Value: !Sub + - "${ArtifactoryDatabaseEndpointAddress}:${port}/xraydb?sslmode=disable" + - { + ArtifactoryDatabaseEndpointAddress: !GetAtt ArtifactoryDatabase.Endpoint.Address, + port: !FindInMap [DatabaseMap, !Ref DatabaseEngine, port], + } + ProDockerRepo: + Value: !FindInMap + - ReleaseStageMap + - !Ref ReleaseStage + - !FindInMap + - ProductMap + - !Ref ArtifactoryProduct + - RepoName + NginxDockerRepo: + Value: !FindInMap [ReleaseStageMap, !Ref ReleaseStage, NginxDockerRepo] + JavaOpts: + Value: !Sub + - "-Xms${min}g -Xmx${max}g" + - { + min: !FindInMap [JavaOptionstoInstance, !Ref InstanceType, Min], + max: !FindInMap [JavaOptionstoInstance, !Ref InstanceType, Max] + } + DeploymentSize: + Value: !FindInMap [JavaOptionstoInstance, !Ref InstanceType, DeploymentSize] + ArtifactoryEbsVolume: + Value: !Ref ArtifactoryEbsVolume diff --git a/Amazon/artifactory7/latest/templates/jfrog-artifactory-ec2-existing-vpc.template.yaml b/Amazon/artifactory7/latest/templates/jfrog-artifactory-ec2-existing-vpc.template.yaml new file mode 100644 index 0000000..8d6c593 --- /dev/null +++ b/Amazon/artifactory7/latest/templates/jfrog-artifactory-ec2-existing-vpc.template.yaml @@ -0,0 +1,1109 @@ +AWSTemplateFormatVersion: '2010-09-09' +Description: 'JFrog Artifactory Quick Start Deployment into an Existing VPC (qs-1q037efj0)' +Metadata: + QuickStartDocumentation: + EntrypointName: "Launch into an existing VPC" + AWS::CloudFormation::Interface: + ParameterGroups: + - Label: + default: Security configuration + Parameters: + - KeyPairName + - AccessCidr + - RemoteAccessCidr + - Label: + default: Network configuration + Parameters: + - AvailabilityZones + - VpcId + - VpcCidr + - PublicSubnet1Id + - PublicSubnet2Id + - PrivateSubnet1Id + - PrivateSubnet2Id + - PrivateSubnet1Cidr + - PrivateSubnet2Cidr + - ELBScheme + - Label: + default: Bastion configuration + Parameters: + - ProvisionBastionHost + - BastionInstanceType + - BastionOs + - BastionRootVolumeSize + - BastionEnableTcpForwarding + - NumBastionHosts + - BastionEnableX11Forwarding + - Label: + default: Amazon EC2 configuration + Parameters: + - VolumeSize + - InstanceType + - Label: + default: JFrog Artifactory configuration + Parameters: + - ArtifactoryProduct + - ArtifactoryVersion + - NumberOfSecondary + - SmLicenseName + - SmCertName + - ArtifactoryServerName + - MasterKey + - ExtraJavaOptions + - DefaultJavaMemSettings + - Label: + default: Amazon RDS configuration + Parameters: + - DatabaseName + - DatabaseEngine + - DatabaseUser + - DatabasePassword + - DatabaseInstance + - DatabaseAllocatedStorage + - DatabasePreferredAz + - MultiAzDatabase + - Label: + default: AWS Quick Start configuration + Parameters: + - QsS3BucketName + - QsS3KeyPrefix + - QsS3BucketRegion + - Label: + default: JFrog Xray Configuration + Parameters: + - InstallXray + - XrayVersion + - XrayNumberOfInstances + - XrayInstanceType + - XrayDatabaseUser + - XrayDatabasePassword + ParameterLabels: + AvailabilityZones: + default: Availability Zones + KeyPairName: + default: SSH key name + VpcId: + default: VPC ID + VpcCidr: + default: VPC CIDR + PublicSubnet1Id: + default: Public subnet 1 ID + PublicSubnet2Id: + default: Public subnet 2 ID + PrivateSubnet1Id: + default: Private subnet 1 ID + PrivateSubnet2Id: + default: Private subnet 2 ID + PrivateSubnet1Cidr: + default: Private subnet 1 CIDR + PrivateSubnet2Cidr: + default: Private subnet 2 CIDR + AccessCidr: + default: Permitted IP range + RemoteAccessCidr: + default: Remote access CIDR + ELBScheme: + default: Elastic Load Balancing scheme + ProvisionBastionHost: + default: Bastion instance + BastionInstanceType: + default: Bastion instance type + BastionRootVolumeSize: + default: Bastion root volume size + BastionEnableTcpForwarding: + default: Bastion enable TCP forwarding + BastionEnableX11Forwarding: + default: Bastion enable X11 forwarding + BastionOs: + default: Bastion operating system + NumBastionHosts: + default: Number of bastion instances + VolumeSize: + default: EBS root volume size + InstanceType: + default: EC2 instance type + NumberOfSecondary: + default: Secondary instances + ArtifactoryProduct: + default: Artifactory product to install + ArtifactoryVersion: + default: Artifactory version + SmLicenseName: + default: Artifactory licenses secret name + SmCertName: + default: Artifactory certificate secret name + ArtifactoryServerName: + default: Artifactory server name + MasterKey: + default: Master server key + ExtraJavaOptions: + default: Extra Java options + DefaultJavaMemSettings: + default: Default Java memory settings + DatabaseName: + default: Database name + DatabaseEngine: + default: Database engine + DatabaseUser: + default: Database user + DatabasePassword: + default: Database password + DatabaseInstance: + default: Database instance type + DatabaseAllocatedStorage: + default: Database allocated storage + DatabasePreferredAz: + default: Database preferred Availability Zone + MultiAzDatabase: + default: High-availability database + QsS3BucketName: + default: Quick Start S3 bucket name + QsS3KeyPrefix: + default: Quick Start S3 key prefix + QsS3BucketRegion: + default: Quick Start S3 bucket region + InstallXray: + default: Install JFrog Xray + XrayVersion: + default: Version of Xray to install + XrayNumberOfInstances: + default: Number of JFrog Xray instances + XrayInstanceType: + default: Xray instance type + XrayDatabaseUser: + default: Xray Database user + XrayDatabasePassword: + default: Xray Database password +Parameters: + AvailabilityZones: + Description: List of Availability Zones to use for the subnets in the VPC. Two + Availability Zones are used for this deployment. + Type: List + KeyPairName: + Description: Name of an existing key pair, + which allows you to connect securely to your instance after it launches. + This is the key pair you created in your preferred Region. + Type: AWS::EC2::KeyPair::KeyName + VpcId: + Description: ID of your existing VPC (e.g., vpc-0343606e). + Type: "AWS::EC2::VPC::Id" + VpcCidr: + Description: CIDR block for the VPC. + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.0.0/16 + Type: String + PublicSubnet1Id: + Description: ID of the public subnet in Availability Zone 1 of your existing VPC (e.g., subnet-z0376dab). + Type: "AWS::EC2::Subnet::Id" + PublicSubnet2Id: + Description: ID of the public subnet in Availability Zone 2 of your existing VPC (e.g., subnet-a29c3d84). + Type: "AWS::EC2::Subnet::Id" + PrivateSubnet1Id: + Description: ID of the private subnet in Availability Zone 1 of your existing VPC (e.g., subnet-a0246dcd). + Type: "AWS::EC2::Subnet::Id" + PrivateSubnet2Id: + Description: ID of the private subnet in Availability Zone 2 of your existing VPC (e.g., subnet-b58c3d67). + Type: "AWS::EC2::Subnet::Id" + PrivateSubnet1Cidr: + Description: CIDR of the private subnet in Availability Zone 1 of your existing VPC (e.g., 10.0.0.0/19). + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.0.0/19 + Type: String + PrivateSubnet2Cidr: + Description: CIDR of the private subnet in Availability Zone 2 of your existing VPC (e.g., 10.0.32.0/19). + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.32.0/19 + Type: String + AccessCidr: + Description: CIDR IP range that is permitted to access Artifactory. + We recommend that you set this value to a trusted IP range. + For example, you might want to grant only your corporate network access to the software. + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$ + Type: String + RemoteAccessCidr: + Description: Remote CIDR range that allows you to connect to the bastion instance by using SSH. + We recommend that you set this value to a trusted IP range. + For example, you might want to grant specific ranges inside your corporate network SSH access. + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$ + Type: String + ELBScheme: + Description: Choose whether this is internet facing or internal. + AllowedValues: + - internal + - internet-facing + Default: internet-facing + Type: String + ProvisionBastionHost: + Description: Choose Disabled to skip creating a bastion instance. Due to the JFrog Container Registry nodes being + created in private subnets, the default setting of Enabled this is highly recommended. + AllowedValues: + - "Enabled" + - "Disabled" + Default: "Enabled" + Type: String + BastionInstanceType: + Description: Size of the bastion instances. + AllowedValues: + - t3.nano + - t3.micro + - t3.small + - t3.medium + - t3.large + - m5.large + - m5.xlarge + - m5.2xlarge + - m5.4xlarge + Default: "t3.micro" + Type: String + BastionRootVolumeSize: + Description: Size of the root volume on the bastion instances. + Default: 10 + Type: Number + BastionEnableTcpForwarding: + Description: Choose whether to enable TCPForwarding via the bootstrapping of the bastion instance + or not. + AllowedValues: + - "true" + - "false" + Default: "true" + Type: String + BastionEnableX11Forwarding: + Description: Choose true to enable X11 via the bootstrapping of the bastion host. + Setting this value to true will enable X Windows over SSH. + X11 forwarding can be useful, but it is also a security risk, so it's recommended + that you keep the default (false) setting. + AllowedValues: + - "true" + - "false" + Default: "false" + Type: String + BastionOs: + Description: Linux distribution for the Amazon Machine Image (AMI) to be used for the bastion instances. + AllowedValues: + - "Amazon-Linux2-HVM" + - "CentOS-7-HVM" + - "Ubuntu-Server-20.04-LTS-HVM" + - "SUSE-SLES-15-HVM" + Default: "Amazon-Linux2-HVM" + Type: String + NumBastionHosts: + Description: Number of bastion instances to create. + AllowedValues: + - '1' + - '2' + - '3' + - '4' + Default: '1' + Type: String + VolumeSize: + Description: Size in gigabytes of the available storage (min 10GB); the Quick Start will create an + Amazon Elastic Block Store (Amazon EBS) volumes of this size. + Default: 200 + Type: Number + InstanceType: + Description: EC2 type for the Artifactory instances. + AllowedValues: + - m5.large + - m5.xlarge + - m5.2xlarge + - m5.4xlarge + - m5.8xlarge + - m5.12xlarge + - m5.16xlarge + - m5.24xlarge + - m5.metal + - m5d.large + - m5d.xlarge + - m5d.2xlarge + - m5d.4xlarge + - m5d.8xlarge + - m5d.12xlarge + - m5d.16xlarge + - m5d.24xlarge + - m5d.metal + - m5a.large + - m5a.xlarge + - m5a.2xlarge + - m5a.4xlarge + - m5a.8xlarge + - m5a.12xlarge + - m5a.16xlarge + - m5a.24xlarge + ConstraintDescription: Must contain valid instance type. + Default: m5.xlarge + Type: String + NumberOfSecondary: + Description: Number of secondary Artifactory servers to complete your + HA deployment. To align with Artifactory best practices, the minimum number + is two and the maximum is seven. Do not select more instances than you + have licenses for. + AllowedValues: + - 0 + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + - 7 + Default: 2 + Type: Number + ArtifactoryProduct: + Description: JFrog Artifactory product you want to install into an AMI. + AllowedValues: + - JFrog-Artifactory-Pro + - JFrog-Artifactory-Enterprise + - JFrog-Container-Registry + Default: JFrog-Artifactory-Enterprise + Type: String + ArtifactoryVersion: + Description: Version of Artifactory that you want to deploy into the Quick Start. + See the release notes to select the version you want to deploy at + https://www.jfrog.com/confluence/display/RTF/Release+Notes. + AllowedPattern: ^(([0-9]|[1-9][0-9])\.){2}([1-9][0-9]|[0-9])$ + ConstraintDescription: A version that matches X.X.X per Artifactory releases + Default: 7.17.4 + Type: String + SmLicenseName: + Description: Secret name created in AWS Secrets Manager, which contains the Artifactory licenses. + Default: '' + Type: String + SmCertName: + Description: Secret name created in AWS Secrets Manager, which contains the SSL certificate and certificate key. + Default: '' + Type: String + ArtifactoryServerName: + Description: Name of your Artifactory server. Ensure that this matches your certificate. + Type: String + MasterKey: + Description: Master key for the Artifactory cluster. Generate a master key by using the command '$openssl rand -hex 16'. + AllowedPattern: ^[a-zA-Z0-9]+$ + MinLength: '1' + MaxLength: '64' + ConstraintDescription: Only capital or lowercase letters and numbers, with a Max of 64 characters. + NoEcho: 'true' + Type: String + ExtraJavaOptions: + Description: Set Java options to pass to the JVM for Artifactory. For more information, see the Artifactory + system requirements at https://www.jfrog.com/confluence/display/RTF/System+Requirements#SystemRequirements-RecommendedHardware. + Do not add Xms or Xmx settings without disabling DefaultJavaMemSettings. + Default: -Xss256k -XX:+UseG1GC + Type: String + DefaultJavaMemSettings: + Description: Choose false to overwrite the standard memory-calculation options to pass to the Artifactory JVM. + If you plan to overwrite them, ensure they are added to the ExtraJavaOptions to prevent the stack provision from failing. + ConstraintDescription: True or False + AllowedValues: + - "true" + - "false" + Default: "true" + Type: String + DatabaseName: + Description: Name of your database instance. The name must be unique across all instances + owned by your AWS account in the current Region. The database instance identifier is case-insensitive, + but it's stored in lowercase (as in "mydbinstance"). + AllowedPattern: ^[a-zA-Z]([a-zA-Z0-9])+$ + MinLength: '1' + MaxLength: '60' + ConstraintDescription: 1 to 60 alphanumeric characters First character must be a letter. + Default: artdb + Type: String + DatabaseEngine: + Description: Database engine that you want to run, which is currently locked to MySQL. + AllowedValues: + - Postgres + Default: Postgres + Type: String + DatabaseUser: + Description: Login ID for the master user of your database instance. + MinLength: '1' + MaxLength: '16' + AllowedPattern: ^[a-zA-Z]([a-zA-Z0-9])+$ + ConstraintDescription: 1 to 16 alphanumeric characters. First character must be a letter. + Default: artifactory + Type: String + DatabasePassword: + Description: Password for the Artifactory database user. + AllowedPattern: ^[^ \\']+$ + MinLength: '8' + MaxLength: '12' + ConstraintDescription: Must be at least 8 and no more than + 12 characters containing letters and (minimum 1 capital letter), numbers and + symbols. + NoEcho: 'true' + Type: String + DatabaseInstance: + Description: Size of the database to be deployed as part of the Quick Start. + AllowedValues: + - db.m5.large + - db.m5.xlarge + - db.m5.2xlarge + - db.m5.10xlarge + - db.m5.16xlarge + - db.m5.large + - db.m5.xlarge + - db.m5.2xlarge + - db.m5.4xlarge + - db.m5.12xlarge + - db.m5.24xlarge + ConstraintDescription: Must be a valid database Instance Type. + Default: db.m5.large + Type: String + DatabaseAllocatedStorage: + Description: Size in gigabytes of the available storage for the database instance. + MinValue: 5 + MaxValue: 1024 + Default: 10 + Type: Number + DatabasePreferredAz: + Description: Preferred availability zone for Amazon RDS primary instance + Type: String + Default: '' + MultiAzDatabase: + Description: Choose false to create an Amazon RDS instance in a single Availability Zone. + ConstraintDescription: True or False + AllowedValues: + - "true" + - "false" + Default: "true" + Type: String + QsS3BucketName: + Description: S3 bucket name for the Quick Start assets. This string can include + numbers, lowercase letters, and hyphens (-). It cannot start + or end with a hyphen (-). + AllowedPattern: ^[0-9a-z]+([0-9a-z-]*[0-9a-z])*$ + ConstraintDescription: Quick Start bucket name can include numbers, lowercase + letters, and hyphens (-). It cannot start or end with a hyphen (-). + Default: jfrog-aws + 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: artifactory7/latest/ + Type: String + QsS3BucketRegion: + Default: 'us-east-1' + Description: AWS Region where the Quick Start S3 bucket (QSS3BucketName) is hosted. If you use your own bucket, you must specify your own value. + Type: String + InstallXray: + Description: Choose true to install JFrog Xray instance(s). + ConstraintDescription: True or False + AllowedValues: + - "true" + - "false" + Default: "true" + Type: String + XrayVersion: + Description: The version of Xray that you want to deploy into the Quick Start. + AllowedPattern: ^(([0-9]|[1-9][0-9])\.){2}([1-9][0-9]|[0-9])$ + ConstraintDescription: A version that matches X.X.X per Xray releases. + Default: 3.21.2 + Type: String + XrayNumberOfInstances: + Description: The number of Xray instances servers to complete your + HA deployment. The minimum number is one; the maximum is seven. + Do not select more than instances than you have licenses for. + MinValue: 1 + MaxValue: 7 + Default: 1 + Type: Number + XrayInstanceType: + Description: The EC2 instance type for the Xray instances. + AllowedValues: + - c5.2xlarge + - c5.4xlarge + ConstraintDescription: Must contain valid instance type. + Default: c5.2xlarge + Type: String + XrayDatabaseUser: + Description: The login ID for the Xray database user. + MinLength: '1' + MaxLength: '16' + AllowedPattern: ^[a-zA-Z]([a-zA-Z0-9])+$ + ConstraintDescription: 1 to 16 alphanumeric characters. First character must be a letter. + Default: xray + Type: String + XrayDatabasePassword: + Description: The password for the Xray database user. + AllowedPattern: ^[^ \\']+$ + MinLength: '8' + MaxLength: '12' + ConstraintDescription: Must be at least 8 and no more than + 12 characters containing letters and (minimum 1 capital letter), numbers and + symbols. + NoEcho: 'true' + Type: String + +Conditions: + EnableBastion: !Equals [!Ref 'ProvisionBastionHost', 'Enabled'] + IsArtifactory: !Not [!Equals [!Ref ArtifactoryProduct, 'JFrog-Container-Registry']] + HasSecondaryNodes: !Not [!Equals [!Ref NumberOfSecondary, '0']] + DefaultJava: !Equals [!Ref DefaultJavaMemSettings, "true"] + UsingDefaultBucket: !Equals [!Ref QsS3BucketName, 'aws-quickstart'] + EnableXray: !Equals [!Ref InstallXray, 'true'] + SmCertNameNotExists: !Equals [!Ref 'SmCertName', ''] + SmCertNameExists: !Not [!Equals [!Ref 'SmCertName', '']] + +Resources: + BastionRole: + Condition: EnableBastion + Type: "AWS::IAM::Role" + Properties: + AssumeRolePolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Principal: + Service: ec2.amazonaws.com + Action: sts:AssumeRole + Policies: + - PolicyName: QSBucketAccess + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: s3:GetObject + Resource: !Sub "arn:${AWS::Partition}:s3:::${QsS3BucketName}/*" + - Effect: Allow + Action: + - logs:CreateLogStream + - logs:GetLogEvents + - logs:PutLogEvents + - logs:DescribeLogGroups + - logs:DescribeLogStreams + - logs:PutRetentionPolicy + - logs:PutMetricFilter + - logs:CreateLogGroup + Resource: !Sub "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:*:*" + - Effect: Allow + Action: + - ec2:AssociateAddress + - ec2:DescribeAddresses + Resource: "*" + BastionStack: + Condition: EnableBastion + Type: AWS::CloudFormation::Stack + Properties: + TemplateURL: !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QsS3KeyPrefix}submodules/quickstart-linux-bastion/templates/linux-bastion.template + - S3Bucket: !If [UsingDefaultBucket, !Sub '${QsS3BucketName}-${AWS::Region}', !Ref 'QsS3BucketName'] + S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref 'QsS3BucketRegion'] + Parameters: + VPCID: !Ref VpcId + PublicSubnet1ID: !Ref PublicSubnet1Id + PublicSubnet2ID: !Ref PublicSubnet2Id + KeyPairName: !Ref KeyPairName + QSS3BucketName: !Ref QsS3BucketName + QSS3KeyPrefix: !Sub '${QsS3KeyPrefix}submodules/quickstart-linux-bastion/' + QSS3BucketRegion: !Ref QsS3BucketRegion + RemoteAccessCIDR: !Ref RemoteAccessCidr + BastionInstanceType: !Ref BastionInstanceType + RootVolumeSize: !Ref BastionRootVolumeSize + BastionAMIOS: !Ref BastionOs + EnableTCPForwarding: !Ref BastionEnableTcpForwarding + EnableX11Forwarding: !Ref BastionEnableX11Forwarding + AlternativeIAMRole: !Ref BastionRole + NumBastionHosts: !Ref NumBastionHosts + + ArtifactoryCoreInfraStack: + Type: AWS::CloudFormation::Stack + Properties: + TemplateURL: !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QsS3KeyPrefix}templates/jfrog-artifactory-core-infrastructure.template.yaml + - S3Bucket: !If [UsingDefaultBucket, !Sub '${QsS3BucketName}-${AWS::Region}', !Ref 'QsS3BucketName'] + S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref 'QsS3BucketRegion'] + Parameters: + AvailabilityZones: + Fn::Join: + - ',' + - Ref: AvailabilityZones + VpcId: !Ref VpcId + VpcCidr: !Ref VpcCidr + PrivateSubnet1Cidr: !Ref PrivateSubnet1Cidr + PrivateSubnet2Cidr: !Ref PrivateSubnet2Cidr + PrivateSubnet3Cidr: !Ref PrivateSubnet2Cidr # This should end up in no new rule but required for EKS + SubnetIds: !Join [",", [!Ref PrivateSubnet1Id, !Ref PrivateSubnet2Id]] + DatabaseAllocatedStorage: !Ref DatabaseAllocatedStorage + DatabasePreferredAz: !Ref DatabasePreferredAz + MultiAzDatabase: !Ref MultiAzDatabase + DatabaseEngine: !Ref DatabaseEngine + DatabaseUser: !Ref DatabaseUser + DatabasePassword: !Ref DatabasePassword + DatabaseInstance: !Ref DatabaseInstance + DatabaseName: !Ref DatabaseName + InstanceType: !Ref InstanceType + ArtifactoryHostRole: !Ref ArtifactoryHostRole + VolumeSize: !Ref VolumeSize + ArtifactoryElb: + Type: AWS::ElasticLoadBalancingV2::LoadBalancer + Properties: + IpAddressType: ipv4 + Scheme: !Ref ELBScheme + Subnets: + - !Ref PublicSubnet1Id + - !Ref PublicSubnet2Id + Type: network + # Type: application + ArtifactorySslTargetGroup: + Type: AWS::ElasticLoadBalancingV2::TargetGroup + Properties: + HealthCheckEnabled: True + HealthCheckIntervalSeconds: 30 + HealthCheckProtocol: TCP + HealthCheckTimeoutSeconds: 10 + HealthyThresholdCount: 3 + HealthCheckPort: "8082" + Port: 443 + Protocol: TCP + TargetType: instance + UnhealthyThresholdCount: 3 + VpcId: !Ref VpcId + ArtifactoryTargetGroup: + Type: AWS::ElasticLoadBalancingV2::TargetGroup + Properties: + HealthCheckEnabled: True + HealthCheckIntervalSeconds: 30 + HealthCheckProtocol: TCP + HealthCheckTimeoutSeconds: 10 + HealthyThresholdCount: 3 + HealthCheckPort: "8082" + Port: 80 + Protocol: TCP + TargetType: instance + UnhealthyThresholdCount: 3 + VpcId: !Ref VpcId + ArtifactorySslElbListener: + Type: AWS::ElasticLoadBalancingV2::Listener + Properties: + DefaultActions: + - TargetGroupArn: !Ref ArtifactorySslTargetGroup + Type: forward + LoadBalancerArn: !Ref ArtifactoryElb + Port: 443 + Protocol: TCP + ArtifactoryElbListener: + Type: AWS::ElasticLoadBalancingV2::Listener + Condition: SmCertNameNotExists + Properties: + DefaultActions: + - TargetGroupArn: !Ref ArtifactoryTargetGroup + Type: forward + LoadBalancerArn: !Ref ArtifactoryElb + Port: 80 + Protocol: TCP + ArtifactoryInternalElb: + Type: AWS::ElasticLoadBalancingV2::LoadBalancer + Properties: + IpAddressType: ipv4 + # Name: ArtifactoryInternal-ELB + Scheme: internal + Subnets: + - !Ref PrivateSubnet1Id + - !Ref PrivateSubnet2Id + Type: network + ArtifactoryInternalTargetGroup: + Type: AWS::ElasticLoadBalancingV2::TargetGroup + Properties: + HealthCheckEnabled: True + HealthCheckIntervalSeconds: 30 + HealthCheckProtocol: TCP + HealthCheckTimeoutSeconds: 10 + HealthyThresholdCount: 3 + HealthCheckPort: "8082" + # Name: artifactory-internal-http + Port: 80 + Protocol: TCP + TargetType: instance + UnhealthyThresholdCount: 3 + VpcId: !Ref VpcId + ArtifactoryInternalElbListener: + Type: AWS::ElasticLoadBalancingV2::Listener + Properties: + DefaultActions: + - TargetGroupArn: !Ref ArtifactoryInternalTargetGroup + Type: forward + LoadBalancerArn: !Ref ArtifactoryInternalElb + Port: 80 + Protocol: TCP + ArtifactoryEc2Sg: + Type: AWS::EC2::SecurityGroup + Properties: + Tags: + - Key: Name + Value: !Sub ${ArtifactoryProduct}-ec2-instances-sg + GroupDescription: SG for EC2 instances (also permits access using SSH from the bastion host) + VpcId: !Ref VpcId + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: 22 + ToPort: 22 + CidrIp: !Ref VpcCidr + - IpProtocol: tcp + FromPort: 80 + ToPort: 80 + CidrIp: !Ref VpcCidr + - IpProtocol: tcp + FromPort: 80 + ToPort: 80 + CidrIp: !Ref AccessCidr + - IpProtocol: tcp + FromPort: 443 + ToPort: 443 + CidrIp: !Ref AccessCidr + - IpProtocol: tcp + FromPort: 443 + ToPort: 443 + CidrIp: !Ref VpcCidr + - IpProtocol: tcp + FromPort: 8081 + ToPort: 8082 + CidrIp: !Ref VpcCidr + - IpProtocol: tcp + FromPort: 8046 + ToPort: 8046 + CidrIp: !Ref VpcCidr + SecurityGroupEgress: + - IpProtocol: "-1" + CidrIp: 0.0.0.0/0 + ArtifactoryHostRole: + Type: AWS::IAM::Role + Properties: + Path: / + AssumeRolePolicyDocument: + Statement: + - Action: + - 'sts:AssumeRole' + Principal: + Service: + - ec2.amazonaws.com + Effect: Allow + Version: 2012-10-17 + ManagedPolicyArns: + - !Sub 'arn:${AWS::Partition}:iam::aws:policy/service-role/AmazonEC2RoleforSSM' + Policies: + - PolicyName: "JFrogAMI-policy" + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: "Allow" + Action: "ec2:Describe*" + Resource: "*" + - Effect: "Allow" + Action: "ec2:AttachVolume" + Resource: "*" + - Effect: "Allow" + Action: "ec2:DetachVolume" + Resource: "*" + - Effect: "Allow" + Action: + - "s3:GetObject" + - "s3:ListObject" + - "s3:ListBucket" + Resource: "*" + - PolicyName: 'CloudWatch-policy' + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: "Allow" + Action: + - "logs:CreateLogGroup" + - "logs:CreateLogStream" + - "logs:PutLogEvents" + - "logs:DescribeLogStreams" + Resource: "arn:aws:logs:*:*:*" + - Effect: "Allow" + Action: + - "s3:GetObject" + Resource: "*" + - PolicyName: 'SecretsMaanger-policy' + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: "Allow" + Action: + - "secretsmanager:GetSecretValue" + Resource: "arn:aws:secretsmanager:*:*:secret:*" + ArtifactoryHostProfile: + Type: AWS::IAM::InstanceProfile + Properties: + InstanceProfileName: !Ref ArtifactoryHostRole + Roles: + - !Ref ArtifactoryHostRole + Path: / + ArtifactoryPrimary: + Type: AWS::CloudFormation::Stack + Properties: + TemplateURL: !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QsS3KeyPrefix}templates/jfrog-artifactory-ec2-instance.template.yaml + - S3Bucket: !If [UsingDefaultBucket, !Sub '${QsS3BucketName}-${AWS::Region}', !Ref 'QsS3BucketName'] + S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref 'QsS3BucketRegion'] + Parameters: + PrivateSubnetIds: !Join [',', [!Ref PrivateSubnet1Id]] + MinScalingNodes: '1' # Always have 1 PrimaryNode + MaxScalingNodes: '1' # Always have 1 PrimaryNode + DeploymentTag: !If [IsArtifactory, "ArtifactoryPrimary", "JcrPrimary"] + HostRole: !Ref ArtifactoryHostRole + QsS3BucketName: !Ref QsS3BucketName + QsS3KeyPrefix: !Ref QsS3KeyPrefix + QsS3Uri: !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QsS3KeyPrefix} + - S3Bucket: !If + - UsingDefaultBucket + - !Sub 'aws-quickstart-${AWS::Region}' + - !Ref 'QsS3BucketName' + S3Region: !If + - UsingDefaultBucket + - !Ref 'AWS::Region' + - !Ref 'QsS3BucketRegion' + ArtifactoryProduct: !Ref ArtifactoryProduct + ArtifactoryLicensesSecretName: !Ref SmLicenseName + ArtifactoryServerName: !Ref ArtifactoryServerName + EnableSSL: !If [SmCertNameExists, true, false] + Certificate: !If [SmCertNameExists, !Sub '{{resolve:secretsmanager:${SmCertName}:SecretString:Certificate}}', ''] + CertificateKey: !If [SmCertNameExists, !Sub '{{resolve:secretsmanager:${SmCertName}:SecretString:CertificateKey}}', ''] + CertificateDomain: !If [SmCertNameExists, !Sub '{{resolve:secretsmanager:${SmCertName}:SecretString:CertificateDomain}}', ''] + ArtifactoryS3Bucket: !GetAtt ArtifactoryCoreInfraStack.Outputs.S3Bucket + DatabaseUrl: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseUrl + DatabaseDriver: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseDriver + DatabasePlugin: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabasePlugin + DatabasePluginUrl: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabasePluginUrl + DatabaseType: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseType + DatabaseUser: !Ref DatabaseUser + DatabasePassword: !Ref DatabasePassword + ArtifactoryPrimary: true + MasterKey: !Ref MasterKey + ExtraJavaOptions: !If [DefaultJava, !Sub "${ArtifactoryCoreInfraStack.Outputs.JavaOpts} ${ExtraJavaOptions}", !Ref ExtraJavaOptions] + ArtifactoryVersion: !Ref ArtifactoryVersion + KeyPairName: !Ref KeyPairName + HostProfile: !Ref ArtifactoryHostProfile + SecurityGroups: !Ref ArtifactoryEc2Sg + InstanceType: !Ref InstanceType + PrimaryVolume: !GetAtt ArtifactoryCoreInfraStack.Outputs.ArtifactoryEbsVolume + VolumeSize: !Ref VolumeSize + TargetGroupARN: !Ref ArtifactoryTargetGroup + SSLTargetGroupARN: !Ref ArtifactorySslTargetGroup + InternalTargetGroupARN: !Ref ArtifactoryInternalTargetGroup + + ArtifactorySecondary: + Condition: HasSecondaryNodes + DependsOn: ArtifactoryPrimary + Type: AWS::CloudFormation::Stack + Properties: + TemplateURL: !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QsS3KeyPrefix}templates/jfrog-artifactory-ec2-instance.template.yaml + - S3Bucket: !If [UsingDefaultBucket, !Sub '${QsS3BucketName}-${AWS::Region}', !Ref 'QsS3BucketName'] + S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref 'QsS3BucketRegion'] + Parameters: + PrivateSubnetIds: !Join [',', [!Ref PrivateSubnet1Id, !Ref PrivateSubnet2Id]] + MinScalingNodes: !Ref NumberOfSecondary + MaxScalingNodes: !Ref NumberOfSecondary + DeploymentTag: ArtifactorySecondary + HostRole: !Ref ArtifactoryHostRole + ArtifactoryProduct: !Ref ArtifactoryProduct + ArtifactoryLicensesSecretName: !Ref SmLicenseName + ArtifactoryServerName: !Ref ArtifactoryServerName + EnableSSL: !If [SmCertNameExists, true, false] + Certificate: !If [SmCertNameExists, !Sub '{{resolve:secretsmanager:${SmCertName}:SecretString:Certificate}}', ''] + CertificateKey: !If [SmCertNameExists, !Sub '{{resolve:secretsmanager:${SmCertName}:SecretString:CertificateKey}}', ''] + CertificateDomain: !If [SmCertNameExists, !Sub '{{resolve:secretsmanager:${SmCertName}:SecretString:CertificateDomain}}', ''] + ArtifactoryS3Bucket: !GetAtt ArtifactoryCoreInfraStack.Outputs.S3Bucket + DatabaseUrl: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseUrl + DatabaseDriver: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseDriver + DatabasePlugin: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabasePlugin + DatabasePluginUrl: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabasePluginUrl + DatabaseType: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseType + DatabaseUser: !Ref DatabaseUser + DatabasePassword: !Ref DatabasePassword + ArtifactoryPrimary: false + MasterKey: !Ref MasterKey + ExtraJavaOptions: !If [DefaultJava, !Sub "${ArtifactoryCoreInfraStack.Outputs.JavaOpts} ${ExtraJavaOptions}", !Ref ExtraJavaOptions] + ArtifactoryVersion: !Ref ArtifactoryVersion + KeyPairName: !Ref KeyPairName + HostProfile: !Ref ArtifactoryHostProfile + SecurityGroups: !Ref ArtifactoryEc2Sg + InstanceType: !Ref InstanceType + PrimaryVolume: !GetAtt ArtifactoryCoreInfraStack.Outputs.ArtifactoryEbsVolume + VolumeSize: !Ref VolumeSize + TargetGroupARN: !Ref ArtifactoryTargetGroup + SSLTargetGroupARN: !Ref ArtifactorySslTargetGroup + InternalTargetGroupARN: !Ref ArtifactoryInternalTargetGroup + QsS3BucketName: !Ref QsS3BucketName + QsS3KeyPrefix: !Ref QsS3KeyPrefix + QsS3Uri: !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QsS3KeyPrefix} + - S3Bucket: !If + - UsingDefaultBucket + - !Sub 'aws-quickstart-${AWS::Region}' + - !Ref 'QsS3BucketName' + S3Region: !If + - UsingDefaultBucket + - !Ref 'AWS::Region' + - !Ref 'QsS3BucketRegion' + XrayHostRole: + Condition: EnableXray + Type: AWS::IAM::Role + Properties: + Path: / + AssumeRolePolicyDocument: + Statement: + - Action: + - 'sts:AssumeRole' + Principal: + Service: + - ec2.amazonaws.com + Effect: Allow + Version: 2012-10-17 + ManagedPolicyArns: + - !Sub 'arn:${AWS::Partition}:iam::aws:policy/service-role/AmazonEC2RoleforSSM' + Policies: + - PolicyName: "JFrogAMI-policy" + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: "Allow" + Action: "ec2:Describe*" + Resource: "*" + - Effect: "Allow" + Action: "ec2:AttachVolume" + Resource: "*" + - Effect: "Allow" + Action: "ec2:DetachVolume" + Resource: "*" + - Effect: "Allow" + Action: + - "s3:GetObject" + - "s3:ListObject" + - "s3:ListBucket" + Resource: "*" + - PolicyName: 'CloudWatch-policy' + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: "Allow" + Action: + - "logs:CreateLogGroup" + - "logs:CreateLogStream" + - "logs:PutLogEvents" + - "logs:DescribeLogStreams" + Resource: "arn:aws:logs:*:*:*" + - Effect: "Allow" + Action: + - "s3:GetObject" + Resource: "*" + XrayHostProfile: + Condition: EnableXray + Type: AWS::IAM::InstanceProfile + Properties: + InstanceProfileName: !Ref XrayHostRole + Roles: + - !Ref XrayHostRole + Path: / + XrayExistingVpcStack: + Condition: EnableXray + DependsOn: ArtifactoryPrimary + Type: AWS::CloudFormation::Stack + Properties: + TemplateURL: !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QsS3KeyPrefix}templates/jfrog-xray-ec2-instance.template.yaml + - S3Bucket: !If [UsingDefaultBucket, !Sub '${QsS3BucketName}-${AWS::Region}', !Ref 'QsS3BucketName'] + S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref 'QsS3BucketRegion'] + Parameters: + PrivateSubnet1Id: !Ref PrivateSubnet1Id + PrivateSubnet2Id: !Ref PrivateSubnet2Id + KeyPairName: !Ref KeyPairName + MinScalingNodes: !Ref XrayNumberOfInstances + MaxScalingNodes: !Ref XrayNumberOfInstances + DeploymentTag: 'xray' + ArtifactoryProduct: !Ref ArtifactoryProduct + QsS3BucketName: !Ref QsS3BucketName + QsS3KeyPrefix: !Ref QsS3KeyPrefix + QsS3Uri: !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QsS3KeyPrefix} + - S3Bucket: !If + - UsingDefaultBucket + - !Sub 'aws-quickstart-${AWS::Region}' + - !Ref 'QsS3BucketName' + S3Region: !If + - UsingDefaultBucket + - !Ref 'AWS::Region' + - !Ref 'QsS3BucketRegion' + DatabaseDriver: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseDriver + DatabaseType: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseType + DatabaseUser: !Ref DatabaseUser + DatabasePassword: !Ref DatabasePassword + MasterKey: !Ref MasterKey + SecurityGroups: !Ref ArtifactoryEc2Sg + VolumeSize: !Ref VolumeSize + ExtraJavaOptions: !GetAtt ArtifactoryCoreInfraStack.Outputs.JavaOpts + XrayInstanceType: !Ref XrayInstanceType + JfrogInternalUrl: !Sub "http://${ArtifactoryInternalElb.DNSName}" + XrayDatabaseUser: !Ref XrayDatabaseUser + XrayDatabasePassword: !Ref XrayDatabasePassword + XrayMasterDatabaseUrl: !GetAtt ArtifactoryCoreInfraStack.Outputs.XrayMasterDatabaseUrl + XrayDatabaseUrl: !GetAtt ArtifactoryCoreInfraStack.Outputs.XrayDatabaseUrl + XrayVersion: !Ref XrayVersion + XrayHostRole: !Ref XrayHostRole + XrayHostProfile: !Ref XrayHostProfile +Outputs: + ArtifactoryUrl: + Description: URL of the ELB to access Artifactory + Value: !If [SmCertNameExists, !Sub "https://${ArtifactoryElb.DNSName}", !Sub "http://${ArtifactoryElb.DNSName}"] + Export: + Name: !Sub '${AWS::StackName}-ArtifactoryUrl' + ArtifactoryInternalUrl: + Description: URL of the internal ELB to access Artifactory + Value: !Sub "http://${ArtifactoryInternalElb.DNSName}" + Export: + Name: !Sub '${AWS::StackName}-ArtifactoryInternalUrl' + DatabaseType: + Description: Type of database + Value: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseType + Export: + Name: !Sub '${AWS::StackName}-DatabaseType' + DatabaseDriver: + Description: Database driver + Value: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseDriver + Export: + Name: !Sub '${AWS::StackName}-DatabaseDriver' + DatabaseUrl: + Description: Database driver + Value: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseUrl + Export: + Name: !Sub '${AWS::StackName}-DatabaseUrl' + ArtifactoryTargetGroup: + Description: Artifactory target group + Value: !Ref ArtifactoryTargetGroup + Export: + Name: !Sub '${AWS::StackName}-ArtifactoryTargetGroup' + ArtifactorySslTargetGroup: + Description: Artifactory SSL target group + Value: !Ref ArtifactorySslTargetGroup + Export: + Name: !Sub '${AWS::StackName}-ArtifactorySslTargetGroup' + ArtifactoryEc2Sg: + Description: Artifactory EC2 sercurity group + Value: !Ref ArtifactoryEc2Sg + Export: + Name: !Sub '${AWS::StackName}-ArtifactoryEc2Sg' + BastionIp: + Value: !If + - EnableBastion + - !GetAtt BastionStack.Outputs.EIP1 + - "" + XrayMasterDatabaseUrl: + Description: Database driver + Value: !GetAtt ArtifactoryCoreInfraStack.Outputs.XrayMasterDatabaseUrl + Export: + Name: !Sub '${AWS::StackName}-XrayMasterDatabaseUrl' + XrayDatabaseUrl: + Description: Database driver + Value: !GetAtt ArtifactoryCoreInfraStack.Outputs.XrayDatabaseUrl + Export: + Name: !Sub '${AWS::StackName}-XrayDatabaseUrl' diff --git a/Amazon/artifactory7/latest/templates/jfrog-artifactory-ec2-instance.template.yaml b/Amazon/artifactory7/latest/templates/jfrog-artifactory-ec2-instance.template.yaml new file mode 100644 index 0000000..1c7e1ee --- /dev/null +++ b/Amazon/artifactory7/latest/templates/jfrog-artifactory-ec2-instance.template.yaml @@ -0,0 +1,433 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: "Deploys the EC2 Autoscaling, LaunchConfig and Instance for Artifactory (qs-1qpmmjh5o)" +Parameters: + PrivateSubnetIds: + Type: List + MinScalingNodes: + Type: Number + MaxScalingNodes: + Type: Number + DeploymentTag: + Type: String + HostRole: + Type: String + ArtifactoryProduct: + Description: JFrog Artifactory product you want to install into an AMI. + AllowedValues: + - JFrog-Artifactory-Pro + - JFrog-Artifactory-Enterprise + - JFrog-Container-Registry + Default: JFrog-Artifactory-Enterprise + Type: String + QsS3BucketName: + Type: String + QsS3KeyPrefix: + Type: String + QsS3Uri: + Type: String + ArtifactoryLicensesSecretName: + Type: String + ArtifactoryServerName: + Type: String + Certificate: + Type: String + CertificateKey: + Type: String + NoEcho: 'true' + CertificateDomain: + Type: String + EnableSSL: + Type: String + 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 + PrimaryVolume: + Type: String + VolumeSize: + Type: Number + UserDataDirectory: + Description: Directory to store Artifactory data. Can be used to store data (via symlink) in detachable volume + Type: String + Default: '/artifactory-user-data' + +# 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: + CentOS7HVM: "ami-00a5245b4816c38e6" + ap-northeast-2: + CentOS7HVM: "ami-00dc207f8ba6dc919" + ap-south-1: + CentOS7HVM: "ami-0ad42f4f66f6c1cc9" + ap-southeast-1: + CentOS7HVM: "ami-05b3bcf7f311194b3" + ap-southeast-2: + CentOS7HVM: "ami-02fd0b06f06d93dfc" + ca-central-1: + CentOS7HVM: "ami-07423fb63ea0a0930" + eu-central-1: + CentOS7HVM: "ami-0cfbf4f6db41068ac" + eu-west-1: + CentOS7HVM: "ami-08935252a36e25f85" + sa-east-1: + CentOS7HVM: "ami-05145e0b28ad8e0b2" + us-east-1: + CentOS7HVM: "ami-0affd4508a5d2481b" + us-east-2: + CentOS7HVM: "ami-01e36b7901e884a10" + us-west-1: + CentOS7HVM: "ami-098f55b4287a885ba" + us-west-2: + CentOS7HVM: "ami-0bc06212a56393ee1" + ArtifactoryProductMap: + JFrog-Container-Registry: + "7153": "Jcr7153" + flavor: "jcr" + haEabled: false + product: "jcr" + JFrog-Artifactory-Enterprise: + "7153": "Artifactory7153" + flavor: "pro" + haEabled: true + product: "artifactory" + JFrog-Artifactory-Pro: + "7153": "Artifactory7153" + flavor: "pro" + haEabled: false + product: "artifactory" + +Conditions: + IsSecondary: !Equals [!Ref ArtifactoryPrimary, 'false'] + +Resources: + ArtifactoryScalingGroup: + Type: AWS::AutoScaling::AutoScalingGroup + Properties: + LaunchConfigurationName: !Ref ArtifactoryLaunchConfiguration + VPCZoneIdentifier: !Ref PrivateSubnetIds + MinSize: !Ref MinScalingNodes + MaxSize: !Ref MaxScalingNodes + Cooldown: '300' + DesiredCapacity: !Ref MinScalingNodes + TargetGroupARNs: + - !Ref TargetGroupARN + - !Ref SSLTargetGroupARN + - !Ref InternalTargetGroupARN + HealthCheckType: ELB + HealthCheckGracePeriod: 1800 + Tags: + - Key: Name + Value: !Ref DeploymentTag + PropagateAtLaunch: true + - Key: ArtifactoryVersion + Value: !Ref ArtifactoryVersion + PropagateAtLaunch: true + TerminationPolicies: + - OldestInstance + - Default + CreationPolicy: + ResourceSignal: + Count: !Ref MinScalingNodes + Timeout: PT60M + + ArtifactoryLaunchConfiguration: + Type: AWS::AutoScaling::LaunchConfiguration + Metadata: + AWS::CloudFormation::Authentication: + S3AccessCreds: + type: S3 + roleName: + - !Ref HostRole # !Ref ArtifactoryHostRole + buckets: + - !Ref QsS3BucketName + AWS::CloudFormation::Init: + configSets: + jfrog_ami_setup: + - "config-cloudwatch" + - "config-ansible-art-ami" + - "config-artifactory-primary" + - "secure-artifactory" + artifactory_install: + - "config-cloudwatch" + - "config-artifactory-primary" + - "secure-artifactory" + config-cloudwatch: + files: + /root/cloudwatch.conf: + content: | + [general] + state_file = /var/awslogs/state/agent-state + + [/var/log/messages] + file = /var/log/messages + log_group_name = /artifactory/instances/{instance_id} + log_stream_name = /var/log/messages/ + datetime_format = %b %d %H:%M:%S + + [/var/log/jfrog-ami-setup.log] + file = /var/log/messages + log_group_name = /artifactory/instances/{instance_id} + log_stream_name = /var/log/jfrog-ami-setup.log + datetime_format = %b %d %H:%M:%S + + [/var/log/jfrog-ami-artifactory.log] + file = /var/log/messages + log_group_name = /artifactory/instances/{instance_id} + log_stream_name = /var/log/jfrog-ami-artifactory.log + datetime_format = %b %d %H:%M:%S + mode: "0400" + 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: false + artifactory_flavour: "pro" + artifactory_ha_enabled: false + artifactory_tar: "https://releases.jfrog.io/artifactory/artifactory-pro/org/artifactory/pro/jfrog-artifactory-pro/${ArtifactoryVersion}/jfrog-artifactory-pro-${ArtifactoryVersion}-linux.tar.gz" + artifactory_version: ${ArtifactoryVersion} + db_download_url: "https://jdbc.postgresql.org/download/postgresql-42.2.12.jar" + db_type: "postgresql" + db_driver: "org.postgresql.Driver" + mode: "0400" + config-artifactory-primary: + files: + /root/attach_volume.sh: + content: !Sub | + #!/usr/bin/env bash + IS_PRIMARY="${ArtifactoryPrimary}" + + if [[ $IS_PRIMARY != "true" ]]; then + echo 'Not primary node. Skipping EBS volume attachment.' + lsblk # debug + exit 0 + fi + + echo "Using primary volume ID ${PrimaryVolume}" + VOLUME_ID="${PrimaryVolume}" + echo "VOLUME_ID: $VOLUME_ID" + if [[ -z "$VOLUME_ID" ]]; then + echo 'Invalid $VOLUME_ID' + exit 1 + fi + + # Get instance id from AWS + INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id) + + # Attach the volume created by another CFT + # the device name should become /dev/nvme1n1 + # See: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nvme-ebs-volumes.html + echo "Attaching volume $VOLUME_ID to instance $INSTANCE_ID" + /var/awslogs/bin/aws ec2 attach-volume --volume-id $VOLUME_ID --instance-id $INSTANCE_ID --device /dev/xvdf --region ${AWS::Region} + + echo "Wait for volume $VOLUME_ID to attach" + sleep 30 # Give volume time to attach + lsblk # debug + mode: "0770" + /root/.jfrog_ami/artifactory.yml: + content: !Sub + - | + # Base install for Artifactory + - import_playbook: site-artifactory.yml + vars: + artifactory_product: ${product} + artifactory_flavour: ${flavor} + artifactory_ha_enabled: ${ha_enabled} + artifactory_is_primary: ${ArtifactoryPrimary} + artifactory_server_name: ${ArtifactoryServerName} + server_name: ${ArtifactoryServerName}.${CertificateDomain} + use_custom_data_directory: true + custom_data_directory: "${UserDataDirectory}" + s3_region: ${AWS::Region} + 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} + 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: ${DatabasePassword} + artifactory_java_db_drivers: + - name: ${DatabasePlugin} + url: ${DatabasePluginUrl} + owner: artifactory + group: artifactory + product_id: 'CloudFormation_SP_EC2/1.0.0' + - flavor: !FindInMap [ArtifactoryProductMap, !Ref ArtifactoryProduct, flavor] + ha_enabled: !FindInMap [ArtifactoryProductMap, !Ref ArtifactoryProduct, haEabled] + product: !FindInMap [ArtifactoryProductMap, !Ref ArtifactoryProduct, product] + mode: "0400" + /root/.vault_pass.txt: + content: !Sub | + ${DatabasePassword} + 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: + KeyName: !Ref KeyPairName + IamInstanceProfile: !Ref HostProfile + ImageId: !FindInMap + - AWSAMIRegionMap + - !Ref AWS::Region + - 'CentOS7HVM' + SecurityGroups: + - !Ref SecurityGroups + BlockDeviceMappings: + !If + - IsSecondary + - - DeviceName: /dev/xvda + Ebs: + VolumeSize: !Ref VolumeSize + VolumeType: gp2 + DeleteOnTermination: true + Encrypted: true + - !Ref AWS::NoValue + InstanceType: !Ref InstanceType + 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} + + # Update OS + yum update -y + + # Install git + yum install -y epel-release git policycoreutils-python + + yum update --security -y 2>&1 | tee /var/log/userdata.yum_security_update.log + + yum install -y jq 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 + + pip install awscli 2>&1 | tee /var/log/userdata.awscli_install.log + + pip install ansible 2>&1 | tee /var/log/userdata.ansible_install.log + + mkdir ~/.jfrog_ami + + aws s3 --region ${AWS::Region} sync s3://${QsS3BucketName}/${QsS3KeyPrefix}cloudInstallerScripts/ ~/.jfrog_ami/ || cfn_fail + + setsebool httpd_can_network_connect 1 -P + + # 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 + + cfn-init -v --stack ${AWS::StackName} --resource ArtifactoryLaunchConfiguration --configsets jfrog_ami_setup --region ${AWS::Region} || cfn_fail + + # Setup CloudWatch Agent + curl https://s3.amazonaws.com/aws-cloudwatch/downloads/latest/awslogs-agent-setup.py -O + chmod +x ./awslogs-agent-setup.py + ./awslogs-agent-setup.py -n -r ${AWS::Region} -c /root/cloudwatch.conf 2>&1 | tee /var/log/userdata.cloudwatch_agent_install.log + + /root/attach_volume.sh || cfn_fail + + ansible-galaxy collection install community.general ansible.posix + + aws secretsmanager get-secret-value --secret-id ${ArtifactoryLicensesSecretName} --region ${AWS::Region} | jq -r '{"artifactory_licenses":(.SecretString | fromjson )}' > ~/.jfrog_ami/licenses.json || cfn_fail + + ansible-playbook /root/.jfrog_ami/jfrog-ami-setup.yml --vault-id /root/.vault_pass.txt 2>&1 | tee /var/log/jfrog-ami-setup.log || cfn_fail + ansible-playbook /root/.jfrog_ami/artifactory.yml -e "@~/.jfrog_ami/licenses.json" --vault-id /root/.vault_pass.txt 2>&1 | tee /var/log/jfrog-ami-artifactory.log || cfn_fail + + rm -rf /root/.secureit.sh + + cfn_success &> /var/log/cfn_success.log + cfn_success || cfn_fail diff --git a/Amazon/artifactory7/latest/templates/jfrog-artifactory-ec2-master.template.yaml b/Amazon/artifactory7/latest/templates/jfrog-artifactory-ec2-master.template.yaml new file mode 100644 index 0000000..3556572 --- /dev/null +++ b/Amazon/artifactory7/latest/templates/jfrog-artifactory-ec2-master.template.yaml @@ -0,0 +1,612 @@ +AWSTemplateFormatVersion: '2010-09-09' +Description: 'JFrog Artifactory Quick Start Deployment (qs-1qpmmjh2f)' +Metadata: + QuickStartDocumentation: + EntrypointName: "Launch into a new VPC" + AWS::CloudFormation::Interface: + ParameterGroups: + - Label: + default: Security configuration + Parameters: + - KeyPairName + - AccessCidr + - RemoteAccessCidr + - Label: + default: Network configuration + Parameters: + - AvailabilityZones + - VpcCidr + - PrivateSubnet1Cidr + - PrivateSubnet2Cidr + - PublicSubnet1Cidr + - PublicSubnet2Cidr + - Label: + default: Bastion configuration + Parameters: + - ProvisionBastionHost + - BastionInstanceType + - BastionOs + - BastionRootVolumeSize + - BastionEnableTcpForwarding + - NumBastionHosts + - BastionEnableX11Forwarding + - Label: + default: Amazon EC2 configuration + Parameters: + - VolumeSize + - InstanceType + - Label: + default: JFrog Artifactory configuration + Parameters: + - ArtifactoryProduct + - ArtifactoryVersion + - NumberOfSecondary + - SmLicenseName + - SmCertName + - ArtifactoryServerName + - MasterKey + - ExtraJavaOptions + - DefaultJavaMemSettings + - Label: + default: Amazon RDS configuration + Parameters: + - DatabaseName + - DatabaseEngine + - DatabaseUser + - DatabasePassword + - DatabaseInstance + - DatabaseAllocatedStorage + - DatabasePreferredAz + - MultiAzDatabase + - Label: + default: AWS Quick Start configuration + Parameters: + - QsS3BucketName + - QsS3KeyPrefix + - QsS3BucketRegion + - Label: + default: JFrog Xray Configuration + Parameters: + - InstallXray + - XrayVersion + - XrayNumberOfInstances + - XrayInstanceType + - XrayDatabaseUser + - XrayDatabasePassword + ParameterLabels: + AvailabilityZones: + default: Availability Zones + KeyPairName: + default: SSH key name + PrivateSubnet1Cidr: + default: Private subnet 1 CIDR + PrivateSubnet2Cidr: + default: Private subnet 2 CIDR + PublicSubnet1Cidr: + default: Public subnet 1 CIDR + PublicSubnet2Cidr: + default: Public subnet 2 CIDR + AccessCidr: + default: Permitted IP range + RemoteAccessCidr: + default: Remote access CIDR + VpcCidr: + default: VPC CIDR + ProvisionBastionHost: + default: Bastion instance + BastionInstanceType: + default: Bastion instance type + BastionRootVolumeSize: + default: Bastion root volume size + BastionEnableTcpForwarding: + default: Bastion enable TCP forwarding + BastionEnableX11Forwarding: + default: Bastion enable X11 forwarding + BastionOs: + default: Bastion operating system + NumBastionHosts: + default: Number of bastion instances + VolumeSize: + default: EBS root volume size + InstanceType: + default: EC2 instance type + NumberOfSecondary: + default: Secondary instances + ArtifactoryProduct: + default: Artifactory product to install + ArtifactoryVersion: + default: Artifactory version + SmLicenseName: + default: Artifactory licenses secret name + SmCertName: + default: Artifactory certificate secret name + ArtifactoryServerName: + default: Artifactory server name + MasterKey: + default: Master server key + ExtraJavaOptions: + default: Extra Java options + DefaultJavaMemSettings: + default: Default Java memory settings + DatabaseName: + default: Database name + DatabaseEngine: + default: Database engine + DatabaseUser: + default: Database user + DatabasePassword: + default: Database password + DatabaseInstance: + default: Database instance type + DatabaseAllocatedStorage: + default: Database allocated storage + DatabasePreferredAz: + default: Database preferred Availability Zone + MultiAzDatabase: + default: High-availability database + QsS3BucketName: + default: Quick Start S3 bucket name + QsS3KeyPrefix: + default: Quick Start S3 key prefix + QsS3BucketRegion: + default: Quick Start S3 bucket region + InstallXray: + default: Install JFrog Xray + XrayVersion: + default: Version of Xray to install + XrayNumberOfInstances: + default: Number of JFrog XrayNumberOfInstances + XrayInstanceType: + default: Xray instance type + XrayDatabaseUser: + default: Xray Database user + XrayDatabasePassword: + default: Xray Database password +Parameters: + VpcCidr: + Description: CIDR block for the VPC. + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.0.0/16 + Type: String + AvailabilityZones: + Description: List of Availability Zones to use for the subnets in the VPC. Two + Availability Zones are used for this deployment. + Type: List + KeyPairName: + Description: Name of an existing key pair, + which allows you to connect securely to your instance after it launches. + This is the key pair you created in your preferred Region. + Type: AWS::EC2::KeyPair::KeyName + PrivateSubnet1Cidr: + Description: CIDR block for private subnet 1 located in Availability Zone 1. + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.0.0/19 + Type: String + PrivateSubnet2Cidr: + Description: CIDR block for private subnet 2 located in Availability Zone 2. + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.32.0/19 + Type: String + PublicSubnet1Cidr: + Description: CIDR block for the public (DMZ) subnet 1 located in Availability + Zone 1. + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.128.0/20 + Type: String + PublicSubnet2Cidr: + Description: CIDR block for the public (DMZ) subnet 2 located in Availability + Zone 2. + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.144.0/20 + Type: String + AccessCidr: + Description: CIDR IP range permitted to access Artifactory. + It is recommended that you set this value to a trusted IP range. + For example, you may want to limit software access to your corporate network. + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$ + Type: String + RemoteAccessCidr: + Description: Remote CIDR range that allows you to connect to the bastion instance by using SSH. + It is recommended that you set this value to a trusted IP range. + For example, you may want to grant specific ranges from within your corporate network that use the SSH protocol. + 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 + ProvisionBastionHost: + Description: To skip creating a bastion instance, choose Disabled. Because Artifactory nodes are + created in private subnets, it's highly recommended to set this value to Enabled. + AllowedValues: + - "Enabled" + - "Disabled" + Default: "Enabled" + Type: String + BastionInstanceType: + Description: Size of the bastion instances. + AllowedValues: + - t3.nano + - t3.micro + - t3.small + - t3.medium + - t3.large + - m5.large + - m5.xlarge + - m5.2xlarge + - m5.4xlarge + Default: "t3.micro" + Type: String + BastionRootVolumeSize: + Description: Size of the root volume in the bastion instances. + Default: 10 + Type: Number + BastionEnableTcpForwarding: + Description: Choose whether to enable TCP forwarding via bootstrapping of the bastion + instance. + AllowedValues: + - "true" + - "false" + Default: "true" + Type: String + BastionEnableX11Forwarding: + Description: Choose true to enable X11 via bootstrapping of the bastion host. + Setting this value to true enables X Windows over SSH. + X11 forwarding can be useful, but it is also a security risk, so it's recommended + that you keep the default (false) setting. + AllowedValues: + - "true" + - "false" + Default: "false" + Type: String + BastionOs: + Description: Linux distribution for the Amazon Machine Image (AMI) to be used for the bastion instances. + AllowedValues: + - "Amazon-Linux2-HVM" + - "CentOS-7-HVM" + - "Ubuntu-Server-20.04-LTS-HVM" + - "SUSE-SLES-15-HVM" + Default: "Amazon-Linux2-HVM" + Type: String + NumBastionHosts: + Description: Number of bastion instances to create. + AllowedValues: + - '1' + - '2' + - '3' + - '4' + Default: '1' + Type: String + VolumeSize: + Description: Size in gigabytes of available storage (min 10GB). The Quick Start creates an + Amazon Elastic Block Store (Amazon EBS) volumes of this size. + Default: 200 + Type: Number + InstanceType: + Description: EC2 instance type for the Artifactory instances. + AllowedValues: + - m5.large + - m5.xlarge + - m5.2xlarge + - m5.4xlarge + - m5.8xlarge + - m5.12xlarge + - m5.16xlarge + - m5.24xlarge + - m5.metal + - m5d.large + - m5d.xlarge + - m5d.2xlarge + - m5d.4xlarge + - m5d.8xlarge + - m5d.12xlarge + - m5d.16xlarge + - m5d.24xlarge + - m5d.metal + - m5a.large + - m5a.xlarge + - m5a.2xlarge + - m5a.4xlarge + - m5a.8xlarge + - m5a.12xlarge + - m5a.16xlarge + - m5a.24xlarge + ConstraintDescription: Must contain valid instance type. + Default: m5.xlarge + Type: String + NumberOfSecondary: + Description: Number of secondary Artifactory servers to complete your + HA deployment. To align with Artifactory best practices, the minimum number + is two, and the maximum is seven. Do not select more instances than you + have licenses for. + AllowedValues: + - 0 + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + - 7 + Default: 2 + Type: Number + ArtifactoryProduct: + Description: JFrog Artifactory product you want to install into an AMI. + AllowedValues: + - JFrog-Artifactory-Pro + - JFrog-Artifactory-Enterprise + - JFrog-Container-Registry + Default: JFrog-Artifactory-Enterprise + Type: String + ArtifactoryVersion: + Description: Version of Artifactory that you want to deploy into the Quick Start. + To select the correct version, see the release notes at + https://www.jfrog.com/confluence/display/RTF/Release+Notes. + Default: 7.17.4 + Type: String + SmLicenseName: + Description: Secret name created in AWS Secrets Manager, which contains the Artifactory licenses. + Default: '' + Type: String + SmCertName: + Description: Secret name created in AWS Secrets Manager, which contains the SSL certificate and certificate key. + Default: '' + Type: String + ArtifactoryServerName: + Description: Name of your Artifactory server. Ensure that this matches your certificate. + Type: String + MasterKey: + Description: Master key for the Artifactory cluster. Generate a master key by using the command '$openssl rand -hex 16'. + AllowedPattern: ^[a-zA-Z0-9]+$ + MinLength: '1' + MaxLength: '64' + ConstraintDescription: Only capital or lowercase letters and numbers, with a Max of 64 characters. + NoEcho: 'true' + Type: String + ExtraJavaOptions: + Description: Set Java options to pass to the JVM for Artifactory. For more information, see the Artifactory + system requirements at https://www.jfrog.com/confluence/display/RTF/System+Requirements#SystemRequirements-RecommendedHardware. + Do not add Xms or Xmx settings without disabling DefaultJavaMemSettings. + Default: -Xss256k -XX:+UseG1GC + Type: String + DefaultJavaMemSettings: + Description: Choose false to overwrite the standard memory-calculation options to pass to the Artifactory JVM. + If you plan to overwrite them, ensure they are added to the ExtraJavaOptions to prevent the stack provision from failing. + ConstraintDescription: True or False + AllowedValues: + - "true" + - "false" + Default: "true" + Type: String + DatabaseName: + Description: Name of your database instance. The name must be unique across all instances + owned by your AWS account in the current Region. The database instance identifier is case-insensitive, + but it's stored in lowercase (as in "mydbinstance"). + AllowedPattern: ^[a-zA-Z]([a-zA-Z0-9])+$ + MinLength: '1' + MaxLength: '60' + ConstraintDescription: 1 to 60 alphanumeric characters First character must be a letter. + Default: artdb + Type: String + DatabaseEngine: + Description: Database engine that you want to run. + AllowedValues: + - Postgres + Default: Postgres + Type: String + DatabaseUser: + Description: Login ID for the master user of your database instance. + MinLength: '1' + MaxLength: '16' + AllowedPattern: ^[a-zA-Z]([a-zA-Z0-9])+$ + ConstraintDescription: 1 to 16 alphanumeric characters. The first character must be a letter. + Default: artifactory + Type: String + DatabasePassword: + Description: Password for the Artifactory database user. + AllowedPattern: ^[^ \\']+$ + MinLength: '8' + MaxLength: '12' + ConstraintDescription: Must be at least 8 and no more than + 12 characters containing letters and (minimum 1 capital letter), numbers and + symbols. + NoEcho: 'true' + Type: String + DatabaseInstance: + Description: Size of the database to be deployed as part of the Quick Start. + AllowedValues: + - db.m5.large + - db.m5.xlarge + - db.m5.2xlarge + - db.m5.10xlarge + - db.m5.16xlarge + - db.m5.large + - db.m5.xlarge + - db.m5.2xlarge + - db.m5.4xlarge + - db.m5.12xlarge + - db.m5.24xlarge + ConstraintDescription: Must be a valid database Instance Type. + Default: db.m5.large + Type: String + DatabaseAllocatedStorage: + Description: Size in gigabytes of available storage for the database instance. + MinValue: 5 + MaxValue: 1024 + Default: 10 + Type: Number + DatabasePreferredAz: + Description: Preferred availability zone for Amazon RDS primary instance + Type: String + Default: '' + MultiAzDatabase: + Description: Choose false to create an Amazon RDS instance in a single Availability Zone. + ConstraintDescription: True or False + AllowedValues: + - "true" + - "false" + Default: "true" + Type: String + QsS3BucketName: + Description: S3 bucket name for the Quick Start assets. This string can include + numbers, lowercase letters, and hyphens (-). It cannot start + or end with a hyphen (-). + AllowedPattern: ^[0-9a-z]+([0-9a-z-]*[0-9a-z])*$ + ConstraintDescription: Quick Start bucket name can include numbers, lowercase + letters, and hyphens (-). It cannot start or end with a hyphen (-). + Default: jfrog-aws + 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: artifactory7/latest/ + Type: String + QsS3BucketRegion: + Default: 'us-east-1' + Description: AWS Region where the Quick Start S3 bucket (QSS3BucketName) is hosted. If you use your own bucket, you must specify your own value. + Type: String + InstallXray: + Description: Choose true to install JFrog Xray instance(s). + ConstraintDescription: True or False + AllowedValues: + - "true" + - "false" + Default: "true" + Type: String + XrayVersion: + Description: The version of Xray that you want to deploy into the Quick Start. + Default: 3.21.2 + Type: String + XrayNumberOfInstances: + Description: The number of Xray instances servers to complete your + HA deployment. The minimum number is one; the maximum is seven. + Do not select more than instances than you have licenses for. + MinValue: 1 + MaxValue: 7 + Default: 1 + Type: Number + XrayInstanceType: + Description: The EC2 instance type for the Xray instances. + AllowedValues: + - c5.2xlarge + - c5.4xlarge + ConstraintDescription: Must contain valid instance type. + Default: c5.2xlarge + Type: String + XrayDatabaseUser: + Description: The login ID for the Xray database user. + MinLength: '1' + MaxLength: '16' + AllowedPattern: ^[a-zA-Z]([a-zA-Z0-9])+$ + ConstraintDescription: 1 to 16 alphanumeric characters. First character must be a letter. + Default: xray + Type: String + XrayDatabasePassword: + Description: The password for the Xray database user. + AllowedPattern: ^[^ \\']+$ + MinLength: '8' + MaxLength: '12' + ConstraintDescription: Must be at least 8 and no more than + 12 characters containing letters and (minimum 1 capital letter), numbers and + symbols. + NoEcho: 'true' + Type: String +Conditions: + UsingDefaultBucket: !Equals [!Ref QsS3BucketName, 'aws-quickstart'] + +Resources: + ArtifactoryVpcStack: + Type: AWS::CloudFormation::Stack + Properties: + TemplateURL: !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QsS3KeyPrefix}submodules/quickstart-aws-vpc/templates/aws-vpc.template + - S3Bucket: !If [UsingDefaultBucket, !Sub '${QsS3BucketName}-${AWS::Region}', !Ref 'QsS3BucketName'] + S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref 'QsS3BucketRegion'] + Parameters: + AvailabilityZones: + Fn::Join: + - ',' + - Ref: AvailabilityZones + KeyPairName: + Ref: KeyPairName + NumberOfAZs: '2' + PrivateSubnet1ACIDR: + Ref: PrivateSubnet1Cidr + PrivateSubnet2ACIDR: + Ref: PrivateSubnet2Cidr + PublicSubnet1CIDR: + Ref: PublicSubnet1Cidr + PublicSubnet2CIDR: + Ref: PublicSubnet2Cidr + VPCCIDR: + Ref: VpcCidr + ArtifactoryExistingVpcStack: + Type: AWS::CloudFormation::Stack + Properties: + TemplateURL: !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QsS3KeyPrefix}templates/jfrog-artifactory-ec2-existing-vpc.template.yaml + - S3Bucket: !If [UsingDefaultBucket, !Sub '${QsS3BucketName}-${AWS::Region}', !Ref 'QsS3BucketName'] + S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref 'QsS3BucketRegion'] + Parameters: + AvailabilityZones: + Fn::Join: + - ',' + - Ref: AvailabilityZones + KeyPairName: !Ref KeyPairName + VpcId: !GetAtt ArtifactoryVpcStack.Outputs.VPCID + VpcCidr: !Ref VpcCidr + PublicSubnet1Id: !GetAtt ArtifactoryVpcStack.Outputs.PublicSubnet1ID + PublicSubnet2Id: !GetAtt ArtifactoryVpcStack.Outputs.PublicSubnet2ID + PrivateSubnet1Id: !GetAtt ArtifactoryVpcStack.Outputs.PrivateSubnet1AID + PrivateSubnet2Id: !GetAtt ArtifactoryVpcStack.Outputs.PrivateSubnet2AID + PrivateSubnet1Cidr: !Ref PrivateSubnet1Cidr + PrivateSubnet2Cidr: !Ref PrivateSubnet2Cidr + AccessCidr: !Ref AccessCidr + RemoteAccessCidr: !Ref RemoteAccessCidr + ProvisionBastionHost: !Ref ProvisionBastionHost + BastionInstanceType: !Ref BastionInstanceType + BastionRootVolumeSize: !Ref BastionRootVolumeSize + BastionEnableTcpForwarding: !Ref BastionEnableTcpForwarding + BastionEnableX11Forwarding: !Ref BastionEnableX11Forwarding + BastionOs: !Ref BastionOs + NumBastionHosts: !Ref NumBastionHosts + VolumeSize: !Ref VolumeSize + InstanceType: !Ref InstanceType + NumberOfSecondary: !Ref NumberOfSecondary + ArtifactoryProduct: !Ref ArtifactoryProduct + ArtifactoryVersion: !Ref ArtifactoryVersion + SmLicenseName: !Ref SmLicenseName + SmCertName: !Ref SmCertName + ArtifactoryServerName: !Ref ArtifactoryServerName + MasterKey: !Ref MasterKey + ExtraJavaOptions: !Ref ExtraJavaOptions + DefaultJavaMemSettings: !Ref DefaultJavaMemSettings + DatabaseName: !Ref DatabaseName + DatabaseEngine: !Ref DatabaseEngine + DatabaseUser: !Ref DatabaseUser + DatabasePassword: !Ref DatabasePassword + DatabaseInstance: !Ref DatabaseInstance + DatabaseAllocatedStorage: !Ref DatabaseAllocatedStorage + DatabasePreferredAz: !Ref DatabasePreferredAz + MultiAzDatabase: !Ref MultiAzDatabase + QsS3BucketName: !Ref QsS3BucketName + QsS3KeyPrefix: !Ref QsS3KeyPrefix + QsS3BucketRegion: !Ref QsS3BucketRegion + InstallXray: !Ref InstallXray + XrayVersion: !Ref XrayVersion + XrayNumberOfInstances: !Ref XrayNumberOfInstances + XrayInstanceType: !Ref XrayInstanceType + XrayDatabaseUser: !Ref XrayDatabaseUser + XrayDatabasePassword: !Ref XrayDatabasePassword +Outputs: + ArtifactoryUrl: + Description: URL of the ELB to access Artifactory + Value: !Sub ${ArtifactoryExistingVpcStack.Outputs.ArtifactoryUrl} + BastionIp: + Value: !Sub ${ArtifactoryExistingVpcStack.Outputs.BastionIp} + Description: Bastion host IP, for admin access via SSH diff --git a/Amazon/artifactory7/latest/templates/jfrog-artifactory-pro-ec2-existing-vpc-master.template.yaml b/Amazon/artifactory7/latest/templates/jfrog-artifactory-pro-ec2-existing-vpc-master.template.yaml new file mode 100644 index 0000000..fa213eb --- /dev/null +++ b/Amazon/artifactory7/latest/templates/jfrog-artifactory-pro-ec2-existing-vpc-master.template.yaml @@ -0,0 +1,355 @@ +AWSTemplateFormatVersion: '2010-09-09' +Description: 'JFrog Artifactory Quick Start Deployment into an Existing VPC (qs-1q037efj0)' +Metadata: + QuickStartDocumentation: + EntrypointName: "Launch into an existing VPC" + AWS::CloudFormation::Interface: + ParameterGroups: + - Label: + default: AWS Quick Start configuration + Parameters: + - QsS3BucketName + - QsS3KeyPrefix + - QsS3BucketRegion + - Label: + default: Essential configuration + Parameters: + - KeyPairName + - DatabasePassword + - Label: + default: Network configuration + Parameters: + - VpcId + - PublicSubnet1Id + - PublicSubnet2Id + - PrivateSubnet1Id + - PrivateSubnet2Id + - PrivateSubnet1Cidr + - PrivateSubnet2Cidr + - Label: + default: Security configuration + Parameters: + - AccessCidr + - RemoteAccessCidr + - Label: + default: Amazon EC2 configuration + Parameters: + - VolumeSize + - InstanceType + - Label: + default: JFrog Artifactory configuration + Parameters: + - ArtifactoryVersion + - SmLicenseName + - SmCertName + - ArtifactoryServerName + - MasterKey + - Label: + default: Amazon RDS configuration + Parameters: + - DatabaseInstance + - DatabaseAllocatedStorage + - DatabasePreferredAz + - Label: + default: JFrog Xray Configuration + Parameters: + - InstallXray + - XrayVersion + - XrayInstanceType + ParameterLabels: + QsS3BucketName: + default: Quick Start S3 bucket name + QsS3KeyPrefix: + default: Quick Start S3 key prefix + QsS3BucketRegion: + default: Quick Start S3 bucket region + KeyPairName: + default: SSH key name + VpcId: + default: VPC ID + PublicSubnet1Id: + default: Public subnet 1 ID + PublicSubnet2Id: + default: Public subnet 2 ID + PrivateSubnet1Id: + default: Private subnet 1 ID + PrivateSubnet2Id: + default: Private subnet 2 ID + PrivateSubnet1Cidr: + default: Private subnet 1 CIDR + PrivateSubnet2Cidr: + default: Private subnet 2 CIDR + AccessCidr: + default: Permitted IP range + RemoteAccessCidr: + default: Remote access CIDR + VolumeSize: + default: EBS root volume size + InstanceType: + default: EC2 instance type + ArtifactoryVersion: + default: Artifactory version + SmLicenseName: + default: Artifactory licenses secret name + SmCertName: + default: Artifactory certificate secret name + ArtifactoryServerName: + default: Artifactory server name + MasterKey: + default: Master server key + DatabasePassword: + default: Database password + DatabaseInstance: + default: Database instance type + DatabaseAllocatedStorage: + default: Database allocated storage + DatabasePreferredAz: + default: Database preferred Availability Zone + InstallXray: + default: Install JFrog Xray + XrayVersion: + default: Version of Xray to install + XrayInstanceType: + default: Xray instance type +Parameters: + QsS3BucketName: + Description: S3 bucket name for the Quick Start assets. This string can include + numbers, lowercase letters, and hyphens (-). It cannot start + or end with a hyphen (-). + AllowedPattern: ^[0-9a-z]+([0-9a-z-]*[0-9a-z])*$ + ConstraintDescription: Quick Start bucket name can include numbers, lowercase + letters, and hyphens (-). It cannot start or end with a hyphen (-). + Default: jfrog-aws + 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: artifactory7/latest/ + Type: String + QsS3BucketRegion: + Default: 'us-east-1' + Description: AWS Region where the Quick Start S3 bucket (QSS3BucketName) is hosted. If you use your own bucket, you must specify your own value. + Type: String + KeyPairName: + Description: Name of an existing key pair, + which allows you to connect securely to your instance after it launches. + This is the key pair you created in your preferred Region. + Type: AWS::EC2::KeyPair::KeyName + VpcId: + Description: ID of your existing VPC (e.g., vpc-0343606e). + Type: "AWS::EC2::VPC::Id" + PublicSubnet1Id: + Description: ID of the public subnet 1 in Availability Zone 1 of your existing VPC (e.g., subnet-z0376dab). + Type: "AWS::EC2::Subnet::Id" + PublicSubnet2Id: + Description: ID of the public subnet 2 in Availability Zone 1 of your existing VPC (e.g., subnet-z0376dab). + Type: "AWS::EC2::Subnet::Id" + PrivateSubnet1Id: + Description: ID of the private subnet 1 in Availability Zone 1 of your existing VPC (e.g., subnet-a29c3d84). + Type: "AWS::EC2::Subnet::Id" + PrivateSubnet2Id: + Description: ID of the private subnet 2 in Availability Zone 1 of your existing VPC (e.g., subnet-a29c3d84). + Type: "AWS::EC2::Subnet::Id" + PrivateSubnet1Cidr: + Description: CIDR of the private subnet 1 in Availability Zone 1 of your existing VPC (e.g., 10.0.0.0/19). + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.128.0/20 + Type: String + PrivateSubnet2Cidr: + Description: CIDR of the private subnet 2 in Availability Zone 1 of your existing VPC (e.g., 10.0.0.0/19). + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.144.0/20 + Type: String + AccessCidr: + Description: CIDR IP range that is permitted to access Artifactory. + We recommend that you set this value to a trusted IP range. + For example, you might want to grant only your corporate network access to the software. + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$ + Default: 0.0.0.0/0 + Type: String + RemoteAccessCidr: + Description: Remote CIDR range that allows you to connect to the bastion instance by using SSH. + It is recommended that you set this value to a trusted IP range. + For example, you may want to grant specific ranges from within your corporate network that use the SSH protocol. + 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 + VolumeSize: + Description: Size in gigabytes of the available storage (min 10GB); the Quick Start will create an + Amazon Elastic Block Store (Amazon EBS) volumes of this size. + Default: 100 + Type: Number + InstanceType: + Description: EC2 type for the Artifactory instances. + AllowedValues: + - m5.large + - m5.xlarge + - m5.2xlarge + - m5.4xlarge + - m5.8xlarge + - m5.12xlarge + - m5.16xlarge + - m5.24xlarge + - m5.metal + - m5d.large + - m5d.xlarge + - m5d.2xlarge + - m5d.4xlarge + - m5d.8xlarge + - m5d.12xlarge + - m5d.16xlarge + - m5d.24xlarge + - m5d.metal + - m5a.large + - m5a.xlarge + - m5a.2xlarge + - m5a.4xlarge + - m5a.8xlarge + - m5a.12xlarge + - m5a.16xlarge + - m5a.24xlarge + ConstraintDescription: Must contain valid instance type. + Default: m5.xlarge + Type: String + ArtifactoryVersion: + Description: Version of Artifactory that you want to deploy into the Quick Start. + To select the correct version, see the release notes at + https://www.jfrog.com/confluence/display/RTF/Release+Notes. + AllowedPattern: ^(([0-9]|[1-9][0-9])\.){2}([1-9][0-9]|[0-9])$ + ConstraintDescription: A version that matches X.X.X per Artifactory releases. + Default: 7.17.4 + Type: String + SmLicenseName: + Description: Secret name created in AWS Secrets Manager, which contains the Artifactory licenses. + Default: '' + Type: String + SmCertName: + Description: Secret name created in AWS Secrets Manager, which contains the SSL certificate and certificate key. + Default: '' + Type: String + ArtifactoryServerName: + Description: Name of your Artifactory server. Ensure that this matches your certificate. + Default: 'artifactory' + Type: String + MasterKey: + Description: Master key for the Artifactory cluster. Generate a master key by using the command '$openssl rand -hex 16'. + AllowedPattern: ^[a-zA-Z0-9]+$ + MinLength: '1' + MaxLength: '64' + ConstraintDescription: Only capital or lowercase letters and numbers, with a Max of 64 characters. + NoEcho: 'true' + Default: 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' + Type: String + DatabasePassword: + Description: Password for the Artifactory database user. + AllowedPattern: ^[^ \\']+$ + MinLength: '8' + MaxLength: '12' + ConstraintDescription: Must be at least 8 and no more than + 12 characters containing letters and (minimum 1 capital letter), numbers and + symbols. + NoEcho: 'true' + Type: String + DatabaseInstance: + Description: Size of the database to be deployed as part of the Quick Start. + AllowedValues: + - db.m5.large + - db.m5.xlarge + - db.m5.2xlarge + - db.m5.10xlarge + - db.m5.16xlarge + - db.m5.large + - db.m5.xlarge + - db.m5.2xlarge + - db.m5.4xlarge + - db.m5.12xlarge + - db.m5.24xlarge + ConstraintDescription: Must be a valid database Instance Type. + Default: db.m5.large + Type: String + DatabaseAllocatedStorage: + Description: Size in gigabytes of the available storage for the database instance. + MinValue: 5 + MaxValue: 1024 + Default: 10 + Type: Number + DatabasePreferredAz: + Description: Preferred availability zone for Amazon RDS primary instance + Default: us-west-2a + Type: AWS::EC2::AvailabilityZone::Name + InstallXray: + Description: Choose true to install JFrog Xray instance(s). + ConstraintDescription: True or False + AllowedValues: + - "true" + - "false" + Default: "false" + Type: String + XrayVersion: + Description: The version of Xray that you want to deploy into the Quick Start. + AllowedPattern: ^(([0-9]|[1-9][0-9])\.){2}([1-9][0-9]|[0-9])$ + ConstraintDescription: A version that matches X.X.X per Xray releases. + Default: 3.21.2 + Type: String + XrayInstanceType: + Description: The EC2 instance type for the Xray instances. + AllowedValues: + - c5.2xlarge + - c5.4xlarge + ConstraintDescription: Must contain valid instance type. + Default: c5.2xlarge + Type: String +Conditions: + UsingDefaultBucket: !Equals [!Ref QsS3BucketName, 'aws-quickstart'] +Resources: + ArtifactoryExistingVpcStack: + Type: AWS::CloudFormation::Stack + Properties: + TemplateURL: !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QsS3KeyPrefix}templates/jfrog-artifactory-ec2-existing-vpc.template.yaml + - S3Bucket: !If [UsingDefaultBucket, !Sub '${QsS3BucketName}-${AWS::Region}', !Ref 'QsS3BucketName'] + S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref 'QsS3BucketRegion'] + Parameters: + AvailabilityZones: !Join [',', [!Ref DatabasePreferredAz]] + KeyPairName: !Ref KeyPairName + ProvisionBastionHost: "Enabled" + AccessCidr: !Ref AccessCidr + RemoteAccessCidr: !Ref RemoteAccessCidr + ArtifactoryProduct: 'JFrog-Artifactory-Pro' + ArtifactoryVersion: !Ref ArtifactoryVersion + VolumeSize: !Ref VolumeSize + InstanceType: !Ref InstanceType + NumberOfSecondary: 0 + SmLicenseName: !Ref SmLicenseName + SmCertName: !Ref SmCertName + ArtifactoryServerName: !Ref ArtifactoryServerName + MasterKey: !Ref MasterKey + DatabasePassword: !Ref DatabasePassword + DatabaseInstance: !Ref DatabaseInstance + DatabaseAllocatedStorage: !Ref DatabaseAllocatedStorage + DatabasePreferredAz: !Ref DatabasePreferredAz + MultiAzDatabase: false + QsS3BucketName: !Ref QsS3BucketName + QsS3KeyPrefix: !Ref QsS3KeyPrefix + QsS3BucketRegion: !Ref QsS3BucketRegion + InstallXray: !Ref InstallXray + XrayVersion: !Ref XrayVersion + XrayInstanceType: !Ref XrayInstanceType + XrayDatabasePassword: !Ref DatabasePassword + VpcId: !Ref VpcId + PublicSubnet1Id: !Ref PublicSubnet1Id + PublicSubnet2Id: !Ref PublicSubnet2Id + PrivateSubnet1Id: !Ref PrivateSubnet1Id + PrivateSubnet2Id: !Ref PrivateSubnet2Id + PrivateSubnet1Cidr: !Ref PrivateSubnet1Cidr + PrivateSubnet2Cidr: !Ref PrivateSubnet2Cidr + +Outputs: + ArtifactoryUrl: + Description: URL of the ELB to access Artifactory + Value: !Sub ${ArtifactoryExistingVpcStack.Outputs.ArtifactoryUrl} diff --git a/Amazon/artifactory7/latest/templates/jfrog-artifactory-pro-ec2-new-vpc-master.template.yaml b/Amazon/artifactory7/latest/templates/jfrog-artifactory-pro-ec2-new-vpc-master.template.yaml new file mode 100644 index 0000000..2736e44 --- /dev/null +++ b/Amazon/artifactory7/latest/templates/jfrog-artifactory-pro-ec2-new-vpc-master.template.yaml @@ -0,0 +1,300 @@ +AWSTemplateFormatVersion: '2010-09-09' +Description: 'JFrog Artifactory Quick Start Deployment into an Existing VPC (qs-1q037efj0)' +Metadata: + QuickStartDocumentation: + EntrypointName: "Launch into an existing VPC" + AWS::CloudFormation::Interface: + ParameterGroups: + - Label: + default: AWS Quick Start configuration + Parameters: + - QsS3BucketName + - QsS3KeyPrefix + - QsS3BucketRegion + - Label: + default: Essential configuration + Parameters: + - KeyPairName + - DatabasePassword + - Label: + default: Network configuration + Parameters: + - AvailabilityZones + - Label: + default: Security configuration + Parameters: + - AccessCidr + - RemoteAccessCidr + - Label: + default: Amazon EC2 configuration + Parameters: + - VolumeSize + - InstanceType + - Label: + default: JFrog Artifactory configuration + Parameters: + - ArtifactoryVersion + - SmLicenseName + - SmCertName + - ArtifactoryServerName + - MasterKey + - Label: + default: Amazon RDS configuration + Parameters: + - DatabaseInstance + - DatabaseAllocatedStorage + - Label: + default: JFrog Xray Configuration + Parameters: + - InstallXray + - XrayVersion + - XrayInstanceType + ParameterLabels: + QsS3BucketName: + default: Quick Start S3 bucket name + QsS3KeyPrefix: + default: Quick Start S3 key prefix + QsS3BucketRegion: + default: Quick Start S3 bucket region + KeyPairName: + default: SSH key name + AccessCidr: + default: Permitted IP range + RemoteAccessCidr: + default: Remote access CIDR + AvailabilityZones: + default: Availability Zones + VolumeSize: + default: EBS root volume size + InstanceType: + default: EC2 instance type + ArtifactoryVersion: + default: Artifactory version + SmLicenseName: + default: Artifactory licenses secret name + SmCertName: + default: Artifactory certificate secret name + ArtifactoryServerName: + default: Artifactory server name + MasterKey: + default: Master server key + DatabasePassword: + default: Database password + DatabaseInstance: + default: Database instance type + DatabaseAllocatedStorage: + default: Database allocated storage + InstallXray: + default: Install JFrog Xray + XrayVersion: + default: Version of Xray to install + XrayInstanceType: + default: Xray instance type +Parameters: + QsS3BucketName: + Description: S3 bucket name for the Quick Start assets. This string can include + numbers, lowercase letters, and hyphens (-). It cannot start + or end with a hyphen (-). + AllowedPattern: ^[0-9a-z]+([0-9a-z-]*[0-9a-z])*$ + ConstraintDescription: Quick Start bucket name can include numbers, lowercase + letters, and hyphens (-). It cannot start or end with a hyphen (-). + Default: jfrog-aws + 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: artifactory7/latest/ + Type: String + QsS3BucketRegion: + Default: 'us-east-1' + Description: AWS Region where the Quick Start S3 bucket (QSS3BucketName) is hosted. If you use your own bucket, you must specify your own value. + Type: String + KeyPairName: + Description: Name of an existing key pair, + which allows you to connect securely to your instance after it launches. + This is the key pair you created in your preferred Region. + Type: AWS::EC2::KeyPair::KeyName + AccessCidr: + Description: CIDR IP range that is permitted to access Artifactory. + We recommend that you set this value to a trusted IP range. + For example, you might want to grant only your corporate network access to the software. + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$ + Default: 0.0.0.0/0 + Type: String + RemoteAccessCidr: + Description: Remote CIDR range that allows you to connect to the bastion instance by using SSH. + It is recommended that you set this value to a trusted IP range. + For example, you may want to grant specific ranges from within your corporate network that use the SSH protocol. + 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 + AvailabilityZones: + Description: List of Availability Zones to use for the subnets in the VPC. Two + Availability Zones are used for this deployment. + Type: List + VolumeSize: + Description: Size in gigabytes of the available storage (min 10GB); the Quick Start will create an + Amazon Elastic Block Store (Amazon EBS) volumes of this size. + Default: 100 + Type: Number + InstanceType: + Description: EC2 type for the Artifactory instances. + AllowedValues: + - m5.large + - m5.xlarge + - m5.2xlarge + - m5.4xlarge + - m5.8xlarge + - m5.12xlarge + - m5.16xlarge + - m5.24xlarge + - m5.metal + - m5d.large + - m5d.xlarge + - m5d.2xlarge + - m5d.4xlarge + - m5d.8xlarge + - m5d.12xlarge + - m5d.16xlarge + - m5d.24xlarge + - m5d.metal + - m5a.large + - m5a.xlarge + - m5a.2xlarge + - m5a.4xlarge + - m5a.8xlarge + - m5a.12xlarge + - m5a.16xlarge + - m5a.24xlarge + ConstraintDescription: Must contain valid instance type. + Default: m5.xlarge + Type: String + ArtifactoryVersion: + Description: Version of Artifactory that you want to deploy into the Quick Start. + To select the correct version, see the release notes at + https://www.jfrog.com/confluence/display/RTF/Release+Notes. + Default: 7.17.4 + Type: String + SmLicenseName: + Description: Secret name created in AWS Secrets Manager, which contains the Artifactory licenses. + Default: '' + Type: String + SmCertName: + Description: Secret name created in AWS Secrets Manager, which contains the SSL certificate and certificate key. + Default: '' + Type: String + ArtifactoryServerName: + Description: Name of your Artifactory server. Ensure that this matches your certificate. + Default: 'artifactory' + Type: String + MasterKey: + Description: Master key for the Artifactory cluster. Generate a master key by using the command '$openssl rand -hex 16'. + AllowedPattern: ^[a-zA-Z0-9]+$ + MinLength: '1' + MaxLength: '64' + ConstraintDescription: Only capital or lowercase letters and numbers, with a Max of 64 characters. + NoEcho: 'true' + Default: 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' + Type: String + DatabasePassword: + Description: Password for the Artifactory database user. + AllowedPattern: ^[^ \\']+$ + MinLength: '8' + MaxLength: '12' + ConstraintDescription: Must be at least 8 and no more than + 12 characters containing letters and (minimum 1 capital letter), numbers and + symbols. + NoEcho: 'true' + Type: String + DatabaseInstance: + Description: Size of the database to be deployed as part of the Quick Start. + AllowedValues: + - db.m5.large + - db.m5.xlarge + - db.m5.2xlarge + - db.m5.10xlarge + - db.m5.16xlarge + - db.m5.large + - db.m5.xlarge + - db.m5.2xlarge + - db.m5.4xlarge + - db.m5.12xlarge + - db.m5.24xlarge + ConstraintDescription: Must be a valid database Instance Type. + Default: db.m5.large + Type: String + DatabaseAllocatedStorage: + Description: Size in gigabytes of the available storage for the database instance. + MinValue: 5 + MaxValue: 1024 + Default: 10 + Type: Number + InstallXray: + Description: Choose true to install JFrog Xray instance(s). + ConstraintDescription: True or False + AllowedValues: + - "true" + - "false" + Default: "false" + Type: String + XrayVersion: + Description: The version of Xray that you want to deploy into the Quick Start. + Default: 3.21.2 + Type: String + XrayInstanceType: + Description: The EC2 instance type for the Xray instances. + AllowedValues: + - c5.2xlarge + - c5.4xlarge + ConstraintDescription: Must contain valid instance type. + Default: c5.2xlarge + Type: String +Conditions: + UsingDefaultBucket: !Equals [!Ref QsS3BucketName, 'aws-quickstart'] +Resources: + ArtifactoryNewVpcStack: + Type: AWS::CloudFormation::Stack + Properties: + TemplateURL: !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QsS3KeyPrefix}templates/jfrog-artifactory-ec2-master.template.yaml + - S3Bucket: !If [UsingDefaultBucket, !Sub '${QsS3BucketName}-${AWS::Region}', !Ref 'QsS3BucketName'] + S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref 'QsS3BucketRegion'] + Parameters: + KeyPairName: !Ref KeyPairName + ProvisionBastionHost: "Enabled" + AccessCidr: !Ref AccessCidr + RemoteAccessCidr: !Ref RemoteAccessCidr + ArtifactoryProduct: 'JFrog-Artifactory-Pro' + ArtifactoryVersion: !Ref ArtifactoryVersion + VolumeSize: !Ref VolumeSize + InstanceType: !Ref InstanceType + NumberOfSecondary: 0 + SmLicenseName: !Ref SmLicenseName + SmCertName: !Ref SmCertName + ArtifactoryServerName: !Ref ArtifactoryServerName + MasterKey: !Ref MasterKey + DatabasePassword: !Ref DatabasePassword + DatabaseInstance: !Ref DatabaseInstance + DatabaseAllocatedStorage: !Ref DatabaseAllocatedStorage + DatabasePreferredAz: !Select + - '0' + - !Ref 'AvailabilityZones' + MultiAzDatabase: false + QsS3BucketName: !Ref QsS3BucketName + QsS3KeyPrefix: !Ref QsS3KeyPrefix + QsS3BucketRegion: !Ref QsS3BucketRegion + InstallXray: !Ref InstallXray + XrayVersion: !Ref XrayVersion + XrayInstanceType: !Ref XrayInstanceType + XrayDatabasePassword: !Ref DatabasePassword + AvailabilityZones: + Fn::Join: + - ',' + - Ref: AvailabilityZones +Outputs: + ArtifactoryUrl: + Description: URL of the ELB to access Artifactory + Value: !Sub ${ArtifactoryNewVpcStack.Outputs.ArtifactoryUrl} diff --git a/Amazon/artifactory7/latest/templates/jfrog-xray-ec2-instance.template.yaml b/Amazon/artifactory7/latest/templates/jfrog-xray-ec2-instance.template.yaml new file mode 100644 index 0000000..0f57609 --- /dev/null +++ b/Amazon/artifactory7/latest/templates/jfrog-xray-ec2-instance.template.yaml @@ -0,0 +1,326 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: "Deploys the EC2 Autoscaling, LaunchConfig and Instance for Xray" +Parameters: + PrivateSubnet1Id: + Type: 'AWS::EC2::Subnet::Id' + PrivateSubnet2Id: + Type: 'AWS::EC2::Subnet::Id' + KeyPairName: + Type: AWS::EC2::KeyPair::KeyName + MinScalingNodes: + Type: Number + MaxScalingNodes: + Type: Number + DeploymentTag: + Type: String + ArtifactoryProduct: + Description: JFrog Artifactory product you want to install into an AMI. + AllowedValues: + - JFrog-Artifactory-Pro + - JFrog-Artifactory-Enterprise + - JFrog-Container-Registry + Default: JFrog-Artifactory-Enterprise + Type: String + QsS3BucketName: + Type: String + QsS3KeyPrefix: + Type: String + QsS3Uri: + Type: String + DatabaseDriver: + Type: String + DatabaseType: + Type: String + DatabaseUser: + Type: String + DatabasePassword: + Type: String + NoEcho: 'true' + MasterKey: + Type: String + NoEcho: 'true' + ExtraJavaOptions: + Type: String + SecurityGroups: + Type: String + XrayHostProfile: + Type: String + XrayHostRole: + Type: String + XrayInstanceType: + Type: String + JfrogInternalUrl: + Type: String + VolumeSize: + Type: Number + XrayDatabaseUser: + Type: String + XrayDatabasePassword: + Type: String + NoEcho: 'true' + XrayMasterDatabaseUrl: + Type: String + XrayDatabaseUrl: + Type: String + XrayVersion: + Type: String + UserDataDirectory: + Description: Directory to store Artifactory data. Can be used to store data (via symlink) in detachable volume + Type: String + Default: '/xray-user-data' + +# 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: + CentOS7HVM: "ami-00a5245b4816c38e6" + ap-northeast-2: + CentOS7HVM: "ami-00dc207f8ba6dc919" + ap-south-1: + CentOS7HVM: "ami-0ad42f4f66f6c1cc9" + ap-southeast-1: + CentOS7HVM: "ami-05b3bcf7f311194b3" + ap-southeast-2: + CentOS7HVM: "ami-02fd0b06f06d93dfc" + ca-central-1: + CentOS7HVM: "ami-07423fb63ea0a0930" + eu-central-1: + CentOS7HVM: "ami-0cfbf4f6db41068ac" + eu-west-1: + CentOS7HVM: "ami-08935252a36e25f85" + sa-east-1: + CentOS7HVM: "ami-05145e0b28ad8e0b2" + us-east-1: + CentOS7HVM: "ami-0affd4508a5d2481b" + us-east-2: + CentOS7HVM: "ami-01e36b7901e884a10" + us-west-1: + CentOS7HVM: "ami-098f55b4287a885ba" + us-west-2: + CentOS7HVM: "ami-0bc06212a56393ee1" + +Conditions: + IsArtifactoryPro: !Equals [!Ref ArtifactoryProduct, 'JFrog-Artifactory-Pro'] + +Resources: + XrayScalingGroup: + Type: AWS::AutoScaling::AutoScalingGroup + Properties: + LaunchConfigurationName: !Ref XrayLaunchConfiguration + VPCZoneIdentifier: + !If [IsArtifactoryPro, [!Ref PrivateSubnet1Id], [!Ref PrivateSubnet1Id, !Ref PrivateSubnet2Id]] + MinSize: !Ref MinScalingNodes + MaxSize: !Ref MaxScalingNodes + Cooldown: '300' + DesiredCapacity: !Ref MinScalingNodes + HealthCheckType: EC2 + HealthCheckGracePeriod: 1800 + Tags: + - Key: Name + Value: !Ref DeploymentTag + PropagateAtLaunch: true + - Key: XrayVersion + Value: !Ref XrayVersion + PropagateAtLaunch: true + TerminationPolicies: + - OldestInstance + - Default + CreationPolicy: + ResourceSignal: + Count: !Ref MinScalingNodes + Timeout: PT60M + XrayLaunchConfiguration: + Type: AWS::AutoScaling::LaunchConfiguration + Metadata: + AWS::CloudFormation::Authentication: + S3AccessCreds: + type: S3 + roleName: + - !Ref XrayHostRole + buckets: + - !Ref QsS3BucketName + AWS::CloudFormation::Init: + configSets: + xray_ami_setup: + - "config-cloudwatch" + - "config-ansible-xray-ami" + xray_install: + - "config-cloudwatch" + - "config-ansible-xray-ami" + - "config-xray" + - "secure-xray" + config-cloudwatch: + files: + /root/cloudwatch.conf: + content: | + [general] + state_file = /var/awslogs/state/agent-state + + [/var/log/messages] + file = /var/log/messages + log_group_name = /xray/instances/{instance_id} + log_stream_name = /var/log/messages/ + datetime_format = %b %d %H:%M:%S + + [/var/log/xray-ami-setup.log] + file = /var/log/messages + log_group_name = /xray/instances/{instance_id} + log_stream_name = /var/log/xray-ami-setup.log + datetime_format = %b %d %H:%M:%S + + [/var/log/xray.log] + file = /var/log/messages + log_group_name = /xray/instances/{instance_id} + log_stream_name = /var/log/xray.log + datetime_format = %b %d %H:%M:%S + mode: "0400" + config-ansible-xray-ami: + files: + /root/.xray_ami/xray-ami-setup.yml: + content: !Sub | + # Base install for Xray + - import_playbook: xray-ami.yml + vars: + ami_creation: false + db_type: postgresql + db_driver: org.postgresql.Driver + xray_version: ${XrayVersion} + xray_ha_enabled: false + mode: "0400" + config-xray: + files: + /root/.xray_ami/xray.yml: + content: !Sub | + # Base install for Xray + - import_playbook: site-xray.yml + vars: + jfrog_url: ${JfrogInternalUrl} + use_custom_data_directory: true + custom_data_directory: "${UserDataDirectory}" + master_key: ${MasterKey} + join_key: ${MasterKey} + extra_java_opts: ${ExtraJavaOptions} + db_type: ${DatabaseType} + db_driver: ${DatabaseDriver} + db_master_url: postgresql://${DatabaseUser}:${DatabasePassword}@${XrayMasterDatabaseUrl} + db_url: postgres://${XrayDatabaseUrl} + db_master_user: ${DatabaseUser} + db_user: ${XrayDatabaseUser} + db_password: ${XrayDatabasePassword} + xray_version: ${XrayVersion} + mode: "0400" + /root/.vault_pass.txt: + content: !Sub | + ${DatabasePassword} + mode: "0400" + /root/.secureit.sh: + content: + ansible-vault encrypt /root/.xray_ami/xray.yml --vault-id /root/.vault_pass.txt + mode: "0770" + secure-xray: + commands: + 'secure ansible playbook': + command: '/root/.secureit.sh' + ignoreErrors: 'false' + Properties: + KeyName: !Ref KeyPairName + IamInstanceProfile: !Ref XrayHostProfile + ImageId: !FindInMap + - AWSAMIRegionMap + - !Ref AWS::Region + - 'CentOS7HVM' + SecurityGroups: + - !Ref SecurityGroups + InstanceType: !Ref XrayInstanceType + BlockDeviceMappings: + - DeviceName: /dev/xvda + Ebs: + VolumeSize: !Ref VolumeSize + VolumeType: gp2 + DeleteOnTermination: true + Encrypted: true + UserData: + Fn::Base64: + !Sub | + #!/bin/bash -x + exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1 + + #CFN Functions + + function cfn_fail + + { + + cfn-signal -e 1 --stack ${AWS::StackName} --region ${AWS::Region} --resource XrayScalingGroup + + exit 1 + + } + + function cfn_success + + { + + cfn-signal -e 0 --stack ${AWS::StackName} --region ${AWS::Region} --resource XrayScalingGroup + + exit 0 + + } + + S3URI=${QsS3Uri} + + yum update --security -y &> /var/log/userdata.yum_security_update.log + + yum install -y git python3 libselinux-python3 + yum install -y postgresql-server postgresql-devel + + 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 + + pip install awscli &> /var/log/userdata.awscli_install.log + + pip install ansible &> /var/log/userdata.ansible_install.log + + mkdir ~/.xray_ami + + aws s3 --region ${AWS::Region} sync s3://${QsS3BucketName}/${QsS3KeyPrefix}cloudInstallerScripts/ ~/.xray_ami/ + + setsebool httpd_can_network_connect 1 -P + + # 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 + + cfn-init -v --stack ${AWS::StackName} --resource XrayLaunchConfiguration --configsets xray_install --region ${AWS::Region} || cfn_fail + + # Setup CloudWatch Agent + curl https://s3.amazonaws.com/aws-cloudwatch/downloads/latest/awslogs-agent-setup.py -O + chmod +x ./awslogs-agent-setup.py + ./awslogs-agent-setup.py -n -r ${AWS::Region} -c /root/cloudwatch.conf + + lsblk # debug + + ansible-galaxy collection install community.general ansible.posix + + ansible-playbook /root/.xray_ami/xray-ami-setup.yml --vault-id /root/.vault_pass.txt 2>&1 | tee /var/log/xray-ami.log || cfn_fail + ansible-playbook /root/.xray_ami/xray.yml --vault-id /root/.vault_pass.txt 2>&1 | tee /var/log/xray.log || cfn_fail + + rm -rf /root/.secureit.sh + + cfn_success &> /var/log/cfn_success.log + cfn_success || cfn_fail diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/artifactory-ami.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/artifactory-ami.yml new file mode 100644 index 0000000..1e115c9 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/artifactory-ami.yml @@ -0,0 +1,5 @@ +- hosts: localhost + gather_facts: true + become: true + roles: + - name: artifactory-ami diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/.travis.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/.travis.yml new file mode 100644 index 0000000..36bbf62 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/.travis.yml @@ -0,0 +1,29 @@ +--- +language: python +python: "2.7" + +# Use the new container infrastructure +sudo: false + +# Install ansible +addons: + apt: + packages: + - python-pip + +install: + # Install ansible + - pip install ansible + + # Check ansible version + - ansible --version + + # Create ansible.cfg with correct roles_path + - printf '[defaults]\nroles_path=../' >ansible.cfg + +script: + # Basic role syntax check + - ansible-playbook tests/test.yml -i tests/inventory --syntax-check + +notifications: + webhooks: https://galaxy.ansible.com/api/v1/notifications/ \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/defaults/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/defaults/main.yml new file mode 100644 index 0000000..6d2c6f9 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/defaults/main.yml @@ -0,0 +1,60 @@ +--- +# defaults file for artifactory +# indicates were this collection was downlaoded from (galaxy, automation_hub, standalone) +ansible_marketplace: standalone + +# whether we are creating a AMI for Marketplace or just for configuring EC2 instance +ami_creation: false + +# The version of Artifactory to install +artifactory_version: 7.15.3 + +# licenses file - specify a licenses file or specify up to 5 licenses +artifactory_license1: +artifactory_license2: +artifactory_license3: +artifactory_license4: +artifactory_license5: +artifactory_license6: + +# whether to enable HA +artifactory_ha_enabled: true + +# value for whether a host is primary. this should be set in host vars +artifactory_is_primary: true + +# The location where Artifactory should install. +artifactory_download_directory: /opt/jfrog + +# The location where Artifactory should store data. +artifactory_file_store_dir: /data + +extra_java_opts: -server -Xms2g -Xmx14g -Xss256k -XX:+UseG1GC + + + +# Pick the Artifactory flavour to install, can be also cpp-ce, jcr, pro. +# for Artifactory, use following values +artifactory_flavour: pro +artifactory_tar: https://releases.jfrog.io/artifactory/artifactory-pro/org/artifactory/{{ artifactory_flavour }}/jfrog-artifactory-{{ artifactory_flavour }}/{{ artifactory_version }}/jfrog-artifactory-{{ artifactory_flavour }}-{{ artifactory_version }}-linux.tar.gz + +# for JCR, use following values +# artifactory_flavour: jcr +# artifactory_tar: https://dl.bintray.com/jfrog/artifactory/org/artifactory/{{ artifactory_flavour }}/jfrog-artifactory-{{ artifactory_flavour }}/{{ artifactory_version }}/jfrog-artifactory-{{ artifactory_flavour }}-{{ artifactory_version }}-linux.tar.gz + +artifactory_home: "{{ artifactory_download_directory }}/artifactory-{{ artifactory_flavour }}-{{ artifactory_version }}" +db_download_url: "https://jdbc.postgresql.org/download/postgresql-42.2.12.jar" + +artifactory_user: artifactory +artifactory_group: artifactory + +# Set the parameters required for the service. +service_list: + - name: artifactory + description: Start script for Artifactory + start_command: "{{ artifactory_home }}/bin/artifactory.sh start" + stop_command: "{{ artifactory_home }}/bin/artifactory.sh stop" + type: forking + status_pattern: artifactory + user_name: "{{ artifactory_user }}" + group_name: "{{ artifactory_group }}" diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/handlers/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/handlers/main.yml new file mode 100644 index 0000000..6f8fcda --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/handlers/main.yml @@ -0,0 +1,10 @@ +--- +# handlers file for artifactory +- name: systemctl daemon-reload + systemd: + daemon_reload: yes + +- name: restart artifactory + service: + name: artifactory + state: restarted diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/meta/exception.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/meta/exception.yml new file mode 100644 index 0000000..7de46df --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/meta/exception.yml @@ -0,0 +1,6 @@ +--- +exceptions: + - variation: Alpine + reason: Artifactory start/stop scripts don't properly work. + - variation: amazonlinux:1 + reason: "Shutting down artifactory: /usr/bin/java\nfinding\nUsing the default catalina management port (8015) to test shutdown\nArtifactory Tomcat already stopped" diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/meta/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/meta/main.yml new file mode 100644 index 0000000..0dc573a --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/meta/main.yml @@ -0,0 +1,35 @@ +--- +galaxy_info: + author: Robert de Bock + role_name: artifactory + description: Install and configure artifactory on your system. + license: Apache-2.0 + company: none + min_ansible_version: 2.8 + + platforms: + - name: Debian + versions: + - all + - name: EL + versions: + - 7 + - 8 + - name: Fedora + versions: + - all + - name: OpenSUSE + versions: + - all + - name: Ubuntu + versions: + - bionic + + galaxy_tags: + - artifactory + - centos + - redhat + - server + - system + +dependencies: [] diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/meta/preferences.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/meta/preferences.yml new file mode 100644 index 0000000..e7fdebf --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/meta/preferences.yml @@ -0,0 +1,2 @@ +--- +tox_parallel: yes diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/meta/version.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/meta/version.yml new file mode 100644 index 0000000..024188d --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/meta/version.yml @@ -0,0 +1,6 @@ +--- +project_name: JFrog +reference: "https://github.com/robertdebock/ansible-role-artifactory/blob/master/defaults/main.yml" +versions: + - name: Artifactory + url: "https://releases.jfrog.io/artifactory/" diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/tasks/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/tasks/main.yml new file mode 100644 index 0000000..68dc835 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/tasks/main.yml @@ -0,0 +1,82 @@ +--- +# tasks file for artifactory +- name: install nginx + include_role: + name: artifactory-nginx-ami + +- name: create group for artifactory + group: + name: "{{ artifactory_group }}" + state: present + become: yes + +- name: create user for artifactory + user: + name: "{{ artifactory_user }}" + group: "{{ artifactory_group }}" + system: yes + become: yes + +- name: ensure artifactory_download_directory exists + file: + path: "{{ artifactory_download_directory }}" + state: directory + become: yes + +- name: download artifactory + unarchive: + src: "{{ artifactory_tar }}" + dest: "{{ artifactory_download_directory }}" + remote_src: yes + owner: "{{ artifactory_user }}" + group: "{{ artifactory_group }}" + creates: "{{ artifactory_home }}" + become: yes + register: downloadartifactory + until: downloadartifactory is succeeded + retries: 3 + +- name: ensure artifactory_file_store_dir exists + file: + path: "{{ artifactory_file_store_dir }}" + state: directory + owner: "{{ artifactory_user }}" + group: "{{ artifactory_group }}" + become: yes + +- name: ensure data subdirectories exist + file: + path: "{{ artifactory_home }}/var/{{ item }}" + state: directory + owner: "{{ artifactory_user }}" + group: "{{ artifactory_group }}" + loop: + - "bootstrap" + - "etc" + become: yes + +- name: download database driver + get_url: + url: "{{ db_download_url }}" + dest: "{{ artifactory_home }}/var/bootstrap/artifactory/tomcat/lib" + owner: "{{ artifactory_user }}" + group: "{{ artifactory_group }}" + become: yes + +- name: clean up after creating ami + block: + - name: Remove SSH keys + file: + path: "{{ ssh_keys.dir }}" + state: absent + loop: + - dir: "/home/.jfrog_ami/.ssh/authorized_keys" + - dir: "/root/.ssh/authorized_keys" + - dir: "/home/centos/.ssh/authorized_keys" + loop_control: + loop_var: ssh_keys + + - name: shutdown VM + command: /sbin/shutdown -h now + ignore_errors: 'yes' + when: ami_creation diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/templates/artifactory.cluster.license.j2 b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/templates/artifactory.cluster.license.j2 new file mode 100644 index 0000000..ec2993b --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/templates/artifactory.cluster.license.j2 @@ -0,0 +1,37 @@ +{% if artifactory_license1 %} +{% if artifactory_license1|length %} +{{ artifactory_license1 }} +{% endif %} +{% endif %} +{% if artifactory_license2 %} + + +{% if artifactory_license2|length %} +{{ artifactory_license2 }} +{% endif %} +{% endif %} +{% if artifactory_license3 %} + + +{% if artifactory_license3|length %} +{{ artifactory_license3 }} +{% endif %} +{% endif %} +{% if artifactory_license4 %} + +{% if artifactory_license4|length %} +{{ artifactory_license4 }} +{% endif %} +{% endif %} +{% if artifactory_license5 %} + +{% if artifactory_license5|length %} +{{ artifactory_license5 }} +{% endif %} +{% endif %} +{% if artifactory_license6 %} + +{% if artifactory_license6|length %} +{{ artifactory_license6 }} +{% endif %} +{% endif %} diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/templates/binarystore.xml.j2 b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/templates/binarystore.xml.j2 new file mode 100644 index 0000000..f85f16f --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/templates/binarystore.xml.j2 @@ -0,0 +1,4 @@ + + + + diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/templates/installer-info.json.j2 b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/templates/installer-info.json.j2 new file mode 100644 index 0000000..f475256 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/templates/installer-info.json.j2 @@ -0,0 +1,12 @@ +{ + "productId": "Ansible_artifactory/1.0.0", + "features": [ + { + "featureId": "Partner/ACC-006973" + }, + { + "featureId": "Channel/{{ ansible_marketplace }}" + } + ] +} + diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/templates/join.key.j2 b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/templates/join.key.j2 new file mode 100644 index 0000000..17d05d2 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/templates/join.key.j2 @@ -0,0 +1 @@ +{{ join_key }} \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/templates/master.key.j2 b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/templates/master.key.j2 new file mode 100644 index 0000000..0462a64 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/templates/master.key.j2 @@ -0,0 +1 @@ +{{ master_key }} \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/templates/system.yaml.j2 b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/templates/system.yaml.j2 new file mode 100644 index 0000000..419a0c3 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/templates/system.yaml.j2 @@ -0,0 +1,38 @@ +## @formatter:off +## JFROG ARTIFACTORY SYSTEM CONFIGURATION FILE +## HOW TO USE: comment-out any field and keep the correct yaml indentation by deleting only the leading '#' character. +configVersion: 1 + +## NOTE: JFROG_HOME is a place holder for the JFrog root directory containing the deployed product, the home directory for all JFrog products. +## Replace JFROG_HOME with the real path! For example, in RPM install, JFROG_HOME=/opt/jfrog + +## NOTE: Sensitive information such as passwords and join key are encrypted on first read. +## NOTE: The provided commented key and value is the default. + +## SHARED CONFIGURATIONS +## A shared section for keys across all services in this config +shared: + + ## Node Settings + node: + ## A unique id to identify this node. + ## Default: auto generated at startup. + id: {{ ansible_machine_id }} + + ## Sets this node as primary in HA installation + primary: {{ artifactory_is_primary }} + + ## Sets this node as part of HA installation + haEnabled: {{ artifactory_ha_enabled }} + + ## Database Configuration + database: + ## One of: mysql, oracle, mssql, postgresql, mariadb + ## Default: Embedded derby + + ## Example for mysql/postgresql + type: "{{ db_type }}" + driver: "{{ db_driver }}" + url: "{{ db_url }}" + username: "{{ db_user }}" + password: "{{ db_password }}" \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/vars/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/vars/main.yml new file mode 100644 index 0000000..cd21505 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-ami/vars/main.yml @@ -0,0 +1,2 @@ +--- + diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/.travis.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/.travis.yml new file mode 100644 index 0000000..36bbf62 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/.travis.yml @@ -0,0 +1,29 @@ +--- +language: python +python: "2.7" + +# Use the new container infrastructure +sudo: false + +# Install ansible +addons: + apt: + packages: + - python-pip + +install: + # Install ansible + - pip install ansible + + # Check ansible version + - ansible --version + + # Create ansible.cfg with correct roles_path + - printf '[defaults]\nroles_path=../' >ansible.cfg + +script: + # Basic role syntax check + - ansible-playbook tests/test.yml -i tests/inventory --syntax-check + +notifications: + webhooks: https://galaxy.ansible.com/api/v1/notifications/ \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/defaults/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/defaults/main.yml new file mode 100644 index 0000000..6b28347 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/defaults/main.yml @@ -0,0 +1,2 @@ +--- +# defaults file for artifactory-nginx \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/files/nginx.conf b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/files/nginx.conf new file mode 100644 index 0000000..19f9422 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/files/nginx.conf @@ -0,0 +1,37 @@ +#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; + variables_hash_max_size 1024; + variables_hash_bucket_size 64; + server_names_hash_max_size 4096; + server_names_hash_bucket_size 128; + types_hash_max_size 2048; + types_hash_bucket_size 64; + proxy_read_timeout 2400s; + client_header_timeout 2400s; + client_body_timeout 2400s; + proxy_connect_timeout 75s; + proxy_send_timeout 2400s; + proxy_buffer_size 32k; + proxy_buffers 40 32k; + proxy_busy_buffers_size 64k; + proxy_temp_file_write_size 250m; + proxy_http_version 1.1; + client_body_buffer_size 128k; + 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; +} \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/handlers/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/handlers/main.yml new file mode 100644 index 0000000..d212386 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/handlers/main.yml @@ -0,0 +1,2 @@ +--- +# handlers file for artifactory-nginx \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/meta/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/meta/main.yml new file mode 100644 index 0000000..227ad9c --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/meta/main.yml @@ -0,0 +1,53 @@ +galaxy_info: + author: your name + description: your role description + company: your company (optional) + + # If the issue tracker for your role is not on github, uncomment the + # next line and provide a value + # issue_tracker_url: http://example.com/issue/tracker + + # Choose a valid license ID from https://spdx.org - some suggested licenses: + # - BSD-3-Clause (default) + # - MIT + # - GPL-2.0-or-later + # - GPL-3.0-only + # - Apache-2.0 + # - CC-BY-4.0 + license: license (GPL-2.0-or-later, MIT, etc) + + min_ansible_version: 2.9 + + # If this a Container Enabled role, provide the minimum Ansible Container version. + # min_ansible_container_version: + + # + # Provide a list of supported platforms, and for each platform a list of versions. + # If you don't wish to enumerate all versions for a particular platform, use 'all'. + # To view available platforms and versions (or releases), visit: + # https://galaxy.ansible.com/api/v1/platforms/ + # + # platforms: + # - name: Fedora + # versions: + # - all + # - 25 + # - name: SomePlatform + # versions: + # - all + # - 1.0 + # - 7 + # - 99.99 + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is a keyword that describes + # and categorizes the role. Users find roles by searching for tags. Be sure to + # remove the '[]' above, if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of alphanumeric characters. + # Maximum 20 tags per role. + +dependencies: [] + # List your role dependencies here, one per line. Be sure to remove the '[]' above, + # if you add dependencies to this list. + \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/tasks/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/tasks/main.yml new file mode 100644 index 0000000..abac794 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/tasks/main.yml @@ -0,0 +1,30 @@ +--- +- name: Add epel-release repo + yum: + name: epel-release + state: present + vars: + ansible_python_interpreter: /bin/python2 + +- name: Install nginx + yum: + name: nginx + state: present + vars: + ansible_python_interpreter: /bin/python2 + +- name: configure main nginx conf file. + copy: + src: nginx.conf + dest: /etc/nginx/nginx.conf + owner: root + group: root + mode: '0755' + become: yes + +- name: restart nginx + service: + name: nginx + state: restarted + enabled: yes + become: yes diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/templates/artifactory.conf.j2 b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/templates/artifactory.conf.j2 new file mode 100644 index 0000000..b36af22 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/templates/artifactory.conf.j2 @@ -0,0 +1,43 @@ +########################################################### +## this configuration was generated by JFrog Artifactory ## + ########################################################### + + ## add HA entries when ha is configure + upstream artifactory { + server 127.0.0.1:8082; +} + upstream artifactory-direct { + server 127.0.0.1:8081; +} + ## server configuration + server { + listen 80 ; + server_name _; + if ($http_x_forwarded_proto = '') { + set $http_x_forwarded_proto $scheme; + } + ## Application specific logs + access_log /var/log/nginx/artifactory-access.log; + error_log /var/log/nginx/artifactory-error.log; + rewrite ^/$ /ui/ redirect; + rewrite ^/ui$ /ui/ redirect; + chunked_transfer_encoding on; + client_max_body_size 0; + location / { + proxy_read_timeout 2400s; + proxy_pass_header Server; + proxy_cookie_path ~*^/.* /; + proxy_pass "http://artifactory"; + proxy_next_upstream error timeout non_idempotent; + proxy_next_upstream_tries 1; + proxy_set_header X-JFrog-Override-Base-Url $http_x_forwarded_proto://$host:$server_port; + 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; + + location ~ ^/artifactory/ { + proxy_pass http://artifactory-direct; + } + } +} \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/tests/inventory b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/tests/inventory new file mode 100644 index 0000000..878877b --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/tests/inventory @@ -0,0 +1,2 @@ +localhost + diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/tests/test.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/tests/test.yml new file mode 100644 index 0000000..7560bbb --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/tests/test.yml @@ -0,0 +1,5 @@ +--- +- hosts: localhost + remote_user: root + roles: + - artifactory-nginx \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/vars/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/vars/main.yml new file mode 100644 index 0000000..7465197 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ami/vars/main.yml @@ -0,0 +1,2 @@ +--- +# vars file for artifactory-nginx \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/.travis.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/.travis.yml new file mode 100644 index 0000000..36bbf62 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/.travis.yml @@ -0,0 +1,29 @@ +--- +language: python +python: "2.7" + +# Use the new container infrastructure +sudo: false + +# Install ansible +addons: + apt: + packages: + - python-pip + +install: + # Install ansible + - pip install ansible + + # Check ansible version + - ansible --version + + # Create ansible.cfg with correct roles_path + - printf '[defaults]\nroles_path=../' >ansible.cfg + +script: + # Basic role syntax check + - ansible-playbook tests/test.yml -i tests/inventory --syntax-check + +notifications: + webhooks: https://galaxy.ansible.com/api/v1/notifications/ \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/defaults/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/defaults/main.yml new file mode 100644 index 0000000..6b28347 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/defaults/main.yml @@ -0,0 +1,2 @@ +--- +# defaults file for artifactory-nginx \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/handlers/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/handlers/main.yml new file mode 100644 index 0000000..d212386 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/handlers/main.yml @@ -0,0 +1,2 @@ +--- +# handlers file for artifactory-nginx \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/meta/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/meta/main.yml new file mode 100644 index 0000000..227ad9c --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/meta/main.yml @@ -0,0 +1,53 @@ +galaxy_info: + author: your name + description: your role description + company: your company (optional) + + # If the issue tracker for your role is not on github, uncomment the + # next line and provide a value + # issue_tracker_url: http://example.com/issue/tracker + + # Choose a valid license ID from https://spdx.org - some suggested licenses: + # - BSD-3-Clause (default) + # - MIT + # - GPL-2.0-or-later + # - GPL-3.0-only + # - Apache-2.0 + # - CC-BY-4.0 + license: license (GPL-2.0-or-later, MIT, etc) + + min_ansible_version: 2.9 + + # If this a Container Enabled role, provide the minimum Ansible Container version. + # min_ansible_container_version: + + # + # Provide a list of supported platforms, and for each platform a list of versions. + # If you don't wish to enumerate all versions for a particular platform, use 'all'. + # To view available platforms and versions (or releases), visit: + # https://galaxy.ansible.com/api/v1/platforms/ + # + # platforms: + # - name: Fedora + # versions: + # - all + # - 25 + # - name: SomePlatform + # versions: + # - all + # - 1.0 + # - 7 + # - 99.99 + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is a keyword that describes + # and categorizes the role. Users find roles by searching for tags. Be sure to + # remove the '[]' above, if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of alphanumeric characters. + # Maximum 20 tags per role. + +dependencies: [] + # List your role dependencies here, one per line. Be sure to remove the '[]' above, + # if you add dependencies to this list. + \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/tasks/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/tasks/main.yml new file mode 100644 index 0000000..670c42d --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/tasks/main.yml @@ -0,0 +1,54 @@ +--- +# tasks file for artifactory-nginx +- name: configure the artifactory nginx conf + template: + src: artifactory.conf.j2 + dest: /etc/nginx/conf.d/artifactory.conf + owner: root + group: root + mode: '0755' + become: yes + +- name: ensure nginx dir exists + file: + path: "/var/opt/jfrog/nginx/ssl" + state: directory + become: yes + +- name: configure certificate + template: + src: certificate.pem.j2 + dest: "/var/opt/jfrog/nginx/ssl/cert.pem" + become: yes + +- name: ensure pki exists + file: + path: "/etc/pki/tls" + state: directory + become: yes + +- name: configure key + template: + src: certificate.key.j2 + dest: "/etc/pki/tls/cert.key" + become: yes + +- name: Allow apache to modify files in /srv/git_repos + sefcontext: + target: '/var/opt/jfrog/nginx/ssl/cert.pem' + setype: httpd_sys_content_t + state: present + vars: + ansible_python_interpreter: /bin/python2 + become: yes + +- name: Apply new SELinux file context to filesystem + command: restorecon -v /var/opt/jfrog/nginx/ssl/cert.pem + become: yes + +- name: restart nginx + service: + name: nginx + state: restarted + enabled: yes + become: yes diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/templates/artifactory.conf.j2 b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/templates/artifactory.conf.j2 new file mode 100644 index 0000000..13a2ac7 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/templates/artifactory.conf.j2 @@ -0,0 +1,49 @@ +########################################################### +## this configuration was generated by JFrog Artifactory ## + ########################################################### + + ## add HA entries when ha is configure + upstream artifactory { + server 127.0.0.1:8082; +} + upstream artifactory-direct { + server 127.0.0.1:8081; +} + ssl_protocols TLSv1.1 TLSv1.2; + ssl_certificate /var/opt/jfrog/nginx/ssl/cert.pem; + ssl_certificate_key /etc/pki/tls/cert.key; + ssl_session_cache shared:SSL:1m; + ssl_prefer_server_ciphers on; + ## server configuration + server { + listen 80; + listen 443 ssl http2; + server_name _; + if ($http_x_forwarded_proto = '') { + set $http_x_forwarded_proto $scheme; + } + ## Application specific logs + access_log /var/log/nginx/artifactory-access.log; + error_log /var/log/nginx/artifactory-error.log; + rewrite ^/$ /ui/ redirect; + rewrite ^/ui$ /ui/ redirect; + chunked_transfer_encoding on; + client_max_body_size 0; + location / { + proxy_read_timeout 2400s; + proxy_pass_header Server; + proxy_cookie_path ~*^/.* /; + proxy_pass "http://artifactory"; + proxy_next_upstream error timeout non_idempotent; + proxy_next_upstream_tries 1; + proxy_set_header X-JFrog-Override-Base-Url $http_x_forwarded_proto://$host:$server_port; + 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; + + location ~ ^/artifactory/ { + proxy_pass http://artifactory-direct; + } + } +} \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/templates/certificate.key.j2 b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/templates/certificate.key.j2 new file mode 100644 index 0000000..30f1d88 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/templates/certificate.key.j2 @@ -0,0 +1 @@ +{{ certificate_key | regex_replace('(-+(BEGIN|END) [A-Z ]*-+ ?|[A-Za-z0-9\+=/]* )', '\\1\n') }} diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/templates/certificate.pem.j2 b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/templates/certificate.pem.j2 new file mode 100644 index 0000000..d9dbd21 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/templates/certificate.pem.j2 @@ -0,0 +1 @@ +{{ certificate | regex_replace('(-+(BEGIN|END) [A-Z ]*-+ ?|[A-Za-z0-9\+=/]* )', '\\1\n') }} \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/tests/inventory b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/tests/inventory new file mode 100644 index 0000000..878877b --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/tests/inventory @@ -0,0 +1,2 @@ +localhost + diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/tests/test.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/tests/test.yml new file mode 100644 index 0000000..7560bbb --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/tests/test.yml @@ -0,0 +1,5 @@ +--- +- hosts: localhost + remote_user: root + roles: + - artifactory-nginx \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/vars/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/vars/main.yml new file mode 100644 index 0000000..7465197 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx-ssl/vars/main.yml @@ -0,0 +1,2 @@ +--- +# vars file for artifactory-nginx \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/.travis.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/.travis.yml new file mode 100644 index 0000000..36bbf62 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/.travis.yml @@ -0,0 +1,29 @@ +--- +language: python +python: "2.7" + +# Use the new container infrastructure +sudo: false + +# Install ansible +addons: + apt: + packages: + - python-pip + +install: + # Install ansible + - pip install ansible + + # Check ansible version + - ansible --version + + # Create ansible.cfg with correct roles_path + - printf '[defaults]\nroles_path=../' >ansible.cfg + +script: + # Basic role syntax check + - ansible-playbook tests/test.yml -i tests/inventory --syntax-check + +notifications: + webhooks: https://galaxy.ansible.com/api/v1/notifications/ \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/defaults/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/defaults/main.yml new file mode 100644 index 0000000..6b28347 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/defaults/main.yml @@ -0,0 +1,2 @@ +--- +# defaults file for artifactory-nginx \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/files/nginx.conf b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/files/nginx.conf new file mode 100644 index 0000000..19f9422 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/files/nginx.conf @@ -0,0 +1,37 @@ +#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; + variables_hash_max_size 1024; + variables_hash_bucket_size 64; + server_names_hash_max_size 4096; + server_names_hash_bucket_size 128; + types_hash_max_size 2048; + types_hash_bucket_size 64; + proxy_read_timeout 2400s; + client_header_timeout 2400s; + client_body_timeout 2400s; + proxy_connect_timeout 75s; + proxy_send_timeout 2400s; + proxy_buffer_size 32k; + proxy_buffers 40 32k; + proxy_busy_buffers_size 64k; + proxy_temp_file_write_size 250m; + proxy_http_version 1.1; + client_body_buffer_size 128k; + 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; +} \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/handlers/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/handlers/main.yml new file mode 100644 index 0000000..d212386 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/handlers/main.yml @@ -0,0 +1,2 @@ +--- +# handlers file for artifactory-nginx \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/meta/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/meta/main.yml new file mode 100644 index 0000000..227ad9c --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/meta/main.yml @@ -0,0 +1,53 @@ +galaxy_info: + author: your name + description: your role description + company: your company (optional) + + # If the issue tracker for your role is not on github, uncomment the + # next line and provide a value + # issue_tracker_url: http://example.com/issue/tracker + + # Choose a valid license ID from https://spdx.org - some suggested licenses: + # - BSD-3-Clause (default) + # - MIT + # - GPL-2.0-or-later + # - GPL-3.0-only + # - Apache-2.0 + # - CC-BY-4.0 + license: license (GPL-2.0-or-later, MIT, etc) + + min_ansible_version: 2.9 + + # If this a Container Enabled role, provide the minimum Ansible Container version. + # min_ansible_container_version: + + # + # Provide a list of supported platforms, and for each platform a list of versions. + # If you don't wish to enumerate all versions for a particular platform, use 'all'. + # To view available platforms and versions (or releases), visit: + # https://galaxy.ansible.com/api/v1/platforms/ + # + # platforms: + # - name: Fedora + # versions: + # - all + # - 25 + # - name: SomePlatform + # versions: + # - all + # - 1.0 + # - 7 + # - 99.99 + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is a keyword that describes + # and categorizes the role. Users find roles by searching for tags. Be sure to + # remove the '[]' above, if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of alphanumeric characters. + # Maximum 20 tags per role. + +dependencies: [] + # List your role dependencies here, one per line. Be sure to remove the '[]' above, + # if you add dependencies to this list. + \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/tasks/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/tasks/main.yml new file mode 100644 index 0000000..146ea79 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/tasks/main.yml @@ -0,0 +1,34 @@ +--- +- name: configure main nginx conf file. + copy: + src: nginx.conf + dest: /etc/nginx/nginx.conf + owner: root + group: root + mode: '0755' + become: yes + +- name: configure main nginx conf file. + copy: + src: nginx.conf + dest: /etc/nginx/nginx.conf + owner: root + group: root + mode: '0755' + become: yes + +- name: configure the artifactory nginx conf + template: + src: artifactory.conf.j2 + dest: /etc/nginx/conf.d/artifactory.conf + owner: root + group: root + mode: '0755' + become: yes + +- name: restart nginx + service: + name: nginx + state: restarted + enabled: yes + become: yes diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/templates/artifactory.conf.j2 b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/templates/artifactory.conf.j2 new file mode 100644 index 0000000..b36af22 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/templates/artifactory.conf.j2 @@ -0,0 +1,43 @@ +########################################################### +## this configuration was generated by JFrog Artifactory ## + ########################################################### + + ## add HA entries when ha is configure + upstream artifactory { + server 127.0.0.1:8082; +} + upstream artifactory-direct { + server 127.0.0.1:8081; +} + ## server configuration + server { + listen 80 ; + server_name _; + if ($http_x_forwarded_proto = '') { + set $http_x_forwarded_proto $scheme; + } + ## Application specific logs + access_log /var/log/nginx/artifactory-access.log; + error_log /var/log/nginx/artifactory-error.log; + rewrite ^/$ /ui/ redirect; + rewrite ^/ui$ /ui/ redirect; + chunked_transfer_encoding on; + client_max_body_size 0; + location / { + proxy_read_timeout 2400s; + proxy_pass_header Server; + proxy_cookie_path ~*^/.* /; + proxy_pass "http://artifactory"; + proxy_next_upstream error timeout non_idempotent; + proxy_next_upstream_tries 1; + proxy_set_header X-JFrog-Override-Base-Url $http_x_forwarded_proto://$host:$server_port; + 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; + + location ~ ^/artifactory/ { + proxy_pass http://artifactory-direct; + } + } +} \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/tests/inventory b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/tests/inventory new file mode 100644 index 0000000..878877b --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/tests/inventory @@ -0,0 +1,2 @@ +localhost + diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/tests/test.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/tests/test.yml new file mode 100644 index 0000000..7560bbb --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/tests/test.yml @@ -0,0 +1,5 @@ +--- +- hosts: localhost + remote_user: root + roles: + - artifactory-nginx \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/vars/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/vars/main.yml new file mode 100644 index 0000000..7465197 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory-nginx/vars/main.yml @@ -0,0 +1,2 @@ +--- +# vars file for artifactory-nginx \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/.travis.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/.travis.yml new file mode 100644 index 0000000..36bbf62 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/.travis.yml @@ -0,0 +1,29 @@ +--- +language: python +python: "2.7" + +# Use the new container infrastructure +sudo: false + +# Install ansible +addons: + apt: + packages: + - python-pip + +install: + # Install ansible + - pip install ansible + + # Check ansible version + - ansible --version + + # Create ansible.cfg with correct roles_path + - printf '[defaults]\nroles_path=../' >ansible.cfg + +script: + # Basic role syntax check + - ansible-playbook tests/test.yml -i tests/inventory --syntax-check + +notifications: + webhooks: https://galaxy.ansible.com/api/v1/notifications/ \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/defaults/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/defaults/main.yml new file mode 100644 index 0000000..bbcfe91 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/defaults/main.yml @@ -0,0 +1,52 @@ +--- +# defaults file for artifactory +# indicates were this collection was downlaoded from (galaxy, automation_hub, standalone) +ansible_marketplace: standalone + +# The version of Artifactory to install +artifactory_version: 7.15.3 + +# licenses - cluster license content in json +artifactory_licenses: + +# whether to enable HA +artifactory_ha_enabled: true + +# value for whether a host is primary. this should be set in host vars +artifactory_is_primary: true + +# The location where Artifactory should install. +artifactory_download_directory: /opt/jfrog + +# The location where Artifactory should store data. +artifactory_file_store_dir: /data + +# whether to customer data directory +use_custom_data_directory: false + +# location for customer directory. Will be symlink to as artifactory/var +custom_data_directory: /artifactory-user-data + +# Pick the Artifactory flavour to install, can be also cpp-ce, jcr, pro. +artifactory_flavour: pro + +extra_java_opts: -server -Xms2g -Xmx14g -Xss256k -XX:+UseG1GC + +artifactory_tar: https://releases.jfrog.io/artifactory/artifactory-pro/org/artifactory/{{ artifactory_flavour }}/jfrog-artifactory-{{ artifactory_flavour }}/{{ artifactory_version }}/jfrog-artifactory-{{ artifactory_flavour }}-{{ artifactory_version }}-linux.tar.gz +artifactory_home: "{{ artifactory_download_directory }}/artifactory-{{ artifactory_flavour }}-{{ artifactory_version }}" + +artifactory_user: artifactory +artifactory_group: artifactory + +# Set the parameters required for the service. +service_list: + - name: artifactory + description: Start script for Artifactory + start_command: "{{ artifactory_home }}/bin/artifactory.sh start" + stop_command: "{{ artifactory_home }}/bin/artifactory.sh stop" + type: forking + status_pattern: artifactory + user_name: "{{ artifactory_user }}" + group_name: "{{ artifactory_group }}" + +product_id: CloudFormation_QS_EC2/1.0.0 diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/handlers/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/handlers/main.yml new file mode 100644 index 0000000..6f8fcda --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/handlers/main.yml @@ -0,0 +1,10 @@ +--- +# handlers file for artifactory +- name: systemctl daemon-reload + systemd: + daemon_reload: yes + +- name: restart artifactory + service: + name: artifactory + state: restarted diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/meta/exception.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/meta/exception.yml new file mode 100644 index 0000000..7de46df --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/meta/exception.yml @@ -0,0 +1,6 @@ +--- +exceptions: + - variation: Alpine + reason: Artifactory start/stop scripts don't properly work. + - variation: amazonlinux:1 + reason: "Shutting down artifactory: /usr/bin/java\nfinding\nUsing the default catalina management port (8015) to test shutdown\nArtifactory Tomcat already stopped" diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/meta/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/meta/main.yml new file mode 100644 index 0000000..0dc573a --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/meta/main.yml @@ -0,0 +1,35 @@ +--- +galaxy_info: + author: Robert de Bock + role_name: artifactory + description: Install and configure artifactory on your system. + license: Apache-2.0 + company: none + min_ansible_version: 2.8 + + platforms: + - name: Debian + versions: + - all + - name: EL + versions: + - 7 + - 8 + - name: Fedora + versions: + - all + - name: OpenSUSE + versions: + - all + - name: Ubuntu + versions: + - bionic + + galaxy_tags: + - artifactory + - centos + - redhat + - server + - system + +dependencies: [] diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/meta/preferences.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/meta/preferences.yml new file mode 100644 index 0000000..e7fdebf --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/meta/preferences.yml @@ -0,0 +1,2 @@ +--- +tox_parallel: yes diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/meta/version.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/meta/version.yml new file mode 100644 index 0000000..024188d --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/meta/version.yml @@ -0,0 +1,6 @@ +--- +project_name: JFrog +reference: "https://github.com/robertdebock/ansible-role-artifactory/blob/master/defaults/main.yml" +versions: + - name: Artifactory + url: "https://releases.jfrog.io/artifactory/" diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/tasks/configure-licenses.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/tasks/configure-licenses.yml new file mode 100644 index 0000000..996f68e --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/tasks/configure-licenses.yml @@ -0,0 +1,43 @@ +- name: set license for Enterprise + block: + - name: use license file + copy: + src: "{{ artifactory_license_file }}" + dest: "{{ artifactory_home }}/var/etc/artifactory/artifactory.cluster.license" + force: no # only copy if file doesn't exist + become: yes + when: artifactory_license_file is defined and artifactory_is_primary == true + + - name: use license strings + vars: + artifactory_licenses_dict: "{{ artifactory_licenses | default('{}') }}" + + template: + src: artifactory.cluster.license.j2 + dest: "{{ artifactory_home }}/var/etc/artifactory/artifactory.cluster.license" + force: no # only create if file doesn't exist + become: yes + when: artifactory_license_file is not defined and artifactory_is_primary == true + when: artifactory_ha_enabled + +- name: set license for Pro + block: + - name: use license file + copy: + src: "{{ artifactory_license_file }}" + dest: "{{ artifactory_home }}/var/etc/artifactory/artifactory.lic" + force: no # only create if file doesn't exist + become: yes + when: artifactory_license_file is defined + + - name: use license strings + vars: + artifactory_licenses_dict: "{{ artifactory_licenses | default('{}') }}" + + template: + src: artifactory.pro.license.j2 + dest: "{{ artifactory_home }}/var/etc/artifactory/artifactory.lic" + force: no # only create if file doesn't exist + become: yes + when: artifactory_license_file is not defined + when: not artifactory_ha_enabled diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/tasks/custom-data-directory.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/tasks/custom-data-directory.yml new file mode 100644 index 0000000..4799a8b --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/tasks/custom-data-directory.yml @@ -0,0 +1,44 @@ +- name: setup directory symlink for using custom data directory/volume + block: + - name: Create a xfs filesystem on /dev/nvme1n1 + # First non-root device is always mapped to /dev/nvme1n1 + # See: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nvme-ebs-volumes.html + community.general.filesystem: + dev: /dev/nvme1n1 + fstype: xfs + + - name: ensure external data directory exists + file: + path: "{{ custom_data_directory }}" + state: directory + + - name: Mount the EBS volume + ansible.posix.mount: + path: "{{ custom_data_directory }}" + src: /dev/nvme1n1 + state: mounted + fstype: xfs + + - name: set custom data directory permission + file: + path: "{{ custom_data_directory }}" + state: directory + recurse: yes + owner: "{{ artifactory_user }}" + group: "{{ artifactory_group }}" + mode: "u=rwX,g=rwX,o=rwX" + + - name: remove var directory if exists + file: + path: "{{ artifactory_home }}/var" + state: absent + + - name: symlink custom data directory to var + file: + src: "{{ custom_data_directory }}" + path: "{{ artifactory_home }}/var" + state: link + owner: "{{ artifactory_user }}" + group: "{{ artifactory_group }}" + become: yes + when: use_custom_data_directory and custom_data_directory is defined diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/tasks/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/tasks/main.yml new file mode 100644 index 0000000..25b1143 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/tasks/main.yml @@ -0,0 +1,132 @@ +--- +# tasks file for artifactory +- name: Set artifactory major version + set_fact: + artifactory_major_verion: "{{ artifactory_version.split('.')[0] }}" + +- name: create group for artifactory + group: + name: "{{ artifactory_group }}" + state: present + become: yes + +- name: create user for artifactory + user: + name: "{{ artifactory_user }}" + group: "{{ artifactory_group }}" + system: yes + become: yes + +- name: ensure artifactory_download_directory exists + file: + path: "{{ artifactory_download_directory }}" + state: directory + become: yes + +- name: ensure artifactory_file_store_dir exists + file: + path: "{{ artifactory_file_store_dir }}" + state: directory + owner: "{{ artifactory_user }}" + group: "{{ artifactory_group }}" + become: yes + +- name: setup directory symlink for using custom data directory/volume + include_tasks: custom-data-directory.yml + when: use_custom_data_directory and custom_data_directory is defined + +- name: ensure data subdirectories exist and have correct ownership + file: + path: "{{ artifactory_home }}/var/{{ item }}" + state: directory + owner: "{{ artifactory_user }}" + group: "{{ artifactory_group }}" + loop: + - "bootstrap" + - "etc" + - "data" + - "etc/info" + - "etc/security" + - "etc/artifactory" + become: yes + +- name: check if system yaml file exits + stat: + path: "{{ artifactory_home }}/var/etc/system.yaml" + register: system_yaml + +- name: use specified system yaml + copy: + src: "{{ system_file }}" + dest: "{{ artifactory_home }}/var/etc/system.yaml" + become: yes + when: system_file is defined and not system_yaml.stat.exists + +- name: configure system yaml + template: + src: system.yaml.j2 + dest: "{{ artifactory_home }}/var/etc/system.yaml" + become: yes + when: system_file is not defined and not system_yaml.stat.exists + +- name: configure master key + template: + src: master.key.j2 + dest: "{{ artifactory_home }}/var/etc/security/master.key" + force: no # only create if file doesn't exist + become: yes + +- name: configure join key + template: + src: join.key.j2 + dest: "{{ artifactory_home }}/var/etc/security/join.key" + force: no # only create if file doesn't exist + become: yes + +- name: configure installer info + template: + src: installer-info.json.j2 + dest: "{{ artifactory_home }}/var/etc/info/installer-info.json" + become: yes + +- name: use specified binary store file + copy: + src: "{{ binary_store_file }}" + dest: "{{ artifactory_home }}/var/etc/artifactory/binarystore.xml" + force: no # only copy if file doesn't exist + become: yes + when: binary_store_file is defined + +- name: set default binary store + template: + src: binarystore.xml.j2 + dest: "{{ artifactory_home }}/var/etc/artifactory/binarystore.xml" + force: no # only create if file doesn't exist + become: yes + when: binary_store_file is not defined + +- name: configure licenses + include_tasks: configure-licenses.yml + +- name: create artifactory service + shell: "{{ artifactory_home }}/app/bin/installService.sh" + become: yes + +- name: start and enable the primary node + service: + name: artifactory + state: restarted + become: yes + when: artifactory_is_primary == true + +- name: random wait before restarting to prevent secondary nodes from hitting DB first + pause: + seconds: "{{ 120 | random + 10}}" + when: artifactory_is_primary == false + +- name: start and enable the secondary nodes + service: + name: artifactory + state: restarted + become: yes + when: artifactory_is_primary == false diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/templates/artifactory.cluster.license.j2 b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/templates/artifactory.cluster.license.j2 new file mode 100644 index 0000000..aa30261 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/templates/artifactory.cluster.license.j2 @@ -0,0 +1,6 @@ +{% if artifactory_licenses_dict %} +{% for key in (artifactory_licenses_dict.keys() | select('match', '^ArtifactoryLicense\d$')) %} +{{ artifactory_licenses_dict[key] }} + +{% endfor %} +{% endif %} diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/templates/artifactory.pro.license.j2 b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/templates/artifactory.pro.license.j2 new file mode 100644 index 0000000..f6881c9 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/templates/artifactory.pro.license.j2 @@ -0,0 +1,8 @@ +{% if artifactory_licenses_dict %} +{% for key in (artifactory_licenses_dict.keys() | select('match', '^ArtifactoryLicense\d$')) %} +{% if loop.first %} + {{ artifactory_licenses_dict[key] }} +{% endif %} + +{% endfor %} +{% endif %} diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/templates/binarystore.xml.j2 b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/templates/binarystore.xml.j2 new file mode 100644 index 0000000..f12dba1 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/templates/binarystore.xml.j2 @@ -0,0 +1,14 @@ + + + + + + + + s3.{{ s3_region }}.amazonaws.com + {{ s3_bucket }} + artifactory/filestore + {{ s3_region }} + true + + diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/templates/installer-info.json.j2 b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/templates/installer-info.json.j2 new file mode 100644 index 0000000..9e78f0e --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/templates/installer-info.json.j2 @@ -0,0 +1,11 @@ +{ + "productId": "{{ product_id }}", + "features": [ + { + "featureId": "Partner/ACC-006973" + }, + { + "featureId": "Channel/{{ ansible_marketplace }}" + } + ] +} diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/templates/join.key.j2 b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/templates/join.key.j2 new file mode 100644 index 0000000..17d05d2 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/templates/join.key.j2 @@ -0,0 +1 @@ +{{ join_key }} \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/templates/master.key.j2 b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/templates/master.key.j2 new file mode 100644 index 0000000..0462a64 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/templates/master.key.j2 @@ -0,0 +1 @@ +{{ master_key }} \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/templates/system.yaml.j2 b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/templates/system.yaml.j2 new file mode 100644 index 0000000..dc58c2c --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/templates/system.yaml.j2 @@ -0,0 +1,40 @@ +## @formatter:off +## JFROG ARTIFACTORY SYSTEM CONFIGURATION FILE +## HOW TO USE: comment-out any field and keep the correct yaml indentation by deleting only the leading '#' character. +configVersion: 1 + +## NOTE: JFROG_HOME is a place holder for the JFrog root directory containing the deployed product, the home directory for all JFrog products. +## Replace JFROG_HOME with the real path! For example, in RPM install, JFROG_HOME=/opt/jfrog + +## NOTE: Sensitive information such as passwords and join key are encrypted on first read. +## NOTE: The provided commented key and value is the default. + +## SHARED CONFIGURATIONS +## A shared section for keys across all services in this config +shared: + ## Java options + extraJavaOpts: "{{ extra_java_opts }}" + + ## Node Settings + node: + ## A unique id to identify this node. + ## Default: auto generated at startup. + id: {{ ansible_machine_id }} + + ## Sets this node as primary in HA installation + primary: {{ artifactory_is_primary }} + + ## Sets this node as part of HA installation + haEnabled: {{ artifactory_ha_enabled }} + + ## Database Configuration + database: + ## One of: mysql, oracle, mssql, postgresql, mariadb + ## Default: Embedded derby + + ## Example for mysql/postgresql + type: "{{ db_type }}" + driver: "{{ db_driver }}" + url: "{{ db_url }}" + username: "{{ db_user }}" + password: "{{ db_password }}" diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/vars/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/vars/main.yml new file mode 100644 index 0000000..cd21505 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/artifactory/vars/main.yml @@ -0,0 +1,2 @@ +--- + diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/.travis.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/.travis.yml new file mode 100644 index 0000000..36bbf62 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/.travis.yml @@ -0,0 +1,29 @@ +--- +language: python +python: "2.7" + +# Use the new container infrastructure +sudo: false + +# Install ansible +addons: + apt: + packages: + - python-pip + +install: + # Install ansible + - pip install ansible + + # Check ansible version + - ansible --version + + # Create ansible.cfg with correct roles_path + - printf '[defaults]\nroles_path=../' >ansible.cfg + +script: + # Basic role syntax check + - ansible-playbook tests/test.yml -i tests/inventory --syntax-check + +notifications: + webhooks: https://galaxy.ansible.com/api/v1/notifications/ \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/defaults/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/defaults/main.yml new file mode 100644 index 0000000..f547a88 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/defaults/main.yml @@ -0,0 +1,26 @@ +--- +# defaults file for xray +# indicates were this collection was downlaoded from (galaxy, automation_hub, standalone) +ansible_marketplace: standalone + +# whether we are creating a AMI for Marketplace or just for configuring EC2 instance +ami_creation: false + +# The version of xray to install +xray_version: 3.17.4 + +# whether to enable HA +xray_ha_enabled: true + +# The location where xray should install. +xray_download_directory: /opt/jfrog + +# The remote xray download file +xray_tar: https://releases.jfrog.io/artifactory/jfrog-xray/xray-linux/{{ xray_version }}/jfrog-xray-{{ xray_version }}-linux.tar.gz + +#The xray install directory +xray_home: "{{ xray_download_directory }}/jfrog-xray-{{ xray_version }}-linux" + +#xray users and groups +xray_user: xray +xray_group: xray diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/handlers/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/handlers/main.yml new file mode 100644 index 0000000..f236fe3 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/handlers/main.yml @@ -0,0 +1,2 @@ +--- +# handlers file for xray \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/meta/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/meta/main.yml new file mode 100644 index 0000000..227ad9c --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/meta/main.yml @@ -0,0 +1,53 @@ +galaxy_info: + author: your name + description: your role description + company: your company (optional) + + # If the issue tracker for your role is not on github, uncomment the + # next line and provide a value + # issue_tracker_url: http://example.com/issue/tracker + + # Choose a valid license ID from https://spdx.org - some suggested licenses: + # - BSD-3-Clause (default) + # - MIT + # - GPL-2.0-or-later + # - GPL-3.0-only + # - Apache-2.0 + # - CC-BY-4.0 + license: license (GPL-2.0-or-later, MIT, etc) + + min_ansible_version: 2.9 + + # If this a Container Enabled role, provide the minimum Ansible Container version. + # min_ansible_container_version: + + # + # Provide a list of supported platforms, and for each platform a list of versions. + # If you don't wish to enumerate all versions for a particular platform, use 'all'. + # To view available platforms and versions (or releases), visit: + # https://galaxy.ansible.com/api/v1/platforms/ + # + # platforms: + # - name: Fedora + # versions: + # - all + # - 25 + # - name: SomePlatform + # versions: + # - all + # - 1.0 + # - 7 + # - 99.99 + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is a keyword that describes + # and categorizes the role. Users find roles by searching for tags. Be sure to + # remove the '[]' above, if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of alphanumeric characters. + # Maximum 20 tags per role. + +dependencies: [] + # List your role dependencies here, one per line. Be sure to remove the '[]' above, + # if you add dependencies to this list. + \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/tasks/Debian.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/tasks/Debian.yml new file mode 100644 index 0000000..420c2d0 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/tasks/Debian.yml @@ -0,0 +1,37 @@ +--- +- name: Install db5.3-util + apt: + deb: "{{ xray_home }}/app/third-party/misc/db5.3-util_5.3.28-3ubuntu3_amd64.deb" + ignore_errors: yes + become: yes + +- name: Install db-util + apt: + deb: "{{ xray_home }}/app/third-party/misc/db-util_1_3a5.3.21exp1ubuntu1_all.deb" + ignore_errors: yes + become: yes + +- name: Install libssl + apt: + deb: "{{ xray_home }}/app/third-party/rabbitmq/libssl1.1_1.1.0j-1_deb9u1_amd64.deb" + ignore_errors: yes + become: yes + +- name: Install socat + apt: + deb: "{{ xray_home }}/app/third-party/rabbitmq/socat_1.7.3.1-2+deb9u1_amd64.deb" + become: yes + +- name: Install libwxbase3.0-0v5 + apt: + name: libwxbase3.0-0v5 + update_cache: yes + state: present + ignore_errors: yes + become: yes + +- name: Install erlang + apt: + deb: "{{ xray_home }}/app/third-party/rabbitmq/esl-erlang_21.2.1-1~ubuntu~xenial_amd64.deb" + become: yes + diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/tasks/RedHat.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/tasks/RedHat.yml new file mode 100644 index 0000000..efdc081 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/tasks/RedHat.yml @@ -0,0 +1,21 @@ +--- +- name: Install db-utl + yum: + name: "{{ xray_home }}/app/third-party/misc/libdb-utils-5.3.21-19.el7.x86_64.rpm" + state: present + vars: + ansible_python_interpreter: /bin/python2 + +- name: Install socat + yum: + name: "{{ xray_home }}/app/third-party/rabbitmq/socat-1.7.3.2-2.el7.x86_64.rpm" + state: present + vars: + ansible_python_interpreter: /bin/python2 + +- name: Install erlang + yum: + name: "{{ xray_home }}/app/third-party/rabbitmq/erlang-22.3.4-1.el7.x86_64.rpm" + state: present + vars: + ansible_python_interpreter: /bin/python2 diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/tasks/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/tasks/main.yml new file mode 100644 index 0000000..6bf93a5 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/tasks/main.yml @@ -0,0 +1,60 @@ +--- +- name: create group for xray + group: + name: "{{ xray_group }}" + state: present + become: yes + +- name: create user for xray + user: + name: "{{ xray_user }}" + group: "{{ xray_group }}" + system: yes + become: yes + +- name: ensure xray_download_directory exists + file: + path: "{{ xray_download_directory }}" + state: directory + become: yes + +- name: download xray + unarchive: + src: "{{ xray_tar }}" + dest: "{{ xray_download_directory }}" + remote_src: yes + owner: "{{ xray_user }}" + group: "{{ xray_group }}" + creates: "{{ xray_home }}" + become: yes + register: downloadxray + until: downloadxray is succeeded + retries: 3 + +- name: perform prerequisite installation + include_tasks: "{{ ansible_os_family }}.yml" + +- name: ensure etc exists + file: + path: "{{ xray_home }}/var/etc" + state: directory + owner: "{{ xray_user }}" + group: "{{ xray_group }}" + become: yes + +- name: Remove SSH keys + file: + path: "{{ ssh_keys.dir }}" + state: absent + loop: + - dir: "/home/.xray_ami/.ssh/authorized_keys" + - dir: "/root/.ssh/authorized_keys" + - dir: "/home/centos/.ssh/authorized_keys" + loop_control: + loop_var: ssh_keys + when: ami_creation + +- name: shutdown VM + command: /sbin/shutdown -h now + ignore_errors: 'yes' + when: ami_creation diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/templates/installer-info.json.j2 b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/templates/installer-info.json.j2 new file mode 100644 index 0000000..a76c88c --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/templates/installer-info.json.j2 @@ -0,0 +1,11 @@ +{ + "productId": "Ansible_artifactory/1.0.0", + "features": [ + { + "featureId": "Partner/ACC-006973" + }, + { + "featureId": "Channel/{{ ansible_marketplace }}" + } + ] +} \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/templates/join.key.j2 b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/templates/join.key.j2 new file mode 100644 index 0000000..17d05d2 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/templates/join.key.j2 @@ -0,0 +1 @@ +{{ join_key }} \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/templates/master.key.j2 b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/templates/master.key.j2 new file mode 100644 index 0000000..0462a64 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/templates/master.key.j2 @@ -0,0 +1 @@ +{{ master_key }} \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/templates/system.yaml.j2 b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/templates/system.yaml.j2 new file mode 100644 index 0000000..206eb77 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/templates/system.yaml.j2 @@ -0,0 +1,36 @@ +## @formatter:off +## JFROG ARTIFACTORY SYSTEM CONFIGURATION FILE +## HOW TO USE: comment-out any field and keep the correct yaml indentation by deleting only the leading '#' character. +configVersion: 1 + +## NOTE: JFROG_HOME is a place holder for the JFrog root directory containing the deployed product, the home directory for all JFrog products. +## Replace JFROG_HOME with the real path! For example, in RPM install, JFROG_HOME=/opt/jfrog + +## NOTE: Sensitive information such as passwords and join key are encrypted on first read. +## NOTE: The provided commented key and value is the default. + +## SHARED CONFIGURATIONS +## A shared section for keys across all services in this config +shared: + ## Base URL of the JFrog Platform Deployment (JPD) + ## This is the URL to the machine where JFrog Artifactory is deployed, or the load balancer pointing to it. It is recommended to use DNS names rather than direct IPs. + ## Examples: "http://jfrog.acme.com" or "http://10.20.30.40:8082" + jfrogUrl: {{ jfrog_url }} + + ## Node Settings + node: + ## A unique id to identify this node. + ## Default: auto generated at startup. + id: {{ ansible_machine_id }} + + ## Database Configuration + database: + ## One of: mysql, oracle, mssql, postgresql, mariadb + ## Default: Embedded derby + + ## Example for mysql/postgresql + type: "{{ db_type }}" + driver: "{{ db_driver }}" + url: "{{ db_url }}" + username: "{{ db_user }}" + password: "{{ db_password }}" \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/tests/inventory b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/tests/inventory new file mode 100644 index 0000000..878877b --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/tests/inventory @@ -0,0 +1,2 @@ +localhost + diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/tests/test.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/tests/test.yml new file mode 100644 index 0000000..f296da6 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/tests/test.yml @@ -0,0 +1,5 @@ +--- +- hosts: localhost + remote_user: root + roles: + - xray \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/vars/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/vars/main.yml new file mode 100644 index 0000000..55363e6 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray-ami/vars/main.yml @@ -0,0 +1,2 @@ +--- +# vars file for xray \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/.travis.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/.travis.yml new file mode 100644 index 0000000..36bbf62 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/.travis.yml @@ -0,0 +1,29 @@ +--- +language: python +python: "2.7" + +# Use the new container infrastructure +sudo: false + +# Install ansible +addons: + apt: + packages: + - python-pip + +install: + # Install ansible + - pip install ansible + + # Check ansible version + - ansible --version + + # Create ansible.cfg with correct roles_path + - printf '[defaults]\nroles_path=../' >ansible.cfg + +script: + # Basic role syntax check + - ansible-playbook tests/test.yml -i tests/inventory --syntax-check + +notifications: + webhooks: https://galaxy.ansible.com/api/v1/notifications/ \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/defaults/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/defaults/main.yml new file mode 100644 index 0000000..77a3f0c --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/defaults/main.yml @@ -0,0 +1,29 @@ +--- +# defaults file for xray +# indicates were this collection was downlaoded from (galaxy, automation_hub, standalone) +ansible_marketplace: standalone + +# The version of xray to install +xray_version: 3.17.4 + +# whether to enable HA +xray_ha_enabled: true + +# The location where xray should install. +xray_download_directory: /opt/jfrog + +# whether to customer data directory +use_custom_data_directory: false + +# location for customer directory. Will be symlink to as artifactory/var +custom_data_directory: /xray-user-data + +# The remote xray download file +xray_tar: https://releases.jfrog.io/artifactory/jfrog-xray/xray-linux/{{ xray_version }}/jfrog-xray-{{ xray_version }}-linux.tar.gz + +#The xray install directory +xray_home: "{{ xray_download_directory }}/jfrog-xray-{{ xray_version }}-linux" + +#xray users and groups +xray_user: xray +xray_group: xray diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/handlers/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/handlers/main.yml new file mode 100644 index 0000000..f236fe3 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/handlers/main.yml @@ -0,0 +1,2 @@ +--- +# handlers file for xray \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/meta/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/meta/main.yml new file mode 100644 index 0000000..227ad9c --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/meta/main.yml @@ -0,0 +1,53 @@ +galaxy_info: + author: your name + description: your role description + company: your company (optional) + + # If the issue tracker for your role is not on github, uncomment the + # next line and provide a value + # issue_tracker_url: http://example.com/issue/tracker + + # Choose a valid license ID from https://spdx.org - some suggested licenses: + # - BSD-3-Clause (default) + # - MIT + # - GPL-2.0-or-later + # - GPL-3.0-only + # - Apache-2.0 + # - CC-BY-4.0 + license: license (GPL-2.0-or-later, MIT, etc) + + min_ansible_version: 2.9 + + # If this a Container Enabled role, provide the minimum Ansible Container version. + # min_ansible_container_version: + + # + # Provide a list of supported platforms, and for each platform a list of versions. + # If you don't wish to enumerate all versions for a particular platform, use 'all'. + # To view available platforms and versions (or releases), visit: + # https://galaxy.ansible.com/api/v1/platforms/ + # + # platforms: + # - name: Fedora + # versions: + # - all + # - 25 + # - name: SomePlatform + # versions: + # - all + # - 1.0 + # - 7 + # - 99.99 + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is a keyword that describes + # and categorizes the role. Users find roles by searching for tags. Be sure to + # remove the '[]' above, if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of alphanumeric characters. + # Maximum 20 tags per role. + +dependencies: [] + # List your role dependencies here, one per line. Be sure to remove the '[]' above, + # if you add dependencies to this list. + \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/tasks/Debian.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/tasks/Debian.yml new file mode 100644 index 0000000..420c2d0 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/tasks/Debian.yml @@ -0,0 +1,37 @@ +--- +- name: Install db5.3-util + apt: + deb: "{{ xray_home }}/app/third-party/misc/db5.3-util_5.3.28-3ubuntu3_amd64.deb" + ignore_errors: yes + become: yes + +- name: Install db-util + apt: + deb: "{{ xray_home }}/app/third-party/misc/db-util_1_3a5.3.21exp1ubuntu1_all.deb" + ignore_errors: yes + become: yes + +- name: Install libssl + apt: + deb: "{{ xray_home }}/app/third-party/rabbitmq/libssl1.1_1.1.0j-1_deb9u1_amd64.deb" + ignore_errors: yes + become: yes + +- name: Install socat + apt: + deb: "{{ xray_home }}/app/third-party/rabbitmq/socat_1.7.3.1-2+deb9u1_amd64.deb" + become: yes + +- name: Install libwxbase3.0-0v5 + apt: + name: libwxbase3.0-0v5 + update_cache: yes + state: present + ignore_errors: yes + become: yes + +- name: Install erlang + apt: + deb: "{{ xray_home }}/app/third-party/rabbitmq/esl-erlang_21.2.1-1~ubuntu~xenial_amd64.deb" + become: yes + diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/tasks/RedHat.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/tasks/RedHat.yml new file mode 100644 index 0000000..efdc081 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/tasks/RedHat.yml @@ -0,0 +1,21 @@ +--- +- name: Install db-utl + yum: + name: "{{ xray_home }}/app/third-party/misc/libdb-utils-5.3.21-19.el7.x86_64.rpm" + state: present + vars: + ansible_python_interpreter: /bin/python2 + +- name: Install socat + yum: + name: "{{ xray_home }}/app/third-party/rabbitmq/socat-1.7.3.2-2.el7.x86_64.rpm" + state: present + vars: + ansible_python_interpreter: /bin/python2 + +- name: Install erlang + yum: + name: "{{ xray_home }}/app/third-party/rabbitmq/erlang-22.3.4-1.el7.x86_64.rpm" + state: present + vars: + ansible_python_interpreter: /bin/python2 diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/tasks/custom-data-directory.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/tasks/custom-data-directory.yml new file mode 100644 index 0000000..8f359ca --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/tasks/custom-data-directory.yml @@ -0,0 +1,44 @@ +- name: setup directory symlink for using custom data directory/volume + block: + - name: Create a xfs filesystem on /dev/nvme1n1 + # First non-root device is always mapped to /dev/nvme1n1 + # See: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nvme-ebs-volumes.html + community.general.filesystem: + dev: /dev/nvme1n1 + fstype: xfs + + - name: ensure external data directory exists + file: + path: "{{ custom_data_directory }}" + state: directory + + - name: Mount the EBS volume + ansible.posix.mount: + path: "{{ custom_data_directory }}" + src: /dev/nvme1n1 + state: mounted + fstype: xfs + + - name: set custom data directory permission + file: + path: "{{ custom_data_directory }}" + state: directory + recurse: yes + owner: "{{ xray_user }}" + group: "{{ xray_group }}" + mode: "u=rwX,g=rwX,o=rwX" + + - name: remove var directory if exists + file: + path: "{{ xray_home }}/var" + state: absent + + - name: symlink custom data directory to var + file: + src: "{{ custom_data_directory }}" + path: "{{ xray_home }}/var" + state: link + owner: "{{ xray_user }}" + group: "{{ xray_group }}" + become: yes + when: use_custom_data_directory and custom_data_directory is defined diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/tasks/initialize-pg-db.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/tasks/initialize-pg-db.yml new file mode 100644 index 0000000..87334b7 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/tasks/initialize-pg-db.yml @@ -0,0 +1,52 @@ +- name: initialize Postgres DB + block: + - name: check if user/role exists + command: psql -A -t {{db_master_url}} -c "SELECT 1 FROM pg_roles WHERE rolname='{{db_user}}'" + register: user_exists + + - debug: + var: user_exists.stdout_lines + + - name: create user/role + command: psql {{db_master_url}} -c "CREATE USER {{db_user}} WITH PASSWORD '{{db_password}}'" + register: shell_output + when: user_exists.stdout != "1" + + - debug: + var: shell_output.stdout_lines + when: user_exists.stdout != "1" + + - name: grant membership role + command: psql {{db_master_url}} -c "GRANT {{db_user}} TO {{db_master_user}}" + register: shell_output + when: user_exists.stdout != "1" + + - debug: + var: shell_output.stdout_lines + when: user_exists.stdout != "1" + + - name: check if xraydb exists + command: psql -A -t {{db_master_url}} -c "SELECT 1 FROM pg_database WHERE datname='xraydb'" + register: db_exists + + - debug: + var: db_exists.stdout_lines + + - name: create xraydb database + command: psql {{db_master_url}} -c "CREATE DATABASE xraydb WITH OWNER={{db_user}} ENCODING='UTF8'" + register: shell_output + when: db_exists.stdout != "1" + + - debug: + var: shell_output.stdout_lines + when: db_exists.stdout != "1" + + - name: grant xraydb privileges to role + command: psql {{db_master_url}} -c "GRANT ALL PRIVILEGES ON DATABASE xraydb TO {{db_user}}" + register: shell_output + when: db_exists.stdout != "1" + + - debug: + var: shell_output.stdout_lines + when: db_exists.stdout != "1" + become: yes diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/tasks/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/tasks/main.yml new file mode 100644 index 0000000..4ae86d6 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/tasks/main.yml @@ -0,0 +1,80 @@ +--- +- name: initialize postgres database + include_tasks: initialize-pg-db.yml + +- name: create group for xray + group: + name: "{{ xray_group }}" + state: present + become: yes + +- name: create user for xray + user: + name: "{{ xray_user }}" + group: "{{ xray_group }}" + system: yes + become: yes + +- name: ensure xray_download_directory exists + file: + path: "{{ xray_download_directory }}" + state: directory + become: yes + +- name: perform prerequisite installation + include_tasks: "{{ ansible_os_family }}.yml" + +- name: setup directory symlink for using custom data directory/volume + include_tasks: custom-data-directory.yml + when: use_custom_data_directory and custom_data_directory is defined + +- name: ensure data subdirectories exist and have correct ownership + file: + path: "{{ xray_home }}/var/{{ item }}" + state: directory + owner: "{{ xray_user }}" + group: "{{ xray_group }}" + loop: + - "etc" + - "data" + - "etc/info" + - "etc/security" + become: yes + +- name: configure system yaml + template: + src: system.yaml.j2 + dest: "{{ xray_home }}/var/etc/system.yaml" + force: no # only create if file doesn't exist + become: yes + +- name: configure master key + template: + src: master.key.j2 + dest: "{{ xray_home }}/var/etc/security/master.key" + force: no # only create if file doesn't exist + become: yes + +- name: configure join key + template: + src: join.key.j2 + dest: "{{ xray_home }}/var/etc/security/join.key" + force: no # only create if file doesn't exist + become: yes + +- name: configure installer info + template: + src: installer-info.json.j2 + dest: "{{ xray_home }}/var/etc/info/installer-info.json" + force: no # only create if file doesn't exist + become: yes + +- name: create xray service + shell: "{{ xray_home }}/app/bin/installService.sh" + become: yes + +- name: start and enable xray + service: + name: xray + state: restarted + become: yes diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/templates/installer-info.json.j2 b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/templates/installer-info.json.j2 new file mode 100644 index 0000000..a76c88c --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/templates/installer-info.json.j2 @@ -0,0 +1,11 @@ +{ + "productId": "Ansible_artifactory/1.0.0", + "features": [ + { + "featureId": "Partner/ACC-006973" + }, + { + "featureId": "Channel/{{ ansible_marketplace }}" + } + ] +} \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/templates/join.key.j2 b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/templates/join.key.j2 new file mode 100644 index 0000000..17d05d2 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/templates/join.key.j2 @@ -0,0 +1 @@ +{{ join_key }} \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/templates/master.key.j2 b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/templates/master.key.j2 new file mode 100644 index 0000000..0462a64 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/templates/master.key.j2 @@ -0,0 +1 @@ +{{ master_key }} \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/templates/system.yaml.j2 b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/templates/system.yaml.j2 new file mode 100644 index 0000000..c6aca8d --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/templates/system.yaml.j2 @@ -0,0 +1,39 @@ +## @formatter:off +## JFROG ARTIFACTORY SYSTEM CONFIGURATION FILE +## HOW TO USE: comment-out any field and keep the correct yaml indentation by deleting only the leading '#' character. +configVersion: 1 + +## NOTE: JFROG_HOME is a place holder for the JFrog root directory containing the deployed product, the home directory for all JFrog products. +## Replace JFROG_HOME with the real path! For example, in RPM install, JFROG_HOME=/opt/jfrog + +## NOTE: Sensitive information such as passwords and join key are encrypted on first read. +## NOTE: The provided commented key and value is the default. + +## SHARED CONFIGURATIONS +## A shared section for keys across all services in this config +shared: + ## Base URL of the JFrog Platform Deployment (JPD) + ## This is the URL to the machine where JFrog Artifactory is deployed, or the load balancer pointing to it. It is recommended to use DNS names rather than direct IPs. + ## Examples: "http://jfrog.acme.com" or "http://10.20.30.40:8082" + jfrogUrl: {{ jfrog_url }} + + ## Java options + extraJavaOpts: "{{ extra_java_opts }}" + + ## Node Settings + node: + ## A unique id to identify this node. + ## Default: auto generated at startup. + id: {{ ansible_machine_id }} + + ## Database Configuration + database: + ## One of: mysql, oracle, mssql, postgresql, mariadb + ## Default: Embedded derby + + ## Example for mysql/postgresql + type: "{{ db_type }}" + driver: "{{ db_driver }}" + url: "{{ db_url }}" + username: "{{ db_user }}" + password: "{{ db_password }}" diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/tests/inventory b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/tests/inventory new file mode 100644 index 0000000..878877b --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/tests/inventory @@ -0,0 +1,2 @@ +localhost + diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/tests/test.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/tests/test.yml new file mode 100644 index 0000000..f296da6 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/tests/test.yml @@ -0,0 +1,5 @@ +--- +- hosts: localhost + remote_user: root + roles: + - xray \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/vars/main.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/vars/main.yml new file mode 100644 index 0000000..55363e6 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/roles/xray/vars/main.yml @@ -0,0 +1,2 @@ +--- +# vars file for xray \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/site-artifactory.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/site-artifactory.yml new file mode 100644 index 0000000..f6b92cf --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/site-artifactory.yml @@ -0,0 +1,12 @@ +- hosts: localhost + gather_facts: true + become: true + tasks: + - include_role: + name: artifactory + - include_role: + name: artifactory-nginx + when: "enable_ssl != true" + - include_role: + name: artifactory-nginx-ssl + when: "enable_ssl == true" diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/site-xray.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/site-xray.yml new file mode 100644 index 0000000..fd761b9 --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/site-xray.yml @@ -0,0 +1,5 @@ +- hosts: localhost + gather_facts: true + become: true + roles: + - name: xray diff --git a/Amazon/artifactory7/v7174/cloudInstallerScripts/xray-ami.yml b/Amazon/artifactory7/v7174/cloudInstallerScripts/xray-ami.yml new file mode 100644 index 0000000..2921a0d --- /dev/null +++ b/Amazon/artifactory7/v7174/cloudInstallerScripts/xray-ami.yml @@ -0,0 +1,5 @@ +- hosts: localhost + gather_facts: true + become: true + roles: + - name: xray-ami diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/.github/workflows/master-docs-build.yml b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/.github/workflows/master-docs-build.yml new file mode 100644 index 0000000..72d5634 --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/.github/workflows/master-docs-build.yml @@ -0,0 +1,37 @@ +name: main-documentation + +on: + push: + branches: + - master +jobs: + build-adocs: + runs-on: ubuntu-18.04 + name: asciidoc builder + steps: + - name: Checkout (master) + uses: actions/checkout@v2 + - name: Get new doc updates + run: | + wget https://raw.githubusercontent.com/aws-quickstart/quickstart-documentation-base-common/master/.utils/configure_git_env.sh + chmod +x configure_git_env.sh + ./configure_git_env.sh + - name: Setup python + uses: actions/setup-python@v2 + with: + python-version: 3.x + - name: Generate dynamic content. + run: ./docs/boilerplate/.utils/generate_dynamic_content.sh + - name: Run local actions + id: adoc + uses: ./docs/boilerplate/.actions/asciidoctor-action + with: + program: "./docs/boilerplate/.utils/build_docs.sh" + - name: Stage and Push changes to gh-pages branch. + run: ./docs/boilerplate/.utils/commit_and_push_to_ghpages.sh + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + - name: Configure gh-pages source and trigger build if necessary. + run: ./docs/boilerplate/.utils/config_and_trigger_gh-pages.sh + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/.gitmodules b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/.gitmodules new file mode 100644 index 0000000..0caba64 --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/.gitmodules @@ -0,0 +1,4 @@ +[submodule "docs/boilerplate"] + path = docs/boilerplate + url = https://github.com/aws-quickstart/quickstart-documentation-base-common.git + branch = main diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/.nojekyll b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/.taskcat.yml b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/.taskcat.yml new file mode 100644 index 0000000..2ca640c --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/.taskcat.yml @@ -0,0 +1,354 @@ +project: + name: quickstart-aws-vpc + owner: quickstart@amazon.com + package_lambda: false + regions: + - af-south-1 + - ap-east-1 + - ap-south-1 + - ap-northeast-3 + - ap-northeast-2 + - ap-southeast-1 + - ap-southeast-2 + - ap-northeast-1 + - ca-central-1 + - cn-north-1 + - cn-northwest-1 + - eu-central-1 + - eu-west-1 + - eu-west-2 + - eu-south-1 + - eu-west-3 + - eu-north-1 + - me-south-1 + - sa-east-1 + - us-east-1 + - us-east-2 + - us-west-1 + - us-west-2 + s3_bucket: '' +tests: + vpc-complete-all-possible-regions: + parameters: + AvailabilityZones: $[taskcat_getaz_2] + CreateAdditionalPrivateSubnets: 'true' + CreatePrivateSubnets: 'true' + NumberOfAZs: '2' + PrivateSubnet1ACIDR: 10.0.0.0/19 + PrivateSubnet1BCIDR: 10.0.192.0/21 + PrivateSubnet2ACIDR: 10.0.32.0/19 + PrivateSubnet2BCIDR: 10.0.200.0/21 + PrivateSubnet3ACIDR: 10.0.64.0/19 + PrivateSubnet3BCIDR: 10.0.208.0/21 + PrivateSubnet4ACIDR: 10.0.96.0/19 + PrivateSubnet4BCIDR: 10.0.216.0/21 + PublicSubnet1CIDR: 10.0.128.0/20 + PublicSubnet2CIDR: 10.0.144.0/20 + PublicSubnet3CIDR: 10.0.160.0/20 + PublicSubnet4CIDR: 10.0.176.0/20 + VPCCIDR: 10.0.0.0/16 + VPCTenancy: default + regions: + - af-south-1 + - ap-east-1 + - ap-south-1 + ## - ap-northeast-3 + - ap-northeast-2 + - ap-southeast-1 + - ap-southeast-2 + - ap-northeast-1 + - ca-central-1 + ## - cn-north-1 + ## - cn-northwest-1 + - eu-central-1 + - eu-west-1 + - eu-west-2 + - eu-south-1 + - eu-west-3 + - eu-north-1 + - me-south-1 + - sa-east-1 + - us-east-1 + - us-east-2 + - us-west-1 + - us-west-2 + s3_bucket: '' + template: templates/aws-vpc.template.yaml + vpc-defaults-all-possible-regions: + parameters: + AvailabilityZones: $[taskcat_getaz_2] + CreateAdditionalPrivateSubnets: 'false' + CreatePrivateSubnets: 'true' + NumberOfAZs: '2' + PrivateSubnet1ACIDR: 10.0.0.0/19 + PrivateSubnet1BCIDR: 10.0.192.0/21 + PrivateSubnet2ACIDR: 10.0.32.0/19 + PrivateSubnet2BCIDR: 10.0.200.0/21 + PrivateSubnet3ACIDR: 10.0.64.0/19 + PrivateSubnet3BCIDR: 10.0.208.0/21 + PrivateSubnet4ACIDR: 10.0.96.0/19 + PrivateSubnet4BCIDR: 10.0.216.0/21 + PublicSubnet1CIDR: 10.0.128.0/20 + PublicSubnet2CIDR: 10.0.144.0/20 + PublicSubnet3CIDR: 10.0.160.0/20 + PublicSubnet4CIDR: 10.0.176.0/20 + VPCCIDR: 10.0.0.0/16 + VPCTenancy: default + regions: + - af-south-1 + - ap-east-1 + - ap-south-1 + ## - ap-northeast-3 + - ap-northeast-2 + - ap-southeast-1 + - ap-southeast-2 + - ap-northeast-1 + - ca-central-1 + ## - cn-north-1 + ## - cn-northwest-1 + - eu-central-1 + - eu-west-1 + - eu-west-2 + - eu-south-1 + - eu-west-3 + - eu-north-1 + - me-south-1 + - sa-east-1 + - us-east-1 + - us-east-2 + - us-west-1 + - us-west-2 + s3_bucket: '' + template: templates/aws-vpc.template.yaml + vpc-public-all-possible-regions: + parameters: + AvailabilityZones: $[taskcat_getaz_2] + CreateAdditionalPrivateSubnets: 'false' + CreateNATGateways: 'false' + CreatePrivateSubnets: 'false' + NumberOfAZs: '2' + PrivateSubnet1ACIDR: 10.0.0.0/19 + PrivateSubnet1BCIDR: 10.0.192.0/21 + PrivateSubnet2ACIDR: 10.0.32.0/19 + PrivateSubnet2BCIDR: 10.0.200.0/21 + PrivateSubnet3ACIDR: 10.0.64.0/19 + PrivateSubnet3BCIDR: 10.0.208.0/21 + PrivateSubnet4ACIDR: 10.0.96.0/19 + PrivateSubnet4BCIDR: 10.0.216.0/21 + PublicSubnet1CIDR: 10.0.128.0/20 + PublicSubnet2CIDR: 10.0.144.0/20 + PublicSubnet3CIDR: 10.0.160.0/20 + PublicSubnet4CIDR: 10.0.176.0/20 + VPCCIDR: 10.0.0.0/16 + VPCTenancy: default + regions: + - af-south-1 + - ap-east-1 + - ap-south-1 + ## - ap-northeast-3 + - ap-northeast-2 + - ap-southeast-1 + - ap-southeast-2 + - ap-northeast-1 + - ca-central-1 + ## - cn-north-1 + ## - cn-northwest-1 + - eu-central-1 + - eu-west-1 + - eu-west-2 + - eu-south-1 + - eu-west-3 + - eu-north-1 + - me-south-1 + - sa-east-1 + - us-east-1 + - us-east-2 + - us-west-1 + - us-west-2 + s3_bucket: '' + template: templates/aws-vpc.template.yaml + vpc-private-all-possible-regions: + parameters: + AvailabilityZones: $[taskcat_getaz_2] + CreateAdditionalPrivateSubnets: 'false' + CreatePublicSubnets: 'false' + CreateNATGateways: 'false' + NumberOfAZs: '2' + PrivateSubnet1ACIDR: 10.0.0.0/19 + PrivateSubnet1BCIDR: 10.0.192.0/21 + PrivateSubnet2ACIDR: 10.0.32.0/19 + PrivateSubnet2BCIDR: 10.0.200.0/21 + PrivateSubnet3ACIDR: 10.0.64.0/19 + PrivateSubnet3BCIDR: 10.0.208.0/21 + PrivateSubnet4ACIDR: 10.0.96.0/19 + PrivateSubnet4BCIDR: 10.0.216.0/21 + PublicSubnet1CIDR: 10.0.128.0/20 + PublicSubnet2CIDR: 10.0.144.0/20 + PublicSubnet3CIDR: 10.0.160.0/20 + PublicSubnet4CIDR: 10.0.176.0/20 + VPCCIDR: 10.0.0.0/16 + VPCTenancy: default + regions: + - af-south-1 + - ap-east-1 + - ap-south-1 + ## - ap-northeast-3 + - ap-northeast-2 + - ap-southeast-1 + - ap-southeast-2 + - ap-northeast-1 + - ca-central-1 + ## - cn-north-1 + ## - cn-northwest-1 + - eu-central-1 + - eu-west-1 + - eu-west-2 + - eu-south-1 + - eu-west-3 + - eu-north-1 + - me-south-1 + - sa-east-1 + - us-east-1 + - us-east-2 + - us-west-1 + - us-west-2 + s3_bucket: '' + template: templates/aws-vpc.template.yaml + 3az-complete-all-possible-regions: + parameters: + AvailabilityZones: $[taskcat_getaz_3] + CreateAdditionalPrivateSubnets: 'true' + CreatePrivateSubnets: 'true' + NumberOfAZs: '3' + PrivateSubnet1ACIDR: 10.0.0.0/19 + PrivateSubnet1BCIDR: 10.0.192.0/21 + PrivateSubnet2ACIDR: 10.0.32.0/19 + PrivateSubnet2BCIDR: 10.0.200.0/21 + PrivateSubnet3ACIDR: 10.0.64.0/19 + PrivateSubnet3BCIDR: 10.0.208.0/21 + PrivateSubnet4ACIDR: 10.0.96.0/19 + PrivateSubnet4BCIDR: 10.0.216.0/21 + PublicSubnet1CIDR: 10.0.128.0/20 + PublicSubnet2CIDR: 10.0.144.0/20 + PublicSubnet3CIDR: 10.0.160.0/20 + PublicSubnet4CIDR: 10.0.176.0/20 + VPCCIDR: 10.0.0.0/16 + VPCTenancy: default + regions: + - af-south-1 + - ap-east-1 + - ap-south-1 + ## - ap-northeast-3 + - ap-northeast-2 + - ap-southeast-1 + - ap-southeast-2 + - ap-northeast-1 + ## - ca-central-1 + ## - cn-north-1 + ## - cn-northwest-1 + - eu-central-1 + - eu-west-1 + - eu-west-2 + - eu-south-1 + - eu-west-3 + - eu-north-1 + - me-south-1 + - sa-east-1 + - us-east-1 + - us-east-2 + ## - us-west-1 + - us-west-2 + s3_bucket: '' + template: templates/aws-vpc.template + 4az-complete-all-possible-regions: + parameters: + AvailabilityZones: $[taskcat_getaz_4] + CreateAdditionalPrivateSubnets: 'true' + CreatePrivateSubnets: 'true' + NumberOfAZs: '4' + PrivateSubnet1ACIDR: 10.0.0.0/19 + PrivateSubnet1BCIDR: 10.0.192.0/21 + PrivateSubnet2ACIDR: 10.0.32.0/19 + PrivateSubnet2BCIDR: 10.0.200.0/21 + PrivateSubnet3ACIDR: 10.0.64.0/19 + PrivateSubnet3BCIDR: 10.0.208.0/21 + PrivateSubnet4ACIDR: 10.0.96.0/19 + PrivateSubnet4BCIDR: 10.0.216.0/21 + PublicSubnet1CIDR: 10.0.128.0/20 + PublicSubnet2CIDR: 10.0.144.0/20 + PublicSubnet3CIDR: 10.0.160.0/20 + PublicSubnet4CIDR: 10.0.176.0/20 + VPCCIDR: 10.0.0.0/16 + VPCTenancy: default + regions: + ## - af-south-1 + ## - ap-east-1 + ## - ap-south-1 + ## - ap-northeast-3 + ## - ap-northeast-2 + ## - ap-southeast-1 + ## - ap-southeast-2 + ## - ap-northeast-1 + ## - ca-central-1 + ## - cn-north-1 + ## - cn-northwest-1 + ## - eu-central-1 + ## - eu-west-1 + ## - eu-west-2 + ## - eu-south-1 + ## - eu-west-3 + ## - eu-north-1 + ## - me-south-1 + ## - sa-east-1 + - us-east-1 + ## - us-east-2 + ## - us-west-1 + - us-west-2 + s3_bucket: '' + template: templates/aws-vpc.template + 4az-public-all-possible-regions: + parameters: + AvailabilityZones: $[taskcat_getaz_4] + CreateAdditionalPrivateSubnets: 'false' + CreatePrivateSubnets: 'false' + NumberOfAZs: '4' + PrivateSubnet1ACIDR: 10.0.0.0/19 + PrivateSubnet1BCIDR: 10.0.192.0/21 + PrivateSubnet2ACIDR: 10.0.32.0/19 + PrivateSubnet2BCIDR: 10.0.200.0/21 + PrivateSubnet3ACIDR: 10.0.64.0/19 + PrivateSubnet3BCIDR: 10.0.208.0/21 + PrivateSubnet4ACIDR: 10.0.96.0/19 + PrivateSubnet4BCIDR: 10.0.216.0/21 + PublicSubnet1CIDR: 10.0.128.0/20 + PublicSubnet2CIDR: 10.0.144.0/20 + PublicSubnet3CIDR: 10.0.160.0/20 + PublicSubnet4CIDR: 10.0.176.0/20 + VPCCIDR: 10.0.0.0/16 + VPCTenancy: default + regions: + ## - af-south-1 + ## - ap-east-1 + ## - ap-south-1 + ## - ap-northeast-3 + ## - ap-northeast-2 + ## - ap-southeast-1 + ## - ap-southeast-2 + ## - ap-northeast-1 + ## - ca-central-1 + ## - cn-north-1 + ## - cn-northwest-1 + ## - eu-central-1 + ## - eu-west-1 + ## - eu-west-2 + ## - eu-south-1 + ## - eu-west-3 + ## - eu-north-1 + ## - me-south-1 + ## - sa-east-1 + - us-east-1 + ## - us-east-2 + ## - us-west-1 + - us-west-2 + s3_bucket: '' + template: templates/aws-vpc.template \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/LICENSE.txt b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/LICENSE.txt new file mode 100644 index 0000000..8dada3e --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/LICENSE.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/NOTICE.txt b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/NOTICE.txt new file mode 100644 index 0000000..c7169b4 --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/NOTICE.txt @@ -0,0 +1,7 @@ +Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with the License. A copy of the License is located at + + http://aws.amazon.com/apache2.0/ + +or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/README.md b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/README.md new file mode 100644 index 0000000..449de22 --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/README.md @@ -0,0 +1,9 @@ +# quickstart-aws-vpc + +This Quick Start provides a networking foundation for AWS Cloud infrastructures. It deploys an Amazon Virtual Private Cloud (Amazon VPC) according to AWS best practices and guidelines. + +The Amazon VPC architecture includes public and private subnets. The first set of private subnets share the default network access control list (ACL) from the Amazon VPC, and a second, optional set of private subnets include dedicated custom network ACLs per subnet. The Quick Start divides the Amazon VPC address space in a predictable manner across multiple Availability Zones, and deploys NAT gateways in each Availability Zone, which provide highly available outbound internet access for the private subnets. + +For architectural details, best practices, step-by-step instructions, and customization options, see the [deployment guide](https://fwd.aws/9VdxN). + +![Quick Start VPC Design Architecture](https://docs.aws.amazon.com/quickstart/latest/vpc/images/quickstart-vpc-design-fullscreen.png) diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-3az-complete.json b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-3az-complete.json new file mode 100644 index 0000000..58e2891 --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-3az-complete.json @@ -0,0 +1,74 @@ +[ + { + "ParameterKey": "AvailabilityZones", + "ParameterValue": "$[taskcat_getaz_3]" + }, + { + "ParameterKey": "CreateAdditionalPrivateSubnets", + "ParameterValue": "true" + }, + { + "ParameterKey": "CreatePrivateSubnets", + "ParameterValue": "true" + }, + { + "ParameterKey": "NumberOfAZs", + "ParameterValue": "3" + }, + { + "ParameterKey": "PrivateSubnet1ACIDR", + "ParameterValue": "10.0.0.0/19" + }, + { + "ParameterKey": "PrivateSubnet1BCIDR", + "ParameterValue": "10.0.192.0/21" + }, + { + "ParameterKey": "PrivateSubnet2ACIDR", + "ParameterValue": "10.0.32.0/19" + }, + { + "ParameterKey": "PrivateSubnet2BCIDR", + "ParameterValue": "10.0.200.0/21" + }, + { + "ParameterKey": "PrivateSubnet3ACIDR", + "ParameterValue": "10.0.64.0/19" + }, + { + "ParameterKey": "PrivateSubnet3BCIDR", + "ParameterValue": "10.0.208.0/21" + }, + { + "ParameterKey": "PrivateSubnet4ACIDR", + "ParameterValue": "10.0.96.0/19" + }, + { + "ParameterKey": "PrivateSubnet4BCIDR", + "ParameterValue": "10.0.216.0/21" + }, + { + "ParameterKey": "PublicSubnet1CIDR", + "ParameterValue": "10.0.128.0/20" + }, + { + "ParameterKey": "PublicSubnet2CIDR", + "ParameterValue": "10.0.144.0/20" + }, + { + "ParameterKey": "PublicSubnet3CIDR", + "ParameterValue": "10.0.160.0/20" + }, + { + "ParameterKey": "PublicSubnet4CIDR", + "ParameterValue": "10.0.176.0/20" + }, + { + "ParameterKey": "VPCCIDR", + "ParameterValue": "10.0.0.0/16" + }, + { + "ParameterKey": "VPCTenancy", + "ParameterValue": "default" + } +] diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-3az-public.json b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-3az-public.json new file mode 100644 index 0000000..bc07459 --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-3az-public.json @@ -0,0 +1,74 @@ +[ + { + "ParameterKey": "AvailabilityZones", + "ParameterValue": "$[taskcat_getaz_3]" + }, + { + "ParameterKey": "CreateAdditionalPrivateSubnets", + "ParameterValue": "false" + }, + { + "ParameterKey": "CreatePrivateSubnets", + "ParameterValue": "false" + }, + { + "ParameterKey": "NumberOfAZs", + "ParameterValue": "3" + }, + { + "ParameterKey": "PrivateSubnet1ACIDR", + "ParameterValue": "10.0.0.0/19" + }, + { + "ParameterKey": "PrivateSubnet1BCIDR", + "ParameterValue": "10.0.192.0/21" + }, + { + "ParameterKey": "PrivateSubnet2ACIDR", + "ParameterValue": "10.0.32.0/19" + }, + { + "ParameterKey": "PrivateSubnet2BCIDR", + "ParameterValue": "10.0.200.0/21" + }, + { + "ParameterKey": "PrivateSubnet3ACIDR", + "ParameterValue": "10.0.64.0/19" + }, + { + "ParameterKey": "PrivateSubnet3BCIDR", + "ParameterValue": "10.0.208.0/21" + }, + { + "ParameterKey": "PrivateSubnet4ACIDR", + "ParameterValue": "10.0.96.0/19" + }, + { + "ParameterKey": "PrivateSubnet4BCIDR", + "ParameterValue": "10.0.216.0/21" + }, + { + "ParameterKey": "PublicSubnet1CIDR", + "ParameterValue": "10.0.128.0/20" + }, + { + "ParameterKey": "PublicSubnet2CIDR", + "ParameterValue": "10.0.144.0/20" + }, + { + "ParameterKey": "PublicSubnet3CIDR", + "ParameterValue": "10.0.160.0/20" + }, + { + "ParameterKey": "PublicSubnet4CIDR", + "ParameterValue": "10.0.176.0/20" + }, + { + "ParameterKey": "VPCCIDR", + "ParameterValue": "10.0.0.0/16" + }, + { + "ParameterKey": "VPCTenancy", + "ParameterValue": "default" + } +] diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-3az.json b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-3az.json new file mode 100644 index 0000000..ee5548a --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-3az.json @@ -0,0 +1,74 @@ +[ + { + "ParameterKey": "AvailabilityZones", + "ParameterValue": "$[taskcat_getaz_3]" + }, + { + "ParameterKey": "CreateAdditionalPrivateSubnets", + "ParameterValue": "false" + }, + { + "ParameterKey": "CreatePrivateSubnets", + "ParameterValue": "true" + }, + { + "ParameterKey": "NumberOfAZs", + "ParameterValue": "3" + }, + { + "ParameterKey": "PrivateSubnet1ACIDR", + "ParameterValue": "10.0.0.0/19" + }, + { + "ParameterKey": "PrivateSubnet1BCIDR", + "ParameterValue": "10.0.192.0/21" + }, + { + "ParameterKey": "PrivateSubnet2ACIDR", + "ParameterValue": "10.0.32.0/19" + }, + { + "ParameterKey": "PrivateSubnet2BCIDR", + "ParameterValue": "10.0.200.0/21" + }, + { + "ParameterKey": "PrivateSubnet3ACIDR", + "ParameterValue": "10.0.64.0/19" + }, + { + "ParameterKey": "PrivateSubnet3BCIDR", + "ParameterValue": "10.0.208.0/21" + }, + { + "ParameterKey": "PrivateSubnet4ACIDR", + "ParameterValue": "10.0.96.0/19" + }, + { + "ParameterKey": "PrivateSubnet4BCIDR", + "ParameterValue": "10.0.216.0/21" + }, + { + "ParameterKey": "PublicSubnet1CIDR", + "ParameterValue": "10.0.128.0/20" + }, + { + "ParameterKey": "PublicSubnet2CIDR", + "ParameterValue": "10.0.144.0/20" + }, + { + "ParameterKey": "PublicSubnet3CIDR", + "ParameterValue": "10.0.160.0/20" + }, + { + "ParameterKey": "PublicSubnet4CIDR", + "ParameterValue": "10.0.176.0/20" + }, + { + "ParameterKey": "VPCCIDR", + "ParameterValue": "10.0.0.0/16" + }, + { + "ParameterKey": "VPCTenancy", + "ParameterValue": "default" + } +] diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-4az-complete.json b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-4az-complete.json new file mode 100644 index 0000000..b9929b4 --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-4az-complete.json @@ -0,0 +1,74 @@ +[ + { + "ParameterKey": "AvailabilityZones", + "ParameterValue": "$[taskcat_getaz_4]" + }, + { + "ParameterKey": "CreateAdditionalPrivateSubnets", + "ParameterValue": "true" + }, + { + "ParameterKey": "CreatePrivateSubnets", + "ParameterValue": "true" + }, + { + "ParameterKey": "NumberOfAZs", + "ParameterValue": "4" + }, + { + "ParameterKey": "PrivateSubnet1ACIDR", + "ParameterValue": "10.0.0.0/19" + }, + { + "ParameterKey": "PrivateSubnet1BCIDR", + "ParameterValue": "10.0.192.0/21" + }, + { + "ParameterKey": "PrivateSubnet2ACIDR", + "ParameterValue": "10.0.32.0/19" + }, + { + "ParameterKey": "PrivateSubnet2BCIDR", + "ParameterValue": "10.0.200.0/21" + }, + { + "ParameterKey": "PrivateSubnet3ACIDR", + "ParameterValue": "10.0.64.0/19" + }, + { + "ParameterKey": "PrivateSubnet3BCIDR", + "ParameterValue": "10.0.208.0/21" + }, + { + "ParameterKey": "PrivateSubnet4ACIDR", + "ParameterValue": "10.0.96.0/19" + }, + { + "ParameterKey": "PrivateSubnet4BCIDR", + "ParameterValue": "10.0.216.0/21" + }, + { + "ParameterKey": "PublicSubnet1CIDR", + "ParameterValue": "10.0.128.0/20" + }, + { + "ParameterKey": "PublicSubnet2CIDR", + "ParameterValue": "10.0.144.0/20" + }, + { + "ParameterKey": "PublicSubnet3CIDR", + "ParameterValue": "10.0.160.0/20" + }, + { + "ParameterKey": "PublicSubnet4CIDR", + "ParameterValue": "10.0.176.0/20" + }, + { + "ParameterKey": "VPCCIDR", + "ParameterValue": "10.0.0.0/16" + }, + { + "ParameterKey": "VPCTenancy", + "ParameterValue": "default" + } +] diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-4az-public.json b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-4az-public.json new file mode 100644 index 0000000..a34e72d --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-4az-public.json @@ -0,0 +1,74 @@ +[ + { + "ParameterKey": "AvailabilityZones", + "ParameterValue": "$[taskcat_getaz_4]" + }, + { + "ParameterKey": "CreateAdditionalPrivateSubnets", + "ParameterValue": "false" + }, + { + "ParameterKey": "CreatePrivateSubnets", + "ParameterValue": "false" + }, + { + "ParameterKey": "NumberOfAZs", + "ParameterValue": "4" + }, + { + "ParameterKey": "PrivateSubnet1ACIDR", + "ParameterValue": "10.0.0.0/19" + }, + { + "ParameterKey": "PrivateSubnet1BCIDR", + "ParameterValue": "10.0.192.0/21" + }, + { + "ParameterKey": "PrivateSubnet2ACIDR", + "ParameterValue": "10.0.32.0/19" + }, + { + "ParameterKey": "PrivateSubnet2BCIDR", + "ParameterValue": "10.0.200.0/21" + }, + { + "ParameterKey": "PrivateSubnet3ACIDR", + "ParameterValue": "10.0.64.0/19" + }, + { + "ParameterKey": "PrivateSubnet3BCIDR", + "ParameterValue": "10.0.208.0/21" + }, + { + "ParameterKey": "PrivateSubnet4ACIDR", + "ParameterValue": "10.0.96.0/19" + }, + { + "ParameterKey": "PrivateSubnet4BCIDR", + "ParameterValue": "10.0.216.0/21" + }, + { + "ParameterKey": "PublicSubnet1CIDR", + "ParameterValue": "10.0.128.0/20" + }, + { + "ParameterKey": "PublicSubnet2CIDR", + "ParameterValue": "10.0.144.0/20" + }, + { + "ParameterKey": "PublicSubnet3CIDR", + "ParameterValue": "10.0.160.0/20" + }, + { + "ParameterKey": "PublicSubnet4CIDR", + "ParameterValue": "10.0.176.0/20" + }, + { + "ParameterKey": "VPCCIDR", + "ParameterValue": "10.0.0.0/16" + }, + { + "ParameterKey": "VPCTenancy", + "ParameterValue": "default" + } +] diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-4az.json b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-4az.json new file mode 100644 index 0000000..a543251 --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-4az.json @@ -0,0 +1,74 @@ +[ + { + "ParameterKey": "AvailabilityZones", + "ParameterValue": "$[taskcat_getaz_4]" + }, + { + "ParameterKey": "CreateAdditionalPrivateSubnets", + "ParameterValue": "false" + }, + { + "ParameterKey": "CreatePrivateSubnets", + "ParameterValue": "true" + }, + { + "ParameterKey": "NumberOfAZs", + "ParameterValue": "4" + }, + { + "ParameterKey": "PrivateSubnet1ACIDR", + "ParameterValue": "10.0.0.0/19" + }, + { + "ParameterKey": "PrivateSubnet1BCIDR", + "ParameterValue": "10.0.192.0/21" + }, + { + "ParameterKey": "PrivateSubnet2ACIDR", + "ParameterValue": "10.0.32.0/19" + }, + { + "ParameterKey": "PrivateSubnet2BCIDR", + "ParameterValue": "10.0.200.0/21" + }, + { + "ParameterKey": "PrivateSubnet3ACIDR", + "ParameterValue": "10.0.64.0/19" + }, + { + "ParameterKey": "PrivateSubnet3BCIDR", + "ParameterValue": "10.0.208.0/21" + }, + { + "ParameterKey": "PrivateSubnet4ACIDR", + "ParameterValue": "10.0.96.0/19" + }, + { + "ParameterKey": "PrivateSubnet4BCIDR", + "ParameterValue": "10.0.216.0/21" + }, + { + "ParameterKey": "PublicSubnet1CIDR", + "ParameterValue": "10.0.128.0/20" + }, + { + "ParameterKey": "PublicSubnet2CIDR", + "ParameterValue": "10.0.144.0/20" + }, + { + "ParameterKey": "PublicSubnet3CIDR", + "ParameterValue": "10.0.160.0/20" + }, + { + "ParameterKey": "PublicSubnet4CIDR", + "ParameterValue": "10.0.176.0/20" + }, + { + "ParameterKey": "VPCCIDR", + "ParameterValue": "10.0.0.0/16" + }, + { + "ParameterKey": "VPCTenancy", + "ParameterValue": "default" + } +] diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-complete.json b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-complete.json new file mode 100644 index 0000000..d180084 --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-complete.json @@ -0,0 +1,74 @@ +[ + { + "ParameterKey": "AvailabilityZones", + "ParameterValue": "$[taskcat_getaz_2]" + }, + { + "ParameterKey": "CreateAdditionalPrivateSubnets", + "ParameterValue": "true" + }, + { + "ParameterKey": "CreatePrivateSubnets", + "ParameterValue": "true" + }, + { + "ParameterKey": "NumberOfAZs", + "ParameterValue": "2" + }, + { + "ParameterKey": "PrivateSubnet1ACIDR", + "ParameterValue": "10.0.0.0/19" + }, + { + "ParameterKey": "PrivateSubnet1BCIDR", + "ParameterValue": "10.0.192.0/21" + }, + { + "ParameterKey": "PrivateSubnet2ACIDR", + "ParameterValue": "10.0.32.0/19" + }, + { + "ParameterKey": "PrivateSubnet2BCIDR", + "ParameterValue": "10.0.200.0/21" + }, + { + "ParameterKey": "PrivateSubnet3ACIDR", + "ParameterValue": "10.0.64.0/19" + }, + { + "ParameterKey": "PrivateSubnet3BCIDR", + "ParameterValue": "10.0.208.0/21" + }, + { + "ParameterKey": "PrivateSubnet4ACIDR", + "ParameterValue": "10.0.96.0/19" + }, + { + "ParameterKey": "PrivateSubnet4BCIDR", + "ParameterValue": "10.0.216.0/21" + }, + { + "ParameterKey": "PublicSubnet1CIDR", + "ParameterValue": "10.0.128.0/20" + }, + { + "ParameterKey": "PublicSubnet2CIDR", + "ParameterValue": "10.0.144.0/20" + }, + { + "ParameterKey": "PublicSubnet3CIDR", + "ParameterValue": "10.0.160.0/20" + }, + { + "ParameterKey": "PublicSubnet4CIDR", + "ParameterValue": "10.0.176.0/20" + }, + { + "ParameterKey": "VPCCIDR", + "ParameterValue": "10.0.0.0/16" + }, + { + "ParameterKey": "VPCTenancy", + "ParameterValue": "default" + } +] diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-dedicated.json b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-dedicated.json new file mode 100644 index 0000000..14186af --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-dedicated.json @@ -0,0 +1,74 @@ +[ + { + "ParameterKey": "AvailabilityZones", + "ParameterValue": "$[taskcat_getaz_2]" + }, + { + "ParameterKey": "CreateAdditionalPrivateSubnets", + "ParameterValue": "false" + }, + { + "ParameterKey": "CreatePrivateSubnets", + "ParameterValue": "false" + }, + { + "ParameterKey": "NumberOfAZs", + "ParameterValue": "2" + }, + { + "ParameterKey": "PrivateSubnet1ACIDR", + "ParameterValue": "10.0.0.0/19" + }, + { + "ParameterKey": "PrivateSubnet1BCIDR", + "ParameterValue": "10.0.192.0/21" + }, + { + "ParameterKey": "PrivateSubnet2ACIDR", + "ParameterValue": "10.0.32.0/19" + }, + { + "ParameterKey": "PrivateSubnet2BCIDR", + "ParameterValue": "10.0.200.0/21" + }, + { + "ParameterKey": "PrivateSubnet3ACIDR", + "ParameterValue": "10.0.64.0/19" + }, + { + "ParameterKey": "PrivateSubnet3BCIDR", + "ParameterValue": "10.0.208.0/21" + }, + { + "ParameterKey": "PrivateSubnet4ACIDR", + "ParameterValue": "10.0.96.0/19" + }, + { + "ParameterKey": "PrivateSubnet4BCIDR", + "ParameterValue": "10.0.216.0/21" + }, + { + "ParameterKey": "PublicSubnet1CIDR", + "ParameterValue": "10.0.128.0/20" + }, + { + "ParameterKey": "PublicSubnet2CIDR", + "ParameterValue": "10.0.144.0/20" + }, + { + "ParameterKey": "PublicSubnet3CIDR", + "ParameterValue": "10.0.160.0/20" + }, + { + "ParameterKey": "PublicSubnet4CIDR", + "ParameterValue": "10.0.176.0/20" + }, + { + "ParameterKey": "VPCCIDR", + "ParameterValue": "10.0.0.0/16" + }, + { + "ParameterKey": "VPCTenancy", + "ParameterValue": "dedicated" + } +] diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-defaults.json b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-defaults.json new file mode 100644 index 0000000..aaca90c --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-defaults.json @@ -0,0 +1,74 @@ +[ + { + "ParameterKey": "AvailabilityZones", + "ParameterValue": "$[taskcat_getaz_2]" + }, + { + "ParameterKey": "CreateAdditionalPrivateSubnets", + "ParameterValue": "false" + }, + { + "ParameterKey": "CreatePrivateSubnets", + "ParameterValue": "true" + }, + { + "ParameterKey": "NumberOfAZs", + "ParameterValue": "2" + }, + { + "ParameterKey": "PrivateSubnet1ACIDR", + "ParameterValue": "10.0.0.0/19" + }, + { + "ParameterKey": "PrivateSubnet1BCIDR", + "ParameterValue": "10.0.192.0/21" + }, + { + "ParameterKey": "PrivateSubnet2ACIDR", + "ParameterValue": "10.0.32.0/19" + }, + { + "ParameterKey": "PrivateSubnet2BCIDR", + "ParameterValue": "10.0.200.0/21" + }, + { + "ParameterKey": "PrivateSubnet3ACIDR", + "ParameterValue": "10.0.64.0/19" + }, + { + "ParameterKey": "PrivateSubnet3BCIDR", + "ParameterValue": "10.0.208.0/21" + }, + { + "ParameterKey": "PrivateSubnet4ACIDR", + "ParameterValue": "10.0.96.0/19" + }, + { + "ParameterKey": "PrivateSubnet4BCIDR", + "ParameterValue": "10.0.216.0/21" + }, + { + "ParameterKey": "PublicSubnet1CIDR", + "ParameterValue": "10.0.128.0/20" + }, + { + "ParameterKey": "PublicSubnet2CIDR", + "ParameterValue": "10.0.144.0/20" + }, + { + "ParameterKey": "PublicSubnet3CIDR", + "ParameterValue": "10.0.160.0/20" + }, + { + "ParameterKey": "PublicSubnet4CIDR", + "ParameterValue": "10.0.176.0/20" + }, + { + "ParameterKey": "VPCCIDR", + "ParameterValue": "10.0.0.0/16" + }, + { + "ParameterKey": "VPCTenancy", + "ParameterValue": "default" + } +] diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-public.json b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-public.json new file mode 100644 index 0000000..86e37a2 --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-public.json @@ -0,0 +1,74 @@ +[ + { + "ParameterKey": "AvailabilityZones", + "ParameterValue": "$[taskcat_getaz_2]" + }, + { + "ParameterKey": "CreateAdditionalPrivateSubnets", + "ParameterValue": "false" + }, + { + "ParameterKey": "CreatePrivateSubnets", + "ParameterValue": "false" + }, + { + "ParameterKey": "NumberOfAZs", + "ParameterValue": "2" + }, + { + "ParameterKey": "PrivateSubnet1ACIDR", + "ParameterValue": "10.0.0.0/19" + }, + { + "ParameterKey": "PrivateSubnet1BCIDR", + "ParameterValue": "10.0.192.0/21" + }, + { + "ParameterKey": "PrivateSubnet2ACIDR", + "ParameterValue": "10.0.32.0/19" + }, + { + "ParameterKey": "PrivateSubnet2BCIDR", + "ParameterValue": "10.0.200.0/21" + }, + { + "ParameterKey": "PrivateSubnet3ACIDR", + "ParameterValue": "10.0.64.0/19" + }, + { + "ParameterKey": "PrivateSubnet3BCIDR", + "ParameterValue": "10.0.208.0/21" + }, + { + "ParameterKey": "PrivateSubnet4ACIDR", + "ParameterValue": "10.0.96.0/19" + }, + { + "ParameterKey": "PrivateSubnet4BCIDR", + "ParameterValue": "10.0.216.0/21" + }, + { + "ParameterKey": "PublicSubnet1CIDR", + "ParameterValue": "10.0.128.0/20" + }, + { + "ParameterKey": "PublicSubnet2CIDR", + "ParameterValue": "10.0.144.0/20" + }, + { + "ParameterKey": "PublicSubnet3CIDR", + "ParameterValue": "10.0.160.0/20" + }, + { + "ParameterKey": "PublicSubnet4CIDR", + "ParameterValue": "10.0.176.0/20" + }, + { + "ParameterKey": "VPCCIDR", + "ParameterValue": "10.0.0.0/16" + }, + { + "ParameterKey": "VPCTenancy", + "ParameterValue": "default" + } +] diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-sa-east-1.json b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-sa-east-1.json new file mode 100644 index 0000000..e8ee3b0 --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/aws-vpc-sa-east-1.json @@ -0,0 +1,74 @@ +[ + { + "ParameterKey": "AvailabilityZones", + "ParameterValue": "sa-east-1b,sa-east-1c" + }, + { + "ParameterKey": "CreateAdditionalPrivateSubnets", + "ParameterValue": "false" + }, + { + "ParameterKey": "CreatePrivateSubnets", + "ParameterValue": "true" + }, + { + "ParameterKey": "NumberOfAZs", + "ParameterValue": "2" + }, + { + "ParameterKey": "PrivateSubnet1ACIDR", + "ParameterValue": "10.0.0.0/19" + }, + { + "ParameterKey": "PrivateSubnet1BCIDR", + "ParameterValue": "10.0.192.0/21" + }, + { + "ParameterKey": "PrivateSubnet2ACIDR", + "ParameterValue": "10.0.32.0/19" + }, + { + "ParameterKey": "PrivateSubnet2BCIDR", + "ParameterValue": "10.0.200.0/21" + }, + { + "ParameterKey": "PrivateSubnet3ACIDR", + "ParameterValue": "10.0.64.0/19" + }, + { + "ParameterKey": "PrivateSubnet3BCIDR", + "ParameterValue": "10.0.208.0/21" + }, + { + "ParameterKey": "PrivateSubnet4ACIDR", + "ParameterValue": "10.0.96.0/19" + }, + { + "ParameterKey": "PrivateSubnet4BCIDR", + "ParameterValue": "10.0.216.0/21" + }, + { + "ParameterKey": "PublicSubnet1CIDR", + "ParameterValue": "10.0.128.0/20" + }, + { + "ParameterKey": "PublicSubnet2CIDR", + "ParameterValue": "10.0.144.0/20" + }, + { + "ParameterKey": "PublicSubnet3CIDR", + "ParameterValue": "10.0.160.0/20" + }, + { + "ParameterKey": "PublicSubnet4CIDR", + "ParameterValue": "10.0.176.0/20" + }, + { + "ParameterKey": "VPCCIDR", + "ParameterValue": "10.0.0.0/16" + }, + { + "ParameterKey": "VPCTenancy", + "ParameterValue": "default" + } +] diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/taskcat.yml b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/taskcat.yml new file mode 100644 index 0000000..57676dc --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/ci/taskcat.yml @@ -0,0 +1,70 @@ +global: + govcloud: true + marketplace-ami: false + owner: quickstart@amazon.com + qsname: quickstart-aws-vpc + regions: + - ap-northeast-1 + - ap-northeast-2 + - ap-south-1 + - ap-southeast-1 + - ap-southeast-2 + - ca-central-1 + - eu-central-1 + - eu-west-1 + - eu-west-2 + - us-east-1 + - us-east-2 + - us-west-1 + - us-west-2 + reporting: true +tests: + vpc-defaults: + parameter_input: aws-vpc-defaults.json + template_file: aws-vpc.template + vpc-complete: + parameter_input: aws-vpc-complete.json + template_file: aws-vpc.template + vpc-defaults-sa-east-1: + parameter_input: aws-vpc-sa-east-1.json + template_file: aws-vpc.template + regions: + - sa-east-1 + vpc-public: + parameter_input: aws-vpc-public.json + template_file: aws-vpc.template + 3az-eu-west-1: + parameter_input: aws-vpc-3az.json + regions: + - eu-west-1 + template_file: aws-vpc.template + 3az-complete-us-east-2: + parameter_input: aws-vpc-3az-complete.json + regions: + - us-east-2 + template_file: aws-vpc.template + 3az-public-us-west-2: + parameter_input: aws-vpc-3az-public.json + regions: + - us-west-2 + template_file: aws-vpc.template + 4az-us-east-1: + parameter_input: aws-vpc-4az.json + regions: + - us-east-1 + template_file: aws-vpc.template + 4az-complete-us-east-1: + parameter_input: aws-vpc-4az-complete.json + regions: + - us-east-1 + template_file: aws-vpc.template + 4az-public-us-east-1: + parameter_input: aws-vpc-4az-public.json + regions: + - us-east-1 + template_file: aws-vpc.template + dedicated-us-west-1: + parameter_input: aws-vpc-dedicated.json + regions: + - us-west-1 + template_file: aws-vpc.template diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/generated/parameters/index.adoc b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/generated/parameters/index.adoc new file mode 100644 index 0000000..ff7bd09 --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/generated/parameters/index.adoc @@ -0,0 +1 @@ +// placeholder diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/generated/regions/index.adoc b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/generated/regions/index.adoc new file mode 100644 index 0000000..ff7bd09 --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/generated/regions/index.adoc @@ -0,0 +1 @@ +// placeholder diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/generated/services/index.adoc b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/generated/services/index.adoc new file mode 100644 index 0000000..ff7bd09 --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/generated/services/index.adoc @@ -0,0 +1 @@ +// placeholder diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/generated/services/metadata.adoc b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/generated/services/metadata.adoc new file mode 100644 index 0000000..ff7bd09 --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/generated/services/metadata.adoc @@ -0,0 +1 @@ +// placeholder diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/images/architecture_diagram.png b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/images/architecture_diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..44926ab045ae41953d9550a1cbe4a16fb623b5f0 GIT binary patch literal 90606 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 literal 0 HcmV?d00001 diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/images/aws-quickstart-graphic.png b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/images/aws-quickstart-graphic.png new file mode 100644 index 0000000000000000000000000000000000000000..8efde67901a751e3324f90ec5eeb40463b11e5ed GIT binary patch literal 26468 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 M^0P$Qr>}nh2kB$5C;$Ke literal 0 HcmV?d00001 diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/images/cfn_outputs.png b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/images/cfn_outputs.png new file mode 100644 index 0000000000000000000000000000000000000000..15ac1591d582e0397d137df72285a17fb6734081 GIT binary patch literal 201384 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

*%k)*$8XKb(0$N4uIbE zRnusiERJvXML;?|j#;;Jk1g>F?|s z`1))jZV~QH64#^@GR#$7s0`fvS#ODlIySls>hI6M#97;(l=pB5o5lie+&i0%QTI6t z>9>3MO_Ve}Pp?i}QTtXNd81bW*W2B%mulRCJu4cRl{BsXO=&try`p7*~js3|!p&q;yYoesXqo$q;2#SA@-I(+a zOYVF#@!B572~iFMs5YNH8uF^H}B+uu8$dugNenWNGB{@Z0CE@v?t6io~h&Wx~q|}@AdZB7H z;>#ZM$0f5N`Ev%;!n^^w*?#QuTHzC@D5timaNpM}+>R8BF6&B*D$RUuvv)7jtQ3=( zx3GldFNQO$36DL&ywUI;Ej~qR?>FCzjT5F5Jw0?@_^{yUln$8lKc;%WLv?%0D{izC1xkb+I<(j}lINvjce90KV=6&3}Lr?el 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

`bW=<=<7KJxtYfhdkSOIs16jB65bR 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 uM +// Identify your target audience and explain how/why they would use this Quick Start. +//Avoid borrowing text from third-party websites (copying text from AWS service documentation is fine). Also, avoid marketing-speak, focusing instead on the technical aspect. + +This Quick Start provides a networking foundation for AWS Cloud infrastructures. It +deploys an Amazon Virtual Private Cloud (Amazon VPC) according to AWS best practices +and guidelines. Amazon VPC is the networking layer for Amazon Elastic Compute Cloud +(Amazon EC2) and provides a private, isolated section of the AWS Cloud where you can +launch AWS services and other resources in a virtual network. For a discussion of best +design practices for Amazon VPC environments, see the documentation and articles listed +in the link:#_other_useful_information[Other useful information] section. \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/partner_editable/pre-reqs.adoc b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/partner_editable/pre-reqs.adoc new file mode 100644 index 0000000..8376035 --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/partner_editable/pre-reqs.adoc @@ -0,0 +1 @@ +// If no preperation is required, remove all content from here \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/partner_editable/product_description.adoc b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/partner_editable/product_description.adoc new file mode 100644 index 0000000..9213cfa --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/partner_editable/product_description.adoc @@ -0,0 +1,18 @@ +// Replace the content in <> +// Briefly describe the software. Use consistent and clear branding. +// Include the benefits of using the software on AWS, and provide details on usage scenarios. + +The Amazon VPC architecture includes public and private subnets. The first set of private +subnets share the default network access control list (ACL) from the Amazon VPC, and a +second, optional set of private subnets includes dedicated custom network ACLs per subnet. + +Optionally you may choose to deploy a completely public VPC (no private subnets), or a completely private VPC (no public subnets). + +The Quick Start divides the Amazon VPC address space in a predictable manner across +multiple Availability Zones, and deploys either NAT instances or NAT gateways for +outbound Internet access, depending on the AWS Region you deploy the Quick Start in. + +You can use this Quick Start as a building block for your own deployments. You can scale it +up or down by adding or removing subnets and Availability Zones according to your needs, +and add other infrastructure components and software layers to complete your AWS +environment. diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/partner_editable/regions.adoc b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/partner_editable/regions.adoc new file mode 100644 index 0000000..8003267 --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/partner_editable/regions.adoc @@ -0,0 +1,29 @@ + +[cols=3*,options="header"] +|=== +|Code +|Name +| Opt-in Status + +|us-east-2 |US East (Ohio) |Not required +|us-east-1 |US East (N. Virginia) |Not required +|us-west-1 |US West (N. California) |Not required +|us-west-2 |US West (Oregon) |Not required +|af-south-1 |Africa (Cape Town) |Required +|ap-east-1 |Asia Pacific (Hong Kong) |Required +|ap-south-1 |Asia Pacific (Mumbai) |Not required +|ap-northeast-3 |Asia Pacific (Osaka-Local) |Not required +|ap-northeast-2 |Asia Pacific (Seoul) |Not required +|ap-southeast-1 |Asia Pacific (Singapore) |Not required +|ap-southeast-2 |Asia Pacific (Sydney) |Not required +|ap-northeast-1 |Asia Pacific (Tokyo) |Not required +|ca-central-1 |Canada (Central) |Not required +|eu-central-1 |Europe (Frankfurt) |Not required +|eu-west-1 |Europe (Ireland) |Not required +|eu-west-2 |Europe (London) |Not required +|eu-south-1 |Europe (Milan) |Required +|eu-west-3 |Europe (Paris) |Not required +|eu-north-1 |Europe (Stockholm) |Not required +|me-south-1 |Middle East (Bahrain) |Required +|sa-east-1 |South America (São Paulo) |Not required +|=== \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/partner_editable/service_limits.adoc b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/partner_editable/service_limits.adoc new file mode 100644 index 0000000..d6b8b90 --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/partner_editable/service_limits.adoc @@ -0,0 +1,7 @@ +// Replace the in each row to specify the number of resources used in this deployment. Remove the rows for resources that aren’t used. +|=== +|Resource |This deployment uses + +// Space needed to maintain table headers +|VPCs |1 +|=== diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/partner_editable/specialized_knowledge.adoc b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/partner_editable/specialized_knowledge.adoc new file mode 100644 index 0000000..1bd75e1 --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/docs/partner_editable/specialized_knowledge.adoc @@ -0,0 +1,6 @@ +// Replace the content in <> +// Describe or link to specific knowledge requirements; for example: “familiarity with basic concepts in the areas of networking, database operations, and data encryption” or “familiarity with .” + +This Quick Start assumes familiarity with VPC architecure and CloudFormation. + + diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/templates/aws-vpc.template b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/templates/aws-vpc.template new file mode 100644 index 0000000..294117a --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/templates/aws-vpc.template @@ -0,0 +1,3591 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "This template creates a Multi-AZ, multi-subnet VPC infrastructure with managed NAT gateways in the public subnet for each Availability Zone. You can also create additional private subnets with dedicated custom network access control lists (ACLs). If you deploy the Quick Start in a region that doesn't support NAT gateways, NAT instances are deployed instead. **WARNING** This template creates AWS resources. You will be billed for the AWS resources used if you create a stack from this template. (qs-1qnnspaap)", + "Metadata": { + "AWS::CloudFormation::Interface": { + "ParameterGroups": [ + { + "Label": { + "default": "Availability Zone Configuration" + }, + "Parameters": [ + "AvailabilityZones", + "NumberOfAZs" + ] + }, + { + "Label": { + "default": "Network Configuration" + }, + "Parameters": [ + "VPCCIDR", + "PublicSubnet1CIDR", + "PublicSubnet2CIDR", + "PublicSubnet3CIDR", + "PublicSubnet4CIDR", + "PublicSubnetTag1", + "PublicSubnetTag2", + "PublicSubnetTag3", + "CreatePrivateSubnets", + "PrivateSubnet1ACIDR", + "PrivateSubnet2ACIDR", + "PrivateSubnet3ACIDR", + "PrivateSubnet4ACIDR", + "PrivateSubnetATag1", + "PrivateSubnetATag2", + "PrivateSubnetATag3", + "CreateAdditionalPrivateSubnets", + "PrivateSubnet1BCIDR", + "PrivateSubnet2BCIDR", + "PrivateSubnet3BCIDR", + "PrivateSubnet4BCIDR", + "PrivateSubnetBTag1", + "PrivateSubnetBTag2", + "PrivateSubnetBTag3", + "VPCTenancy" + ] + }, + { + "Label": { + "default": "Deprecated: NAT Instance Configuration" + }, + "Parameters": [ + "KeyPairName", + "NATInstanceType" + ] + } + ], + "ParameterLabels": { + "AvailabilityZones": { + "default": "Availability Zones" + }, + "CreateAdditionalPrivateSubnets": { + "default": "Create additional private subnets with dedicated network ACLs" + }, + "CreatePrivateSubnets": { + "default": "Create private subnets" + }, + "KeyPairName": { + "default": "Deprecated: Key pair name" + }, + "NATInstanceType": { + "default": "Deprecated: NAT instance type" + }, + "NumberOfAZs": { + "default": "Number of Availability Zones" + }, + "PrivateSubnet1ACIDR": { + "default": "Private subnet 1A CIDR" + }, + "PrivateSubnet1BCIDR": { + "default": "Private subnet 1B with dedicated network ACL CIDR" + }, + "PrivateSubnet2ACIDR": { + "default": "Private subnet 2A CIDR" + }, + "PrivateSubnet2BCIDR": { + "default": "Private subnet 2B with dedicated network ACL CIDR" + }, + "PrivateSubnet3ACIDR": { + "default": "Private subnet 3A CIDR" + }, + "PrivateSubnet3BCIDR": { + "default": "Private subnet 3B with dedicated network ACL CIDR" + }, + "PrivateSubnet4ACIDR": { + "default": "Private subnet 4A CIDR" + }, + "PrivateSubnet4BCIDR": { + "default": "Private subnet 4B with dedicated network ACL CIDR" + }, + "PrivateSubnetATag1": { + "default": "Tag for Private A Subnets" + }, + "PrivateSubnetATag2": { + "default": "Tag for Private A Subnets" + }, + "PrivateSubnetATag3": { + "default": "Tag for Private A Subnets" + }, + "PrivateSubnetBTag1": { + "default": "Tag for Private B Subnets" + }, + "PrivateSubnetBTag2": { + "default": "Tag for Private B Subnets" + }, + "PrivateSubnetBTag3": { + "default": "Tag for Private B Subnets" + }, + "PublicSubnet1CIDR": { + "default": "Public subnet 1 CIDR" + }, + "PublicSubnet2CIDR": { + "default": "Public subnet 2 CIDR" + }, + "PublicSubnet3CIDR": { + "default": "Public subnet 3 CIDR" + }, + "PublicSubnet4CIDR": { + "default": "Public subnet 4 CIDR" + }, + "PublicSubnetTag1": { + "default": "Tag for Public Subnets" + }, + "PublicSubnetTag2": { + "default": "Tag for Public Subnets" + }, + "PublicSubnetTag3": { + "default": "Tag for Public Subnets" + }, + "VPCCIDR": { + "default": "VPC CIDR" + }, + "VPCTenancy": { + "default": "VPC Tenancy" + } + } + } + }, + "Parameters": { + "AvailabilityZones": { + "Description": "List of Availability Zones to use for the subnets in the VPC. Note: The logical order is preserved.", + "Type": "List" + }, + "CreateAdditionalPrivateSubnets": { + "AllowedValues": [ + "true", + "false" + ], + "Default": "false", + "Description": "Set to true to create a network ACL protected subnet in each Availability Zone. If false, the CIDR parameters for those subnets will be ignored. If true, it also requires that the 'Create private subnets' parameter is also true to have any effect.", + "Type": "String" + }, + "CreatePrivateSubnets": { + "AllowedValues": [ + "true", + "false" + ], + "Default": "true", + "Description": "Set to false to create only public subnets. If false, the CIDR parameters for ALL private subnets will be ignored.", + "Type": "String" + }, + "KeyPairName": { + "Description": "Deprecated. NAT gateways are now supported in all regions.", + "Type": "String", + "Default": "deprecated" + }, + "NATInstanceType": { + "Default": "deprecated", + "Description": "Deprecated. NAT gateways are now supported in all regions.", + "Type": "String" + }, + "NumberOfAZs": { + "AllowedValues": [ + "2", + "3", + "4" + ], + "Default": "2", + "Description": "Number of Availability Zones to use in the VPC. This must match your selections in the list of Availability Zones parameter.", + "Type": "String" + }, + "PrivateSubnet1ACIDR": { + "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$", + "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28", + "Default": "10.0.0.0/19", + "Description": "CIDR block for private subnet 1A located in Availability Zone 1", + "Type": "String" + }, + "PrivateSubnet1BCIDR": { + "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$", + "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28", + "Default": "10.0.192.0/21", + "Description": "CIDR block for private subnet 1B with dedicated network ACL located in Availability Zone 1", + "Type": "String" + }, + "PrivateSubnet2ACIDR": { + "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$", + "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28", + "Default": "10.0.32.0/19", + "Description": "CIDR block for private subnet 2A located in Availability Zone 2", + "Type": "String" + }, + "PrivateSubnet2BCIDR": { + "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$", + "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28", + "Default": "10.0.200.0/21", + "Description": "CIDR block for private subnet 2B with dedicated network ACL located in Availability Zone 2", + "Type": "String" + }, + "PrivateSubnet3ACIDR": { + "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$", + "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28", + "Default": "10.0.64.0/19", + "Description": "CIDR block for private subnet 3A located in Availability Zone 3", + "Type": "String" + }, + "PrivateSubnet3BCIDR": { + "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$", + "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28", + "Default": "10.0.208.0/21", + "Description": "CIDR block for private subnet 3B with dedicated network ACL located in Availability Zone 3", + "Type": "String" + }, + "PrivateSubnet4ACIDR": { + "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$", + "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28", + "Default": "10.0.96.0/19", + "Description": "CIDR block for private subnet 4A located in Availability Zone 4", + "Type": "String" + }, + "PrivateSubnet4BCIDR": { + "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$", + "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28", + "Default": "10.0.216.0/21", + "Description": "CIDR block for private subnet 4B with dedicated network ACL located in Availability Zone 4", + "Type": "String" + }, + "PrivateSubnetATag1": { + "AllowedPattern": "^([a-zA-Z0-9+\\-._:/@]+=[a-zA-Z0-9+\\-.,_:/@ *\\\\\"'\\[\\]\\{\\}]*)?$", + "ConstraintDescription": "tags must be in format \"Key=Value\" keys can only contain [a-zA-Z0-9+\\-._:/@], values can contain [a-zA-Z0-9+\\-._:/@ *\\\\\"'\\[\\]\\{\\}]", + "Default": "Network=Private", + "Description": "tag to add to private subnets A, in format Key=Value (Optional)", + "Type": "String" + }, + "PrivateSubnetATag2": { + "AllowedPattern": "^([a-zA-Z0-9+\\-._:/@]+=[a-zA-Z0-9+\\-.,_:/@ *\\\\\"'\\[\\]\\{\\}]*)?$", + "ConstraintDescription": "tags must be in format \"Key=Value\" keys can only contain [a-zA-Z0-9+\\-._:/@], values can contain [a-zA-Z0-9+\\-._:/@ *\\\\\"'\\[\\]\\{\\}]", + "Default": "", + "Description": "tag to add to private subnets A, in format Key=Value (Optional)", + "Type": "String" + }, + "PrivateSubnetATag3": { + "AllowedPattern": "^([a-zA-Z0-9+\\-._:/@]+=[a-zA-Z0-9+\\-.,_:/@ *\\\\\"'\\[\\]\\{\\}]*)?$", + "ConstraintDescription": "tags must be in format \"Key=Value\" keys can only contain [a-zA-Z0-9+\\-._:/@], values can contain [a-zA-Z0-9+\\-._:/@ *\\\\\"'\\[\\]\\{\\}]", + "Default": "", + "Description": "tag to add to private subnets A, in format Key=Value (Optional)", + "Type": "String" + }, + "PrivateSubnetBTag1": { + "AllowedPattern": "^([a-zA-Z0-9+\\-._:/@]+=[a-zA-Z0-9+\\-.,_:/@ *\\\\\"'\\[\\]\\{\\}]*)?$", + "ConstraintDescription": "tags must be in format \"Key=Value\" keys can only contain [a-zA-Z0-9+\\-._:/@], values can contain [a-zA-Z0-9+\\-._:/@ *\\\\\"'\\[\\]\\{\\}]", + "Default": "Network=Private", + "Description": "tag to add to private subnets B, in format Key=Value (Optional)", + "Type": "String" + }, + "PrivateSubnetBTag2": { + "AllowedPattern": "^([a-zA-Z0-9+\\-._:/@]+=[a-zA-Z0-9+\\-.,_:/@ *\\\\\"'\\[\\]\\{\\}]*)?$", + "ConstraintDescription": "tags must be in format \"Key=Value\" keys can only contain [a-zA-Z0-9+\\-._:/@], values can contain [a-zA-Z0-9+\\-._:/@ *\\\\\"'\\[\\]\\{\\}]", + "Default": "", + "Description": "tag to add to private subnets B, in format Key=Value (Optional)", + "Type": "String" + }, + "PrivateSubnetBTag3": { + "AllowedPattern": "^([a-zA-Z0-9+\\-._:/@]+=[a-zA-Z0-9+\\-.,_:/@ *\\\\\"'\\[\\]\\{\\}]*)?$", + "ConstraintDescription": "tags must be in format \"Key=Value\" keys can only contain [a-zA-Z0-9+\\-._:/@], values can contain [a-zA-Z0-9+\\-._:/@ *\\\\\"'\\[\\]\\{\\}]", + "Default": "", + "Description": "tag to add to private subnets B, in format Key=Value (Optional)", + "Type": "String" + }, + "PublicSubnet1CIDR": { + "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$", + "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28", + "Default": "10.0.128.0/20", + "Description": "CIDR block for the public DMZ subnet 1 located in Availability Zone 1", + "Type": "String" + }, + "PublicSubnet2CIDR": { + "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$", + "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28", + "Default": "10.0.144.0/20", + "Description": "CIDR block for the public DMZ subnet 2 located in Availability Zone 2", + "Type": "String" + }, + "PublicSubnet3CIDR": { + "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$", + "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28", + "Default": "10.0.160.0/20", + "Description": "CIDR block for the public DMZ subnet 3 located in Availability Zone 3", + "Type": "String" + }, + "PublicSubnet4CIDR": { + "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$", + "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28", + "Default": "10.0.176.0/20", + "Description": "CIDR block for the public DMZ subnet 4 located in Availability Zone 4", + "Type": "String" + }, + "PublicSubnetTag1": { + "AllowedPattern": "^([a-zA-Z0-9+\\-._:/@]+=[a-zA-Z0-9+\\-.,_:/@ *\\\\\"'\\[\\]\\{\\}]*)?$", + "ConstraintDescription": "tags must be in format \"Key=Value\" keys can only contain [a-zA-Z0-9+\\-._:/@], values can contain [a-zA-Z0-9+\\-._:/@ *\\\\\"'\\[\\]\\{\\}]", + "Default": "Network=Public", + "Description": "tag to add to public subnets, in format Key=Value (Optional)", + "Type": "String" + }, + "PublicSubnetTag2": { + "AllowedPattern": "^([a-zA-Z0-9+\\-._:/@]+=[a-zA-Z0-9+\\-.,_:/@ *\\\\\"'\\[\\]\\{\\}]*)?$", + "ConstraintDescription": "tags must be in format \"Key=Value\" keys can only contain [a-zA-Z0-9+\\-._:/@], values can contain [a-zA-Z0-9+\\-._:/@ *\\\\\"'\\[\\]\\{\\}]", + "Default": "", + "Description": "tag to add to public subnets, in format Key=Value (Optional)", + "Type": "String" + }, + "PublicSubnetTag3": { + "AllowedPattern": "^([a-zA-Z0-9+\\-._:/@]+=[a-zA-Z0-9+\\-.,_:/@ *\\\\\"'\\[\\]\\{\\}]*)?$", + "ConstraintDescription": "tags must be in format \"Key=Value\" keys can only contain [a-zA-Z0-9+\\-._:/@], values can contain [a-zA-Z0-9+\\-._:/@ *\\\\\"'\\[\\]\\{\\}]", + "Default": "", + "Description": "tag to add to public subnets, in format Key=Value (Optional)", + "Type": "String" + }, + "VPCCIDR": { + "AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-8]))$", + "ConstraintDescription": "CIDR block parameter must be in the form x.x.x.x/16-28", + "Default": "10.0.0.0/16", + "Description": "CIDR block for the VPC", + "Type": "String" + }, + "VPCTenancy": { + "AllowedValues": [ + "default", + "dedicated" + ], + "Default": "default", + "Description": "The allowed tenancy of instances launched into the VPC", + "Type": "String" + } + }, + "Conditions": { + "3AZCondition": { + "Fn::Or": [ + { + "Fn::Equals": [ + { + "Ref": "NumberOfAZs" + }, + "3" + ] + }, + { + "Condition": "4AZCondition" + } + ] + }, + "4AZCondition": { + "Fn::Equals": [ + { + "Ref": "NumberOfAZs" + }, + "4" + ] + }, + "AdditionalPrivateSubnetsCondition": { + "Fn::And": [ + { + "Fn::Equals": [ + { + "Ref": "CreatePrivateSubnets" + }, + "true" + ] + }, + { + "Fn::Equals": [ + { + "Ref": "CreateAdditionalPrivateSubnets" + }, + "true" + ] + } + ] + }, + "AdditionalPrivateSubnets&3AZCondition": { + "Fn::And": [ + { + "Condition": "AdditionalPrivateSubnetsCondition" + }, + { + "Condition": "3AZCondition" + } + ] + }, + "AdditionalPrivateSubnets&4AZCondition": { + "Fn::And": [ + { + "Condition": "AdditionalPrivateSubnetsCondition" + }, + { + "Condition": "4AZCondition" + } + ] + }, + "GovCloudCondition": { + "Fn::Equals": [ + { + "Ref": "AWS::Region" + }, + "us-gov-west-1" + ] + }, + "NVirginiaRegionCondition": { + "Fn::Equals": [ + { + "Ref": "AWS::Region" + }, + "us-east-1" + ] + }, + "PrivateSubnetsCondition": { + "Fn::Equals": [ + { + "Ref": "CreatePrivateSubnets" + }, + "true" + ] + }, + "PrivateSubnets&3AZCondition": { + "Fn::And": [ + { + "Condition": "PrivateSubnetsCondition" + }, + { + "Condition": "3AZCondition" + } + ] + }, + "PrivateSubnets&4AZCondition": { + "Fn::And": [ + { + "Condition": "PrivateSubnetsCondition" + }, + { + "Condition": "4AZCondition" + } + ] + }, + "PrivateSubnetATag1Condition": { + "Fn::Not": [ + { + "Fn::Equals": [ + { + "Ref": "PrivateSubnetATag1" + }, + "" + ] + } + ] + }, + "PrivateSubnetATag2Condition": { + "Fn::Not": [ + { + "Fn::Equals": [ + { + "Ref": "PrivateSubnetATag2" + }, + "" + ] + } + ] + }, + "PrivateSubnetATag3Condition": { + "Fn::Not": [ + { + "Fn::Equals": [ + { + "Ref": "PrivateSubnetATag3" + }, + "" + ] + } + ] + }, + "PrivateSubnetBTag1Condition": { + "Fn::Not": [ + { + "Fn::Equals": [ + { + "Ref": "PrivateSubnetBTag1" + }, + "" + ] + } + ] + }, + "PrivateSubnetBTag2Condition": { + "Fn::Not": [ + { + "Fn::Equals": [ + { + "Ref": "PrivateSubnetBTag2" + }, + "" + ] + } + ] + }, + "PrivateSubnetBTag3Condition": { + "Fn::Not": [ + { + "Fn::Equals": [ + { + "Ref": "PrivateSubnetBTag3" + }, + "" + ] + } + ] + }, + "PublicSubnetTag1Condition": { + "Fn::Not": [ + { + "Fn::Equals": [ + { + "Ref": "PublicSubnetTag1" + }, + "" + ] + } + ] + }, + "PublicSubnetTag2Condition": { + "Fn::Not": [ + { + "Fn::Equals": [ + { + "Ref": "PublicSubnetTag2" + }, + "" + ] + } + ] + }, + "PublicSubnetTag3Condition": { + "Fn::Not": [ + { + "Fn::Equals": [ + { + "Ref": "PublicSubnetTag3" + }, + "" + ] + } + ] + } + }, + "Resources": { + "DHCPOptions": { + "Type": "AWS::EC2::DHCPOptions", + "Properties": { + "DomainName": { + "Fn::If": [ + "NVirginiaRegionCondition", + "ec2.internal", + { + "Fn::Sub": "${AWS::Region}.compute.internal" + } + ] + }, + "DomainNameServers": [ + "AmazonProvidedDNS" + ] + } + }, + "VPC": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": { + "Ref": "VPCCIDR" + }, + "InstanceTenancy": { + "Ref": "VPCTenancy" + }, + "EnableDnsSupport": true, + "EnableDnsHostnames": true, + "Tags": [ + { + "Key": "Name", + "Value": { + "Ref": "AWS::StackName" + } + } + ] + } + }, + "VPCDHCPOptionsAssociation": { + "Type": "AWS::EC2::VPCDHCPOptionsAssociation", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "DhcpOptionsId": { + "Ref": "DHCPOptions" + } + } + }, + "InternetGateway": { + "Type": "AWS::EC2::InternetGateway", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": { + "Ref": "AWS::StackName" + } + } + ] + } + }, + "VPCGatewayAttachment": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "InternetGatewayId": { + "Ref": "InternetGateway" + } + } + }, + "PrivateSubnet1A": { + "Condition": "PrivateSubnetsCondition", + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "CidrBlock": { + "Ref": "PrivateSubnet1ACIDR" + }, + "AvailabilityZone": { + "Fn::Select": [ + "0", + { + "Ref": "AvailabilityZones" + } + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 1A" + }, + { + "Fn::If": [ + "PrivateSubnetATag1Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag1" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag1" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetATag2Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag2" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag2" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetATag3Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag3" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag3" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + } + ] + } + }, + "PrivateSubnet1B": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "CidrBlock": { + "Ref": "PrivateSubnet1BCIDR" + }, + "AvailabilityZone": { + "Fn::Select": [ + "0", + { + "Ref": "AvailabilityZones" + } + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 1B" + }, + { + "Fn::If": [ + "PrivateSubnetBTag1Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag1" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag1" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetBTag2Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag2" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag2" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetBTag3Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag3" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag3" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + } + ] + } + }, + "PrivateSubnet2A": { + "Condition": "PrivateSubnetsCondition", + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "CidrBlock": { + "Ref": "PrivateSubnet2ACIDR" + }, + "AvailabilityZone": { + "Fn::Select": [ + "1", + { + "Ref": "AvailabilityZones" + } + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 2A" + }, + { + "Fn::If": [ + "PrivateSubnetATag1Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag1" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag1" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetATag2Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag2" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag2" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetATag3Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag3" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag3" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + } + ] + } + }, + "PrivateSubnet2B": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "CidrBlock": { + "Ref": "PrivateSubnet2BCIDR" + }, + "AvailabilityZone": { + "Fn::Select": [ + "1", + { + "Ref": "AvailabilityZones" + } + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 2B" + }, + { + "Fn::If": [ + "PrivateSubnetBTag1Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag1" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag1" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetBTag2Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag2" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag2" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetBTag3Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag3" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag3" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + } + ] + } + }, + "PrivateSubnet3A": { + "Condition": "PrivateSubnets&3AZCondition", + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "CidrBlock": { + "Ref": "PrivateSubnet3ACIDR" + }, + "AvailabilityZone": { + "Fn::Select": [ + "2", + { + "Ref": "AvailabilityZones" + } + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 3A" + }, + { + "Fn::If": [ + "PrivateSubnetATag1Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag1" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag1" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetATag2Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag2" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag2" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetATag3Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag3" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag3" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + } + ] + } + }, + "PrivateSubnet3B": { + "Condition": "AdditionalPrivateSubnets&3AZCondition", + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "CidrBlock": { + "Ref": "PrivateSubnet3BCIDR" + }, + "AvailabilityZone": { + "Fn::Select": [ + "2", + { + "Ref": "AvailabilityZones" + } + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 3B" + }, + { + "Fn::If": [ + "PrivateSubnetBTag1Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag1" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag1" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetBTag2Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag2" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag2" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetBTag3Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag3" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag3" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + } + ] + } + }, + "PrivateSubnet4A": { + "Condition": "PrivateSubnets&4AZCondition", + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "CidrBlock": { + "Ref": "PrivateSubnet4ACIDR" + }, + "AvailabilityZone": { + "Fn::Select": [ + "3", + { + "Ref": "AvailabilityZones" + } + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 4A" + }, + { + "Fn::If": [ + "PrivateSubnetATag1Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag1" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag1" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetATag2Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag2" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag2" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetATag3Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag3" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetATag3" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + } + ] + } + }, + "PrivateSubnet4B": { + "Condition": "AdditionalPrivateSubnets&4AZCondition", + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "CidrBlock": { + "Ref": "PrivateSubnet4BCIDR" + }, + "AvailabilityZone": { + "Fn::Select": [ + "3", + { + "Ref": "AvailabilityZones" + } + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 4B" + }, + { + "Fn::If": [ + "PrivateSubnetBTag1Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag1" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag1" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetBTag2Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag2" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag2" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnetBTag3Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag3" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PrivateSubnetBTag3" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + } + ] + } + }, + "PublicSubnet1": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "CidrBlock": { + "Ref": "PublicSubnet1CIDR" + }, + "AvailabilityZone": { + "Fn::Select": [ + "0", + { + "Ref": "AvailabilityZones" + } + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "Public subnet 1" + }, + { + "Fn::If": [ + "PublicSubnetTag1Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag1" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag1" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PublicSubnetTag2Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag2" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag2" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PublicSubnetTag3Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag3" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag3" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + } + ], + "MapPublicIpOnLaunch": true + } + }, + "PublicSubnet2": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "CidrBlock": { + "Ref": "PublicSubnet2CIDR" + }, + "AvailabilityZone": { + "Fn::Select": [ + "1", + { + "Ref": "AvailabilityZones" + } + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "Public subnet 2" + }, + { + "Fn::If": [ + "PublicSubnetTag1Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag1" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag1" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PublicSubnetTag2Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag2" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag2" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PublicSubnetTag3Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag3" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag3" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + } + ], + "MapPublicIpOnLaunch": true + } + }, + "PublicSubnet3": { + "Condition": "3AZCondition", + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "CidrBlock": { + "Ref": "PublicSubnet3CIDR" + }, + "AvailabilityZone": { + "Fn::Select": [ + "2", + { + "Ref": "AvailabilityZones" + } + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "Public subnet 3" + }, + { + "Fn::If": [ + "PublicSubnetTag1Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag1" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag1" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PublicSubnetTag2Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag2" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag2" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PublicSubnetTag3Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag3" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag3" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + } + ], + "MapPublicIpOnLaunch": true + } + }, + "PublicSubnet4": { + "Condition": "4AZCondition", + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "CidrBlock": { + "Ref": "PublicSubnet4CIDR" + }, + "AvailabilityZone": { + "Fn::Select": [ + "3", + { + "Ref": "AvailabilityZones" + } + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "Public subnet 4" + }, + { + "Fn::If": [ + "PublicSubnetTag1Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag1" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag1" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PublicSubnetTag2Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag2" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag2" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PublicSubnetTag3Condition", + { + "Key": { + "Fn::Select": [ + "0", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag3" + } + ] + } + ] + }, + "Value": { + "Fn::Select": [ + "1", + { + "Fn::Split": [ + "=", + { + "Ref": "PublicSubnetTag3" + } + ] + } + ] + } + }, + { + "Ref": "AWS::NoValue" + } + ] + } + ], + "MapPublicIpOnLaunch": true + } + }, + "PrivateSubnet1ARouteTable": { + "Condition": "PrivateSubnetsCondition", + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 1A" + }, + { + "Key": "Network", + "Value": "Private" + } + ] + } + }, + "PrivateSubnet1ARoute": { + "Condition": "PrivateSubnetsCondition", + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "PrivateSubnet1ARouteTable" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "NATGateway1" + } + } + }, + "PrivateSubnet1ARouteTableAssociation": { + "Condition": "PrivateSubnetsCondition", + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "SubnetId": { + "Ref": "PrivateSubnet1A" + }, + "RouteTableId": { + "Ref": "PrivateSubnet1ARouteTable" + } + } + }, + "PrivateSubnet2ARouteTable": { + "Condition": "PrivateSubnetsCondition", + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 2A" + }, + { + "Key": "Network", + "Value": "Private" + } + ] + } + }, + "PrivateSubnet2ARoute": { + "Condition": "PrivateSubnetsCondition", + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "PrivateSubnet2ARouteTable" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "NATGateway2" + } + } + }, + "PrivateSubnet2ARouteTableAssociation": { + "Condition": "PrivateSubnetsCondition", + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "SubnetId": { + "Ref": "PrivateSubnet2A" + }, + "RouteTableId": { + "Ref": "PrivateSubnet2ARouteTable" + } + } + }, + "PrivateSubnet3ARouteTable": { + "Condition": "PrivateSubnets&3AZCondition", + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 3A" + }, + { + "Key": "Network", + "Value": "Private" + } + ] + } + }, + "PrivateSubnet3ARoute": { + "Condition": "PrivateSubnets&3AZCondition", + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "PrivateSubnet3ARouteTable" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "NATGateway3" + } + } + }, + "PrivateSubnet3ARouteTableAssociation": { + "Condition": "PrivateSubnets&3AZCondition", + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "SubnetId": { + "Ref": "PrivateSubnet3A" + }, + "RouteTableId": { + "Ref": "PrivateSubnet3ARouteTable" + } + } + }, + "PrivateSubnet4ARouteTable": { + "Condition": "PrivateSubnets&4AZCondition", + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 4A" + }, + { + "Key": "Network", + "Value": "Private" + } + ] + } + }, + "PrivateSubnet4ARoute": { + "Condition": "PrivateSubnets&4AZCondition", + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "PrivateSubnet4ARouteTable" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "NATGateway4" + } + } + }, + "PrivateSubnet4ARouteTableAssociation": { + "Condition": "PrivateSubnets&4AZCondition", + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "SubnetId": { + "Ref": "PrivateSubnet4A" + }, + "RouteTableId": { + "Ref": "PrivateSubnet4ARouteTable" + } + } + }, + "PrivateSubnet1BRouteTable": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 1B" + }, + { + "Key": "Network", + "Value": "Private" + } + ] + } + }, + "PrivateSubnet1BRoute": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "PrivateSubnet1BRouteTable" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "NATGateway1" + } + } + }, + "PrivateSubnet1BRouteTableAssociation": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "SubnetId": { + "Ref": "PrivateSubnet1B" + }, + "RouteTableId": { + "Ref": "PrivateSubnet1BRouteTable" + } + } + }, + "PrivateSubnet1BNetworkAcl": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::NetworkAcl", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "Tags": [ + { + "Key": "Name", + "Value": "NACL Protected subnet 1" + }, + { + "Key": "Network", + "Value": "NACL Protected" + } + ] + } + }, + "PrivateSubnet1BNetworkAclEntryInbound": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::NetworkAclEntry", + "Properties": { + "CidrBlock": "0.0.0.0/0", + "Egress": false, + "NetworkAclId": { + "Ref": "PrivateSubnet1BNetworkAcl" + }, + "Protocol": -1, + "RuleAction": "allow", + "RuleNumber": 100 + } + }, + "PrivateSubnet1BNetworkAclEntryOutbound": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::NetworkAclEntry", + "Properties": { + "CidrBlock": "0.0.0.0/0", + "Egress": true, + "NetworkAclId": { + "Ref": "PrivateSubnet1BNetworkAcl" + }, + "Protocol": -1, + "RuleAction": "allow", + "RuleNumber": 100 + } + }, + "PrivateSubnet1BNetworkAclAssociation": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::SubnetNetworkAclAssociation", + "Properties": { + "SubnetId": { + "Ref": "PrivateSubnet1B" + }, + "NetworkAclId": { + "Ref": "PrivateSubnet1BNetworkAcl" + } + } + }, + "PrivateSubnet2BRouteTable": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 2B" + }, + { + "Key": "Network", + "Value": "Private" + } + ] + } + }, + "PrivateSubnet2BRoute": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "PrivateSubnet2BRouteTable" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "NATGateway2" + } + } + }, + "PrivateSubnet2BRouteTableAssociation": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "SubnetId": { + "Ref": "PrivateSubnet2B" + }, + "RouteTableId": { + "Ref": "PrivateSubnet2BRouteTable" + } + } + }, + "PrivateSubnet2BNetworkAcl": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::NetworkAcl", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "Tags": [ + { + "Key": "Name", + "Value": "NACL Protected subnet 2" + }, + { + "Key": "Network", + "Value": "NACL Protected" + } + ] + } + }, + "PrivateSubnet2BNetworkAclEntryInbound": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::NetworkAclEntry", + "Properties": { + "CidrBlock": "0.0.0.0/0", + "Egress": false, + "NetworkAclId": { + "Ref": "PrivateSubnet2BNetworkAcl" + }, + "Protocol": -1, + "RuleAction": "allow", + "RuleNumber": 100 + } + }, + "PrivateSubnet2BNetworkAclEntryOutbound": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::NetworkAclEntry", + "Properties": { + "CidrBlock": "0.0.0.0/0", + "Egress": true, + "NetworkAclId": { + "Ref": "PrivateSubnet2BNetworkAcl" + }, + "Protocol": -1, + "RuleAction": "allow", + "RuleNumber": 100 + } + }, + "PrivateSubnet2BNetworkAclAssociation": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Type": "AWS::EC2::SubnetNetworkAclAssociation", + "Properties": { + "SubnetId": { + "Ref": "PrivateSubnet2B" + }, + "NetworkAclId": { + "Ref": "PrivateSubnet2BNetworkAcl" + } + } + }, + "PrivateSubnet3BRouteTable": { + "Condition": "AdditionalPrivateSubnets&3AZCondition", + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 3B" + }, + { + "Key": "Network", + "Value": "Private" + } + ] + } + }, + "PrivateSubnet3BRoute": { + "Condition": "AdditionalPrivateSubnets&3AZCondition", + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "PrivateSubnet3BRouteTable" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "NATGateway3" + } + } + }, + "PrivateSubnet3BRouteTableAssociation": { + "Condition": "AdditionalPrivateSubnets&3AZCondition", + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "SubnetId": { + "Ref": "PrivateSubnet3B" + }, + "RouteTableId": { + "Ref": "PrivateSubnet3BRouteTable" + } + } + }, + "PrivateSubnet3BNetworkAcl": { + "Condition": "AdditionalPrivateSubnets&3AZCondition", + "Type": "AWS::EC2::NetworkAcl", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "Tags": [ + { + "Key": "Name", + "Value": "NACL Protected subnet 3" + }, + { + "Key": "Network", + "Value": "NACL Protected" + } + ] + } + }, + "PrivateSubnet3BNetworkAclEntryInbound": { + "Condition": "AdditionalPrivateSubnets&3AZCondition", + "Type": "AWS::EC2::NetworkAclEntry", + "Properties": { + "CidrBlock": "0.0.0.0/0", + "Egress": false, + "NetworkAclId": { + "Ref": "PrivateSubnet3BNetworkAcl" + }, + "Protocol": -1, + "RuleAction": "allow", + "RuleNumber": 100 + } + }, + "PrivateSubnet3BNetworkAclEntryOutbound": { + "Condition": "AdditionalPrivateSubnets&3AZCondition", + "Type": "AWS::EC2::NetworkAclEntry", + "Properties": { + "CidrBlock": "0.0.0.0/0", + "Egress": true, + "NetworkAclId": { + "Ref": "PrivateSubnet3BNetworkAcl" + }, + "Protocol": -1, + "RuleAction": "allow", + "RuleNumber": 100 + } + }, + "PrivateSubnet3BNetworkAclAssociation": { + "Condition": "AdditionalPrivateSubnets&3AZCondition", + "Type": "AWS::EC2::SubnetNetworkAclAssociation", + "Properties": { + "SubnetId": { + "Ref": "PrivateSubnet3B" + }, + "NetworkAclId": { + "Ref": "PrivateSubnet3BNetworkAcl" + } + } + }, + "PrivateSubnet4BRouteTable": { + "Condition": "AdditionalPrivateSubnets&4AZCondition", + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "Tags": [ + { + "Key": "Name", + "Value": "Private subnet 4B" + }, + { + "Key": "Network", + "Value": "Private" + } + ] + } + }, + "PrivateSubnet4BRoute": { + "Condition": "AdditionalPrivateSubnets&4AZCondition", + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "PrivateSubnet4BRouteTable" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "NATGateway4" + } + } + }, + "PrivateSubnet4BRouteTableAssociation": { + "Condition": "AdditionalPrivateSubnets&4AZCondition", + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "SubnetId": { + "Ref": "PrivateSubnet4B" + }, + "RouteTableId": { + "Ref": "PrivateSubnet4BRouteTable" + } + } + }, + "PrivateSubnet4BNetworkAcl": { + "Condition": "AdditionalPrivateSubnets&4AZCondition", + "Type": "AWS::EC2::NetworkAcl", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "Tags": [ + { + "Key": "Name", + "Value": "NACL Protected subnet 4" + }, + { + "Key": "Network", + "Value": "NACL Protected" + } + ] + } + }, + "PrivateSubnet4BNetworkAclEntryInbound": { + "Condition": "AdditionalPrivateSubnets&4AZCondition", + "Type": "AWS::EC2::NetworkAclEntry", + "Properties": { + "CidrBlock": "0.0.0.0/0", + "Egress": false, + "NetworkAclId": { + "Ref": "PrivateSubnet4BNetworkAcl" + }, + "Protocol": -1, + "RuleAction": "allow", + "RuleNumber": 100 + } + }, + "PrivateSubnet4BNetworkAclEntryOutbound": { + "Condition": "AdditionalPrivateSubnets&4AZCondition", + "Type": "AWS::EC2::NetworkAclEntry", + "Properties": { + "CidrBlock": "0.0.0.0/0", + "Egress": true, + "NetworkAclId": { + "Ref": "PrivateSubnet4BNetworkAcl" + }, + "Protocol": -1, + "RuleAction": "allow", + "RuleNumber": 100 + } + }, + "PrivateSubnet4BNetworkAclAssociation": { + "Condition": "AdditionalPrivateSubnets&4AZCondition", + "Type": "AWS::EC2::SubnetNetworkAclAssociation", + "Properties": { + "SubnetId": { + "Ref": "PrivateSubnet4B" + }, + "NetworkAclId": { + "Ref": "PrivateSubnet4BNetworkAcl" + } + } + }, + "PublicSubnetRouteTable": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPC" + }, + "Tags": [ + { + "Key": "Name", + "Value": "Public Subnets" + }, + { + "Key": "Network", + "Value": "Public" + } + ] + } + }, + "PublicSubnetRoute": { + "DependsOn": "VPCGatewayAttachment", + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "PublicSubnetRouteTable" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "InternetGateway" + } + } + }, + "PublicSubnet1RouteTableAssociation": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "SubnetId": { + "Ref": "PublicSubnet1" + }, + "RouteTableId": { + "Ref": "PublicSubnetRouteTable" + } + } + }, + "PublicSubnet2RouteTableAssociation": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "SubnetId": { + "Ref": "PublicSubnet2" + }, + "RouteTableId": { + "Ref": "PublicSubnetRouteTable" + } + } + }, + "PublicSubnet3RouteTableAssociation": { + "Condition": "3AZCondition", + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "SubnetId": { + "Ref": "PublicSubnet3" + }, + "RouteTableId": { + "Ref": "PublicSubnetRouteTable" + } + } + }, + "PublicSubnet4RouteTableAssociation": { + "Condition": "4AZCondition", + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "SubnetId": { + "Ref": "PublicSubnet4" + }, + "RouteTableId": { + "Ref": "PublicSubnetRouteTable" + } + } + }, + "NAT1EIP": { + "Condition": "PrivateSubnetsCondition", + "DependsOn": "VPCGatewayAttachment", + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc" + } + }, + "NAT2EIP": { + "Condition": "PrivateSubnetsCondition", + "DependsOn": "VPCGatewayAttachment", + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc" + } + }, + "NAT3EIP": { + "Condition": "PrivateSubnets&3AZCondition", + "DependsOn": "VPCGatewayAttachment", + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc" + } + }, + "NAT4EIP": { + "Condition": "PrivateSubnets&4AZCondition", + "DependsOn": "VPCGatewayAttachment", + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc" + } + }, + "NATGateway1": { + "Condition": "PrivateSubnetsCondition", + "DependsOn": "VPCGatewayAttachment", + "Type": "AWS::EC2::NatGateway", + "Properties": { + "AllocationId": { + "Fn::GetAtt": [ + "NAT1EIP", + "AllocationId" + ] + }, + "SubnetId": { + "Ref": "PublicSubnet1" + } + } + }, + "NATGateway2": { + "Condition": "PrivateSubnetsCondition", + "DependsOn": "VPCGatewayAttachment", + "Type": "AWS::EC2::NatGateway", + "Properties": { + "AllocationId": { + "Fn::GetAtt": [ + "NAT2EIP", + "AllocationId" + ] + }, + "SubnetId": { + "Ref": "PublicSubnet2" + } + } + }, + "NATGateway3": { + "Condition": "PrivateSubnets&3AZCondition", + "DependsOn": "VPCGatewayAttachment", + "Type": "AWS::EC2::NatGateway", + "Properties": { + "AllocationId": { + "Fn::GetAtt": [ + "NAT3EIP", + "AllocationId" + ] + }, + "SubnetId": { + "Ref": "PublicSubnet3" + } + } + }, + "NATGateway4": { + "Condition": "PrivateSubnets&4AZCondition", + "DependsOn": "VPCGatewayAttachment", + "Type": "AWS::EC2::NatGateway", + "Properties": { + "AllocationId": { + "Fn::GetAtt": [ + "NAT4EIP", + "AllocationId" + ] + }, + "SubnetId": { + "Ref": "PublicSubnet4" + } + } + }, + "S3VPCEndpoint": { + "Condition": "PrivateSubnetsCondition", + "Type": "AWS::EC2::VPCEndpoint", + "Properties": { + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "*", + "Effect": "Allow", + "Resource": "*", + "Principal": "*" + } + ] + }, + "RouteTableIds": [ + { + "Ref": "PrivateSubnet1ARouteTable" + }, + { + "Ref": "PrivateSubnet2ARouteTable" + }, + { + "Fn::If": [ + "PrivateSubnets&3AZCondition", + { + "Ref": "PrivateSubnet3ARouteTable" + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "PrivateSubnets&4AZCondition", + { + "Ref": "PrivateSubnet4ARouteTable" + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "AdditionalPrivateSubnetsCondition", + { + "Ref": "PrivateSubnet1BRouteTable" + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "AdditionalPrivateSubnetsCondition", + { + "Ref": "PrivateSubnet2BRouteTable" + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "AdditionalPrivateSubnets&3AZCondition", + { + "Ref": "PrivateSubnet3BRouteTable" + }, + { + "Ref": "AWS::NoValue" + } + ] + }, + { + "Fn::If": [ + "AdditionalPrivateSubnets&4AZCondition", + { + "Ref": "PrivateSubnet4BRouteTable" + }, + { + "Ref": "AWS::NoValue" + } + ] + } + ], + "ServiceName": { + "Fn::Sub": "com.amazonaws.${AWS::Region}.s3" + }, + "VpcId": { + "Ref": "VPC" + } + } + } + }, + "Outputs": { + "NAT1EIP": { + "Condition": "PrivateSubnetsCondition", + "Description": "NAT 1 IP address", + "Value": { + "Ref": "NAT1EIP" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-NAT1EIP" + } + } + }, + "NAT2EIP": { + "Condition": "PrivateSubnetsCondition", + "Description": "NAT 2 IP address", + "Value": { + "Ref": "NAT2EIP" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-NAT2EIP" + } + } + }, + "NAT3EIP": { + "Condition": "PrivateSubnets&3AZCondition", + "Description": "NAT 3 IP address", + "Value": { + "Ref": "NAT3EIP" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-NAT3EIP" + } + } + }, + "NAT4EIP": { + "Condition": "PrivateSubnets&4AZCondition", + "Description": "NAT 4 IP address", + "Value": { + "Ref": "NAT4EIP" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-NAT4EIP" + } + } + }, + "PrivateSubnet1ACIDR": { + "Condition": "PrivateSubnetsCondition", + "Description": "Private subnet 1A CIDR in Availability Zone 1", + "Value": { + "Ref": "PrivateSubnet1ACIDR" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet1ACIDR" + } + } + }, + "PrivateSubnet1AID": { + "Condition": "PrivateSubnetsCondition", + "Description": "Private subnet 1A ID in Availability Zone 1", + "Value": { + "Ref": "PrivateSubnet1A" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet1AID" + } + } + }, + "PrivateSubnet1BCIDR": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Description": "Private subnet 1B CIDR in Availability Zone 1", + "Value": { + "Ref": "PrivateSubnet1BCIDR" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet1BCIDR" + } + } + }, + "PrivateSubnet1BID": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Description": "Private subnet 1B ID in Availability Zone 1", + "Value": { + "Ref": "PrivateSubnet1B" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet1BID" + } + } + }, + "PrivateSubnet2ACIDR": { + "Condition": "PrivateSubnetsCondition", + "Description": "Private subnet 2A CIDR in Availability Zone 2", + "Value": { + "Ref": "PrivateSubnet2ACIDR" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet2ACIDR" + } + } + }, + "PrivateSubnet2AID": { + "Condition": "PrivateSubnetsCondition", + "Description": "Private subnet 2A ID in Availability Zone 2", + "Value": { + "Ref": "PrivateSubnet2A" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet2AID" + } + } + }, + "PrivateSubnet2BCIDR": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Description": "Private subnet 2B CIDR in Availability Zone 2", + "Value": { + "Ref": "PrivateSubnet2BCIDR" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet2BCIDR" + } + } + }, + "PrivateSubnet2BID": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Description": "Private subnet 2B ID in Availability Zone 2", + "Value": { + "Ref": "PrivateSubnet2B" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet2BID" + } + } + }, + "PrivateSubnet3ACIDR": { + "Condition": "PrivateSubnets&3AZCondition", + "Description": "Private subnet 3A CIDR in Availability Zone 3", + "Value": { + "Ref": "PrivateSubnet3ACIDR" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet3ACIDR" + } + } + }, + "PrivateSubnet3AID": { + "Condition": "PrivateSubnets&3AZCondition", + "Description": "Private subnet 3A ID in Availability Zone 3", + "Value": { + "Ref": "PrivateSubnet3A" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet3AID" + } + } + }, + "PrivateSubnet3BCIDR": { + "Condition": "AdditionalPrivateSubnets&3AZCondition", + "Description": "Private subnet 3B CIDR in Availability Zone 3", + "Value": { + "Ref": "PrivateSubnet3BCIDR" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet3BCIDR" + } + } + }, + "PrivateSubnet3BID": { + "Condition": "AdditionalPrivateSubnets&3AZCondition", + "Description": "Private subnet 3B ID in Availability Zone 3", + "Value": { + "Ref": "PrivateSubnet3B" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet3BID" + } + } + }, + "PrivateSubnet4ACIDR": { + "Condition": "PrivateSubnets&4AZCondition", + "Description": "Private subnet 4A CIDR in Availability Zone 4", + "Value": { + "Ref": "PrivateSubnet4ACIDR" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet4ACIDR" + } + } + }, + "PrivateSubnet4AID": { + "Condition": "PrivateSubnets&4AZCondition", + "Description": "Private subnet 4A ID in Availability Zone 4", + "Value": { + "Ref": "PrivateSubnet4A" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet4AID" + } + } + }, + "PrivateSubnet4BCIDR": { + "Condition": "AdditionalPrivateSubnets&4AZCondition", + "Description": "Private subnet 4B CIDR in Availability Zone 4", + "Value": { + "Ref": "PrivateSubnet4BCIDR" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet4BCIDR" + } + } + }, + "PrivateSubnet4BID": { + "Condition": "AdditionalPrivateSubnets&4AZCondition", + "Description": "Private subnet 4B ID in Availability Zone 4", + "Value": { + "Ref": "PrivateSubnet4B" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet4BID" + } + } + }, + "PublicSubnet1CIDR": { + "Description": "Public subnet 1 CIDR in Availability Zone 1", + "Value": { + "Ref": "PublicSubnet1CIDR" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PublicSubnet1CIDR" + } + } + }, + "PublicSubnet1ID": { + "Description": "Public subnet 1 ID in Availability Zone 1", + "Value": { + "Ref": "PublicSubnet1" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PublicSubnet1ID" + } + } + }, + "PublicSubnet2CIDR": { + "Description": "Public subnet 2 CIDR in Availability Zone 2", + "Value": { + "Ref": "PublicSubnet2CIDR" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PublicSubnet2CIDR" + } + } + }, + "PublicSubnet2ID": { + "Description": "Public subnet 2 ID in Availability Zone 2", + "Value": { + "Ref": "PublicSubnet2" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PublicSubnet2ID" + } + } + }, + "PublicSubnet3CIDR": { + "Condition": "3AZCondition", + "Description": "Public subnet 3 CIDR in Availability Zone 3", + "Value": { + "Ref": "PublicSubnet3CIDR" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PublicSubnet3CIDR" + } + } + }, + "PublicSubnet3ID": { + "Condition": "3AZCondition", + "Description": "Public subnet 3 ID in Availability Zone 3", + "Value": { + "Ref": "PublicSubnet3" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PublicSubnet3ID" + } + } + }, + "PublicSubnet4CIDR": { + "Condition": "4AZCondition", + "Description": "Public subnet 4 CIDR in Availability Zone 4", + "Value": { + "Ref": "PublicSubnet4CIDR" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PublicSubnet4CIDR" + } + } + }, + "PublicSubnet4ID": { + "Condition": "4AZCondition", + "Description": "Public subnet 4 ID in Availability Zone 4", + "Value": { + "Ref": "PublicSubnet4" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PublicSubnet4ID" + } + } + }, + "S3VPCEndpoint": { + "Condition": "PrivateSubnetsCondition", + "Description": "S3 VPC Endpoint", + "Value": { + "Ref": "S3VPCEndpoint" + }, + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-S3VPCEndpoint" + } + } + }, + "PrivateSubnet1ARouteTable": { + "Condition": "PrivateSubnetsCondition", + "Value": { + "Ref": "PrivateSubnet1ARouteTable" + }, + "Description": "Private subnet 1A route table", + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet1ARouteTable" + } + } + }, + "PrivateSubnet1BRouteTable": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Value": { + "Ref": "PrivateSubnet1BRouteTable" + }, + "Description": "Private subnet 1B route table", + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet1BRouteTable" + } + } + }, + "PrivateSubnet2ARouteTable": { + "Condition": "PrivateSubnetsCondition", + "Value": { + "Ref": "PrivateSubnet2ARouteTable" + }, + "Description": "Private subnet 2A route table", + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet2ARouteTable" + } + } + }, + "PrivateSubnet2BRouteTable": { + "Condition": "AdditionalPrivateSubnetsCondition", + "Value": { + "Ref": "PrivateSubnet2BRouteTable" + }, + "Description": "Private subnet 2B route table", + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet2BRouteTable" + } + } + }, + "PrivateSubnet3ARouteTable": { + "Condition": "PrivateSubnets&3AZCondition", + "Value": { + "Ref": "PrivateSubnet3ARouteTable" + }, + "Description": "Private subnet 3A route table", + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet3ARouteTable" + } + } + }, + "PrivateSubnet3BRouteTable": { + "Condition": "AdditionalPrivateSubnets&3AZCondition", + "Value": { + "Ref": "PrivateSubnet3BRouteTable" + }, + "Description": "Private subnet 3B route table", + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet3BRouteTable" + } + } + }, + "PrivateSubnet4ARouteTable": { + "Condition": "PrivateSubnets&4AZCondition", + "Value": { + "Ref": "PrivateSubnet4ARouteTable" + }, + "Description": "Private subnet 4A route table", + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet4ARouteTable" + } + } + }, + "PrivateSubnet4BRouteTable": { + "Condition": "AdditionalPrivateSubnets&4AZCondition", + "Value": { + "Ref": "PrivateSubnet4BRouteTable" + }, + "Description": "Private subnet 4B route table", + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PrivateSubnet4BRouteTable" + } + } + }, + "PublicSubnetRouteTable": { + "Value": { + "Ref": "PublicSubnetRouteTable" + }, + "Description": "Public subnet route table", + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-PublicSubnetRouteTable" + } + } + }, + "VPCCIDR": { + "Value": { + "Ref": "VPCCIDR" + }, + "Description": "VPC CIDR", + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-VPCCIDR" + } + } + }, + "VPCID": { + "Value": { + "Ref": "VPC" + }, + "Description": "VPC ID", + "Export": { + "Name": { + "Fn::Sub": "${AWS::StackName}-VPCID" + } + } + } + } +} diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/templates/aws-vpc.template.yaml b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/templates/aws-vpc.template.yaml new file mode 100644 index 0000000..f1292d8 --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-aws-vpc/templates/aws-vpc.template.yaml @@ -0,0 +1,1809 @@ +AWSTemplateFormatVersion: '2010-09-09' +Description: >- + This template creates a Multi-AZ, multi-subnet VPC infrastructure with managed NAT + gateways in the public subnet for each Availability Zone. You can also create additional + private subnets with dedicated custom network access control lists (ACLs). If you + deploy the Quick Start in a region that doesn't support NAT gateways, NAT instances + are deployed instead. **WARNING** This template creates AWS resources. You will + be billed for the AWS resources used if you create a stack from this template. (qs-1qnnspaap) +Metadata: + QuickStartDocumentation: + EntrypointName: "Launch a New VPC" + OptionalParameters: + - PrivateSubnetATag1 + - PrivateSubnetATag2 + - PrivateSubnetATag3 + - PrivateSubnetBTag1 + - PrivateSubnetBTag2 + - PrivateSubnetBTag3 + - PublicSubnetTag1 + - PublicSubnetTag2 + - PublicSubnetTag3 + AWS::CloudFormation::Interface: + ParameterGroups: + - Label: + default: Availability Zone Configuration + Parameters: + - AvailabilityZones + - NumberOfAZs + - Label: + default: Network Configuration + Parameters: + - VPCCIDR + - CreatePublicSubnets + - PublicSubnet1CIDR + - PublicSubnet2CIDR + - PublicSubnet3CIDR + - PublicSubnet4CIDR + - PublicSubnetTag1 + - PublicSubnetTag2 + - PublicSubnetTag3 + - CreatePrivateSubnets + - CreateNATGateways + - PrivateSubnet1ACIDR + - PrivateSubnet2ACIDR + - PrivateSubnet3ACIDR + - PrivateSubnet4ACIDR + - PrivateSubnetATag1 + - PrivateSubnetATag2 + - PrivateSubnetATag3 + - CreateAdditionalPrivateSubnets + - PrivateSubnet1BCIDR + - PrivateSubnet2BCIDR + - PrivateSubnet3BCIDR + - PrivateSubnet4BCIDR + - PrivateSubnetBTag1 + - PrivateSubnetBTag2 + - PrivateSubnetBTag3 + - VPCTenancy + - Label: + default: 'Deprecated: NAT Instance Configuration' + Parameters: + - KeyPairName + - NATInstanceType + ParameterLabels: + AvailabilityZones: + default: Availability Zones + CreateAdditionalPrivateSubnets: + default: Create additional private subnets with dedicated network ACLs + CreateNATGateways: + default: Create NAT Gateways + CreatePublicSubnets: + default: Create public subnets + CreatePrivateSubnets: + default: Create private subnets + KeyPairName: + default: 'Deprecated: Key pair name' + NATInstanceType: + default: 'Deprecated: NAT instance type' + NumberOfAZs: + default: Number of Availability Zones + PrivateSubnet1ACIDR: + default: Private subnet 1A CIDR + PrivateSubnet1BCIDR: + default: Private subnet 1B with dedicated network ACL CIDR + PrivateSubnet2ACIDR: + default: Private subnet 2A CIDR + PrivateSubnet2BCIDR: + default: Private subnet 2B with dedicated network ACL CIDR + PrivateSubnet3ACIDR: + default: Private subnet 3A CIDR + PrivateSubnet3BCIDR: + default: Private subnet 3B with dedicated network ACL CIDR + PrivateSubnet4ACIDR: + default: Private subnet 4A CIDR + PrivateSubnet4BCIDR: + default: Private subnet 4B with dedicated network ACL CIDR + PrivateSubnetATag1: + default: Tag for Private A Subnets + PrivateSubnetATag2: + default: Tag for Private A Subnets + PrivateSubnetATag3: + default: Tag for Private A Subnets + PrivateSubnetBTag1: + default: Tag for Private B Subnets + PrivateSubnetBTag2: + default: Tag for Private B Subnets + PrivateSubnetBTag3: + default: Tag for Private B Subnets + PublicSubnet1CIDR: + default: Public subnet 1 CIDR + PublicSubnet2CIDR: + default: Public subnet 2 CIDR + PublicSubnet3CIDR: + default: Public subnet 3 CIDR + PublicSubnet4CIDR: + default: Public subnet 4 CIDR + PublicSubnetTag1: + default: Tag for Public Subnets + PublicSubnetTag2: + default: Tag for Public Subnets + PublicSubnetTag3: + default: Tag for Public Subnets + VPCCIDR: + default: VPC CIDR + VPCTenancy: + default: VPC Tenancy +Parameters: + AvailabilityZones: + Description: 'List of Availability Zones to use for the subnets in the VPC. Note: + The logical order is preserved.' + Type: List + CreateAdditionalPrivateSubnets: + AllowedValues: + - 'true' + - 'false' + Default: 'false' + Description: >- + Set to true to create a network ACL protected subnet in each Availability Zone. + If false, the CIDR parameters for those subnets will be ignored. If true, it + also requires that the 'Create private subnets' parameter is also true to have + any effect. + Type: String + CreateNATGateways: + AllowedValues: + - 'true' + - 'false' + Default: 'true' + Description: Set to false when creating only private subnets. If True, both CreatePublicSubnets and CreatePrivateSubnets must also be true. + Type: String + CreatePublicSubnets: + AllowedValues: + - 'true' + - 'false' + Default: 'true' + Description: Set to false to create only private subnets. If false, CreatePrivateSubnets must be True and the CIDR parameters for ALL public subnets will be ignored + Type: String + CreatePrivateSubnets: + AllowedValues: + - 'true' + - 'false' + Default: 'true' + Description: Set to false to create only public subnets. If false, the CIDR parameters + for ALL private subnets will be ignored. + Type: String + KeyPairName: + Description: Deprecated. NAT gateways are now supported in all regions. + Type: String + Default: deprecated + NATInstanceType: + Default: deprecated + Description: Deprecated. NAT gateways are now supported in all regions. + Type: String + NumberOfAZs: + AllowedValues: + - '2' + - '3' + - '4' + Default: '2' + Description: Number of Availability Zones to use in the VPC. This must match your + selections in the list of Availability Zones parameter. + Type: String + PrivateSubnet1ACIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.0.0/19 + Description: CIDR block for private subnet 1A located in Availability Zone 1 + Type: String + PrivateSubnet1BCIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.192.0/21 + Description: CIDR block for private subnet 1B with dedicated network ACL located + in Availability Zone 1 + Type: String + PrivateSubnet2ACIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.32.0/19 + Description: CIDR block for private subnet 2A located in Availability Zone 2 + Type: String + PrivateSubnet2BCIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.200.0/21 + Description: CIDR block for private subnet 2B with dedicated network ACL located + in Availability Zone 2 + Type: String + PrivateSubnet3ACIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.64.0/19 + Description: CIDR block for private subnet 3A located in Availability Zone 3 + Type: String + PrivateSubnet3BCIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.208.0/21 + Description: CIDR block for private subnet 3B with dedicated network ACL located + in Availability Zone 3 + Type: String + PrivateSubnet4ACIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.96.0/19 + Description: CIDR block for private subnet 4A located in Availability Zone 4 + Type: String + PrivateSubnet4BCIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.216.0/21 + Description: CIDR block for private subnet 4B with dedicated network ACL located + in Availability Zone 4 + Type: String + PrivateSubnetATag1: + AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ + ConstraintDescription: tags must be in format "Key=Value" keys can only contain + [a-zA-Z0-9+\-._:/@], values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}] + Default: Network=Private + Description: tag to add to private subnets A, in format Key=Value (Optional) + Type: String + PrivateSubnetATag2: + AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ + ConstraintDescription: tags must be in format "Key=Value" keys can only contain + [a-zA-Z0-9+\-._:/@], values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}] + Default: '' + Description: tag to add to private subnets A, in format Key=Value (Optional) + Type: String + PrivateSubnetATag3: + AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ + ConstraintDescription: tags must be in format "Key=Value" keys can only contain + [a-zA-Z0-9+\-._:/@], values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}] + Default: '' + Description: tag to add to private subnets A, in format Key=Value (Optional) + Type: String + PrivateSubnetBTag1: + AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ + ConstraintDescription: tags must be in format "Key=Value" keys can only contain + [a-zA-Z0-9+\-._:/@], values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}] + Default: Network=Private + Description: tag to add to private subnets B, in format Key=Value (Optional) + Type: String + PrivateSubnetBTag2: + AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ + ConstraintDescription: tags must be in format "Key=Value" keys can only contain + [a-zA-Z0-9+\-._:/@], values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}] + Default: '' + Description: tag to add to private subnets B, in format Key=Value (Optional) + Type: String + PrivateSubnetBTag3: + AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ + ConstraintDescription: tags must be in format "Key=Value" keys can only contain + [a-zA-Z0-9+\-._:/@], values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}] + Default: '' + Description: tag to add to private subnets B, in format Key=Value (Optional) + Type: String + PublicSubnet1CIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.128.0/20 + Description: CIDR block for the public DMZ subnet 1 located in Availability Zone + 1 + Type: String + PublicSubnet2CIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.144.0/20 + Description: CIDR block for the public DMZ subnet 2 located in Availability Zone + 2 + Type: String + PublicSubnet3CIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.160.0/20 + Description: CIDR block for the public DMZ subnet 3 located in Availability Zone + 3 + Type: String + PublicSubnet4CIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.176.0/20 + Description: CIDR block for the public DMZ subnet 4 located in Availability Zone + 4 + Type: String + PublicSubnetTag1: + AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ + ConstraintDescription: tags must be in format "Key=Value" keys can only contain + [a-zA-Z0-9+\-._:/@], values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}] + Default: Network=Public + Description: tag to add to public subnets, in format Key=Value (Optional) + Type: String + PublicSubnetTag2: + AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ + ConstraintDescription: tags must be in format "Key=Value" keys can only contain + [a-zA-Z0-9+\-._:/@], values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}] + Default: '' + Description: tag to add to public subnets, in format Key=Value (Optional) + Type: String + PublicSubnetTag3: + AllowedPattern: ^([a-zA-Z0-9+\-._:/@]+=[a-zA-Z0-9+\-.,_:/@ *\\"'\[\]\{\}]*)?$ + ConstraintDescription: tags must be in format "Key=Value" keys can only contain + [a-zA-Z0-9+\-._:/@], values can contain [a-zA-Z0-9+\-._:/@ *\\"'\[\]\{\}] + Default: '' + Description: tag to add to public subnets, in format Key=Value (Optional) + Type: String + VPCCIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.0.0/16 + Description: CIDR block for the VPC + Type: String + VPCTenancy: + AllowedValues: + - default + - dedicated + Default: default + Description: The allowed tenancy of instances launched into the VPC + Type: String +Rules: + NAT: + RuleCondition: !Equals [!Ref CreateNATGateways, 'true'] + Assertions: + - Assert: !And + - !Equals [!Ref CreatePrivateSubnets, 'true'] + - !Equals [!Ref CreatePublicSubnets, 'true'] + AssertDescription: To enable NAT gateways you must have both CreatePrivateSubnets and CreatePublicSubnets set to 'true' + Subnets: + Assertions: + - Assert: !Or + - !Equals [!Ref CreatePrivateSubnets, 'true'] + - !Equals [!Ref CreatePublicSubnets, 'true'] + AssertDescription: At least one of CreatePublicSubnets or CreatePrivateSubnets must be set to 'true' +Conditions: + 3AZCondition: !Or + - !Equals + - !Ref 'NumberOfAZs' + - '3' + - !Condition '4AZCondition' + 4AZCondition: !Equals + - !Ref 'NumberOfAZs' + - '4' + AdditionalPrivateSubnetsCondition: !And + - !Equals + - !Ref 'CreatePrivateSubnets' + - 'true' + - !Equals + - !Ref 'CreateAdditionalPrivateSubnets' + - 'true' + AdditionalPrivateSubnets&3AZCondition: !And + - !Condition 'AdditionalPrivateSubnetsCondition' + - !Condition '3AZCondition' + AdditionalPrivateSubnets&4AZCondition: !And + - !Condition 'AdditionalPrivateSubnetsCondition' + - !Condition '4AZCondition' + AdditionalPrivateSubnets&PublicSubnets&NatGatewaysCondition: !And + - !Condition 'AdditionalPrivateSubnetsCondition' + - !Condition 'PublicSubnetsCondition' + - !Condition 'NATGatewaysCondition' + AdditionalPrivateSubnets&PublicSubnets&NatGateways&3AZCondition: !And + - !Condition 'AdditionalPrivateSubnets&3AZCondition' + - !Condition 'PublicSubnetsCondition' + - !Condition 'NATGatewaysCondition' + AdditionalPrivateSubnets&PublicSubnets&NatGateways&4AZCondition: !And + - !Condition 'AdditionalPrivateSubnets&4AZCondition' + - !Condition 'PublicSubnetsCondition' + - !Condition 'NATGatewaysCondition' + GovCloudCondition: !Equals + - !Ref 'AWS::Region' + - us-gov-west-1 + NATGatewaysCondition: !Equals + - !Ref 'CreateNATGateways' + - 'true' + NATGateways&3AZCondition: !And + - !Condition 'NATGatewaysCondition' + - !Condition '3AZCondition' + NATGateways&4AZCondition: !And + - !Condition 'NATGatewaysCondition' + - !Condition '4AZCondition' + NVirginiaRegionCondition: !Equals + - !Ref 'AWS::Region' + - us-east-1 + PrivateSubnetsCondition: !Equals + - !Ref 'CreatePrivateSubnets' + - 'true' + PrivateSubnets&3AZCondition: !And + - !Condition 'PrivateSubnetsCondition' + - !Condition '3AZCondition' + PrivateSubnets&4AZCondition: !And + - !Condition 'PrivateSubnetsCondition' + - !Condition '4AZCondition' + PublicSubnetsCondition: !Equals + - !Ref 'CreatePublicSubnets' + - 'true' + PublicSubnets&3AZCondition: !And + - !Condition 'PublicSubnetsCondition' + - !Condition '3AZCondition' + PublicSubnets&4AZCondition: !And + - !Condition 'PublicSubnetsCondition' + - !Condition '4AZCondition' + PrivateSubnetATag1Condition: !Not + - !Equals + - !Ref 'PrivateSubnetATag1' + - '' + PrivateSubnetATag2Condition: !Not + - !Equals + - !Ref 'PrivateSubnetATag2' + - '' + PrivateSubnetATag3Condition: !Not + - !Equals + - !Ref 'PrivateSubnetATag3' + - '' + PrivateSubnetBTag1Condition: !Not + - !Equals + - !Ref 'PrivateSubnetBTag1' + - '' + PrivateSubnetBTag2Condition: !Not + - !Equals + - !Ref 'PrivateSubnetBTag2' + - '' + PrivateSubnetBTag3Condition: !Not + - !Equals + - !Ref 'PrivateSubnetBTag3' + - '' + PublicSubnetTag1Condition: !Not + - !Equals + - !Ref 'PublicSubnetTag1' + - '' + PublicSubnetTag2Condition: !Not + - !Equals + - !Ref 'PublicSubnetTag2' + - '' + PublicSubnetTag3Condition: !Not + - !Equals + - !Ref 'PublicSubnetTag3' + - '' +Resources: + DHCPOptions: + Type: AWS::EC2::DHCPOptions + Properties: + DomainName: !If + - NVirginiaRegionCondition + - ec2.internal + - !Sub '${AWS::Region}.compute.internal' + DomainNameServers: + - AmazonProvidedDNS + VPC: + Type: AWS::EC2::VPC + Properties: + CidrBlock: !Ref 'VPCCIDR' + InstanceTenancy: !Ref 'VPCTenancy' + EnableDnsSupport: true + EnableDnsHostnames: true + Tags: + - Key: Name + Value: !Ref 'AWS::StackName' + VPCDHCPOptionsAssociation: + Type: AWS::EC2::VPCDHCPOptionsAssociation + Properties: + VpcId: !Ref 'VPC' + DhcpOptionsId: !Ref 'DHCPOptions' + InternetGateway: + Condition: PublicSubnetsCondition + Type: AWS::EC2::InternetGateway + Properties: + Tags: + - Key: Name + Value: !Ref 'AWS::StackName' + VPCGatewayAttachment: + Condition: PublicSubnetsCondition + Type: AWS::EC2::VPCGatewayAttachment + Properties: + VpcId: !Ref 'VPC' + InternetGatewayId: !Ref 'InternetGateway' + PrivateSubnet1A: + Condition: PrivateSubnetsCondition + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref 'VPC' + CidrBlock: !Ref 'PrivateSubnet1ACIDR' + AvailabilityZone: !Select + - '0' + - !Ref 'AvailabilityZones' + Tags: + - Key: Name + Value: Private subnet 1A + - !If + - PrivateSubnetATag1Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetATag1' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetATag1' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetATag2Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetATag2' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetATag2' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetATag3Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetATag3' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetATag3' + - !Ref 'AWS::NoValue' + PrivateSubnet1B: + Condition: AdditionalPrivateSubnetsCondition + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref 'VPC' + CidrBlock: !Ref 'PrivateSubnet1BCIDR' + AvailabilityZone: !Select + - '0' + - !Ref 'AvailabilityZones' + Tags: + - Key: Name + Value: Private subnet 1B + - !If + - PrivateSubnetBTag1Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag1' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag1' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetBTag2Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag2' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag2' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetBTag3Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag3' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag3' + - !Ref 'AWS::NoValue' + PrivateSubnet2A: + Condition: PrivateSubnetsCondition + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref 'VPC' + CidrBlock: !Ref 'PrivateSubnet2ACIDR' + AvailabilityZone: !Select + - '1' + - !Ref 'AvailabilityZones' + Tags: + - Key: Name + Value: Private subnet 2A + - !If + - PrivateSubnetATag1Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetATag1' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetATag1' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetATag2Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetATag2' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetATag2' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetATag3Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetATag3' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetATag3' + - !Ref 'AWS::NoValue' + PrivateSubnet2B: + Condition: AdditionalPrivateSubnetsCondition + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref 'VPC' + CidrBlock: !Ref 'PrivateSubnet2BCIDR' + AvailabilityZone: !Select + - '1' + - !Ref 'AvailabilityZones' + Tags: + - Key: Name + Value: Private subnet 2B + - !If + - PrivateSubnetBTag1Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag1' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag1' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetBTag2Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag2' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag2' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetBTag3Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag3' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag3' + - !Ref 'AWS::NoValue' + PrivateSubnet3A: + Condition: PrivateSubnets&3AZCondition + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref 'VPC' + CidrBlock: !Ref 'PrivateSubnet3ACIDR' + AvailabilityZone: !Select + - '2' + - !Ref 'AvailabilityZones' + Tags: + - Key: Name + Value: Private subnet 3A + - !If + - PrivateSubnetATag1Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetATag1' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetATag1' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetATag2Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetATag2' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetATag2' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetATag3Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetATag3' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetATag3' + - !Ref 'AWS::NoValue' + PrivateSubnet3B: + Condition: AdditionalPrivateSubnets&3AZCondition + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref 'VPC' + CidrBlock: !Ref 'PrivateSubnet3BCIDR' + AvailabilityZone: !Select + - '2' + - !Ref 'AvailabilityZones' + Tags: + - Key: Name + Value: Private subnet 3B + - !If + - PrivateSubnetBTag1Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag1' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag1' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetBTag2Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag2' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag2' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetBTag3Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag3' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag3' + - !Ref 'AWS::NoValue' + PrivateSubnet4A: + Condition: PrivateSubnets&4AZCondition + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref 'VPC' + CidrBlock: !Ref 'PrivateSubnet4ACIDR' + AvailabilityZone: !Select + - '3' + - !Ref 'AvailabilityZones' + Tags: + - Key: Name + Value: Private subnet 4A + - !If + - PrivateSubnetATag1Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetATag1' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetATag1' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetATag2Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetATag2' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetATag2' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetATag3Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetATag3' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetATag3' + - !Ref 'AWS::NoValue' + PrivateSubnet4B: + Condition: AdditionalPrivateSubnets&4AZCondition + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref 'VPC' + CidrBlock: !Ref 'PrivateSubnet4BCIDR' + AvailabilityZone: !Select + - '3' + - !Ref 'AvailabilityZones' + Tags: + - Key: Name + Value: Private subnet 4B + - !If + - PrivateSubnetBTag1Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag1' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag1' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetBTag2Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag2' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag2' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnetBTag3Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag3' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PrivateSubnetBTag3' + - !Ref 'AWS::NoValue' + PublicSubnet1: + Condition: PublicSubnetsCondition + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref 'VPC' + CidrBlock: !Ref 'PublicSubnet1CIDR' + AvailabilityZone: !Select + - '0' + - !Ref 'AvailabilityZones' + Tags: + - Key: Name + Value: Public subnet 1 + - !If + - PublicSubnetTag1Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PublicSubnetTag1' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PublicSubnetTag1' + - !Ref 'AWS::NoValue' + - !If + - PublicSubnetTag2Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PublicSubnetTag2' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PublicSubnetTag2' + - !Ref 'AWS::NoValue' + - !If + - PublicSubnetTag3Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PublicSubnetTag3' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PublicSubnetTag3' + - !Ref 'AWS::NoValue' + MapPublicIpOnLaunch: true + PublicSubnet2: + Condition: PublicSubnetsCondition + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref 'VPC' + CidrBlock: !Ref 'PublicSubnet2CIDR' + AvailabilityZone: !Select + - '1' + - !Ref 'AvailabilityZones' + Tags: + - Key: Name + Value: Public subnet 2 + - !If + - PublicSubnetTag1Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PublicSubnetTag1' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PublicSubnetTag1' + - !Ref 'AWS::NoValue' + - !If + - PublicSubnetTag2Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PublicSubnetTag2' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PublicSubnetTag2' + - !Ref 'AWS::NoValue' + - !If + - PublicSubnetTag3Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PublicSubnetTag3' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PublicSubnetTag3' + - !Ref 'AWS::NoValue' + MapPublicIpOnLaunch: true + PublicSubnet3: + Condition: PublicSubnets&3AZCondition + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref 'VPC' + CidrBlock: !Ref 'PublicSubnet3CIDR' + AvailabilityZone: !Select + - '2' + - !Ref 'AvailabilityZones' + Tags: + - Key: Name + Value: Public subnet 3 + - !If + - PublicSubnetTag1Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PublicSubnetTag1' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PublicSubnetTag1' + - !Ref 'AWS::NoValue' + - !If + - PublicSubnetTag2Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PublicSubnetTag2' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PublicSubnetTag2' + - !Ref 'AWS::NoValue' + - !If + - PublicSubnetTag3Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PublicSubnetTag3' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PublicSubnetTag3' + - !Ref 'AWS::NoValue' + MapPublicIpOnLaunch: true + PublicSubnet4: + Condition: PublicSubnets&4AZCondition + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref 'VPC' + CidrBlock: !Ref 'PublicSubnet4CIDR' + AvailabilityZone: !Select + - '3' + - !Ref 'AvailabilityZones' + Tags: + - Key: Name + Value: Public subnet 4 + - !If + - PublicSubnetTag1Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PublicSubnetTag1' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PublicSubnetTag1' + - !Ref 'AWS::NoValue' + - !If + - PublicSubnetTag2Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PublicSubnetTag2' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PublicSubnetTag2' + - !Ref 'AWS::NoValue' + - !If + - PublicSubnetTag3Condition + - Key: !Select + - '0' + - !Split + - '=' + - !Ref 'PublicSubnetTag3' + Value: !Select + - '1' + - !Split + - '=' + - !Ref 'PublicSubnetTag3' + - !Ref 'AWS::NoValue' + MapPublicIpOnLaunch: true + PrivateSubnet1ARouteTable: + Condition: PrivateSubnetsCondition + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref 'VPC' + Tags: + - Key: Name + Value: Private subnet 1A + - Key: Network + Value: Private + PrivateSubnet1ARoute: + Condition: NATGatewaysCondition + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref 'PrivateSubnet1ARouteTable' + DestinationCidrBlock: '0.0.0.0/0' + NatGatewayId: !Ref 'NATGateway1' + PrivateSubnet1ARouteTableAssociation: + Condition: PrivateSubnetsCondition + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref 'PrivateSubnet1A' + RouteTableId: !Ref 'PrivateSubnet1ARouteTable' + PrivateSubnet2ARouteTable: + Condition: PrivateSubnetsCondition + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref 'VPC' + Tags: + - Key: Name + Value: Private subnet 2A + - Key: Network + Value: Private + PrivateSubnet2ARoute: + Condition: NATGatewaysCondition + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref 'PrivateSubnet2ARouteTable' + DestinationCidrBlock: '0.0.0.0/0' + NatGatewayId: !Ref 'NATGateway2' + PrivateSubnet2ARouteTableAssociation: + Condition: PrivateSubnetsCondition + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref 'PrivateSubnet2A' + RouteTableId: !Ref 'PrivateSubnet2ARouteTable' + PrivateSubnet3ARouteTable: + Condition: PrivateSubnets&3AZCondition + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref 'VPC' + Tags: + - Key: Name + Value: Private subnet 3A + - Key: Network + Value: Private + PrivateSubnet3ARoute: + Condition: NATGateways&3AZCondition + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref 'PrivateSubnet3ARouteTable' + DestinationCidrBlock: '0.0.0.0/0' + NatGatewayId: !Ref 'NATGateway3' + PrivateSubnet3ARouteTableAssociation: + Condition: PrivateSubnets&3AZCondition + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref 'PrivateSubnet3A' + RouteTableId: !Ref 'PrivateSubnet3ARouteTable' + PrivateSubnet4ARouteTable: + Condition: PrivateSubnets&4AZCondition + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref 'VPC' + Tags: + - Key: Name + Value: Private subnet 4A + - Key: Network + Value: Private + PrivateSubnet4ARoute: + Condition: NATGateways&4AZCondition + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref 'PrivateSubnet4ARouteTable' + DestinationCidrBlock: '0.0.0.0/0' + NatGatewayId: !Ref 'NATGateway4' + PrivateSubnet4ARouteTableAssociation: + Condition: PrivateSubnets&4AZCondition + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref 'PrivateSubnet4A' + RouteTableId: !Ref 'PrivateSubnet4ARouteTable' + PrivateSubnet1BRouteTable: + Condition: AdditionalPrivateSubnetsCondition + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref 'VPC' + Tags: + - Key: Name + Value: Private subnet 1B + - Key: Network + Value: Private + PrivateSubnet1BRoute: + Condition: AdditionalPrivateSubnets&PublicSubnets&NatGatewaysCondition + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref 'PrivateSubnet1BRouteTable' + DestinationCidrBlock: '0.0.0.0/0' + NatGatewayId: !Ref 'NATGateway1' + PrivateSubnet1BRouteTableAssociation: + Condition: AdditionalPrivateSubnetsCondition + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref 'PrivateSubnet1B' + RouteTableId: !Ref 'PrivateSubnet1BRouteTable' + PrivateSubnet1BNetworkAcl: + Condition: AdditionalPrivateSubnetsCondition + Type: AWS::EC2::NetworkAcl + Properties: + VpcId: !Ref 'VPC' + Tags: + - Key: Name + Value: NACL Protected subnet 1 + - Key: Network + Value: NACL Protected + PrivateSubnet1BNetworkAclEntryInbound: + Condition: AdditionalPrivateSubnetsCondition + Type: AWS::EC2::NetworkAclEntry + Properties: + CidrBlock: '0.0.0.0/0' + Egress: false + NetworkAclId: !Ref 'PrivateSubnet1BNetworkAcl' + Protocol: -1 + RuleAction: allow + RuleNumber: 100 + PrivateSubnet1BNetworkAclEntryOutbound: + Condition: AdditionalPrivateSubnetsCondition + Type: AWS::EC2::NetworkAclEntry + Properties: + CidrBlock: '0.0.0.0/0' + Egress: true + NetworkAclId: !Ref 'PrivateSubnet1BNetworkAcl' + Protocol: -1 + RuleAction: allow + RuleNumber: 100 + PrivateSubnet1BNetworkAclAssociation: + Condition: AdditionalPrivateSubnetsCondition + Type: AWS::EC2::SubnetNetworkAclAssociation + Properties: + SubnetId: !Ref 'PrivateSubnet1B' + NetworkAclId: !Ref 'PrivateSubnet1BNetworkAcl' + PrivateSubnet2BRouteTable: + Condition: AdditionalPrivateSubnetsCondition + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref 'VPC' + Tags: + - Key: Name + Value: Private subnet 2B + - Key: Network + Value: Private + PrivateSubnet2BRoute: + Condition: AdditionalPrivateSubnets&PublicSubnets&NatGatewaysCondition + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref 'PrivateSubnet2BRouteTable' + DestinationCidrBlock: '0.0.0.0/0' + NatGatewayId: !Ref 'NATGateway2' + PrivateSubnet2BRouteTableAssociation: + Condition: AdditionalPrivateSubnetsCondition + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref 'PrivateSubnet2B' + RouteTableId: !Ref 'PrivateSubnet2BRouteTable' + PrivateSubnet2BNetworkAcl: + Condition: AdditionalPrivateSubnetsCondition + Type: AWS::EC2::NetworkAcl + Properties: + VpcId: !Ref 'VPC' + Tags: + - Key: Name + Value: NACL Protected subnet 2 + - Key: Network + Value: NACL Protected + PrivateSubnet2BNetworkAclEntryInbound: + Condition: AdditionalPrivateSubnetsCondition + Type: AWS::EC2::NetworkAclEntry + Properties: + CidrBlock: '0.0.0.0/0' + Egress: false + NetworkAclId: !Ref 'PrivateSubnet2BNetworkAcl' + Protocol: -1 + RuleAction: allow + RuleNumber: 100 + PrivateSubnet2BNetworkAclEntryOutbound: + Condition: AdditionalPrivateSubnetsCondition + Type: AWS::EC2::NetworkAclEntry + Properties: + CidrBlock: '0.0.0.0/0' + Egress: true + NetworkAclId: !Ref 'PrivateSubnet2BNetworkAcl' + Protocol: -1 + RuleAction: allow + RuleNumber: 100 + PrivateSubnet2BNetworkAclAssociation: + Condition: AdditionalPrivateSubnetsCondition + Type: AWS::EC2::SubnetNetworkAclAssociation + Properties: + SubnetId: !Ref 'PrivateSubnet2B' + NetworkAclId: !Ref 'PrivateSubnet2BNetworkAcl' + PrivateSubnet3BRouteTable: + Condition: AdditionalPrivateSubnets&3AZCondition + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref 'VPC' + Tags: + - Key: Name + Value: Private subnet 3B + - Key: Network + Value: Private + PrivateSubnet3BRoute: + Condition: AdditionalPrivateSubnets&PublicSubnets&NatGateways&3AZCondition + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref 'PrivateSubnet3BRouteTable' + DestinationCidrBlock: '0.0.0.0/0' + NatGatewayId: !Ref 'NATGateway3' + PrivateSubnet3BRouteTableAssociation: + Condition: AdditionalPrivateSubnets&3AZCondition + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref 'PrivateSubnet3B' + RouteTableId: !Ref 'PrivateSubnet3BRouteTable' + PrivateSubnet3BNetworkAcl: + Condition: AdditionalPrivateSubnets&3AZCondition + Type: AWS::EC2::NetworkAcl + Properties: + VpcId: !Ref 'VPC' + Tags: + - Key: Name + Value: NACL Protected subnet 3 + - Key: Network + Value: NACL Protected + PrivateSubnet3BNetworkAclEntryInbound: + Condition: AdditionalPrivateSubnets&3AZCondition + Type: AWS::EC2::NetworkAclEntry + Properties: + CidrBlock: '0.0.0.0/0' + Egress: false + NetworkAclId: !Ref 'PrivateSubnet3BNetworkAcl' + Protocol: -1 + RuleAction: allow + RuleNumber: 100 + PrivateSubnet3BNetworkAclEntryOutbound: + Condition: AdditionalPrivateSubnets&3AZCondition + Type: AWS::EC2::NetworkAclEntry + Properties: + CidrBlock: '0.0.0.0/0' + Egress: true + NetworkAclId: !Ref 'PrivateSubnet3BNetworkAcl' + Protocol: -1 + RuleAction: allow + RuleNumber: 100 + PrivateSubnet3BNetworkAclAssociation: + Condition: AdditionalPrivateSubnets&3AZCondition + Type: AWS::EC2::SubnetNetworkAclAssociation + Properties: + SubnetId: !Ref 'PrivateSubnet3B' + NetworkAclId: !Ref 'PrivateSubnet3BNetworkAcl' + PrivateSubnet4BRouteTable: + Condition: AdditionalPrivateSubnets&4AZCondition + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref 'VPC' + Tags: + - Key: Name + Value: Private subnet 4B + - Key: Network + Value: Private + PrivateSubnet4BRoute: + Condition: AdditionalPrivateSubnets&PublicSubnets&NatGateways&4AZCondition + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref 'PrivateSubnet4BRouteTable' + DestinationCidrBlock: '0.0.0.0/0' + NatGatewayId: !Ref 'NATGateway4' + PrivateSubnet4BRouteTableAssociation: + Condition: AdditionalPrivateSubnets&4AZCondition + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref 'PrivateSubnet4B' + RouteTableId: !Ref 'PrivateSubnet4BRouteTable' + PrivateSubnet4BNetworkAcl: + Condition: AdditionalPrivateSubnets&4AZCondition + Type: AWS::EC2::NetworkAcl + Properties: + VpcId: !Ref 'VPC' + Tags: + - Key: Name + Value: NACL Protected subnet 4 + - Key: Network + Value: NACL Protected + PrivateSubnet4BNetworkAclEntryInbound: + Condition: AdditionalPrivateSubnets&4AZCondition + Type: AWS::EC2::NetworkAclEntry + Properties: + CidrBlock: '0.0.0.0/0' + Egress: false + NetworkAclId: !Ref 'PrivateSubnet4BNetworkAcl' + Protocol: -1 + RuleAction: allow + RuleNumber: 100 + PrivateSubnet4BNetworkAclEntryOutbound: + Condition: AdditionalPrivateSubnets&4AZCondition + Type: AWS::EC2::NetworkAclEntry + Properties: + CidrBlock: '0.0.0.0/0' + Egress: true + NetworkAclId: !Ref 'PrivateSubnet4BNetworkAcl' + Protocol: -1 + RuleAction: allow + RuleNumber: 100 + PrivateSubnet4BNetworkAclAssociation: + Condition: AdditionalPrivateSubnets&4AZCondition + Type: AWS::EC2::SubnetNetworkAclAssociation + Properties: + SubnetId: !Ref 'PrivateSubnet4B' + NetworkAclId: !Ref 'PrivateSubnet4BNetworkAcl' + PublicSubnetRouteTable: + Condition: PublicSubnetsCondition + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref 'VPC' + Tags: + - Key: Name + Value: Public Subnets + - Key: Network + Value: Public + PublicSubnetRoute: + Condition: PublicSubnetsCondition + DependsOn: VPCGatewayAttachment + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref 'PublicSubnetRouteTable' + DestinationCidrBlock: '0.0.0.0/0' + GatewayId: !Ref 'InternetGateway' + PublicSubnet1RouteTableAssociation: + Condition: PublicSubnetsCondition + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref 'PublicSubnet1' + RouteTableId: !Ref 'PublicSubnetRouteTable' + PublicSubnet2RouteTableAssociation: + Condition: PublicSubnetsCondition + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref 'PublicSubnet2' + RouteTableId: !Ref 'PublicSubnetRouteTable' + PublicSubnet3RouteTableAssociation: + Condition: PublicSubnets&3AZCondition + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref 'PublicSubnet3' + RouteTableId: !Ref 'PublicSubnetRouteTable' + PublicSubnet4RouteTableAssociation: + Condition: PublicSubnets&4AZCondition + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref 'PublicSubnet4' + RouteTableId: !Ref 'PublicSubnetRouteTable' + NAT1EIP: + Condition: NATGatewaysCondition + DependsOn: VPCGatewayAttachment + Type: AWS::EC2::EIP + Properties: + Domain: vpc + NAT2EIP: + Condition: NATGatewaysCondition + DependsOn: VPCGatewayAttachment + Type: AWS::EC2::EIP + Properties: + Domain: vpc + NAT3EIP: + Condition: NATGateways&3AZCondition + DependsOn: VPCGatewayAttachment + Type: AWS::EC2::EIP + Properties: + Domain: vpc + NAT4EIP: + Condition: NATGateways&4AZCondition + DependsOn: VPCGatewayAttachment + Type: AWS::EC2::EIP + Properties: + Domain: vpc + NATGateway1: + Condition: NATGatewaysCondition + DependsOn: VPCGatewayAttachment + Type: AWS::EC2::NatGateway + Properties: + AllocationId: !GetAtt 'NAT1EIP.AllocationId' + SubnetId: !Ref 'PublicSubnet1' + NATGateway2: + Condition: NATGatewaysCondition + DependsOn: VPCGatewayAttachment + Type: AWS::EC2::NatGateway + Properties: + AllocationId: !GetAtt 'NAT2EIP.AllocationId' + SubnetId: !Ref 'PublicSubnet2' + NATGateway3: + Condition: NATGateways&3AZCondition + DependsOn: VPCGatewayAttachment + Type: AWS::EC2::NatGateway + Properties: + AllocationId: !GetAtt 'NAT3EIP.AllocationId' + SubnetId: !Ref 'PublicSubnet3' + NATGateway4: + Condition: NATGateways&4AZCondition + DependsOn: VPCGatewayAttachment + Type: AWS::EC2::NatGateway + Properties: + AllocationId: !GetAtt 'NAT4EIP.AllocationId' + SubnetId: !Ref 'PublicSubnet4' + S3VPCEndpoint: + Condition: PrivateSubnetsCondition + Type: AWS::EC2::VPCEndpoint + Properties: + PolicyDocument: + Version: '2012-10-17' + Statement: + - Action: '*' + Effect: Allow + Resource: '*' + Principal: '*' + RouteTableIds: + - !Ref 'PrivateSubnet1ARouteTable' + - !Ref 'PrivateSubnet2ARouteTable' + - !If + - PrivateSubnets&3AZCondition + - !Ref 'PrivateSubnet3ARouteTable' + - !Ref 'AWS::NoValue' + - !If + - PrivateSubnets&4AZCondition + - !Ref 'PrivateSubnet4ARouteTable' + - !Ref 'AWS::NoValue' + - !If + - AdditionalPrivateSubnetsCondition + - !Ref 'PrivateSubnet1BRouteTable' + - !Ref 'AWS::NoValue' + - !If + - AdditionalPrivateSubnetsCondition + - !Ref 'PrivateSubnet2BRouteTable' + - !Ref 'AWS::NoValue' + - !If + - AdditionalPrivateSubnets&3AZCondition + - !Ref 'PrivateSubnet3BRouteTable' + - !Ref 'AWS::NoValue' + - !If + - AdditionalPrivateSubnets&4AZCondition + - !Ref 'PrivateSubnet4BRouteTable' + - !Ref 'AWS::NoValue' + ServiceName: !Sub 'com.amazonaws.${AWS::Region}.s3' + VpcId: !Ref 'VPC' +Outputs: + NAT1EIP: + Condition: NATGatewaysCondition + Description: NAT 1 IP address + Value: !Ref 'NAT1EIP' + Export: + Name: !Sub '${AWS::StackName}-NAT1EIP' + NAT2EIP: + Condition: NATGatewaysCondition + Description: NAT 2 IP address + Value: !Ref 'NAT2EIP' + Export: + Name: !Sub '${AWS::StackName}-NAT2EIP' + NAT3EIP: + Condition: NATGateways&3AZCondition + Description: NAT 3 IP address + Value: !Ref 'NAT3EIP' + Export: + Name: !Sub '${AWS::StackName}-NAT3EIP' + NAT4EIP: + Condition: NATGateways&4AZCondition + Description: NAT 4 IP address + Value: !Ref 'NAT4EIP' + Export: + Name: !Sub '${AWS::StackName}-NAT4EIP' + PrivateSubnet1ACIDR: + Condition: PrivateSubnetsCondition + Description: Private subnet 1A CIDR in Availability Zone 1 + Value: !Ref 'PrivateSubnet1ACIDR' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet1ACIDR' + PrivateSubnet1AID: + Condition: PrivateSubnetsCondition + Description: Private subnet 1A ID in Availability Zone 1 + Value: !Ref 'PrivateSubnet1A' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet1AID' + PrivateSubnet1BCIDR: + Condition: AdditionalPrivateSubnetsCondition + Description: Private subnet 1B CIDR in Availability Zone 1 + Value: !Ref 'PrivateSubnet1BCIDR' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet1BCIDR' + PrivateSubnet1BID: + Condition: AdditionalPrivateSubnetsCondition + Description: Private subnet 1B ID in Availability Zone 1 + Value: !Ref 'PrivateSubnet1B' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet1BID' + PrivateSubnet2ACIDR: + Condition: PrivateSubnetsCondition + Description: Private subnet 2A CIDR in Availability Zone 2 + Value: !Ref 'PrivateSubnet2ACIDR' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet2ACIDR' + PrivateSubnet2AID: + Condition: PrivateSubnetsCondition + Description: Private subnet 2A ID in Availability Zone 2 + Value: !Ref 'PrivateSubnet2A' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet2AID' + PrivateSubnet2BCIDR: + Condition: AdditionalPrivateSubnetsCondition + Description: Private subnet 2B CIDR in Availability Zone 2 + Value: !Ref 'PrivateSubnet2BCIDR' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet2BCIDR' + PrivateSubnet2BID: + Condition: AdditionalPrivateSubnetsCondition + Description: Private subnet 2B ID in Availability Zone 2 + Value: !Ref 'PrivateSubnet2B' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet2BID' + PrivateSubnet3ACIDR: + Condition: PrivateSubnets&3AZCondition + Description: Private subnet 3A CIDR in Availability Zone 3 + Value: !Ref 'PrivateSubnet3ACIDR' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet3ACIDR' + PrivateSubnet3AID: + Condition: PrivateSubnets&3AZCondition + Description: Private subnet 3A ID in Availability Zone 3 + Value: !Ref 'PrivateSubnet3A' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet3AID' + PrivateSubnet3BCIDR: + Condition: AdditionalPrivateSubnets&3AZCondition + Description: Private subnet 3B CIDR in Availability Zone 3 + Value: !Ref 'PrivateSubnet3BCIDR' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet3BCIDR' + PrivateSubnet3BID: + Condition: AdditionalPrivateSubnets&3AZCondition + Description: Private subnet 3B ID in Availability Zone 3 + Value: !Ref 'PrivateSubnet3B' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet3BID' + PrivateSubnet4ACIDR: + Condition: PrivateSubnets&4AZCondition + Description: Private subnet 4A CIDR in Availability Zone 4 + Value: !Ref 'PrivateSubnet4ACIDR' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet4ACIDR' + PrivateSubnet4AID: + Condition: PrivateSubnets&4AZCondition + Description: Private subnet 4A ID in Availability Zone 4 + Value: !Ref 'PrivateSubnet4A' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet4AID' + PrivateSubnet4BCIDR: + Condition: AdditionalPrivateSubnets&4AZCondition + Description: Private subnet 4B CIDR in Availability Zone 4 + Value: !Ref 'PrivateSubnet4BCIDR' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet4BCIDR' + PrivateSubnet4BID: + Condition: AdditionalPrivateSubnets&4AZCondition + Description: Private subnet 4B ID in Availability Zone 4 + Value: !Ref 'PrivateSubnet4B' + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet4BID' + PublicSubnet1CIDR: + Condition: PublicSubnetsCondition + Description: Public subnet 1 CIDR in Availability Zone 1 + Value: !Ref 'PublicSubnet1CIDR' + Export: + Name: !Sub '${AWS::StackName}-PublicSubnet1CIDR' + PublicSubnet1ID: + Condition: PublicSubnetsCondition + Description: Public subnet 1 ID in Availability Zone 1 + Value: !Ref 'PublicSubnet1' + Export: + Name: !Sub '${AWS::StackName}-PublicSubnet1ID' + PublicSubnet2CIDR: + Condition: PublicSubnetsCondition + Description: Public subnet 2 CIDR in Availability Zone 2 + Value: !Ref 'PublicSubnet2CIDR' + Export: + Name: !Sub '${AWS::StackName}-PublicSubnet2CIDR' + PublicSubnet2ID: + Condition: PublicSubnetsCondition + Description: Public subnet 2 ID in Availability Zone 2 + Value: !Ref 'PublicSubnet2' + Export: + Name: !Sub '${AWS::StackName}-PublicSubnet2ID' + PublicSubnet3CIDR: + Condition: PublicSubnets&3AZCondition + Description: Public subnet 3 CIDR in Availability Zone 3 + Value: !Ref 'PublicSubnet3CIDR' + Export: + Name: !Sub '${AWS::StackName}-PublicSubnet3CIDR' + PublicSubnet3ID: + Condition: PublicSubnets&3AZCondition + Description: Public subnet 3 ID in Availability Zone 3 + Value: !Ref 'PublicSubnet3' + Export: + Name: !Sub '${AWS::StackName}-PublicSubnet3ID' + PublicSubnet4CIDR: + Condition: PublicSubnets&4AZCondition + Description: Public subnet 4 CIDR in Availability Zone 4 + Value: !Ref 'PublicSubnet4CIDR' + Export: + Name: !Sub '${AWS::StackName}-PublicSubnet4CIDR' + PublicSubnet4ID: + Condition: PublicSubnets&4AZCondition + Description: Public subnet 4 ID in Availability Zone 4 + Value: !Ref 'PublicSubnet4' + Export: + Name: !Sub '${AWS::StackName}-PublicSubnet4ID' + S3VPCEndpoint: + Condition: PrivateSubnetsCondition + Description: S3 VPC Endpoint + Value: !Ref 'S3VPCEndpoint' + Export: + Name: !Sub '${AWS::StackName}-S3VPCEndpoint' + PrivateSubnet1ARouteTable: + Condition: PrivateSubnetsCondition + Value: !Ref 'PrivateSubnet1ARouteTable' + Description: Private subnet 1A route table + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet1ARouteTable' + PrivateSubnet1BRouteTable: + Condition: AdditionalPrivateSubnetsCondition + Value: !Ref 'PrivateSubnet1BRouteTable' + Description: Private subnet 1B route table + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet1BRouteTable' + PrivateSubnet2ARouteTable: + Condition: PrivateSubnetsCondition + Value: !Ref 'PrivateSubnet2ARouteTable' + Description: Private subnet 2A route table + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet2ARouteTable' + PrivateSubnet2BRouteTable: + Condition: AdditionalPrivateSubnetsCondition + Value: !Ref 'PrivateSubnet2BRouteTable' + Description: Private subnet 2B route table + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet2BRouteTable' + PrivateSubnet3ARouteTable: + Condition: PrivateSubnets&3AZCondition + Value: !Ref 'PrivateSubnet3ARouteTable' + Description: Private subnet 3A route table + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet3ARouteTable' + PrivateSubnet3BRouteTable: + Condition: AdditionalPrivateSubnets&3AZCondition + Value: !Ref 'PrivateSubnet3BRouteTable' + Description: Private subnet 3B route table + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet3BRouteTable' + PrivateSubnet4ARouteTable: + Condition: PrivateSubnets&4AZCondition + Value: !Ref 'PrivateSubnet4ARouteTable' + Description: Private subnet 4A route table + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet4ARouteTable' + PrivateSubnet4BRouteTable: + Condition: AdditionalPrivateSubnets&4AZCondition + Value: !Ref 'PrivateSubnet4BRouteTable' + Description: Private subnet 4B route table + Export: + Name: !Sub '${AWS::StackName}-PrivateSubnet4BRouteTable' + PublicSubnetRouteTable: + Condition: PublicSubnetsCondition + Value: !Ref 'PublicSubnetRouteTable' + Description: Public subnet route table + Export: + Name: !Sub '${AWS::StackName}-PublicSubnetRouteTable' + VPCCIDR: + Value: !Ref 'VPCCIDR' + Description: VPC CIDR + Export: + Name: !Sub '${AWS::StackName}-VPCCIDR' + VPCID: + Value: !Ref 'VPC' + Description: VPC ID + Export: + Name: !Sub '${AWS::StackName}-VPCID' diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/.gitignore b/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/.gitignore new file mode 100644 index 0000000..42e7431 --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +taskcat_outputs/* +packages/ \ No newline at end of file diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/.gitmodules b/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/.gitmodules new file mode 100644 index 0000000..2bacf10 --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/.gitmodules @@ -0,0 +1,4 @@ +[submodule "submodules/quickstart-aws-vpc"] + path = submodules/quickstart-aws-vpc + url = https://github.com/aws-quickstart/quickstart-aws-vpc.git + branch = main diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/.taskcat.yml b/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/.taskcat.yml new file mode 100644 index 0000000..d9a6c23 --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/.taskcat.yml @@ -0,0 +1,94 @@ +project: + name: quickstart-linux-bastion + owner: quickstart-eng@amazon.com + lambda_source_path: functions/source + lambda_zip_path: packages + s3_regional_buckets: true + regions: + - ap-northeast-1 + - ap-northeast-2 + - ap-south-1 + - ap-southeast-1 + - ap-southeast-2 + - ap-east-1 + - ca-central-1 + - eu-central-1 + - eu-west-1 + - eu-west-2 + - eu-west-3 + - me-south-1 + - sa-east-1 + - us-east-1 + - us-east-2 + - us-west-1 + - us-west-2 + - us-gov-east-1 + - us-gov-west-1 + template: templates/linux-bastion-master.template + parameters: + AvailabilityZones: $[taskcat_getaz_2] + BastionInstanceType: t3.medium + KeyPairName: $[taskcat_getkeypair] + PrivateSubnet1CIDR: 10.0.0.0/19 + PrivateSubnet2CIDR: 10.0.32.0/19 + PublicSubnet1CIDR: 10.0.128.0/20 + PublicSubnet2CIDR: 10.0.144.0/20 + QSS3BucketName: $[taskcat_autobucket] + RemoteAccessCIDR: 10.0.0.0/16 + VPCCIDR: 10.0.0.0/16 + QSS3BucketRegion: $[taskcat_current_region] +tests: + amznlinux2hvm: + parameters: + BastionAMIOS: Amazon-Linux2-HVM + regions: + - ap-northeast-1 + - ap-northeast-2 + - ap-south-1 + - ap-southeast-1 + - ap-southeast-2 + - ca-central-1 + - eu-central-1 + - eu-north-1 + - eu-west-1 + - eu-west-2 + - eu-west-3 + - sa-east-1 + - us-east-1 + - us-east-2 + - us-west-1 + - us-west-2 + - cn-north-1 + - cn-northwest-1 + - us-gov-east-1 + - us-gov-west-1 + centos7hvm: + parameters: + BastionAMIOS: CentOS-7-HVM + regions: + - ap-south-1 + - ca-central-1 + - eu-central-1 + - eu-north-1 + - eu-west-1 + - us-east-1 + sles15hvm: + parameters: + BastionAMIOS: SUSE-SLES-15-HVM + regions: + - ap-south-1 + - ca-central-1 + - eu-central-1 + - eu-north-1 + - eu-west-1 + - us-east-1 + us2004hvm: + parameters: + BastionAMIOS: Ubuntu-Server-20.04-LTS-HVM + regions: + - ap-south-1 + - ca-central-1 + - eu-central-1 + - eu-north-1 + - eu-west-1 + - us-east-1 diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/LICENSE.txt b/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/LICENSE.txt new file mode 100644 index 0000000..8f71f43 --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/LICENSE.txt @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/NOTICE.txt b/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/NOTICE.txt new file mode 100644 index 0000000..9be841c --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/NOTICE.txt @@ -0,0 +1,7 @@ +Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with the License. A copy of the License is located at + + http://aws.amazon.com/apache2.0/ + +or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/README.md b/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/README.md new file mode 100644 index 0000000..a36ee37 --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/README.md @@ -0,0 +1,16 @@ +# quickstart-linux-bastion + +This Quick Start adds Linux bastion functionality to your AWS Cloud environment. It deploys Linux bastion hosts that provide secure access to your Linux instances in public or private subnets. Use this Quick Start as a building block for your Linux-based deployments on AWS. You can choose to create a new VPC environment for your Linux bastion hosts or deploy them into your existing VPC environment. After you deploy the Quick Start, you can add other AWS services, infrastructure components, and software layers to complete your test or production Linux environment on the AWS Cloud. + +![Quick Start Linux Bastion Design Architecture](https://docs.aws.amazon.com/quickstart/latest/linux-bastion/images/linux-bastion-hosts-on-aws-architecture.png ) + +Deployment steps: + +1. Sign up for an AWS account at https://aws.amazon.com, select a region, and create a key pair. +2. In the AWS CloudFormation console, launch one of the following templates to build a new stack: + * /templates/linux-bastion-master.template (to deploy bastion hosts into a new VPC) + * /templates/linux-bastion.template (to deploy bastion hosts into your existing VPC) +3. Add AWS services and other applications. + +The Quick Start provides parameters that you can set to customize your deployment. For architectural details, best practices, step-by-step instructions, and customization options, see the [deployment guide](https://fwd.aws/R9NRw). + diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/scripts/auditing_configure.sh b/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/scripts/auditing_configure.sh new file mode 100644 index 0000000..2a25924 --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/scripts/auditing_configure.sh @@ -0,0 +1,32 @@ +#!/bin/bash +function install_stuff_ubuntu(){ + apt-get -y install auditd +} + +function add_the_rules(){ + cat /tmp/auditd.rules >> /etc/audit/rules.d/audit.rules + rm /tmp/auditd.rules +} + +function restart_services(){ + case "${BASTION_OS}" in + Amazon) + /usr/sbin/service auditd restart + ;; + CentOS|SUSE) + /sbin/service auditd restart + ;; + Ubuntu) + service auditd restart + ;; + esac +} + +case "${BASTION_OS}" in + Ubuntu) + install_stuff_ubuntu + ;; +esac + +add_the_rules +restart_services diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/scripts/banner_message.txt b/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/scripts/banner_message.txt new file mode 100644 index 0000000..ad35b1b --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/scripts/banner_message.txt @@ -0,0 +1,12 @@ + +############################################################################### +# ___ ______ ___ _ _ ____ _ _ # +# / \ \ / / ___| / _ \ _ _(_) ___| | __ / ___|| |_ __ _ _ __| |_ # +# / _ \ \ /\ / /\___ \ | | | | | | | |/ __| |/ / \___ \| __/ _` | '__| __| # +# / ___ \ V V / ___) | | |_| | |_| | | (__| < ___) | || (_| | | | |_ # +# /_/ \_\_/\_/ |____/ \__\_\\__,_|_|\___|_|\_\ |____/ \__\__,_|_| \__| # +#-----------------------------------------------------------------------------# +# Authorized access only! # +# Disconnect IMMEDIATELY if you are not an authorized user!!! # +# All actions will be monitored and recorded. # +############################################################################### diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/scripts/bastion_bootstrap.sh b/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/scripts/bastion_bootstrap.sh new file mode 100644 index 0000000..a79667d --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/scripts/bastion_bootstrap.sh @@ -0,0 +1,380 @@ +#!/bin/bash -e +# Bastion Bootstrapping +# authors: tonynv@amazon.com, sancard@amazon.com, ianhill@amazon.com +# NOTE: This requires GNU getopt. On Mac OS X and FreeBSD you must install GNU getopt and mod the checkos function so that it's supported + + +# Configuration +PROGRAM='Linux Bastion' + +##################################### Functions Definitions +function checkos () { + platform='unknown' + unamestr=`uname` + if [[ "${unamestr}" == 'Linux' ]]; then + platform='linux' + else + echo "[WARNING] This script is not supported on MacOS or FreeBSD" + exit 1 + fi + echo "${FUNCNAME[0]} Ended" +} + +function setup_environment_variables() { + REGION=$(curl -sq http://169.254.169.254/latest/meta-data/placement/availability-zone/) + #ex: us-east-1a => us-east-1 + REGION=${REGION: :-1} + + ETH0_MAC=$(/sbin/ip link show dev eth0 | /bin/egrep -o -i 'link/ether\ ([0-9a-z]{2}:){5}[0-9a-z]{2}' | /bin/sed -e 's,link/ether\ ,,g') + + _userdata_file="/var/lib/cloud/instance/user-data.txt" + + INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id) + EIP_LIST=$(grep EIP_LIST ${_userdata_file} | sed -e 's/EIP_LIST=//g' -e 's/\"//g') + + LOCAL_IP_ADDRESS=$(curl -sq 169.254.169.254/latest/meta-data/network/interfaces/macs/${ETH0_MAC}/local-ipv4s/) + + CWG=$(grep CLOUDWATCHGROUP ${_userdata_file} | sed 's/CLOUDWATCHGROUP=//g') + + + export REGION ETH0_MAC EIP_LIST CWG LOCAL_IP_ADDRESS INSTANCE_ID +} + +function verify_dependencies(){ + if [[ "a$(which aws)" == "a" ]]; then + pip install awscli + fi + echo "${FUNCNAME[0]} Ended" +} + +function usage() { + echo "$0 " + echo " " + echo "options:" + echo -e "--help \t Show options for this script" + echo -e "--banner \t Enable or Disable Bastion Message" + echo -e "--enable \t SSH Banner" + echo -e "--tcp-forwarding \t Enable or Disable TCP Forwarding" + echo -e "--x11-forwarding \t Enable or Disable X11 Forwarding" +} + +function chkstatus () { + if [[ $? -eq 0 ]] + then + echo "Script [PASS]" + else + echo "Script [FAILED]" >&2 + exit 1 + fi +} + +function osrelease () { + OS=`cat /etc/os-release | grep '^NAME=' | tr -d \" | sed 's/\n//g' | sed 's/NAME=//g'` + if [[ "${OS}" == "Ubuntu" ]]; then + echo "Ubuntu" + elif [[ "${OS}" == "Amazon Linux AMI" ]] || [[ "${OS}" == "Amazon Linux" ]]; then + echo "AMZN" + elif [[ "${OS}" == "CentOS Linux" ]]; then + echo "CentOS" + elif [[ "${OS}" == "SLES" ]]; then + echo "SLES" + else + echo "Operating System Not Found" + fi + echo "${FUNCNAME[0]} Ended" >> /var/log/cfn-init.log +} + +function setup_logs () { + + echo "${FUNCNAME[0]} Started" + URL_SUFFIX="${URL_SUFFIX:-amazonaws.com}" + + if [[ "${release}" == "SLES" ]]; then + curl "https://amazoncloudwatch-agent-${REGION}.s3.${REGION}.${URL_SUFFIX}/suse/amd64/latest/amazon-cloudwatch-agent.rpm" -O + zypper install --allow-unsigned-rpm -y ./amazon-cloudwatch-agent.rpm + rm ./amazon-cloudwatch-agent.rpm + elif [[ "${release}" == "CentOS" ]]; then + curl "https://amazoncloudwatch-agent-${REGION}.s3.${REGION}.${URL_SUFFIX}/centos/amd64/latest/amazon-cloudwatch-agent.rpm" -O + rpm -U ./amazon-cloudwatch-agent.rpm + rm ./amazon-cloudwatch-agent.rpm + elif [[ "${release}" == "Ubuntu" ]]; then + export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin + curl "https://amazoncloudwatch-agent-${REGION}.s3.${REGION}.${URL_SUFFIX}/ubuntu/amd64/latest/amazon-cloudwatch-agent.deb" -O + dpkg -i -E ./amazon-cloudwatch-agent.deb + rm ./amazon-cloudwatch-agent.deb + elif [[ "${release}" == "AMZN" ]]; then + curl "https://amazoncloudwatch-agent-${REGION}.s3.${REGION}.${URL_SUFFIX}/amazon_linux/amd64/latest/amazon-cloudwatch-agent.rpm" -O + rpm -U ./amazon-cloudwatch-agent.rpm + rm ./amazon-cloudwatch-agent.rpm + fi + + cat <> /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json +{ + "logs": { + "force_flush_interval": 5, + "logs_collected": { + "files": { + "collect_list": [ + { + "file_path": "/var/log/auditd/auditd.log", + "log_group_name": "${CWG}", + "log_stream_name": "{instance_id}", + "timestamp_format": "%Y-%m-%d %H:%M:%S", + "timezone": "UTC" + } + ] + } + } + } +} +EOF + + if [ -x /bin/systemctl ] || [ -x /usr/bin/systemctl ]; then + systemctl enable amazon-cloudwatch-agent.service + systemctl restart amazon-cloudwatch-agent.service + else + start amazon-cloudwatch-agent + fi +} + +function setup_os () { + + echo "${FUNCNAME[0]} Started" + + echo "Defaults env_keep += \"SSH_CLIENT\"" >> /etc/sudoers + + if [[ "${release}" == "Ubuntu" ]]; then + user_group="ubuntu" + elif [[ "${release}" == "CentOS" ]]; then + user_group="centos" + elif [[ "${release}" == "SLES" ]]; then + user_group="users" + else + user_group="ec2-user" + fi + + if [[ "${release}" == "CentOS" ]]; then + /sbin/restorecon -v /etc/ssh/sshd_config + systemctl restart sshd + fi + + if [[ "${release}" == "SLES" ]]; then + echo "0 0 * * * zypper patch --non-interactive" > ~/mycron + elif [[ "${release}" == "Ubuntu" ]]; then + apt-get install -y unattended-upgrades + echo "0 0 * * * unattended-upgrades -d" > ~/mycron + else + echo "0 0 * * * yum -y update --security" > ~/mycron + fi + + crontab ~/mycron + rm ~/mycron + + echo "${FUNCNAME[0]} Ended" +} + +function request_eip() { + + # Is the already-assigned Public IP an elastic IP? + _query_assigned_public_ip + + set +e + _determine_eip_assc_status ${PUBLIC_IP_ADDRESS} + set -e + + if [[ ${_eip_associated} -eq 0 ]]; then + echo "The Public IP address associated with eth0 (${PUBLIC_IP_ADDRESS}) is already an Elastic IP. Not proceeding further." + exit 1 + fi + + EIP_ARRAY=(${EIP_LIST//,/ }) + _eip_assigned_count=0 + + for eip in "${EIP_ARRAY[@]}"; do + + if [[ "${eip}" == "Null" ]]; then + echo "Detected a NULL Value, moving on." + continue + fi + + # Determine if the EIP has already been assigned. + set +e + _determine_eip_assc_status ${eip} + set -e + if [[ ${_eip_associated} -eq 0 ]]; then + echo "Elastic IP [${eip}] already has an association. Moving on." + let _eip_assigned_count+=1 + if [[ "${_eip_assigned_count}" -eq "${#EIP_ARRAY[@]}" ]]; then + echo "All of the stack EIPs have been assigned (${_eip_assigned_count}/${#EIP_ARRAY[@]}). I can't assign anything else. Exiting." + exit 1 + fi + continue + fi + + _determine_eip_allocation ${eip} + + # Attempt to assign EIP to the ENI. + set +e + aws ec2 associate-address --instance-id ${INSTANCE_ID} --allocation-id ${eip_allocation} --region ${REGION} + + rc=$? + set -e + + if [[ ${rc} -ne 0 ]]; then + + let _eip_assigned_count+=1 + continue + else + echo "The newly-assigned EIP is ${eip}. It is mapped under EIP Allocation ${eip_allocation}" + break + fi + done + echo "${FUNCNAME[0]} Ended" +} + +function _query_assigned_public_ip() { + # Note: ETH0 Only. + # - Does not distinguish between EIP and Standard IP. Need to cross-ref later. + echo "Querying the assigned public IP" + PUBLIC_IP_ADDRESS=$(curl -sq 169.254.169.254/latest/meta-data/public-ipv4/${ETH0_MAC}/public-ipv4s/) +} + +function _determine_eip_assc_status(){ + # Is the provided EIP associated? + # Also determines if an IP is an EIP. + # 0 => true + # 1 => false + echo "Determining EIP Association Status for [${1}]" + set +e + aws ec2 describe-addresses --public-ips ${1} --output text --region ${REGION} 2>/dev/null | grep -o -i eipassoc -q + rc=$? + set -e + if [[ ${rc} -eq 1 ]]; then + _eip_associated=1 + else + _eip_associated=0 + fi + +} + +function _determine_eip_allocation(){ + echo "Determining EIP Allocation for [${1}]" + resource_id_length=$(aws ec2 describe-addresses --public-ips ${1} --output text --region ${REGION} | head -n 1 | awk {'print $2'} | sed 's/.*eipalloc-//') + if [[ "${#resource_id_length}" -eq 17 ]]; then + eip_allocation=$(aws ec2 describe-addresses --public-ips ${1} --output text --region ${REGION}| egrep 'eipalloc-([a-z0-9]{17})' -o) + else + eip_allocation=$(aws ec2 describe-addresses --public-ips ${1} --output text --region ${REGION}| egrep 'eipalloc-([a-z0-9]{8})' -o) + fi +} + +function prevent_process_snooping() { + # Prevent bastion host users from viewing processes owned by other users. + mount -o remount,rw,hidepid=2 /proc + awk '!/proc/' /etc/fstab > temp && mv temp /etc/fstab + echo "proc /proc proc defaults,hidepid=2 0 0" >> /etc/fstab + echo "${FUNCNAME[0]} Ended" +} + +##################################### End Function Definitions + +# Call checkos to ensure platform is Linux +checkos +# Verify dependencies are installed. +verify_dependencies +# Assuming it is, setup environment variables. +setup_environment_variables + +## set an initial value +SSH_BANNER="LINUX BASTION" + +# Read the options from cli input +TEMP=`getopt -o h --longoptions help,banner:,enable:,tcp-forwarding:,x11-forwarding: -n $0 -- "$@"` +eval set -- "${TEMP}" + + +if [[ $# == 1 ]] ; then echo "No input provided! type ($0 --help) to see usage help" >&2 ; exit 1 ; fi + +# extract options and their arguments into variables. +while true; do + case "$1" in + -h | --help) + usage + exit 1 + ;; + --banner) + BANNER_PATH="$2"; + shift 2 + ;; + --enable) + ENABLE="$2"; + shift 2 + ;; + --tcp-forwarding) + TCP_FORWARDING="$2"; + shift 2 + ;; + --x11-forwarding) + X11_FORWARDING="$2"; + shift 2 + ;; + --) + break + ;; + *) + break + ;; + esac +done + +# BANNER CONFIGURATION +BANNER_FILE="/etc/ssh_banner" +if [[ ${ENABLE} == "true" ]];then + if [[ -z ${BANNER_PATH} ]];then + echo "BANNER_PATH is null skipping ..." + else + echo "BANNER_PATH = ${BANNER_PATH}" + echo "Creating Banner in ${BANNER_FILE}" + aws s3 cp "${BANNER_PATH}" "${BANNER_FILE}" --region ${BANNER_REGION} + if [[ -e ${BANNER_FILE} ]] ;then + echo "[INFO] Installing banner ... " + echo -e "\n Banner ${BANNER_FILE}" >>/etc/ssh/sshd_config + else + echo "[INFO] banner file is not accessible skipping ..." + exit 1; + fi + fi +else + echo "Banner message is not enabled!" +fi + +#Enable/Disable TCP forwarding +TCP_FORWARDING=`echo "${TCP_FORWARDING}" | sed 's/\\n//g'` + +#Enable/Disable X11 forwarding +X11_FORWARDING=`echo "${X11_FORWARDING}" | sed 's/\\n//g'` + +echo "Value of TCP_FORWARDING - ${TCP_FORWARDING}" +echo "Value of X11_FORWARDING - ${X11_FORWARDING}" +if [[ ${TCP_FORWARDING} == "false" ]];then + awk '!/AllowTcpForwarding/' /etc/ssh/sshd_config > temp && mv temp /etc/ssh/sshd_config + echo "AllowTcpForwarding no" >> /etc/ssh/sshd_config +fi + +if [[ ${X11_FORWARDING} == "false" ]];then + awk '!/X11Forwarding/' /etc/ssh/sshd_config > temp && mv temp /etc/ssh/sshd_config + echo "X11Forwarding no" >> /etc/ssh/sshd_config +fi + +release=$(osrelease) +if [[ "${release}" == "Operating System Not Found" ]]; then + echo "[ERROR] Unsupported Linux Bastion OS" + exit 1 +else + setup_os + setup_logs +fi + +prevent_process_snooping +request_eip + +echo "Bootstrap complete." diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/templates/linux-bastion-master.template b/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/templates/linux-bastion-master.template new file mode 100644 index 0000000..3119956 --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/templates/linux-bastion-master.template @@ -0,0 +1,299 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: LinuxBastion+VPC Jul,30,2020 (qs-1qup6ra9p) (Please do not remove) +Metadata: + LICENSE: Apache License, Version 2.0 + 'AWS::CloudFormation::Interface': + ParameterGroups: + - Label: + default: Network configuration + Parameters: + - AvailabilityZones + - VPCCIDR + - PrivateSubnet1CIDR + - PrivateSubnet2CIDR + - PublicSubnet1CIDR + - PublicSubnet2CIDR + - RemoteAccessCIDR + - VPCTenancy + - Label: + default: Amazon EC2 configuration + Parameters: + - KeyPairName + - BastionAMIOS + - BastionInstanceType + - Label: + default: Linux bastion configuration + Parameters: + - NumBastionHosts + - BastionHostName + - BastionTenancy + - EnableBanner + - BastionBanner + - EnableTCPForwarding + - EnableX11Forwarding + - Label: + default: AWS Quick Start configuration + Parameters: + - QSS3BucketName + - QSS3KeyPrefix + - QSS3BucketRegion + ParameterLabels: + AvailabilityZones: + default: Availability Zones + BastionAMIOS: + default: Bastion AMI operating system + BastionHostName: + default: Bastion Host Name + BastionTenancy: + default: Bastion tenancy + BastionBanner: + default: Banner text + BastionInstanceType: + default: Bastion instance type + QSS3BucketRegion: + default: Quick Start S3 bucket region + EnableBanner: + default: Bastion banner + EnableTCPForwarding: + default: TCP forwarding + EnableX11Forwarding: + default: X11 forwarding + KeyPairName: + default: Key pair name + NumBastionHosts: + default: Number of bastion hosts + PrivateSubnet1CIDR: + default: Private subnet 1 CIDR + PrivateSubnet2CIDR: + default: Private subnet 2 CIDR + PublicSubnet1CIDR: + default: Public subnet 1 CIDR + PublicSubnet2CIDR: + default: Public subnet 2 CIDR + VPCTenancy: + default: VPC tenancy + QSS3BucketName: + default: Quick Start S3 bucket name + QSS3KeyPrefix: + default: Quick Start S3 key prefix + RemoteAccessCIDR: + default: Allowed bastion external access CIDR + VPCCIDR: + default: VPC CIDR + cfn-lint: { config: { ignore_checks: [E9007] } } +Parameters: + AvailabilityZones: + Description: 'List of Availability Zones to use for the subnets in the VPC. Note: ( The logical order is preserved and only 2 AZs are used for this deployment.' + Type: 'List' + BastionAMIOS: + AllowedValues: + - Amazon-Linux2-HVM + - CentOS-7-HVM + - Ubuntu-Server-20.04-LTS-HVM + - SUSE-SLES-15-HVM + Default: Amazon-Linux2-HVM + Description: The Linux distribution for the AMI to be used for the bastion instances. + Type: String + BastionHostName: + Default: 'LinuxBastion' + Description: The value used for the name tag of the bastion host + Type: String + BastionBanner: + Default: "" + Description: Banner text to display upon login. + Type: String + BastionTenancy: + Description: 'VPC tenancy to launch the bastion in. Options: ''dedicated'' or ''default''' + Type: String + Default: default + AllowedValues: + - dedicated + - default + BastionInstanceType: + Description: Amazon EC2 instance type for the bastion instances. + Type: String + Default: t2.micro + AllowedValues: + - t2.nano + - t2.micro + - t2.small + - t2.medium + - t2.large + - t3.micro + - t3.small + - t3.medium + - t3.large + - t3.xlarge + - t3.2xlarge + - m3.large + - m3.xlarge + - m3.2xlarge + - m4.large + - m4.xlarge + - m4.2xlarge + - m4.4xlarge + EnableBanner: + AllowedValues: + - 'true' + - 'false' + Default: 'false' + Description: To include a banner to be displayed when connecting via SSH to the + bastion, choose true. + Type: String + EnableTCPForwarding: + Type: String + Description: To enable TCP forwarding, choose true. + Default: 'false' + AllowedValues: + - 'true' + - 'false' + EnableX11Forwarding: + Type: String + Description: To enable X11 forwarding, choose true. + Default: 'false' + AllowedValues: + - 'true' + - 'false' + KeyPairName: + Description: 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' + NumBastionHosts: + AllowedValues: + - '1' + - '2' + - '3' + - '4' + Default: '1' + Description: The number of bastion hosts to create. The maximum number is four. + Type: String + PrivateSubnet1CIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.0.0/19 + Description: CIDR block for private subnet 1 located in Availability Zone 1. + Type: String + PrivateSubnet2CIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.32.0/19 + Description: CIDR block for private subnet 2 located in Availability Zone 2. + Type: String + PublicSubnet1CIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.128.0/20 + Description: CIDR Block for the public DMZ subnet 1 located in Availability Zone 1. + Type: String + PublicSubnet2CIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.144.0/20 + Description: CIDR Block for the public DMZ subnet 2 located in Availability Zone 2. + Type: String + VPCTenancy: + AllowedValues: + - default + - dedicated + Default: default + Description: The allowed tenancy of instances launched into the VPC. + Type: String + QSS3BucketName: + 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 + Description: S3 bucket name for the Quick Start assets. Quick Start bucket name can + include numbers, lowercase letters, uppercase letters, and hyphens (-). It + cannot start or end with a hyphen (-). + Type: String + QSS3KeyPrefix: + AllowedPattern: ^([0-9a-zA-Z-.]+/)*$ + ConstraintDescription: Quick Start key prefix can include numbers, lowercase letters, uppercase letters, hyphens (-), dots (.) and forward slash (/). The prefix should end with a forward slash (/). + Default: quickstart-linux-bastion/ + Description: S3 key prefix for the Quick Start assets. Quick Start key prefix can + include numbers, lowercase letters, uppercase letters, hyphens (-), dots + (.) and forward slash (/) and it should end with a forward slash (/). + 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 + RemoteAccessCIDR: + 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]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/x + Description: Allowed CIDR block for external SSH access to the bastions + Type: String + VPCCIDR: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.0.0/16 + Description: CIDR Block for the VPC. + Type: String +Conditions: + UsingDefaultBucket: !Equals + - !Ref QSS3BucketName + - 'aws-quickstart' +Resources: + VPCStack: + Type: 'AWS::CloudFormation::Stack' + Properties: + TemplateURL: !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-aws-vpc/templates/aws-vpc.template + - S3Bucket: !If + - UsingDefaultBucket + - !Sub 'aws-quickstart-${AWS::Region}' + - !Ref 'QSS3BucketName' + S3Region: !If + - UsingDefaultBucket + - !Ref 'AWS::Region' + - !Ref 'QSS3BucketRegion' + Parameters: + AvailabilityZones: !Join + - ',' + - !Ref AvailabilityZones + KeyPairName: !Ref KeyPairName + NumberOfAZs: '2' + PrivateSubnet1ACIDR: !Ref PrivateSubnet1CIDR + PrivateSubnet2ACIDR: !Ref PrivateSubnet2CIDR + PublicSubnet1CIDR: !Ref PublicSubnet1CIDR + PublicSubnet2CIDR: !Ref PublicSubnet2CIDR + VPCCIDR: !Ref VPCCIDR + VPCTenancy: !Ref VPCTenancy + BastionStack: + Type: 'AWS::CloudFormation::Stack' + Properties: + TemplateURL: !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}templates/linux-bastion.template + - S3Bucket: !If + - UsingDefaultBucket + - !Sub 'aws-quickstart-${AWS::Region}' + - !Ref 'QSS3BucketName' + S3Region: !If + - UsingDefaultBucket + - !Ref 'AWS::Region' + - !Ref 'QSS3BucketRegion' + Parameters: + BastionAMIOS: !Ref BastionAMIOS + BastionHostName: !Ref BastionHostName + BastionBanner: !Ref BastionBanner + BastionInstanceType: !Ref BastionInstanceType + BastionTenancy: !Ref BastionTenancy + EnableBanner: !Ref EnableBanner + EnableTCPForwarding: !Ref EnableTCPForwarding + EnableX11Forwarding: !Ref EnableX11Forwarding + KeyPairName: !Ref KeyPairName + NumBastionHosts: !Ref NumBastionHosts + PublicSubnet1ID: !GetAtt + - VPCStack + - Outputs.PublicSubnet1ID + PublicSubnet2ID: !GetAtt + - VPCStack + - Outputs.PublicSubnet2ID + QSS3BucketRegion: !Ref QSS3BucketRegion + QSS3BucketName: !Ref QSS3BucketName + QSS3KeyPrefix: !Ref QSS3KeyPrefix + RemoteAccessCIDR: !Ref RemoteAccessCIDR + VPCID: !GetAtt + - VPCStack + - Outputs.VPCID + diff --git a/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/templates/linux-bastion.template b/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/templates/linux-bastion.template new file mode 100644 index 0000000..46046a9 --- /dev/null +++ b/Amazon/artifactory7/v7174/submodules/quickstart-linux-bastion/templates/linux-bastion.template @@ -0,0 +1,725 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: LinuxBastion+VPC Jul,30,2020 (qs-1qup6ra99) (Please do not remove) +Metadata: + LICENSE: Apache License, Version 2.0 + 'AWS::CloudFormation::Interface': + ParameterGroups: + - Label: + default: Network configuration + Parameters: + - VPCID + - PublicSubnet1ID + - PublicSubnet2ID + - RemoteAccessCIDR + - Label: + default: Amazon EC2 configuration + Parameters: + - KeyPairName + - BastionAMIOS + - BastionInstanceType + - RootVolumeSize + - Label: + default: Linux bastion configuration + Parameters: + - NumBastionHosts + - BastionHostName + - BastionTenancy + - EnableBanner + - BastionBanner + - EnableTCPForwarding + - EnableX11Forwarding + - Label: + default: Alternative configurations + Parameters: + - AlternativeInitializationScript + - OSImageOverride + - AlternativeIAMRole + - EnvironmentVariables + - Label: + default: AWS Quick Start configuration + Parameters: + - QSS3BucketName + - QSS3KeyPrefix + - QSS3BucketRegion + ParameterLabels: + AlternativeIAMRole: + default: Alternative IAM role + AlternativeInitializationScript: + default: Alternative initialization script + BastionAMIOS: + default: Bastion AMI operating system + BastionHostName: + default: Bastion Host Name + BastionTenancy: + default: Bastion tenancy + BastionBanner: + default: Banner text + QSS3BucketRegion: + default: Quick Start S3 bucket region + BastionInstanceType: + default: Bastion instance type + EnableBanner: + default: Bastion banner + EnableTCPForwarding: + default: TCP forwarding + EnableX11Forwarding: + default: X11 forwarding + EnvironmentVariables: + default: Environment variables + KeyPairName: + default: Key pair name + NumBastionHosts: + default: Number of bastion hosts + OSImageOverride: + default: Operating system override + PublicSubnet1ID: + default: Public subnet 1 ID + PublicSubnet2ID: + default: Public subnet 2 ID + QSS3BucketName: + default: Quick Start S3 bucket name + QSS3KeyPrefix: + default: Quick Start S3 key prefix + RemoteAccessCIDR: + default: Allowed bastion external access CIDR + VPCID: + default: VPC ID + RootVolumeSize: + default: Root volume size + cfn-lint: { config: { ignore_checks: [E9007] } } +Parameters: + BastionAMIOS: + AllowedValues: + - Amazon-Linux2-HVM + - CentOS-7-HVM + - Ubuntu-Server-20.04-LTS-HVM + - SUSE-SLES-15-HVM + Default: Amazon-Linux2-HVM + Description: The Linux distribution for the AMI to be used for the bastion instances. + Type: String + BastionHostName: + Default: 'LinuxBastion' + Description: The value used for the name tag of the bastion host + Type: String + BastionBanner: + Default: "" + Description: Banner text to display upon login. + Type: String + BastionTenancy: + Description: 'VPC tenancy to launch the bastion in. Options: ''dedicated'' or ''default''' + Type: String + Default: default + AllowedValues: + - dedicated + - default + BastionInstanceType: + AllowedValues: + - t2.nano + - t2.micro + - t2.small + - t2.medium + - t2.large + - t3.micro + - t3.small + - t3.medium + - t3.large + - t3.xlarge + - t3.2xlarge + - m4.large + - m4.xlarge + - m4.2xlarge + - m4.4xlarge + Default: t2.micro + Description: Amazon EC2 instance type for the bastion instances. + Type: String + EnableBanner: + AllowedValues: + - 'true' + - 'false' + Default: 'false' + Description: To include a banner to be displayed when connecting via SSH to the + bastion, choose true. + Type: String + EnableTCPForwarding: + Type: String + Description: To enable TCP forwarding, choose true. + Default: 'false' + AllowedValues: + - 'true' + - 'false' + EnableX11Forwarding: + Type: String + Description: To enable X11 forwarding, choose true. + Default: 'false' + AllowedValues: + - 'true' + - 'false' + KeyPairName: + Description: Name of an existing public/private key pair. If you do not have one in this AWS Region, + please create it before continuing. + Type: 'AWS::EC2::KeyPair::KeyName' + NumBastionHosts: + AllowedValues: + - '1' + - '2' + - '3' + - '4' + Default: '1' + Description: The number of bastion hosts to create. The maximum number is four. + Type: String + PublicSubnet1ID: + Description: ID of the public subnet 1 that you want to provision the first bastion + into (e.g., subnet-a0246dcd). + Type: 'AWS::EC2::Subnet::Id' + PublicSubnet2ID: + Description: ID of the public subnet 2 that you want to provision the second bastion into + (e.g., subnet-e3246d8e). + Type: 'AWS::EC2::Subnet::Id' + QSS3BucketName: + 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 + Description: S3 bucket name for the Quick Start assets. Quick Start bucket name can + include numbers, lowercase letters, uppercase letters, and hyphens (-). It + cannot start or end with a hyphen (-). + 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 + QSS3KeyPrefix: + AllowedPattern: '^([0-9a-zA-Z-.]+/)*$' + ConstraintDescription: Quick Start key prefix can include numbers, lowercase letters, uppercase + letters, hyphens (-), dots (.) and forward slash (/). The prefix should + end with a forward slash (/). + Default: quickstart-linux-bastion/ + Description: S3 key prefix for the Quick Start assets. Quick Start key prefix can + include numbers, lowercase letters, uppercase letters, hyphens (-), dots + (.) and forward slash (/) and it should end with a forward slash (/). + Type: String + RemoteAccessCIDR: + 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]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/x + Description: Allowed CIDR block for external SSH access to the bastions. + Type: String + VPCID: + Description: 'ID of the VPC (e.g., vpc-0343606e).' + Type: 'AWS::EC2::VPC::Id' + AlternativeInitializationScript: + AllowedPattern: ^http.*|^$ + ConstraintDescription: URL must begin with http + Description: An alternative initialization script to run during setup. + Default: '' + Type: String + OSImageOverride: + Description: The Region-specific image to use for the instance. + Type: String + Default: '' + AlternativeIAMRole: + Description: An existing IAM Role name to attach to the bastion. If left blank, + a new role will be created. + Default: '' + Type: String + EnvironmentVariables: + Description: A comma-separated list of environment variables for use in + bootstrapping. Variables must be in the format KEY=VALUE. VALUE cannot + contain commas. + Type: String + Default: '' + RootVolumeSize: + Description: The size in GB for the root EBS volume. + Type: Number + Default: '10' +Rules: + SubnetsInVPC: + Assertions: + - Assert: + 'Fn::EachMemberIn': + - 'Fn::ValueOfAll': + - 'AWS::EC2::Subnet::Id' + - VpcId + - 'Fn::RefAll': 'AWS::EC2::VPC::Id' + AssertDescription: All subnets must exist in the VPC +Mappings: + AWSAMIRegionMap: + ap-northeast-1: + AMZNLINUX2: ami-0cc75a8978fbbc969 + US2004HVM: ami-0461b11e2fad8c14a + CENTOS7HVM: ami-06a46da680048c8ae + SLES15HVM: ami-056ac8ad44e6a7e1f + ap-northeast-2: + AMZNLINUX2: ami-0bd7691bf6470fe9c + US2004HVM: ami-0dbad3c7f731477cb + CENTOS7HVM: ami-06e83aceba2cb0907 + SLES15HVM: ami-0f81fff879bafe6b8 + ap-south-1: + AMZNLINUX2: ami-0ebc1ac48dfd14136 + US2004HVM: ami-0ebd654017556e025 + CENTOS7HVM: ami-026f33d38b6410e30 + SLES15HVM: ami-01be89269d32f2a16 + ap-southeast-1: + AMZNLINUX2: ami-0cd31be676780afa7 + US2004HVM: ami-0ba1d1f3433cd4c68 + CENTOS7HVM: ami-07f65177cb990d65b + SLES15HVM: ami-070356c21596ddc67 + ap-southeast-2: + AMZNLINUX2: ami-0ded330691a314693 + US2004HVM: ami-02be36619a83e9a16 + CENTOS7HVM: ami-0b2045146eb00b617 + SLES15HVM: ami-0c4245381c67efb39 + ca-central-1: + AMZNLINUX2: ami-013d1df4bcea6ba95 + US2004HVM: ami-071c33c681c9d4a00 + CENTOS7HVM: ami-04a25c39dc7a8aebb + SLES15HVM: ami-0c97d9b588207dad6 + eu-central-1: + AMZNLINUX2: ami-0c115dbd34c69a004 + US2004HVM: ami-0c2b1c303a2e4cb49 + CENTOS7HVM: ami-0e8286b71b81c3cc1 + SLES15HVM: ami-05dfd265ea534a3e9 + me-south-1: + AMZNLINUX2: ami-01f41d49c363da2ad + US2004HVM: ami-07f9fe3f7a8c82448 + CENTOS7HVM: ami-011c71a894b10f35b + SLES15HVM: ami-0252c6d3a59c7473b + ap-east-1: + AMZNLINUX2: ami-47317236 + US2004HVM: ami-545b1825 + CENTOS7HVM: ami-0e5c29e6c87a9644f + SLES15HVM: ami-0ad6e15bcbb2dbe38 + eu-north-1: + AMZNLINUX2: ami-039609244d2810a6b + US2004HVM: ami-08baf9e3c347b7092 + CENTOS7HVM: ami-05788af9005ef9a93 + SLES15HVM: ami-0741fa1a008af40ad + eu-west-1: + AMZNLINUX2: ami-07d9160fa81ccffb5 + US2004HVM: ami-0f1d11c92a9467c07 + CENTOS7HVM: ami-0b850cf02cc00fdc8 + SLES15HVM: ami-0a58a1b152ba55f1d + eu-west-2: + AMZNLINUX2: ami-0a13d44dccf1f5cf6 + US2004HVM: ami-082335b69bcfdb15b + CENTOS7HVM: ami-09e5afc68eed60ef4 + SLES15HVM: ami-01497522185aaa4ee + eu-west-3: + AMZNLINUX2: ami-093fa4c538885becf + US2004HVM: ami-00f6fb16625871821 + CENTOS7HVM: ami-0cb72d2e599cffbf9 + SLES15HVM: ami-0f238bd4c6fdbefb0 + sa-east-1: + AMZNLINUX2: ami-018ccfb6b4745882a + US2004HVM: ami-083aa2af86ff2bd11 + CENTOS7HVM: ami-0b30f38d939dd4b54 + SLES15HVM: ami-0772af912976aa692 + us-east-1: + AMZNLINUX2: ami-02354e95b39ca8dec + US2004HVM: ami-0758470213bdd23b1 + CENTOS7HVM: ami-0affd4508a5d2481b + SLES15HVM: ami-0b1764f3d7d2e2316 + us-gov-west-1: + AMZNLINUX2: ami-74c4f215 + SLES15HVM: ami-57c0ba36 + us-gov-east-1: + AMZNLINUX2: ami-30e00c41 + SLES15HVM: ami-05e4bedfad53425e9 + us-east-2: + AMZNLINUX2: ami-07c8bc5c1ce9598c3 + US2004HVM: ami-07fb7bd53bacdfc16 + CENTOS7HVM: ami-01e36b7901e884a10 + SLES15HVM: ami-05ea824317ffc0c20 + us-west-1: + AMZNLINUX2: ami-05655c267c89566dd + US2004HVM: ami-0cd230f950c3de5d8 + CENTOS7HVM: ami-098f55b4287a885ba + SLES15HVM: ami-00e34a7624e5a7107 + us-west-2: + AMZNLINUX2: ami-0873b46c45c11058d + US2004HVM: ami-056cb9ae6e2df09e8 + CENTOS7HVM: ami-0bc06212a56393ee1 + SLES15HVM: ami-0f1e3b3fb0fec0361 + cn-north-1: + AMZNLINUX2: ami-010e92a33d9d1fc40 + CENTOS7HVM: ami-0e02aaefeb74c3373 + SLES15HVM: ami-021392849b6221a81 + cn-northwest-1: + AMZNLINUX2: ami-0959f8e18a2aac0fb + CENTOS7HVM: ami-07183a7702633260b + SLES15HVM: ami-00e1de3ee6d0d28ea + LinuxAMINameMap: + Amazon-Linux2-HVM: + Code: AMZNLINUX2 + OS: Amazon + CentOS-7-HVM: + Code: CENTOS7HVM + OS: CentOS + Ubuntu-Server-18.04-LTS-HVM: + Code: US1804HVM + OS: Ubuntu + Ubuntu-Server-20.04-LTS-HVM: + Code: US2004HVM + OS: Ubuntu + SUSE-SLES-15-HVM: + Code: SLES15HVM + OS: SLES +Conditions: + 2BastionCondition: !Or + - !Equals + - !Ref NumBastionHosts + - '2' + - !Condition 3BastionCondition + - !Condition 4BastionCondition + 3BastionCondition: !Or + - !Equals + - !Ref NumBastionHosts + - '3' + - !Condition 4BastionCondition + 4BastionCondition: !Equals + - !Ref NumBastionHosts + - '4' + UseAlternativeInitialization: !Not + - !Equals + - !Ref AlternativeInitializationScript + - '' + CreateIAMRole: !Equals + - !Ref AlternativeIAMRole + - '' + UseOSImageOverride: !Not + - !Equals + - !Ref OSImageOverride + - '' + UsingDefaultBucket: !Equals + - !Ref QSS3BucketName + - 'aws-quickstart' + DefaultBanner: !Equals [!Ref BastionBanner, ""] +Resources: + BastionMainLogGroup: + Type: 'AWS::Logs::LogGroup' + SSHMetricFilter: + Type: 'AWS::Logs::MetricFilter' + Properties: + LogGroupName: !Ref BastionMainLogGroup + FilterPattern: ON FROM USER PWD + MetricTransformations: + - MetricName: SSHCommandCount + MetricValue: '1' + MetricNamespace: !Sub "AWSQuickStart/${AWS::StackName}" + BastionHostRole: + Condition: CreateIAMRole + Type: 'AWS::IAM::Role' + Properties: + Path: / + AssumeRolePolicyDocument: + Statement: + - Action: + - 'sts:AssumeRole' + Principal: + Service: + - !Sub 'ec2.${AWS::URLSuffix}' + Effect: Allow + Version: 2012-10-17 + ManagedPolicyArns: + - !Sub 'arn:${AWS::Partition}:iam::aws:policy/AmazonSSMManagedInstanceCore' + - !Sub 'arn:${AWS::Partition}:iam::aws:policy/CloudWatchAgentServerPolicy' + BastionHostPolicy: + Type: 'AWS::IAM::Policy' + Properties: + PolicyName: BastionPolicy + PolicyDocument: + Version: 2012-10-17 + Statement: + - Action: + - 's3:GetObject' + Resource: !Sub + - arn:${AWS::Partition}:s3:::${S3Bucket}/${QSS3KeyPrefix}* + - S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] + Effect: Allow + - Action: + - 'logs:CreateLogStream' + - 'logs:GetLogEvents' + - 'logs:PutLogEvents' + - 'logs:DescribeLogGroups' + - 'logs:DescribeLogStreams' + - 'logs:PutRetentionPolicy' + - 'logs:PutMetricFilter' + - 'logs:CreateLogGroup' + Resource: !Sub "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:${BastionMainLogGroup}:*" + Effect: Allow + - Action: + - 'ec2:AssociateAddress' + - 'ec2:DescribeAddresses' + Resource: '*' + Effect: Allow + Roles: + - !If + - CreateIAMRole + - !Ref BastionHostRole + - !Ref AlternativeIAMRole + BastionHostProfile: + DependsOn: BastionHostPolicy + Type: 'AWS::IAM::InstanceProfile' + Properties: + Roles: + - !If + - CreateIAMRole + - !Ref BastionHostRole + - !Ref AlternativeIAMRole + Path: / + EIP1: + Type: 'AWS::EC2::EIP' + Properties: + Domain: vpc + EIP2: + Type: 'AWS::EC2::EIP' + Condition: 2BastionCondition + Properties: + Domain: vpc + EIP3: + Type: 'AWS::EC2::EIP' + Condition: 3BastionCondition + Properties: + Domain: vpc + EIP4: + Type: 'AWS::EC2::EIP' + Condition: 4BastionCondition + Properties: + Domain: vpc + BastionAutoScalingGroup: + Type: 'AWS::AutoScaling::AutoScalingGroup' + Properties: + LaunchConfigurationName: !Ref BastionLaunchConfiguration + VPCZoneIdentifier: + - !Ref PublicSubnet1ID + - !Ref PublicSubnet2ID + MinSize: !Ref NumBastionHosts + MaxSize: !Ref NumBastionHosts + Cooldown: '900' + DesiredCapacity: !Ref NumBastionHosts + Tags: + - Key: Name + Value: !Ref BastionHostName + PropagateAtLaunch: true + CreationPolicy: + ResourceSignal: + Count: !Ref NumBastionHosts + Timeout: PT60M + AutoScalingCreationPolicy: + MinSuccessfulInstancesPercent: 100 + UpdatePolicy: + AutoScalingReplacingUpdate: + WillReplace: true + BastionLaunchConfiguration: + Type: 'AWS::AutoScaling::LaunchConfiguration' + Metadata: + 'AWS::CloudFormation::Authentication': + S3AccessCreds: + type: S3 + roleName: !If + - CreateIAMRole + - !Ref BastionHostRole + - !Ref AlternativeIAMRole + buckets: + - !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] + 'AWS::CloudFormation::Init': + config: + files: + /tmp/auditd.rules: + mode: '000550' + owner: root + group: root + content: | + -a exit,always -F arch=b64 -S execve + -a exit,always -F arch=b32 -S execve + /tmp/auditing_configure.sh: + source: !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/auditing_configure.sh + - S3Bucket: !If + - UsingDefaultBucket + - !Sub 'aws-quickstart-${AWS::Region}' + - !Ref 'QSS3BucketName' + S3Region: !If + - UsingDefaultBucket + - !Ref 'AWS::Region' + - !Ref 'QSS3BucketRegion' + mode: '000550' + owner: root + group: root + authentication: S3AccessCreds + /tmp/bastion_bootstrap.sh: + source: !If + - UseAlternativeInitialization + - !Ref AlternativeInitializationScript + - !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/bastion_bootstrap.sh + - S3Bucket: !If + - UsingDefaultBucket + - !Sub 'aws-quickstart-${AWS::Region}' + - !Ref 'QSS3BucketName' + S3Region: !If + - UsingDefaultBucket + - !Ref 'AWS::Region' + - !Ref 'QSS3BucketRegion' + mode: '000550' + owner: root + group: root + authentication: S3AccessCreds + commands: + a-add_auditd_rules: + cwd: '/tmp/' + env: + BASTION_OS: !FindInMap [LinuxAMINameMap, !Ref BastionAMIOS, OS] + command: "./auditing_configure.sh" + # command: + # - !If [ ] + # - "cat /tmp/auditd.rules >> /etc/audit/rules.d/audit.rules && service auditd restart" + b-bootstrap: + cwd: '/tmp/' + env: + REGION: !Sub ${AWS::Region} + URL_SUFFIX: !Sub ${AWS::URLSuffix} + BANNER_REGION: !If [ UsingDefaultBucket, !Ref 'AWS::Region', !Ref 'QSS3BucketRegion' ] + command: !Sub + - "./bastion_bootstrap.sh --banner ${BannerUrl} --enable ${EnableBanner} --tcp-forwarding ${EnableTCPForwarding} --x11-forwarding ${EnableX11Forwarding}" + - BannerUrl: !If + - DefaultBanner + - !Sub + - s3://${S3Bucket}/${QSS3KeyPrefix}scripts/banner_message.txt + - S3Bucket: !If [ UsingDefaultBucket, !Sub 'aws-quickstart-${AWS::Region}', !Ref 'QSS3BucketName' ] + - !Ref BastionBanner + Properties: + AssociatePublicIpAddress: true + PlacementTenancy: !Ref BastionTenancy + KeyName: !Ref KeyPairName + IamInstanceProfile: !Ref BastionHostProfile + ImageId: !If + - UseOSImageOverride + - !Ref OSImageOverride + - !FindInMap + - AWSAMIRegionMap + - !Ref 'AWS::Region' + - !FindInMap + - LinuxAMINameMap + - !Ref BastionAMIOS + - Code + SecurityGroups: + - !Ref BastionSecurityGroup + InstanceType: !Ref BastionInstanceType + BlockDeviceMappings: + - DeviceName: /dev/xvda + Ebs: + VolumeSize: !Ref RootVolumeSize + VolumeType: gp2 + Encrypted: true + DeleteOnTermination: true + UserData: + Fn::Base64: !Sub + - | + #!/bin/bash + set -x + for e in $(echo "${EnvironmentVariables}" | tr ',' ' '); do + export $e + done + export PATH=$PATH:/usr/local/bin + #cfn signaling functions + yum install git -y || apt-get install -y git || zypper -n install git + + function cfn_fail + { + cfn-signal -e 1 --stack ${AWS::StackName} --region ${AWS::Region} --resource BastionAutoScalingGroup + exit 1 + } + + function cfn_success + { + cfn-signal -e 0 --stack ${AWS::StackName} --region ${AWS::Region} --resource BastionAutoScalingGroup + exit 0 + } + + until git clone https://github.com/aws-quickstart/quickstart-linux-utilities.git ; do echo "Retrying"; done + cd /quickstart-linux-utilities; + source quickstart-cfn-tools.source; + qs_update-os || qs_err; + qs_bootstrap_pip || qs_err " pip bootstrap failed "; + qs_aws-cfn-bootstrap || qs_err " cfn bootstrap failed "; + + EIP_LIST="${EIP1},${EIP2},${EIP3},${EIP4}" + CLOUDWATCHGROUP=${BastionMainLogGroup} + cfn-init -v --stack '${AWS::StackName}' --resource BastionLaunchConfiguration --region ${AWS::Region} || cfn_fail + [ $(qs_status) == 0 ] && cfn_success || cfn_fail + - EIP2: + !If + - 2BastionCondition + - !Ref EIP2 + - 'Null' + EIP3: + !If + - 3BastionCondition + - !Ref EIP3 + - 'Null' + EIP4: + !If + - 4BastionCondition + - !Ref EIP4 + - 'Null' + BastionSecurityGroup: + Type: 'AWS::EC2::SecurityGroup' + Properties: + GroupDescription: Enables SSH Access to Bastion Hosts + VpcId: !Ref VPCID + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: 22 + ToPort: 22 + CidrIp: !Ref RemoteAccessCIDR + - IpProtocol: icmp + FromPort: -1 + ToPort: -1 + CidrIp: !Ref RemoteAccessCIDR +Outputs: + BastionAutoScalingGroup: + Description: Auto Scaling Group Reference ID + Value: !Ref BastionAutoScalingGroup + Export: + Name: !Sub '${AWS::StackName}-BastionAutoScalingGroup' + EIP1: + Description: Elastic IP 1 for Bastion + Value: !Ref EIP1 + Export: + Name: !Sub '${AWS::StackName}-EIP1' + EIP2: + Condition: 2BastionCondition + Description: Elastic IP 2 for Bastion + Value: !Ref EIP2 + Export: + Name: !Sub '${AWS::StackName}-EIP2' + EIP3: + Condition: 3BastionCondition + Description: Elastic IP 3 for Bastion + Value: !Ref EIP3 + Export: + Name: !Sub '${AWS::StackName}-EIP3' + EIP4: + Condition: 4BastionCondition + Description: Elastic IP 4 for Bastion + Value: !Ref EIP4 + Export: + Name: !Sub '${AWS::StackName}-EIP4' + CloudWatchLogs: + Description: CloudWatch Logs GroupName. Your SSH logs will be stored here. + Value: !Ref BastionMainLogGroup + Export: + Name: !Sub '${AWS::StackName}-CloudWatchLogs' + BastionSecurityGroupID: + Description: Bastion Security Group ID + Value: !Ref BastionSecurityGroup + Export: + Name: !Sub '${AWS::StackName}-BastionSecurityGroupID' + BastionHostRole: + Description: Bastion IAM Role name + Value: !If + - CreateIAMRole + - !Ref BastionHostRole + - !Ref AlternativeIAMRole + Export: + Name: !Sub '${AWS::StackName}-BastionHostRole' diff --git a/Amazon/artifactory7/v7174/templates/jfrog-artifactory-core-infrastructure.template.yaml b/Amazon/artifactory7/v7174/templates/jfrog-artifactory-core-infrastructure.template.yaml new file mode 100644 index 0000000..da6c649 --- /dev/null +++ b/Amazon/artifactory7/v7174/templates/jfrog-artifactory-core-infrastructure.template.yaml @@ -0,0 +1,425 @@ +AWSTemplateFormatVersion: '2010-09-09' +Description: 'JFrog Artifactory Quick Start Deployment (qs-1qpmmjh61)' +Parameters: + AvailabilityZones: + Description: List of Availability Zones to use for the subnets in the VPC. Two + Availability Zones are used for this deployment. + Type: List + VpcId: + Type: AWS::EC2::VPC::Id + VpcCidr: + Description: CIDR block for the VPC + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.0.0/16 + Type: String + PrivateSubnet1Cidr: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.0.0/19 + Type: String + PrivateSubnet2Cidr: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.32.0/19 + Type: String + PrivateSubnet3Cidr: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.64.0/19 + Type: String + SubnetIds: + Type: List + DatabaseAllocatedStorage: + Type: Number + DatabasePreferredAz: + Type: String + MultiAzDatabase: + Description: Choose false to create an Amazon RDS instance in a single Availability Zone. + ConstraintDescription: True or False + AllowedValues: + - "true" + - "false" + Type: String + DatabaseEngine: + Type: String + DatabaseUser: + Type: String + DatabasePassword: + NoEcho: 'true' + Type: String + DatabaseInstance: + Type: String + DatabaseName: + Type: String + ArtifactoryProduct: + Default: JFrog-Artifactory-Pro + Type: String + ReleaseStage: + Default: GA + Type: String + InstanceType: + Default: m5.xlarge + Type: String + ArtifactoryHostRole: + Type: String + VolumeSize: + Type: Number + +Mappings: + DatabaseMap: + Postgres: + Name: postgresql + DatabaseVersion: 11.5 + Driver: "org.postgresql.Driver" + Plugin: postgresql-42.2.9.jar + PluginURL: https://jdbc.postgresql.org/download/ + port: "5432" + extraDatabaseOps: "" + ReleaseStageMap: + BETA: + ProDockerRepo: "earlyaccess-docker.jfrog.io/jfrog/artifactory-pro" + JcrDockerRepo: "earlyaccess-docker.jfrog.io/jfrog/artifactory-jcr" + NginxDockerRepo: "earlyaccess-docker.jfrog.io/jfrog/nginx-artifactory-pro" + GA: + ProDockerRepo: "docker.bintray.io/jfrog/artifactory-pro" + JcrDockerRepo: "docker.bintray.io/jfrog/artifactory-jcr" + NginxDockerRepo: "docker.bintray.io/jfrog/nginx-artifactory-pro" + ProductMap: + JFrog-Container-Registry: + RepoName: JcrDockerRepo + JFrog-Artifactory-Pro: + RepoName: ProDockerRepo + JavaOptionstoInstance: + c5.2xlarge: + Min: 8 + Max: 12 + DeploymentSize: Small + c5.4xlarge: + Min: 16 + Max: 24 + DeploymentSize: Large + m5.large: + Min: 4 + Max: 4 + DeploymentSize: xxSmall + m5.xlarge: + Min: 8 + Max: 12 + DeploymentSize: xSmall + m5.2xlarge: + Min: 16 + Max: 24 + DeploymentSize: Small + m5.4xlarge: + Min: 32 + Max: 48 + DeploymentSize: Medium + m5.8xlarge: + Min: 64 + Max: 96 + DeploymentSize: Large + m5.12xlarge: + Min: 96 + Max: 144 + DeploymentSize: xLarge + m5.16xlarge: + Min: 128 + Max: 192 + DeploymentSize: xxLarge + m5.24xlarge: + Min: 192 + Max: 288 + DeploymentSize: xxxLarge + m5.metal: + Min: 192 + Max: 288 + DeploymentSize: xxxLarge + m5d.large: + Min: 4 + Max: 4 + DeploymentSize: xxSmall + m5d.xlarge: + Min: 8 + Max: 12 + DeploymentSize: xSmall + m5d.2xlarge: + Min: 16 + Max: 24 + DeploymentSize: Small + m5d.4xlarge: + Min: 32 + Max: 48 + DeploymentSize: Medium + m5d.8xlarge: + Min: 64 + Max: 96 + DeploymentSize: Large + m5d.12xlarge: + Min: 96 + Max: 144 + DeploymentSize: xLarge + m5d.16xlarge: + Min: 128 + Max: 192 + DeploymentSize: xxLarge + m5d.24xlarge: + Min: 192 + Max: 288 + DeploymentSize: xxxLarge + m5d.metal: + Min: 192 + Max: 288 + DeploymentSize: xxxLarge + m5a.large: + Min: 4 + Max: 4 + DeploymentSize: xxSmall + m5a.xlarge: + Min: 8 + Max: 12 + DeploymentSize: xSmall + m5a.2xlarge: + Min: 16 + Max: 24 + DeploymentSize: Small + m5a.4xlarge: + Min: 32 + Max: 48 + DeploymentSize: Medium + m5a.8xlarge: + Min: 64 + Max: 96 + DeploymentSize: Large + m5a.12xlarge: + Min: 96 + Max: 144 + DeploymentSize: xLarge + m5a.16xlarge: + Min: 128 + Max: 192 + DeploymentSize: xxLarge + m5a.24xlarge: + Min: 192 + Max: 288 + DeploymentSize: xxxLarge + m5ad.large: + Min: 4 + Max: 4 + DeploymentSize: xxSmall + m5ad.xlarge: + Min: 8 + Max: 12 + DeploymentSize: xSmall + m5ad.2xlarge: + Min: 16 + Max: 24 + DeploymentSize: Small + m5ad.4xlarge: + Min: 32 + Max: 48 + DeploymentSize: Medium + m5ad.12xlarge: + Min: 96 + Max: 144 + DeploymentSize: xLarge + m5ad.24xlarge: + Min: 192 + Max: 288 + DeploymentSize: xxxLarge + +Conditions: + IsMultiAzDatabase: !Equals [!Ref MultiAzDatabase, 'true'] + +Resources: + ArtifactoryDatabaseSubnetGroup: + Type: AWS::RDS::DBSubnetGroup + Properties: + DBSubnetGroupDescription: Private Subnets available to the RDS Instance(s) + SubnetIds: !Ref SubnetIds + ArtifactoryDatabase: + Type: AWS::RDS::DBInstance + Properties: + AllocatedStorage: !Ref DatabaseAllocatedStorage + AvailabilityZone: !If [IsMultiAzDatabase, !Ref AWS::NoValue, !Ref DatabasePreferredAz] + BackupRetentionPeriod: 30 + DBInstanceClass: !Ref DatabaseInstance + DBName: !Ref DatabaseName + DBSubnetGroupName: !Ref ArtifactoryDatabaseSubnetGroup + Engine: !Ref DatabaseEngine + EngineVersion: !FindInMap + - DatabaseMap + - !Ref DatabaseEngine + - DatabaseVersion + MasterUsername: !Ref DatabaseUser + MasterUserPassword: !Ref DatabasePassword + MultiAZ: !Ref MultiAzDatabase + StorageEncrypted: true + VPCSecurityGroups: + - !Ref ArtifactoryDatabaseSG + ArtifactoryDatabaseSG: + Type: AWS::EC2::SecurityGroup + Properties: + Tags: + - Key: Name + Value: artifactory-rds-sg + GroupDescription: SG for RDS Instance to allow communication from the Bastion and Artifactory servers. + VpcId: !Ref VpcId + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: 22 + ToPort: 22 + CidrIp: !Ref VpcCidr + - IpProtocol: tcp + FromPort: !FindInMap + - DatabaseMap + - !Ref DatabaseEngine + - port + ToPort: !FindInMap + - DatabaseMap + - !Ref DatabaseEngine + - port + CidrIp: !Ref PrivateSubnet1Cidr + - IpProtocol: tcp + FromPort: !FindInMap + - DatabaseMap + - !Ref DatabaseEngine + - port + ToPort: !FindInMap + - DatabaseMap + - !Ref DatabaseEngine + - port + CidrIp: !Ref PrivateSubnet2Cidr + - IpProtocol: tcp + FromPort: !FindInMap + - DatabaseMap + - !Ref DatabaseEngine + - port + ToPort: !FindInMap + - DatabaseMap + - !Ref DatabaseEngine + - port + CidrIp: !Ref PrivateSubnet3Cidr + SecurityGroupEgress: + - IpProtocol: tcp + FromPort: 22 + ToPort: 22 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 80 + ToPort: 80 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 443 + ToPort: 443 + CidrIp: 0.0.0.0/0 + ArtifactoryS3Bucket: + Type: AWS::S3::Bucket + Properties: + AccessControl: Private + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: AES256 + ArtifactoryS3IAMPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyName: S3BucketPermissions + PolicyDocument: + Version: 2012-10-17 + Statement: + - Sid: S3BucketPermissions + Effect: Allow + Action: + - s3:* + Resource: + - Fn::Join: + - '' + - - !Sub "arn:${AWS::Partition}:s3:::" + - !Ref ArtifactoryS3Bucket + - Fn::Join: + - '' + - - !Sub "arn:${AWS::Partition}:s3:::" + - !Ref ArtifactoryS3Bucket + - "/*" + Roles: + - !Ref ArtifactoryHostRole + ArtifactoryEbsVolume: + Type: AWS::EC2::Volume + Properties: + AvailabilityZone: + !If + - IsMultiAzDatabase + - !Select + - '0' + - !Ref AvailabilityZones + - !Ref DatabasePreferredAz + Encrypted: false + Size: !Ref VolumeSize + Tags: + - Key: Name + Value: !Sub "Artifactory-${AWS::StackName}" + VolumeType: gp2 + DeletionPolicy: Snapshot + UpdateReplacePolicy: Snapshot +Outputs: + S3Bucket: + Value: !Ref ArtifactoryS3Bucket + Description: Actual S3 bucket created for Artifactory + DatabaseDriver: + Value: !FindInMap [DatabaseMap, !Ref DatabaseEngine, Driver] + DatabasePlugin: + Value: !FindInMap [DatabaseMap, !Ref DatabaseEngine, Plugin] + DatabasePluginUrl: + Value: !Sub + - "${MainURL}${PluginVersion}" + - { + MainURL: !FindInMap [DatabaseMap, !Ref DatabaseEngine, PluginURL], + PluginVersion: !FindInMap [DatabaseMap, !Ref DatabaseEngine, Plugin] + } + DatabaseType: + Value: !FindInMap [DatabaseMap, !Ref DatabaseEngine, Name] + DatabaseUrl: + Value: !Sub + - "jdbc:${DatabaseType}://${ArtifactoryDatabaseEndpointAddress}:${port}/${DatabaseName}${extraDatabaseOps}" + - { + DatabaseType: !FindInMap [DatabaseMap, !Ref DatabaseEngine, Name], + ArtifactoryDatabaseEndpointAddress: !GetAtt ArtifactoryDatabase.Endpoint.Address, + port: !FindInMap [DatabaseMap, !Ref DatabaseEngine, port], + extraDatabaseOps: !FindInMap [DatabaseMap, !Ref DatabaseEngine, extraDatabaseOps], + } + XrayMasterDatabaseUrl: + Value: !Sub + - "${ArtifactoryDatabaseEndpointAddress}:${port}/${DatabaseName}?sslmode=disable" + - { + ArtifactoryDatabaseEndpointAddress: !GetAtt ArtifactoryDatabase.Endpoint.Address, + port: !FindInMap [DatabaseMap, !Ref DatabaseEngine, port], + } + XrayDatabaseUrl: + Value: !Sub + - "${ArtifactoryDatabaseEndpointAddress}:${port}/xraydb?sslmode=disable" + - { + ArtifactoryDatabaseEndpointAddress: !GetAtt ArtifactoryDatabase.Endpoint.Address, + port: !FindInMap [DatabaseMap, !Ref DatabaseEngine, port], + } + ProDockerRepo: + Value: !FindInMap + - ReleaseStageMap + - !Ref ReleaseStage + - !FindInMap + - ProductMap + - !Ref ArtifactoryProduct + - RepoName + NginxDockerRepo: + Value: !FindInMap [ReleaseStageMap, !Ref ReleaseStage, NginxDockerRepo] + JavaOpts: + Value: !Sub + - "-Xms${min}g -Xmx${max}g" + - { + min: !FindInMap [JavaOptionstoInstance, !Ref InstanceType, Min], + max: !FindInMap [JavaOptionstoInstance, !Ref InstanceType, Max] + } + DeploymentSize: + Value: !FindInMap [JavaOptionstoInstance, !Ref InstanceType, DeploymentSize] + ArtifactoryEbsVolume: + Value: !Ref ArtifactoryEbsVolume diff --git a/Amazon/artifactory7/v7174/templates/jfrog-artifactory-ec2-existing-vpc.template.yaml b/Amazon/artifactory7/v7174/templates/jfrog-artifactory-ec2-existing-vpc.template.yaml new file mode 100644 index 0000000..8d6c593 --- /dev/null +++ b/Amazon/artifactory7/v7174/templates/jfrog-artifactory-ec2-existing-vpc.template.yaml @@ -0,0 +1,1109 @@ +AWSTemplateFormatVersion: '2010-09-09' +Description: 'JFrog Artifactory Quick Start Deployment into an Existing VPC (qs-1q037efj0)' +Metadata: + QuickStartDocumentation: + EntrypointName: "Launch into an existing VPC" + AWS::CloudFormation::Interface: + ParameterGroups: + - Label: + default: Security configuration + Parameters: + - KeyPairName + - AccessCidr + - RemoteAccessCidr + - Label: + default: Network configuration + Parameters: + - AvailabilityZones + - VpcId + - VpcCidr + - PublicSubnet1Id + - PublicSubnet2Id + - PrivateSubnet1Id + - PrivateSubnet2Id + - PrivateSubnet1Cidr + - PrivateSubnet2Cidr + - ELBScheme + - Label: + default: Bastion configuration + Parameters: + - ProvisionBastionHost + - BastionInstanceType + - BastionOs + - BastionRootVolumeSize + - BastionEnableTcpForwarding + - NumBastionHosts + - BastionEnableX11Forwarding + - Label: + default: Amazon EC2 configuration + Parameters: + - VolumeSize + - InstanceType + - Label: + default: JFrog Artifactory configuration + Parameters: + - ArtifactoryProduct + - ArtifactoryVersion + - NumberOfSecondary + - SmLicenseName + - SmCertName + - ArtifactoryServerName + - MasterKey + - ExtraJavaOptions + - DefaultJavaMemSettings + - Label: + default: Amazon RDS configuration + Parameters: + - DatabaseName + - DatabaseEngine + - DatabaseUser + - DatabasePassword + - DatabaseInstance + - DatabaseAllocatedStorage + - DatabasePreferredAz + - MultiAzDatabase + - Label: + default: AWS Quick Start configuration + Parameters: + - QsS3BucketName + - QsS3KeyPrefix + - QsS3BucketRegion + - Label: + default: JFrog Xray Configuration + Parameters: + - InstallXray + - XrayVersion + - XrayNumberOfInstances + - XrayInstanceType + - XrayDatabaseUser + - XrayDatabasePassword + ParameterLabels: + AvailabilityZones: + default: Availability Zones + KeyPairName: + default: SSH key name + VpcId: + default: VPC ID + VpcCidr: + default: VPC CIDR + PublicSubnet1Id: + default: Public subnet 1 ID + PublicSubnet2Id: + default: Public subnet 2 ID + PrivateSubnet1Id: + default: Private subnet 1 ID + PrivateSubnet2Id: + default: Private subnet 2 ID + PrivateSubnet1Cidr: + default: Private subnet 1 CIDR + PrivateSubnet2Cidr: + default: Private subnet 2 CIDR + AccessCidr: + default: Permitted IP range + RemoteAccessCidr: + default: Remote access CIDR + ELBScheme: + default: Elastic Load Balancing scheme + ProvisionBastionHost: + default: Bastion instance + BastionInstanceType: + default: Bastion instance type + BastionRootVolumeSize: + default: Bastion root volume size + BastionEnableTcpForwarding: + default: Bastion enable TCP forwarding + BastionEnableX11Forwarding: + default: Bastion enable X11 forwarding + BastionOs: + default: Bastion operating system + NumBastionHosts: + default: Number of bastion instances + VolumeSize: + default: EBS root volume size + InstanceType: + default: EC2 instance type + NumberOfSecondary: + default: Secondary instances + ArtifactoryProduct: + default: Artifactory product to install + ArtifactoryVersion: + default: Artifactory version + SmLicenseName: + default: Artifactory licenses secret name + SmCertName: + default: Artifactory certificate secret name + ArtifactoryServerName: + default: Artifactory server name + MasterKey: + default: Master server key + ExtraJavaOptions: + default: Extra Java options + DefaultJavaMemSettings: + default: Default Java memory settings + DatabaseName: + default: Database name + DatabaseEngine: + default: Database engine + DatabaseUser: + default: Database user + DatabasePassword: + default: Database password + DatabaseInstance: + default: Database instance type + DatabaseAllocatedStorage: + default: Database allocated storage + DatabasePreferredAz: + default: Database preferred Availability Zone + MultiAzDatabase: + default: High-availability database + QsS3BucketName: + default: Quick Start S3 bucket name + QsS3KeyPrefix: + default: Quick Start S3 key prefix + QsS3BucketRegion: + default: Quick Start S3 bucket region + InstallXray: + default: Install JFrog Xray + XrayVersion: + default: Version of Xray to install + XrayNumberOfInstances: + default: Number of JFrog Xray instances + XrayInstanceType: + default: Xray instance type + XrayDatabaseUser: + default: Xray Database user + XrayDatabasePassword: + default: Xray Database password +Parameters: + AvailabilityZones: + Description: List of Availability Zones to use for the subnets in the VPC. Two + Availability Zones are used for this deployment. + Type: List + KeyPairName: + Description: Name of an existing key pair, + which allows you to connect securely to your instance after it launches. + This is the key pair you created in your preferred Region. + Type: AWS::EC2::KeyPair::KeyName + VpcId: + Description: ID of your existing VPC (e.g., vpc-0343606e). + Type: "AWS::EC2::VPC::Id" + VpcCidr: + Description: CIDR block for the VPC. + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.0.0/16 + Type: String + PublicSubnet1Id: + Description: ID of the public subnet in Availability Zone 1 of your existing VPC (e.g., subnet-z0376dab). + Type: "AWS::EC2::Subnet::Id" + PublicSubnet2Id: + Description: ID of the public subnet in Availability Zone 2 of your existing VPC (e.g., subnet-a29c3d84). + Type: "AWS::EC2::Subnet::Id" + PrivateSubnet1Id: + Description: ID of the private subnet in Availability Zone 1 of your existing VPC (e.g., subnet-a0246dcd). + Type: "AWS::EC2::Subnet::Id" + PrivateSubnet2Id: + Description: ID of the private subnet in Availability Zone 2 of your existing VPC (e.g., subnet-b58c3d67). + Type: "AWS::EC2::Subnet::Id" + PrivateSubnet1Cidr: + Description: CIDR of the private subnet in Availability Zone 1 of your existing VPC (e.g., 10.0.0.0/19). + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.0.0/19 + Type: String + PrivateSubnet2Cidr: + Description: CIDR of the private subnet in Availability Zone 2 of your existing VPC (e.g., 10.0.32.0/19). + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.32.0/19 + Type: String + AccessCidr: + Description: CIDR IP range that is permitted to access Artifactory. + We recommend that you set this value to a trusted IP range. + For example, you might want to grant only your corporate network access to the software. + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$ + Type: String + RemoteAccessCidr: + Description: Remote CIDR range that allows you to connect to the bastion instance by using SSH. + We recommend that you set this value to a trusted IP range. + For example, you might want to grant specific ranges inside your corporate network SSH access. + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$ + Type: String + ELBScheme: + Description: Choose whether this is internet facing or internal. + AllowedValues: + - internal + - internet-facing + Default: internet-facing + Type: String + ProvisionBastionHost: + Description: Choose Disabled to skip creating a bastion instance. Due to the JFrog Container Registry nodes being + created in private subnets, the default setting of Enabled this is highly recommended. + AllowedValues: + - "Enabled" + - "Disabled" + Default: "Enabled" + Type: String + BastionInstanceType: + Description: Size of the bastion instances. + AllowedValues: + - t3.nano + - t3.micro + - t3.small + - t3.medium + - t3.large + - m5.large + - m5.xlarge + - m5.2xlarge + - m5.4xlarge + Default: "t3.micro" + Type: String + BastionRootVolumeSize: + Description: Size of the root volume on the bastion instances. + Default: 10 + Type: Number + BastionEnableTcpForwarding: + Description: Choose whether to enable TCPForwarding via the bootstrapping of the bastion instance + or not. + AllowedValues: + - "true" + - "false" + Default: "true" + Type: String + BastionEnableX11Forwarding: + Description: Choose true to enable X11 via the bootstrapping of the bastion host. + Setting this value to true will enable X Windows over SSH. + X11 forwarding can be useful, but it is also a security risk, so it's recommended + that you keep the default (false) setting. + AllowedValues: + - "true" + - "false" + Default: "false" + Type: String + BastionOs: + Description: Linux distribution for the Amazon Machine Image (AMI) to be used for the bastion instances. + AllowedValues: + - "Amazon-Linux2-HVM" + - "CentOS-7-HVM" + - "Ubuntu-Server-20.04-LTS-HVM" + - "SUSE-SLES-15-HVM" + Default: "Amazon-Linux2-HVM" + Type: String + NumBastionHosts: + Description: Number of bastion instances to create. + AllowedValues: + - '1' + - '2' + - '3' + - '4' + Default: '1' + Type: String + VolumeSize: + Description: Size in gigabytes of the available storage (min 10GB); the Quick Start will create an + Amazon Elastic Block Store (Amazon EBS) volumes of this size. + Default: 200 + Type: Number + InstanceType: + Description: EC2 type for the Artifactory instances. + AllowedValues: + - m5.large + - m5.xlarge + - m5.2xlarge + - m5.4xlarge + - m5.8xlarge + - m5.12xlarge + - m5.16xlarge + - m5.24xlarge + - m5.metal + - m5d.large + - m5d.xlarge + - m5d.2xlarge + - m5d.4xlarge + - m5d.8xlarge + - m5d.12xlarge + - m5d.16xlarge + - m5d.24xlarge + - m5d.metal + - m5a.large + - m5a.xlarge + - m5a.2xlarge + - m5a.4xlarge + - m5a.8xlarge + - m5a.12xlarge + - m5a.16xlarge + - m5a.24xlarge + ConstraintDescription: Must contain valid instance type. + Default: m5.xlarge + Type: String + NumberOfSecondary: + Description: Number of secondary Artifactory servers to complete your + HA deployment. To align with Artifactory best practices, the minimum number + is two and the maximum is seven. Do not select more instances than you + have licenses for. + AllowedValues: + - 0 + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + - 7 + Default: 2 + Type: Number + ArtifactoryProduct: + Description: JFrog Artifactory product you want to install into an AMI. + AllowedValues: + - JFrog-Artifactory-Pro + - JFrog-Artifactory-Enterprise + - JFrog-Container-Registry + Default: JFrog-Artifactory-Enterprise + Type: String + ArtifactoryVersion: + Description: Version of Artifactory that you want to deploy into the Quick Start. + See the release notes to select the version you want to deploy at + https://www.jfrog.com/confluence/display/RTF/Release+Notes. + AllowedPattern: ^(([0-9]|[1-9][0-9])\.){2}([1-9][0-9]|[0-9])$ + ConstraintDescription: A version that matches X.X.X per Artifactory releases + Default: 7.17.4 + Type: String + SmLicenseName: + Description: Secret name created in AWS Secrets Manager, which contains the Artifactory licenses. + Default: '' + Type: String + SmCertName: + Description: Secret name created in AWS Secrets Manager, which contains the SSL certificate and certificate key. + Default: '' + Type: String + ArtifactoryServerName: + Description: Name of your Artifactory server. Ensure that this matches your certificate. + Type: String + MasterKey: + Description: Master key for the Artifactory cluster. Generate a master key by using the command '$openssl rand -hex 16'. + AllowedPattern: ^[a-zA-Z0-9]+$ + MinLength: '1' + MaxLength: '64' + ConstraintDescription: Only capital or lowercase letters and numbers, with a Max of 64 characters. + NoEcho: 'true' + Type: String + ExtraJavaOptions: + Description: Set Java options to pass to the JVM for Artifactory. For more information, see the Artifactory + system requirements at https://www.jfrog.com/confluence/display/RTF/System+Requirements#SystemRequirements-RecommendedHardware. + Do not add Xms or Xmx settings without disabling DefaultJavaMemSettings. + Default: -Xss256k -XX:+UseG1GC + Type: String + DefaultJavaMemSettings: + Description: Choose false to overwrite the standard memory-calculation options to pass to the Artifactory JVM. + If you plan to overwrite them, ensure they are added to the ExtraJavaOptions to prevent the stack provision from failing. + ConstraintDescription: True or False + AllowedValues: + - "true" + - "false" + Default: "true" + Type: String + DatabaseName: + Description: Name of your database instance. The name must be unique across all instances + owned by your AWS account in the current Region. The database instance identifier is case-insensitive, + but it's stored in lowercase (as in "mydbinstance"). + AllowedPattern: ^[a-zA-Z]([a-zA-Z0-9])+$ + MinLength: '1' + MaxLength: '60' + ConstraintDescription: 1 to 60 alphanumeric characters First character must be a letter. + Default: artdb + Type: String + DatabaseEngine: + Description: Database engine that you want to run, which is currently locked to MySQL. + AllowedValues: + - Postgres + Default: Postgres + Type: String + DatabaseUser: + Description: Login ID for the master user of your database instance. + MinLength: '1' + MaxLength: '16' + AllowedPattern: ^[a-zA-Z]([a-zA-Z0-9])+$ + ConstraintDescription: 1 to 16 alphanumeric characters. First character must be a letter. + Default: artifactory + Type: String + DatabasePassword: + Description: Password for the Artifactory database user. + AllowedPattern: ^[^ \\']+$ + MinLength: '8' + MaxLength: '12' + ConstraintDescription: Must be at least 8 and no more than + 12 characters containing letters and (minimum 1 capital letter), numbers and + symbols. + NoEcho: 'true' + Type: String + DatabaseInstance: + Description: Size of the database to be deployed as part of the Quick Start. + AllowedValues: + - db.m5.large + - db.m5.xlarge + - db.m5.2xlarge + - db.m5.10xlarge + - db.m5.16xlarge + - db.m5.large + - db.m5.xlarge + - db.m5.2xlarge + - db.m5.4xlarge + - db.m5.12xlarge + - db.m5.24xlarge + ConstraintDescription: Must be a valid database Instance Type. + Default: db.m5.large + Type: String + DatabaseAllocatedStorage: + Description: Size in gigabytes of the available storage for the database instance. + MinValue: 5 + MaxValue: 1024 + Default: 10 + Type: Number + DatabasePreferredAz: + Description: Preferred availability zone for Amazon RDS primary instance + Type: String + Default: '' + MultiAzDatabase: + Description: Choose false to create an Amazon RDS instance in a single Availability Zone. + ConstraintDescription: True or False + AllowedValues: + - "true" + - "false" + Default: "true" + Type: String + QsS3BucketName: + Description: S3 bucket name for the Quick Start assets. This string can include + numbers, lowercase letters, and hyphens (-). It cannot start + or end with a hyphen (-). + AllowedPattern: ^[0-9a-z]+([0-9a-z-]*[0-9a-z])*$ + ConstraintDescription: Quick Start bucket name can include numbers, lowercase + letters, and hyphens (-). It cannot start or end with a hyphen (-). + Default: jfrog-aws + 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: artifactory7/latest/ + Type: String + QsS3BucketRegion: + Default: 'us-east-1' + Description: AWS Region where the Quick Start S3 bucket (QSS3BucketName) is hosted. If you use your own bucket, you must specify your own value. + Type: String + InstallXray: + Description: Choose true to install JFrog Xray instance(s). + ConstraintDescription: True or False + AllowedValues: + - "true" + - "false" + Default: "true" + Type: String + XrayVersion: + Description: The version of Xray that you want to deploy into the Quick Start. + AllowedPattern: ^(([0-9]|[1-9][0-9])\.){2}([1-9][0-9]|[0-9])$ + ConstraintDescription: A version that matches X.X.X per Xray releases. + Default: 3.21.2 + Type: String + XrayNumberOfInstances: + Description: The number of Xray instances servers to complete your + HA deployment. The minimum number is one; the maximum is seven. + Do not select more than instances than you have licenses for. + MinValue: 1 + MaxValue: 7 + Default: 1 + Type: Number + XrayInstanceType: + Description: The EC2 instance type for the Xray instances. + AllowedValues: + - c5.2xlarge + - c5.4xlarge + ConstraintDescription: Must contain valid instance type. + Default: c5.2xlarge + Type: String + XrayDatabaseUser: + Description: The login ID for the Xray database user. + MinLength: '1' + MaxLength: '16' + AllowedPattern: ^[a-zA-Z]([a-zA-Z0-9])+$ + ConstraintDescription: 1 to 16 alphanumeric characters. First character must be a letter. + Default: xray + Type: String + XrayDatabasePassword: + Description: The password for the Xray database user. + AllowedPattern: ^[^ \\']+$ + MinLength: '8' + MaxLength: '12' + ConstraintDescription: Must be at least 8 and no more than + 12 characters containing letters and (minimum 1 capital letter), numbers and + symbols. + NoEcho: 'true' + Type: String + +Conditions: + EnableBastion: !Equals [!Ref 'ProvisionBastionHost', 'Enabled'] + IsArtifactory: !Not [!Equals [!Ref ArtifactoryProduct, 'JFrog-Container-Registry']] + HasSecondaryNodes: !Not [!Equals [!Ref NumberOfSecondary, '0']] + DefaultJava: !Equals [!Ref DefaultJavaMemSettings, "true"] + UsingDefaultBucket: !Equals [!Ref QsS3BucketName, 'aws-quickstart'] + EnableXray: !Equals [!Ref InstallXray, 'true'] + SmCertNameNotExists: !Equals [!Ref 'SmCertName', ''] + SmCertNameExists: !Not [!Equals [!Ref 'SmCertName', '']] + +Resources: + BastionRole: + Condition: EnableBastion + Type: "AWS::IAM::Role" + Properties: + AssumeRolePolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Principal: + Service: ec2.amazonaws.com + Action: sts:AssumeRole + Policies: + - PolicyName: QSBucketAccess + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: s3:GetObject + Resource: !Sub "arn:${AWS::Partition}:s3:::${QsS3BucketName}/*" + - Effect: Allow + Action: + - logs:CreateLogStream + - logs:GetLogEvents + - logs:PutLogEvents + - logs:DescribeLogGroups + - logs:DescribeLogStreams + - logs:PutRetentionPolicy + - logs:PutMetricFilter + - logs:CreateLogGroup + Resource: !Sub "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:*:*" + - Effect: Allow + Action: + - ec2:AssociateAddress + - ec2:DescribeAddresses + Resource: "*" + BastionStack: + Condition: EnableBastion + Type: AWS::CloudFormation::Stack + Properties: + TemplateURL: !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QsS3KeyPrefix}submodules/quickstart-linux-bastion/templates/linux-bastion.template + - S3Bucket: !If [UsingDefaultBucket, !Sub '${QsS3BucketName}-${AWS::Region}', !Ref 'QsS3BucketName'] + S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref 'QsS3BucketRegion'] + Parameters: + VPCID: !Ref VpcId + PublicSubnet1ID: !Ref PublicSubnet1Id + PublicSubnet2ID: !Ref PublicSubnet2Id + KeyPairName: !Ref KeyPairName + QSS3BucketName: !Ref QsS3BucketName + QSS3KeyPrefix: !Sub '${QsS3KeyPrefix}submodules/quickstart-linux-bastion/' + QSS3BucketRegion: !Ref QsS3BucketRegion + RemoteAccessCIDR: !Ref RemoteAccessCidr + BastionInstanceType: !Ref BastionInstanceType + RootVolumeSize: !Ref BastionRootVolumeSize + BastionAMIOS: !Ref BastionOs + EnableTCPForwarding: !Ref BastionEnableTcpForwarding + EnableX11Forwarding: !Ref BastionEnableX11Forwarding + AlternativeIAMRole: !Ref BastionRole + NumBastionHosts: !Ref NumBastionHosts + + ArtifactoryCoreInfraStack: + Type: AWS::CloudFormation::Stack + Properties: + TemplateURL: !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QsS3KeyPrefix}templates/jfrog-artifactory-core-infrastructure.template.yaml + - S3Bucket: !If [UsingDefaultBucket, !Sub '${QsS3BucketName}-${AWS::Region}', !Ref 'QsS3BucketName'] + S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref 'QsS3BucketRegion'] + Parameters: + AvailabilityZones: + Fn::Join: + - ',' + - Ref: AvailabilityZones + VpcId: !Ref VpcId + VpcCidr: !Ref VpcCidr + PrivateSubnet1Cidr: !Ref PrivateSubnet1Cidr + PrivateSubnet2Cidr: !Ref PrivateSubnet2Cidr + PrivateSubnet3Cidr: !Ref PrivateSubnet2Cidr # This should end up in no new rule but required for EKS + SubnetIds: !Join [",", [!Ref PrivateSubnet1Id, !Ref PrivateSubnet2Id]] + DatabaseAllocatedStorage: !Ref DatabaseAllocatedStorage + DatabasePreferredAz: !Ref DatabasePreferredAz + MultiAzDatabase: !Ref MultiAzDatabase + DatabaseEngine: !Ref DatabaseEngine + DatabaseUser: !Ref DatabaseUser + DatabasePassword: !Ref DatabasePassword + DatabaseInstance: !Ref DatabaseInstance + DatabaseName: !Ref DatabaseName + InstanceType: !Ref InstanceType + ArtifactoryHostRole: !Ref ArtifactoryHostRole + VolumeSize: !Ref VolumeSize + ArtifactoryElb: + Type: AWS::ElasticLoadBalancingV2::LoadBalancer + Properties: + IpAddressType: ipv4 + Scheme: !Ref ELBScheme + Subnets: + - !Ref PublicSubnet1Id + - !Ref PublicSubnet2Id + Type: network + # Type: application + ArtifactorySslTargetGroup: + Type: AWS::ElasticLoadBalancingV2::TargetGroup + Properties: + HealthCheckEnabled: True + HealthCheckIntervalSeconds: 30 + HealthCheckProtocol: TCP + HealthCheckTimeoutSeconds: 10 + HealthyThresholdCount: 3 + HealthCheckPort: "8082" + Port: 443 + Protocol: TCP + TargetType: instance + UnhealthyThresholdCount: 3 + VpcId: !Ref VpcId + ArtifactoryTargetGroup: + Type: AWS::ElasticLoadBalancingV2::TargetGroup + Properties: + HealthCheckEnabled: True + HealthCheckIntervalSeconds: 30 + HealthCheckProtocol: TCP + HealthCheckTimeoutSeconds: 10 + HealthyThresholdCount: 3 + HealthCheckPort: "8082" + Port: 80 + Protocol: TCP + TargetType: instance + UnhealthyThresholdCount: 3 + VpcId: !Ref VpcId + ArtifactorySslElbListener: + Type: AWS::ElasticLoadBalancingV2::Listener + Properties: + DefaultActions: + - TargetGroupArn: !Ref ArtifactorySslTargetGroup + Type: forward + LoadBalancerArn: !Ref ArtifactoryElb + Port: 443 + Protocol: TCP + ArtifactoryElbListener: + Type: AWS::ElasticLoadBalancingV2::Listener + Condition: SmCertNameNotExists + Properties: + DefaultActions: + - TargetGroupArn: !Ref ArtifactoryTargetGroup + Type: forward + LoadBalancerArn: !Ref ArtifactoryElb + Port: 80 + Protocol: TCP + ArtifactoryInternalElb: + Type: AWS::ElasticLoadBalancingV2::LoadBalancer + Properties: + IpAddressType: ipv4 + # Name: ArtifactoryInternal-ELB + Scheme: internal + Subnets: + - !Ref PrivateSubnet1Id + - !Ref PrivateSubnet2Id + Type: network + ArtifactoryInternalTargetGroup: + Type: AWS::ElasticLoadBalancingV2::TargetGroup + Properties: + HealthCheckEnabled: True + HealthCheckIntervalSeconds: 30 + HealthCheckProtocol: TCP + HealthCheckTimeoutSeconds: 10 + HealthyThresholdCount: 3 + HealthCheckPort: "8082" + # Name: artifactory-internal-http + Port: 80 + Protocol: TCP + TargetType: instance + UnhealthyThresholdCount: 3 + VpcId: !Ref VpcId + ArtifactoryInternalElbListener: + Type: AWS::ElasticLoadBalancingV2::Listener + Properties: + DefaultActions: + - TargetGroupArn: !Ref ArtifactoryInternalTargetGroup + Type: forward + LoadBalancerArn: !Ref ArtifactoryInternalElb + Port: 80 + Protocol: TCP + ArtifactoryEc2Sg: + Type: AWS::EC2::SecurityGroup + Properties: + Tags: + - Key: Name + Value: !Sub ${ArtifactoryProduct}-ec2-instances-sg + GroupDescription: SG for EC2 instances (also permits access using SSH from the bastion host) + VpcId: !Ref VpcId + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: 22 + ToPort: 22 + CidrIp: !Ref VpcCidr + - IpProtocol: tcp + FromPort: 80 + ToPort: 80 + CidrIp: !Ref VpcCidr + - IpProtocol: tcp + FromPort: 80 + ToPort: 80 + CidrIp: !Ref AccessCidr + - IpProtocol: tcp + FromPort: 443 + ToPort: 443 + CidrIp: !Ref AccessCidr + - IpProtocol: tcp + FromPort: 443 + ToPort: 443 + CidrIp: !Ref VpcCidr + - IpProtocol: tcp + FromPort: 8081 + ToPort: 8082 + CidrIp: !Ref VpcCidr + - IpProtocol: tcp + FromPort: 8046 + ToPort: 8046 + CidrIp: !Ref VpcCidr + SecurityGroupEgress: + - IpProtocol: "-1" + CidrIp: 0.0.0.0/0 + ArtifactoryHostRole: + Type: AWS::IAM::Role + Properties: + Path: / + AssumeRolePolicyDocument: + Statement: + - Action: + - 'sts:AssumeRole' + Principal: + Service: + - ec2.amazonaws.com + Effect: Allow + Version: 2012-10-17 + ManagedPolicyArns: + - !Sub 'arn:${AWS::Partition}:iam::aws:policy/service-role/AmazonEC2RoleforSSM' + Policies: + - PolicyName: "JFrogAMI-policy" + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: "Allow" + Action: "ec2:Describe*" + Resource: "*" + - Effect: "Allow" + Action: "ec2:AttachVolume" + Resource: "*" + - Effect: "Allow" + Action: "ec2:DetachVolume" + Resource: "*" + - Effect: "Allow" + Action: + - "s3:GetObject" + - "s3:ListObject" + - "s3:ListBucket" + Resource: "*" + - PolicyName: 'CloudWatch-policy' + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: "Allow" + Action: + - "logs:CreateLogGroup" + - "logs:CreateLogStream" + - "logs:PutLogEvents" + - "logs:DescribeLogStreams" + Resource: "arn:aws:logs:*:*:*" + - Effect: "Allow" + Action: + - "s3:GetObject" + Resource: "*" + - PolicyName: 'SecretsMaanger-policy' + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: "Allow" + Action: + - "secretsmanager:GetSecretValue" + Resource: "arn:aws:secretsmanager:*:*:secret:*" + ArtifactoryHostProfile: + Type: AWS::IAM::InstanceProfile + Properties: + InstanceProfileName: !Ref ArtifactoryHostRole + Roles: + - !Ref ArtifactoryHostRole + Path: / + ArtifactoryPrimary: + Type: AWS::CloudFormation::Stack + Properties: + TemplateURL: !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QsS3KeyPrefix}templates/jfrog-artifactory-ec2-instance.template.yaml + - S3Bucket: !If [UsingDefaultBucket, !Sub '${QsS3BucketName}-${AWS::Region}', !Ref 'QsS3BucketName'] + S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref 'QsS3BucketRegion'] + Parameters: + PrivateSubnetIds: !Join [',', [!Ref PrivateSubnet1Id]] + MinScalingNodes: '1' # Always have 1 PrimaryNode + MaxScalingNodes: '1' # Always have 1 PrimaryNode + DeploymentTag: !If [IsArtifactory, "ArtifactoryPrimary", "JcrPrimary"] + HostRole: !Ref ArtifactoryHostRole + QsS3BucketName: !Ref QsS3BucketName + QsS3KeyPrefix: !Ref QsS3KeyPrefix + QsS3Uri: !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QsS3KeyPrefix} + - S3Bucket: !If + - UsingDefaultBucket + - !Sub 'aws-quickstart-${AWS::Region}' + - !Ref 'QsS3BucketName' + S3Region: !If + - UsingDefaultBucket + - !Ref 'AWS::Region' + - !Ref 'QsS3BucketRegion' + ArtifactoryProduct: !Ref ArtifactoryProduct + ArtifactoryLicensesSecretName: !Ref SmLicenseName + ArtifactoryServerName: !Ref ArtifactoryServerName + EnableSSL: !If [SmCertNameExists, true, false] + Certificate: !If [SmCertNameExists, !Sub '{{resolve:secretsmanager:${SmCertName}:SecretString:Certificate}}', ''] + CertificateKey: !If [SmCertNameExists, !Sub '{{resolve:secretsmanager:${SmCertName}:SecretString:CertificateKey}}', ''] + CertificateDomain: !If [SmCertNameExists, !Sub '{{resolve:secretsmanager:${SmCertName}:SecretString:CertificateDomain}}', ''] + ArtifactoryS3Bucket: !GetAtt ArtifactoryCoreInfraStack.Outputs.S3Bucket + DatabaseUrl: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseUrl + DatabaseDriver: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseDriver + DatabasePlugin: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabasePlugin + DatabasePluginUrl: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabasePluginUrl + DatabaseType: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseType + DatabaseUser: !Ref DatabaseUser + DatabasePassword: !Ref DatabasePassword + ArtifactoryPrimary: true + MasterKey: !Ref MasterKey + ExtraJavaOptions: !If [DefaultJava, !Sub "${ArtifactoryCoreInfraStack.Outputs.JavaOpts} ${ExtraJavaOptions}", !Ref ExtraJavaOptions] + ArtifactoryVersion: !Ref ArtifactoryVersion + KeyPairName: !Ref KeyPairName + HostProfile: !Ref ArtifactoryHostProfile + SecurityGroups: !Ref ArtifactoryEc2Sg + InstanceType: !Ref InstanceType + PrimaryVolume: !GetAtt ArtifactoryCoreInfraStack.Outputs.ArtifactoryEbsVolume + VolumeSize: !Ref VolumeSize + TargetGroupARN: !Ref ArtifactoryTargetGroup + SSLTargetGroupARN: !Ref ArtifactorySslTargetGroup + InternalTargetGroupARN: !Ref ArtifactoryInternalTargetGroup + + ArtifactorySecondary: + Condition: HasSecondaryNodes + DependsOn: ArtifactoryPrimary + Type: AWS::CloudFormation::Stack + Properties: + TemplateURL: !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QsS3KeyPrefix}templates/jfrog-artifactory-ec2-instance.template.yaml + - S3Bucket: !If [UsingDefaultBucket, !Sub '${QsS3BucketName}-${AWS::Region}', !Ref 'QsS3BucketName'] + S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref 'QsS3BucketRegion'] + Parameters: + PrivateSubnetIds: !Join [',', [!Ref PrivateSubnet1Id, !Ref PrivateSubnet2Id]] + MinScalingNodes: !Ref NumberOfSecondary + MaxScalingNodes: !Ref NumberOfSecondary + DeploymentTag: ArtifactorySecondary + HostRole: !Ref ArtifactoryHostRole + ArtifactoryProduct: !Ref ArtifactoryProduct + ArtifactoryLicensesSecretName: !Ref SmLicenseName + ArtifactoryServerName: !Ref ArtifactoryServerName + EnableSSL: !If [SmCertNameExists, true, false] + Certificate: !If [SmCertNameExists, !Sub '{{resolve:secretsmanager:${SmCertName}:SecretString:Certificate}}', ''] + CertificateKey: !If [SmCertNameExists, !Sub '{{resolve:secretsmanager:${SmCertName}:SecretString:CertificateKey}}', ''] + CertificateDomain: !If [SmCertNameExists, !Sub '{{resolve:secretsmanager:${SmCertName}:SecretString:CertificateDomain}}', ''] + ArtifactoryS3Bucket: !GetAtt ArtifactoryCoreInfraStack.Outputs.S3Bucket + DatabaseUrl: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseUrl + DatabaseDriver: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseDriver + DatabasePlugin: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabasePlugin + DatabasePluginUrl: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabasePluginUrl + DatabaseType: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseType + DatabaseUser: !Ref DatabaseUser + DatabasePassword: !Ref DatabasePassword + ArtifactoryPrimary: false + MasterKey: !Ref MasterKey + ExtraJavaOptions: !If [DefaultJava, !Sub "${ArtifactoryCoreInfraStack.Outputs.JavaOpts} ${ExtraJavaOptions}", !Ref ExtraJavaOptions] + ArtifactoryVersion: !Ref ArtifactoryVersion + KeyPairName: !Ref KeyPairName + HostProfile: !Ref ArtifactoryHostProfile + SecurityGroups: !Ref ArtifactoryEc2Sg + InstanceType: !Ref InstanceType + PrimaryVolume: !GetAtt ArtifactoryCoreInfraStack.Outputs.ArtifactoryEbsVolume + VolumeSize: !Ref VolumeSize + TargetGroupARN: !Ref ArtifactoryTargetGroup + SSLTargetGroupARN: !Ref ArtifactorySslTargetGroup + InternalTargetGroupARN: !Ref ArtifactoryInternalTargetGroup + QsS3BucketName: !Ref QsS3BucketName + QsS3KeyPrefix: !Ref QsS3KeyPrefix + QsS3Uri: !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QsS3KeyPrefix} + - S3Bucket: !If + - UsingDefaultBucket + - !Sub 'aws-quickstart-${AWS::Region}' + - !Ref 'QsS3BucketName' + S3Region: !If + - UsingDefaultBucket + - !Ref 'AWS::Region' + - !Ref 'QsS3BucketRegion' + XrayHostRole: + Condition: EnableXray + Type: AWS::IAM::Role + Properties: + Path: / + AssumeRolePolicyDocument: + Statement: + - Action: + - 'sts:AssumeRole' + Principal: + Service: + - ec2.amazonaws.com + Effect: Allow + Version: 2012-10-17 + ManagedPolicyArns: + - !Sub 'arn:${AWS::Partition}:iam::aws:policy/service-role/AmazonEC2RoleforSSM' + Policies: + - PolicyName: "JFrogAMI-policy" + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: "Allow" + Action: "ec2:Describe*" + Resource: "*" + - Effect: "Allow" + Action: "ec2:AttachVolume" + Resource: "*" + - Effect: "Allow" + Action: "ec2:DetachVolume" + Resource: "*" + - Effect: "Allow" + Action: + - "s3:GetObject" + - "s3:ListObject" + - "s3:ListBucket" + Resource: "*" + - PolicyName: 'CloudWatch-policy' + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: "Allow" + Action: + - "logs:CreateLogGroup" + - "logs:CreateLogStream" + - "logs:PutLogEvents" + - "logs:DescribeLogStreams" + Resource: "arn:aws:logs:*:*:*" + - Effect: "Allow" + Action: + - "s3:GetObject" + Resource: "*" + XrayHostProfile: + Condition: EnableXray + Type: AWS::IAM::InstanceProfile + Properties: + InstanceProfileName: !Ref XrayHostRole + Roles: + - !Ref XrayHostRole + Path: / + XrayExistingVpcStack: + Condition: EnableXray + DependsOn: ArtifactoryPrimary + Type: AWS::CloudFormation::Stack + Properties: + TemplateURL: !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QsS3KeyPrefix}templates/jfrog-xray-ec2-instance.template.yaml + - S3Bucket: !If [UsingDefaultBucket, !Sub '${QsS3BucketName}-${AWS::Region}', !Ref 'QsS3BucketName'] + S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref 'QsS3BucketRegion'] + Parameters: + PrivateSubnet1Id: !Ref PrivateSubnet1Id + PrivateSubnet2Id: !Ref PrivateSubnet2Id + KeyPairName: !Ref KeyPairName + MinScalingNodes: !Ref XrayNumberOfInstances + MaxScalingNodes: !Ref XrayNumberOfInstances + DeploymentTag: 'xray' + ArtifactoryProduct: !Ref ArtifactoryProduct + QsS3BucketName: !Ref QsS3BucketName + QsS3KeyPrefix: !Ref QsS3KeyPrefix + QsS3Uri: !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QsS3KeyPrefix} + - S3Bucket: !If + - UsingDefaultBucket + - !Sub 'aws-quickstart-${AWS::Region}' + - !Ref 'QsS3BucketName' + S3Region: !If + - UsingDefaultBucket + - !Ref 'AWS::Region' + - !Ref 'QsS3BucketRegion' + DatabaseDriver: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseDriver + DatabaseType: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseType + DatabaseUser: !Ref DatabaseUser + DatabasePassword: !Ref DatabasePassword + MasterKey: !Ref MasterKey + SecurityGroups: !Ref ArtifactoryEc2Sg + VolumeSize: !Ref VolumeSize + ExtraJavaOptions: !GetAtt ArtifactoryCoreInfraStack.Outputs.JavaOpts + XrayInstanceType: !Ref XrayInstanceType + JfrogInternalUrl: !Sub "http://${ArtifactoryInternalElb.DNSName}" + XrayDatabaseUser: !Ref XrayDatabaseUser + XrayDatabasePassword: !Ref XrayDatabasePassword + XrayMasterDatabaseUrl: !GetAtt ArtifactoryCoreInfraStack.Outputs.XrayMasterDatabaseUrl + XrayDatabaseUrl: !GetAtt ArtifactoryCoreInfraStack.Outputs.XrayDatabaseUrl + XrayVersion: !Ref XrayVersion + XrayHostRole: !Ref XrayHostRole + XrayHostProfile: !Ref XrayHostProfile +Outputs: + ArtifactoryUrl: + Description: URL of the ELB to access Artifactory + Value: !If [SmCertNameExists, !Sub "https://${ArtifactoryElb.DNSName}", !Sub "http://${ArtifactoryElb.DNSName}"] + Export: + Name: !Sub '${AWS::StackName}-ArtifactoryUrl' + ArtifactoryInternalUrl: + Description: URL of the internal ELB to access Artifactory + Value: !Sub "http://${ArtifactoryInternalElb.DNSName}" + Export: + Name: !Sub '${AWS::StackName}-ArtifactoryInternalUrl' + DatabaseType: + Description: Type of database + Value: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseType + Export: + Name: !Sub '${AWS::StackName}-DatabaseType' + DatabaseDriver: + Description: Database driver + Value: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseDriver + Export: + Name: !Sub '${AWS::StackName}-DatabaseDriver' + DatabaseUrl: + Description: Database driver + Value: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseUrl + Export: + Name: !Sub '${AWS::StackName}-DatabaseUrl' + ArtifactoryTargetGroup: + Description: Artifactory target group + Value: !Ref ArtifactoryTargetGroup + Export: + Name: !Sub '${AWS::StackName}-ArtifactoryTargetGroup' + ArtifactorySslTargetGroup: + Description: Artifactory SSL target group + Value: !Ref ArtifactorySslTargetGroup + Export: + Name: !Sub '${AWS::StackName}-ArtifactorySslTargetGroup' + ArtifactoryEc2Sg: + Description: Artifactory EC2 sercurity group + Value: !Ref ArtifactoryEc2Sg + Export: + Name: !Sub '${AWS::StackName}-ArtifactoryEc2Sg' + BastionIp: + Value: !If + - EnableBastion + - !GetAtt BastionStack.Outputs.EIP1 + - "" + XrayMasterDatabaseUrl: + Description: Database driver + Value: !GetAtt ArtifactoryCoreInfraStack.Outputs.XrayMasterDatabaseUrl + Export: + Name: !Sub '${AWS::StackName}-XrayMasterDatabaseUrl' + XrayDatabaseUrl: + Description: Database driver + Value: !GetAtt ArtifactoryCoreInfraStack.Outputs.XrayDatabaseUrl + Export: + Name: !Sub '${AWS::StackName}-XrayDatabaseUrl' diff --git a/Amazon/artifactory7/v7174/templates/jfrog-artifactory-ec2-instance.template.yaml b/Amazon/artifactory7/v7174/templates/jfrog-artifactory-ec2-instance.template.yaml new file mode 100644 index 0000000..1c7e1ee --- /dev/null +++ b/Amazon/artifactory7/v7174/templates/jfrog-artifactory-ec2-instance.template.yaml @@ -0,0 +1,433 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: "Deploys the EC2 Autoscaling, LaunchConfig and Instance for Artifactory (qs-1qpmmjh5o)" +Parameters: + PrivateSubnetIds: + Type: List + MinScalingNodes: + Type: Number + MaxScalingNodes: + Type: Number + DeploymentTag: + Type: String + HostRole: + Type: String + ArtifactoryProduct: + Description: JFrog Artifactory product you want to install into an AMI. + AllowedValues: + - JFrog-Artifactory-Pro + - JFrog-Artifactory-Enterprise + - JFrog-Container-Registry + Default: JFrog-Artifactory-Enterprise + Type: String + QsS3BucketName: + Type: String + QsS3KeyPrefix: + Type: String + QsS3Uri: + Type: String + ArtifactoryLicensesSecretName: + Type: String + ArtifactoryServerName: + Type: String + Certificate: + Type: String + CertificateKey: + Type: String + NoEcho: 'true' + CertificateDomain: + Type: String + EnableSSL: + Type: String + 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 + PrimaryVolume: + Type: String + VolumeSize: + Type: Number + UserDataDirectory: + Description: Directory to store Artifactory data. Can be used to store data (via symlink) in detachable volume + Type: String + Default: '/artifactory-user-data' + +# 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: + CentOS7HVM: "ami-00a5245b4816c38e6" + ap-northeast-2: + CentOS7HVM: "ami-00dc207f8ba6dc919" + ap-south-1: + CentOS7HVM: "ami-0ad42f4f66f6c1cc9" + ap-southeast-1: + CentOS7HVM: "ami-05b3bcf7f311194b3" + ap-southeast-2: + CentOS7HVM: "ami-02fd0b06f06d93dfc" + ca-central-1: + CentOS7HVM: "ami-07423fb63ea0a0930" + eu-central-1: + CentOS7HVM: "ami-0cfbf4f6db41068ac" + eu-west-1: + CentOS7HVM: "ami-08935252a36e25f85" + sa-east-1: + CentOS7HVM: "ami-05145e0b28ad8e0b2" + us-east-1: + CentOS7HVM: "ami-0affd4508a5d2481b" + us-east-2: + CentOS7HVM: "ami-01e36b7901e884a10" + us-west-1: + CentOS7HVM: "ami-098f55b4287a885ba" + us-west-2: + CentOS7HVM: "ami-0bc06212a56393ee1" + ArtifactoryProductMap: + JFrog-Container-Registry: + "7153": "Jcr7153" + flavor: "jcr" + haEabled: false + product: "jcr" + JFrog-Artifactory-Enterprise: + "7153": "Artifactory7153" + flavor: "pro" + haEabled: true + product: "artifactory" + JFrog-Artifactory-Pro: + "7153": "Artifactory7153" + flavor: "pro" + haEabled: false + product: "artifactory" + +Conditions: + IsSecondary: !Equals [!Ref ArtifactoryPrimary, 'false'] + +Resources: + ArtifactoryScalingGroup: + Type: AWS::AutoScaling::AutoScalingGroup + Properties: + LaunchConfigurationName: !Ref ArtifactoryLaunchConfiguration + VPCZoneIdentifier: !Ref PrivateSubnetIds + MinSize: !Ref MinScalingNodes + MaxSize: !Ref MaxScalingNodes + Cooldown: '300' + DesiredCapacity: !Ref MinScalingNodes + TargetGroupARNs: + - !Ref TargetGroupARN + - !Ref SSLTargetGroupARN + - !Ref InternalTargetGroupARN + HealthCheckType: ELB + HealthCheckGracePeriod: 1800 + Tags: + - Key: Name + Value: !Ref DeploymentTag + PropagateAtLaunch: true + - Key: ArtifactoryVersion + Value: !Ref ArtifactoryVersion + PropagateAtLaunch: true + TerminationPolicies: + - OldestInstance + - Default + CreationPolicy: + ResourceSignal: + Count: !Ref MinScalingNodes + Timeout: PT60M + + ArtifactoryLaunchConfiguration: + Type: AWS::AutoScaling::LaunchConfiguration + Metadata: + AWS::CloudFormation::Authentication: + S3AccessCreds: + type: S3 + roleName: + - !Ref HostRole # !Ref ArtifactoryHostRole + buckets: + - !Ref QsS3BucketName + AWS::CloudFormation::Init: + configSets: + jfrog_ami_setup: + - "config-cloudwatch" + - "config-ansible-art-ami" + - "config-artifactory-primary" + - "secure-artifactory" + artifactory_install: + - "config-cloudwatch" + - "config-artifactory-primary" + - "secure-artifactory" + config-cloudwatch: + files: + /root/cloudwatch.conf: + content: | + [general] + state_file = /var/awslogs/state/agent-state + + [/var/log/messages] + file = /var/log/messages + log_group_name = /artifactory/instances/{instance_id} + log_stream_name = /var/log/messages/ + datetime_format = %b %d %H:%M:%S + + [/var/log/jfrog-ami-setup.log] + file = /var/log/messages + log_group_name = /artifactory/instances/{instance_id} + log_stream_name = /var/log/jfrog-ami-setup.log + datetime_format = %b %d %H:%M:%S + + [/var/log/jfrog-ami-artifactory.log] + file = /var/log/messages + log_group_name = /artifactory/instances/{instance_id} + log_stream_name = /var/log/jfrog-ami-artifactory.log + datetime_format = %b %d %H:%M:%S + mode: "0400" + 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: false + artifactory_flavour: "pro" + artifactory_ha_enabled: false + artifactory_tar: "https://releases.jfrog.io/artifactory/artifactory-pro/org/artifactory/pro/jfrog-artifactory-pro/${ArtifactoryVersion}/jfrog-artifactory-pro-${ArtifactoryVersion}-linux.tar.gz" + artifactory_version: ${ArtifactoryVersion} + db_download_url: "https://jdbc.postgresql.org/download/postgresql-42.2.12.jar" + db_type: "postgresql" + db_driver: "org.postgresql.Driver" + mode: "0400" + config-artifactory-primary: + files: + /root/attach_volume.sh: + content: !Sub | + #!/usr/bin/env bash + IS_PRIMARY="${ArtifactoryPrimary}" + + if [[ $IS_PRIMARY != "true" ]]; then + echo 'Not primary node. Skipping EBS volume attachment.' + lsblk # debug + exit 0 + fi + + echo "Using primary volume ID ${PrimaryVolume}" + VOLUME_ID="${PrimaryVolume}" + echo "VOLUME_ID: $VOLUME_ID" + if [[ -z "$VOLUME_ID" ]]; then + echo 'Invalid $VOLUME_ID' + exit 1 + fi + + # Get instance id from AWS + INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id) + + # Attach the volume created by another CFT + # the device name should become /dev/nvme1n1 + # See: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nvme-ebs-volumes.html + echo "Attaching volume $VOLUME_ID to instance $INSTANCE_ID" + /var/awslogs/bin/aws ec2 attach-volume --volume-id $VOLUME_ID --instance-id $INSTANCE_ID --device /dev/xvdf --region ${AWS::Region} + + echo "Wait for volume $VOLUME_ID to attach" + sleep 30 # Give volume time to attach + lsblk # debug + mode: "0770" + /root/.jfrog_ami/artifactory.yml: + content: !Sub + - | + # Base install for Artifactory + - import_playbook: site-artifactory.yml + vars: + artifactory_product: ${product} + artifactory_flavour: ${flavor} + artifactory_ha_enabled: ${ha_enabled} + artifactory_is_primary: ${ArtifactoryPrimary} + artifactory_server_name: ${ArtifactoryServerName} + server_name: ${ArtifactoryServerName}.${CertificateDomain} + use_custom_data_directory: true + custom_data_directory: "${UserDataDirectory}" + s3_region: ${AWS::Region} + 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} + 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: ${DatabasePassword} + artifactory_java_db_drivers: + - name: ${DatabasePlugin} + url: ${DatabasePluginUrl} + owner: artifactory + group: artifactory + product_id: 'CloudFormation_SP_EC2/1.0.0' + - flavor: !FindInMap [ArtifactoryProductMap, !Ref ArtifactoryProduct, flavor] + ha_enabled: !FindInMap [ArtifactoryProductMap, !Ref ArtifactoryProduct, haEabled] + product: !FindInMap [ArtifactoryProductMap, !Ref ArtifactoryProduct, product] + mode: "0400" + /root/.vault_pass.txt: + content: !Sub | + ${DatabasePassword} + 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: + KeyName: !Ref KeyPairName + IamInstanceProfile: !Ref HostProfile + ImageId: !FindInMap + - AWSAMIRegionMap + - !Ref AWS::Region + - 'CentOS7HVM' + SecurityGroups: + - !Ref SecurityGroups + BlockDeviceMappings: + !If + - IsSecondary + - - DeviceName: /dev/xvda + Ebs: + VolumeSize: !Ref VolumeSize + VolumeType: gp2 + DeleteOnTermination: true + Encrypted: true + - !Ref AWS::NoValue + InstanceType: !Ref InstanceType + 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} + + # Update OS + yum update -y + + # Install git + yum install -y epel-release git policycoreutils-python + + yum update --security -y 2>&1 | tee /var/log/userdata.yum_security_update.log + + yum install -y jq 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 + + pip install awscli 2>&1 | tee /var/log/userdata.awscli_install.log + + pip install ansible 2>&1 | tee /var/log/userdata.ansible_install.log + + mkdir ~/.jfrog_ami + + aws s3 --region ${AWS::Region} sync s3://${QsS3BucketName}/${QsS3KeyPrefix}cloudInstallerScripts/ ~/.jfrog_ami/ || cfn_fail + + setsebool httpd_can_network_connect 1 -P + + # 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 + + cfn-init -v --stack ${AWS::StackName} --resource ArtifactoryLaunchConfiguration --configsets jfrog_ami_setup --region ${AWS::Region} || cfn_fail + + # Setup CloudWatch Agent + curl https://s3.amazonaws.com/aws-cloudwatch/downloads/latest/awslogs-agent-setup.py -O + chmod +x ./awslogs-agent-setup.py + ./awslogs-agent-setup.py -n -r ${AWS::Region} -c /root/cloudwatch.conf 2>&1 | tee /var/log/userdata.cloudwatch_agent_install.log + + /root/attach_volume.sh || cfn_fail + + ansible-galaxy collection install community.general ansible.posix + + aws secretsmanager get-secret-value --secret-id ${ArtifactoryLicensesSecretName} --region ${AWS::Region} | jq -r '{"artifactory_licenses":(.SecretString | fromjson )}' > ~/.jfrog_ami/licenses.json || cfn_fail + + ansible-playbook /root/.jfrog_ami/jfrog-ami-setup.yml --vault-id /root/.vault_pass.txt 2>&1 | tee /var/log/jfrog-ami-setup.log || cfn_fail + ansible-playbook /root/.jfrog_ami/artifactory.yml -e "@~/.jfrog_ami/licenses.json" --vault-id /root/.vault_pass.txt 2>&1 | tee /var/log/jfrog-ami-artifactory.log || cfn_fail + + rm -rf /root/.secureit.sh + + cfn_success &> /var/log/cfn_success.log + cfn_success || cfn_fail diff --git a/Amazon/artifactory7/v7174/templates/jfrog-artifactory-ec2-master.template.yaml b/Amazon/artifactory7/v7174/templates/jfrog-artifactory-ec2-master.template.yaml new file mode 100644 index 0000000..3556572 --- /dev/null +++ b/Amazon/artifactory7/v7174/templates/jfrog-artifactory-ec2-master.template.yaml @@ -0,0 +1,612 @@ +AWSTemplateFormatVersion: '2010-09-09' +Description: 'JFrog Artifactory Quick Start Deployment (qs-1qpmmjh2f)' +Metadata: + QuickStartDocumentation: + EntrypointName: "Launch into a new VPC" + AWS::CloudFormation::Interface: + ParameterGroups: + - Label: + default: Security configuration + Parameters: + - KeyPairName + - AccessCidr + - RemoteAccessCidr + - Label: + default: Network configuration + Parameters: + - AvailabilityZones + - VpcCidr + - PrivateSubnet1Cidr + - PrivateSubnet2Cidr + - PublicSubnet1Cidr + - PublicSubnet2Cidr + - Label: + default: Bastion configuration + Parameters: + - ProvisionBastionHost + - BastionInstanceType + - BastionOs + - BastionRootVolumeSize + - BastionEnableTcpForwarding + - NumBastionHosts + - BastionEnableX11Forwarding + - Label: + default: Amazon EC2 configuration + Parameters: + - VolumeSize + - InstanceType + - Label: + default: JFrog Artifactory configuration + Parameters: + - ArtifactoryProduct + - ArtifactoryVersion + - NumberOfSecondary + - SmLicenseName + - SmCertName + - ArtifactoryServerName + - MasterKey + - ExtraJavaOptions + - DefaultJavaMemSettings + - Label: + default: Amazon RDS configuration + Parameters: + - DatabaseName + - DatabaseEngine + - DatabaseUser + - DatabasePassword + - DatabaseInstance + - DatabaseAllocatedStorage + - DatabasePreferredAz + - MultiAzDatabase + - Label: + default: AWS Quick Start configuration + Parameters: + - QsS3BucketName + - QsS3KeyPrefix + - QsS3BucketRegion + - Label: + default: JFrog Xray Configuration + Parameters: + - InstallXray + - XrayVersion + - XrayNumberOfInstances + - XrayInstanceType + - XrayDatabaseUser + - XrayDatabasePassword + ParameterLabels: + AvailabilityZones: + default: Availability Zones + KeyPairName: + default: SSH key name + PrivateSubnet1Cidr: + default: Private subnet 1 CIDR + PrivateSubnet2Cidr: + default: Private subnet 2 CIDR + PublicSubnet1Cidr: + default: Public subnet 1 CIDR + PublicSubnet2Cidr: + default: Public subnet 2 CIDR + AccessCidr: + default: Permitted IP range + RemoteAccessCidr: + default: Remote access CIDR + VpcCidr: + default: VPC CIDR + ProvisionBastionHost: + default: Bastion instance + BastionInstanceType: + default: Bastion instance type + BastionRootVolumeSize: + default: Bastion root volume size + BastionEnableTcpForwarding: + default: Bastion enable TCP forwarding + BastionEnableX11Forwarding: + default: Bastion enable X11 forwarding + BastionOs: + default: Bastion operating system + NumBastionHosts: + default: Number of bastion instances + VolumeSize: + default: EBS root volume size + InstanceType: + default: EC2 instance type + NumberOfSecondary: + default: Secondary instances + ArtifactoryProduct: + default: Artifactory product to install + ArtifactoryVersion: + default: Artifactory version + SmLicenseName: + default: Artifactory licenses secret name + SmCertName: + default: Artifactory certificate secret name + ArtifactoryServerName: + default: Artifactory server name + MasterKey: + default: Master server key + ExtraJavaOptions: + default: Extra Java options + DefaultJavaMemSettings: + default: Default Java memory settings + DatabaseName: + default: Database name + DatabaseEngine: + default: Database engine + DatabaseUser: + default: Database user + DatabasePassword: + default: Database password + DatabaseInstance: + default: Database instance type + DatabaseAllocatedStorage: + default: Database allocated storage + DatabasePreferredAz: + default: Database preferred Availability Zone + MultiAzDatabase: + default: High-availability database + QsS3BucketName: + default: Quick Start S3 bucket name + QsS3KeyPrefix: + default: Quick Start S3 key prefix + QsS3BucketRegion: + default: Quick Start S3 bucket region + InstallXray: + default: Install JFrog Xray + XrayVersion: + default: Version of Xray to install + XrayNumberOfInstances: + default: Number of JFrog XrayNumberOfInstances + XrayInstanceType: + default: Xray instance type + XrayDatabaseUser: + default: Xray Database user + XrayDatabasePassword: + default: Xray Database password +Parameters: + VpcCidr: + Description: CIDR block for the VPC. + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.0.0/16 + Type: String + AvailabilityZones: + Description: List of Availability Zones to use for the subnets in the VPC. Two + Availability Zones are used for this deployment. + Type: List + KeyPairName: + Description: Name of an existing key pair, + which allows you to connect securely to your instance after it launches. + This is the key pair you created in your preferred Region. + Type: AWS::EC2::KeyPair::KeyName + PrivateSubnet1Cidr: + Description: CIDR block for private subnet 1 located in Availability Zone 1. + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.0.0/19 + Type: String + PrivateSubnet2Cidr: + Description: CIDR block for private subnet 2 located in Availability Zone 2. + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.32.0/19 + Type: String + PublicSubnet1Cidr: + Description: CIDR block for the public (DMZ) subnet 1 located in Availability + Zone 1. + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.128.0/20 + Type: String + PublicSubnet2Cidr: + Description: CIDR block for the public (DMZ) subnet 2 located in Availability + Zone 2. + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.144.0/20 + Type: String + AccessCidr: + Description: CIDR IP range permitted to access Artifactory. + It is recommended that you set this value to a trusted IP range. + For example, you may want to limit software access to your corporate network. + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$ + Type: String + RemoteAccessCidr: + Description: Remote CIDR range that allows you to connect to the bastion instance by using SSH. + It is recommended that you set this value to a trusted IP range. + For example, you may want to grant specific ranges from within your corporate network that use the SSH protocol. + 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 + ProvisionBastionHost: + Description: To skip creating a bastion instance, choose Disabled. Because Artifactory nodes are + created in private subnets, it's highly recommended to set this value to Enabled. + AllowedValues: + - "Enabled" + - "Disabled" + Default: "Enabled" + Type: String + BastionInstanceType: + Description: Size of the bastion instances. + AllowedValues: + - t3.nano + - t3.micro + - t3.small + - t3.medium + - t3.large + - m5.large + - m5.xlarge + - m5.2xlarge + - m5.4xlarge + Default: "t3.micro" + Type: String + BastionRootVolumeSize: + Description: Size of the root volume in the bastion instances. + Default: 10 + Type: Number + BastionEnableTcpForwarding: + Description: Choose whether to enable TCP forwarding via bootstrapping of the bastion + instance. + AllowedValues: + - "true" + - "false" + Default: "true" + Type: String + BastionEnableX11Forwarding: + Description: Choose true to enable X11 via bootstrapping of the bastion host. + Setting this value to true enables X Windows over SSH. + X11 forwarding can be useful, but it is also a security risk, so it's recommended + that you keep the default (false) setting. + AllowedValues: + - "true" + - "false" + Default: "false" + Type: String + BastionOs: + Description: Linux distribution for the Amazon Machine Image (AMI) to be used for the bastion instances. + AllowedValues: + - "Amazon-Linux2-HVM" + - "CentOS-7-HVM" + - "Ubuntu-Server-20.04-LTS-HVM" + - "SUSE-SLES-15-HVM" + Default: "Amazon-Linux2-HVM" + Type: String + NumBastionHosts: + Description: Number of bastion instances to create. + AllowedValues: + - '1' + - '2' + - '3' + - '4' + Default: '1' + Type: String + VolumeSize: + Description: Size in gigabytes of available storage (min 10GB). The Quick Start creates an + Amazon Elastic Block Store (Amazon EBS) volumes of this size. + Default: 200 + Type: Number + InstanceType: + Description: EC2 instance type for the Artifactory instances. + AllowedValues: + - m5.large + - m5.xlarge + - m5.2xlarge + - m5.4xlarge + - m5.8xlarge + - m5.12xlarge + - m5.16xlarge + - m5.24xlarge + - m5.metal + - m5d.large + - m5d.xlarge + - m5d.2xlarge + - m5d.4xlarge + - m5d.8xlarge + - m5d.12xlarge + - m5d.16xlarge + - m5d.24xlarge + - m5d.metal + - m5a.large + - m5a.xlarge + - m5a.2xlarge + - m5a.4xlarge + - m5a.8xlarge + - m5a.12xlarge + - m5a.16xlarge + - m5a.24xlarge + ConstraintDescription: Must contain valid instance type. + Default: m5.xlarge + Type: String + NumberOfSecondary: + Description: Number of secondary Artifactory servers to complete your + HA deployment. To align with Artifactory best practices, the minimum number + is two, and the maximum is seven. Do not select more instances than you + have licenses for. + AllowedValues: + - 0 + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + - 7 + Default: 2 + Type: Number + ArtifactoryProduct: + Description: JFrog Artifactory product you want to install into an AMI. + AllowedValues: + - JFrog-Artifactory-Pro + - JFrog-Artifactory-Enterprise + - JFrog-Container-Registry + Default: JFrog-Artifactory-Enterprise + Type: String + ArtifactoryVersion: + Description: Version of Artifactory that you want to deploy into the Quick Start. + To select the correct version, see the release notes at + https://www.jfrog.com/confluence/display/RTF/Release+Notes. + Default: 7.17.4 + Type: String + SmLicenseName: + Description: Secret name created in AWS Secrets Manager, which contains the Artifactory licenses. + Default: '' + Type: String + SmCertName: + Description: Secret name created in AWS Secrets Manager, which contains the SSL certificate and certificate key. + Default: '' + Type: String + ArtifactoryServerName: + Description: Name of your Artifactory server. Ensure that this matches your certificate. + Type: String + MasterKey: + Description: Master key for the Artifactory cluster. Generate a master key by using the command '$openssl rand -hex 16'. + AllowedPattern: ^[a-zA-Z0-9]+$ + MinLength: '1' + MaxLength: '64' + ConstraintDescription: Only capital or lowercase letters and numbers, with a Max of 64 characters. + NoEcho: 'true' + Type: String + ExtraJavaOptions: + Description: Set Java options to pass to the JVM for Artifactory. For more information, see the Artifactory + system requirements at https://www.jfrog.com/confluence/display/RTF/System+Requirements#SystemRequirements-RecommendedHardware. + Do not add Xms or Xmx settings without disabling DefaultJavaMemSettings. + Default: -Xss256k -XX:+UseG1GC + Type: String + DefaultJavaMemSettings: + Description: Choose false to overwrite the standard memory-calculation options to pass to the Artifactory JVM. + If you plan to overwrite them, ensure they are added to the ExtraJavaOptions to prevent the stack provision from failing. + ConstraintDescription: True or False + AllowedValues: + - "true" + - "false" + Default: "true" + Type: String + DatabaseName: + Description: Name of your database instance. The name must be unique across all instances + owned by your AWS account in the current Region. The database instance identifier is case-insensitive, + but it's stored in lowercase (as in "mydbinstance"). + AllowedPattern: ^[a-zA-Z]([a-zA-Z0-9])+$ + MinLength: '1' + MaxLength: '60' + ConstraintDescription: 1 to 60 alphanumeric characters First character must be a letter. + Default: artdb + Type: String + DatabaseEngine: + Description: Database engine that you want to run. + AllowedValues: + - Postgres + Default: Postgres + Type: String + DatabaseUser: + Description: Login ID for the master user of your database instance. + MinLength: '1' + MaxLength: '16' + AllowedPattern: ^[a-zA-Z]([a-zA-Z0-9])+$ + ConstraintDescription: 1 to 16 alphanumeric characters. The first character must be a letter. + Default: artifactory + Type: String + DatabasePassword: + Description: Password for the Artifactory database user. + AllowedPattern: ^[^ \\']+$ + MinLength: '8' + MaxLength: '12' + ConstraintDescription: Must be at least 8 and no more than + 12 characters containing letters and (minimum 1 capital letter), numbers and + symbols. + NoEcho: 'true' + Type: String + DatabaseInstance: + Description: Size of the database to be deployed as part of the Quick Start. + AllowedValues: + - db.m5.large + - db.m5.xlarge + - db.m5.2xlarge + - db.m5.10xlarge + - db.m5.16xlarge + - db.m5.large + - db.m5.xlarge + - db.m5.2xlarge + - db.m5.4xlarge + - db.m5.12xlarge + - db.m5.24xlarge + ConstraintDescription: Must be a valid database Instance Type. + Default: db.m5.large + Type: String + DatabaseAllocatedStorage: + Description: Size in gigabytes of available storage for the database instance. + MinValue: 5 + MaxValue: 1024 + Default: 10 + Type: Number + DatabasePreferredAz: + Description: Preferred availability zone for Amazon RDS primary instance + Type: String + Default: '' + MultiAzDatabase: + Description: Choose false to create an Amazon RDS instance in a single Availability Zone. + ConstraintDescription: True or False + AllowedValues: + - "true" + - "false" + Default: "true" + Type: String + QsS3BucketName: + Description: S3 bucket name for the Quick Start assets. This string can include + numbers, lowercase letters, and hyphens (-). It cannot start + or end with a hyphen (-). + AllowedPattern: ^[0-9a-z]+([0-9a-z-]*[0-9a-z])*$ + ConstraintDescription: Quick Start bucket name can include numbers, lowercase + letters, and hyphens (-). It cannot start or end with a hyphen (-). + Default: jfrog-aws + 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: artifactory7/latest/ + Type: String + QsS3BucketRegion: + Default: 'us-east-1' + Description: AWS Region where the Quick Start S3 bucket (QSS3BucketName) is hosted. If you use your own bucket, you must specify your own value. + Type: String + InstallXray: + Description: Choose true to install JFrog Xray instance(s). + ConstraintDescription: True or False + AllowedValues: + - "true" + - "false" + Default: "true" + Type: String + XrayVersion: + Description: The version of Xray that you want to deploy into the Quick Start. + Default: 3.21.2 + Type: String + XrayNumberOfInstances: + Description: The number of Xray instances servers to complete your + HA deployment. The minimum number is one; the maximum is seven. + Do not select more than instances than you have licenses for. + MinValue: 1 + MaxValue: 7 + Default: 1 + Type: Number + XrayInstanceType: + Description: The EC2 instance type for the Xray instances. + AllowedValues: + - c5.2xlarge + - c5.4xlarge + ConstraintDescription: Must contain valid instance type. + Default: c5.2xlarge + Type: String + XrayDatabaseUser: + Description: The login ID for the Xray database user. + MinLength: '1' + MaxLength: '16' + AllowedPattern: ^[a-zA-Z]([a-zA-Z0-9])+$ + ConstraintDescription: 1 to 16 alphanumeric characters. First character must be a letter. + Default: xray + Type: String + XrayDatabasePassword: + Description: The password for the Xray database user. + AllowedPattern: ^[^ \\']+$ + MinLength: '8' + MaxLength: '12' + ConstraintDescription: Must be at least 8 and no more than + 12 characters containing letters and (minimum 1 capital letter), numbers and + symbols. + NoEcho: 'true' + Type: String +Conditions: + UsingDefaultBucket: !Equals [!Ref QsS3BucketName, 'aws-quickstart'] + +Resources: + ArtifactoryVpcStack: + Type: AWS::CloudFormation::Stack + Properties: + TemplateURL: !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QsS3KeyPrefix}submodules/quickstart-aws-vpc/templates/aws-vpc.template + - S3Bucket: !If [UsingDefaultBucket, !Sub '${QsS3BucketName}-${AWS::Region}', !Ref 'QsS3BucketName'] + S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref 'QsS3BucketRegion'] + Parameters: + AvailabilityZones: + Fn::Join: + - ',' + - Ref: AvailabilityZones + KeyPairName: + Ref: KeyPairName + NumberOfAZs: '2' + PrivateSubnet1ACIDR: + Ref: PrivateSubnet1Cidr + PrivateSubnet2ACIDR: + Ref: PrivateSubnet2Cidr + PublicSubnet1CIDR: + Ref: PublicSubnet1Cidr + PublicSubnet2CIDR: + Ref: PublicSubnet2Cidr + VPCCIDR: + Ref: VpcCidr + ArtifactoryExistingVpcStack: + Type: AWS::CloudFormation::Stack + Properties: + TemplateURL: !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QsS3KeyPrefix}templates/jfrog-artifactory-ec2-existing-vpc.template.yaml + - S3Bucket: !If [UsingDefaultBucket, !Sub '${QsS3BucketName}-${AWS::Region}', !Ref 'QsS3BucketName'] + S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref 'QsS3BucketRegion'] + Parameters: + AvailabilityZones: + Fn::Join: + - ',' + - Ref: AvailabilityZones + KeyPairName: !Ref KeyPairName + VpcId: !GetAtt ArtifactoryVpcStack.Outputs.VPCID + VpcCidr: !Ref VpcCidr + PublicSubnet1Id: !GetAtt ArtifactoryVpcStack.Outputs.PublicSubnet1ID + PublicSubnet2Id: !GetAtt ArtifactoryVpcStack.Outputs.PublicSubnet2ID + PrivateSubnet1Id: !GetAtt ArtifactoryVpcStack.Outputs.PrivateSubnet1AID + PrivateSubnet2Id: !GetAtt ArtifactoryVpcStack.Outputs.PrivateSubnet2AID + PrivateSubnet1Cidr: !Ref PrivateSubnet1Cidr + PrivateSubnet2Cidr: !Ref PrivateSubnet2Cidr + AccessCidr: !Ref AccessCidr + RemoteAccessCidr: !Ref RemoteAccessCidr + ProvisionBastionHost: !Ref ProvisionBastionHost + BastionInstanceType: !Ref BastionInstanceType + BastionRootVolumeSize: !Ref BastionRootVolumeSize + BastionEnableTcpForwarding: !Ref BastionEnableTcpForwarding + BastionEnableX11Forwarding: !Ref BastionEnableX11Forwarding + BastionOs: !Ref BastionOs + NumBastionHosts: !Ref NumBastionHosts + VolumeSize: !Ref VolumeSize + InstanceType: !Ref InstanceType + NumberOfSecondary: !Ref NumberOfSecondary + ArtifactoryProduct: !Ref ArtifactoryProduct + ArtifactoryVersion: !Ref ArtifactoryVersion + SmLicenseName: !Ref SmLicenseName + SmCertName: !Ref SmCertName + ArtifactoryServerName: !Ref ArtifactoryServerName + MasterKey: !Ref MasterKey + ExtraJavaOptions: !Ref ExtraJavaOptions + DefaultJavaMemSettings: !Ref DefaultJavaMemSettings + DatabaseName: !Ref DatabaseName + DatabaseEngine: !Ref DatabaseEngine + DatabaseUser: !Ref DatabaseUser + DatabasePassword: !Ref DatabasePassword + DatabaseInstance: !Ref DatabaseInstance + DatabaseAllocatedStorage: !Ref DatabaseAllocatedStorage + DatabasePreferredAz: !Ref DatabasePreferredAz + MultiAzDatabase: !Ref MultiAzDatabase + QsS3BucketName: !Ref QsS3BucketName + QsS3KeyPrefix: !Ref QsS3KeyPrefix + QsS3BucketRegion: !Ref QsS3BucketRegion + InstallXray: !Ref InstallXray + XrayVersion: !Ref XrayVersion + XrayNumberOfInstances: !Ref XrayNumberOfInstances + XrayInstanceType: !Ref XrayInstanceType + XrayDatabaseUser: !Ref XrayDatabaseUser + XrayDatabasePassword: !Ref XrayDatabasePassword +Outputs: + ArtifactoryUrl: + Description: URL of the ELB to access Artifactory + Value: !Sub ${ArtifactoryExistingVpcStack.Outputs.ArtifactoryUrl} + BastionIp: + Value: !Sub ${ArtifactoryExistingVpcStack.Outputs.BastionIp} + Description: Bastion host IP, for admin access via SSH diff --git a/Amazon/artifactory7/v7174/templates/jfrog-artifactory-pro-ec2-existing-vpc-master.template.yaml b/Amazon/artifactory7/v7174/templates/jfrog-artifactory-pro-ec2-existing-vpc-master.template.yaml new file mode 100644 index 0000000..fa213eb --- /dev/null +++ b/Amazon/artifactory7/v7174/templates/jfrog-artifactory-pro-ec2-existing-vpc-master.template.yaml @@ -0,0 +1,355 @@ +AWSTemplateFormatVersion: '2010-09-09' +Description: 'JFrog Artifactory Quick Start Deployment into an Existing VPC (qs-1q037efj0)' +Metadata: + QuickStartDocumentation: + EntrypointName: "Launch into an existing VPC" + AWS::CloudFormation::Interface: + ParameterGroups: + - Label: + default: AWS Quick Start configuration + Parameters: + - QsS3BucketName + - QsS3KeyPrefix + - QsS3BucketRegion + - Label: + default: Essential configuration + Parameters: + - KeyPairName + - DatabasePassword + - Label: + default: Network configuration + Parameters: + - VpcId + - PublicSubnet1Id + - PublicSubnet2Id + - PrivateSubnet1Id + - PrivateSubnet2Id + - PrivateSubnet1Cidr + - PrivateSubnet2Cidr + - Label: + default: Security configuration + Parameters: + - AccessCidr + - RemoteAccessCidr + - Label: + default: Amazon EC2 configuration + Parameters: + - VolumeSize + - InstanceType + - Label: + default: JFrog Artifactory configuration + Parameters: + - ArtifactoryVersion + - SmLicenseName + - SmCertName + - ArtifactoryServerName + - MasterKey + - Label: + default: Amazon RDS configuration + Parameters: + - DatabaseInstance + - DatabaseAllocatedStorage + - DatabasePreferredAz + - Label: + default: JFrog Xray Configuration + Parameters: + - InstallXray + - XrayVersion + - XrayInstanceType + ParameterLabels: + QsS3BucketName: + default: Quick Start S3 bucket name + QsS3KeyPrefix: + default: Quick Start S3 key prefix + QsS3BucketRegion: + default: Quick Start S3 bucket region + KeyPairName: + default: SSH key name + VpcId: + default: VPC ID + PublicSubnet1Id: + default: Public subnet 1 ID + PublicSubnet2Id: + default: Public subnet 2 ID + PrivateSubnet1Id: + default: Private subnet 1 ID + PrivateSubnet2Id: + default: Private subnet 2 ID + PrivateSubnet1Cidr: + default: Private subnet 1 CIDR + PrivateSubnet2Cidr: + default: Private subnet 2 CIDR + AccessCidr: + default: Permitted IP range + RemoteAccessCidr: + default: Remote access CIDR + VolumeSize: + default: EBS root volume size + InstanceType: + default: EC2 instance type + ArtifactoryVersion: + default: Artifactory version + SmLicenseName: + default: Artifactory licenses secret name + SmCertName: + default: Artifactory certificate secret name + ArtifactoryServerName: + default: Artifactory server name + MasterKey: + default: Master server key + DatabasePassword: + default: Database password + DatabaseInstance: + default: Database instance type + DatabaseAllocatedStorage: + default: Database allocated storage + DatabasePreferredAz: + default: Database preferred Availability Zone + InstallXray: + default: Install JFrog Xray + XrayVersion: + default: Version of Xray to install + XrayInstanceType: + default: Xray instance type +Parameters: + QsS3BucketName: + Description: S3 bucket name for the Quick Start assets. This string can include + numbers, lowercase letters, and hyphens (-). It cannot start + or end with a hyphen (-). + AllowedPattern: ^[0-9a-z]+([0-9a-z-]*[0-9a-z])*$ + ConstraintDescription: Quick Start bucket name can include numbers, lowercase + letters, and hyphens (-). It cannot start or end with a hyphen (-). + Default: jfrog-aws + 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: artifactory7/latest/ + Type: String + QsS3BucketRegion: + Default: 'us-east-1' + Description: AWS Region where the Quick Start S3 bucket (QSS3BucketName) is hosted. If you use your own bucket, you must specify your own value. + Type: String + KeyPairName: + Description: Name of an existing key pair, + which allows you to connect securely to your instance after it launches. + This is the key pair you created in your preferred Region. + Type: AWS::EC2::KeyPair::KeyName + VpcId: + Description: ID of your existing VPC (e.g., vpc-0343606e). + Type: "AWS::EC2::VPC::Id" + PublicSubnet1Id: + Description: ID of the public subnet 1 in Availability Zone 1 of your existing VPC (e.g., subnet-z0376dab). + Type: "AWS::EC2::Subnet::Id" + PublicSubnet2Id: + Description: ID of the public subnet 2 in Availability Zone 1 of your existing VPC (e.g., subnet-z0376dab). + Type: "AWS::EC2::Subnet::Id" + PrivateSubnet1Id: + Description: ID of the private subnet 1 in Availability Zone 1 of your existing VPC (e.g., subnet-a29c3d84). + Type: "AWS::EC2::Subnet::Id" + PrivateSubnet2Id: + Description: ID of the private subnet 2 in Availability Zone 1 of your existing VPC (e.g., subnet-a29c3d84). + Type: "AWS::EC2::Subnet::Id" + PrivateSubnet1Cidr: + Description: CIDR of the private subnet 1 in Availability Zone 1 of your existing VPC (e.g., 10.0.0.0/19). + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.128.0/20 + Type: String + PrivateSubnet2Cidr: + Description: CIDR of the private subnet 2 in Availability Zone 1 of your existing VPC (e.g., 10.0.0.0/19). + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.144.0/20 + Type: String + AccessCidr: + Description: CIDR IP range that is permitted to access Artifactory. + We recommend that you set this value to a trusted IP range. + For example, you might want to grant only your corporate network access to the software. + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$ + Default: 0.0.0.0/0 + Type: String + RemoteAccessCidr: + Description: Remote CIDR range that allows you to connect to the bastion instance by using SSH. + It is recommended that you set this value to a trusted IP range. + For example, you may want to grant specific ranges from within your corporate network that use the SSH protocol. + 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 + VolumeSize: + Description: Size in gigabytes of the available storage (min 10GB); the Quick Start will create an + Amazon Elastic Block Store (Amazon EBS) volumes of this size. + Default: 100 + Type: Number + InstanceType: + Description: EC2 type for the Artifactory instances. + AllowedValues: + - m5.large + - m5.xlarge + - m5.2xlarge + - m5.4xlarge + - m5.8xlarge + - m5.12xlarge + - m5.16xlarge + - m5.24xlarge + - m5.metal + - m5d.large + - m5d.xlarge + - m5d.2xlarge + - m5d.4xlarge + - m5d.8xlarge + - m5d.12xlarge + - m5d.16xlarge + - m5d.24xlarge + - m5d.metal + - m5a.large + - m5a.xlarge + - m5a.2xlarge + - m5a.4xlarge + - m5a.8xlarge + - m5a.12xlarge + - m5a.16xlarge + - m5a.24xlarge + ConstraintDescription: Must contain valid instance type. + Default: m5.xlarge + Type: String + ArtifactoryVersion: + Description: Version of Artifactory that you want to deploy into the Quick Start. + To select the correct version, see the release notes at + https://www.jfrog.com/confluence/display/RTF/Release+Notes. + AllowedPattern: ^(([0-9]|[1-9][0-9])\.){2}([1-9][0-9]|[0-9])$ + ConstraintDescription: A version that matches X.X.X per Artifactory releases. + Default: 7.17.4 + Type: String + SmLicenseName: + Description: Secret name created in AWS Secrets Manager, which contains the Artifactory licenses. + Default: '' + Type: String + SmCertName: + Description: Secret name created in AWS Secrets Manager, which contains the SSL certificate and certificate key. + Default: '' + Type: String + ArtifactoryServerName: + Description: Name of your Artifactory server. Ensure that this matches your certificate. + Default: 'artifactory' + Type: String + MasterKey: + Description: Master key for the Artifactory cluster. Generate a master key by using the command '$openssl rand -hex 16'. + AllowedPattern: ^[a-zA-Z0-9]+$ + MinLength: '1' + MaxLength: '64' + ConstraintDescription: Only capital or lowercase letters and numbers, with a Max of 64 characters. + NoEcho: 'true' + Default: 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' + Type: String + DatabasePassword: + Description: Password for the Artifactory database user. + AllowedPattern: ^[^ \\']+$ + MinLength: '8' + MaxLength: '12' + ConstraintDescription: Must be at least 8 and no more than + 12 characters containing letters and (minimum 1 capital letter), numbers and + symbols. + NoEcho: 'true' + Type: String + DatabaseInstance: + Description: Size of the database to be deployed as part of the Quick Start. + AllowedValues: + - db.m5.large + - db.m5.xlarge + - db.m5.2xlarge + - db.m5.10xlarge + - db.m5.16xlarge + - db.m5.large + - db.m5.xlarge + - db.m5.2xlarge + - db.m5.4xlarge + - db.m5.12xlarge + - db.m5.24xlarge + ConstraintDescription: Must be a valid database Instance Type. + Default: db.m5.large + Type: String + DatabaseAllocatedStorage: + Description: Size in gigabytes of the available storage for the database instance. + MinValue: 5 + MaxValue: 1024 + Default: 10 + Type: Number + DatabasePreferredAz: + Description: Preferred availability zone for Amazon RDS primary instance + Default: us-west-2a + Type: AWS::EC2::AvailabilityZone::Name + InstallXray: + Description: Choose true to install JFrog Xray instance(s). + ConstraintDescription: True or False + AllowedValues: + - "true" + - "false" + Default: "false" + Type: String + XrayVersion: + Description: The version of Xray that you want to deploy into the Quick Start. + AllowedPattern: ^(([0-9]|[1-9][0-9])\.){2}([1-9][0-9]|[0-9])$ + ConstraintDescription: A version that matches X.X.X per Xray releases. + Default: 3.21.2 + Type: String + XrayInstanceType: + Description: The EC2 instance type for the Xray instances. + AllowedValues: + - c5.2xlarge + - c5.4xlarge + ConstraintDescription: Must contain valid instance type. + Default: c5.2xlarge + Type: String +Conditions: + UsingDefaultBucket: !Equals [!Ref QsS3BucketName, 'aws-quickstart'] +Resources: + ArtifactoryExistingVpcStack: + Type: AWS::CloudFormation::Stack + Properties: + TemplateURL: !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QsS3KeyPrefix}templates/jfrog-artifactory-ec2-existing-vpc.template.yaml + - S3Bucket: !If [UsingDefaultBucket, !Sub '${QsS3BucketName}-${AWS::Region}', !Ref 'QsS3BucketName'] + S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref 'QsS3BucketRegion'] + Parameters: + AvailabilityZones: !Join [',', [!Ref DatabasePreferredAz]] + KeyPairName: !Ref KeyPairName + ProvisionBastionHost: "Enabled" + AccessCidr: !Ref AccessCidr + RemoteAccessCidr: !Ref RemoteAccessCidr + ArtifactoryProduct: 'JFrog-Artifactory-Pro' + ArtifactoryVersion: !Ref ArtifactoryVersion + VolumeSize: !Ref VolumeSize + InstanceType: !Ref InstanceType + NumberOfSecondary: 0 + SmLicenseName: !Ref SmLicenseName + SmCertName: !Ref SmCertName + ArtifactoryServerName: !Ref ArtifactoryServerName + MasterKey: !Ref MasterKey + DatabasePassword: !Ref DatabasePassword + DatabaseInstance: !Ref DatabaseInstance + DatabaseAllocatedStorage: !Ref DatabaseAllocatedStorage + DatabasePreferredAz: !Ref DatabasePreferredAz + MultiAzDatabase: false + QsS3BucketName: !Ref QsS3BucketName + QsS3KeyPrefix: !Ref QsS3KeyPrefix + QsS3BucketRegion: !Ref QsS3BucketRegion + InstallXray: !Ref InstallXray + XrayVersion: !Ref XrayVersion + XrayInstanceType: !Ref XrayInstanceType + XrayDatabasePassword: !Ref DatabasePassword + VpcId: !Ref VpcId + PublicSubnet1Id: !Ref PublicSubnet1Id + PublicSubnet2Id: !Ref PublicSubnet2Id + PrivateSubnet1Id: !Ref PrivateSubnet1Id + PrivateSubnet2Id: !Ref PrivateSubnet2Id + PrivateSubnet1Cidr: !Ref PrivateSubnet1Cidr + PrivateSubnet2Cidr: !Ref PrivateSubnet2Cidr + +Outputs: + ArtifactoryUrl: + Description: URL of the ELB to access Artifactory + Value: !Sub ${ArtifactoryExistingVpcStack.Outputs.ArtifactoryUrl} diff --git a/Amazon/artifactory7/v7174/templates/jfrog-artifactory-pro-ec2-new-vpc-master.template.yaml b/Amazon/artifactory7/v7174/templates/jfrog-artifactory-pro-ec2-new-vpc-master.template.yaml new file mode 100644 index 0000000..2736e44 --- /dev/null +++ b/Amazon/artifactory7/v7174/templates/jfrog-artifactory-pro-ec2-new-vpc-master.template.yaml @@ -0,0 +1,300 @@ +AWSTemplateFormatVersion: '2010-09-09' +Description: 'JFrog Artifactory Quick Start Deployment into an Existing VPC (qs-1q037efj0)' +Metadata: + QuickStartDocumentation: + EntrypointName: "Launch into an existing VPC" + AWS::CloudFormation::Interface: + ParameterGroups: + - Label: + default: AWS Quick Start configuration + Parameters: + - QsS3BucketName + - QsS3KeyPrefix + - QsS3BucketRegion + - Label: + default: Essential configuration + Parameters: + - KeyPairName + - DatabasePassword + - Label: + default: Network configuration + Parameters: + - AvailabilityZones + - Label: + default: Security configuration + Parameters: + - AccessCidr + - RemoteAccessCidr + - Label: + default: Amazon EC2 configuration + Parameters: + - VolumeSize + - InstanceType + - Label: + default: JFrog Artifactory configuration + Parameters: + - ArtifactoryVersion + - SmLicenseName + - SmCertName + - ArtifactoryServerName + - MasterKey + - Label: + default: Amazon RDS configuration + Parameters: + - DatabaseInstance + - DatabaseAllocatedStorage + - Label: + default: JFrog Xray Configuration + Parameters: + - InstallXray + - XrayVersion + - XrayInstanceType + ParameterLabels: + QsS3BucketName: + default: Quick Start S3 bucket name + QsS3KeyPrefix: + default: Quick Start S3 key prefix + QsS3BucketRegion: + default: Quick Start S3 bucket region + KeyPairName: + default: SSH key name + AccessCidr: + default: Permitted IP range + RemoteAccessCidr: + default: Remote access CIDR + AvailabilityZones: + default: Availability Zones + VolumeSize: + default: EBS root volume size + InstanceType: + default: EC2 instance type + ArtifactoryVersion: + default: Artifactory version + SmLicenseName: + default: Artifactory licenses secret name + SmCertName: + default: Artifactory certificate secret name + ArtifactoryServerName: + default: Artifactory server name + MasterKey: + default: Master server key + DatabasePassword: + default: Database password + DatabaseInstance: + default: Database instance type + DatabaseAllocatedStorage: + default: Database allocated storage + InstallXray: + default: Install JFrog Xray + XrayVersion: + default: Version of Xray to install + XrayInstanceType: + default: Xray instance type +Parameters: + QsS3BucketName: + Description: S3 bucket name for the Quick Start assets. This string can include + numbers, lowercase letters, and hyphens (-). It cannot start + or end with a hyphen (-). + AllowedPattern: ^[0-9a-z]+([0-9a-z-]*[0-9a-z])*$ + ConstraintDescription: Quick Start bucket name can include numbers, lowercase + letters, and hyphens (-). It cannot start or end with a hyphen (-). + Default: jfrog-aws + 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: artifactory7/latest/ + Type: String + QsS3BucketRegion: + Default: 'us-east-1' + Description: AWS Region where the Quick Start S3 bucket (QSS3BucketName) is hosted. If you use your own bucket, you must specify your own value. + Type: String + KeyPairName: + Description: Name of an existing key pair, + which allows you to connect securely to your instance after it launches. + This is the key pair you created in your preferred Region. + Type: AWS::EC2::KeyPair::KeyName + AccessCidr: + Description: CIDR IP range that is permitted to access Artifactory. + We recommend that you set this value to a trusted IP range. + For example, you might want to grant only your corporate network access to the software. + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$ + Default: 0.0.0.0/0 + Type: String + RemoteAccessCidr: + Description: Remote CIDR range that allows you to connect to the bastion instance by using SSH. + It is recommended that you set this value to a trusted IP range. + For example, you may want to grant specific ranges from within your corporate network that use the SSH protocol. + 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 + AvailabilityZones: + Description: List of Availability Zones to use for the subnets in the VPC. Two + Availability Zones are used for this deployment. + Type: List + VolumeSize: + Description: Size in gigabytes of the available storage (min 10GB); the Quick Start will create an + Amazon Elastic Block Store (Amazon EBS) volumes of this size. + Default: 100 + Type: Number + InstanceType: + Description: EC2 type for the Artifactory instances. + AllowedValues: + - m5.large + - m5.xlarge + - m5.2xlarge + - m5.4xlarge + - m5.8xlarge + - m5.12xlarge + - m5.16xlarge + - m5.24xlarge + - m5.metal + - m5d.large + - m5d.xlarge + - m5d.2xlarge + - m5d.4xlarge + - m5d.8xlarge + - m5d.12xlarge + - m5d.16xlarge + - m5d.24xlarge + - m5d.metal + - m5a.large + - m5a.xlarge + - m5a.2xlarge + - m5a.4xlarge + - m5a.8xlarge + - m5a.12xlarge + - m5a.16xlarge + - m5a.24xlarge + ConstraintDescription: Must contain valid instance type. + Default: m5.xlarge + Type: String + ArtifactoryVersion: + Description: Version of Artifactory that you want to deploy into the Quick Start. + To select the correct version, see the release notes at + https://www.jfrog.com/confluence/display/RTF/Release+Notes. + Default: 7.17.4 + Type: String + SmLicenseName: + Description: Secret name created in AWS Secrets Manager, which contains the Artifactory licenses. + Default: '' + Type: String + SmCertName: + Description: Secret name created in AWS Secrets Manager, which contains the SSL certificate and certificate key. + Default: '' + Type: String + ArtifactoryServerName: + Description: Name of your Artifactory server. Ensure that this matches your certificate. + Default: 'artifactory' + Type: String + MasterKey: + Description: Master key for the Artifactory cluster. Generate a master key by using the command '$openssl rand -hex 16'. + AllowedPattern: ^[a-zA-Z0-9]+$ + MinLength: '1' + MaxLength: '64' + ConstraintDescription: Only capital or lowercase letters and numbers, with a Max of 64 characters. + NoEcho: 'true' + Default: 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' + Type: String + DatabasePassword: + Description: Password for the Artifactory database user. + AllowedPattern: ^[^ \\']+$ + MinLength: '8' + MaxLength: '12' + ConstraintDescription: Must be at least 8 and no more than + 12 characters containing letters and (minimum 1 capital letter), numbers and + symbols. + NoEcho: 'true' + Type: String + DatabaseInstance: + Description: Size of the database to be deployed as part of the Quick Start. + AllowedValues: + - db.m5.large + - db.m5.xlarge + - db.m5.2xlarge + - db.m5.10xlarge + - db.m5.16xlarge + - db.m5.large + - db.m5.xlarge + - db.m5.2xlarge + - db.m5.4xlarge + - db.m5.12xlarge + - db.m5.24xlarge + ConstraintDescription: Must be a valid database Instance Type. + Default: db.m5.large + Type: String + DatabaseAllocatedStorage: + Description: Size in gigabytes of the available storage for the database instance. + MinValue: 5 + MaxValue: 1024 + Default: 10 + Type: Number + InstallXray: + Description: Choose true to install JFrog Xray instance(s). + ConstraintDescription: True or False + AllowedValues: + - "true" + - "false" + Default: "false" + Type: String + XrayVersion: + Description: The version of Xray that you want to deploy into the Quick Start. + Default: 3.21.2 + Type: String + XrayInstanceType: + Description: The EC2 instance type for the Xray instances. + AllowedValues: + - c5.2xlarge + - c5.4xlarge + ConstraintDescription: Must contain valid instance type. + Default: c5.2xlarge + Type: String +Conditions: + UsingDefaultBucket: !Equals [!Ref QsS3BucketName, 'aws-quickstart'] +Resources: + ArtifactoryNewVpcStack: + Type: AWS::CloudFormation::Stack + Properties: + TemplateURL: !Sub + - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QsS3KeyPrefix}templates/jfrog-artifactory-ec2-master.template.yaml + - S3Bucket: !If [UsingDefaultBucket, !Sub '${QsS3BucketName}-${AWS::Region}', !Ref 'QsS3BucketName'] + S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref 'QsS3BucketRegion'] + Parameters: + KeyPairName: !Ref KeyPairName + ProvisionBastionHost: "Enabled" + AccessCidr: !Ref AccessCidr + RemoteAccessCidr: !Ref RemoteAccessCidr + ArtifactoryProduct: 'JFrog-Artifactory-Pro' + ArtifactoryVersion: !Ref ArtifactoryVersion + VolumeSize: !Ref VolumeSize + InstanceType: !Ref InstanceType + NumberOfSecondary: 0 + SmLicenseName: !Ref SmLicenseName + SmCertName: !Ref SmCertName + ArtifactoryServerName: !Ref ArtifactoryServerName + MasterKey: !Ref MasterKey + DatabasePassword: !Ref DatabasePassword + DatabaseInstance: !Ref DatabaseInstance + DatabaseAllocatedStorage: !Ref DatabaseAllocatedStorage + DatabasePreferredAz: !Select + - '0' + - !Ref 'AvailabilityZones' + MultiAzDatabase: false + QsS3BucketName: !Ref QsS3BucketName + QsS3KeyPrefix: !Ref QsS3KeyPrefix + QsS3BucketRegion: !Ref QsS3BucketRegion + InstallXray: !Ref InstallXray + XrayVersion: !Ref XrayVersion + XrayInstanceType: !Ref XrayInstanceType + XrayDatabasePassword: !Ref DatabasePassword + AvailabilityZones: + Fn::Join: + - ',' + - Ref: AvailabilityZones +Outputs: + ArtifactoryUrl: + Description: URL of the ELB to access Artifactory + Value: !Sub ${ArtifactoryNewVpcStack.Outputs.ArtifactoryUrl} diff --git a/Amazon/artifactory7/v7174/templates/jfrog-xray-ec2-instance.template.yaml b/Amazon/artifactory7/v7174/templates/jfrog-xray-ec2-instance.template.yaml new file mode 100644 index 0000000..0f57609 --- /dev/null +++ b/Amazon/artifactory7/v7174/templates/jfrog-xray-ec2-instance.template.yaml @@ -0,0 +1,326 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: "Deploys the EC2 Autoscaling, LaunchConfig and Instance for Xray" +Parameters: + PrivateSubnet1Id: + Type: 'AWS::EC2::Subnet::Id' + PrivateSubnet2Id: + Type: 'AWS::EC2::Subnet::Id' + KeyPairName: + Type: AWS::EC2::KeyPair::KeyName + MinScalingNodes: + Type: Number + MaxScalingNodes: + Type: Number + DeploymentTag: + Type: String + ArtifactoryProduct: + Description: JFrog Artifactory product you want to install into an AMI. + AllowedValues: + - JFrog-Artifactory-Pro + - JFrog-Artifactory-Enterprise + - JFrog-Container-Registry + Default: JFrog-Artifactory-Enterprise + Type: String + QsS3BucketName: + Type: String + QsS3KeyPrefix: + Type: String + QsS3Uri: + Type: String + DatabaseDriver: + Type: String + DatabaseType: + Type: String + DatabaseUser: + Type: String + DatabasePassword: + Type: String + NoEcho: 'true' + MasterKey: + Type: String + NoEcho: 'true' + ExtraJavaOptions: + Type: String + SecurityGroups: + Type: String + XrayHostProfile: + Type: String + XrayHostRole: + Type: String + XrayInstanceType: + Type: String + JfrogInternalUrl: + Type: String + VolumeSize: + Type: Number + XrayDatabaseUser: + Type: String + XrayDatabasePassword: + Type: String + NoEcho: 'true' + XrayMasterDatabaseUrl: + Type: String + XrayDatabaseUrl: + Type: String + XrayVersion: + Type: String + UserDataDirectory: + Description: Directory to store Artifactory data. Can be used to store data (via symlink) in detachable volume + Type: String + Default: '/xray-user-data' + +# 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: + CentOS7HVM: "ami-00a5245b4816c38e6" + ap-northeast-2: + CentOS7HVM: "ami-00dc207f8ba6dc919" + ap-south-1: + CentOS7HVM: "ami-0ad42f4f66f6c1cc9" + ap-southeast-1: + CentOS7HVM: "ami-05b3bcf7f311194b3" + ap-southeast-2: + CentOS7HVM: "ami-02fd0b06f06d93dfc" + ca-central-1: + CentOS7HVM: "ami-07423fb63ea0a0930" + eu-central-1: + CentOS7HVM: "ami-0cfbf4f6db41068ac" + eu-west-1: + CentOS7HVM: "ami-08935252a36e25f85" + sa-east-1: + CentOS7HVM: "ami-05145e0b28ad8e0b2" + us-east-1: + CentOS7HVM: "ami-0affd4508a5d2481b" + us-east-2: + CentOS7HVM: "ami-01e36b7901e884a10" + us-west-1: + CentOS7HVM: "ami-098f55b4287a885ba" + us-west-2: + CentOS7HVM: "ami-0bc06212a56393ee1" + +Conditions: + IsArtifactoryPro: !Equals [!Ref ArtifactoryProduct, 'JFrog-Artifactory-Pro'] + +Resources: + XrayScalingGroup: + Type: AWS::AutoScaling::AutoScalingGroup + Properties: + LaunchConfigurationName: !Ref XrayLaunchConfiguration + VPCZoneIdentifier: + !If [IsArtifactoryPro, [!Ref PrivateSubnet1Id], [!Ref PrivateSubnet1Id, !Ref PrivateSubnet2Id]] + MinSize: !Ref MinScalingNodes + MaxSize: !Ref MaxScalingNodes + Cooldown: '300' + DesiredCapacity: !Ref MinScalingNodes + HealthCheckType: EC2 + HealthCheckGracePeriod: 1800 + Tags: + - Key: Name + Value: !Ref DeploymentTag + PropagateAtLaunch: true + - Key: XrayVersion + Value: !Ref XrayVersion + PropagateAtLaunch: true + TerminationPolicies: + - OldestInstance + - Default + CreationPolicy: + ResourceSignal: + Count: !Ref MinScalingNodes + Timeout: PT60M + XrayLaunchConfiguration: + Type: AWS::AutoScaling::LaunchConfiguration + Metadata: + AWS::CloudFormation::Authentication: + S3AccessCreds: + type: S3 + roleName: + - !Ref XrayHostRole + buckets: + - !Ref QsS3BucketName + AWS::CloudFormation::Init: + configSets: + xray_ami_setup: + - "config-cloudwatch" + - "config-ansible-xray-ami" + xray_install: + - "config-cloudwatch" + - "config-ansible-xray-ami" + - "config-xray" + - "secure-xray" + config-cloudwatch: + files: + /root/cloudwatch.conf: + content: | + [general] + state_file = /var/awslogs/state/agent-state + + [/var/log/messages] + file = /var/log/messages + log_group_name = /xray/instances/{instance_id} + log_stream_name = /var/log/messages/ + datetime_format = %b %d %H:%M:%S + + [/var/log/xray-ami-setup.log] + file = /var/log/messages + log_group_name = /xray/instances/{instance_id} + log_stream_name = /var/log/xray-ami-setup.log + datetime_format = %b %d %H:%M:%S + + [/var/log/xray.log] + file = /var/log/messages + log_group_name = /xray/instances/{instance_id} + log_stream_name = /var/log/xray.log + datetime_format = %b %d %H:%M:%S + mode: "0400" + config-ansible-xray-ami: + files: + /root/.xray_ami/xray-ami-setup.yml: + content: !Sub | + # Base install for Xray + - import_playbook: xray-ami.yml + vars: + ami_creation: false + db_type: postgresql + db_driver: org.postgresql.Driver + xray_version: ${XrayVersion} + xray_ha_enabled: false + mode: "0400" + config-xray: + files: + /root/.xray_ami/xray.yml: + content: !Sub | + # Base install for Xray + - import_playbook: site-xray.yml + vars: + jfrog_url: ${JfrogInternalUrl} + use_custom_data_directory: true + custom_data_directory: "${UserDataDirectory}" + master_key: ${MasterKey} + join_key: ${MasterKey} + extra_java_opts: ${ExtraJavaOptions} + db_type: ${DatabaseType} + db_driver: ${DatabaseDriver} + db_master_url: postgresql://${DatabaseUser}:${DatabasePassword}@${XrayMasterDatabaseUrl} + db_url: postgres://${XrayDatabaseUrl} + db_master_user: ${DatabaseUser} + db_user: ${XrayDatabaseUser} + db_password: ${XrayDatabasePassword} + xray_version: ${XrayVersion} + mode: "0400" + /root/.vault_pass.txt: + content: !Sub | + ${DatabasePassword} + mode: "0400" + /root/.secureit.sh: + content: + ansible-vault encrypt /root/.xray_ami/xray.yml --vault-id /root/.vault_pass.txt + mode: "0770" + secure-xray: + commands: + 'secure ansible playbook': + command: '/root/.secureit.sh' + ignoreErrors: 'false' + Properties: + KeyName: !Ref KeyPairName + IamInstanceProfile: !Ref XrayHostProfile + ImageId: !FindInMap + - AWSAMIRegionMap + - !Ref AWS::Region + - 'CentOS7HVM' + SecurityGroups: + - !Ref SecurityGroups + InstanceType: !Ref XrayInstanceType + BlockDeviceMappings: + - DeviceName: /dev/xvda + Ebs: + VolumeSize: !Ref VolumeSize + VolumeType: gp2 + DeleteOnTermination: true + Encrypted: true + UserData: + Fn::Base64: + !Sub | + #!/bin/bash -x + exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1 + + #CFN Functions + + function cfn_fail + + { + + cfn-signal -e 1 --stack ${AWS::StackName} --region ${AWS::Region} --resource XrayScalingGroup + + exit 1 + + } + + function cfn_success + + { + + cfn-signal -e 0 --stack ${AWS::StackName} --region ${AWS::Region} --resource XrayScalingGroup + + exit 0 + + } + + S3URI=${QsS3Uri} + + yum update --security -y &> /var/log/userdata.yum_security_update.log + + yum install -y git python3 libselinux-python3 + yum install -y postgresql-server postgresql-devel + + 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 + + pip install awscli &> /var/log/userdata.awscli_install.log + + pip install ansible &> /var/log/userdata.ansible_install.log + + mkdir ~/.xray_ami + + aws s3 --region ${AWS::Region} sync s3://${QsS3BucketName}/${QsS3KeyPrefix}cloudInstallerScripts/ ~/.xray_ami/ + + setsebool httpd_can_network_connect 1 -P + + # 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 + + cfn-init -v --stack ${AWS::StackName} --resource XrayLaunchConfiguration --configsets xray_install --region ${AWS::Region} || cfn_fail + + # Setup CloudWatch Agent + curl https://s3.amazonaws.com/aws-cloudwatch/downloads/latest/awslogs-agent-setup.py -O + chmod +x ./awslogs-agent-setup.py + ./awslogs-agent-setup.py -n -r ${AWS::Region} -c /root/cloudwatch.conf + + lsblk # debug + + ansible-galaxy collection install community.general ansible.posix + + ansible-playbook /root/.xray_ami/xray-ami-setup.yml --vault-id /root/.vault_pass.txt 2>&1 | tee /var/log/xray-ami.log || cfn_fail + ansible-playbook /root/.xray_ami/xray.yml --vault-id /root/.vault_pass.txt 2>&1 | tee /var/log/xray.log || cfn_fail + + rm -rf /root/.secureit.sh + + cfn_success &> /var/log/cfn_success.log + cfn_success || cfn_fail diff --git a/Amazon/marketplace-jfrog-artifactory/v7174/templates/jfrog-artifactory-core-infrastructure.template.yaml b/Amazon/marketplace-jfrog-artifactory/v7174/templates/jfrog-artifactory-core-infrastructure.template.yaml new file mode 100644 index 0000000..90f0ea8 --- /dev/null +++ b/Amazon/marketplace-jfrog-artifactory/v7174/templates/jfrog-artifactory-core-infrastructure.template.yaml @@ -0,0 +1,360 @@ +AWSTemplateFormatVersion: '2010-09-09' +Description: 'JFrog Artifactory Quick Start Deployment (qs-1qpmmjh61)' +Parameters: + AvailabilityZones: + Description: List of Availability Zones to use for the subnets in the VPC. Two + Availability Zones are used for this deployment. + Type: List + VpcId: + Type: AWS::EC2::VPC::Id + VpcCidr: + Description: CIDR block for the VPC + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.0.0/16 + Type: String + PrivateSubnet1Cidr: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.0.0/19 + Type: String + PrivateSubnet2Cidr: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.32.0/19 + Type: String + PrivateSubnet3Cidr: + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.64.0/19 + Type: String + SubnetIds: + Type: List + DatabaseAllocatedStorage: + Type: Number + MultiAzDatabase: + Description: Choose false to create an Amazon RDS instance in a single Availability Zone. + ConstraintDescription: True or False + AllowedValues: + - "true" + - "false" + Type: String + DatabaseUser: + Type: String + DatabasePassword: + NoEcho: 'true' + Type: String + DatabaseInstance: + Type: String + DatabaseName: + Type: String + ArtifactoryProduct: + Default: JFrog-Artifactory-Pro + Type: String + ReleaseStage: + Default: GA + Type: String + InstanceType: + Default: m5.xlarge + Type: String + ArtifactoryHostRole: + Type: String + VolumeSize: + Type: Number + +Mappings: + ReleaseStageMap: + BETA: + ProDockerRepo: "earlyaccess-docker.jfrog.io/jfrog/artifactory-pro" + JcrDockerRepo: "earlyaccess-docker.jfrog.io/jfrog/artifactory-jcr" + NginxDockerRepo: "earlyaccess-docker.jfrog.io/jfrog/nginx-artifactory-pro" + GA: + ProDockerRepo: "docker.bintray.io/jfrog/artifactory-pro" + JcrDockerRepo: "docker.bintray.io/jfrog/artifactory-jcr" + NginxDockerRepo: "docker.bintray.io/jfrog/nginx-artifactory-pro" + ProductMap: + JFrog-Container-Registry: + RepoName: JcrDockerRepo + JFrog-Artifactory-Pro: + RepoName: ProDockerRepo + JavaOptionstoInstance: + m5.large: + Min: 4 + Max: 4 + DeploymentSize: xxSmall + m5.xlarge: + Min: 8 + Max: 12 + DeploymentSize: xSmall + m5.2xlarge: + Min: 16 + Max: 24 + DeploymentSize: Small + m5.4xlarge: + Min: 32 + Max: 48 + DeploymentSize: Medium + m5.8xlarge: + Min: 64 + Max: 96 + DeploymentSize: Large + m5.12xlarge: + Min: 96 + Max: 144 + DeploymentSize: xLarge + m5.16xlarge: + Min: 128 + Max: 192 + DeploymentSize: xxLarge + m5.24xlarge: + Min: 192 + Max: 288 + DeploymentSize: xxxLarge + m5.metal: + Min: 192 + Max: 288 + DeploymentSize: xxxLarge + m5d.large: + Min: 4 + Max: 4 + DeploymentSize: xxSmall + m5d.xlarge: + Min: 8 + Max: 12 + DeploymentSize: xSmall + m5d.2xlarge: + Min: 16 + Max: 24 + DeploymentSize: Small + m5d.4xlarge: + Min: 32 + Max: 48 + DeploymentSize: Medium + m5d.8xlarge: + Min: 64 + Max: 96 + DeploymentSize: Large + m5d.12xlarge: + Min: 96 + Max: 144 + DeploymentSize: xLarge + m5d.16xlarge: + Min: 128 + Max: 192 + DeploymentSize: xxLarge + m5d.24xlarge: + Min: 192 + Max: 288 + DeploymentSize: xxxLarge + m5d.metal: + Min: 192 + Max: 288 + DeploymentSize: xxxLarge + m5a.large: + Min: 4 + Max: 4 + DeploymentSize: xxSmall + m5a.xlarge: + Min: 8 + Max: 12 + DeploymentSize: xSmall + m5a.2xlarge: + Min: 16 + Max: 24 + DeploymentSize: Small + m5a.4xlarge: + Min: 32 + Max: 48 + DeploymentSize: Medium + m5a.8xlarge: + Min: 64 + Max: 96 + DeploymentSize: Large + m5a.12xlarge: + Min: 96 + Max: 144 + DeploymentSize: xLarge + m5a.16xlarge: + Min: 128 + Max: 192 + DeploymentSize: xxLarge + m5a.24xlarge: + Min: 192 + Max: 288 + DeploymentSize: xxxLarge + m5ad.large: + Min: 4 + Max: 4 + DeploymentSize: xxSmall + m5ad.xlarge: + Min: 8 + Max: 12 + DeploymentSize: xSmall + m5ad.2xlarge: + Min: 16 + Max: 24 + DeploymentSize: Small + m5ad.4xlarge: + Min: 32 + Max: 48 + DeploymentSize: Medium + m5ad.12xlarge: + Min: 96 + Max: 144 + DeploymentSize: xLarge + m5ad.24xlarge: + Min: 192 + Max: 288 + DeploymentSize: xxxLarge + +Resources: + ArtifactoryDatabaseSubnetGroup: + Type: AWS::RDS::DBSubnetGroup + Properties: + DBSubnetGroupDescription: Private Subnets available to the RDS Instance(s) + SubnetIds: !Ref SubnetIds + ArtifactoryDatabase: + Type: AWS::RDS::DBInstance + Properties: + AllocatedStorage: !Ref DatabaseAllocatedStorage + MultiAZ: !Ref MultiAzDatabase + Engine: Postgres + EngineVersion: "11.5" + MasterUsername: !Ref DatabaseUser + MasterUserPassword: !Ref DatabasePassword + DBInstanceClass: !Ref DatabaseInstance + DBName: !Ref DatabaseName + DBSubnetGroupName: !Ref ArtifactoryDatabaseSubnetGroup + StorageEncrypted: true + VPCSecurityGroups: + - !Ref ArtifactoryDatabaseSG + ArtifactoryDatabaseSG: + Type: AWS::EC2::SecurityGroup + Properties: + Tags: + - Key: Name + Value: artifactory-rds-sg + GroupDescription: SG for RDS Instance to allow communication from the Bastion and Artifactory servers. + VpcId: !Ref VpcId + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: 22 + ToPort: 22 + CidrIp: !Ref VpcCidr + - IpProtocol: tcp + FromPort: 5432 + ToPort: 5432 + CidrIp: !Ref PrivateSubnet1Cidr + - IpProtocol: tcp + FromPort: 5432 + ToPort: 5432 + CidrIp: !Ref PrivateSubnet2Cidr + - IpProtocol: tcp + FromPort: 5432 + ToPort: 5432 + CidrIp: !Ref PrivateSubnet3Cidr + SecurityGroupEgress: + - IpProtocol: tcp + FromPort: 22 + ToPort: 22 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 80 + ToPort: 80 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 443 + ToPort: 443 + CidrIp: 0.0.0.0/0 + ArtifactoryS3Bucket: + Type: AWS::S3::Bucket + Properties: + AccessControl: Private + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: AES256 + ArtifactoryS3IAMPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyName: S3BucketPermissions + PolicyDocument: + Version: 2012-10-17 + Statement: + - Sid: S3BucketPermissions + Effect: Allow + Action: + - s3:* + Resource: + - Fn::Join: + - '' + - - !Sub "arn:${AWS::Partition}:s3:::" + - !Ref ArtifactoryS3Bucket + - Fn::Join: + - '' + - - !Sub "arn:${AWS::Partition}:s3:::" + - !Ref ArtifactoryS3Bucket + - "/*" + Roles: + - !Ref ArtifactoryHostRole + ArtifactoryEbsVolume: + Type: AWS::EC2::Volume + Properties: + AvailabilityZone: + !Select + - '0' + - !Ref AvailabilityZones + Encrypted: false + Size: !Ref VolumeSize + Tags: + - Key: Name + Value: !Sub "Artifactory-${AWS::StackName}" + VolumeType: gp2 + DeletionPolicy: Snapshot + UpdateReplacePolicy: Snapshot + +Outputs: + S3Bucket: + Value: !Ref ArtifactoryS3Bucket + Description: Actual S3 bucket created for Artifactory + DatabaseDriver: + Value: "org.postgresql.Driver" + DatabasePlugin: + Value: postgresql-42.2.9.jar + DatabasePluginUrl: + Value: https://jdbc.postgresql.org/download/postgresql-42.2.9.jar" + DatabaseType: + Value: postgresql + DatabaseUrl: + Value: !Sub + - "jdbc:postgresql://${ArtifactoryDatabaseEndpointAddress}:5432/${DatabaseName}" + - ArtifactoryDatabaseEndpointAddress: !GetAtt ArtifactoryDatabase.Endpoint.Address + XrayMasterDatabaseUrl: + Value: !Sub + - "${ArtifactoryDatabaseEndpointAddress}:5432/${DatabaseName}?sslmode=disable" + - ArtifactoryDatabaseEndpointAddress: !GetAtt ArtifactoryDatabase.Endpoint.Address + XrayDatabaseUrl: + Value: !Sub + - "${ArtifactoryDatabaseEndpointAddress}:5432/xraydb?sslmode=disable" + - ArtifactoryDatabaseEndpointAddress: !GetAtt ArtifactoryDatabase.Endpoint.Address + ProDockerRepo: + Value: !FindInMap + - ReleaseStageMap + - !Ref ReleaseStage + - !FindInMap + - ProductMap + - !Ref ArtifactoryProduct + - RepoName + NginxDockerRepo: + Value: !FindInMap [ReleaseStageMap, !Ref ReleaseStage, NginxDockerRepo] + JavaOpts: + Value: !Sub + - "-Xms${min}g -Xmx${max}g" + - { + min: !FindInMap [JavaOptionstoInstance, !Ref InstanceType, Min], + max: !FindInMap [JavaOptionstoInstance, !Ref InstanceType, Max] + } + DeploymentSize: + Value: !FindInMap [JavaOptionstoInstance, !Ref InstanceType, DeploymentSize] + ArtifactoryEbsVolume: + Value: !Ref ArtifactoryEbsVolume diff --git a/Amazon/marketplace-jfrog-artifactory/v7174/templates/jfrog-artifactory-ec2-existing-vpc.template.yaml b/Amazon/marketplace-jfrog-artifactory/v7174/templates/jfrog-artifactory-ec2-existing-vpc.template.yaml new file mode 100644 index 0000000..ea268a5 --- /dev/null +++ b/Amazon/marketplace-jfrog-artifactory/v7174/templates/jfrog-artifactory-ec2-existing-vpc.template.yaml @@ -0,0 +1,802 @@ +AWSTemplateFormatVersion: '2010-09-09' +Description: 'JFrog Artifactory Quick Start Deployment into an Existing VPC (qs-1q037efj0)' +Metadata: + QuickStartDocumentation: + EntrypointName: "Launch into an existing VPC" + AWS::CloudFormation::Interface: + ParameterGroups: + - Label: + default: Security configuration + Parameters: + - KeyPairName + - AccessCidr + - Label: + default: Network configuration + Parameters: + - AvailabilityZones + - VpcId + - VpcCidr + - PublicSubnet1Id + - PublicSubnet2Id + - PrivateSubnet1Id + - PrivateSubnet2Id + - PrivateSubnet1Cidr + - PrivateSubnet2Cidr + - ELBScheme + - Label: + default: Amazon EC2 configuration + Parameters: + - VolumeSize + - InstanceType + - Label: + default: JFrog Artifactory configuration + Parameters: + - NumberOfSecondary + - SmLicenseName + - SmCertName + - ArtifactoryServerName + - MasterKey + - ExtraJavaOptions + - DefaultJavaMemSettings + - Label: + default: Amazon RDS configuration + Parameters: + - DatabaseName + - DatabaseUser + - DatabasePassword + - DatabaseInstance + - DatabaseAllocatedStorage + - MultiAzDatabase + - Label: + default: JFrog Xray Configuration + Parameters: + - InstallXray + - XrayNumberOfInstances + - XrayInstanceType + - XrayDatabaseUser + - XrayDatabasePassword + ParameterLabels: + AvailabilityZones: + default: Availability Zones + KeyPairName: + default: SSH key name + VpcId: + default: VPC ID + VpcCidr: + default: VPC CIDR + PublicSubnet1Id: + default: Public subnet 1 ID + PublicSubnet2Id: + default: Public subnet 2 ID + PrivateSubnet1Id: + default: Private subnet 1 ID + PrivateSubnet2Id: + default: Private subnet 2 ID + PrivateSubnet1Cidr: + default: Private subnet 1 CIDR + PrivateSubnet2Cidr: + default: Private subnet 2 CIDR + AccessCidr: + default: Permitted IP range + ELBScheme: + default: Elastic Load Balancing scheme + VolumeSize: + default: EBS root volume size + InstanceType: + default: EC2 instance type + NumberOfSecondary: + default: Secondary instances + SmLicenseName: + default: Artifactory licenses secret name + SmCertName: + default: Artifactory certificate secret name + ArtifactoryServerName: + default: Artifactory server name + MasterKey: + default: Master server key + ExtraJavaOptions: + default: Extra Java options + DefaultJavaMemSettings: + default: Default Java memory settings + DatabaseName: + default: Database name + DatabaseUser: + default: Database user + DatabasePassword: + default: Database password + DatabaseInstance: + default: Database instance type + DatabaseAllocatedStorage: + default: Database allocated storage + MultiAzDatabase: + default: High-availability database + InstallXray: + default: Install JFrog Xray + XrayNumberOfInstances: + default: Number of JFrog Xray instances + XrayInstanceType: + default: Xray instance type + XrayDatabaseUser: + default: Xray Database user + XrayDatabasePassword: + default: Xray Database password +Parameters: + AvailabilityZones: + Description: List of Availability Zones to use for the subnets in the VPC. Two + Availability Zones are used for this deployment. + Type: List + KeyPairName: + Description: Name of an existing key pair, + which allows you to connect securely to your instance after it launches. + This is the key pair you created in your preferred Region. + Type: AWS::EC2::KeyPair::KeyName + VpcId: + Description: ID of your existing VPC (e.g., vpc-0343606e). + Type: "AWS::EC2::VPC::Id" + VpcCidr: + Description: CIDR block for the VPC. + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.0.0/16 + Type: String + PublicSubnet1Id: + Description: ID of the public subnet in Availability Zone 1 of your existing VPC (e.g., subnet-z0376dab). + Type: "AWS::EC2::Subnet::Id" + PublicSubnet2Id: + Description: ID of the public subnet in Availability Zone 2 of your existing VPC (e.g., subnet-a29c3d84). + Type: "AWS::EC2::Subnet::Id" + PrivateSubnet1Id: + Description: ID of the private subnet in Availability Zone 1 of your existing VPC (e.g., subnet-a0246dcd). + Type: "AWS::EC2::Subnet::Id" + PrivateSubnet2Id: + Description: ID of the private subnet in Availability Zone 2 of your existing VPC (e.g., subnet-b58c3d67). + Type: "AWS::EC2::Subnet::Id" + PrivateSubnet1Cidr: + Description: CIDR of the private subnet in Availability Zone 1 of your existing VPC (e.g., 10.0.0.0/19). + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.0.0/19 + Type: String + PrivateSubnet2Cidr: + Description: CIDR of the private subnet in Availability Zone 2 of your existing VPC (e.g., 10.0.32.0/19). + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ + ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 + Default: 10.0.32.0/19 + Type: String + AccessCidr: + Description: CIDR IP range that is permitted to access Artifactory. + We recommend that you set this value to a trusted IP range. + For example, you might want to grant only your corporate network access to the software. + AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$ + Type: String + ELBScheme: + Description: Choose whether this is internet facing or internal. + AllowedValues: + - internal + - internet-facing + Default: internet-facing + Type: String + VolumeSize: + Description: Size in gigabytes of the available storage (min 10GB); the Quick Start will create an + Amazon Elastic Block Store (Amazon EBS) volumes of this size. + Default: 200 + Type: Number + InstanceType: + Description: EC2 type for the Artifactory instances. + AllowedValues: + - m5.large + - m5.xlarge + - m5.2xlarge + - m5.4xlarge + - m5.8xlarge + - m5.12xlarge + - m5.16xlarge + - m5.24xlarge + - m5.metal + - m5d.large + - m5d.xlarge + - m5d.2xlarge + - m5d.4xlarge + - m5d.8xlarge + - m5d.12xlarge + - m5d.16xlarge + - m5d.24xlarge + - m5d.metal + - m5a.large + - m5a.xlarge + - m5a.2xlarge + - m5a.4xlarge + - m5a.8xlarge + - m5a.12xlarge + - m5a.16xlarge + - m5a.24xlarge + ConstraintDescription: Must contain valid instance type. + Default: m5.xlarge + Type: String + NumberOfSecondary: + Description: Number of secondary Artifactory servers to complete your + HA deployment. To align with Artifactory best practices, the minimum number + is two and the maximum is seven. Do not select more instances than you + have licenses for. + AllowedValues: + - 0 + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + - 7 + Default: 2 + Type: Number + SmLicenseName: + Description: Secret name created in AWS Secrets Manager, which contains the Artifactory licenses. + Default: '' + Type: String + SmCertName: + Description: Secret name created in AWS Secrets Manager, which contains the SSL certificate and certificate key. + Default: '' + Type: String + ArtifactoryServerName: + Description: Name of your Artifactory server. Ensure that this matches your certificate. + Type: String + MasterKey: + Description: Master key for the Artifactory cluster. Generate a master key by using the command '$openssl rand -hex 16'. + AllowedPattern: ^[a-zA-Z0-9]+$ + MinLength: '1' + MaxLength: '64' + ConstraintDescription: Only capital or lowercase letters and numbers, with a Max of 64 characters. + NoEcho: 'true' + Type: String + ExtraJavaOptions: + Description: Set Java options to pass to the JVM for Artifactory. For more information, see the Artifactory + system requirements at https://www.jfrog.com/confluence/display/RTF/System+Requirements#SystemRequirements-RecommendedHardware. + Do not add Xms or Xmx settings without disabling DefaultJavaMemSettings. + Default: -Xss256k -XX:+UseG1GC + Type: String + DefaultJavaMemSettings: + Description: Choose false to overwrite the standard memory-calculation options to pass to the Artifactory JVM. + If you plan to overwrite them, ensure they are added to the ExtraJavaOptions to prevent the stack provision from failing. + ConstraintDescription: True or False + AllowedValues: + - "true" + - "false" + Default: "true" + Type: String + DatabaseName: + Description: Name of your database instance. The name must be unique across all instances + owned by your AWS account in the current Region. The database instance identifier is case-insensitive, + but it's stored in lowercase (as in "mydbinstance"). + AllowedPattern: ^[a-zA-Z]([a-zA-Z0-9])+$ + MinLength: '1' + MaxLength: '60' + ConstraintDescription: 1 to 60 alphanumeric characters First character must be a letter. + Default: artdb + Type: String + DatabaseUser: + Description: Login ID for the master user of your database instance. + MinLength: '1' + MaxLength: '16' + AllowedPattern: ^[a-zA-Z]([a-zA-Z0-9])+$ + ConstraintDescription: 1 to 16 alphanumeric characters. First character must be a letter. + Default: artifactory + Type: String + DatabasePassword: + Description: Password for the Artifactory database user. + AllowedPattern: ^[^ \\']+$ + MinLength: '8' + MaxLength: '12' + ConstraintDescription: Must be at least 8 and no more than + 12 characters containing letters and (minimum 1 capital letter), numbers and + symbols. + NoEcho: 'true' + Type: String + DatabaseInstance: + Description: Size of the database to be deployed as part of the Quick Start. + AllowedValues: + - db.m5.large + - db.m5.xlarge + - db.m5.2xlarge + - db.m5.10xlarge + - db.m5.16xlarge + - db.m5.large + - db.m5.xlarge + - db.m5.2xlarge + - db.m5.4xlarge + - db.m5.12xlarge + - db.m5.24xlarge + ConstraintDescription: Must be a valid database Instance Type. + Default: db.m5.large + Type: String + DatabaseAllocatedStorage: + Description: Size in gigabytes of the available storage for the database instance. + MinValue: 5 + MaxValue: 1024 + Default: 10 + Type: Number + MultiAzDatabase: + Description: Choose false to create an Amazon RDS instance in a single Availability Zone. + ConstraintDescription: True or False + AllowedValues: + - "true" + - "false" + Default: "true" + Type: String + InstallXray: + Description: Choose true to install JFrog Xray instance(s). + ConstraintDescription: True or False + AllowedValues: + - "true" + - "false" + Default: "true" + Type: String + XrayNumberOfInstances: + Description: The number of Xray instances servers to complete your + HA deployment. The minimum number is one; the maximum is seven. + Do not select more than instances than you have licenses for. + MinValue: 1 + MaxValue: 7 + Default: 1 + Type: Number + XrayInstanceType: + Description: The EC2 instance type for the Xray instances. + AllowedValues: + - c5.2xlarge + - c5.4xlarge + ConstraintDescription: Must contain valid instance type. + Default: c5.2xlarge + Type: String + XrayDatabaseUser: + Description: The login ID for the Xray database user. + MinLength: '1' + MaxLength: '16' + AllowedPattern: ^[a-zA-Z]([a-zA-Z0-9])+$ + ConstraintDescription: 1 to 16 alphanumeric characters. First character must be a letter. + Default: xray + Type: String + XrayDatabasePassword: + Description: The password for the Xray database user. + AllowedPattern: ^[^ \\']+$ + MinLength: '8' + MaxLength: '12' + ConstraintDescription: Must be at least 8 and no more than + 12 characters containing letters and (minimum 1 capital letter), numbers and + symbols. + NoEcho: 'true' + Type: String + +Conditions: + HasSecondaryNodes: !Not [!Equals [!Ref NumberOfSecondary, '0']] + DefaultJava: !Equals [!Ref DefaultJavaMemSettings, "true"] + EnableXray: !Equals [!Ref InstallXray, 'true'] + SmCertNameExists: !Not [!Equals [!Ref 'SmCertName', '']] + +Resources: + ArtifactoryCoreInfraStack: + Type: AWS::CloudFormation::Stack + Properties: + TemplateURL: https://jfrog-marketplace-test-us-east-1.s3.amazonaws.com/marketplace-jfrog-artifactory/v7174/templates/jfrog-artifactory-core-infrastructure.template.yaml + Parameters: + AvailabilityZones: + Fn::Join: + - ',' + - Ref: AvailabilityZones + VpcId: !Ref VpcId + VpcCidr: !Ref VpcCidr + PrivateSubnet1Cidr: !Ref PrivateSubnet1Cidr + PrivateSubnet2Cidr: !Ref PrivateSubnet2Cidr + PrivateSubnet3Cidr: !Ref PrivateSubnet2Cidr # This should end up in no new rule but required for EKS + SubnetIds: !Join [",", [!Ref PrivateSubnet1Id, !Ref PrivateSubnet2Id]] + DatabaseAllocatedStorage: !Ref DatabaseAllocatedStorage + MultiAzDatabase: !Ref MultiAzDatabase + DatabaseUser: !Ref DatabaseUser + DatabasePassword: !Ref DatabasePassword + DatabaseInstance: !Ref DatabaseInstance + DatabaseName: !Ref DatabaseName + InstanceType: !Ref InstanceType + ArtifactoryHostRole: !Ref ArtifactoryHostRole + VolumeSize: !Ref VolumeSize + ArtifactoryElb: + Type: AWS::ElasticLoadBalancingV2::LoadBalancer + Properties: + IpAddressType: ipv4 + Scheme: !Ref ELBScheme + Subnets: + - !Ref PublicSubnet1Id + - !Ref PublicSubnet2Id + Type: network + ArtifactorySslTargetGroup: + Type: AWS::ElasticLoadBalancingV2::TargetGroup + Properties: + HealthCheckEnabled: True + HealthCheckIntervalSeconds: 30 + HealthCheckProtocol: TCP + HealthCheckTimeoutSeconds: 10 + HealthyThresholdCount: 3 + HealthCheckPort: "8082" + Port: 443 + Protocol: TCP + TargetType: instance + UnhealthyThresholdCount: 3 + VpcId: !Ref VpcId + ArtifactoryTargetGroup: + Type: AWS::ElasticLoadBalancingV2::TargetGroup + Properties: + HealthCheckEnabled: True + HealthCheckIntervalSeconds: 30 + HealthCheckProtocol: TCP + HealthCheckTimeoutSeconds: 10 + HealthyThresholdCount: 3 + HealthCheckPort: "8082" + Port: 80 + Protocol: TCP + TargetType: instance + UnhealthyThresholdCount: 3 + VpcId: !Ref VpcId + ArtifactorySslElbListener: + Type: AWS::ElasticLoadBalancingV2::Listener + Properties: + DefaultActions: + - TargetGroupArn: !Ref ArtifactorySslTargetGroup + Type: forward + LoadBalancerArn: !Ref ArtifactoryElb + Port: 443 + Protocol: TCP + ArtifactoryElbListener: + Type: AWS::ElasticLoadBalancingV2::Listener + Properties: + DefaultActions: + - TargetGroupArn: !Ref ArtifactoryTargetGroup + Type: forward + LoadBalancerArn: !Ref ArtifactoryElb + Port: 80 + Protocol: TCP + ArtifactoryInternalElb: + Type: AWS::ElasticLoadBalancingV2::LoadBalancer + Properties: + IpAddressType: ipv4 + Scheme: internal + Subnets: + - !Ref PrivateSubnet1Id + - !Ref PrivateSubnet2Id + Type: network + ArtifactoryInternalTargetGroup: + Type: AWS::ElasticLoadBalancingV2::TargetGroup + Properties: + HealthCheckEnabled: True + HealthCheckIntervalSeconds: 30 + HealthCheckProtocol: TCP + HealthCheckTimeoutSeconds: 10 + HealthyThresholdCount: 3 + HealthCheckPort: "8082" + Port: 80 + Protocol: TCP + TargetType: instance + UnhealthyThresholdCount: 3 + VpcId: !Ref VpcId + ArtifactoryInternalElbListener: + Type: AWS::ElasticLoadBalancingV2::Listener + Properties: + DefaultActions: + - TargetGroupArn: !Ref ArtifactoryInternalTargetGroup + Type: forward + LoadBalancerArn: !Ref ArtifactoryInternalElb + Port: 80 + Protocol: TCP + ArtifactoryEc2Sg: + Type: AWS::EC2::SecurityGroup + Properties: + Tags: + - Key: Name + Value: "JFrog-Artifactory-Pro-ec2-instances-sg" + GroupDescription: SG for EC2 instances + VpcId: !Ref VpcId + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: 22 + ToPort: 22 + CidrIp: !Ref VpcCidr + - IpProtocol: tcp + FromPort: 80 + ToPort: 80 + CidrIp: !Ref VpcCidr + - IpProtocol: tcp + FromPort: 80 + ToPort: 80 + CidrIp: !Ref AccessCidr + - IpProtocol: tcp + FromPort: 443 + ToPort: 443 + CidrIp: !Ref AccessCidr + - IpProtocol: tcp + FromPort: 443 + ToPort: 443 + CidrIp: !Ref VpcCidr + - IpProtocol: tcp + FromPort: 8081 + ToPort: 8082 + CidrIp: !Ref VpcCidr + - IpProtocol: tcp + FromPort: 8046 + ToPort: 8046 + CidrIp: !Ref VpcCidr + SecurityGroupEgress: + - IpProtocol: "-1" + CidrIp: 0.0.0.0/0 + ArtifactoryHostRole: + Type: 'AWS::IAM::Role' + Properties: + Path: / + AssumeRolePolicyDocument: + Statement: + - Action: + - 'sts:AssumeRole' + Principal: + Service: + - ec2.amazonaws.com + Effect: Allow + Version: 2012-10-17 + ManagedPolicyArns: + - !Sub 'arn:${AWS::Partition}:iam::aws:policy/service-role/AmazonEC2RoleforSSM' + Policies: + - PolicyName: "JFrogAMI-policy" + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: "Allow" + Action: "ec2:Describe*" + Resource: "*" + - Effect: "Allow" + Action: "ec2:AttachVolume" + Resource: "*" + - Effect: "Allow" + Action: "ec2:DetachVolume" + Resource: "*" + - Effect: "Allow" + Action: + - "s3:GetObject" + - "s3:ListObject" + - "s3:ListBucket" + Resource: "*" + - PolicyName: 'CloudWatch-policy' + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: "Allow" + Action: + - "logs:CreateLogGroup" + - "logs:CreateLogStream" + - "logs:PutLogEvents" + - "logs:DescribeLogStreams" + Resource: !Sub "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:*:*" + - PolicyName: 'SecretsManager-policy' + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: "Allow" + Action: + - "secretsmanager:GetSecretValue" + Resource: !Sub "arn:${AWS::Partition}:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:*" + ArtifactoryHostProfile: + Type: AWS::IAM::InstanceProfile + Properties: + Roles: + - !Ref ArtifactoryHostRole + Path: / + ArtifactoryPrimary: + Type: AWS::CloudFormation::Stack + Properties: + TemplateURL: https://jfrog-marketplace-test-us-east-1.s3.amazonaws.com/marketplace-jfrog-artifactory/v7174/templates/jfrog-artifactory-ec2-instance.template.yaml + Parameters: + PrivateSubnetIds: !Join [',', [!Ref PrivateSubnet1Id]] + MinScalingNodes: '1' # Always have 1 Primary Node + MaxScalingNodes: '1' # Always have 1 Primary Node + DeploymentTag: "ArtifactoryPrimary" + HostRole: !Ref ArtifactoryHostRole + ArtifactoryProduct: "JFrog-Artifactory-Pro" + ArtifactoryLicensesSecretName: !Ref SmLicenseName + ArtifactoryServerName: !Ref ArtifactoryServerName + EnableSSL: !If [SmCertNameExists, true, false] + Certificate: !If [SmCertNameExists, !Sub '{{resolve:secretsmanager:${SmCertName}:SecretString:Certificate}}', ''] + CertificateKey: !If [SmCertNameExists, !Sub '{{resolve:secretsmanager:${SmCertName}:SecretString:CertificateKey}}', ''] + CertificateDomain: !If [SmCertNameExists, !Sub '{{resolve:secretsmanager:${SmCertName}:SecretString:CertificateDomain}}', ''] + ArtifactoryS3Bucket: !GetAtt ArtifactoryCoreInfraStack.Outputs.S3Bucket + DatabaseUrl: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseUrl + DatabaseDriver: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseDriver + DatabasePlugin: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabasePlugin + DatabasePluginUrl: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabasePluginUrl + DatabaseType: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseType + DatabaseUser: !Ref DatabaseUser + DatabasePassword: !Ref DatabasePassword + ArtifactoryPrimary: true + MasterKey: !Ref MasterKey + ExtraJavaOptions: !If [DefaultJava, !Sub "${ArtifactoryCoreInfraStack.Outputs.JavaOpts} ${ExtraJavaOptions}", !Ref ExtraJavaOptions] + AmiId: "7174" + ArtifactoryVersion: "7.17.4" + KeyPairName: !Ref KeyPairName + HostProfile: !Ref ArtifactoryHostProfile + SecurityGroups: !Ref ArtifactoryEc2Sg + InstanceType: !Ref InstanceType + PrimaryVolume: !GetAtt ArtifactoryCoreInfraStack.Outputs.ArtifactoryEbsVolume + VolumeSize: !Ref VolumeSize + TargetGroupARN: !Ref ArtifactoryTargetGroup + SSLTargetGroupARN: !Ref ArtifactorySslTargetGroup + InternalTargetGroupARN: !Ref ArtifactoryInternalTargetGroup + + ArtifactorySecondary: + Condition: HasSecondaryNodes + DependsOn: ArtifactoryPrimary + Type: AWS::CloudFormation::Stack + Properties: + TemplateURL: https://jfrog-marketplace-test-us-east-1.s3.amazonaws.com/marketplace-jfrog-artifactory/v7174/templates/jfrog-artifactory-ec2-instance.template.yaml + Parameters: + PrivateSubnetIds: !Join [',', [!Ref PrivateSubnet1Id, !Ref PrivateSubnet2Id]] + MinScalingNodes: !Ref NumberOfSecondary + MaxScalingNodes: !Ref NumberOfSecondary + DeploymentTag: ArtifactorySecondary + HostRole: !Ref ArtifactoryHostRole + ArtifactoryProduct: "JFrog-Artifactory-Pro" + ArtifactoryLicensesSecretName: !Ref SmLicenseName + ArtifactoryServerName: !Ref ArtifactoryServerName + EnableSSL: !If [SmCertNameExists, true, false] + Certificate: !If [SmCertNameExists, !Sub '{{resolve:secretsmanager:${SmCertName}:SecretString:Certificate}}', ''] + CertificateKey: !If [SmCertNameExists, !Sub '{{resolve:secretsmanager:${SmCertName}:SecretString:CertificateKey}}', ''] + CertificateDomain: !If [SmCertNameExists, !Sub '{{resolve:secretsmanager:${SmCertName}:SecretString:CertificateDomain}}', ''] + ArtifactoryS3Bucket: !GetAtt ArtifactoryCoreInfraStack.Outputs.S3Bucket + DatabaseUrl: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseUrl + DatabaseDriver: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseDriver + DatabasePlugin: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabasePlugin + DatabasePluginUrl: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabasePluginUrl + DatabaseType: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseType + DatabaseUser: !Ref DatabaseUser + DatabasePassword: !Ref DatabasePassword + ArtifactoryPrimary: false + MasterKey: !Ref MasterKey + ExtraJavaOptions: !If [DefaultJava, !Sub "${ArtifactoryCoreInfraStack.Outputs.JavaOpts} ${ExtraJavaOptions}", !Ref ExtraJavaOptions] + AmiId: "7174" + ArtifactoryVersion: "7.17.4" + KeyPairName: !Ref KeyPairName + HostProfile: !Ref ArtifactoryHostProfile + SecurityGroups: !Ref ArtifactoryEc2Sg + InstanceType: !Ref InstanceType + PrimaryVolume: !GetAtt ArtifactoryCoreInfraStack.Outputs.ArtifactoryEbsVolume + VolumeSize: !Ref VolumeSize + TargetGroupARN: !Ref ArtifactoryTargetGroup + SSLTargetGroupARN: !Ref ArtifactorySslTargetGroup + InternalTargetGroupARN: !Ref ArtifactoryInternalTargetGroup + XrayHostRole: + Condition: EnableXray + Type: AWS::IAM::Role + Properties: + Path: / + AssumeRolePolicyDocument: + Statement: + - Action: + - 'sts:AssumeRole' + Principal: + Service: + - ec2.amazonaws.com + Effect: Allow + Version: 2012-10-17 + ManagedPolicyArns: + - !Sub 'arn:${AWS::Partition}:iam::aws:policy/service-role/AmazonEC2RoleforSSM' + Policies: + - PolicyName: "JFrogAMI-policy" + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: "Allow" + Action: "ec2:Describe*" + Resource: "*" + - Effect: "Allow" + Action: "ec2:AttachVolume" + Resource: "*" + - Effect: "Allow" + Action: "ec2:DetachVolume" + Resource: "*" + - Effect: "Allow" + Action: + - "s3:GetObject" + - "s3:ListObject" + - "s3:ListBucket" + Resource: "*" + - PolicyName: 'CloudWatch-policy' + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: "Allow" + Action: + - "logs:CreateLogGroup" + - "logs:CreateLogStream" + - "logs:PutLogEvents" + - "logs:DescribeLogStreams" + Resource: !Sub "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:*:*" + XrayHostProfile: + Condition: EnableXray + Type: 'AWS::IAM::InstanceProfile' + Properties: + Roles: + - !Ref XrayHostRole + Path: / + XrayExistingVpcStack: + Condition: EnableXray + DependsOn: ArtifactoryPrimary + Type: AWS::CloudFormation::Stack + Properties: + TemplateURL: https://jfrog-marketplace-test-us-east-1.s3.amazonaws.com/marketplace-jfrog-artifactory/v7174/templates/jfrog-xray-ec2-instance.template.yaml + Parameters: + PrivateSubnet1Id: !Ref PrivateSubnet1Id + PrivateSubnet2Id: !Ref PrivateSubnet2Id + KeyPairName: !Ref KeyPairName + MinScalingNodes: !Ref XrayNumberOfInstances + MaxScalingNodes: !Ref XrayNumberOfInstances + DeploymentTag: 'xray' + DatabaseDriver: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseDriver + DatabaseType: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseType + DatabaseUser: !Ref DatabaseUser + DatabasePassword: !Ref DatabasePassword + MasterKey: !Ref MasterKey + SecurityGroups: !Ref ArtifactoryEc2Sg + VolumeSize: !Ref VolumeSize + ExtraJavaOptions: !GetAtt ArtifactoryCoreInfraStack.Outputs.JavaOpts + XrayInstanceType: !Ref XrayInstanceType + JfrogInternalUrl: !Sub "http://${ArtifactoryInternalElb.DNSName}" + XrayDatabaseUser: !Ref XrayDatabaseUser + XrayDatabasePassword: !Ref XrayDatabasePassword + XrayMasterDatabaseUrl: !GetAtt ArtifactoryCoreInfraStack.Outputs.XrayMasterDatabaseUrl + XrayDatabaseUrl: !GetAtt ArtifactoryCoreInfraStack.Outputs.XrayDatabaseUrl + XrayVersion: "3.21.2" + XrayAmiId: "3212" + XrayHostRole: !Ref XrayHostRole + XrayHostProfile: !Ref XrayHostProfile +Outputs: + ArtifactoryUrl: + Description: URL of the ELB to access Artifactory + Value: !If [SmCertNameExists, !Sub "https://${ArtifactoryElb.DNSName}", !Sub "http://${ArtifactoryElb.DNSName}"] + Export: + Name: !Sub '${AWS::StackName}-ArtifactoryUrl' + ArtifactoryInternalUrl: + Description: URL of the internal ELB to access Artifactory + Value: !Sub "http://${ArtifactoryInternalElb.DNSName}" + Export: + Name: !Sub '${AWS::StackName}-ArtifactoryInternalUrl' + DatabaseType: + Description: Type of database + Value: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseType + Export: + Name: !Sub '${AWS::StackName}-DatabaseType' + DatabaseDriver: + Description: Database driver + Value: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseDriver + Export: + Name: !Sub '${AWS::StackName}-DatabaseDriver' + DatabaseUrl: + Description: Database driver + Value: !GetAtt ArtifactoryCoreInfraStack.Outputs.DatabaseUrl + Export: + Name: !Sub '${AWS::StackName}-DatabaseUrl' + ArtifactoryTargetGroup: + Description: Artifactory target group + Value: !Ref ArtifactoryTargetGroup + Export: + Name: !Sub '${AWS::StackName}-ArtifactoryTargetGroup' + ArtifactorySslTargetGroup: + Description: Artifactory SSL target group + Value: !Ref ArtifactorySslTargetGroup + Export: + Name: !Sub '${AWS::StackName}-ArtifactorySslTargetGroup' + ArtifactoryEc2Sg: + Description: Artifactory EC2 sercurity group + Value: !Ref ArtifactoryEc2Sg + Export: + Name: !Sub '${AWS::StackName}-ArtifactoryEc2Sg' + XrayMasterDatabaseUrl: + Description: Database driver + Value: !GetAtt ArtifactoryCoreInfraStack.Outputs.XrayMasterDatabaseUrl + Export: + Name: !Sub '${AWS::StackName}-XrayMasterDatabaseUrl' + XrayDatabaseUrl: + Description: Database driver + Value: !GetAtt ArtifactoryCoreInfraStack.Outputs.XrayDatabaseUrl + Export: + Name: !Sub '${AWS::StackName}-XrayDatabaseUrl' diff --git a/Amazon/marketplace-jfrog-artifactory/v7174/templates/jfrog-artifactory-ec2-instance.template.yaml b/Amazon/marketplace-jfrog-artifactory/v7174/templates/jfrog-artifactory-ec2-instance.template.yaml new file mode 100644 index 0000000..b351bd5 --- /dev/null +++ b/Amazon/marketplace-jfrog-artifactory/v7174/templates/jfrog-artifactory-ec2-instance.template.yaml @@ -0,0 +1,367 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: "Deploys the EC2 Autoscaling, LaunchConfig and Instance for Artifactory (qs-1qpmmjh5o)" +Parameters: + PrivateSubnetIds: + Type: List + MinScalingNodes: + Type: Number + MaxScalingNodes: + Type: Number + DeploymentTag: + Type: String + HostRole: + Type: String + AmiId: + Type: String + ArtifactoryProduct: + Type: String + ArtifactoryLicensesSecretName: + Type: String + ArtifactoryServerName: + Type: String + Certificate: + Type: String + CertificateKey: + Type: String + NoEcho: 'true' + CertificateDomain: + Type: String + EnableSSL: + Type: String + 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 + PrimaryVolume: + Type: String + VolumeSize: + Type: Number + UserDataDirectory: + Description: Directory to store Artifactory data. Can be used to store data (via symlink) in detachable volume + Type: String + Default: '/artifactory-user-data' + +Mappings: + AWSAMIRegionMap: + us-east-1: + "Artifactory7174": ami-0c1b46ce4d4261d8d + us-east-2: + "Artifactory7174": xxxxxxx + us-west-1: + "Artifactory7174": xxxxxxx + us-west-2: + "Artifactory7174": xxxxxxx + ca-central-1: + "Artifactory7174": xxxxxxx + eu-central-1: + "Artifactory7174": xxxxxxx + eu-west-1: + "Artifactory7174": xxxxxxx + eu-west-2: + "Artifactory7174": xxxxxxx + eu-west-3: + "Artifactory7174": xxxxxxx + ap-southeast-1: + "Artifactory7174": xxxxxxx + ap-southeast-2: + "Artifactory7174": xxxxxxx + ap-south-1: + "Artifactory7174": xxxxxxx + ap-northeast-1: + "Artifactory7174": xxxxxxx + ap-northeast-2: + "Artifactory7174": xxxxxxx + sa-east-1: + "Artifactory7174": xxxxxxx + us-gov-east-1: + "Artifactory7174": ami-0796bc1304b9a6937 + us-gov-west-1: + "Artifactory7174": xxxxxxx + ArtifactoryProductMap: + JFrog-Artifactory-Pro: + "7174": "Artifactory7174" + product: "artifactory" + +Conditions: + IsSecondary: !Equals [!Ref ArtifactoryPrimary, 'false'] + +Resources: + ArtifactoryScalingGroup: + Type: AWS::AutoScaling::AutoScalingGroup + Properties: + LaunchConfigurationName: !Ref ArtifactoryLaunchConfiguration + VPCZoneIdentifier: !Ref PrivateSubnetIds + MinSize: !Ref MinScalingNodes + MaxSize: !Ref MaxScalingNodes + Cooldown: '300' + DesiredCapacity: !Ref MinScalingNodes + TargetGroupARNs: + - !Ref TargetGroupARN + - !Ref SSLTargetGroupARN + - !Ref InternalTargetGroupARN + HealthCheckType: ELB + HealthCheckGracePeriod: 1800 + Tags: + - Key: Name + Value: !Ref DeploymentTag + PropagateAtLaunch: true + - Key: ArtifactoryVersion + Value: !Ref ArtifactoryVersion + PropagateAtLaunch: true + TerminationPolicies: + - OldestInstance + - Default + CreationPolicy: + ResourceSignal: + Count: !Ref MinScalingNodes + Timeout: PT60M + + ArtifactoryLaunchConfiguration: + Type: 'AWS::AutoScaling::LaunchConfiguration' + Metadata: + AWS::CloudFormation::Init: + configSets: + artifactory_install: + - "config-cloudwatch" + - "config-artifactory-primary" + - "secure-artifactory" + config-cloudwatch: + files: + /root/cloudwatch.conf: + content: | + [general] + state_file = /var/awslogs/state/agent-state + + [/var/log/messages] + file = /var/log/messages + log_group_name = /artifactory/instances/{instance_id} + log_stream_name = /var/log/messages/ + datetime_format = %b %d %H:%M:%S + + [/var/log/jfrog-ami-setup.log] + file = /var/log/messages + log_group_name = /artifactory/instances/{instance_id} + log_stream_name = /var/log/jfrog-ami-setup.log + datetime_format = %b %d %H:%M:%S + + [/var/log/jfrog-ami-artifactory.log] + file = /var/log/messages + log_group_name = /artifactory/instances/{instance_id} + log_stream_name = /var/log/jfrog-ami-artifactory.log + datetime_format = %b %d %H:%M:%S + mode: "0400" + config-artifactory-primary: + files: + /root/attach_volume.sh: + content: !Sub | + #!/usr/bin/env bash + IS_PRIMARY="${ArtifactoryPrimary}" + + if [[ $IS_PRIMARY != "true" ]]; then + echo 'Not primary node. Skipping EBS volume attachment.' + lsblk # debug + exit 0 + fi + + echo "Using primary volume ID ${PrimaryVolume}" + VOLUME_ID="${PrimaryVolume}" + echo "VOLUME_ID: $VOLUME_ID" + if [[ -z "$VOLUME_ID" ]]; then + echo 'Invalid $VOLUME_ID' + exit 1 + fi + + # Get instance id from AWS + INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id) + + # Attach the volume created by another CFT + # the device name should become /dev/nvme1n1 + # See: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nvme-ebs-volumes.html + echo "Attaching volume $VOLUME_ID to instance $INSTANCE_ID" + /var/awslogs/bin/aws ec2 attach-volume --volume-id $VOLUME_ID --instance-id $INSTANCE_ID --device /dev/xvdf --region ${AWS::Region} + + echo "Wait for volume $VOLUME_ID to attach" + sleep 30 # Give volume time to attach + lsblk # debug + mode: "0770" + /root/.jfrog_ami/artifactory.yml: + content: !Sub + - | + # Base install for Artifactory + - import_playbook: site-artifactory.yml + vars: + artifactory_product: ${product} + artifactory_flavour: "{{ 'pro' if '${product}' == 'artifactory' else 'jcr' if '${product}' == 'jcr' }}" + artifactory_ha_enabled: true + artifactory_is_primary: ${ArtifactoryPrimary} + artifactory_server_name: ${ArtifactoryServerName} + server_name: ${ArtifactoryServerName}.${CertificateDomain} + use_custom_data_directory: true + custom_data_directory: "${UserDataDirectory}" + s3_region: ${AWS::Region} + 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: ${DatabasePassword} + 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 | + ${DatabasePassword} + 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: + 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: + !If + - IsSecondary + - - DeviceName: /dev/xvda + Ebs: + VolumeSize: !Ref VolumeSize + VolumeType: gp2 + DeleteOnTermination: true + Encrypted: true + - !Ref AWS::NoValue + 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 + + } + + # Install jq + yum install -y epel-release + yum install -y jq + + echo $PATH + + PATH=/opt/aws/bin:$PATH + + echo $PATH + + # Activate virtual env + source ~/venv/bin/activate + + setsebool httpd_can_network_connect 1 -P + + # 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 + + cfn-init -v --stack ${AWS::StackName} --resource ArtifactoryLaunchConfiguration --configsets artifactory_install --region ${AWS::Region} || cfn_fail + + # Setup CloudWatch Agent + curl https://s3.amazonaws.com/aws-cloudwatch/downloads/latest/awslogs-agent-setup.py -O + chmod +x ./awslogs-agent-setup.py + ./awslogs-agent-setup.py -n -r ${AWS::Region} -c /root/cloudwatch.conf 2>&1 | tee /var/log/userdata.cloudwatch_agent_install.log + + /root/attach_volume.sh || cfn_fail + + setsebool httpd_can_network_connect 1 -P + + aws secretsmanager get-secret-value --secret-id ${ArtifactoryLicensesSecretName} --region ${AWS::Region} | jq -r '{"artifactory_licenses":(.SecretString | fromjson )}' > ~/.jfrog_ami/licenses.json || cfn_fail + + ansible-playbook /root/.jfrog_ami/artifactory.yml -e "@~/.jfrog_ami/licenses.json" --vault-id /root/.vault_pass.txt 2>&1 | tee /var/log/jfrog-ami-artifactory.log || cfn_fail + + rm -rf /root/.secureit.sh + + cfn_success &> /var/log/cfn_success.log + cfn_success || cfn_fail diff --git a/Amazon/marketplace-jfrog-artifactory/v7174/templates/jfrog-xray-ec2-instance.template.yaml b/Amazon/marketplace-jfrog-artifactory/v7174/templates/jfrog-xray-ec2-instance.template.yaml new file mode 100644 index 0000000..8b5f422 --- /dev/null +++ b/Amazon/marketplace-jfrog-artifactory/v7174/templates/jfrog-xray-ec2-instance.template.yaml @@ -0,0 +1,255 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: "Deploys the EC2 Autoscaling, LaunchConfig and Instance for Xray" +Parameters: + PrivateSubnet1Id: + Type: AWS::EC2::Subnet::Id + PrivateSubnet2Id: + Type: AWS::EC2::Subnet::Id + KeyPairName: + Type: AWS::EC2::KeyPair::KeyName + MinScalingNodes: + Type: Number + MaxScalingNodes: + Type: Number + DeploymentTag: + Type: String + DatabaseDriver: + Type: String + DatabaseType: + Type: String + DatabaseUser: + Type: String + DatabasePassword: + Type: String + NoEcho: 'true' + MasterKey: + Type: String + NoEcho: 'true' + ExtraJavaOptions: + Type: String + SecurityGroups: + Type: String + VolumeSize: + Type: Number + XrayHostProfile: + Type: String + XrayHostRole: + Type: String + XrayInstanceType: + Type: String + JfrogInternalUrl: + Type: String + XrayDatabaseUser: + Type: String + XrayDatabasePassword: + Type: String + NoEcho: 'true' + XrayMasterDatabaseUrl: + Type: String + XrayDatabaseUrl: + Type: String + XrayVersion: + Type: String + XrayAmiId: + Type: String + +# 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: + us-east-1: + "3212": ami-043e27c61f75d25dc + us-east-2: + "3212": xxxxxxxxxx + us-west-1: + "3212": xxxxxxxxxx + us-west-2: + "3212": xxxxxxxxxx + ca-central-1: + "3212": xxxxxxxxxx + eu-central-1: + "3212": xxxxxxxxxx + eu-west-1: + "3212": xxxxxxxxxx + eu-west-2: + "3212": xxxxxxxxxx + eu-west-3: + "3212": xxxxxxxxxx + ap-southeast-1: + "3212": xxxxxxxxxx + ap-southeast-2: + "3212": xxxxxxxxxx + ap-south-1: + "3212": xxxxxxxxxx + ap-northeast-1: + "3212": xxxxxxxxxx + ap-northeast-2: + "3212": xxxxxxxxxx + sa-east-1: + "3212": xxxxxxxxxx + us-gov-east-1: + "3212": ami-057fbdfe9cbdd7386 + us-gov-west-1: + "3212": xxxxxxxxxx + +Resources: + XrayScalingGroup: + Type: AWS::AutoScaling::AutoScalingGroup + Properties: + LaunchConfigurationName: !Ref XrayLaunchConfiguration + VPCZoneIdentifier: + - !Ref PrivateSubnet1Id + - !Ref PrivateSubnet2Id + MinSize: !Ref MinScalingNodes + MaxSize: !Ref MaxScalingNodes + Cooldown: '300' + DesiredCapacity: !Ref MinScalingNodes + HealthCheckType: EC2 + HealthCheckGracePeriod: 1800 + Tags: + - Key: Name + Value: !Ref DeploymentTag + PropagateAtLaunch: true + - Key: XrayVersion + Value: !Ref XrayVersion + PropagateAtLaunch: true + TerminationPolicies: + - OldestInstance + - Default + CreationPolicy: + ResourceSignal: + Count: !Ref MinScalingNodes + Timeout: PT60M + XrayLaunchConfiguration: + Type: AWS::AutoScaling::LaunchConfiguration + Metadata: + AWS::CloudFormation::Init: + configSets: + xray_install: + - "config-cloudwatch" + - "config-xray" + config-cloudwatch: + files: + /root/cloudwatch.conf: + content: | + [general] + state_file = /var/awslogs/state/agent-state + + [/var/log/messages] + file = /var/log/messages + log_group_name = /xray/instances/{instance_id} + log_stream_name = /var/log/messages/ + datetime_format = %b %d %H:%M:%S + + [/var/log/xray-ami-setup.log] + file = /var/log/messages + log_group_name = /xray/instances/{instance_id} + log_stream_name = /var/log/xray-ami-setup.log + datetime_format = %b %d %H:%M:%S + + [/var/log/xray.log] + file = /var/log/messages + log_group_name = /xray/instances/{instance_id} + log_stream_name = /var/log/xray.log + datetime_format = %b %d %H:%M:%S + mode: "0400" + config-xray: + files: + /root/.xray_ami/xray.yml: + content: !Sub | + # Base install for Xray + - import_playbook: site-xray.yml + vars: + jfrog_url: ${JfrogInternalUrl} + master_key: ${MasterKey} + join_key: ${MasterKey} + extra_java_opts: ${ExtraJavaOptions} + db_type: ${DatabaseType} + db_driver: ${DatabaseDriver} + db_master_url: postgresql://${DatabaseUser}:${DatabasePassword}@${XrayMasterDatabaseUrl} + db_url: postgres://${XrayDatabaseUrl} + db_master_user: ${DatabaseUser} + db_user: ${XrayDatabaseUser} + db_password: ${XrayDatabasePassword} + xray_version: ${XrayVersion} + mode: "0400" + /root/.vault_pass.txt: + content: !Sub | + ${DatabasePassword} + mode: "0400" + Properties: + KeyName: !Ref KeyPairName + IamInstanceProfile: !Ref XrayHostProfile + ImageId: !FindInMap + - AWSAMIRegionMap + - !Ref AWS::Region + - !Ref XrayAmiId + SecurityGroups: + - !Ref SecurityGroups + InstanceType: !Ref XrayInstanceType + BlockDeviceMappings: + - DeviceName: /dev/xvda + Ebs: + VolumeSize: !Ref VolumeSize + VolumeType: gp2 + DeleteOnTermination: true + Encrypted: true + UserData: + Fn::Base64: + !Sub | + #!/bin/bash -x + exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1 + + #CFN Functions + + function cfn_fail + + { + + cfn-signal -e 1 --stack ${AWS::StackName} --region ${AWS::Region} --resource XrayScalingGroup + + exit 1 + + } + + function cfn_success + + { + + cfn-signal -e 0 --stack ${AWS::StackName} --region ${AWS::Region} --resource XrayScalingGroup + + exit 0 + + } + + echo $PATH + + PATH=/opt/aws/bin:$PATH + + echo $PATH + + # Activate virtual env + source ~/venv/bin/activate + + setsebool httpd_can_network_connect 1 -P + + # 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 + + cfn-init -v --stack ${AWS::StackName} --resource XrayLaunchConfiguration --configsets xray_install --region ${AWS::Region} || cfn_fail + + # Setup CloudWatch Agent + curl https://s3.amazonaws.com/aws-cloudwatch/downloads/latest/awslogs-agent-setup.py -O + chmod +x ./awslogs-agent-setup.py + ./awslogs-agent-setup.py -n -r ${AWS::Region} -c /root/cloudwatch.conf + + lsblk # debug + + ansible-playbook /root/.xray_ami/xray.yml --vault-id /root/.vault_pass.txt 2>&1 | tee /var/log/xray.log || cfn_fail + + rm -rf /root/.secureit.sh + + cfn_success &> /var/log/cfn_success.log + cfn_success || cfn_fail