Split out Firewall / Nexus / Gitea (#1365)

* WIP: doesn't work yet

* Make temporary changes to the makefile

* Fixes to firewall submodule

* Update Makefile

* move firewall name to locals

* Init porter bundles for Gitea and Nexus

* Add parameters to the new porter bundles

* Revert "Convert data inputs into variable inputs for modules in Terraform (#1154)"

This reverts commit c3e2cb7f0a.

* WIP: moving variables around for Gitea

* Update Gitea module to consume variables from data

* Fix several problems in firewall module

* Changes to Gitea terraform (fix state container, add az login for local-exec)

* Initial Nexus porter configuration

* Add Sonatype-Nexus bundle

* Uncomment firewall lock, fix local-exec command

* Fix comments

* fmt

* Gitea, Nexus: Move variable inputs to data and locals

* change path to nexus.properties

* temporarily remove arm_client_id

* fmt

* remove unused arguments

* fmt

* Use key_vault_reference_identity_id in Terraform

* Remove unused variables

* Deploy Firewall, Gitea and Nexus as part of the main build

* Add deploying of shared services to tre-deploy command

* Add uninstall back

* WIP: working transfer of state for Firewall

* WIP: fiddling with more states

* WIP: fix removal of terraform state

* Add import script for Gitea

* fixup tre-start/stop make target naming

* strip '-' from string in storage account name

* removed state_remove for gitea + nexus

* removed state_remove for gitea + nexus

* local modifications of import/remove state scripts

* fw / gitea / nexus deploy from local via tf functional

* gitignore

* bumped gitea version

* tf linting

* PR updates

* vars for ci

* added check_dependencies to login in CI

* check for non-existing RG and skipping import state if we're in a fresh CI

* removed lock from remove/import scripts

* remove/import state for gitea

* gitea and nexus state moved

* nexus + gitea state moved, apart from storage share

* fixed storage import

* PR snags

* override

* kv uri

* new secret import style

* secret

* secret

* state list

* state list

* remove state fix

* remove state special chars

* importing random_password to prevent KV updating

* moved make target out of default path

* supress risky log output

* unwound gitea/nexus state moving debacle

Co-authored-by: Tanya Borisova <tborisova@microsoft.com>
Co-authored-by: Ross Smith <ross-p-smith@users.noreply.github.com>
Co-authored-by: Stuart Leeks <stuartle@microsoft.com>
This commit is contained in:
David Moore 2022-02-25 13:46:14 +00:00 коммит произвёл GitHub
Родитель c2742f6feb
Коммит ce3ddb91af
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
45 изменённых файлов: 847 добавлений и 170 удалений

2
.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

Просмотреть файл

@ -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 \

Просмотреть файл

@ -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
}

Просмотреть файл

@ -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
}

Просмотреть файл

@ -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
]
}

Просмотреть файл

@ -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
}

Просмотреть файл

@ -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"

Просмотреть файл

@ -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

2
templates/shared_services/firewall/.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,2 @@
.cnab/
.terraform*

Просмотреть файл

@ -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

Просмотреть файл

@ -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"
}
}
]
}

Просмотреть файл

@ -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"
}
}
]
}

Просмотреть файл

@ -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"

Просмотреть файл

@ -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
}

Просмотреть файл

@ -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
]
}

Просмотреть файл

@ -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"

Просмотреть файл

@ -0,0 +1,4 @@
locals {
core_resource_group_name = "rg-${var.tre_id}"
firewall_name = "fw-${var.tre_id}"
}

Просмотреть файл

@ -6,4 +6,10 @@ terraform {
version = "=2.97.0"
}
}
backend "azurerm" {}
}
provider "azurerm" {
features {}
}

Просмотреть файл

@ -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

Просмотреть файл

@ -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
}

Просмотреть файл

@ -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"
}

Просмотреть файл

@ -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

1
templates/shared_services/gitea/.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
.cnab/

Просмотреть файл

@ -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

Просмотреть файл

@ -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"
}
}
]
}

Просмотреть файл

@ -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"
}
}
]
}

Просмотреть файл

@ -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"

Просмотреть файл

@ -20,3 +20,4 @@ resource "azurerm_firewall_application_rule_collection" "web_app_subnet_gitea" {
source_addresses = data.azurerm_subnet.web_app.address_prefixes
}
}

Просмотреть файл

@ -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

Просмотреть файл

@ -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, " ", ""))))

Просмотреть файл

@ -6,4 +6,10 @@ terraform {
version = "=2.97.0"
}
}
backend "azurerm" {}
}
provider "azurerm" {
features {}
}

Просмотреть файл

@ -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

Просмотреть файл

@ -1 +1 @@
__version__ = "0.1.1"
__version__ = "0.1.2"

Просмотреть файл

@ -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

1
templates/shared_services/sonatype-nexus/.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
.cnab/

Просмотреть файл

@ -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

Просмотреть файл

@ -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"
}
}
]
}

Просмотреть файл

@ -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"
}
}
]
}

Просмотреть файл

@ -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"

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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, " ", ""))))
}

Просмотреть файл

@ -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 {}
}

Просмотреть файл

@ -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"
}

Просмотреть файл

@ -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}