diff --git a/.gitignore b/.gitignore index dd41ef25b..72faa30e7 100644 --- a/.gitignore +++ b/.gitignore @@ -155,7 +155,7 @@ override.tf override.tf.json *_override.tf *_override.tf.json -templates/core/tre_output.json +tre_output.json # generated backend files *_backend.tf diff --git a/Makefile b/Makefile index 8aa2b2bf2..9117ea825 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,13 @@ build-and-push-api: build-api-image push-api-image build-and-push-resource-processor: build-resource-processor-vm-porter-image push-resource-processor-vm-porter-image build-and-push-gitea: build-gitea-image push-gitea-image build-and-push-guacamole: build-guacamole-image push-guacamole-image +tre-deploy: deploy-core deploy-shared-services tre-start +deploy-shared-services: firewall-install gitea-install nexus-install + +# to move your environment from the single 'core' deployment (which includes the firewall) +# toward the shared services model, where it is split out - run the following make target before a tre-deploy +# This will remove + import the resource state into a shared service +migrate-firewall-state: prepare-tf-state bootstrap: $(call target_title, "Bootstrap Terraform") \ @@ -97,7 +104,44 @@ push-gitea-image: push-guacamole-image: $(call push_image,"guac-server","./templates/workspace_services/guacamole/version.txt") -tre-deploy: tre-start +# # These targets are for a graceful migration of Firewall +# # from terraform state in Core to a Shared Service. +# # See https://github.com/microsoft/AzureTRE/issues/1177 +prepare-tf-state: + $(call target_title, "Preparing terraform state") \ + && . ./devops/scripts/check_dependencies.sh nodocker \ + && . ./devops/scripts/load_env.sh ./templates/core/.env \ + && . ./devops/scripts/load_env.sh ./devops/.env \ + && . ./devops/scripts/load_terraform_env.sh ./devops/.env \ + && . ./devops/scripts/load_terraform_env.sh ./templates/core/.env \ + && pushd ./templates/core/terraform > /dev/null && ../../shared_services/firewall/terraform/remove_state.sh && popd > /dev/null \ + && pushd ./templates/shared_services/firewall/terraform > /dev/null && ./import_state.sh && popd > /dev/null + + +terraform-shared-service-deploy: + $(call target_title, "Deploying ${DIR} with Terraform") \ + && . ./devops/scripts/check_dependencies.sh \ + && . ./devops/scripts/load_env.sh ./templates/core/.env \ + && . ./devops/scripts/load_env.sh ./devops/.env \ + && . ./devops/scripts/load_terraform_env.sh ./devops/.env \ + && . ./devops/scripts/load_terraform_env.sh ./templates/core/.env \ + && cd ${DIR} && ../../deploy_from_local.sh + +firewall-install: + $(call target_title, "Installing Firewall") \ + && make SHARED_SERVICE_KEY=shared-service-firewall terraform-shared-service-deploy DIR=./templates/shared_services/firewall/terraform + +gitea-install: + $(call target_title, "Installing Gitea") \ + && make SHARED_SERVICE_KEY=shared-service-gitea terraform-shared-service-deploy DIR=./templates/shared_services/gitea/terraform + +nexus-install: + $(call target_title, "Installing Nexus") \ + && make SHARED_SERVICE_KEY=shared-service-sonatype-nexus TF_VAR_nexus_properties_path=../nexus.properties terraform-shared-service-deploy DIR=./templates/shared_services/sonatype-nexus/terraform + +# / End migration targets + +deploy-core: $(call target_title, "Deploying TRE") \ && . ./devops/scripts/check_dependencies.sh nodocker \ && . ./devops/scripts/load_env.sh ./templates/core/.env \ @@ -117,13 +161,6 @@ letsencrypt: && . ./devops/scripts/load_env.sh ./templates/core/tre.env \ && ./templates/core/terraform/scripts/letsencrypt.sh -tre-stop: - $(call target_title, "Stopping TRE") \ - && . ./devops/scripts/check_dependencies.sh azfirewall \ - && . ./devops/scripts/load_env.sh ./templates/core/.env \ - && . ./devops/scripts/load_env.sh ./devops/.env \ - && ./devops/scripts/control_tre.sh stop - tre-start: $(call target_title, "Starting TRE") \ && . ./devops/scripts/check_dependencies.sh azfirewall \ @@ -131,6 +168,13 @@ tre-start: && . ./devops/scripts/load_env.sh ./devops/.env \ && ./devops/scripts/control_tre.sh start +tre-stop: + $(call target_title, "Stopping TRE") \ + && . ./devops/scripts/check_dependencies.sh azfirewall \ + && . ./devops/scripts/load_env.sh ./templates/core/.env \ + && . ./devops/scripts/load_env.sh ./devops/.env \ + && ./devops/scripts/control_tre.sh stop + tre-destroy: $(call target_title, "Destroying TRE") \ && . ./devops/scripts/check_dependencies.sh nodocker \ diff --git a/templates/core/terraform/firewall/output.tf b/templates/core/terraform/firewall/output.tf deleted file mode 100644 index 777659f27..000000000 --- a/templates/core/terraform/firewall/output.tf +++ /dev/null @@ -1,15 +0,0 @@ -output "firewall_name" { - value = azurerm_firewall.fw.name -} - -output "firewall_resource_group_name" { - value = azurerm_firewall.fw.resource_group_name -} - -output "firewall_private_ip_address" { - value = azurerm_firewall.fw.ip_configuration.0.private_ip_address -} - -output "firewall_public_ip" { - value = azurerm_public_ip.fwpip.ip_address -} diff --git a/templates/core/terraform/firewall/variables.tf b/templates/core/terraform/firewall/variables.tf deleted file mode 100644 index 93a60282e..000000000 --- a/templates/core/terraform/firewall/variables.tf +++ /dev/null @@ -1,40 +0,0 @@ -variable "tre_id" {} -variable "location" {} -variable "resource_group_name" {} -variable "log_analytics_workspace_id" {} -variable "shared_subnet" { - type = object({ - id = string - address_prefixes = list(string) - }) - description = "The ID of the shared subnet" -} - -variable "firewall_subnet" { - type = object({ - id = string - address_prefixes = list(string) - }) - description = "The ID of the firewall subnet" -} - -variable "resource_processor_subnet" { - type = object({ - id = string - address_prefixes = list(string) - }) - description = "The ID of the resource_processor subnet" -} - -variable "web_app_subnet" { - type = object({ - id = string - address_prefixes = list(string) - }) - description = "The ID of the web app subnet" -} - -variable "stateful_resources_locked" { - type = bool - default = true -} diff --git a/templates/core/terraform/main.tf b/templates/core/terraform/main.tf index d1b7cb0ad..d4c5bd830 100644 --- a/templates/core/terraform/main.tf +++ b/templates/core/terraform/main.tf @@ -88,68 +88,6 @@ module "resource_processor_vmss_porter" { depends_on = [ module.azure_monitor, - azurerm_key_vault.kv, - module.firewall - ] -} - -module "firewall" { - source = "./firewall" - tre_id = var.tre_id - location = var.location - resource_group_name = azurerm_resource_group.core.name - log_analytics_workspace_id = module.azure_monitor.log_analytics_workspace_id - stateful_resources_locked = var.stateful_resources_locked - - shared_subnet = { - id = module.network.shared_subnet_id - address_prefixes = module.network.shared_subnet_address_prefixes - } - firewall_subnet = { - id = module.network.azure_firewall_subnet_id - address_prefixes = module.network.azure_firewall_subnet_address_prefixes - } - resource_processor_subnet = { - id = module.network.resource_processor_subnet_id - address_prefixes = module.network.resource_processor_subnet_address_prefixes - } - web_app_subnet = { - id = module.network.web_app_subnet_id - address_prefixes = module.network.web_app_subnet_address_prefixes - } - depends_on = [ - module.network - ] -} - -module "gitea" { - count = var.deploy_gitea == true ? 1 : 0 - source = "../../shared_services/gitea/terraform" - tre_id = var.tre_id - location = var.location - acr_name = data.azurerm_container_registry.mgmt_acr.name - mgmt_resource_group_name = var.mgmt_resource_group_name - - depends_on = [ - module.firewall, - module.network, - azurerm_app_service_plan.core, - azurerm_key_vault.kv, - azurerm_storage_account.stg - ] -} - -module "nexus" { - count = var.deploy_nexus == true ? 1 : 0 - source = "../../shared_services/sonatype-nexus/terraform" - tre_id = var.tre_id - location = var.location - - depends_on = [ - module.firewall, - module.network, - azurerm_app_service_plan.core, - azurerm_key_vault.kv, - azurerm_storage_account.stg + azurerm_key_vault.kv ] } diff --git a/templates/core/terraform/network/output.tf b/templates/core/terraform/network/output.tf index aa9217555..2616b925e 100644 --- a/templates/core/terraform/network/output.tf +++ b/templates/core/terraform/network/output.tf @@ -10,34 +10,18 @@ output "azure_firewall_subnet_id" { value = azurerm_subnet.azure_firewall.id } -output "azure_firewall_subnet_address_prefixes" { - value = azurerm_subnet.azure_firewall.address_prefixes -} - output "app_gw_subnet_id" { value = azurerm_subnet.app_gw.id } -output "app_gw_subnet_address_prefixes" { - value = azurerm_subnet.app_gw.address_prefixes -} - output "web_app_subnet_id" { value = azurerm_subnet.web_app.id } -output "web_app_subnet_address_prefixes" { - value = azurerm_subnet.web_app.address_prefixes -} - output "shared_subnet_id" { value = azurerm_subnet.shared.id } -output "shared_subnet_address_prefixes" { - value = azurerm_subnet.shared.address_prefixes -} - output "private_dns_zone_azurewebsites_id" { value = azurerm_private_dns_zone.azurewebsites.id } @@ -50,10 +34,6 @@ output "resource_processor_subnet_id" { value = azurerm_subnet.resource_processor.id } -output "resource_processor_subnet_address_prefixes" { - value = azurerm_subnet.resource_processor.address_prefixes -} - output "azure_monitor_dns_zone_id" { value = azurerm_private_dns_zone.azure_monitor.id } diff --git a/templates/shared_services/deploy_from_local.sh b/templates/shared_services/deploy_from_local.sh new file mode 100755 index 000000000..671c6c895 --- /dev/null +++ b/templates/shared_services/deploy_from_local.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# This script exists to support the migration from the firewall into a shared service bundle, that can be deployed from a dev workstation. + +set -e + +PLAN_FILE="tfplan$$" +LOG_FILE="tmp$$.log" + +LOC="$(dirname -- "$(readlink -f "${BASH_SOURCE}")")" + +${LOC}/../../devops/scripts/terraform_wrapper.sh \ + -g $TF_VAR_mgmt_resource_group_name \ + -s $TF_VAR_mgmt_storage_account_name \ + -n $TF_VAR_terraform_state_container_name \ + -k ${TRE_ID}-${SHARED_SERVICE_KEY} \ + -l ${LOG_FILE} \ + -c "terraform plan -out ${PLAN_FILE} && \ + terraform apply -input=false -auto-approve ${PLAN_FILE} && \ + terraform output -json > ../tre_output.json" + diff --git a/templates/shared_services/firewall/.dockerignore b/templates/shared_services/firewall/.dockerignore new file mode 100644 index 000000000..2919244c8 --- /dev/null +++ b/templates/shared_services/firewall/.dockerignore @@ -0,0 +1,4 @@ +# See https://docs.docker.com/engine/reference/builder/#dockerignore-file +# Put files here that you don't want copied into your bundle's invocation image +.gitignore +Dockerfile.tmpl diff --git a/templates/shared_services/firewall/.gitignore b/templates/shared_services/firewall/.gitignore new file mode 100644 index 000000000..73a68e497 --- /dev/null +++ b/templates/shared_services/firewall/.gitignore @@ -0,0 +1,2 @@ +.cnab/ +.terraform* diff --git a/templates/shared_services/firewall/Dockerfile.tmpl b/templates/shared_services/firewall/Dockerfile.tmpl new file mode 100644 index 000000000..fef57e177 --- /dev/null +++ b/templates/shared_services/firewall/Dockerfile.tmpl @@ -0,0 +1,32 @@ +FROM debian:stretch-slim + +ARG BUNDLE_DIR + +RUN apt-get update && apt-get install -y ca-certificates + +# Install Azure CLI (neeeded for import_state.sh) +RUN apt-get update \ + && apt-get install -y ca-certificates jq curl apt-transport-https lsb-release gnupg \ + && curl -sL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | tee /etc/apt/trusted.gpg.d/microsoft.gpg > /dev/null \ + && AZ_REPO=$(lsb_release -cs) \ + && echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ $AZ_REPO main" | tee /etc/apt/sources.list.d/azure-cli.list \ + && apt-get update && apt-get -y install azure-cli + +# To be able to use `az network firewall` commands +RUN az config set extension.use_dynamic_install=yes_without_prompt + +# This is a template Dockerfile for the bundle's invocation image +# You can customize it to use different base images, install tools and copy configuration files. +# +# Porter will use it as a template and append lines to it for the mixins +# and to set the CMD appropriately for the CNAB specification. +# +# Add the following line to porter.yaml to instruct Porter to use this template +# dockerfile: Dockerfile.tmpl + +# You can control where the mixin's Dockerfile lines are inserted into this file by moving "# PORTER_MIXINS" line +# another location in this file. If you remove that line, the mixins generated content is appended to this file. +# PORTER_MIXINS + +# Use the BUNDLE_DIR build argument to copy files into the bundle +COPY . $BUNDLE_DIR diff --git a/templates/shared_services/firewall/azure.json b/templates/shared_services/firewall/azure.json new file mode 100755 index 000000000..cdc4c1365 --- /dev/null +++ b/templates/shared_services/firewall/azure.json @@ -0,0 +1,32 @@ +{ + "schemaVersion": "1.0.0-DRAFT+b6c701f", + "name": "azure", + "created": "2021-06-03T11:31:05.7314113Z", + "modified": "2021-06-03T11:31:05.7314113Z", + "credentials": [ + { + "name": "azure_client_id", + "source": { + "env": "ARM_CLIENT_ID" + } + }, + { + "name": "azure_client_secret", + "source": { + "env": "ARM_CLIENT_SECRET" + } + }, + { + "name": "azure_subscription_id", + "source": { + "env": "ARM_SUBSCRIPTION_ID" + } + }, + { + "name": "azure_tenant_id", + "source": { + "env": "ARM_TENANT_ID" + } + } + ] +} diff --git a/templates/shared_services/firewall/parameters.json b/templates/shared_services/firewall/parameters.json new file mode 100755 index 000000000..7c41929a0 --- /dev/null +++ b/templates/shared_services/firewall/parameters.json @@ -0,0 +1,38 @@ +{ + "schemaVersion": "1.0.0-DRAFT", + "name": "base", + "created": "2021-06-04T13:37:29.5071039+03:00", + "modified": "2021-06-04T13:37:29.5071039+03:00", + "parameters": [ + { + "name": "tre_id", + "source": { + "env": "TRE_ID" + } + }, + { + "name": "azure_location", + "source": { + "env": "LOCATION" + } + }, + { + "name": "tfstate_container_name", + "source": { + "env": "TERRAFORM_STATE_CONTAINER_NAME" + } + }, + { + "name": "tfstate_resource_group_name", + "source": { + "env": "MGMT_RESOURCE_GROUP_NAME" + } + }, + { + "name": "tfstate_storage_account_name", + "source": { + "env": "MGMT_STORAGE_ACCOUNT_NAME" + } + } + ] +} diff --git a/templates/shared_services/firewall/porter.yaml b/templates/shared_services/firewall/porter.yaml new file mode 100644 index 000000000..b291bddc0 --- /dev/null +++ b/templates/shared_services/firewall/porter.yaml @@ -0,0 +1,71 @@ +name: tre-shared-service-firewall +version: 0.0.3 +description: "An Azure TRE Firewall shared service" +registry: azuretre +dockerfile: Dockerfile.tmpl + +credentials: + - name: azure_tenant_id + env: ARM_TENANT_ID + - name: azure_subscription_id + env: ARM_SUBSCRIPTION_ID + - name: azure_client_id + env: ARM_CLIENT_ID + - name: azure_client_secret + env: ARM_CLIENT_SECRET + +parameters: + - name: tre_id + type: string + description: "The ID of the parent TRE instance e.g., mytre-dev-3142" + - name: azure_location + type: string + description: "Azure location (region) to deploy to" + - name: tfstate_resource_group_name + type: string + description: "Resource group containing the Terraform state storage account" + - name: tfstate_storage_account_name + type: string + description: "The name of the Terraform state storage account" + - name: tfstate_container_name + type: string + default: "tfstate" + description: "The name of the Terraform state storage container" + +mixins: + - exec + - terraform: + clientVersion: 1.1.5 + +install: + - terraform: + description: "Deploy shared service" + input: false + vars: + tre_id: "{{ bundle.parameters.tre_id }}" + location: "{{ bundle.parameters.azure_location }}" + backendConfig: + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" + container_name: "{{ bundle.parameters.tfstate_container_name }}" + key: "{{ bundle.parameters.tre_id }}-shared-service-firewall" + +upgrade: + - exec: + description: "Upgrade shared service" + command: echo + arguments: + - "This shared service does not implement upgrade action" + +uninstall: + - terraform: + description: "Tear down shared service" + input: false + vars: + tre_id: "{{ bundle.parameters.tre_id }}" + location: "{{ bundle.parameters.azure_location }}" + backendConfig: + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" + container_name: "{{ bundle.parameters.tfstate_container_name }}" + key: "{{ bundle.parameters.tre_id }}-shared-service-firewall" diff --git a/templates/shared_services/firewall/terraform/data.tf b/templates/shared_services/firewall/terraform/data.tf new file mode 100644 index 000000000..82548f78a --- /dev/null +++ b/templates/shared_services/firewall/terraform/data.tf @@ -0,0 +1,32 @@ +data "azurerm_subnet" "firewall" { + name = "AzureFirewallSubnet" + virtual_network_name = "vnet-${var.tre_id}" + + resource_group_name = local.core_resource_group_name +} + +data "azurerm_subnet" "shared" { + name = "SharedSubnet" + virtual_network_name = "vnet-${var.tre_id}" + + resource_group_name = local.core_resource_group_name +} + +data "azurerm_subnet" "resource_processor" { + name = "ResourceProcessorSubnet" + virtual_network_name = "vnet-${var.tre_id}" + + resource_group_name = local.core_resource_group_name +} + +data "azurerm_subnet" "web_app" { + name = "WebAppSubnet" + virtual_network_name = "vnet-${var.tre_id}" + + resource_group_name = local.core_resource_group_name +} + +data "azurerm_log_analytics_workspace" "tre" { + name = "log-${var.tre_id}" + resource_group_name = local.core_resource_group_name +} diff --git a/templates/core/terraform/firewall/firewall.tf b/templates/shared_services/firewall/terraform/firewall.tf similarity index 89% rename from templates/core/terraform/firewall/firewall.tf rename to templates/shared_services/firewall/terraform/firewall.tf index 0a465fcad..8cf5d5c0f 100644 --- a/templates/core/terraform/firewall/firewall.tf +++ b/templates/shared_services/firewall/terraform/firewall.tf @@ -1,6 +1,6 @@ resource "azurerm_public_ip" "fwpip" { name = "pip-fw-${var.tre_id}" - resource_group_name = var.resource_group_name + resource_group_name = local.core_resource_group_name location = var.location allocation_method = "Static" sku = "Standard" @@ -11,11 +11,11 @@ resource "azurerm_public_ip" "fwpip" { resource "azurerm_firewall" "fw" { depends_on = [azurerm_public_ip.fwpip] name = "fw-${var.tre_id}" - resource_group_name = var.resource_group_name + resource_group_name = local.core_resource_group_name location = var.location ip_configuration { name = "fw-ip-configuration" - subnet_id = var.firewall_subnet.id + subnet_id = data.azurerm_subnet.firewall.id public_ip_address_id = azurerm_public_ip.fwpip.id } @@ -33,7 +33,7 @@ resource "azurerm_management_lock" "fw" { resource "azurerm_monitor_diagnostic_setting" "firewall" { name = "diagnostics-firewall-${var.tre_id}" target_resource_id = azurerm_firewall.fw.id - log_analytics_workspace_id = var.log_analytics_workspace_id + log_analytics_workspace_id = data.azurerm_log_analytics_workspace.tre.id log_analytics_destination_type = "Dedicated" log { @@ -125,7 +125,7 @@ resource "azurerm_firewall_application_rule_collection" "shared_subnet" { "graph.windows.net" ] - source_addresses = var.shared_subnet.address_prefixes + source_addresses = data.azurerm_subnet.shared.address_prefixes } } @@ -161,7 +161,7 @@ resource "azurerm_firewall_application_rule_collection" "resource_processor_subn "registry.terraform.io", "releases.hashicorp.com" ] - source_addresses = var.resource_processor_subnet.address_prefixes + source_addresses = data.azurerm_subnet.resource_processor.address_prefixes } depends_on = [ @@ -225,7 +225,7 @@ resource "azurerm_firewall_network_rule_collection" "resource_processor_subnet" destination_ports = [ "443" ] - source_addresses = var.resource_processor_subnet.address_prefixes + source_addresses = data.azurerm_subnet.resource_processor.address_prefixes } depends_on = [ @@ -256,7 +256,7 @@ resource "azurerm_firewall_network_rule_collection" "web_app_subnet" { destination_ports = [ "443" ] - source_addresses = var.web_app_subnet.address_prefixes + source_addresses = data.azurerm_subnet.web_app.address_prefixes } depends_on = [ @@ -281,6 +281,10 @@ resource "azurerm_firewall_application_rule_collection" "web_app_subnet" { target_fqdns = [ "graph.microsoft.com" ] - source_addresses = var.web_app_subnet.address_prefixes + source_addresses = data.azurerm_subnet.web_app.address_prefixes } + + depends_on = [ + azurerm_firewall_network_rule_collection.web_app_subnet + ] } diff --git a/templates/shared_services/firewall/terraform/import_state.sh b/templates/shared_services/firewall/terraform/import_state.sh new file mode 100755 index 000000000..d998f7f41 --- /dev/null +++ b/templates/shared_services/firewall/terraform/import_state.sh @@ -0,0 +1,103 @@ +#!/bin/bash +# See remove_state.sh for the purpose of these scripts +echo "IMPORTING STATE FOR FIREWALL..." + +# check for the existence of the RG. If it's not there it's because we're in CI and building from scratch - we can skip this script +set +e +RESOURCE_GROUP_ID="rg-${TRE_ID}" +az group show -n $RESOURCE_GROUP_ID +if [ $? -ne 0 ]; then + echo "RG not found, skipping import_state" + exit 0 +fi + +set -e + +# Initialise state for Terraform +terraform init -input=false -backend=true -reconfigure -upgrade \ + -backend-config="resource_group_name=${TF_VAR_mgmt_resource_group_name}" \ + -backend-config="storage_account_name=${TF_VAR_mgmt_storage_account_name}" \ + -backend-config="container_name=${TF_VAR_terraform_state_container_name}" \ + -backend-config="key=${TRE_ID}-shared-service-firewall" + +# Import a resource if it exists in Azure but doesn't exist in Terraform +tf_state_list="$(terraform state list)" +function import_if_exists() { + ADDRESS=$1 + ID=$2 + CMD=$3 + + # Check if the resource exists in Terraform + TF_RESOURCE_EXISTS=$(echo "$tf_state_list" | grep -q ^${ADDRESS}$; echo $?) + + if [[ ${TF_RESOURCE_EXISTS} -eq 0 ]]; then + echo "${ADDRESS} already in TF State, ignoring..." + return + fi + + # Some resources, e.g. Firewall rules and Diagnostics, don't show up in `az resource show`, + # so we need a way to set up a custom command for them + if [[ -z ${CMD} ]]; then + CMD="az resource show --ids ${ID}" + fi + ${CMD} > /dev/null + AZ_RESOURCE_EXISTS=$? + + # If resource exists in Terraform, it's already managed -- don't do anything + # If resource doesn't exist in Terraform and doesn't exist in Azure, it will be created -- don't do anything + # If resource doesn't exist in Terraform but exist in Azure, we need to import it + if [[ ${TF_RESOURCE_EXISTS} -ne 0 && ${AZ_RESOURCE_EXISTS} -eq 0 ]]; then + echo "IMPORTING ${ADDRESS} ${ID}" + terraform import -var "tre_id=${TRE_ID}" -var "location=${LOCATION}" ${ADDRESS} ${ID} + fi +} + +import_if_exists azurerm_firewall.fw "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/azureFirewalls/fw-${TRE_ID}" || echo "Resource already exists" + +# Firewall rules +import_if_exists azurerm_firewall_application_rule_collection.resource_processor_subnet \ + "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/azureFirewalls/fw-${TRE_ID}/applicationRuleCollections/arc-resource_processor_subnet" \ + "az network firewall show --ids /subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/azureFirewalls/fw-${TRE_ID}/applicationRuleCollections/arc-resource_processor_subnet" + +import_if_exists azurerm_firewall_application_rule_collection.shared_subnet \ + "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/azureFirewalls/fw-${TRE_ID}/applicationRuleCollections/arc-shared_subnet" \ + "az network firewall show --ids /subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/azureFirewalls/fw-${TRE_ID}/applicationRuleCollections/arc-shared_subnet" + +import_if_exists azurerm_firewall_application_rule_collection.web_app_subnet \ + "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/azureFirewalls/fw-${TRE_ID}/applicationRuleCollections/arc-web_app_subnet" \ + "az network firewall show --ids /subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/azureFirewalls/fw-${TRE_ID}/applicationRuleCollections/arc-web_app_subnet" + +import_if_exists azurerm_firewall_network_rule_collection.general \ + "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/azureFirewalls/fw-${TRE_ID}/networkRuleCollections/general" \ + "az network firewall show --ids /subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/azureFirewalls/fw-${TRE_ID}/networkRuleCollections/general" + +import_if_exists azurerm_firewall_network_rule_collection.resource_processor_subnet \ + "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/azureFirewalls/fw-${TRE_ID}/networkRuleCollections/nrc-resource_processor_subnet" \ + "az network firewall show --ids /subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/azureFirewalls/fw-${TRE_ID}/networkRuleCollections/nrc-resource_processor_subnet" + +import_if_exists azurerm_firewall_network_rule_collection.web_app_subnet \ + "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/azureFirewalls/fw-${TRE_ID}/networkRuleCollections/nrc-web_app_subnet" \ + "az network firewall show --ids /subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/azureFirewalls/fw-${TRE_ID}/networkRuleCollections/nrc-web_app_subnet" + + +# Diagnostic settings +import_if_exists azurerm_monitor_diagnostic_setting.firewall \ + "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/azureFirewalls/fw-${TRE_ID}|diagnostics-firewall-${TRE_ID}" \ + "az monitor diagnostic-settings show --resource /subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/rg-${TRE_ID}/providers/microsoft.network/azureFirewalls/fw-${TRE_ID} --name diagnostics-firewall-${TRE_ID}" + + +import_if_exists azurerm_public_ip.fwpip "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/publicIPAddresses/pip-fw-${TRE_ID}" + + +import_if_exists azurerm_subnet_route_table_association.rt_web_app_subnet_association \ + "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/virtualNetworks/vnet-${TRE_ID}/subnets/WebAppSubnet" + +# Route tables +import_if_exists azurerm_route_table.rt \ + "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/routeTables/rt-${TRE_ID}" + +import_if_exists azurerm_subnet_route_table_association.rt_shared_subnet_association \ + "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/virtualNetworks/vnet-${TRE_ID}/subnets/SharedSubnet" + +import_if_exists azurerm_subnet_route_table_association.rt_resource_processor_subnet_association \ + "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/virtualNetworks/vnet-${TRE_ID}/subnets/ResourceProcessorSubnet" diff --git a/templates/shared_services/firewall/terraform/locals.tf b/templates/shared_services/firewall/terraform/locals.tf new file mode 100644 index 000000000..06f276d0a --- /dev/null +++ b/templates/shared_services/firewall/terraform/locals.tf @@ -0,0 +1,4 @@ +locals { + core_resource_group_name = "rg-${var.tre_id}" + firewall_name = "fw-${var.tre_id}" +} diff --git a/templates/shared_services/sonatype-nexus/terraform/terraform.tf b/templates/shared_services/firewall/terraform/main.tf similarity index 73% rename from templates/shared_services/sonatype-nexus/terraform/terraform.tf rename to templates/shared_services/firewall/terraform/main.tf index 68c07285a..715a8db03 100644 --- a/templates/shared_services/sonatype-nexus/terraform/terraform.tf +++ b/templates/shared_services/firewall/terraform/main.tf @@ -6,4 +6,10 @@ terraform { version = "=2.97.0" } } + + backend "azurerm" {} +} + +provider "azurerm" { + features {} } diff --git a/templates/shared_services/firewall/terraform/remove_state.sh b/templates/shared_services/firewall/terraform/remove_state.sh new file mode 100755 index 000000000..140d098ed --- /dev/null +++ b/templates/shared_services/firewall/terraform/remove_state.sh @@ -0,0 +1,41 @@ +#!/bin/bash +# This script works together with the import_state.sh script to manually remove the firewall state from the core deployment +# and import it into the firewall deployment. It's used for migration purposes only and will be removed when clients are all +# using the shared services model +echo "REMOVING STATE FOR FIREWALL..." + +set -e + +terraform init -input=false -backend=true -reconfigure -upgrade \ + -backend-config="resource_group_name=${TF_VAR_mgmt_resource_group_name}" \ + -backend-config="storage_account_name=${TF_VAR_mgmt_storage_account_name}" \ + -backend-config="container_name=${TF_VAR_terraform_state_container_name}" \ + -backend-config="key=${TRE_ID}" + +tf_state_list="$(terraform state list)" +function remove_if_present() { + echo -n "Checking $1 ..." + found=$(echo "$tf_state_list" | grep -q ^$1$; echo $?) + + if [[ $found -eq 0 ]]; then + echo " removing" + terraform state rm $1 + else + echo " not present" + fi +} + +remove_if_present azurerm_route_table.rt +remove_if_present azurerm_subnet_route_table_association.rt_resource_processor_subnet_association +remove_if_present azurerm_subnet_route_table_association.rt_shared_subnet_association +remove_if_present azurerm_subnet_route_table_association.rt_web_app_subnet_association +remove_if_present module.firewall +remove_if_present module.firewall.azurerm_public_ip.fwpip +remove_if_present module.firewall.azurerm_monitor_diagnostic_setting.firewall +remove_if_present module.firewall.azurerm_firewall_network_rule_collection.web_app_subnet +remove_if_present module.firewall.azurerm_firewall_network_rule_collection.resource_processor_subnet +remove_if_present module.firewall.azurerm_firewall_network_rule_collection.general +remove_if_present module.firewall.azurerm_firewall_application_rule_collection.web_app_subnet +remove_if_present module.firewall.azurerm_firewall_application_rule_collection.shared_subnet +remove_if_present module.firewall.azurerm_firewall_application_rule_collection.resource_processor_subnet +remove_if_present module.firewall.azurerm_firewall.fw diff --git a/templates/core/terraform/routetable.tf b/templates/shared_services/firewall/terraform/routetable.tf similarity index 65% rename from templates/core/terraform/routetable.tf rename to templates/shared_services/firewall/terraform/routetable.tf index e1a567bb8..a3798a275 100644 --- a/templates/core/terraform/routetable.tf +++ b/templates/shared_services/firewall/terraform/routetable.tf @@ -1,7 +1,7 @@ resource "azurerm_route_table" "rt" { name = "rt-${var.tre_id}" - resource_group_name = azurerm_resource_group.core.name - location = azurerm_resource_group.core.location + resource_group_name = local.core_resource_group_name + location = var.location disable_bgp_route_propagation = false lifecycle { ignore_changes = [tags] } @@ -10,21 +10,21 @@ resource "azurerm_route_table" "rt" { name = "DefaultRoute" address_prefix = "0.0.0.0/0" next_hop_type = "VirtualAppliance" - next_hop_in_ip_address = module.firewall.firewall_private_ip_address + next_hop_in_ip_address = azurerm_firewall.fw.ip_configuration.0.private_ip_address } } resource "azurerm_subnet_route_table_association" "rt_shared_subnet_association" { - subnet_id = module.network.shared_subnet_id + subnet_id = data.azurerm_subnet.shared.id route_table_id = azurerm_route_table.rt.id } resource "azurerm_subnet_route_table_association" "rt_resource_processor_subnet_association" { - subnet_id = module.network.resource_processor_subnet_id + subnet_id = data.azurerm_subnet.resource_processor.id route_table_id = azurerm_route_table.rt.id } resource "azurerm_subnet_route_table_association" "rt_web_app_subnet_association" { - subnet_id = module.network.web_app_subnet_id + subnet_id = data.azurerm_subnet.web_app.id route_table_id = azurerm_route_table.rt.id } diff --git a/templates/shared_services/firewall/terraform/variables.tf b/templates/shared_services/firewall/terraform/variables.tf new file mode 100644 index 000000000..5fdcc17b1 --- /dev/null +++ b/templates/shared_services/firewall/terraform/variables.tf @@ -0,0 +1,7 @@ +variable "tre_id" {} +variable "location" {} +variable "stateful_resources_locked" { + type = bool + default = true + description = "Used to add locks on resources with state" +} diff --git a/templates/shared_services/gitea/.dockerignore b/templates/shared_services/gitea/.dockerignore new file mode 100644 index 000000000..2919244c8 --- /dev/null +++ b/templates/shared_services/gitea/.dockerignore @@ -0,0 +1,4 @@ +# See https://docs.docker.com/engine/reference/builder/#dockerignore-file +# Put files here that you don't want copied into your bundle's invocation image +.gitignore +Dockerfile.tmpl diff --git a/templates/shared_services/gitea/.gitignore b/templates/shared_services/gitea/.gitignore new file mode 100644 index 000000000..e08a3e22b --- /dev/null +++ b/templates/shared_services/gitea/.gitignore @@ -0,0 +1 @@ +.cnab/ diff --git a/templates/shared_services/gitea/Dockerfile.tmpl b/templates/shared_services/gitea/Dockerfile.tmpl new file mode 100644 index 000000000..32442c813 --- /dev/null +++ b/templates/shared_services/gitea/Dockerfile.tmpl @@ -0,0 +1,29 @@ +FROM debian:stretch-slim + +ARG BUNDLE_DIR + +RUN apt-get update && apt-get install -y ca-certificates + +# Install Azure CLI (neeeded for import_state.sh) +RUN apt-get update \ + && apt-get install -y ca-certificates jq curl apt-transport-https lsb-release gnupg \ + && curl -sL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | tee /etc/apt/trusted.gpg.d/microsoft.gpg > /dev/null \ + && AZ_REPO=$(lsb_release -cs) \ + && echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ $AZ_REPO main" | tee /etc/apt/sources.list.d/azure-cli.list \ + && apt-get update && apt-get -y install azure-cli + +# This is a template Dockerfile for the bundle's invocation image +# You can customize it to use different base images, install tools and copy configuration files. +# +# Porter will use it as a template and append lines to it for the mixins +# and to set the CMD appropriately for the CNAB specification. +# +# Add the following line to porter.yaml to instruct Porter to use this template +# dockerfile: Dockerfile.tmpl + +# You can control where the mixin's Dockerfile lines are inserted into this file by moving "# PORTER_MIXINS" line +# another location in this file. If you remove that line, the mixins generated content is appended to this file. +# PORTER_MIXINS + +# Use the BUNDLE_DIR build argument to copy files into the bundle +COPY . $BUNDLE_DIR diff --git a/templates/shared_services/gitea/azure.json b/templates/shared_services/gitea/azure.json new file mode 100755 index 000000000..1f2298a92 --- /dev/null +++ b/templates/shared_services/gitea/azure.json @@ -0,0 +1,32 @@ +{ + "schemaVersion": "1.0.0-DRAFT+b6c701f", + "name": "azure", + "created": "2021-06-03T11:31:05.7314113Z", + "modified": "2021-06-03T11:31:05.7314113Z", + "credentials": [ + { + "name": "azure_client_id", + "source": { + "env": "ARM_CLIENT_ID" + } + }, + { + "name": "azure_client_secret", + "source": { + "env": "ARM_CLIENT_SECRET" + } + }, + { + "name": "azure_subscription_id", + "source": { + "env": "ARM_SUBSCRIPTION_ID" + } + }, + { + "name": "azure_tenant_id", + "source": { + "env": "ARM_TENANT_ID" + } + } + ] +} \ No newline at end of file diff --git a/templates/shared_services/gitea/parameters.json b/templates/shared_services/gitea/parameters.json new file mode 100755 index 000000000..47bddaa8f --- /dev/null +++ b/templates/shared_services/gitea/parameters.json @@ -0,0 +1,44 @@ +{ + "schemaVersion": "1.0.0-DRAFT+TODO", + "name": "base", + "created": "2021-06-04T13:37:29.5071039+03:00", + "modified": "2021-06-04T13:37:29.5071039+03:00", + "parameters": [ + { + "name": "tre_id", + "source": { + "env": "TRE_ID" + } + }, + { + "name": "azure_location", + "source": { + "env": "LOCATION" + } + }, + { + "name": "acr_name", + "source": { + "env": "ACR_NAME" + } + }, + { + "name": "tfstate_container_name", + "source": { + "env": "TERRAFORM_STATE_CONTAINER_NAME" + } + }, + { + "name": "tfstate_resource_group_name", + "source": { + "env": "MGMT_RESOURCE_GROUP_NAME" + } + }, + { + "name": "tfstate_storage_account_name", + "source": { + "env": "MGMT_STORAGE_ACCOUNT_NAME" + } + } + ] +} diff --git a/templates/shared_services/gitea/porter.yaml b/templates/shared_services/gitea/porter.yaml new file mode 100644 index 000000000..3ec8a65a7 --- /dev/null +++ b/templates/shared_services/gitea/porter.yaml @@ -0,0 +1,74 @@ +name: tre-shared-service-gitea +version: 0.0.1 +description: "A Gitea shared service" +registry: azuretre +dockerfile: Dockerfile.tmpl + +credentials: + - name: azure_tenant_id + env: ARM_TENANT_ID + - name: azure_subscription_id + env: ARM_SUBSCRIPTION_ID + - name: azure_client_id + env: ARM_CLIENT_ID + - name: azure_client_secret + env: ARM_CLIENT_SECRET +parameters: + - name: tre_id + type: string + description: "The ID of the parent TRE instance e.g., mytre-dev-3142" + - name: azure_location + type: string + description: "Azure location (region) to deploy to" + - name: acr_name + type: string + description: "The name of the Azure Container Registry" + - name: tfstate_resource_group_name + type: string + description: "Resource group containing the Terraform state storage account" + - name: tfstate_storage_account_name + type: string + description: "The name of the Terraform state storage account" + - name: tfstate_container_name + type: string + default: "tfstate" + description: "The name of the Terraform state storage container" +mixins: + - exec + - terraform: + clientVersion: 1.1.5 + +install: + - terraform: + description: "Deploy shared service" + input: false + vars: + tre_id: "{{ bundle.parameters.tre_id }}" + location: "{{ bundle.parameters.azure_location }}" + mgmt_resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + acr_name: "{{ bundle.parameters.acr_name }}" + backendConfig: + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" + container_name: "{{ bundle.parameters.tfstate_container_name }}" + key: "{{ bundle.parameters.tre_id }}-shared-service-gitea" +upgrade: + - exec: + description: "Upgrade shared service" + command: echo + arguments: + - "This shared service does not implement upgrade action" +uninstall: + - terraform: + description: "Tear down shared service" + input: false + vars: + tre_id: "{{ bundle.parameters.tre_id }}" + location: "{{ bundle.parameters.azure_location }}" + mgmt_resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + acr_name: "{{ bundle.parameters.acr_name }}" + backendConfig: + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" + container_name: "{{ bundle.parameters.tfstate_container_name }}" + key: "{{ bundle.parameters.tre_id }}-shared-service-gitea" diff --git a/templates/shared_services/gitea/terraform/firewall.tf b/templates/shared_services/gitea/terraform/firewall.tf index 7a042bd0f..2371ffb83 100644 --- a/templates/shared_services/gitea/terraform/firewall.tf +++ b/templates/shared_services/gitea/terraform/firewall.tf @@ -20,3 +20,4 @@ resource "azurerm_firewall_application_rule_collection" "web_app_subnet_gitea" { source_addresses = data.azurerm_subnet.web_app.address_prefixes } } + diff --git a/templates/shared_services/gitea/terraform/gitea-webapp.tf b/templates/shared_services/gitea/terraform/gitea-webapp.tf index 7634b1ff7..e12537739 100644 --- a/templates/shared_services/gitea/terraform/gitea-webapp.tf +++ b/templates/shared_services/gitea/terraform/gitea-webapp.tf @@ -243,7 +243,7 @@ resource "azurerm_key_vault_access_policy" "gitea_policy" { } resource "azurerm_key_vault_secret" "gitea_password" { - name = "${local.webapp_name}-admin-password" + name = "${local.webapp_name}-administrator-password" value = random_password.gitea_passwd.result key_vault_id = data.azurerm_key_vault.keyvault.id diff --git a/templates/shared_services/gitea/terraform/locals.tf b/templates/shared_services/gitea/terraform/locals.tf index e3a315fe8..55d131251 100644 --- a/templates/shared_services/gitea/terraform/locals.tf +++ b/templates/shared_services/gitea/terraform/locals.tf @@ -3,7 +3,7 @@ locals { core_resource_group_name = "rg-${var.tre_id}" webapp_name = "gitea-${var.tre_id}" firewall_name = "fw-${var.tre_id}" - storage_account_name = "stg${var.tre_id}" + storage_account_name = lower(replace("stg-${var.tre_id}", "-", "")) keyvault_name = "kv-${var.tre_id}" version = replace(replace(replace(data.local_file.version.content, "__version__ = \"", ""), "\"", ""), "\n", "") gitea_allowed_fqdns_list = distinct(compact(split(",", replace(var.gitea_allowed_fqdns, " ", "")))) diff --git a/templates/shared_services/gitea/terraform/terraform.tf b/templates/shared_services/gitea/terraform/main.tf similarity index 73% rename from templates/shared_services/gitea/terraform/terraform.tf rename to templates/shared_services/gitea/terraform/main.tf index 68c07285a..715a8db03 100644 --- a/templates/shared_services/gitea/terraform/terraform.tf +++ b/templates/shared_services/gitea/terraform/main.tf @@ -6,4 +6,10 @@ terraform { version = "=2.97.0" } } + + backend "azurerm" {} +} + +provider "azurerm" { + features {} } diff --git a/templates/shared_services/gitea/terraform/mysql.tf b/templates/shared_services/gitea/terraform/mysql.tf index 0b068786a..7e5ed208c 100644 --- a/templates/shared_services/gitea/terraform/mysql.tf +++ b/templates/shared_services/gitea/terraform/mysql.tf @@ -56,7 +56,7 @@ resource "azurerm_private_endpoint" "private-endpoint" { } resource "azurerm_key_vault_secret" "db_password" { - name = "${azurerm_mysql_server.gitea.name}-password" + name = "${azurerm_mysql_server.gitea.name}-administrator-password" value = random_password.password.result key_vault_id = data.azurerm_key_vault.keyvault.id diff --git a/templates/shared_services/gitea/version.txt b/templates/shared_services/gitea/version.txt index 485f44ac2..b3f475621 100644 --- a/templates/shared_services/gitea/version.txt +++ b/templates/shared_services/gitea/version.txt @@ -1 +1 @@ -__version__ = "0.1.1" +__version__ = "0.1.2" diff --git a/templates/shared_services/sonatype-nexus/.dockerignore b/templates/shared_services/sonatype-nexus/.dockerignore new file mode 100644 index 000000000..2919244c8 --- /dev/null +++ b/templates/shared_services/sonatype-nexus/.dockerignore @@ -0,0 +1,4 @@ +# See https://docs.docker.com/engine/reference/builder/#dockerignore-file +# Put files here that you don't want copied into your bundle's invocation image +.gitignore +Dockerfile.tmpl diff --git a/templates/shared_services/sonatype-nexus/.gitignore b/templates/shared_services/sonatype-nexus/.gitignore new file mode 100644 index 000000000..e08a3e22b --- /dev/null +++ b/templates/shared_services/sonatype-nexus/.gitignore @@ -0,0 +1 @@ +.cnab/ diff --git a/templates/shared_services/sonatype-nexus/Dockerfile.tmpl b/templates/shared_services/sonatype-nexus/Dockerfile.tmpl new file mode 100644 index 000000000..9a66e15f5 --- /dev/null +++ b/templates/shared_services/sonatype-nexus/Dockerfile.tmpl @@ -0,0 +1,21 @@ +FROM debian:stretch-slim + +ARG BUNDLE_DIR + +RUN apt-get update && apt-get install -y ca-certificates + +# This is a template Dockerfile for the bundle's invocation image +# You can customize it to use different base images, install tools and copy configuration files. +# +# Porter will use it as a template and append lines to it for the mixins +# and to set the CMD appropriately for the CNAB specification. +# +# Add the following line to porter.yaml to instruct Porter to use this template +# dockerfile: Dockerfile.tmpl + +# You can control where the mixin's Dockerfile lines are inserted into this file by moving "# PORTER_MIXINS" line +# another location in this file. If you remove that line, the mixins generated content is appended to this file. +# PORTER_MIXINS + +# Use the BUNDLE_DIR build argument to copy files into the bundle +COPY . $BUNDLE_DIR diff --git a/templates/shared_services/sonatype-nexus/azure.json b/templates/shared_services/sonatype-nexus/azure.json new file mode 100755 index 000000000..cdc4c1365 --- /dev/null +++ b/templates/shared_services/sonatype-nexus/azure.json @@ -0,0 +1,32 @@ +{ + "schemaVersion": "1.0.0-DRAFT+b6c701f", + "name": "azure", + "created": "2021-06-03T11:31:05.7314113Z", + "modified": "2021-06-03T11:31:05.7314113Z", + "credentials": [ + { + "name": "azure_client_id", + "source": { + "env": "ARM_CLIENT_ID" + } + }, + { + "name": "azure_client_secret", + "source": { + "env": "ARM_CLIENT_SECRET" + } + }, + { + "name": "azure_subscription_id", + "source": { + "env": "ARM_SUBSCRIPTION_ID" + } + }, + { + "name": "azure_tenant_id", + "source": { + "env": "ARM_TENANT_ID" + } + } + ] +} diff --git a/templates/shared_services/sonatype-nexus/parameters.json b/templates/shared_services/sonatype-nexus/parameters.json new file mode 100755 index 000000000..9a0d0f983 --- /dev/null +++ b/templates/shared_services/sonatype-nexus/parameters.json @@ -0,0 +1,38 @@ +{ + "schemaVersion": "1.0.0-DRAFT+TODO", + "name": "base", + "created": "2021-06-04T13:37:29.5071039+03:00", + "modified": "2021-06-04T13:37:29.5071039+03:00", + "parameters": [ + { + "name": "tre_id", + "source": { + "env": "TRE_ID" + } + }, + { + "name": "azure_location", + "source": { + "env": "LOCATION" + } + }, + { + "name": "tfstate_container_name", + "source": { + "env": "TERRAFORM_STATE_CONTAINER_NAME" + } + }, + { + "name": "tfstate_resource_group_name", + "source": { + "env": "MGMT_RESOURCE_GROUP_NAME" + } + }, + { + "name": "tfstate_storage_account_name", + "source": { + "env": "MGMT_STORAGE_ACCOUNT_NAME" + } + } + ] +} diff --git a/templates/shared_services/sonatype-nexus/porter.yaml b/templates/shared_services/sonatype-nexus/porter.yaml new file mode 100644 index 000000000..fc2d24e86 --- /dev/null +++ b/templates/shared_services/sonatype-nexus/porter.yaml @@ -0,0 +1,65 @@ +name: tre-shared-service-nexus +version: 0.0.1 +description: "A Sonatype Nexus shared service" +registry: azuretre +credentials: + - name: azure_tenant_id + env: ARM_TENANT_ID + - name: azure_subscription_id + env: ARM_SUBSCRIPTION_ID + - name: azure_client_id + env: ARM_CLIENT_ID + - name: azure_client_secret + env: ARM_CLIENT_SECRET +parameters: + - name: tre_id + type: string + description: "The ID of the parent TRE instance e.g., mytre-dev-3142" + - name: azure_location + type: string + description: "Azure location (region) to deploy to" + - name: tfstate_resource_group_name + type: string + description: "Resource group containing the Terraform state storage account" + - name: tfstate_storage_account_name + type: string + description: "The name of the Terraform state storage account" + - name: tfstate_container_name + type: string + default: "tfstate" + description: "The name of the Terraform state storage container" +mixins: + - exec + - az + - terraform: + clientVersion: 1.1.5 +install: + - terraform: + description: "Deploy shared service" + input: false + vars: + tre_id: "{{ bundle.parameters.tre_id }}" + location: "{{ bundle.parameters.azure_location }}" + backendConfig: + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" + container_name: "{{ bundle.parameters.tfstate_container_name }}" + key: "{{ bundle.parameters.tre_id }}-shared-service-sonatype-nexus" +upgrade: + - exec: + description: "Upgrade shared service" + command: echo + arguments: + - "This shared service does not implement upgrade action" +uninstall: + - terraform: + description: "Tear down shared service" + input: false + vars: + tre_id: "{{ bundle.parameters.tre_id }}" + location: "{{ bundle.parameters.azure_location }}" + backendConfig: + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" + container_name: "{{ bundle.parameters.tfstate_container_name }}" + key: "{{ bundle.parameters.tre_id }}-shared-service-sonatype-nexus" diff --git a/templates/shared_services/sonatype-nexus/terraform/deploy.sh b/templates/shared_services/sonatype-nexus/terraform/deploy.sh index 05a9f3dbb..14160537e 100755 --- a/templates/shared_services/sonatype-nexus/terraform/deploy.sh +++ b/templates/shared_services/sonatype-nexus/terraform/deploy.sh @@ -4,6 +4,6 @@ terraform init -input=false -backend=true -reconfigure \ -backend-config="resource_group_name=$TF_VAR_mgmt_resource_group_name" \ -backend-config="storage_account_name=$TF_VAR_mgmt_storage_account_name" \ -backend-config="container_name=$TF_VAR_terraform_state_container_name" \ - -backend-config="key=${TRE_ID}-nexus" + -backend-config="key=${TRE_ID}-shared-service-sonatype-nexus" terraform plan terraform apply -auto-approve diff --git a/templates/shared_services/sonatype-nexus/terraform/destroy.sh b/templates/shared_services/sonatype-nexus/terraform/destroy.sh index aa0f4971d..14ad9ec21 100755 --- a/templates/shared_services/sonatype-nexus/terraform/destroy.sh +++ b/templates/shared_services/sonatype-nexus/terraform/destroy.sh @@ -4,6 +4,6 @@ terraform init -input=false -backend=true -reconfigure \ -backend-config="resource_group_name=$TF_VAR_mgmt_resource_group_name" \ -backend-config="storage_account_name=$TF_VAR_mgmt_storage_account_name" \ -backend-config="container_name=$TF_VAR_terraform_state_container_name" \ - -backend-config="key=${TRE_ID}-gitea" + -backend-config="key=${TRE_ID}-shared-service-sonatype-nexus" terraform destroy -auto-approve diff --git a/templates/shared_services/sonatype-nexus/terraform/locals.tf b/templates/shared_services/sonatype-nexus/terraform/locals.tf index f9828b7ec..015df1fe3 100644 --- a/templates/shared_services/sonatype-nexus/terraform/locals.tf +++ b/templates/shared_services/sonatype-nexus/terraform/locals.tf @@ -2,6 +2,6 @@ locals { core_vnet = "vnet-${var.tre_id}" core_resource_group_name = "rg-${var.tre_id}" firewall_name = "fw-${var.tre_id}" - storage_account_name = "stg${var.tre_id}" + storage_account_name = lower(replace("stg-${var.tre_id}", "-", "")) nexus_allowed_fqdns_list = distinct(compact(split(",", replace(var.nexus_allowed_fqdns, " ", "")))) } diff --git a/templates/shared_services/sonatype-nexus/terraform/main.tf b/templates/shared_services/sonatype-nexus/terraform/main.tf new file mode 100644 index 000000000..715a8db03 --- /dev/null +++ b/templates/shared_services/sonatype-nexus/terraform/main.tf @@ -0,0 +1,15 @@ +# Azure Provider source and version being used +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "=2.97.0" + } + } + + backend "azurerm" {} +} + +provider "azurerm" { + features {} +} diff --git a/templates/shared_services/sonatype-nexus/terraform/variables.tf b/templates/shared_services/sonatype-nexus/terraform/variables.tf index dd574d3c1..d89848be7 100644 --- a/templates/shared_services/sonatype-nexus/terraform/variables.tf +++ b/templates/shared_services/sonatype-nexus/terraform/variables.tf @@ -19,3 +19,9 @@ variable "nexus_allowed_fqdns" { description = "comma seperated string of allowed FQDNs for Nexus" default = "*pypi.org,files.pythonhosted.org,security.ubuntu.com,archive.ubuntu.com" } + +variable "nexus_properties_path" { + type = string + description = "relative path of nexus properties file" + default = "/cnab/app/nexus.properties" +} diff --git a/templates/shared_services/sonatype-nexus/terraform/webapp.tf b/templates/shared_services/sonatype-nexus/terraform/webapp.tf index 283e17a22..d992c71c6 100644 --- a/templates/shared_services/sonatype-nexus/terraform/webapp.tf +++ b/templates/shared_services/sonatype-nexus/terraform/webapp.tf @@ -199,7 +199,7 @@ resource "null_resource" "upload_nexus_props" { --name etc --share-name ${azurerm_storage_share.nexus.name} \ --account-name ${data.azurerm_storage_account.nexus.name} \ --account-key ${data.azurerm_storage_account.nexus.primary_access_key} && \ - az storage file upload --source ../../shared_services/sonatype-nexus/nexus.properties \ + az storage file upload --source ${var.nexus_properties_path} \ --path etc --share-name ${azurerm_storage_share.nexus.name} \ --account-name ${data.azurerm_storage_account.nexus.name} \ --account-key ${data.azurerm_storage_account.nexus.primary_access_key}