From 65b906f72fa26bdebe567a6a1f8d7555e26b6c23 Mon Sep 17 00:00:00 2001 From: Glenn Musa Date: Thu, 1 Apr 2021 15:26:22 -0400 Subject: [PATCH 01/31] create names and resources the same way --- .gitignore | 1 + src/docs/ui-deployment.md | 40 +-- src/mlz.config.sample | 11 + src/scripts/config/generate_config_file.sh | 49 ++++ src/scripts/config/generate_names.sh | 15 +- src/scripts/config/mlz_config_create.sh | 34 +-- src/scripts/mlz_tf_setup.sh | 8 +- src/scripts/setup_ezdeploy.sh | 303 +++++++++++---------- 8 files changed, 256 insertions(+), 205 deletions(-) create mode 100644 src/mlz.config.sample create mode 100755 src/scripts/config/generate_config_file.sh diff --git a/.gitignore b/.gitignore index 3276b3bfe..6821f2e6e 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ terraform-provider-random_v* # Setup config variables file mlz_tf_cfg.var +mlz.config saca-hub.tfvars.json tier-0.tfvars.json tier-1.tfvars.json diff --git a/src/docs/ui-deployment.md b/src/docs/ui-deployment.md index aec764ce9..e9c3ef3ef 100644 --- a/src/docs/ui-deployment.md +++ b/src/docs/ui-deployment.md @@ -1,6 +1,6 @@ # Mission LZ User Interface -The mission LZ front-end is designed to be a single stop for easily entering all of the configuration items that Terraform needs to deploy Mission LZ to a target set of subscriptions. +The mission LZ front-end is designed to be a single stop for easily entering all of the configuration items that Terraform needs to deploy Mission LZ to a target set of subscriptions. ## General Requirements @@ -11,11 +11,11 @@ For any of the following options you will need docker on your machine. If you ar 1. Install [Install WSL2](https://docs.microsoft.com/en-us/windows/wsl/install-win10) and [Docker on Windows for WSL2](https://docs.microsoft.com/en-us/windows/wsl/tutorials/wsl-containers), or [Install Docker Linux](https://docs.docker.com/engine/install/ubuntu) (Docker-Compose is also required, and is intalled by default with Docker Desktop.) 1. [Install the Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli). Be sure to install the Azure CLI in your Linux or WSL environment. -> If you will be transferring this package to an air-gapped cloud, please run the pre-packaging requirements to build a package that's ready to be transferred. This will prepare a docker image with all requirements to run ezdeploy. This is necessary if you don't have access to an updated docker repo/pip repo in your target network. If you do have these, you can proceed with the installation as if installing to an internet connected Azure Cloud. +> If you will be transferring this package to an air-gapped cloud, please run the pre-packaging requirements to build a package that's ready to be transferred. This will prepare a docker image with all requirements to run ezdeploy. This is necessary if you don't have access to an updated docker repo/pip repo in your target network. If you do have these, you can proceed with the installation as if installing to an internet connected Azure Cloud. ## Step-By-Step -[Step-by-Step Remote Installation/Execution](#Step-by-Step-Azure-Installation) (recommended) +[Step-by-Step Remote Installation/Execution](#Step-by-Step-Azure-Installation) (recommended) [Step-by-Step Local Installation/Execution](#Step-by-Step-Local-Installation) (more difficult) To get started, you'll need to be running from a bash/zsh environment. If you are on a Windows machine you can use WSL2. @@ -57,7 +57,7 @@ apt-get update \ Before running locally, you must follow the instructions in the primary readme file for this repo. You must have terraform pre-requisites installed in order to execute from a local system. Local execution will also require your credentials to have access to the service principal credentials for this system to assume; meaning that you should perform: -```BASH +```bash az login ``` @@ -65,18 +65,18 @@ prior to following the following instructions 1. Install and Source a Python Virtual Environment -```bash + ```bash python3 -m venv /path/to/new/virtual/environment source /path/to/new/virtual/environment/bin/activate -``` + ``` -2. Install requirements via pip +1. Install requirements via pip -```BASH + ```bash pip install -r src/front/requirements.txt -``` + ``` -3. Run the installation scripts to deploy app requirements +1. Run the installation scripts to deploy app requirements You will need the following variables for the script: @@ -98,14 +98,14 @@ prior to following the following instructions -2: Tier 1 Subscription ID -3: Tier 2 Subscription ID -```bash + ```bash chmod u+x ./script/setup_ezdeploy.sh ./script/setup_ezdeploy.sh -d local -s -t -l -e -m -p port p -0 -1 -2 -3 " -``` + ``` -4. Invoke environment variables needed for login (These are returned after setup_ezdeploy.sh is run) +1. Invoke environment variables needed for login (These are returned after setup_ezdeploy.sh is run) -```powershell + ```powershell $env:CLIENT_ID="" $env:CLIENT_SECRET=" -``` + ``` You can then access the application by pointing your browser at "localhost". diff --git a/src/mlz.config.sample b/src/mlz.config.sample new file mode 100644 index 000000000..a82a65656 --- /dev/null +++ b/src/mlz.config.sample @@ -0,0 +1,11 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +tf_environment="{TF_ENVIRONMENT}" # https://www.terraform.io/docs/language/settings/backends/azurerm.html#environment +mlz_env_name="{MLZ_ENV_NAME}" # Unique name for MLZ environment +mlz_config_subid="{MLZ_CONFIG_SUBID}" # Subscription ID for Key Vault storing Service Principal creds +mlz_config_location="{MLZ_CONFIG_LOCATION}" # Azure Region for deploying Mission LZ configuration resources +mlz_tenantid="{MLZ_TENANTID}" +mlz_saca_subid="{MLZ_SACA_SUBID}" +mlz_tier0_subid="{MLZ_TIER0_SUBID}" +mlz_tier1_subid="{MLZ_TIER1_SUBID}" +mlz_tier2_subid="{MLZ_TIER2_SUBID}" diff --git a/src/scripts/config/generate_config_file.sh b/src/scripts/config/generate_config_file.sh new file mode 100755 index 000000000..6bcbda6c0 --- /dev/null +++ b/src/scripts/config/generate_config_file.sh @@ -0,0 +1,49 @@ +#!/bin/bash +# +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# +# Generate a file named mlz.config given MLZ prerequisites. + +set -e + +error_log() { + echo "${1}" 1>&2; +} + +usage() { + echo "generate_config_file.sh: Generate a file at the root named mlz.config given MLZ prerequisites" + error_log "usage: generate_config_file.sh " +} + +if [[ "$#" -lt 11 ]]; then + usage + exit 1 +fi + +dest_file=${1} +tf_env=${2} +metadatahost=${3} +env_name=${4} +location=${5} +config_subid=${6} +tenantid=${7} +saca_subid=${8} +tier0_subid=${9} +tier1_subid=${10} +tier2_subid=${11} + +rm -f "$dest_file" +touch "$dest_file" +{ + echo "tf_environment=${tf_env}" + echo "mlz_metadatahost=${metadatahost}" + echo "mlz_env_name=${env_name}" + echo "mlz_config_location=${location}" + echo "mlz_config_subid=${config_subid}" + echo "mlz_tenantid=${tenantid}" + echo "mlz_saca_subid=${saca_subid}" + echo "mlz_tier0_subid=${tier0_subid}" + echo "mlz_tier1_subid=${tier1_subid}" + echo "mlz_tier2_subid=${tier2_subid}" +} >> "$dest_file" diff --git a/src/scripts/config/generate_names.sh b/src/scripts/config/generate_names.sh index 4ac7862a2..1a3653c46 100755 --- a/src/scripts/config/generate_names.sh +++ b/src/scripts/config/generate_names.sh @@ -26,15 +26,12 @@ if [[ "$#" -lt 1 ]]; then exit 1 fi -# Front End By Pass Check -if [[ ${1} != "bypass" ]]; then - mlz_config=$(realpath "${1}") - tf_sub_id_raw=${2:-notset} - tf_name_raw=${3:-notset} +mlz_config=$(realpath "${1}") +tf_sub_id_raw=${2:-notset} +tf_name_raw=${3:-notset} - # source variables from MLZ config - . "${mlz_config}" -fi +# source variables from MLZ config +. "${mlz_config}" # remove hyphens for resource naming restrictions # in the future, do more cleansing @@ -68,8 +65,6 @@ export mlz_fe_app_name="${mlz_fe_app_name_full:0:24}" export mlz_instance_name="${mlz_instance_name_full:0:24}" export mlz_dns_name="${mlz_dns_name_full:0:24}" -# FE Resources - if [[ $tf_name_raw != "notset" ]]; then # remove hyphens for resource naming restrictions # in the future, do more cleansing diff --git a/src/scripts/config/mlz_config_create.sh b/src/scripts/config/mlz_config_create.sh index 210ae8ac7..6d37b6a02 100755 --- a/src/scripts/config/mlz_config_create.sh +++ b/src/scripts/config/mlz_config_create.sh @@ -25,25 +25,19 @@ if [[ "$#" -lt 1 ]]; then exit 1 fi -# Front End By Pass Check -if [[ ${1} != "bypass" ]]; then - - mlz_tf_cfg=$(realpath "${1}") - - # Source variables - . "${mlz_tf_cfg}" - - # Create array of unique subscription IDs. The 'sed' command below search thru the source - # variables file looking for all lines that do not have a '#' in the line. If a line with - # a '#' is found, the '#' and ever character after it in the line is ignored. The output - # of what remains from the sed command is then piped to grep to find the words that match - # the pattern. These words are what make up the 'mlz_subs' array. - mlz_sub_pattern="mlz_.*._subid" - mlz_subs=$(< "${mlz_tf_cfg}" sed 's:#.*$::g' | grep -w "${mlz_sub_pattern}") - subs=() -else - mlz_tf_cfg="bypass" -fi +mlz_tf_cfg=$(realpath "${1}") + +# Source variables +. "${mlz_tf_cfg}" + +# Create array of unique subscription IDs. The 'sed' command below search thru the source +# variables file looking for all lines that do not have a '#' in the line. If a line with +# a '#' is found, the '#' and ever character after it in the line is ignored. The output +# of what remains from the sed command is then piped to grep to find the words that match +# the pattern. These words are what make up the 'mlz_subs' array. +mlz_sub_pattern="mlz_.*._subid" +mlz_subs=$(< "${mlz_tf_cfg}" sed 's:#.*$::g' | grep -w "${mlz_sub_pattern}") +subs=() # generate MLZ configuration names . "${BASH_SOURCE%/*}/generate_names.sh" "${mlz_tf_cfg}" @@ -83,7 +77,7 @@ if [[ -z $(az ad sp list --filter "displayName eq '${mlz_sp_name}'" --query "[]. # Make available to calling scripts export sp_objid=${sp_objid} - + # Assign Contributor role to Service Principal for sub in "${subs[@]}" do diff --git a/src/scripts/mlz_tf_setup.sh b/src/scripts/mlz_tf_setup.sh index 91b3fd6fb..b431f732b 100755 --- a/src/scripts/mlz_tf_setup.sh +++ b/src/scripts/mlz_tf_setup.sh @@ -17,8 +17,8 @@ error_log() { } usage() { - echo "mlz_tf_setup.sh: configure a resource group that contains Terraform state and a secret store, the presence of bypass indicates skipping primary creation" - error_log "usage: mlz_tf_setup.sh " + echo "mlz_tf_setup.sh: configure a resource group that contains Terraform state and a secret store" + error_log "usage: mlz_tf_setup.sh " } if [[ "$#" -lt 1 ]]; then @@ -49,9 +49,7 @@ create_tf_config() { ################################################## # generate MLZ configuration resources -if [[ ${2} != "bypass" ]]; then - . "${BASH_SOURCE%/*}/config/mlz_config_create.sh" "${mlz_tf_cfg}" "${mlz_env_name}" "${mlz_config_location}" -fi +. "${BASH_SOURCE%/*}/config/mlz_config_create.sh" "${mlz_tf_cfg}" "${mlz_env_name}" "${mlz_config_location}" create_tf_config "${mlz_saca_subid}" "${core_path}/saca-hub" create_tf_config "${mlz_tier0_subid}" "${core_path}/tier-0" diff --git a/src/scripts/setup_ezdeploy.sh b/src/scripts/setup_ezdeploy.sh index e194f63aa..45d052d11 100755 --- a/src/scripts/setup_ezdeploy.sh +++ b/src/scripts/setup_ezdeploy.sh @@ -26,38 +26,40 @@ if [[ "$#" -lt 8 ]]; then exit 1 fi -export tf_environment=public -export mlz_env_name=mlzdeployment -export web_port=80 +metadata_host="management.azure.com" # TODO (20210401): pass this by parameter or derive from cloud + +tf_environment=public +mlz_env_name=mlzdeployment +web_port=80 subs=() while getopts "d:s:t:l:e:m:p:0:1:2:3:4:" opts; do case "${opts}" in - d) export docker_strategy=${OPTARG} + d) docker_strategy=${OPTARG} ;; - s) export mlz_config_subid=${OPTARG} + s) mlz_config_subid=${OPTARG} subs+=("${OPTARG}") ;; - t) export mlz_tenantid=${OPTARG} + t) mlz_tenantid=${OPTARG} ;; - l) export mlz_config_location=${OPTARG} + l) mlz_config_location=${OPTARG} ;; - e) export tf_environment=${OPTARG} + e) tf_environment=${OPTARG} ;; - m) export mlz_env_name=${OPTARG} + m) mlz_env_name=${OPTARG} ;; - p) export web_port=${OPTARG} + p) web_port=${OPTARG} ;; - 0) export mlz_saca_subid=${OPTARG} + 0) mlz_saca_subid=${OPTARG} subs+=("${OPTARG}") ;; - 1) export mlz_tier0_subid=${OPTARG} + 1) mlz_tier0_subid=${OPTARG} subs+=("${OPTARG}") ;; - 2) export mlz_tier1_subid=${OPTARG} + 2) mlz_tier1_subid=${OPTARG} subs+=("${OPTARG}") ;; - 3) export mlz_tier2_subid=${OPTARG} + 3) mlz_tier2_subid=${OPTARG} subs+=("${OPTARG}") ;; ?) @@ -67,140 +69,141 @@ while getopts "d:s:t:l:e:m:p:0:1:2:3:4:" opts; do esac done -# generate MLZ configuration names -. "${BASH_SOURCE%/*}/config/generate_names.sh" "bypass" - -# create the subscription resources -. "${BASH_SOURCE%/*}/config/mlz_config_create.sh" "bypass" - -for sub in "${subs[@]}" - do - echo "Setting Contributor role assignment for ${mlz_sp_name} on subscription ID: ${sub}" - az role assignment create \ - --role Contributor \ - --assignee-object-id "${sp_objid}" \ - --scope "/subscriptions/${sub}" \ - --assignee-principal-type ServicePrincipal \ - --output none - done - -echo "INFO: Setting current az cli subscription to ${mlz_config_subid}" -az account set --subscription "${mlz_config_subid}" - -# Handle Deployment of Login Services - -# Handle Remote Deploy to a Container Instance -if [[ $docker_strategy != "local" ]]; then - echo "Creating ACR" - az acr create \ - --resource-group "${mlz_rg_name}" \ - --name "${mlz_acr_name}" \ - --sku Basic - - echo "Waiting for registry completion and running post process to enable admin on ACR" - sleep 60 - az acr update --name "${mlz_acr_name}" --admin-enabled true - - . "${BASH_SOURCE%/*}/ezdeploy_docker.sh" "$docker_strategy" - - docker tag lzfront:latest "${mlz_acr_name}.azurecr.io/lzfront:latest" - - echo "INFO: Logging into Container Registry" - az acr login --name "${mlz_acr_name}" - - ACR_REGISTRY_ID=$(az acr show --name "${mlz_acr_name}" --query id --output tsv) - az role assignment create --assignee "$(az keyvault secret show --name "${mlz_sp_kv_name}" --vault-name "${mlz_kv_name}" --query value --output tsv)" --scope "${ACR_REGISTRY_ID}" --role acrpull - - echo "INFO: pushing docker container" - docker tag lzfront:latest "${mlz_acr_name}".azurecr.io/lzfront:latest - docker push "${mlz_acr_name}".azurecr.io/lzfront:latest - ACR_LOGIN_SERVER=$(az acr show --name "${mlz_acr_name}" --resource-group "${mlz_rg_name}" --query "loginServer" --output tsv) - - echo "INFO: creating instance" - fqdn=$(az container create \ - --resource-group "${mlz_rg_name}"\ - --name "${mlz_instance_name}" \ - --image "$ACR_LOGIN_SERVER"/lzfront:latest \ - --dns-name-label "${mlz_dns_name}" \ - --environment-variables KEYVAULT_ID="${mlz_kv_name}" TENANT_ID="${mlz_tenantid}" MLZ_LOCATION="${mlz_config_location}" SUBSCRIPTION_ID="${mlz_config_subid}" TF_ENV="${tf_environment}" MLZ_ENV="${mlz_env_name}" \ - --registry-username "$(az keyvault secret show --name "${mlz_sp_kv_name}" --vault-name "${mlz_kv_name}" --query value --output tsv)" \ - --registry-password "$(az keyvault secret show --name "${mlz_sp_kv_password}" --vault-name "${mlz_kv_name}" --query value --output tsv)" \ - --ports 80 \ - --query ipAddress.fqdn \ - --assign-identity \ - --output tsv) - - echo "INFO: Giving Instance the necessary permissions" - az keyvault set-policy \ - -n "${mlz_kv_name}" \ - --key-permissions get list \ - --secret-permissions get list \ - --object-id "$(az container show --resource-group "${mlz_rg_name}" --name "${mlz_instance_name}" --query identity.principalId --output tsv)" -else - fqdn="localhost" -fi +# create 'src/mlz.config' file +src_path=$(dirname "$(realpath "${BASH_SOURCE%/*}")") +mlz_config_file="${src_path}/mlz.config" + +. "${BASH_SOURCE%/*}/config/generate_config_file.sh" \ + "$mlz_config_file" \ + "$tf_environment" \ + "$metadata_host" \ + "$mlz_env_name" \ + "$mlz_config_location" \ + "$mlz_config_subid" \ + "$mlz_tenantid" \ + "$mlz_saca_subid" \ + "$mlz_tier0_subid" \ + "$mlz_tier1_subid" \ + "$mlz_tier2_subid" -if [[ $web_port != 80 ]]; then - fqdn+=":$web_port" -fi - - -# Generate the Login EndPoint for Security Purposes -echo "Creating App Registration to facilitate login capabilities" -client_id=$(az ad app create \ - --display-name "${mlz_fe_app_name}" \ - --reply-urls "http://$fqdn/redirect" \ - --required-resource-accesses "${BASH_SOURCE%/*}"/config/mlz_login_app_resources.json \ - --query appId \ - --output tsv) - -client_password=$(az ad app credential reset \ - --id "$client_id" \ - --query password \ - --output tsv) - -echo "Storing client id at ${mlz_login_app_kv_name}" -az keyvault secret set \ - --name "${mlz_login_app_kv_name}" \ - --subscription "${mlz_config_subid}" \ - --vault-name "${mlz_kv_name}" \ - --value "$client_id" \ - --output none - -echo "Storing client secret at ${mlz_login_app_kv_password}" -az keyvault secret set \ - --name "${mlz_login_app_kv_password}" \ - --subscription "${mlz_config_subid}" \ - --vault-name "${mlz_kv_name}" \ - --value "$client_password" \ - --output none - -echo "KeyVault updated with Login App Registration secret!" -echo "All steps have been completed you will need the following to access the configuration utility:" - -if [[ $docker_strategy == "local" ]]; then - echo "Your environment variables for local execution are:" - echo "Copy-Paste:" - echo "Bash:" - echo "export CLIENT_ID=$client_id" - echo "export CLIENT_SECRET=$client_password" - echo "export TENANT_ID=$mlz_tenantid" - echo "export LOCATION=$mlz_config_location" - echo "export SUBSCRIPTION_ID=$mlz_config_subid" - echo "export TF_ENV=$tf_environment" - echo "export MLZ_ENV=$mlz_env_name" - echo "export MLZCLIENTID=$(az keyvault secret show --name "${mlz_sp_kv_name}" --vault-name "${mlz_kv_name}" --query value --output tsv)" - echo "export MLZCLIENTSECRET=$(az keyvault secret show --name "${mlz_sp_kv_password}" --vault-name "${mlz_kv_name}" --query value --output tsv)" - echo "Powershell:" - echo "\$env:CLIENT_ID='$client_id'" - echo "\$env:CLIENT_SECRET='$client_password'" - echo "\$env:TENANT_ID='$mlz_tenantid'" - echo "\$env:LOCATION='$mlz_config_location'" - echo "\$env:SUBSCRIPTION_ID='$mlz_config_subid'" - echo "\$env:TF_ENV='$tf_environment'" - echo "\$env:MLZ_ENV='$mlz_env_name'" - echo "\$env:MLZCLIENTID='$(az keyvault secret show --name "${mlz_sp_kv_name}" --vault-name "${mlz_kv_name}" --query value --output tsv)'" - echo "\$env:MLZCLIENTSECRET='$(az keyvault secret show --name "${mlz_sp_kv_password}" --vault-name "${mlz_kv_name}" --query value --output tsv)'" -else - echo "You can access the front end at http://$fqdn" -fi \ No newline at end of file +# generate MLZ configuration names +. "${BASH_SOURCE%/*}/config/generate_names.sh" "$mlz_config_file" + +# echo "INFO: Setting current az cli subscription to ${mlz_config_subid}" +# az account set --subscription "${mlz_config_subid}" + +# # Handle Remote Deploy to a Container Instance +# if [[ $docker_strategy != "local" ]]; then +# echo "Creating ACR" +# az acr create \ +# --resource-group "${mlz_rg_name}" \ +# --name "${mlz_acr_name}" \ +# --sku Basic + +# echo "Waiting for registry completion and running post process to enable admin on ACR" +# sleep 60 +# az acr update --name "${mlz_acr_name}" --admin-enabled true + +# . "${BASH_SOURCE%/*}/ezdeploy_docker.sh" "$docker_strategy" + +# docker tag lzfront:latest "${mlz_acr_name}.azurecr.io/lzfront:latest" + +# echo "INFO: Logging into Container Registry" +# az acr login --name "${mlz_acr_name}" + +# ACR_REGISTRY_ID=$(az acr show --name "${mlz_acr_name}" --query id --output tsv) +# az role assignment create --assignee "$(az keyvault secret show --name "${mlz_sp_kv_name}" --vault-name "${mlz_kv_name}" --query value --output tsv)" --scope "${ACR_REGISTRY_ID}" --role acrpull + +# echo "INFO: pushing docker container" +# docker tag lzfront:latest "${mlz_acr_name}".azurecr.io/lzfront:latest +# docker push "${mlz_acr_name}".azurecr.io/lzfront:latest +# ACR_LOGIN_SERVER=$(az acr show --name "${mlz_acr_name}" --resource-group "${mlz_rg_name}" --query "loginServer" --output tsv) + +# echo "INFO: creating instance" +# fqdn=$(az container create \ +# --resource-group "${mlz_rg_name}"\ +# --name "${mlz_instance_name}" \ +# --image "$ACR_LOGIN_SERVER"/lzfront:latest \ +# --dns-name-label "${mlz_dns_name}" \ +# --environment-variables KEYVAULT_ID="${mlz_kv_name}" TENANT_ID="${mlz_tenantid}" MLZ_LOCATION="${mlz_config_location}" SUBSCRIPTION_ID="${mlz_config_subid}" TF_ENV="${tf_environment}" MLZ_ENV="${mlz_env_name}" \ +# --registry-username "$(az keyvault secret show --name "${mlz_sp_kv_name}" --vault-name "${mlz_kv_name}" --query value --output tsv)" \ +# --registry-password "$(az keyvault secret show --name "${mlz_sp_kv_password}" --vault-name "${mlz_kv_name}" --query value --output tsv)" \ +# --ports 80 \ +# --query ipAddress.fqdn \ +# --assign-identity \ +# --output tsv) + +# echo "INFO: Giving Instance the necessary permissions" +# az keyvault set-policy \ +# -n "${mlz_kv_name}" \ +# --key-permissions get list \ +# --secret-permissions get list \ +# --object-id "$(az container show --resource-group "${mlz_rg_name}" --name "${mlz_instance_name}" --query identity.principalId --output tsv)" +# else +# fqdn="localhost" +# fi + +# if [[ $web_port != 80 ]]; then +# fqdn+=":$web_port" +# fi + + +# # Generate the Login EndPoint for Security Purposes +# echo "Creating App Registration to facilitate login capabilities" +# client_id=$(az ad app create \ +# --display-name "${mlz_fe_app_name}" \ +# --reply-urls "http://$fqdn/redirect" \ +# --required-resource-accesses "${BASH_SOURCE%/*}"/config/mlz_login_app_resources.json \ +# --query appId \ +# --output tsv) + +# client_password=$(az ad app credential reset \ +# --id "$client_id" \ +# --query password \ +# --output tsv) + +# echo "Storing client id at ${mlz_login_app_kv_name}" +# az keyvault secret set \ +# --name "${mlz_login_app_kv_name}" \ +# --subscription "${mlz_config_subid}" \ +# --vault-name "${mlz_kv_name}" \ +# --value "$client_id" \ +# --output none + +# echo "Storing client secret at ${mlz_login_app_kv_password}" +# az keyvault secret set \ +# --name "${mlz_login_app_kv_password}" \ +# --subscription "${mlz_config_subid}" \ +# --vault-name "${mlz_kv_name}" \ +# --value "$client_password" \ +# --output none + +# echo "KeyVault updated with Login App Registration secret!" +# echo "All steps have been completed you will need the following to access the configuration utility:" + +# if [[ $docker_strategy == "local" ]]; then +# echo "Your environment variables for local execution are:" +# echo "Copy-Paste:" +# echo "Bash:" +# echo "export CLIENT_ID=$client_id" +# echo "export CLIENT_SECRET=$client_password" +# echo "export TENANT_ID=$mlz_tenantid" +# echo "export LOCATION=$mlz_config_location" +# echo "export SUBSCRIPTION_ID=$mlz_config_subid" +# echo "export TF_ENV=$tf_environment" +# echo "export MLZ_ENV=$mlz_env_name" +# echo "export MLZCLIENTID=$(az keyvault secret show --name "${mlz_sp_kv_name}" --vault-name "${mlz_kv_name}" --query value --output tsv)" +# echo "export MLZCLIENTSECRET=$(az keyvault secret show --name "${mlz_sp_kv_password}" --vault-name "${mlz_kv_name}" --query value --output tsv)" +# echo "Powershell:" +# echo "\$env:CLIENT_ID='$client_id'" +# echo "\$env:CLIENT_SECRET='$client_password'" +# echo "\$env:TENANT_ID='$mlz_tenantid'" +# echo "\$env:LOCATION='$mlz_config_location'" +# echo "\$env:SUBSCRIPTION_ID='$mlz_config_subid'" +# echo "\$env:TF_ENV='$tf_environment'" +# echo "\$env:MLZ_ENV='$mlz_env_name'" +# echo "\$env:MLZCLIENTID='$(az keyvault secret show --name "${mlz_sp_kv_name}" --vault-name "${mlz_kv_name}" --query value --output tsv)'" +# echo "\$env:MLZCLIENTSECRET='$(az keyvault secret show --name "${mlz_sp_kv_password}" --vault-name "${mlz_kv_name}" --query value --output tsv)'" +# else +# echo "You can access the front end at http://$fqdn" +# fi \ No newline at end of file From 3012f9ce1149010318bc26accca8248a1be6fe66 Mon Sep 17 00:00:00 2001 From: Glenn Musa Date: Thu, 1 Apr 2021 15:55:49 -0400 Subject: [PATCH 02/31] branch on strategy --- src/scripts/config/mlz_config_create.sh | 3 --- src/scripts/setup_ezdeploy.sh | 29 +++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/scripts/config/mlz_config_create.sh b/src/scripts/config/mlz_config_create.sh index 6d37b6a02..095059e1b 100755 --- a/src/scripts/config/mlz_config_create.sh +++ b/src/scripts/config/mlz_config_create.sh @@ -75,9 +75,6 @@ if [[ -z $(az ad sp list --filter "displayName eq '${mlz_sp_name}'" --query "[]. --query objectId \ --output tsv) - # Make available to calling scripts - export sp_objid=${sp_objid} - # Assign Contributor role to Service Principal for sub in "${subs[@]}" do diff --git a/src/scripts/setup_ezdeploy.sh b/src/scripts/setup_ezdeploy.sh index 45d052d11..ad4d04eab 100755 --- a/src/scripts/setup_ezdeploy.sh +++ b/src/scripts/setup_ezdeploy.sh @@ -89,8 +89,33 @@ mlz_config_file="${src_path}/mlz.config" # generate MLZ configuration names . "${BASH_SOURCE%/*}/config/generate_names.sh" "$mlz_config_file" -# echo "INFO: Setting current az cli subscription to ${mlz_config_subid}" -# az account set --subscription "${mlz_config_subid}" +echo "INFO: Setting current az cli subscription to ${mlz_config_subid}" +az account set --subscription "${mlz_config_subid}" + +if [[ $docker_strategy != "build" && \ + $docker_strategy != "load" && \ + $docker_strategy != "local" ]]; then + error_log "Unrecognized docker strategy detected. Must be 'local', 'build', or 'load'." +fi + +if [[ $docker_strategy == "build" ]]; then + echo "do work" + # create ACR + # build image + # deploy instance + # add permissions + # get URL +fi + +if [[ $docker_strategy == "load" ]]; then + echo "do work" + # ??? +fi + +if [[ $docker_strategy == "local" ]]; then + echo "do work" + # set env vars +fi # # Handle Remote Deploy to a Container Instance # if [[ $docker_strategy != "local" ]]; then From 23f5ebef3c4b6710feea5b483a8b4c54eb35957f Mon Sep 17 00:00:00 2001 From: Glenn Musa Date: Thu, 1 Apr 2021 16:00:34 -0400 Subject: [PATCH 03/31] fail when not a valid strategy --- src/scripts/setup_ezdeploy.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/src/scripts/setup_ezdeploy.sh b/src/scripts/setup_ezdeploy.sh index ad4d04eab..acd697287 100755 --- a/src/scripts/setup_ezdeploy.sh +++ b/src/scripts/setup_ezdeploy.sh @@ -96,6 +96,7 @@ if [[ $docker_strategy != "build" && \ $docker_strategy != "load" && \ $docker_strategy != "local" ]]; then error_log "Unrecognized docker strategy detected. Must be 'local', 'build', or 'load'." + exit 1 fi if [[ $docker_strategy == "build" ]]; then From a210faaeb17bca35c95fe82c32d51168e658895f Mon Sep 17 00:00:00 2001 From: Glenn Musa Date: Thu, 1 Apr 2021 18:22:53 -0400 Subject: [PATCH 04/31] setup tf state and service principals before creating container --- .../container-registry/add_auth_scopes.sh | 69 +++++++ src/scripts/container-registry/create_acr.sh | 68 ++++++ .../container-registry/deploy_instance.sh | 80 ++++++++ src/scripts/ezdeploy_docker.sh | 45 ---- src/scripts/setup_ezdeploy.sh | 193 +++++------------- src/scripts/setup_ezdeploy_local.sh | 82 ++++++++ src/scripts/util/checkfordocker.sh | 13 ++ 7 files changed, 367 insertions(+), 183 deletions(-) create mode 100755 src/scripts/container-registry/add_auth_scopes.sh create mode 100755 src/scripts/container-registry/create_acr.sh create mode 100755 src/scripts/container-registry/deploy_instance.sh delete mode 100755 src/scripts/ezdeploy_docker.sh create mode 100644 src/scripts/setup_ezdeploy_local.sh create mode 100755 src/scripts/util/checkfordocker.sh diff --git a/src/scripts/container-registry/add_auth_scopes.sh b/src/scripts/container-registry/add_auth_scopes.sh new file mode 100755 index 000000000..4d95a4557 --- /dev/null +++ b/src/scripts/container-registry/add_auth_scopes.sh @@ -0,0 +1,69 @@ +#!/bin/bash +# +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# +# shellcheck disable=SC1090,2154 +# SC1090: Can't follow non-constant source. Use a directive to specify location. +# SC2154: "var is referenced but not assigned". These values come from an external file. +# +# create an app registration and add MSAL auth scopes to facilitate user logon to MLZ UI + +set -e + +error_log() { + echo "${1}" 1>&2; +} + +usage() { + echo "add_auth_scopes.sh: create an app registration and add MSAL auth scopes to facilitate user logon to MLZ UI" + error_log "usage: add_auth_scopes.sh " +} + +if [[ "$#" -lt 3 ]]; then + usage + exit 1 +fi + +mlz_config_file=$1 +fqdn=$2 + +# generate MLZ configuration names +. "$(dirname "$(realpath "${BASH_SOURCE%/*}")")/generate_names.sh" "$mlz_config_file" + +# path to app resources definition file +required_resources_json_file="$(dirname "$(realpath "${BASH_SOURCE%/*}")")/config/mlz_login_app_resources.json" + +# generate app registration +echo "INFO: creating app registration ${mlz_fe_app_name} to facilitate user logon at ${fqdn}..." +client_id=$(az ad app create \ + --display-name "${mlz_fe_app_name}" \ + --reply-urls "http://$fqdn/redirect" \ + --required-resource-accesses "${required_resources_json_file}" \ + --query appId \ + --output tsv) +client_password=$(az ad app credential reset \ + --id "$client_id" \ + --query password \ + --output tsv) + +# update keyvault with the app registration information +echo "INFO: storing app registration information for client ID ${client_id} at ${mlz_login_app_kv_name}..." +az keyvault secret set \ + --name "${mlz_login_app_kv_name}" \ + --subscription "${mlz_config_subid}" \ + --vault-name "${mlz_kv_name}" \ + --value "$client_id" \ + --only-show-errors \ + --output none + +az keyvault secret set \ + --name "${mlz_login_app_kv_password}" \ + --subscription "${mlz_config_subid}" \ + --vault-name "${mlz_kv_name}" \ + --value "$client_password" \ + --only-show-errors \ + --output none + +echo "INFO: waiting thirty seconds to propagate app registration..." +sleep 30 \ No newline at end of file diff --git a/src/scripts/container-registry/create_acr.sh b/src/scripts/container-registry/create_acr.sh new file mode 100755 index 000000000..0c94c0124 --- /dev/null +++ b/src/scripts/container-registry/create_acr.sh @@ -0,0 +1,68 @@ +#!/bin/bash +# +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# +# shellcheck disable=SC1090,SC2154 +# SC1090: Can't follow non-constant source. Use a directive to specify location. +# SC2154: "var is referenced but not assigned". These values come from an external file. +# +# create an Azure Container Registry for hosting the MLZ UI given an MLZ configuration + +set -e + +error_log() { + echo "${1}" 1>&2; +} + +usage() { + echo "create_acr.sh: Create an Azure Container Registry for hosting the MLZ UI given an MLZ configuration" + error_log "usage: create_acr.sh " +} + +if [[ "$#" -lt 1 ]]; then + usage + exit 1 +fi + +mlz_config_file=$1 + +# generate MLZ configuration names +. "$(dirname "$(realpath "${BASH_SOURCE%/*}")")/generate_names.sh" "$mlz_config_file" + +echo "INFO: creating Azure Container Registry ${mlz_acr_name}..." +az acr create \ + --resource-group "${mlz_rg_name}" \ + --name "${mlz_acr_name}" \ + --sku Basic \ + --only-show-errors \ + --output none + +echo "INFO: enabling administration of ${mlz_acr_name}..." +sleep 60 +az acr update \ + --name "${mlz_acr_name}" \ + --admin-enabled true \ + --only-show-errors \ + --output none + +az acr login --name "${mlz_acr_name}" + +acr_id=$(az acr show \ + --name "${mlz_acr_name}" \ + --query id \ + --output tsv) + +client_id=$(az keyvault secret show \ + --name "${mlz_sp_kv_name}" \ + --vault-name "${mlz_kv_name}" \ + --query value \ + --output tsv) + +echo "INFO: granting ${client_id} 'acrpull' on ${mlz_acr_name}" +az role assignment create \ + --assignee "${client_id}" \ + --scope "${acr_id}" \ + --role acrpull \ + --only-show-errors \ + --output none diff --git a/src/scripts/container-registry/deploy_instance.sh b/src/scripts/container-registry/deploy_instance.sh new file mode 100755 index 000000000..b1b05410f --- /dev/null +++ b/src/scripts/container-registry/deploy_instance.sh @@ -0,0 +1,80 @@ +#!/bin/bash +# +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# +# shellcheck disable=SC1090,SC2154 +# SC1090: Can't follow non-constant source. Use a directive to specify location. +# SC2154: "var is referenced but not assigned". These values come from an external file. +# +# deploy a docker image to Azure Container Registry that hosts the MLZ UI + +set -e + +error_log() { + echo "${1}" 1>&2; +} + +usage() { + echo "create_acr.sh: Create an Azure Container Registry for hosting the MLZ UI given an MLZ configuration" + error_log "usage: create_acr.sh " +} + +if [[ "$#" -lt 3 ]]; then + usage + exit 1 +fi + +mlz_config_file=$1 +image_name=$2 +image_tag=$3 + +# generate MLZ configuration names +. "$(dirname "$(realpath "${BASH_SOURCE%/*}")")/generate_names.sh" "$mlz_config_file" + +acr_login_server=$(az acr show \ + --name "${mlz_acr_name}" \ + --resource-group "${mlz_rg_name}" \ + --query "loginServer" \ + --output tsv) + +echo "INFO: creating instance ${mlz_instance_name} in ${mlz_acr_name}..." + +registry_username=$(az keyvault secret show \ + --name "${mlz_sp_kv_name}" \ + --vault-name "${mlz_kv_name}" \ + --query value \ + --output tsv) + +registry_password=$(az keyvault secret show \ + --name "${mlz_sp_kv_password}" \ + --vault-name "${mlz_kv_name}" \ + --query value \ + --output tsv) + +az container create \ + --resource-group "${mlz_rg_name}"\ + --name "${mlz_instance_name}" \ + --image "${acr_login_server}/${image_name}:${image_tag}" \ + --dns-name-label "${mlz_dns_name}" \ + --environment-variables KEYVAULT_ID="${mlz_kv_name}" TENANT_ID="${mlz_tenantid}" MLZ_LOCATION="${mlz_config_location}" SUBSCRIPTION_ID="${mlz_config_subid}" TF_ENV="${tf_environment}" MLZ_ENV="${mlz_env_name}" \ + --registry-username "${registry_username}" \ + --registry-password "${registry_password}" \ + --ports 80 \ + --assign-identity \ + --only-show-errors \ + --output none + +echo "INFO: granting instance ${mlz_instance_name} necessary permissions to keyvault ${mlz_kv_name}..." + +container_obj_id=$(az container show \ + --resource-group "${mlz_rg_name}" \ + --name "${mlz_instance_name}" \ + --query identity.principalId \ + --output tsv) + +az keyvault set-policy \ + --name "${mlz_kv_name}" \ + --key-permissions get list \ + --secret-permissions get list \ + --object-id "${container_obj_id}" diff --git a/src/scripts/ezdeploy_docker.sh b/src/scripts/ezdeploy_docker.sh deleted file mode 100755 index 3b1e52957..000000000 --- a/src/scripts/ezdeploy_docker.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/bash -# -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# -# shellcheck disable=SC1090,SC1091 -# SC1090: Can't follow non-constant source. Use a directive to specify location. -# SC1091: Not following. Shellcheck can't follow non-constant source. -# -# This script builds and tags the docker image - -set -e - -error_log() { - echo "${1}" 1>&2; -} - -# Check for Docker CLI -if ! command -v docker &> /dev/null; then - echo "Docker could not be found. Docker is required to build docker images." - echo "see https://docs.docker.com/engine/install/ubuntu for installation instructions." - exit 1 -fi - -usage() { - echo "ezdeploy_docker.sh: If using 'load' will load from a specified zip file, if using 'build' will build the docker image from the dockerfile." - error_log "usage: ezdeploy_docker.sh {{default=build}}" -} - -if [[ "$#" -lt 1 ]]; then - usage - exit 1 -fi - -echo "INFO: building docker container" - if [[ "${1}" == "build" ]]; then - docker build -t lzfront "${BASH_SOURCE%/*}/../" - elif [[ "${1}" == "load" ]]; then - #TODO: Change this to a file pointer - unzip mlz.zip . - docker load -i mlz.tar - else - echo "Unrecognized docker strategy detected. Must be build or load" - fi - diff --git a/src/scripts/setup_ezdeploy.sh b/src/scripts/setup_ezdeploy.sh index acd697287..23818d54e 100755 --- a/src/scripts/setup_ezdeploy.sh +++ b/src/scripts/setup_ezdeploy.sh @@ -27,6 +27,7 @@ if [[ "$#" -lt 8 ]]; then fi metadata_host="management.azure.com" # TODO (20210401): pass this by parameter or derive from cloud +acr_endpoint="azurecr.io" # TODO (20210401): pass this by parameter or derive from cloud tf_environment=public mlz_env_name=mlzdeployment @@ -69,11 +70,26 @@ while getopts "d:s:t:l:e:m:p:0:1:2:3:4:" opts; do esac done -# create 'src/mlz.config' file -src_path=$(dirname "$(realpath "${BASH_SOURCE%/*}")") -mlz_config_file="${src_path}/mlz.config" +this_script_path=$(realpath "${BASH_SOURCE%/*}") +src_path=$(dirname "${this_script_path}") +container_registry_path="$(realpath "${this_script_path}")/container-registry" + +# check for dependencies +"${this_script_path}/util/checkforazcli.sh" +"${this_script_path}/util/checkfordocker.sh" + +# check docker strategy +if [[ $docker_strategy != "local" && \ + $docker_strategy != "build" && \ + $docker_strategy != "load" ]]; then + error_log "ERROR: Unrecognized docker strategy detected. Must be 'local', 'build', or 'load'." + exit 1 +fi -. "${BASH_SOURCE%/*}/config/generate_config_file.sh" \ +# create MLZ configuration file +mlz_config_file="${src_path}/mlz.config" +echo "INFO: creating a mlz.config file based on user input at $(realpath "$mlz_config_file")..." +"${this_script_path}/config/generate_config_file.sh" \ "$mlz_config_file" \ "$tf_environment" \ "$metadata_host" \ @@ -87,149 +103,50 @@ mlz_config_file="${src_path}/mlz.config" "$mlz_tier2_subid" # generate MLZ configuration names -. "${BASH_SOURCE%/*}/config/generate_names.sh" "$mlz_config_file" +. "${this_script_path}/config/generate_names.sh" "$mlz_config_file" -echo "INFO: Setting current az cli subscription to ${mlz_config_subid}" +echo "INFO: setting up required MLZ resources using $(realpath "$mlz_config_file")..." +"${this_script_path}/mlz_tf_setup.sh" "$mlz_config_file" + +echo "INFO: setting current az cli subscription to ${mlz_config_subid}..." az account set --subscription "${mlz_config_subid}" -if [[ $docker_strategy != "build" && \ - $docker_strategy != "load" && \ - $docker_strategy != "local" ]]; then - error_log "Unrecognized docker strategy detected. Must be 'local', 'build', or 'load'." - exit 1 +if [[ $docker_strategy == "local" ]]; then + local_fqdn="localhost:${web_port}" + "${this_script_path}/setup_ezdeploy_local.sh" "$mlz_config_file" "$local_fqdn" + exit 0 fi +# create container registry +"${container_registry_path}/create_acr.sh" "$mlz_config_file" + +# build/load, tag, and push image +image_name="lzfront" +image_tag=":latest" + if [[ $docker_strategy == "build" ]]; then - echo "do work" - # create ACR - # build image - # deploy instance - # add permissions - # get URL + docker build -t "${image_name}" "${src_path}" fi if [[ $docker_strategy == "load" ]]; then - echo "do work" - # ??? + unzip mlz.zip . + docker load -i mlz.tar fi -if [[ $docker_strategy == "local" ]]; then - echo "do work" - # set env vars -fi +docker tag "${image_name}${image_tag}" "${mlz_acr_name}.${acr_endpoint}/${image_name}${image_tag}" +docker push "${mlz_acr_name}.${acr_endpoint}/${image_name}${image_tag}" + +# deploy instance +"${container_registry_path}/deploy_instance.sh" "$mlz_config_file" "$image_name" "$image_tag" + +# get URL +container_fqdn=$(az container show \ + --resource-group "${mlz_rg_name}"\ + --name "${mlz_instance_name}" \ + --query ipAddress.fqdn \ + --output tsv) + +# create an app registration and add auth scopes to facilitate MSAL login +"${container_registry_path}/add_auth_scopes.sh" "$mlz_config_file" "$container_fqdn" -# # Handle Remote Deploy to a Container Instance -# if [[ $docker_strategy != "local" ]]; then -# echo "Creating ACR" -# az acr create \ -# --resource-group "${mlz_rg_name}" \ -# --name "${mlz_acr_name}" \ -# --sku Basic - -# echo "Waiting for registry completion and running post process to enable admin on ACR" -# sleep 60 -# az acr update --name "${mlz_acr_name}" --admin-enabled true - -# . "${BASH_SOURCE%/*}/ezdeploy_docker.sh" "$docker_strategy" - -# docker tag lzfront:latest "${mlz_acr_name}.azurecr.io/lzfront:latest" - -# echo "INFO: Logging into Container Registry" -# az acr login --name "${mlz_acr_name}" - -# ACR_REGISTRY_ID=$(az acr show --name "${mlz_acr_name}" --query id --output tsv) -# az role assignment create --assignee "$(az keyvault secret show --name "${mlz_sp_kv_name}" --vault-name "${mlz_kv_name}" --query value --output tsv)" --scope "${ACR_REGISTRY_ID}" --role acrpull - -# echo "INFO: pushing docker container" -# docker tag lzfront:latest "${mlz_acr_name}".azurecr.io/lzfront:latest -# docker push "${mlz_acr_name}".azurecr.io/lzfront:latest -# ACR_LOGIN_SERVER=$(az acr show --name "${mlz_acr_name}" --resource-group "${mlz_rg_name}" --query "loginServer" --output tsv) - -# echo "INFO: creating instance" -# fqdn=$(az container create \ -# --resource-group "${mlz_rg_name}"\ -# --name "${mlz_instance_name}" \ -# --image "$ACR_LOGIN_SERVER"/lzfront:latest \ -# --dns-name-label "${mlz_dns_name}" \ -# --environment-variables KEYVAULT_ID="${mlz_kv_name}" TENANT_ID="${mlz_tenantid}" MLZ_LOCATION="${mlz_config_location}" SUBSCRIPTION_ID="${mlz_config_subid}" TF_ENV="${tf_environment}" MLZ_ENV="${mlz_env_name}" \ -# --registry-username "$(az keyvault secret show --name "${mlz_sp_kv_name}" --vault-name "${mlz_kv_name}" --query value --output tsv)" \ -# --registry-password "$(az keyvault secret show --name "${mlz_sp_kv_password}" --vault-name "${mlz_kv_name}" --query value --output tsv)" \ -# --ports 80 \ -# --query ipAddress.fqdn \ -# --assign-identity \ -# --output tsv) - -# echo "INFO: Giving Instance the necessary permissions" -# az keyvault set-policy \ -# -n "${mlz_kv_name}" \ -# --key-permissions get list \ -# --secret-permissions get list \ -# --object-id "$(az container show --resource-group "${mlz_rg_name}" --name "${mlz_instance_name}" --query identity.principalId --output tsv)" -# else -# fqdn="localhost" -# fi - -# if [[ $web_port != 80 ]]; then -# fqdn+=":$web_port" -# fi - - -# # Generate the Login EndPoint for Security Purposes -# echo "Creating App Registration to facilitate login capabilities" -# client_id=$(az ad app create \ -# --display-name "${mlz_fe_app_name}" \ -# --reply-urls "http://$fqdn/redirect" \ -# --required-resource-accesses "${BASH_SOURCE%/*}"/config/mlz_login_app_resources.json \ -# --query appId \ -# --output tsv) - -# client_password=$(az ad app credential reset \ -# --id "$client_id" \ -# --query password \ -# --output tsv) - -# echo "Storing client id at ${mlz_login_app_kv_name}" -# az keyvault secret set \ -# --name "${mlz_login_app_kv_name}" \ -# --subscription "${mlz_config_subid}" \ -# --vault-name "${mlz_kv_name}" \ -# --value "$client_id" \ -# --output none - -# echo "Storing client secret at ${mlz_login_app_kv_password}" -# az keyvault secret set \ -# --name "${mlz_login_app_kv_password}" \ -# --subscription "${mlz_config_subid}" \ -# --vault-name "${mlz_kv_name}" \ -# --value "$client_password" \ -# --output none - -# echo "KeyVault updated with Login App Registration secret!" -# echo "All steps have been completed you will need the following to access the configuration utility:" - -# if [[ $docker_strategy == "local" ]]; then -# echo "Your environment variables for local execution are:" -# echo "Copy-Paste:" -# echo "Bash:" -# echo "export CLIENT_ID=$client_id" -# echo "export CLIENT_SECRET=$client_password" -# echo "export TENANT_ID=$mlz_tenantid" -# echo "export LOCATION=$mlz_config_location" -# echo "export SUBSCRIPTION_ID=$mlz_config_subid" -# echo "export TF_ENV=$tf_environment" -# echo "export MLZ_ENV=$mlz_env_name" -# echo "export MLZCLIENTID=$(az keyvault secret show --name "${mlz_sp_kv_name}" --vault-name "${mlz_kv_name}" --query value --output tsv)" -# echo "export MLZCLIENTSECRET=$(az keyvault secret show --name "${mlz_sp_kv_password}" --vault-name "${mlz_kv_name}" --query value --output tsv)" -# echo "Powershell:" -# echo "\$env:CLIENT_ID='$client_id'" -# echo "\$env:CLIENT_SECRET='$client_password'" -# echo "\$env:TENANT_ID='$mlz_tenantid'" -# echo "\$env:LOCATION='$mlz_config_location'" -# echo "\$env:SUBSCRIPTION_ID='$mlz_config_subid'" -# echo "\$env:TF_ENV='$tf_environment'" -# echo "\$env:MLZ_ENV='$mlz_env_name'" -# echo "\$env:MLZCLIENTID='$(az keyvault secret show --name "${mlz_sp_kv_name}" --vault-name "${mlz_kv_name}" --query value --output tsv)'" -# echo "\$env:MLZCLIENTSECRET='$(az keyvault secret show --name "${mlz_sp_kv_password}" --vault-name "${mlz_kv_name}" --query value --output tsv)'" -# else -# echo "You can access the front end at http://$fqdn" -# fi \ No newline at end of file +echo "INFO: Complete! You can access the front end at http://$container_fqdn" diff --git a/src/scripts/setup_ezdeploy_local.sh b/src/scripts/setup_ezdeploy_local.sh new file mode 100644 index 000000000..6ba618b67 --- /dev/null +++ b/src/scripts/setup_ezdeploy_local.sh @@ -0,0 +1,82 @@ +#!/bin/bash +# +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# +# shellcheck disable=SC1090,2154 +# SC1090: Can't follow non-constant source. Use a directive to specify location. +# SC2154: "var is referenced but not assigned". These values come from an external file. +# +# setup a local front end for MLZ + +set -e + +error_log() { + echo "${1}" 1>&2; +} + +usage() { + echo "setup_ezdeploy_local.sh: setup a local front end for MLZ" + error_log "usage: setup_ezdeploy.sh " +} + +if [[ "$#" -lt 8 ]]; then + usage + exit 1 +fi + +mlz_config_file=$1 +local_fqdn=$2 + +container_registry_path="$(realpath "${BASH_SOURCE%/*}")/container-registry" + +# generate MLZ configuration names +. "$(realpath "${BASH_SOURCE%/*}")/config/generate_names.sh" "$mlz_config_file" + +# create auth scopes +"${container_registry_path}/add_auth_scopes.sh" "$mlz_config_file" "$local_fqdn" + +auth_client_id=$(az keyvault secret show \ + --name "${mlz_login_app_kv_name}" \ + --vault-name "${mlz_kv_name}" \ + --query value \ + --output tsv) +auth_client_secret=$(az keyvault secret show \ + --name "${mlz_login_app_kv_password}" \ + --vault-name "${mlz_kv_name}" \ + --query value \ + --output tsv) +mlz_client_id=$(az keyvault secret show \ + --name "${mlz_sp_kv_name}" \ + --vault-name "${mlz_kv_name}" \ + --query value \ + --output tsv) +mlz_client_secret=$(az keyvault secret show \ + --name "${mlz_sp_kv_password}" \ + --vault-name "${mlz_kv_name}" \ + --query value \ + --output tsv) + +# echo out env vars +echo "INFO: Your environment variables for local execution are:" +echo "for bash:" +echo "export CLIENT_ID=$auth_client_id" +echo "export CLIENT_SECRET=$auth_client_secret" +echo "export TENANT_ID=$mlz_tenantid" +echo "export LOCATION=$mlz_config_location" +echo "export SUBSCRIPTION_ID=$mlz_config_subid" +echo "export TF_ENV=$tf_environment" +echo "export MLZ_ENV=$mlz_env_name" +echo "export MLZCLIENTID=$mlz_client_id" +echo "export MLZCLIENTSECRET=$mlz_client_secret" +echo "for PowerShell:" +echo "\$env:CLIENT_ID='$client_id'" +echo "\$env:CLIENT_SECRET='$client_password'" +echo "\$env:TENANT_ID='$mlz_tenantid'" +echo "\$env:LOCATION='$mlz_config_location'" +echo "\$env:SUBSCRIPTION_ID='$mlz_config_subid'" +echo "\$env:TF_ENV='$tf_environment'" +echo "\$env:MLZ_ENV='$mlz_env_name'" +echo "\$env:MLZCLIENTID='$(az keyvault secret show --name "${mlz_sp_kv_name}" --vault-name "${mlz_kv_name}" --query value --output tsv)'" +echo "\$env:MLZCLIENTSECRET='$(az keyvault secret show --name "${mlz_sp_kv_password}" --vault-name "${mlz_kv_name}" --query value --output tsv)'" +exit 0 \ No newline at end of file diff --git a/src/scripts/util/checkfordocker.sh b/src/scripts/util/checkfordocker.sh new file mode 100755 index 000000000..a2934f923 --- /dev/null +++ b/src/scripts/util/checkfordocker.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +set -e + +# Check for docker CLI +if ! command -v docker &> /dev/null; then + echo "docker could not be found. This script requires the docker CLI." + echo "see https://docs.docker.com/engine/install/ for installation instructions." + exit 1 +fi \ No newline at end of file From 03ecd00b04c40abdd1a9771dc6c2763b8338281a Mon Sep 17 00:00:00 2001 From: Glenn Musa Date: Thu, 1 Apr 2021 18:25:34 -0400 Subject: [PATCH 05/31] update using --- src/scripts/container-registry/create_acr.sh | 2 +- src/scripts/container-registry/deploy_instance.sh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/scripts/container-registry/create_acr.sh b/src/scripts/container-registry/create_acr.sh index 0c94c0124..f26a45dae 100755 --- a/src/scripts/container-registry/create_acr.sh +++ b/src/scripts/container-registry/create_acr.sh @@ -16,7 +16,7 @@ error_log() { } usage() { - echo "create_acr.sh: Create an Azure Container Registry for hosting the MLZ UI given an MLZ configuration" + echo "create_acr.sh: create an Azure Container Registry for hosting the MLZ UI given an MLZ configuration" error_log "usage: create_acr.sh " } diff --git a/src/scripts/container-registry/deploy_instance.sh b/src/scripts/container-registry/deploy_instance.sh index b1b05410f..832515712 100755 --- a/src/scripts/container-registry/deploy_instance.sh +++ b/src/scripts/container-registry/deploy_instance.sh @@ -16,8 +16,8 @@ error_log() { } usage() { - echo "create_acr.sh: Create an Azure Container Registry for hosting the MLZ UI given an MLZ configuration" - error_log "usage: create_acr.sh " + echo "deploy_instance.sh: deploy a docker image to Azure Container Registry that hosts the MLZ UI" + error_log "usage: deploy_instance.sh " } if [[ "$#" -lt 3 ]]; then From 9bb58de3573fe22638c6bceab4138106cb61a2e8 Mon Sep 17 00:00:00 2001 From: Glenn Musa Date: Thu, 1 Apr 2021 20:11:21 -0400 Subject: [PATCH 06/31] remove unused arguments --- src/scripts/config/generate_config_file.sh | 12 ++---------- src/scripts/setup_ezdeploy.sh | 20 ++------------------ 2 files changed, 4 insertions(+), 28 deletions(-) diff --git a/src/scripts/config/generate_config_file.sh b/src/scripts/config/generate_config_file.sh index 6bcbda6c0..802e845eb 100755 --- a/src/scripts/config/generate_config_file.sh +++ b/src/scripts/config/generate_config_file.sh @@ -13,10 +13,10 @@ error_log() { usage() { echo "generate_config_file.sh: Generate a file at the root named mlz.config given MLZ prerequisites" - error_log "usage: generate_config_file.sh " + error_log "usage: generate_config_file.sh " } -if [[ "$#" -lt 11 ]]; then +if [[ "$#" -lt 7 ]]; then usage exit 1 fi @@ -28,10 +28,6 @@ env_name=${4} location=${5} config_subid=${6} tenantid=${7} -saca_subid=${8} -tier0_subid=${9} -tier1_subid=${10} -tier2_subid=${11} rm -f "$dest_file" touch "$dest_file" @@ -42,8 +38,4 @@ touch "$dest_file" echo "mlz_config_location=${location}" echo "mlz_config_subid=${config_subid}" echo "mlz_tenantid=${tenantid}" - echo "mlz_saca_subid=${saca_subid}" - echo "mlz_tier0_subid=${tier0_subid}" - echo "mlz_tier1_subid=${tier1_subid}" - echo "mlz_tier2_subid=${tier2_subid}" } >> "$dest_file" diff --git a/src/scripts/setup_ezdeploy.sh b/src/scripts/setup_ezdeploy.sh index 23818d54e..fca176c1e 100755 --- a/src/scripts/setup_ezdeploy.sh +++ b/src/scripts/setup_ezdeploy.sh @@ -51,18 +51,6 @@ while getopts "d:s:t:l:e:m:p:0:1:2:3:4:" opts; do ;; p) web_port=${OPTARG} ;; - 0) mlz_saca_subid=${OPTARG} - subs+=("${OPTARG}") - ;; - 1) mlz_tier0_subid=${OPTARG} - subs+=("${OPTARG}") - ;; - 2) mlz_tier1_subid=${OPTARG} - subs+=("${OPTARG}") - ;; - 3) mlz_tier2_subid=${OPTARG} - subs+=("${OPTARG}") - ;; ?) echo "Invalid option: -${OPTARG}." exit 2 @@ -96,17 +84,13 @@ echo "INFO: creating a mlz.config file based on user input at $(realpath "$mlz_c "$mlz_env_name" \ "$mlz_config_location" \ "$mlz_config_subid" \ - "$mlz_tenantid" \ - "$mlz_saca_subid" \ - "$mlz_tier0_subid" \ - "$mlz_tier1_subid" \ - "$mlz_tier2_subid" + "$mlz_tenantid" # generate MLZ configuration names . "${this_script_path}/config/generate_names.sh" "$mlz_config_file" echo "INFO: setting up required MLZ resources using $(realpath "$mlz_config_file")..." -"${this_script_path}/mlz_tf_setup.sh" "$mlz_config_file" +"${this_script_path}/config/mlz_config_create.sh" "$mlz_config_file" echo "INFO: setting current az cli subscription to ${mlz_config_subid}..." az account set --subscription "${mlz_config_subid}" From 95cff9978f442e23fecf8ecc83fbed1ab268b2d9 Mon Sep 17 00:00:00 2001 From: Glenn Musa Date: Fri, 2 Apr 2021 08:11:34 -0400 Subject: [PATCH 07/31] paths for conatiner-registry --- src/scripts/container-registry/add_auth_scopes.sh | 2 +- src/scripts/container-registry/create_acr.sh | 2 +- src/scripts/container-registry/deploy_instance.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/scripts/container-registry/add_auth_scopes.sh b/src/scripts/container-registry/add_auth_scopes.sh index 4d95a4557..fe77720a7 100755 --- a/src/scripts/container-registry/add_auth_scopes.sh +++ b/src/scripts/container-registry/add_auth_scopes.sh @@ -29,7 +29,7 @@ mlz_config_file=$1 fqdn=$2 # generate MLZ configuration names -. "$(dirname "$(realpath "${BASH_SOURCE%/*}")")/generate_names.sh" "$mlz_config_file" +. "$(dirname "$(realpath "${BASH_SOURCE%/*}")")/config/generate_names.sh" "$mlz_config_file" # path to app resources definition file required_resources_json_file="$(dirname "$(realpath "${BASH_SOURCE%/*}")")/config/mlz_login_app_resources.json" diff --git a/src/scripts/container-registry/create_acr.sh b/src/scripts/container-registry/create_acr.sh index f26a45dae..e29b385b3 100755 --- a/src/scripts/container-registry/create_acr.sh +++ b/src/scripts/container-registry/create_acr.sh @@ -28,7 +28,7 @@ fi mlz_config_file=$1 # generate MLZ configuration names -. "$(dirname "$(realpath "${BASH_SOURCE%/*}")")/generate_names.sh" "$mlz_config_file" +. "$(dirname "$(realpath "${BASH_SOURCE%/*}")")/config/generate_names.sh" "$mlz_config_file" echo "INFO: creating Azure Container Registry ${mlz_acr_name}..." az acr create \ diff --git a/src/scripts/container-registry/deploy_instance.sh b/src/scripts/container-registry/deploy_instance.sh index 832515712..6828e81e7 100755 --- a/src/scripts/container-registry/deploy_instance.sh +++ b/src/scripts/container-registry/deploy_instance.sh @@ -30,7 +30,7 @@ image_name=$2 image_tag=$3 # generate MLZ configuration names -. "$(dirname "$(realpath "${BASH_SOURCE%/*}")")/generate_names.sh" "$mlz_config_file" +. "$(dirname "$(realpath "${BASH_SOURCE%/*}")")/config/generate_names.sh" "$mlz_config_file" acr_login_server=$(az acr show \ --name "${mlz_acr_name}" \ From 082c9789b5bd27bd65bfe4cb90596874d533eb19 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Fri, 2 Apr 2021 14:04:06 -0400 Subject: [PATCH 08/31] optional args on setup_ezdeploy --- src/core/globals.front.json | 8 +- src/core/mlz_tf_cfg.var.sample | 2 +- src/docs/ui-deployment.md | 22 +++- src/front/main.py | 24 ++++ src/mlz.config.sample | 2 +- src/scripts/config/generate_config_file.sh | 100 ++++++++++++---- .../container-registry/add_auth_scopes.sh | 3 +- src/scripts/container-registry/create_acr.sh | 3 +- .../container-registry/deploy_instance.sh | 3 +- src/scripts/setup_ezdeploy.sh | 108 +++++++++++------- 10 files changed, 199 insertions(+), 76 deletions(-) diff --git a/src/core/globals.front.json b/src/core/globals.front.json index 207aea159..482574598 100644 --- a/src/core/globals.front.json +++ b/src/core/globals.front.json @@ -5,7 +5,7 @@ "varname": "tf_environment", "type": "text", "default_val": "env:TF_ENV", - "description": "Terraform deployment Environment https://www.terraform.io/docs/language/settings/backends/azurerm.html#environment", + "description": "Terraform azurerm environment (e.g. 'public') see: https://www.terraform.io/docs/language/settings/backends/azurerm.html#environment", "options": [] }, { @@ -19,21 +19,21 @@ "varname": "mlz_tenantid", "type": "text", "default_val": "env:TENANT_ID", - "description": "Tenant ID where your subscriptions liv", + "description": "Tenant ID where your subscriptions live", "options": [] }, { "varname": "mlz_metadatahost", "type": "text", "default_val": "management.azure.com", - "description": "Host for azure metadata: e.g 'management.azure.com' or 'management.usgovcloudapi.net'", + "description": "Azure Metadata Service endpoint. (e.g 'management.azure.com' or 'management.usgovcloudapi.net')", "options": [] }, { "varname": "mlz_location", "type": "text", "default_val": "env:MLZ_LOCATION", - "description": "The location that you're deploying to.", + "description": "The location that you're deploying to (e.g. 'eastus')", "options": [] } ] diff --git a/src/core/mlz_tf_cfg.var.sample b/src/core/mlz_tf_cfg.var.sample index 76d403fdc..9092fb5e7 100644 --- a/src/core/mlz_tf_cfg.var.sample +++ b/src/core/mlz_tf_cfg.var.sample @@ -2,7 +2,7 @@ # Licensed under the MIT License. tf_environment="{TF_ENVIRONMENT}" # https://www.terraform.io/docs/language/settings/backends/azurerm.html#environment mlz_env_name="{MLZ_ENV_NAME}" # Unique name for MLZ environment -mlz_config_subid="{MLZ_CONFIG_SUBID}" # Subscription ID for Key Vault storing Service Principal creds +mlz_config_subid="{MLZ_CONFIG_SUBID}" # Subscription ID for MissionLZ configuration resources mlz_config_location="{MLZ_CONFIG_LOCATION}" # Azure Region for deploying Mission LZ configuration resources mlz_tenantid="{MLZ_TENANTID}" mlz_tier0_subid="{MLZ_TIER0_SUBID}" diff --git a/src/docs/ui-deployment.md b/src/docs/ui-deployment.md index e9c3ef3ef..04f234da3 100644 --- a/src/docs/ui-deployment.md +++ b/src/docs/ui-deployment.md @@ -24,11 +24,25 @@ To get started, you'll need to be running from a bash/zsh environment. If you ar This process will build the user interface container image on your workstation using Docker, upload the container image to your Azure subscription, and install an instance of the container in Azure Container Instances (ACI). You'll need to have Docker installed locally, as well as the Azure Bash CLI. -From the "src" directory - ```BASH -chmod u+x ./scripts/setup_ezdeploy.sh -./script/setup_ezdeploy.sh -d build -s -t -l -e -m -p port -0 -1 -2 -3 " +cd src/scripts +./setup_ezdeploy.sh -s -t +``` + +`setup_ezdeploy.sh` has more configurable options, but these are the minimum required to deploy a running UI that will help you make a full MLZ deployment. + +Here's the full list of parameters for reference: + +```plaintext +setup_ezdeploy.sh: Setup the front end for MLZ + argument description + --docker-strategy -d [local|build|load] 'local' for localhost, 'build' to build from this repo, or 'load' to unzip an image + --subscription-id -s Subscription ID for MissionLZ resources + --tenant-id -t Tenant ID where your subscriptions live + --location -l The location that you're deploying to (defaults to 'eastus') + --tf-environment -e Terraform azurerm environment (defaults to 'public') see: https://www.terraform.io/docs/language/settings/backends/azurerm.html#environment + --mlz-env-name -z Unique name for MLZ environment (defaults to 'mlz' + UNIX timestamp) + --port -p port to expose the front end web UI on (defaults to '80') ``` The final results will include a URI that you can use to access the front end running in a remote azure container instance. diff --git a/src/front/main.py b/src/front/main.py index 9f4f41b0e..491439ac6 100644 --- a/src/front/main.py +++ b/src/front/main.py @@ -323,6 +323,30 @@ async def process_input(request: Request): json.dump(doc, open(os.path.join(os.getcwd(), "config_output", os.path.basename(f_name)), "w+")) # Use what we know and write out the environment file: + # src_dir=os.path.dirname(os.getcwd()) + # mlz_config_path = os.path.join(src_dir, "mlz.config") + + # write_config_executable = os.path.join(src_dir, "scripts", "config", "generate_config_file.sh") + # os.chmod(write_config_executable, 0o755) + + # write_config_command = "{} {} {} {} {} {} {} {}".format( + # write_config_executable, + # '--file ' + mlz_config_path, + # '--tf-env public', + # '--metadatahost metadata', + # '--mlz-env glenn', + # '--location eastus', + # '--config-sub-id configsubid', + # '--tenant-id tenantid',) + + # # optionals + # write_config_command+=" -h hubid" + # write_config_command+=" -0 t0id" + # write_config_command+=" -1 t1id" + # write_config_command+=" -2 t2id" + + # subprocess.check_call(write_config_command, shell=True) + with open(os.path.join(os.getcwd(), "config_output", "mlz_tf_var_front"), "w+") as f: f.writelines("tf_environment=\"" + os.getenv("TF_ENV") + "\"\n" + "mlz_env_name=\"" + os.getenv("MLZ_ENV") + "\"\n" + diff --git a/src/mlz.config.sample b/src/mlz.config.sample index a82a65656..3e1dc979f 100644 --- a/src/mlz.config.sample +++ b/src/mlz.config.sample @@ -2,7 +2,7 @@ # Licensed under the MIT License. tf_environment="{TF_ENVIRONMENT}" # https://www.terraform.io/docs/language/settings/backends/azurerm.html#environment mlz_env_name="{MLZ_ENV_NAME}" # Unique name for MLZ environment -mlz_config_subid="{MLZ_CONFIG_SUBID}" # Subscription ID for Key Vault storing Service Principal creds +mlz_config_subid="{MLZ_CONFIG_SUBID}" # Subscription ID for MissionLZ configuration resources mlz_config_location="{MLZ_CONFIG_LOCATION}" # Azure Region for deploying Mission LZ configuration resources mlz_tenantid="{MLZ_TENANTID}" mlz_saca_subid="{MLZ_SACA_SUBID}" diff --git a/src/scripts/config/generate_config_file.sh b/src/scripts/config/generate_config_file.sh index 802e845eb..264a72b8b 100755 --- a/src/scripts/config/generate_config_file.sh +++ b/src/scripts/config/generate_config_file.sh @@ -3,7 +3,7 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # -# Generate a file named mlz.config given MLZ prerequisites. +# Generate a configuration file for MLZ prerequisites and optional SACA and T0-T2 subscriptions. set -e @@ -11,31 +11,91 @@ error_log() { echo "${1}" 1>&2; } +show_help() { + print_formatted() { + long_name=$1 + char_name=$2 + desc=$3 + printf "%15s %2s %s \n" "$long_name" "$char_name" "$desc" + } + print_formatted "argument" "" "description" + print_formatted "--file" "-f" "the destination file path and name (e.g. 'src/mlz.config')" + print_formatted "--tf-env" "-e" "Terraform azurerm environment (e.g. 'public') see: https://www.terraform.io/docs/language/settings/backends/azurerm.html#environment" + print_formatted "--metadatahost" "-m" "Azure Metadata Service endpoint. (e.g 'management.azure.com' or 'management.usgovcloudapi.net')" + print_formatted "--mlz-env-name" "-z" "Unique name for MLZ environment" + print_formatted "--location" "-l" "The location that you're deploying to (e.g. 'eastus')" + print_formatted "--config-sub-id" "-s" "Subscription ID for MissionLZ configuration resources" + print_formatted "--tenant-id" "-t" "Tenant ID where your subscriptions live" + print_formatted "--hub-sub-id" "-h" "[OPTIONAL]: subscription ID for the hub network and resources" + print_formatted "--tier0-sub-id" "-0" "[OPTIONAL]: subscription ID for tier 0 network and resources" + print_formatted "--tier1-sub-id" "-1" "[OPTIONAL]: subscription ID for tier 1 network and resources" + print_formatted "--tier2-sub-id" "-2" "[OPTIONAL]: subscription ID for tier 2 network and resources" +} + usage() { - echo "generate_config_file.sh: Generate a file at the root named mlz.config given MLZ prerequisites" - error_log "usage: generate_config_file.sh " + echo "generate_config_file.sh: Generate a configuration file for MLZ prerequisites and optional SACA and T0-T2 subscriptions" + show_help } -if [[ "$#" -lt 7 ]]; then - usage - exit 1 -fi +# stage required parameters as not set +dest_file="notset" +tf_environment="notset" +metadatahost="notset" +mlz_env_name="notset" +mlz_config_location="notset" +mlz_config_subid="notset" +mlz_tenant_id="notset" + +# inspect arguments +while [ $# -gt 0 ] ; do + case $1 in + -f | --file) dest_file="$2" ;; + -e | --tf-env) tf_environment="$2" ;; + -m | --metadatahost) metadatahost="$2" ;; + -z | --mlz-env-name) mlz_env_name="$2" ;; + -l | --location) mlz_config_location="$2" ;; + -s | --config-sub-id) mlz_config_subid="$2" ;; + -t | --tenant-id) mlz_tenant_id="$2" ;; + -h | --hub-sub-id) mlz_saca_subid="$2" ;; + -0 | --tier0-sub-id) mlz_tier0_subid="$2" ;; + -1 | --tier1-sub-id) mlz_tier1_subid="$2" ;; + -2 | --tier2-sub-id) mlz_tier2_subid="$2" ;; + esac + shift +done -dest_file=${1} -tf_env=${2} -metadatahost=${3} -env_name=${4} -location=${5} -config_subid=${6} -tenantid=${7} +# check mandatory parameters +for i in { $dest_file $tf_environment $metadatahost $mlz_env_name $mlz_config_location $mlz_config_subid $mlz_tenant_id } +do + if [[ $i == "notset" ]]; then + error_log "ERROR: Missing required arguments. These arguments are mandatory: -f, -e, -m, -z, -l, -s, -t" + usage + exit 1 + fi +done +# write the file to the desired path rm -f "$dest_file" touch "$dest_file" { - echo "tf_environment=${tf_env}" - echo "mlz_metadatahost=${metadatahost}" - echo "mlz_env_name=${env_name}" - echo "mlz_config_location=${location}" - echo "mlz_config_subid=${config_subid}" - echo "mlz_tenantid=${tenantid}" + echo "tf_environment=${tf_environment}" + echo "mlz_metadatahost=${metadatahost}" + echo "mlz_env_name=${mlz_env_name}" + echo "mlz_config_location=${mlz_config_location}" + echo "mlz_config_subid=${mlz_config_subid}" + echo "mlz_tenantid=${mlz_tenant_id}" } >> "$dest_file" + +# for any optional parameters, check if they're set before appending them to the file +append_optional_args() { + key_name=$1 + key_value=$2 + file_to_append=$3 + if [[ $key_value ]]; then + printf "${key_name}=${key_value}\n" >> "${file_to_append}" + fi +} +append_optional_args "mlz_saca_subid" "${mlz_saca_subid}" "${dest_file}" +append_optional_args "mlz_tier0_subid" "${mlz_tier0_subid}" "${dest_file}" +append_optional_args "mlz_tier1_subid" "${mlz_tier1_subid}" "${dest_file}" +append_optional_args "mlz_tier2_subid" "${mlz_tier2_subid}" "${dest_file}" \ No newline at end of file diff --git a/src/scripts/container-registry/add_auth_scopes.sh b/src/scripts/container-registry/add_auth_scopes.sh index 4d95a4557..fc08d761a 100755 --- a/src/scripts/container-registry/add_auth_scopes.sh +++ b/src/scripts/container-registry/add_auth_scopes.sh @@ -29,7 +29,8 @@ mlz_config_file=$1 fqdn=$2 # generate MLZ configuration names -. "$(dirname "$(realpath "${BASH_SOURCE%/*}")")/generate_names.sh" "$mlz_config_file" +. "$mlz_config_file" +. "$(dirname "$(realpath "${BASH_SOURCE%/*}")")/config/generate_names.sh" "$mlz_config_file" # path to app resources definition file required_resources_json_file="$(dirname "$(realpath "${BASH_SOURCE%/*}")")/config/mlz_login_app_resources.json" diff --git a/src/scripts/container-registry/create_acr.sh b/src/scripts/container-registry/create_acr.sh index f26a45dae..69fa0b819 100755 --- a/src/scripts/container-registry/create_acr.sh +++ b/src/scripts/container-registry/create_acr.sh @@ -28,7 +28,8 @@ fi mlz_config_file=$1 # generate MLZ configuration names -. "$(dirname "$(realpath "${BASH_SOURCE%/*}")")/generate_names.sh" "$mlz_config_file" +. "$mlz_config_file" +. "$(dirname "$(realpath "${BASH_SOURCE%/*}")")/config/generate_names.sh" "$mlz_config_file" echo "INFO: creating Azure Container Registry ${mlz_acr_name}..." az acr create \ diff --git a/src/scripts/container-registry/deploy_instance.sh b/src/scripts/container-registry/deploy_instance.sh index 832515712..d685b09d5 100755 --- a/src/scripts/container-registry/deploy_instance.sh +++ b/src/scripts/container-registry/deploy_instance.sh @@ -30,7 +30,8 @@ image_name=$2 image_tag=$3 # generate MLZ configuration names -. "$(dirname "$(realpath "${BASH_SOURCE%/*}")")/generate_names.sh" "$mlz_config_file" +. "$mlz_config_file" +. "$(dirname "$(realpath "${BASH_SOURCE%/*}")")/config/generate_names.sh" "$mlz_config_file" acr_login_server=$(az acr show \ --name "${mlz_acr_name}" \ diff --git a/src/scripts/setup_ezdeploy.sh b/src/scripts/setup_ezdeploy.sh index fca176c1e..1a432d85e 100755 --- a/src/scripts/setup_ezdeploy.sh +++ b/src/scripts/setup_ezdeploy.sh @@ -16,46 +16,65 @@ error_log() { echo "${1}" 1>&2; } +show_help() { + print_formatted() { + long_name=$1 + char_name=$2 + desc=$3 + printf "%20s %2s %s \n" "$long_name" "$char_name" "$desc" + } + print_formatted "argument" "" "description" + print_formatted "--docker-strategy" "-d" "[local|build|load] 'local' for localhost, 'build' to build from this repo, or 'load' to unzip an image (defaults to 'build')" + print_formatted "--subscription-id" "-s" "Subscription ID for MissionLZ resources" + print_formatted "--tenant-id" "-t" "Tenant ID where your subscriptions live" + print_formatted "--location" "-l" "The location that you're deploying to (defaults to 'eastus')" + print_formatted "--tf-environment" "-e" "Terraform azurerm environment (defaults to 'public') see: https://www.terraform.io/docs/language/settings/backends/azurerm.html#environment" + print_formatted "--mlz-env-name" "-z" "Unique name for MLZ environment (defaults to 'mlz' + UNIX timestamp)" + print_formatted "--port" "-p" "port to expose the front end web UI on (defaults to '80')" +} + usage() { - echo "setup_ezdeploy.sh: Setup the Front End for MLZ" - error_log "usage: setup_ezdeploy.sh -d -s -t -l -e -m -p -0 -1 -2 -3 " + echo "setup_ezdeploy.sh: Setup the front end for MLZ" + show_help } -if [[ "$#" -lt 8 ]]; then - usage - exit 1 -fi +timestamp=$(date +%s) metadata_host="management.azure.com" # TODO (20210401): pass this by parameter or derive from cloud acr_endpoint="azurecr.io" # TODO (20210401): pass this by parameter or derive from cloud -tf_environment=public -mlz_env_name=mlzdeployment -web_port=80 -subs=() - -while getopts "d:s:t:l:e:m:p:0:1:2:3:4:" opts; do - case "${opts}" in - d) docker_strategy=${OPTARG} - ;; - s) mlz_config_subid=${OPTARG} - subs+=("${OPTARG}") - ;; - t) mlz_tenantid=${OPTARG} - ;; - l) mlz_config_location=${OPTARG} - ;; - e) tf_environment=${OPTARG} - ;; - m) mlz_env_name=${OPTARG} - ;; - p) web_port=${OPTARG} - ;; - ?) - echo "Invalid option: -${OPTARG}." - exit 2 - ;; +# set helpful defaults that can be overriden +# or 'notset' to for mandatory input +docker_strategy="build" +mlz_config_subid="notset" +mlz_tenantid="notset" +mlz_config_location="eastus" +tf_environment="public" +mlz_env_name="mlz${timestamp}" +web_port="80" + +# inspect user input +while [ $# -gt 0 ] ; do + case $1 in + -d | --docker-strategy) docker_strategy="$2" ;; + -s | --subscription-id) mlz_config_subid="$2" ;; + -t | --tenant-id) mlz_tenantid="$2" ;; + -l | --location) mlz_config_location="$2" ;; + -e | --tf-environment) tf_environment="$2" ;; + -z | --mlz-env-name) mlz_env_name="$2" ;; + -p | --port) web_port="$2" ;; esac + shift +done + +# check mandatory parameters +for i in { $docker_strategy $mlz_config_subid $mlz_tenantid $mlz_config_location $tf_environment $mlz_env_name $web_port } +do + if [[ $i == "notset" ]]; then + error_log "ERROR: Missing required arguments. These arguments are mandatory: -d, -s, -t, -l, -e, -z, -p" + usage + exit 1 + fi done this_script_path=$(realpath "${BASH_SOURCE%/*}") @@ -78,30 +97,33 @@ fi mlz_config_file="${src_path}/mlz.config" echo "INFO: creating a mlz.config file based on user input at $(realpath "$mlz_config_file")..." "${this_script_path}/config/generate_config_file.sh" \ - "$mlz_config_file" \ - "$tf_environment" \ - "$metadata_host" \ - "$mlz_env_name" \ - "$mlz_config_location" \ - "$mlz_config_subid" \ - "$mlz_tenantid" + -f "$mlz_config_file" \ + -e "$tf_environment" \ + -m "$metadata_host" \ + -z "$mlz_env_name" \ + -l "$mlz_config_location" \ + -s "$mlz_config_subid" \ + -t "$mlz_tenantid" # generate MLZ configuration names . "${this_script_path}/config/generate_names.sh" "$mlz_config_file" +# create MLZ required resources echo "INFO: setting up required MLZ resources using $(realpath "$mlz_config_file")..." "${this_script_path}/config/mlz_config_create.sh" "$mlz_config_file" +# switch to the MLZ subscription echo "INFO: setting current az cli subscription to ${mlz_config_subid}..." az account set --subscription "${mlz_config_subid}" +# if local, call setup_ezdeploy_local if [[ $docker_strategy == "local" ]]; then local_fqdn="localhost:${web_port}" "${this_script_path}/setup_ezdeploy_local.sh" "$mlz_config_file" "$local_fqdn" exit 0 fi -# create container registry +# otherwise, create container registry "${container_registry_path}/create_acr.sh" "$mlz_config_file" # build/load, tag, and push image @@ -120,17 +142,17 @@ fi docker tag "${image_name}${image_tag}" "${mlz_acr_name}.${acr_endpoint}/${image_name}${image_tag}" docker push "${mlz_acr_name}.${acr_endpoint}/${image_name}${image_tag}" -# deploy instance +# deploy an instance "${container_registry_path}/deploy_instance.sh" "$mlz_config_file" "$image_name" "$image_tag" -# get URL +# get the URL for the instance container_fqdn=$(az container show \ --resource-group "${mlz_rg_name}"\ --name "${mlz_instance_name}" \ --query ipAddress.fqdn \ --output tsv) -# create an app registration and add auth scopes to facilitate MSAL login +# create an app registration and add auth scopes to facilitate MSAL login for the instance "${container_registry_path}/add_auth_scopes.sh" "$mlz_config_file" "$container_fqdn" echo "INFO: Complete! You can access the front end at http://$container_fqdn" From a1a8e427177ef3920ba1387766060578251e36b2 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Fri, 2 Apr 2021 14:23:49 -0400 Subject: [PATCH 09/31] incorrect number of args --- src/scripts/container-registry/add_auth_scopes.sh | 2 +- src/scripts/container-registry/deploy_instance.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scripts/container-registry/add_auth_scopes.sh b/src/scripts/container-registry/add_auth_scopes.sh index fc08d761a..983e33243 100755 --- a/src/scripts/container-registry/add_auth_scopes.sh +++ b/src/scripts/container-registry/add_auth_scopes.sh @@ -20,7 +20,7 @@ usage() { error_log "usage: add_auth_scopes.sh " } -if [[ "$#" -lt 3 ]]; then +if [[ "$#" -lt 2 ]]; then usage exit 1 fi diff --git a/src/scripts/container-registry/deploy_instance.sh b/src/scripts/container-registry/deploy_instance.sh index d685b09d5..f09e277cb 100755 --- a/src/scripts/container-registry/deploy_instance.sh +++ b/src/scripts/container-registry/deploy_instance.sh @@ -54,7 +54,7 @@ registry_password=$(az keyvault secret show \ --output tsv) az container create \ - --resource-group "${mlz_rg_name}"\ + --resource-group "${mlz_rg_name}" \ --name "${mlz_instance_name}" \ --image "${acr_login_server}/${image_name}:${image_tag}" \ --dns-name-label "${mlz_dns_name}" \ From 52ed68514c60d7316a5eb620c1739f0d956916ac Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Fri, 2 Apr 2021 14:27:54 -0400 Subject: [PATCH 10/31] line endings --- src/scripts/container-registry/add_auth_scopes.sh | 2 +- src/scripts/setup_ezdeploy_local.sh | 2 +- src/scripts/util/checkfordocker.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/scripts/container-registry/add_auth_scopes.sh b/src/scripts/container-registry/add_auth_scopes.sh index 983e33243..037894814 100755 --- a/src/scripts/container-registry/add_auth_scopes.sh +++ b/src/scripts/container-registry/add_auth_scopes.sh @@ -67,4 +67,4 @@ az keyvault secret set \ --output none echo "INFO: waiting thirty seconds to propagate app registration..." -sleep 30 \ No newline at end of file +sleep 30 diff --git a/src/scripts/setup_ezdeploy_local.sh b/src/scripts/setup_ezdeploy_local.sh index 6ba618b67..c75fed2c5 100644 --- a/src/scripts/setup_ezdeploy_local.sh +++ b/src/scripts/setup_ezdeploy_local.sh @@ -79,4 +79,4 @@ echo "\$env:TF_ENV='$tf_environment'" echo "\$env:MLZ_ENV='$mlz_env_name'" echo "\$env:MLZCLIENTID='$(az keyvault secret show --name "${mlz_sp_kv_name}" --vault-name "${mlz_kv_name}" --query value --output tsv)'" echo "\$env:MLZCLIENTSECRET='$(az keyvault secret show --name "${mlz_sp_kv_password}" --vault-name "${mlz_kv_name}" --query value --output tsv)'" -exit 0 \ No newline at end of file +exit 0 diff --git a/src/scripts/util/checkfordocker.sh b/src/scripts/util/checkfordocker.sh index a2934f923..f761f1114 100755 --- a/src/scripts/util/checkfordocker.sh +++ b/src/scripts/util/checkfordocker.sh @@ -10,4 +10,4 @@ if ! command -v docker &> /dev/null; then echo "docker could not be found. This script requires the docker CLI." echo "see https://docs.docker.com/engine/install/ for installation instructions." exit 1 -fi \ No newline at end of file +fi From 1d4e8865cb1839da213c744baeab31970f67a5d3 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Fri, 2 Apr 2021 14:32:37 -0400 Subject: [PATCH 11/31] line endings --- src/scripts/config/generate_config_file.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/config/generate_config_file.sh b/src/scripts/config/generate_config_file.sh index 264a72b8b..6817f1668 100755 --- a/src/scripts/config/generate_config_file.sh +++ b/src/scripts/config/generate_config_file.sh @@ -98,4 +98,4 @@ append_optional_args() { append_optional_args "mlz_saca_subid" "${mlz_saca_subid}" "${dest_file}" append_optional_args "mlz_tier0_subid" "${mlz_tier0_subid}" "${dest_file}" append_optional_args "mlz_tier1_subid" "${mlz_tier1_subid}" "${dest_file}" -append_optional_args "mlz_tier2_subid" "${mlz_tier2_subid}" "${dest_file}" \ No newline at end of file +append_optional_args "mlz_tier2_subid" "${mlz_tier2_subid}" "${dest_file}" From ce07e8b37cfa64bf9b1701e0f2e89ead7ef5c06e Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Fri, 2 Apr 2021 14:36:20 -0400 Subject: [PATCH 12/31] suppress keyvault output --- src/scripts/container-registry/deploy_instance.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/scripts/container-registry/deploy_instance.sh b/src/scripts/container-registry/deploy_instance.sh index f09e277cb..594b07744 100755 --- a/src/scripts/container-registry/deploy_instance.sh +++ b/src/scripts/container-registry/deploy_instance.sh @@ -78,4 +78,6 @@ az keyvault set-policy \ --name "${mlz_kv_name}" \ --key-permissions get list \ --secret-permissions get list \ - --object-id "${container_obj_id}" + --object-id "${container_obj_id}" \ + --only-show-errors \ + --output none From 491d8b4e44f74ef3ffba31b9965a7a5cc8bf842d Mon Sep 17 00:00:00 2001 From: Brooke Hamilton Date: Fri, 2 Apr 2021 14:45:25 -0400 Subject: [PATCH 13/31] readme linting --- .devcontainer/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/README.md b/.devcontainer/README.md index 4bc8b2251..75f6cac4b 100644 --- a/.devcontainer/README.md +++ b/.devcontainer/README.md @@ -12,7 +12,7 @@ All configuration related to the development container is in the `.devcontainer` ### Setup - Install Docker Desktop or Docker CE on a host machine. The host machine can be Windows, Linux, or Mac, and can run on-premises or in the cloud. -- Recommended: If you are using Windows for the host machine, clone and open this repository on Windows Subsystem for Linux (WSL). WSL is not required, but disk IO performance in the container is better and the overall experience is more consistent when running a development container from WSL. +- Recommended: If you are using Windows for the host machine, clone and open this repository on Windows Subsystem for Linux (WSL). WSL is not required, but disk IO performance in the container is better and the overall experience is more consistent when running a development container from WSL. > NOTE: the Windows Git Credential Manager can be configured to work from WSL. See the [documentation here](https://docs.microsoft.com/en-us/windows/wsl/tutorials/wsl-git#git-credential-manager-setup). Below is the command to run for setting the Windows credential manager in WSL: From e0a690a19047e065c697e189f13850538af3913e Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Fri, 2 Apr 2021 14:47:13 -0400 Subject: [PATCH 14/31] get valid value for client secret --- src/scripts/container-registry/add_auth_scopes.sh | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/scripts/container-registry/add_auth_scopes.sh b/src/scripts/container-registry/add_auth_scopes.sh index 037894814..fb1f1ed1b 100755 --- a/src/scripts/container-registry/add_auth_scopes.sh +++ b/src/scripts/container-registry/add_auth_scopes.sh @@ -29,8 +29,8 @@ mlz_config_file=$1 fqdn=$2 # generate MLZ configuration names -. "$mlz_config_file" -. "$(dirname "$(realpath "${BASH_SOURCE%/*}")")/config/generate_names.sh" "$mlz_config_file" +. "${mlz_config_file}" +. "$(dirname "$(realpath "${BASH_SOURCE%/*}")")/config/generate_names.sh" "${mlz_config_file}" # path to app resources definition file required_resources_json_file="$(dirname "$(realpath "${BASH_SOURCE%/*}")")/config/mlz_login_app_resources.json" @@ -39,13 +39,14 @@ required_resources_json_file="$(dirname "$(realpath "${BASH_SOURCE%/*}")")/confi echo "INFO: creating app registration ${mlz_fe_app_name} to facilitate user logon at ${fqdn}..." client_id=$(az ad app create \ --display-name "${mlz_fe_app_name}" \ - --reply-urls "http://$fqdn/redirect" \ + --reply-urls "http://${fqdn}/redirect" \ --required-resource-accesses "${required_resources_json_file}" \ --query appId \ --output tsv) client_password=$(az ad app credential reset \ - --id "$client_id" \ + --id ${client_id} \ --query password \ + --only-show-errors \ --output tsv) # update keyvault with the app registration information @@ -54,7 +55,7 @@ az keyvault secret set \ --name "${mlz_login_app_kv_name}" \ --subscription "${mlz_config_subid}" \ --vault-name "${mlz_kv_name}" \ - --value "$client_id" \ + --value "${client_id}" \ --only-show-errors \ --output none @@ -62,7 +63,7 @@ az keyvault secret set \ --name "${mlz_login_app_kv_password}" \ --subscription "${mlz_config_subid}" \ --vault-name "${mlz_kv_name}" \ - --value "$client_password" \ + --value "${client_password}" \ --only-show-errors \ --output none From 4e256edd75b412860165d2bd66da3e4f117548b8 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Fri, 2 Apr 2021 15:18:48 -0400 Subject: [PATCH 15/31] fix image tag sytnax and add better logging --- src/scripts/container-registry/add_auth_scopes.sh | 4 ++-- src/scripts/container-registry/create_acr.sh | 15 ++++++++++----- src/scripts/container-registry/deploy_instance.sh | 6 +++--- src/scripts/setup_ezdeploy.sh | 12 ++++++------ 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/scripts/container-registry/add_auth_scopes.sh b/src/scripts/container-registry/add_auth_scopes.sh index fb1f1ed1b..9c18347e4 100755 --- a/src/scripts/container-registry/add_auth_scopes.sh +++ b/src/scripts/container-registry/add_auth_scopes.sh @@ -50,7 +50,7 @@ client_password=$(az ad app credential reset \ --output tsv) # update keyvault with the app registration information -echo "INFO: storing app registration information for client ID ${client_id} at ${mlz_login_app_kv_name}..." +echo "INFO: storing app registration information for client ID ${client_id} in ${mlz_kv_name}..." az keyvault secret set \ --name "${mlz_login_app_kv_name}" \ --subscription "${mlz_config_subid}" \ @@ -67,5 +67,5 @@ az keyvault secret set \ --only-show-errors \ --output none -echo "INFO: waiting thirty seconds to propagate app registration..." +echo "INFO: waiting thirty seconds to allow for app registration propogation..." sleep 30 diff --git a/src/scripts/container-registry/create_acr.sh b/src/scripts/container-registry/create_acr.sh index 69fa0b819..664d8a5c4 100755 --- a/src/scripts/container-registry/create_acr.sh +++ b/src/scripts/container-registry/create_acr.sh @@ -28,8 +28,8 @@ fi mlz_config_file=$1 # generate MLZ configuration names -. "$mlz_config_file" -. "$(dirname "$(realpath "${BASH_SOURCE%/*}")")/config/generate_names.sh" "$mlz_config_file" +. "${mlz_config_file}" +. "$(dirname "$(realpath "${BASH_SOURCE%/*}")")/config/generate_names.sh" "${mlz_config_file}" echo "INFO: creating Azure Container Registry ${mlz_acr_name}..." az acr create \ @@ -39,7 +39,7 @@ az acr create \ --only-show-errors \ --output none -echo "INFO: enabling administration of ${mlz_acr_name}..." +echo "INFO: enabling administration of registry ${mlz_acr_name}..." sleep 60 az acr update \ --name "${mlz_acr_name}" \ @@ -47,7 +47,10 @@ az acr update \ --only-show-errors \ --output none -az acr login --name "${mlz_acr_name}" +az acr login \ + --name "${mlz_acr_name}" \ + --only-show-errors \ + --output none acr_id=$(az acr show \ --name "${mlz_acr_name}" \ @@ -58,9 +61,11 @@ client_id=$(az keyvault secret show \ --name "${mlz_sp_kv_name}" \ --vault-name "${mlz_kv_name}" \ --query value \ + --only-show-errors \ --output tsv) -echo "INFO: granting ${client_id} 'acrpull' on ${mlz_acr_name}" +echo "INFO: granting registry identity ${client_id} 'acrpull' on ${mlz_acr_name}..." + az role assignment create \ --assignee "${client_id}" \ --scope "${acr_id}" \ diff --git a/src/scripts/container-registry/deploy_instance.sh b/src/scripts/container-registry/deploy_instance.sh index 594b07744..67c1cb72d 100755 --- a/src/scripts/container-registry/deploy_instance.sh +++ b/src/scripts/container-registry/deploy_instance.sh @@ -30,8 +30,8 @@ image_name=$2 image_tag=$3 # generate MLZ configuration names -. "$mlz_config_file" -. "$(dirname "$(realpath "${BASH_SOURCE%/*}")")/config/generate_names.sh" "$mlz_config_file" +. "${mlz_config_file}" +. "$(dirname "$(realpath "${BASH_SOURCE%/*}")")/config/generate_names.sh" "${mlz_config_file}" acr_login_server=$(az acr show \ --name "${mlz_acr_name}" \ @@ -39,7 +39,7 @@ acr_login_server=$(az acr show \ --query "loginServer" \ --output tsv) -echo "INFO: creating instance ${mlz_instance_name} in ${mlz_acr_name}..." +echo "INFO: creating instance of ${image_name}:${image_tag} on ${mlz_instance_name} in ${mlz_acr_name}..." registry_username=$(az keyvault secret show \ --name "${mlz_sp_kv_name}" \ diff --git a/src/scripts/setup_ezdeploy.sh b/src/scripts/setup_ezdeploy.sh index 1a432d85e..9207bd46e 100755 --- a/src/scripts/setup_ezdeploy.sh +++ b/src/scripts/setup_ezdeploy.sh @@ -43,8 +43,8 @@ timestamp=$(date +%s) metadata_host="management.azure.com" # TODO (20210401): pass this by parameter or derive from cloud acr_endpoint="azurecr.io" # TODO (20210401): pass this by parameter or derive from cloud -# set helpful defaults that can be overriden -# or 'notset' to for mandatory input +# set helpful defaults that can be overridden +# or to 'notset' require mandatory input docker_strategy="build" mlz_config_subid="notset" mlz_tenantid="notset" @@ -128,7 +128,7 @@ fi # build/load, tag, and push image image_name="lzfront" -image_tag=":latest" +image_tag="latest" if [[ $docker_strategy == "build" ]]; then docker build -t "${image_name}" "${src_path}" @@ -139,8 +139,8 @@ if [[ $docker_strategy == "load" ]]; then docker load -i mlz.tar fi -docker tag "${image_name}${image_tag}" "${mlz_acr_name}.${acr_endpoint}/${image_name}${image_tag}" -docker push "${mlz_acr_name}.${acr_endpoint}/${image_name}${image_tag}" +docker tag "${image_name}:${image_tag}" "${mlz_acr_name}.${acr_endpoint}/${image_name}:${image_tag}" +docker push "${mlz_acr_name}.${acr_endpoint}/${image_name}:${image_tag}" # deploy an instance "${container_registry_path}/deploy_instance.sh" "$mlz_config_file" "$image_name" "$image_tag" @@ -155,4 +155,4 @@ container_fqdn=$(az container show \ # create an app registration and add auth scopes to facilitate MSAL login for the instance "${container_registry_path}/add_auth_scopes.sh" "$mlz_config_file" "$container_fqdn" -echo "INFO: Complete! You can access the front end at http://$container_fqdn" +echo "INFO: COMPLETE! You can access the front end at http://$container_fqdn" From 9d11dab5b0c07ec37fb9816c82972187e13427f7 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Mon, 5 Apr 2021 11:39:10 -0400 Subject: [PATCH 16/31] create backends from frontend --- src/build/front_wrapper.sh | 14 +++++ src/front/main.py | 107 +++++++++++++++++-------------------- 2 files changed, 63 insertions(+), 58 deletions(-) diff --git a/src/build/front_wrapper.sh b/src/build/front_wrapper.sh index 9df7996d7..c18870141 100755 --- a/src/build/front_wrapper.sh +++ b/src/build/front_wrapper.sh @@ -41,4 +41,18 @@ az login --service-principal \ --allow-no-subscriptions \ --output none +# Create config resources given a subscription ID and terraform configuration folder path +create_tf_config() { + . "${BASH_SOURCE%/*}/config/config_create.sh" "${mlz_tf_cfg}" "${1}" "${2}" +} + +# get core terraform modules path +core_path="$(dirname "$(realpath "${BASH_SOURCE%/*}")")/core" + +# create backends for terraform modules +create_tf_config "${mlz_saca_subid}" "${core_path}/saca-hub" +create_tf_config "${mlz_tier0_subid}" "${core_path}/tier-0" +create_tf_config "${mlz_tier1_subid}" "${core_path}/tier-1" +create_tf_config "${mlz_tier2_subid}" "${core_path}/tier-2" + . "${BASH_SOURCE%/*}/apply_tf.sh" "${1}" "${2}" "${3}" "${4}" "${5}" "${6}" "${7}" \ No newline at end of file diff --git a/src/front/main.py b/src/front/main.py index 491439ac6..b062d6210 100644 --- a/src/front/main.py +++ b/src/front/main.py @@ -322,55 +322,52 @@ async def process_input(request: Request): for f_name, doc in tf_json.items(): json.dump(doc, open(os.path.join(os.getcwd(), "config_output", os.path.basename(f_name)), "w+")) - # Use what we know and write out the environment file: - # src_dir=os.path.dirname(os.getcwd()) - # mlz_config_path = os.path.join(src_dir, "mlz.config") - - # write_config_executable = os.path.join(src_dir, "scripts", "config", "generate_config_file.sh") - # os.chmod(write_config_executable, 0o755) - - # write_config_command = "{} {} {} {} {} {} {} {}".format( - # write_config_executable, - # '--file ' + mlz_config_path, - # '--tf-env public', - # '--metadatahost metadata', - # '--mlz-env glenn', - # '--location eastus', - # '--config-sub-id configsubid', - # '--tenant-id tenantid',) - - # # optionals - # write_config_command+=" -h hubid" - # write_config_command+=" -0 t0id" - # write_config_command+=" -1 t1id" - # write_config_command+=" -2 t2id" - - # subprocess.check_call(write_config_command, shell=True) - - with open(os.path.join(os.getcwd(), "config_output", "mlz_tf_var_front"), "w+") as f: - f.writelines("tf_environment=\"" + os.getenv("TF_ENV") + "\"\n" + - "mlz_env_name=\"" + os.getenv("MLZ_ENV") + "\"\n" + - "mlz_config_subid=\"" + os.getenv("SUBSCRIPTION_ID") + "\"\n" + - "mlz_config_location=\"" + os.getenv("MLZ_LOCATION") + "\"\n" + - "mlz_tenantid=\"" + os.getenv("TENANT_ID") + "\"\n" + - "mlz_tier0_subid=\"" + form_values["tier0_subid"] + "\"\n" + - "mlz_tier1_subid=\"" + form_values["tier1_subid"] + "\"\n" + - "mlz_tier2_subid=\"" + form_values["tier2_subid"] + "\"\n" + - "mlz_saca_subid=\"" + form_values["saca_subid"] + "\"\n") - - # Call the build script - # Check that it's executable: - config_executable = os.path.join(os.getcwd(), "..", "scripts", "mlz_tf_setup.sh") - apply_executable = os.path.join(os.getcwd(), "..", "build", "front_wrapper.sh") - os.chmod(config_executable, 0o755) - os.chmod(apply_executable, 0o755) - mlz_config = os.path.join(os.getcwd(), "config_output", "mlz_tf_var_front") - global_config = os.path.join(os.getcwd(), "config_output", "globals.tfvars.json") - saca = os.path.join(os.getcwd(), "config_output", "saca-hub.tfvars.json") - tier0 = os.path.join(os.getcwd(), "config_output", "tier-0.tfvars.json") - tier1 = os.path.join(os.getcwd(), "config_output", "tier-1.tfvars.json") - tier2 = os.path.join(os.getcwd(), "config_output", "tier-2.tfvars.json") - + # write a command to write mlz.config: + src_dir = os.path.dirname(os.getcwd()) + generate_config_executable = os.path.join(src_dir, "scripts", "config", "generate_config_file.sh") + os.chmod(generate_config_executable, 0o755) + + mlz_config_path = os.path.join(src_dir, "mlz.config") + + generate_config_args = [] + generate_config_args.append('--file ' + mlz_config_path) + generate_config_args.append('--tf-env ' + os.getenv("TF_ENV")) + generate_config_args.append('--metadatahost management.azure.com') # TODO (20210401): pass this by parameter or derive from cloud + generate_config_args.append('--mlz-env ' + os.getenv("MLZ_ENV")) + generate_config_args.append('--location ' + os.getenv("MLZ_LOCATION")) + generate_config_args.append('--config-sub-id ' + os.getenv("SUBSCRIPTION_ID")) + generate_config_args.append('--tenant-id ' + os.getenv("TENANT_ID")) + generate_config_args.append('--hub-sub-id ' + form_values["saca_subid"]) + generate_config_args.append('--tier0-sub-id ' + form_values["tier0_subid"]) + generate_config_args.append('--tier1-sub-id ' + form_values["tier1_subid"]) + generate_config_args.append('--tier2-sub-id ' + form_values["tier2_subid"]) + + generate_config_command = "{} {}".format(generate_config_executable, ' '.join(generate_config_args)) + + # write a command to execute front_wrapper.sh: + wrapper_executable = os.path.join(os.getcwd(), "..", "build", "front_wrapper.sh") + os.chmod(wrapper_executable, 0o755) + + wrapper_command = "{} {} {} {} {} {} {} y {} {}".format( + wrapper_executable, + mlz_config_path, + global_vars, + saca_vars, + tier0_vars, + tier1_vars, + tier2_vars, + sp_id, + sp_pwd) + + # set terraform vars paths + config_output_dir = os.path.join(os.getcwd(), "config_output") + global_vars = os.path.join(config_output_dir, "globals.tfvars.json") + saca_vars = os.path.join(config_output_dir, "saca-hub.tfvars.json") + tier0_vars = os.path.join(config_output_dir, "tier-0.tfvars.json") + tier1_vars = os.path.join(config_output_dir, "tier-1.tfvars.json") + tier2_vars = os.path.join(config_output_dir, "tier-2.tfvars.json") + + # get service principal to execute terraform if keyVaultName: sp_id = secret_client.get_secret("serviceprincipal-clientid").value sp_pwd = secret_client.get_secret("serviceprincipal-pwd").value @@ -378,22 +375,16 @@ async def process_input(request: Request): sp_id = os.getenv("MLZCLIENTID", "NotSet") sp_pwd = os.getenv("MLZCLIENTSECRET", "NotSet") - config_str = "{} {} {}".format(config_executable, mlz_config, "bypass") - exec_str = "{} {} {} {} {} {} {} y {} {}".format( - apply_executable, mlz_config, global_config, saca, tier0, tier1, tier2, sp_id, sp_pwd) - with open(exec_output, "w+") as out: - creation = await asyncio.create_subprocess_exec(*config_str.split(), stderr=out, stdout=out) + generate_mlz_config = await asyncio.create_subprocess_exec(*write_config_command.split(), stderr=out, stdout=out) # This capture is setting to a dead object. If we want to do work with the process in the future # we have to do it here. - await creation.wait() - _ = await asyncio.create_subprocess_exec(*exec_str.split(), stderr=out, stdout=out) + await generate_mlz_config.wait() + _ = await asyncio.create_subprocess_exec(*wrapper_command.split(), stderr=out, stdout=out) return JSONResponse(content={"status": "success"}, status_code=200) - - # Execute a poll for the contents of a specific job, logs from terraform execution will be stored as text with # a job key ast he file name? @app.get("/poll") From 6cfd25a58c70532ba25b7db313cd78c5e5937d21 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Mon, 5 Apr 2021 12:47:16 -0400 Subject: [PATCH 17/31] create tf state from frontend --- src/build/front_wrapper.sh | 17 ++++++------ src/core/saca-hub/saca-hub.front.json | 20 +++++++------- src/core/tier-0/tier-0.front.json | 10 +++---- src/core/tier-1/tier-1.front.json | 10 +++---- src/core/tier-2/tier-2.front.json | 10 +++---- src/docs/ui-deployment.md | 31 +++++++--------------- src/front/main.py | 38 +++++++++++++-------------- src/scripts/setup_ezdeploy_local.sh | 6 ++--- 8 files changed, 65 insertions(+), 77 deletions(-) mode change 100644 => 100755 src/scripts/setup_ezdeploy_local.sh diff --git a/src/build/front_wrapper.sh b/src/build/front_wrapper.sh index c18870141..ad3c4ada9 100755 --- a/src/build/front_wrapper.sh +++ b/src/build/front_wrapper.sh @@ -41,18 +41,17 @@ az login --service-principal \ --allow-no-subscriptions \ --output none +src_dir=$(dirname "$(realpath "${BASH_SOURCE%/*}")") + # Create config resources given a subscription ID and terraform configuration folder path create_tf_config() { - . "${BASH_SOURCE%/*}/config/config_create.sh" "${mlz_tf_cfg}" "${1}" "${2}" + . "${src_dir}/scripts/config/config_create.sh" "${mlz_config}" "${1}" "${2}" } -# get core terraform modules path -core_path="$(dirname "$(realpath "${BASH_SOURCE%/*}")")/core" - # create backends for terraform modules -create_tf_config "${mlz_saca_subid}" "${core_path}/saca-hub" -create_tf_config "${mlz_tier0_subid}" "${core_path}/tier-0" -create_tf_config "${mlz_tier1_subid}" "${core_path}/tier-1" -create_tf_config "${mlz_tier2_subid}" "${core_path}/tier-2" +create_tf_config "${mlz_saca_subid}" "${src_dir}/core/saca-hub" +create_tf_config "${mlz_tier0_subid}" "${src_dir}/core/tier-0" +create_tf_config "${mlz_tier1_subid}" "${src_dir}/core/tier-1" +create_tf_config "${mlz_tier2_subid}" "${src_dir}/core/tier-2" -. "${BASH_SOURCE%/*}/apply_tf.sh" "${1}" "${2}" "${3}" "${4}" "${5}" "${6}" "${7}" \ No newline at end of file +. "${BASH_SOURCE%/*}/apply_tf.sh" "${1}" "${2}" "${3}" "${4}" "${5}" "${6}" "${7}" \ No newline at end of file diff --git a/src/core/saca-hub/saca-hub.front.json b/src/core/saca-hub/saca-hub.front.json index fda365706..247b36f65 100644 --- a/src/core/saca-hub/saca-hub.front.json +++ b/src/core/saca-hub/saca-hub.front.json @@ -4,7 +4,7 @@ { "varname": "deploymentname", "type": "text", - "default_val": "mlzci", + "default_val": "mlz", "description": "A unique name for your terraform deployment", "options": [] }, @@ -18,21 +18,21 @@ { "varname": "saca_rgname", "type": "text", - "default_val": "rg-eastus-mlz-sacaci", + "default_val": "rg-eastus-mlz-saca", "description": "Resource group name", "options": [] }, { "varname": "saca_vnetname", "type": "text", - "default_val": "vn-eastus-mlz-sacaci", + "default_val": "vn-eastus-mlz-saca", "description": "Virtual Network Name", "options": [] }, { "varname": "saca_lawsname", "type": "text", - "default_val": "laws-eastus-mlz-sacaci", + "default_val": "laws-eastus-mlz-saca", "description": "Name for log analytic workspace", "options": [] }, @@ -48,42 +48,42 @@ { "varname": "tier0_rgname", "type": "text", - "default_val": "rg-eastus-mlz-t0ci", + "default_val": "rg-eastus-mlz-t0", "description": "Tier 0 resource group name", "options": [] }, { "varname": "tier0_vnetname", "type": "text", - "default_val": "vn-eastus-mlz-t0ci", + "default_val": "vn-eastus-mlz-t0", "description": "Tier 0 virtual network name", "options": [] }, { "varname": "tier1_rgname", "type": "text", - "default_val": "rg-eastus-mlz-t1ci", + "default_val": "rg-eastus-mlz-t1", "description": "Tier 1 resource group name", "options": [] }, { "varname": "tier1_vnetname", "type": "text", - "default_val": "vn-eastus-mlz-t1ci", + "default_val": "vn-eastus-mlz-t1", "description": "Tier one virtual network name", "options": [] }, { "varname": "tier2_rgname", "type": "text", - "default_val": "rg-eastus-mlz-t1ci", + "default_val": "rg-eastus-mlz-t1", "description": "Tier 2 resource group name", "options": [] }, { "varname": "tier2_vnetname", "type": "text", - "default_val": "vn-eastus-mlz-t2ci", + "default_val": "vn-eastus-mlz-t2", "description": "Tier 2 virtual network name", "options": [] }, diff --git a/src/core/tier-0/tier-0.front.json b/src/core/tier-0/tier-0.front.json index 21b32364f..28ce1ec25 100644 --- a/src/core/tier-0/tier-0.front.json +++ b/src/core/tier-0/tier-0.front.json @@ -14,14 +14,14 @@ { "varname": "saca_rgname", "type": "text", - "default_val": "rg-eastus-mlz-sacaci", + "default_val": "rg-eastus-mlz-saca", "description": "Saca Hub Resource Group Name", "options": [] }, { "varname": "saca_vnetname", "type": "text", - "default_val": "vn-eastus-mlz-sacaci", + "default_val": "vn-eastus-mlz-saca", "description": "Saca Virtual Network Name", "options": [] }, @@ -35,7 +35,7 @@ { "varname": "saca_lawsname", "type": "text", - "default_val": "laws-eastus-mlz-sacaci", + "default_val": "laws-eastus-mlz-saca", "description": "Saca Log Analytic Workspace Name", "options": [] }, @@ -49,14 +49,14 @@ { "varname": "tier0_rgname", "type": "text", - "default_val": "rg-eastus-mlz-t0ci", + "default_val": "rg-eastus-mlz-t0", "description": "Tier0 Resource Group Name", "options": [] }, { "varname": "tier0_vnetname", "type": "text", - "default_val": "vn-eastus-mlz-t0ci", + "default_val": "vn-eastus-mlz-t0", "description": "Tier0 Virtual Network Name", "options": [] }, diff --git a/src/core/tier-1/tier-1.front.json b/src/core/tier-1/tier-1.front.json index 7ac628a78..72f97529d 100644 --- a/src/core/tier-1/tier-1.front.json +++ b/src/core/tier-1/tier-1.front.json @@ -14,14 +14,14 @@ { "varname": "saca_rgname", "type": "text", - "default_val": "rg-eastus-mlz-sacaci", + "default_val": "rg-eastus-mlz-saca", "description": "Saca Hub Resource Group Name", "options": [] }, { "varname": "saca_vnetname", "type": "text", - "default_val": "vn-eastus-mlz-sacaci", + "default_val": "vn-eastus-mlz-saca", "description": "Saca Virtual Network Name", "options": [] }, @@ -35,7 +35,7 @@ { "varname": "saca_lawsname", "type": "text", - "default_val": "laws-eastus-mlz-sacaci", + "default_val": "laws-eastus-mlz-saca", "description": "Saca Log Analytic Workspace Name", "options": [] }, @@ -49,14 +49,14 @@ { "varname": "tier1_rgname", "type": "text", - "default_val": "rg-eastus-mlz-t1ci", + "default_val": "rg-eastus-mlz-t1", "description": "Tier0 Resource Group Name", "options": [] }, { "varname": "tier1_vnetname", "type": "text", - "default_val": "vn-eastus-mlz-t1ci", + "default_val": "vn-eastus-mlz-t1", "description": "Tier0 Virtual Network Name", "options": [] }, diff --git a/src/core/tier-2/tier-2.front.json b/src/core/tier-2/tier-2.front.json index f38ae0ed4..05c0c68b1 100644 --- a/src/core/tier-2/tier-2.front.json +++ b/src/core/tier-2/tier-2.front.json @@ -14,14 +14,14 @@ { "varname": "saca_rgname", "type": "text", - "default_val": "rg-eastus-mlz-sacaci", + "default_val": "rg-eastus-mlz-saca", "description": "Saca Hub Resource Group Name", "options": [] }, { "varname": "saca_vnetname", "type": "text", - "default_val": "vn-eastus-mlz-sacaci", + "default_val": "vn-eastus-mlz-saca", "description": "Saca Virtual Network Name", "options": [] }, @@ -35,7 +35,7 @@ { "varname": "saca_lawsname", "type": "text", - "default_val": "laws-eastus-mlz-sacaci", + "default_val": "laws-eastus-mlz-saca", "description": "Saca Log Analytic Workspace Name", "options": [] }, @@ -49,14 +49,14 @@ { "varname": "tier2_rgname", "type": "text", - "default_val": "rg-eastus-mlz-t2ci", + "default_val": "rg-eastus-mlz-t2", "description": "Tier2 Resource Group Name", "options": [] }, { "varname": "tier2_vnetname", "type": "text", - "default_val": "vn-eastus-mlz-t2ci", + "default_val": "vn-eastus-mlz-t2", "description": "Tier2 Virtual Network Name", "options": [] }, diff --git a/src/docs/ui-deployment.md b/src/docs/ui-deployment.md index 04f234da3..e3d7e08b3 100644 --- a/src/docs/ui-deployment.md +++ b/src/docs/ui-deployment.md @@ -87,34 +87,22 @@ prior to following the following instructions 1. Install requirements via pip ```bash - pip install -r src/front/requirements.txt + pip3 install -r src/front/requirements.txt ``` 1. Run the installation scripts to deploy app requirements You will need the following variables for the script: - subscription_id: is the subscription that will house all deployment artifacts: kv, storage, fe instance + `subscription_id`: is the subscription that will house all deployment artifacts: kv, storage, fe instance - tenant_id: the tenant_id where all of your subscriptions are located + `tenant_id`: the tenant_id where all of your subscriptions are located - tf_env_name: Please refer to [https://www.terraform.io/docs/language/settings/backends/azurerm.html#environment] for more information. (Defaults to Public) - - mlz_env_name: Can be anything unique to your deployment/environment it is used to ensure unique entries for resources. (Defaults to mlzdeployment) - - port: Default is 80, if you are running in WSL or otherwise can't bind to 80, use this flag to enter a port - - Multiple Subscriptions: - If you are running with multiple subscriptions, you'll need to use these flags with the setup command. - - -0: SACA Hub Subscription ID - -1: Tier 0 Subscription ID - -2: Tier 1 Subscription ID - -3: Tier 2 Subscription ID + `port`: Default is 80, if you are running in WSL or otherwise can't bind to 80, use this flag to enter a port ```bash - chmod u+x ./script/setup_ezdeploy.sh - ./script/setup_ezdeploy.sh -d local -s -t -l -e -m -p port p -0 -1 -2 -3 " + cd src/scripts + ./setup_ezdeploy.sh -d local -s -t -p ``` 1. Invoke environment variables needed for login (These are returned after setup_ezdeploy.sh is run) @@ -123,7 +111,7 @@ prior to following the following instructions $env:CLIENT_ID="" $env:CLIENT_SECRET=" + cd src/front + python3 main.py ``` You can then access the application by pointing your browser at "localhost". diff --git a/src/front/main.py b/src/front/main.py index b062d6210..69b5af501 100644 --- a/src/front/main.py +++ b/src/front/main.py @@ -322,6 +322,22 @@ async def process_input(request: Request): for f_name, doc in tf_json.items(): json.dump(doc, open(os.path.join(os.getcwd(), "config_output", os.path.basename(f_name)), "w+")) + # set terraform vars paths + config_output_dir = os.path.join(os.getcwd(), "config_output") + global_vars = os.path.join(config_output_dir, "globals.tfvars.json") + saca_vars = os.path.join(config_output_dir, "saca-hub.tfvars.json") + tier0_vars = os.path.join(config_output_dir, "tier-0.tfvars.json") + tier1_vars = os.path.join(config_output_dir, "tier-1.tfvars.json") + tier2_vars = os.path.join(config_output_dir, "tier-2.tfvars.json") + + # get service principal to execute terraform + if keyVaultName: + sp_id = secret_client.get_secret("serviceprincipal-clientid").value + sp_pwd = secret_client.get_secret("serviceprincipal-pwd").value + else: + sp_id = os.getenv("MLZCLIENTID", "NotSet") + sp_pwd = os.getenv("MLZCLIENTSECRET", "NotSet") + # write a command to write mlz.config: src_dir = os.path.dirname(os.getcwd()) generate_config_executable = os.path.join(src_dir, "scripts", "config", "generate_config_file.sh") @@ -333,7 +349,7 @@ async def process_input(request: Request): generate_config_args.append('--file ' + mlz_config_path) generate_config_args.append('--tf-env ' + os.getenv("TF_ENV")) generate_config_args.append('--metadatahost management.azure.com') # TODO (20210401): pass this by parameter or derive from cloud - generate_config_args.append('--mlz-env ' + os.getenv("MLZ_ENV")) + generate_config_args.append('--mlz-env-name ' + os.getenv("MLZ_ENV")) generate_config_args.append('--location ' + os.getenv("MLZ_LOCATION")) generate_config_args.append('--config-sub-id ' + os.getenv("SUBSCRIPTION_ID")) generate_config_args.append('--tenant-id ' + os.getenv("TENANT_ID")) @@ -345,7 +361,7 @@ async def process_input(request: Request): generate_config_command = "{} {}".format(generate_config_executable, ' '.join(generate_config_args)) # write a command to execute front_wrapper.sh: - wrapper_executable = os.path.join(os.getcwd(), "..", "build", "front_wrapper.sh") + wrapper_executable = os.path.join(src_dir, "build", "front_wrapper.sh") os.chmod(wrapper_executable, 0o755) wrapper_command = "{} {} {} {} {} {} {} y {} {}".format( @@ -359,24 +375,8 @@ async def process_input(request: Request): sp_id, sp_pwd) - # set terraform vars paths - config_output_dir = os.path.join(os.getcwd(), "config_output") - global_vars = os.path.join(config_output_dir, "globals.tfvars.json") - saca_vars = os.path.join(config_output_dir, "saca-hub.tfvars.json") - tier0_vars = os.path.join(config_output_dir, "tier-0.tfvars.json") - tier1_vars = os.path.join(config_output_dir, "tier-1.tfvars.json") - tier2_vars = os.path.join(config_output_dir, "tier-2.tfvars.json") - - # get service principal to execute terraform - if keyVaultName: - sp_id = secret_client.get_secret("serviceprincipal-clientid").value - sp_pwd = secret_client.get_secret("serviceprincipal-pwd").value - else: - sp_id = os.getenv("MLZCLIENTID", "NotSet") - sp_pwd = os.getenv("MLZCLIENTSECRET", "NotSet") - with open(exec_output, "w+") as out: - generate_mlz_config = await asyncio.create_subprocess_exec(*write_config_command.split(), stderr=out, stdout=out) + generate_mlz_config = await asyncio.create_subprocess_exec(*generate_config_command.split(), stderr=out, stdout=out) # This capture is setting to a dead object. If we want to do work with the process in the future # we have to do it here. await generate_mlz_config.wait() diff --git a/src/scripts/setup_ezdeploy_local.sh b/src/scripts/setup_ezdeploy_local.sh old mode 100644 new mode 100755 index c75fed2c5..e21b267e7 --- a/src/scripts/setup_ezdeploy_local.sh +++ b/src/scripts/setup_ezdeploy_local.sh @@ -20,7 +20,7 @@ usage() { error_log "usage: setup_ezdeploy.sh " } -if [[ "$#" -lt 8 ]]; then +if [[ "$#" -lt 2 ]]; then usage exit 1 fi @@ -63,7 +63,7 @@ echo "for bash:" echo "export CLIENT_ID=$auth_client_id" echo "export CLIENT_SECRET=$auth_client_secret" echo "export TENANT_ID=$mlz_tenantid" -echo "export LOCATION=$mlz_config_location" +echo "export MLZ_LOCATION=$mlz_config_location" echo "export SUBSCRIPTION_ID=$mlz_config_subid" echo "export TF_ENV=$tf_environment" echo "export MLZ_ENV=$mlz_env_name" @@ -73,7 +73,7 @@ echo "for PowerShell:" echo "\$env:CLIENT_ID='$client_id'" echo "\$env:CLIENT_SECRET='$client_password'" echo "\$env:TENANT_ID='$mlz_tenantid'" -echo "\$env:LOCATION='$mlz_config_location'" +echo "\$env:MLZ_LOCATION='$mlz_config_location'" echo "\$env:SUBSCRIPTION_ID='$mlz_config_subid'" echo "\$env:TF_ENV='$tf_environment'" echo "\$env:MLZ_ENV='$mlz_env_name'" From 9062c3c52da48c954f92489f1d5fb6572cda05b2 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Mon, 5 Apr 2021 13:04:00 -0400 Subject: [PATCH 18/31] misplaced default --- src/core/saca-hub/saca-hub.front.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/saca-hub/saca-hub.front.json b/src/core/saca-hub/saca-hub.front.json index 247b36f65..7ddc06d16 100644 --- a/src/core/saca-hub/saca-hub.front.json +++ b/src/core/saca-hub/saca-hub.front.json @@ -76,7 +76,7 @@ { "varname": "tier2_rgname", "type": "text", - "default_val": "rg-eastus-mlz-t1", + "default_val": "rg-eastus-mlz-t2", "description": "Tier 2 resource group name", "options": [] }, From cb6019ec4ac82d1f0149556ea7fbf36eb16c28a1 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Mon, 5 Apr 2021 13:45:59 -0400 Subject: [PATCH 19/31] add a todo to replace vault endpoint --- src/front/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/front/main.py b/src/front/main.py index 69b5af501..0b1492943 100644 --- a/src/front/main.py +++ b/src/front/main.py @@ -27,7 +27,7 @@ keyVaultName = os.getenv("KEYVAULT_ID", None) if keyVaultName: - keyVaultUrl = "https://{}.vault.azure.net/".format(keyVaultName) + keyVaultUrl = "https://{}.vault.azure.net/".format(keyVaultName) # TODO (20210401): pass this endpoint by parameter or derive from cloud # This will use your Azure Managed Identity credential = DefaultAzureCredential() From 31082d52a4e6b3219d8d3ea2437c1b5e205cc4d3 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Mon, 5 Apr 2021 13:50:23 -0400 Subject: [PATCH 20/31] defer changing name to mlz.config --- .gitignore | 1 - src/front/main.py | 4 ++-- src/mlz.config.sample | 11 ----------- src/scripts/config/generate_config_file.sh | 2 +- src/scripts/setup_ezdeploy.sh | 4 ++-- 5 files changed, 5 insertions(+), 17 deletions(-) delete mode 100644 src/mlz.config.sample diff --git a/.gitignore b/.gitignore index 6821f2e6e..3276b3bfe 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,6 @@ terraform-provider-random_v* # Setup config variables file mlz_tf_cfg.var -mlz.config saca-hub.tfvars.json tier-0.tfvars.json tier-1.tfvars.json diff --git a/src/front/main.py b/src/front/main.py index 0b1492943..1800b4f71 100644 --- a/src/front/main.py +++ b/src/front/main.py @@ -338,12 +338,12 @@ async def process_input(request: Request): sp_id = os.getenv("MLZCLIENTID", "NotSet") sp_pwd = os.getenv("MLZCLIENTSECRET", "NotSet") - # write a command to write mlz.config: + # write a command to write mlz config: src_dir = os.path.dirname(os.getcwd()) generate_config_executable = os.path.join(src_dir, "scripts", "config", "generate_config_file.sh") os.chmod(generate_config_executable, 0o755) - mlz_config_path = os.path.join(src_dir, "mlz.config") + mlz_config_path = os.path.join(src_dir, "mlz_tf_cfg.var") generate_config_args = [] generate_config_args.append('--file ' + mlz_config_path) diff --git a/src/mlz.config.sample b/src/mlz.config.sample deleted file mode 100644 index 3e1dc979f..000000000 --- a/src/mlz.config.sample +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -tf_environment="{TF_ENVIRONMENT}" # https://www.terraform.io/docs/language/settings/backends/azurerm.html#environment -mlz_env_name="{MLZ_ENV_NAME}" # Unique name for MLZ environment -mlz_config_subid="{MLZ_CONFIG_SUBID}" # Subscription ID for MissionLZ configuration resources -mlz_config_location="{MLZ_CONFIG_LOCATION}" # Azure Region for deploying Mission LZ configuration resources -mlz_tenantid="{MLZ_TENANTID}" -mlz_saca_subid="{MLZ_SACA_SUBID}" -mlz_tier0_subid="{MLZ_TIER0_SUBID}" -mlz_tier1_subid="{MLZ_TIER1_SUBID}" -mlz_tier2_subid="{MLZ_TIER2_SUBID}" diff --git a/src/scripts/config/generate_config_file.sh b/src/scripts/config/generate_config_file.sh index 6817f1668..1a501bab9 100755 --- a/src/scripts/config/generate_config_file.sh +++ b/src/scripts/config/generate_config_file.sh @@ -19,7 +19,7 @@ show_help() { printf "%15s %2s %s \n" "$long_name" "$char_name" "$desc" } print_formatted "argument" "" "description" - print_formatted "--file" "-f" "the destination file path and name (e.g. 'src/mlz.config')" + print_formatted "--file" "-f" "the destination file path and name (e.g. 'src/mlz_tf_cfg.var')" print_formatted "--tf-env" "-e" "Terraform azurerm environment (e.g. 'public') see: https://www.terraform.io/docs/language/settings/backends/azurerm.html#environment" print_formatted "--metadatahost" "-m" "Azure Metadata Service endpoint. (e.g 'management.azure.com' or 'management.usgovcloudapi.net')" print_formatted "--mlz-env-name" "-z" "Unique name for MLZ environment" diff --git a/src/scripts/setup_ezdeploy.sh b/src/scripts/setup_ezdeploy.sh index 9207bd46e..18483dcb7 100755 --- a/src/scripts/setup_ezdeploy.sh +++ b/src/scripts/setup_ezdeploy.sh @@ -94,8 +94,8 @@ if [[ $docker_strategy != "local" && \ fi # create MLZ configuration file -mlz_config_file="${src_path}/mlz.config" -echo "INFO: creating a mlz.config file based on user input at $(realpath "$mlz_config_file")..." +mlz_config_file="${src_path}/mlz_tf_cfg.var" +echo "INFO: creating a MLZ config file based on user input at $(realpath "$mlz_config_file")..." "${this_script_path}/config/generate_config_file.sh" \ -f "$mlz_config_file" \ -e "$tf_environment" \ From 0b1a3f1f82ada5c5b666033693ec11c5531e53af Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Mon, 5 Apr 2021 14:03:03 -0400 Subject: [PATCH 21/31] move the mlz config to the root --- src/docs/command-line-deployment.md | 2 +- src/{core => }/mlz_tf_cfg.var.sample | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/{core => }/mlz_tf_cfg.var.sample (100%) diff --git a/src/docs/command-line-deployment.md b/src/docs/command-line-deployment.md index b56f85205..b4957f21b 100644 --- a/src/docs/command-line-deployment.md +++ b/src/docs/command-line-deployment.md @@ -48,7 +48,7 @@ The MLZ deployment architecture uses a single Service Principal whose credential chmod u+x src/scripts/mlz_tf_setup.sh - src/scripts/mlz_tf_setup.sh src/core/mlz_tf_cfg.var + src/scripts/mlz_tf_setup.sh src/mlz_tf_cfg.var ``` ### Set Terraform Configuration Variables diff --git a/src/core/mlz_tf_cfg.var.sample b/src/mlz_tf_cfg.var.sample similarity index 100% rename from src/core/mlz_tf_cfg.var.sample rename to src/mlz_tf_cfg.var.sample From 43f38f2e37c765592372cc61f5d443e405415855 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Mon, 5 Apr 2021 14:20:35 -0400 Subject: [PATCH 22/31] update defaults --- src/core/tier-0/tier-0.front.json | 4 ++-- src/core/tier-1/tier-1.front.json | 4 ++-- src/core/tier-2/tier-2.front.json | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/core/tier-0/tier-0.front.json b/src/core/tier-0/tier-0.front.json index 28ce1ec25..a51831e9f 100644 --- a/src/core/tier-0/tier-0.front.json +++ b/src/core/tier-0/tier-0.front.json @@ -28,7 +28,7 @@ { "varname": "saca_fwname", "type": "text", - "default_val": "DemoFirewallci", + "default_val": "DemoFirewall", "description": "Saca Firewall Name", "options": [] }, @@ -125,7 +125,7 @@ { "varname": "subnets.{TIER0_SUBNETVM_NAME}.routetable_name", "type": "text", - "default_val": "tier0vmsrtci", + "default_val": "tier0vmsrt", "description": "Tier 0 Routeable Subnet Name", "options": [] } diff --git a/src/core/tier-1/tier-1.front.json b/src/core/tier-1/tier-1.front.json index 72f97529d..467f7c1b9 100644 --- a/src/core/tier-1/tier-1.front.json +++ b/src/core/tier-1/tier-1.front.json @@ -28,7 +28,7 @@ { "varname": "saca_fwname", "type": "text", - "default_val": "DemoFirewallci", + "default_val": "DemoFirewall", "description": "Saca Firewall Name", "options": [] }, @@ -125,7 +125,7 @@ { "varname": "subnets.{TIER1_SUBNETVM_NAME}.routetable_name", "type": "text", - "default_val": "tier1vmsrtci", + "default_val": "tier1vmsrt", "description": "Tier 0 Routeable Subnet Name", "options": [] } diff --git a/src/core/tier-2/tier-2.front.json b/src/core/tier-2/tier-2.front.json index 05c0c68b1..27e2337b2 100644 --- a/src/core/tier-2/tier-2.front.json +++ b/src/core/tier-2/tier-2.front.json @@ -28,7 +28,7 @@ { "varname": "saca_fwname", "type": "text", - "default_val": "DemoFirewallci", + "default_val": "DemoFirewall", "description": "Saca Firewall Name", "options": [] }, @@ -125,7 +125,7 @@ { "varname": "subnets.{TIER2_SUBNETVM_NAME}.routetable_name", "type": "text", - "default_val": "tier2vmsrtci", + "default_val": "tier2vmsrt", "description": "Tier 0 Routeable Subnet Name", "options": [] } From ddc0702f1f6b97323ea3d57e517832f9c8d6764b Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Mon, 5 Apr 2021 16:06:37 -0400 Subject: [PATCH 23/31] add support for multiple subscriptions --- src/core/saca-hub/saca-hub.front.json | 2 +- src/core/tier-0/tier-0.front.json | 4 +- src/core/tier-1/tier-1.front.json | 4 +- src/core/tier-2/tier-2.front.json | 4 +- src/scripts/config/generate_config_file.sh | 13 +-- .../container-registry/deploy_instance.sh | 18 +++- src/scripts/setup_ezdeploy.sh | 82 ++++++++++++++++--- src/scripts/setup_ezdeploy_local.sh | 27 +++++- 8 files changed, 127 insertions(+), 27 deletions(-) diff --git a/src/core/saca-hub/saca-hub.front.json b/src/core/saca-hub/saca-hub.front.json index 7ddc06d16..a7f1e4534 100644 --- a/src/core/saca-hub/saca-hub.front.json +++ b/src/core/saca-hub/saca-hub.front.json @@ -11,7 +11,7 @@ { "varname": "saca_subid", "type": "text", - "default_val": "env:SUBSCRIPTION_ID", + "default_val": "env:HUB_SUBSCRIPTION_ID", "description": "The subscription id where the SACA hub lives", "options": [] }, diff --git a/src/core/tier-0/tier-0.front.json b/src/core/tier-0/tier-0.front.json index a51831e9f..24ed0b7af 100644 --- a/src/core/tier-0/tier-0.front.json +++ b/src/core/tier-0/tier-0.front.json @@ -7,7 +7,7 @@ { "varname": "saca_subid", "type": "text", - "default_val": "env:SUBSCRIPTION_ID", + "default_val": "env:HUB_SUBSCRIPTION_ID", "description": "Saca Hub Subscription ID", "options": [] }, @@ -42,7 +42,7 @@ { "varname": "tier0_subid", "type": "text", - "default_val": "env:SUBSCRIPTION_ID", + "default_val": "env:TIER0_SUBSCRIPTION_ID", "description": "Tier0 Subscription Id", "options": [] }, diff --git a/src/core/tier-1/tier-1.front.json b/src/core/tier-1/tier-1.front.json index 467f7c1b9..61ef150db 100644 --- a/src/core/tier-1/tier-1.front.json +++ b/src/core/tier-1/tier-1.front.json @@ -7,7 +7,7 @@ { "varname": "saca_subid", "type": "text", - "default_val": "env:SUBSCRIPTION_ID", + "default_val": "env:HUB_SUBSCRIPTION_ID", "description": "Saca Hub Subscription ID", "options": [] }, @@ -42,7 +42,7 @@ { "varname": "tier1_subid", "type": "text", - "default_val": "env:SUBSCRIPTION_ID", + "default_val": "env:TIER1_SUBSCRIPTION_ID", "description": "Tier0 Subscription Id", "options": [] }, diff --git a/src/core/tier-2/tier-2.front.json b/src/core/tier-2/tier-2.front.json index 27e2337b2..be8fd4ed1 100644 --- a/src/core/tier-2/tier-2.front.json +++ b/src/core/tier-2/tier-2.front.json @@ -7,7 +7,7 @@ { "varname": "saca_subid", "type": "text", - "default_val": "env:SUBSCRIPTION_ID", + "default_val": "env:HUB_SUBSCRIPTION_ID", "description": "Saca Hub Subscription ID", "options": [] }, @@ -42,7 +42,7 @@ { "varname": "tier2_subid", "type": "text", - "default_val": "env:SUBSCRIPTION_ID", + "default_val": "env:TIER2_SUBSCRIPTION_ID", "description": "Tier0 Subscription Id", "options": [] }, diff --git a/src/scripts/config/generate_config_file.sh b/src/scripts/config/generate_config_file.sh index 1a501bab9..79a286ca7 100755 --- a/src/scripts/config/generate_config_file.sh +++ b/src/scripts/config/generate_config_file.sh @@ -90,12 +90,15 @@ touch "$dest_file" append_optional_args() { key_name=$1 key_value=$2 - file_to_append=$3 + default_value=$3 + file_to_append=$4 if [[ $key_value ]]; then printf "${key_name}=${key_value}\n" >> "${file_to_append}" + else + printf "${key_name}=${default_value}\n" >> "${file_to_append}" fi } -append_optional_args "mlz_saca_subid" "${mlz_saca_subid}" "${dest_file}" -append_optional_args "mlz_tier0_subid" "${mlz_tier0_subid}" "${dest_file}" -append_optional_args "mlz_tier1_subid" "${mlz_tier1_subid}" "${dest_file}" -append_optional_args "mlz_tier2_subid" "${mlz_tier2_subid}" "${dest_file}" +append_optional_args "mlz_saca_subid" "${mlz_saca_subid}" "${mlz_config_subid}" "${dest_file}" +append_optional_args "mlz_tier0_subid" "${mlz_tier0_subid}" "${mlz_config_subid}" "${dest_file}" +append_optional_args "mlz_tier1_subid" "${mlz_tier1_subid}" "${mlz_config_subid}" "${dest_file}" +append_optional_args "mlz_tier2_subid" "${mlz_tier2_subid}" "${mlz_config_subid}" "${dest_file}" diff --git a/src/scripts/container-registry/deploy_instance.sh b/src/scripts/container-registry/deploy_instance.sh index 67c1cb72d..58de2b419 100755 --- a/src/scripts/container-registry/deploy_instance.sh +++ b/src/scripts/container-registry/deploy_instance.sh @@ -53,12 +53,28 @@ registry_password=$(az keyvault secret show \ --query value \ --output tsv) +# set container environment variables from MLZ config +env_vars_args=() +env_vars_args+=("KEYVAULT_ID=${mlz_kv_name}") +env_vars_args+=("TENANT_ID=${mlz_tenantid}") +env_vars_args+=("MLZ_LOCATION=${mlz_config_location}") +env_vars_args+=("SUBSCRIPTION_ID=${mlz_config_subid}") +env_vars_args+=("TF_ENV=${tf_environment}") +env_vars_args+=("MLZ_ENV=${mlz_env_name}") +env_vars_args+=("HUB_SUBSCRIPTION_ID=${mlz_saca_subid}") +env_vars_args+=("TIER0_SUBSCRIPTION_ID=${mlz_tier0_subid}") +env_vars_args+=("TIER1_SUBSCRIPTION_ID=${mlz_tier1_subid}") +env_vars_args+=("TIER2_SUBSCRIPTION_ID=${mlz_tier2_subid}") + +# expand array into a string of space separated arguments +env_vars=$(printf '%s ' "${env_vars_args[*]}") + az container create \ --resource-group "${mlz_rg_name}" \ --name "${mlz_instance_name}" \ --image "${acr_login_server}/${image_name}:${image_tag}" \ --dns-name-label "${mlz_dns_name}" \ - --environment-variables KEYVAULT_ID="${mlz_kv_name}" TENANT_ID="${mlz_tenantid}" MLZ_LOCATION="${mlz_config_location}" SUBSCRIPTION_ID="${mlz_config_subid}" TF_ENV="${tf_environment}" MLZ_ENV="${mlz_env_name}" \ + --environment-variables "${env_vars}" \ --registry-username "${registry_username}" \ --registry-password "${registry_password}" \ --ports 80 \ diff --git a/src/scripts/setup_ezdeploy.sh b/src/scripts/setup_ezdeploy.sh index 18483dcb7..4ddc7ab5e 100755 --- a/src/scripts/setup_ezdeploy.sh +++ b/src/scripts/setup_ezdeploy.sh @@ -3,7 +3,8 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # -# shellcheck disable=SC1090,SC1091,2154 +# shellcheck disable=SC1083,SC1090,SC1091,2154 +# SC1083: This is literal. # SC1090: Can't follow non-constant source. Use a directive to specify location. # SC1091: Not following. Shellcheck can't follow non-constant source. # SC2154: "var is referenced but not assigned". These values come from an external file. @@ -53,6 +54,15 @@ tf_environment="public" mlz_env_name="mlz${timestamp}" web_port="80" +subs=() +add_unique_sub_to_array() { + if [[ ! "${subs[*]}" =~ ${1} ]];then + subs+=("${1}") + fi +} + +subs_args=() + # inspect user input while [ $# -gt 0 ] ; do case $1 in @@ -63,6 +73,22 @@ while [ $# -gt 0 ] ; do -e | --tf-environment) tf_environment="$2" ;; -z | --mlz-env-name) mlz_env_name="$2" ;; -p | --port) web_port="$2" ;; + -h | --hub-sub-id) + add_unique_sub_to_array "$2" + subs_args+=("-h ${2}") + ;; + -0 | --tier0-sub-id) + add_unique_sub_to_array "$2" + subs_args+=("-0 ${2}") + ;; + -1 | --tier1-sub-id) + add_unique_sub_to_array "$2" + subs_args+=("-1 ${2}") + ;; + -2 | --tier2-sub-id) + add_unique_sub_to_array "$2" + subs_args+=("-2 ${2}") + ;; esac shift done @@ -93,17 +119,32 @@ if [[ $docker_strategy != "local" && \ exit 1 fi -# create MLZ configuration file +# create MLZ configuration file based on user input mlz_config_file="${src_path}/mlz_tf_cfg.var" echo "INFO: creating a MLZ config file based on user input at $(realpath "$mlz_config_file")..." -"${this_script_path}/config/generate_config_file.sh" \ - -f "$mlz_config_file" \ - -e "$tf_environment" \ - -m "$metadata_host" \ - -z "$mlz_env_name" \ - -l "$mlz_config_location" \ - -s "$mlz_config_subid" \ - -t "$mlz_tenantid" + +### derive args from user input +gen_config_args=() +gen_config_args+=("-f ${mlz_config_file}") +gen_config_args+=("-e ${tf_environment}") +gen_config_args+=("-m ${metadata_host}") +gen_config_args+=("-z ${mlz_env_name}") +gen_config_args+=("-l ${mlz_config_location}") +gen_config_args+=("-s ${mlz_config_subid}") +gen_config_args+=("-t ${mlz_tenantid}") + +### add hubs and spokes, if present +for j in "${subs_args[@]}" +do + gen_config_args+=("$j") +done + +### expand array into a string of space separated arguments +gen_config_args_str=$(printf '%s ' "${gen_config_args[*]}") + +### create the file +# shellcheck disable=SC2086 +. "${this_script_path}/config/generate_config_file.sh" $gen_config_args_str # generate MLZ configuration names . "${this_script_path}/config/generate_names.sh" "$mlz_config_file" @@ -112,14 +153,31 @@ echo "INFO: creating a MLZ config file based on user input at $(realpath "$mlz_c echo "INFO: setting up required MLZ resources using $(realpath "$mlz_config_file")..." "${this_script_path}/config/mlz_config_create.sh" "$mlz_config_file" +# add permissions to subscriptions provided by input +mlz_sp_objid=$(az ad sp show \ + --id "http://${mlz_sp_name}" \ + --query objectId \ + --output tsv) + +for sub in "${subs[@]}" +do + echo "INFO: setting Contributor role assignment for ${mlz_sp_name} on subscription ${sub}..." + az role assignment create \ + --role Contributor \ + --assignee-object-id "${mlz_sp_objid}" \ + --scope "/subscriptions/${sub}" \ + --assignee-principal-type ServicePrincipal \ + --only-show-errors \ + --output none +done + # switch to the MLZ subscription echo "INFO: setting current az cli subscription to ${mlz_config_subid}..." az account set --subscription "${mlz_config_subid}" # if local, call setup_ezdeploy_local if [[ $docker_strategy == "local" ]]; then - local_fqdn="localhost:${web_port}" - "${this_script_path}/setup_ezdeploy_local.sh" "$mlz_config_file" "$local_fqdn" + "${this_script_path}/setup_ezdeploy_local.sh" "$mlz_config_file" "$web_port" exit 0 fi diff --git a/src/scripts/setup_ezdeploy_local.sh b/src/scripts/setup_ezdeploy_local.sh index e21b267e7..1395baae4 100755 --- a/src/scripts/setup_ezdeploy_local.sh +++ b/src/scripts/setup_ezdeploy_local.sh @@ -26,14 +26,18 @@ if [[ "$#" -lt 2 ]]; then fi mlz_config_file=$1 -local_fqdn=$2 +web_port=$2 container_registry_path="$(realpath "${BASH_SOURCE%/*}")/container-registry" +# source mlz_config_file +. "${mlz_config_file}" + # generate MLZ configuration names . "$(realpath "${BASH_SOURCE%/*}")/config/generate_names.sh" "$mlz_config_file" # create auth scopes +local_fqdn="localhost:${web_port}" "${container_registry_path}/add_auth_scopes.sh" "$mlz_config_file" "$local_fqdn" auth_client_id=$(az keyvault secret show \ @@ -58,25 +62,44 @@ mlz_client_secret=$(az keyvault secret show \ --output tsv) # echo out env vars -echo "INFO: Your environment variables for local execution are:" +echo "INFO: Complete!" +echo "==============================" +echo "INFO: 1) To run the UI first set the environment variables below" +echo "==============================" + echo "for bash:" echo "export CLIENT_ID=$auth_client_id" echo "export CLIENT_SECRET=$auth_client_secret" echo "export TENANT_ID=$mlz_tenantid" echo "export MLZ_LOCATION=$mlz_config_location" echo "export SUBSCRIPTION_ID=$mlz_config_subid" +echo "export HUB_SUBSCRIPTION_ID=$mlz_saca_subid" +echo "export TIER0_SUBSCRIPTION_ID=$mlz_tier0_subid" +echo "export TIER1_SUBSCRIPTION_ID=$mlz_tier1_subid" +echo "export TIER2_SUBSCRIPTION_ID=$mlz_tier2_subid" echo "export TF_ENV=$tf_environment" echo "export MLZ_ENV=$mlz_env_name" echo "export MLZCLIENTID=$mlz_client_id" echo "export MLZCLIENTSECRET=$mlz_client_secret" + echo "for PowerShell:" echo "\$env:CLIENT_ID='$client_id'" echo "\$env:CLIENT_SECRET='$client_password'" echo "\$env:TENANT_ID='$mlz_tenantid'" echo "\$env:MLZ_LOCATION='$mlz_config_location'" echo "\$env:SUBSCRIPTION_ID='$mlz_config_subid'" +echo "\$env:HUB_SUBSCRIPTION_ID='HUB_SUBSCRIPTION_ID=$mlz_saca_subid'" +echo "\$env:TIER0_SUBSCRIPTION_ID='TIER0_SUBSCRIPTION_ID=$mlz_tier0_subid'" +echo "\$env:TIER1_SUBSCRIPTION_ID='TIER1_SUBSCRIPTION_ID=$mlz_tier1_subid'" +echo "\$env:TIER2_SUBSCRIPTION_ID='TIER2_SUBSCRIPTION_ID=$mlz_tier2_subid'" echo "\$env:TF_ENV='$tf_environment'" echo "\$env:MLZ_ENV='$mlz_env_name'" echo "\$env:MLZCLIENTID='$(az keyvault secret show --name "${mlz_sp_kv_name}" --vault-name "${mlz_kv_name}" --query value --output tsv)'" echo "\$env:MLZCLIENTSECRET='$(az keyvault secret show --name "${mlz_sp_kv_password}" --vault-name "${mlz_kv_name}" --query value --output tsv)'" + +echo "==============================" +echo "INFO: 2) Then, execute the web server with:" +echo "==============================" +echo "cd ../front" +echo "python3 main.py ${web_port}" exit 0 From 9962e42f48e56c74473b180c92704f341234036e Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Mon, 5 Apr 2021 16:10:05 -0400 Subject: [PATCH 24/31] update help --- src/scripts/setup_ezdeploy.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/scripts/setup_ezdeploy.sh b/src/scripts/setup_ezdeploy.sh index 4ddc7ab5e..ee0bc5030 100755 --- a/src/scripts/setup_ezdeploy.sh +++ b/src/scripts/setup_ezdeploy.sh @@ -31,7 +31,10 @@ show_help() { print_formatted "--location" "-l" "The location that you're deploying to (defaults to 'eastus')" print_formatted "--tf-environment" "-e" "Terraform azurerm environment (defaults to 'public') see: https://www.terraform.io/docs/language/settings/backends/azurerm.html#environment" print_formatted "--mlz-env-name" "-z" "Unique name for MLZ environment (defaults to 'mlz' + UNIX timestamp)" - print_formatted "--port" "-p" "port to expose the front end web UI on (defaults to '80')" + print_formatted "--hub-sub-id" "-h" "subscription ID for the hub network and resources (defaults to the value provided for -s --subscription-id)" + print_formatted "--tier0-sub-id" "-0" "subscription ID for tier 0 network and resources (defaults to the value provided for -s --subscription-id)" + print_formatted "--tier1-sub-id" "-1" "subscription ID for tier 1 network and resources (defaults to the value provided for -s --subscription-id)" + print_formatted "--tier2-sub-id" "-2" "subscription ID for tier 2 network and resources (defaults to the value provided for -s --subscription-id)" } usage() { From 408a5aed74821525d97f971e34fd0c2e6894f423 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Mon, 5 Apr 2021 16:10:50 -0400 Subject: [PATCH 25/31] update comment --- src/front/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/front/main.py b/src/front/main.py index 1800b4f71..f68f62d1d 100644 --- a/src/front/main.py +++ b/src/front/main.py @@ -27,7 +27,7 @@ keyVaultName = os.getenv("KEYVAULT_ID", None) if keyVaultName: - keyVaultUrl = "https://{}.vault.azure.net/".format(keyVaultName) # TODO (20210401): pass this endpoint by parameter or derive from cloud + keyVaultUrl = "https://{}.vault.azure.net/".format(keyVaultName) # TODO (20210401): pass this by parameter or derive from cloud # This will use your Azure Managed Identity credential = DefaultAzureCredential() From b5c67d0e99fb48a66d19cb3fb5bdc0e37a873d05 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Mon, 5 Apr 2021 16:24:03 -0400 Subject: [PATCH 26/31] remove redundant assignment --- src/scripts/setup_ezdeploy.sh | 51 +++++------------------------------ 1 file changed, 6 insertions(+), 45 deletions(-) diff --git a/src/scripts/setup_ezdeploy.sh b/src/scripts/setup_ezdeploy.sh index ee0bc5030..ab9fee1b9 100755 --- a/src/scripts/setup_ezdeploy.sh +++ b/src/scripts/setup_ezdeploy.sh @@ -47,8 +47,7 @@ timestamp=$(date +%s) metadata_host="management.azure.com" # TODO (20210401): pass this by parameter or derive from cloud acr_endpoint="azurecr.io" # TODO (20210401): pass this by parameter or derive from cloud -# set helpful defaults that can be overridden -# or to 'notset' require mandatory input +# set helpful defaults that can be overridden or 'notset' for mandatory input docker_strategy="build" mlz_config_subid="notset" mlz_tenantid="notset" @@ -56,14 +55,6 @@ mlz_config_location="eastus" tf_environment="public" mlz_env_name="mlz${timestamp}" web_port="80" - -subs=() -add_unique_sub_to_array() { - if [[ ! "${subs[*]}" =~ ${1} ]];then - subs+=("${1}") - fi -} - subs_args=() # inspect user input @@ -76,22 +67,10 @@ while [ $# -gt 0 ] ; do -e | --tf-environment) tf_environment="$2" ;; -z | --mlz-env-name) mlz_env_name="$2" ;; -p | --port) web_port="$2" ;; - -h | --hub-sub-id) - add_unique_sub_to_array "$2" - subs_args+=("-h ${2}") - ;; - -0 | --tier0-sub-id) - add_unique_sub_to_array "$2" - subs_args+=("-0 ${2}") - ;; - -1 | --tier1-sub-id) - add_unique_sub_to_array "$2" - subs_args+=("-1 ${2}") - ;; - -2 | --tier2-sub-id) - add_unique_sub_to_array "$2" - subs_args+=("-2 ${2}") - ;; + -h | --hub-sub-id) subs_args+=("-h ${2}") ;; + -0 | --tier0-sub-id) subs_args+=("-0 ${2}") ;; + -1 | --tier1-sub-id) subs_args+=("-1 ${2}") ;; + -2 | --tier2-sub-id) subs_args+=("-2 ${2}") ;; esac shift done @@ -147,7 +126,7 @@ gen_config_args_str=$(printf '%s ' "${gen_config_args[*]}") ### create the file # shellcheck disable=SC2086 -. "${this_script_path}/config/generate_config_file.sh" $gen_config_args_str +"${this_script_path}/config/generate_config_file.sh" $gen_config_args_str # generate MLZ configuration names . "${this_script_path}/config/generate_names.sh" "$mlz_config_file" @@ -156,24 +135,6 @@ gen_config_args_str=$(printf '%s ' "${gen_config_args[*]}") echo "INFO: setting up required MLZ resources using $(realpath "$mlz_config_file")..." "${this_script_path}/config/mlz_config_create.sh" "$mlz_config_file" -# add permissions to subscriptions provided by input -mlz_sp_objid=$(az ad sp show \ - --id "http://${mlz_sp_name}" \ - --query objectId \ - --output tsv) - -for sub in "${subs[@]}" -do - echo "INFO: setting Contributor role assignment for ${mlz_sp_name} on subscription ${sub}..." - az role assignment create \ - --role Contributor \ - --assignee-object-id "${mlz_sp_objid}" \ - --scope "/subscriptions/${sub}" \ - --assignee-principal-type ServicePrincipal \ - --only-show-errors \ - --output none -done - # switch to the MLZ subscription echo "INFO: setting current az cli subscription to ${mlz_config_subid}..." az account set --subscription "${mlz_config_subid}" From 3b67102ab91debeab7116e4fcd9b0172b044cef7 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Mon, 5 Apr 2021 17:08:48 -0400 Subject: [PATCH 27/31] better comments --- src/scripts/container-registry/deploy_instance.sh | 5 ++++- src/scripts/setup_ezdeploy.sh | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/scripts/container-registry/deploy_instance.sh b/src/scripts/container-registry/deploy_instance.sh index 58de2b419..78d5b39d2 100755 --- a/src/scripts/container-registry/deploy_instance.sh +++ b/src/scripts/container-registry/deploy_instance.sh @@ -69,12 +69,15 @@ env_vars_args+=("TIER2_SUBSCRIPTION_ID=${mlz_tier2_subid}") # expand array into a string of space separated arguments env_vars=$(printf '%s ' "${env_vars_args[*]}") +# do not quote args $env_vars, we intend to split +# ignoring shellcheck for word splitting because that is the desired behavior +# shellcheck disable=SC2086 az container create \ --resource-group "${mlz_rg_name}" \ --name "${mlz_instance_name}" \ --image "${acr_login_server}/${image_name}:${image_tag}" \ --dns-name-label "${mlz_dns_name}" \ - --environment-variables "${env_vars}" \ + --environment-variables $env_vars \ --registry-username "${registry_username}" \ --registry-password "${registry_password}" \ --ports 80 \ diff --git a/src/scripts/setup_ezdeploy.sh b/src/scripts/setup_ezdeploy.sh index ab9fee1b9..7a5e18b09 100755 --- a/src/scripts/setup_ezdeploy.sh +++ b/src/scripts/setup_ezdeploy.sh @@ -125,6 +125,8 @@ done gen_config_args_str=$(printf '%s ' "${gen_config_args[*]}") ### create the file +### do not quote args $gen_config_args_str, we intend to split +### ignoring shellcheck for word splitting because that is the desired behavior # shellcheck disable=SC2086 "${this_script_path}/config/generate_config_file.sh" $gen_config_args_str From 0559cb7d1cca70eb26f27cbc41dafbfa519d915a Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Mon, 5 Apr 2021 17:23:34 -0400 Subject: [PATCH 28/31] update docs --- src/docs/ui-deployment.md | 42 +++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/src/docs/ui-deployment.md b/src/docs/ui-deployment.md index e3d7e08b3..afa7bf1b5 100644 --- a/src/docs/ui-deployment.md +++ b/src/docs/ui-deployment.md @@ -98,7 +98,7 @@ prior to following the following instructions `tenant_id`: the tenant_id where all of your subscriptions are located - `port`: Default is 80, if you are running in WSL or otherwise can't bind to 80, use this flag to enter a port + `port`: Default is 80, if you are running in WSL or otherwise can't bind to 80, use this flag to enter a port (e.g. 8081) ```bash cd src/scripts @@ -108,23 +108,35 @@ prior to following the following instructions 1. Invoke environment variables needed for login (These are returned after setup_ezdeploy.sh is run) ```powershell - $env:CLIENT_ID="" - $env:CLIENT_SECRET=" Date: Tue, 6 Apr 2021 15:32:45 -0400 Subject: [PATCH 29/31] default the tenant id --- src/docs/ui-deployment.md | 7 ++----- src/scripts/setup_ezdeploy.sh | 37 +++++++++++++++++++---------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/docs/ui-deployment.md b/src/docs/ui-deployment.md index a0132ce77..0f87bc76e 100644 --- a/src/docs/ui-deployment.md +++ b/src/docs/ui-deployment.md @@ -41,7 +41,7 @@ Then deploy a container instance of the front end with: ```BASH cd src/scripts -./setup_ezdeploy.sh -s -t +./setup_ezdeploy.sh -s ``` `setup_ezdeploy.sh` has more configurable options, but these are the minimum required to deploy a running UI that will help you make a full MLZ deployment. @@ -53,7 +53,6 @@ setup_ezdeploy.sh: Setup the front end for MLZ argument description --docker-strategy -d [local|build|load] 'local' for localhost, 'build' to build from this repo, or 'load' to unzip an image --subscription-id -s Subscription ID for MissionLZ resources - --tenant-id -t Tenant ID where your subscriptions live --location -l The location that you're deploying to (defaults to 'eastus') --tf-environment -e Terraform azurerm environment (defaults to 'public') see: https://www.terraform.io/docs/language/settings/backends/azurerm.html#environment --mlz-env-name -z Unique name for MLZ environment (defaults to 'mlz' + UNIX timestamp) @@ -113,13 +112,11 @@ prior to following the following instructions `subscription_id`: is the subscription that will house all deployment artifacts: kv, storage, fe instance - `tenant_id`: the tenant_id where all of your subscriptions are located - `port`: Default is 80, if you are running in WSL or otherwise can't bind to 80, use this flag to enter a port (e.g. 8081) ```bash cd src/scripts - ./setup_ezdeploy.sh -d local -s -t -p + ./setup_ezdeploy.sh -d local -s -p ``` 1. Invoke environment variables needed for login (These are returned after setup_ezdeploy.sh is run) diff --git a/src/scripts/setup_ezdeploy.sh b/src/scripts/setup_ezdeploy.sh index 7a5e18b09..3884ce964 100755 --- a/src/scripts/setup_ezdeploy.sh +++ b/src/scripts/setup_ezdeploy.sh @@ -27,7 +27,6 @@ show_help() { print_formatted "argument" "" "description" print_formatted "--docker-strategy" "-d" "[local|build|load] 'local' for localhost, 'build' to build from this repo, or 'load' to unzip an image (defaults to 'build')" print_formatted "--subscription-id" "-s" "Subscription ID for MissionLZ resources" - print_formatted "--tenant-id" "-t" "Tenant ID where your subscriptions live" print_formatted "--location" "-l" "The location that you're deploying to (defaults to 'eastus')" print_formatted "--tf-environment" "-e" "Terraform azurerm environment (defaults to 'public') see: https://www.terraform.io/docs/language/settings/backends/azurerm.html#environment" print_formatted "--mlz-env-name" "-z" "Unique name for MLZ environment (defaults to 'mlz' + UNIX timestamp)" @@ -50,7 +49,6 @@ acr_endpoint="azurecr.io" # TODO (20210401): pass this by parameter or derive fr # set helpful defaults that can be overridden or 'notset' for mandatory input docker_strategy="build" mlz_config_subid="notset" -mlz_tenantid="notset" mlz_config_location="eastus" tf_environment="public" mlz_env_name="mlz${timestamp}" @@ -62,7 +60,6 @@ while [ $# -gt 0 ] ; do case $1 in -d | --docker-strategy) docker_strategy="$2" ;; -s | --subscription-id) mlz_config_subid="$2" ;; - -t | --tenant-id) mlz_tenantid="$2" ;; -l | --location) mlz_config_location="$2" ;; -e | --tf-environment) tf_environment="$2" ;; -z | --mlz-env-name) mlz_env_name="$2" ;; @@ -75,16 +72,7 @@ while [ $# -gt 0 ] ; do shift done -# check mandatory parameters -for i in { $docker_strategy $mlz_config_subid $mlz_tenantid $mlz_config_location $tf_environment $mlz_env_name $web_port } -do - if [[ $i == "notset" ]]; then - error_log "ERROR: Missing required arguments. These arguments are mandatory: -d, -s, -t, -l, -e, -z, -p" - usage - exit 1 - fi -done - +# setup paths this_script_path=$(realpath "${BASH_SOURCE%/*}") src_path=$(dirname "${this_script_path}") container_registry_path="$(realpath "${this_script_path}")/container-registry" @@ -93,6 +81,16 @@ container_registry_path="$(realpath "${this_script_path}")/container-registry" "${this_script_path}/util/checkforazcli.sh" "${this_script_path}/util/checkfordocker.sh" +# check mandatory parameters +for i in { $docker_strategy $mlz_config_subid $mlz_config_location $tf_environment $mlz_env_name $web_port } +do + if [[ $i == "notset" ]]; then + error_log "ERROR: Missing required arguments. These arguments are mandatory: -d, -s, -l, -e, -z, -p" + usage + exit 1 + fi +done + # check docker strategy if [[ $docker_strategy != "local" && \ $docker_strategy != "build" && \ @@ -101,6 +99,15 @@ if [[ $docker_strategy != "local" && \ exit 1 fi +# switch to the MLZ subscription +echo "INFO: setting current az cli subscription to ${mlz_config_subid}..." +az account set --subscription "${mlz_config_subid}" + +# retrieve tenant ID for the MLZ subscription +mlz_tenantid=$(az account show \ + --query "tenantId" \ + --output tsv) + # create MLZ configuration file based on user input mlz_config_file="${src_path}/mlz_tf_cfg.var" echo "INFO: creating a MLZ config file based on user input at $(realpath "$mlz_config_file")..." @@ -137,10 +144,6 @@ gen_config_args_str=$(printf '%s ' "${gen_config_args[*]}") echo "INFO: setting up required MLZ resources using $(realpath "$mlz_config_file")..." "${this_script_path}/config/mlz_config_create.sh" "$mlz_config_file" -# switch to the MLZ subscription -echo "INFO: setting current az cli subscription to ${mlz_config_subid}..." -az account set --subscription "${mlz_config_subid}" - # if local, call setup_ezdeploy_local if [[ $docker_strategy == "local" ]]; then "${this_script_path}/setup_ezdeploy_local.sh" "$mlz_config_file" "$web_port" From d009afd4e01a35123fea3f446b685268ecc35a5a Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Wed, 7 Apr 2021 09:45:45 -0400 Subject: [PATCH 30/31] update docs --- src/docs/ui-deployment.md | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/docs/ui-deployment.md b/src/docs/ui-deployment.md index de0cf35ca..351e18151 100644 --- a/src/docs/ui-deployment.md +++ b/src/docs/ui-deployment.md @@ -27,26 +27,6 @@ This process will build the user interface container image on your workstation u Log in using the Azure CLI ```BASH -chmod u+x ./scripts/setup_ezdeploy.sh -./scripts/setup_ezdeploy.sh \ - -d build \ - -s \ - -t \ - -l \ - -e \ - -m \ - -p port \ - -0 \ - -1 \ - -2 \ - -3 -az login -``` - -> **Note:** For deployments to Azure Government, you will first need to set the cloud before logging in, such as: - -```BASH - az cloud set --name AzureUSGovernment az login ``` From c7191c9e7983ee5c4ac5e39b8bea7471853d3950 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Wed, 7 Apr 2021 10:29:58 -0400 Subject: [PATCH 31/31] get cloud specific endpoints for mlz config --- src/scripts/config/append_prereq_endpoints.sh | 45 +++++++++++++++++++ src/scripts/config/generate_config_file.sh | 4 ++ 2 files changed, 49 insertions(+) create mode 100755 src/scripts/config/append_prereq_endpoints.sh diff --git a/src/scripts/config/append_prereq_endpoints.sh b/src/scripts/config/append_prereq_endpoints.sh new file mode 100755 index 000000000..1c42330ca --- /dev/null +++ b/src/scripts/config/append_prereq_endpoints.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# +# append pre-req endpoints to an MLZ config file + +set -e + +error_log() { + echo "${1}" 1>&2; +} + +usage() { + echo "append_prereq_endpoints.sh: append pre-req endpoints to an MLZ config file" + error_log "usage: append_prereq_endpoints.sh " +} + +if [[ "$#" -lt 1 ]]; then + usage + exit 1 +fi + +file_to_append=$1 + +cloudEndpoints=($(az cloud show \ + --query '[endpoints.resourceManager, suffixes.acrLoginServerEndpoint, suffixes.keyvaultDns]' \ + --output tsv)) + +resourceManager=${cloudEndpoints[0]} +acrLoginServerEndpoint=${cloudEndpoints[1]} +keyvaultDns=${cloudEndpoints[2]} + +append_if_not_empty() { + key_name=$1 + key_value=$2 + file=$3 + if [[ $key_value ]]; then + printf "${key_name}=${key_value}\n" >> "${file}" + fi +} + +append_if_not_empty "metadatahost" ${cloudEndpoints[0]} ${file_to_append} +append_if_not_empty "acrLoginServerEndpoint" ${cloudEndpoints[1]} ${file_to_append} +append_if_not_empty "keyvaultDns" ${cloudEndpoints[2]} ${file_to_append} diff --git a/src/scripts/config/generate_config_file.sh b/src/scripts/config/generate_config_file.sh index 79a286ca7..1fd0edb85 100755 --- a/src/scripts/config/generate_config_file.sh +++ b/src/scripts/config/generate_config_file.sh @@ -102,3 +102,7 @@ append_optional_args "mlz_saca_subid" "${mlz_saca_subid}" "${mlz_config_subid}" append_optional_args "mlz_tier0_subid" "${mlz_tier0_subid}" "${mlz_config_subid}" "${dest_file}" append_optional_args "mlz_tier1_subid" "${mlz_tier1_subid}" "${mlz_config_subid}" "${dest_file}" append_optional_args "mlz_tier2_subid" "${mlz_tier2_subid}" "${mlz_config_subid}" "${dest_file}" + +# append cloud specific endpoints +this_script_path=$(realpath "${BASH_SOURCE%/*}") +. "${this_script_path}/append_prereq_endpoints.sh" ${dest_file}