Skip to content

Commit

Permalink
Generate configuration names and config.vars files (#53)
Browse files Browse the repository at this point in the history
* add a config folder to centralize generation
  • Loading branch information
glennmusa committed Mar 3, 2021
1 parent cc84cc0 commit 95d631f
Show file tree
Hide file tree
Showing 10 changed files with 341 additions and 383 deletions.
14 changes: 6 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,12 @@ Create the `mlz_tf_cfg.var` file using the `mlz_tf_cfg.var.sample` as the templa
- A Storage Account and Container for each tier to store tier Terraform state files
- Tier specific Terraform backend config files

Usage: ./mlz_tf_setup.sh <enclave name> <location> <terraform environment>
```bash
# usage mlz_tf_setup.sh: <mlz_tf_cfg.var path> <enclave name> <location>

NOTE: While the field <terraform environment> is analogous to the "--name" parameter in Azure CLI (az cloud set --name), the values aren't always the same. As an example, For Azure Commercial the `--name` value is AzureCloud while the Terraform value would be public
chmod u+x scripts/mlz_tf_setup.sh

```bash
cd scripts
chmod u+x mlz_tf_setup.sh
./mlz_tf_setup.sh dev eastus public
scripts/mlz_tf_setup.sh src/core/mlz_tf_cfg.var eastus public
```

### Set Terraform Configuration Variables
Expand Down Expand Up @@ -126,8 +124,8 @@ contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additio

## Trademarks

This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft
trademarks or logos is subject to and must follow
This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft
trademarks or logos is subject to and must follow
[Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general).
Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship.
Any use of third-party trademarks or logos are subject to those third-party's policies.
4 changes: 2 additions & 2 deletions scripts/apply_terraform.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ plugin_dir="$(dirname "$(dirname "$(realpath "$0")")")/src/provider_cache"
. "${BASH_SOURCE%/*}"/util/checkforterraform.sh

# Validate necessary Azure resources exist
. "${BASH_SOURCE%/*}"/mlz_config_validate.sh "${tf_dir}"
. "${BASH_SOURCE%/*}"/config/config_validate.sh "${tf_dir}"

# Get the .tfvars file matching the terraform directory name
if [[ ! -f "${tfvars}" ]]
Expand Down Expand Up @@ -114,4 +114,4 @@ terraform apply \
-var-file="${globalvars}" \
-var-file="${tfvars}" \
-var "mlz_clientid=${client_id}" \
-var "mlz_clientsecret=${client_secret}"
-var "mlz_clientsecret=${client_secret}"
84 changes: 84 additions & 0 deletions scripts/config/config_create.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#!/bin/bash
#
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
#
# shellcheck disable=SC1090,SC1091,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 Terraform module backend config resources

error_log() {
echo "${1}" 1>&2;
}

usage() {
echo "${0}: Create Terraform module config resources"
error_log "usage: ${0} <mlz tf config vars> <enclave name> <location> <tf subscription id> <path to terraform module>"
}

if [[ "$#" -lt 4 ]]; then
usage
exit 1
fi

mlz_tf_cfg=$(realpath "${1}")
enclave_name=$2
location=$3
tf_sub_id=$4
tf_dir=$(realpath "${5}")

# source MLZ config vars
. "${mlz_tf_cfg}"

# derive TF names from the terraform directory
tf_name=$(basename "${tf_dir}")

# generate names
. "${BASH_SOURCE%/*}"/generate_names.sh "${tf_config_subid}" "${enclave_name}" "${tf_sub_id}" "${tf_name}"

# create TF Resource Group and Storage Account for Terraform State files
echo "Validating Resource Group for Terraform state..."
if [[ -z $(az group show --name "${tf_rg_name}" --subscription "${tf_sub_id}" --query name --output tsv) ]];then
echo "Resource Group does not exist...creating resource group ${tf_rg_name}"
az group create \
--subscription "${tf_sub_id}" \
--location "${location}" \
--name "${tf_rg_name}"
else
echo "Resource Group already exists...getting resource group"
fi

echo "Validating Storage Account for Terraform state..."
if [[ -z $(az storage account show --name "${tf_sa_name}" --subscription "${tf_sub_id}" --query name --output tsv) ]];then
echo "Storage Account does not exist...creating storage account ${tf_sa_name}"
az storage account create \
--name "${tf_sa_name}" \
--subscription "${tf_sub_id}" \
--resource-group "${tf_rg_name}" \
--location "${location}" \
--sku Standard_LRS \
--output none

sa_key=$(az storage account keys list \
--account-name "${tf_sa_name}" \
--subscription "${tf_sub_id}" \
--resource-group "${tf_rg_name}" \
--query "[?keyName=='key1'].value" \
--output tsv)

az storage container create \
--name "${container_name}" \
--subscription "${tf_sub_id}" \
--resource-group "${tf_rg_name}" \
--account-name "${tf_sa_name}" \
--account-key "${sa_key}" \
--output none
echo "Storage account and container for Terraform state created!"
else
echo "Storage Account already exists"
fi

# generate a config.vars file
. "${BASH_SOURCE%/*}"/generate_vars.sh "${tf_config_subid}" "${enclave_name}" "${tf_sub_id}" "${tf_name}" "${tf_dir}"
2 changes: 1 addition & 1 deletion scripts/mlz_config_validate.sh → scripts/config/config_validate.sh
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

PGM=$(basename "${0}")

if [[ "${PGM}" == "mlz_config_validate" && "$#" -lt 1 ]]; then
if [[ "$#" -lt 1 ]]; then
echo "${0}: Validates the existence of resources required to run Terraform init and apply scripts using a variables file for input"
echo "usage: ${PGM} <terraform configuration directory>"
exit 1
Expand Down
63 changes: 63 additions & 0 deletions scripts/config/generate_names.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#!/bin/bash
#
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
#
#

error_log() {
echo "${1}" 1>&2;
}

usage() {
echo "${0}: Generate MLZ resource names"
error_log "usage: ${0} <mlz config subscription ID> <enclave name> <optional tf sub id> <optional tf name>"
}

if [[ "$#" -lt 2 ]]; then
usage
exit 1
fi

mlz_sub_id_raw=$1
mlz_enclave_name_raw=$2

tf_sub_id_raw=${3:-notset}
tf_name_raw=${4:-notset}

# remove hyphens for resource naming restrictions
# in the future, do more cleansing
mlz_sub_id_clean="${mlz_sub_id_raw//-}"
mlz_enclave_name="${mlz_enclave_name_raw//-}"

# Universal names
export container_name="tfstate"

# MLZ naming patterns
mlz_prefix="mlz-tf"
mlz_sp_name_full="sp-${mlz_prefix}-${mlz_enclave_name}"
mlz_sa_name_full="mlztfsa${mlz_enclave_name}${mlz_sub_id_clean}"
mlz_kv_name_full="mlzkv${mlz_enclave_name}${mlz_sub_id_clean}"

# Name MLZ config resources
export mlz_rg_name="rg-${mlz_prefix}-${mlz_enclave_name}"
export mlz_sp_name="${mlz_sp_name_full}"
export mlz_sp_kv_name="${mlz_sp_name_full}-clientid"
export mlz_sp_kv_password="${mlz_sp_name_full}-pwd"
export mlz_sa_name="${mlz_sa_name_full:0:24}" # take the 24 characters of the storage account name
export mlz_kv_name="${mlz_kv_name_full:0:24}" # take the 24 characters of the key vault name

if [[ $tf_name_raw != "notset" ]]; then
# remove hyphens for resource naming restrictions
# in the future, do more cleansing
tf_sub_id_clean="${tf_sub_id_raw//-}"
tf_name="${tf_name_raw//-}"

# TF naming patterns
tf_prefix="tf-${tf_name}"
tf_sa_name_full="tfsa${tf_name}${mlz_enclave_name}${tf_sub_id_clean}"

# Name TF config resources
export tf_rg_name="rg-${tf_prefix}-${mlz_enclave_name}"
export tf_sa_name="${tf_sa_name_full:0:24}" # take the 24 characters of the storage account name
fi
53 changes: 53 additions & 0 deletions scripts/config/generate_vars.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/bin/bash
#
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
#
# shellcheck disable=SC1090,SC1091,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.
#
# Generate a config.vars file at a given Terraform directory

error_log() {
echo "${1}" 1>&2;
}

usage() {
echo "${0}: Generate a config.vars file at a given Terraform directory"
error_log "usage: ${0} <mlz config subscription ID> <enclave name> <tf sub id> <tf name> <tf dir>"
}

if [[ "$#" -lt 5 ]]; then
usage
exit 1
fi

mlz_sub_id=$1
mlz_enclave_name=$2

tf_sub_id=${3}
tf_name=${4}
tf_dir=$(realpath "${5}")

# generate names
. "${BASH_SOURCE%/*}"/generate_names.sh "${mlz_sub_id}" "${mlz_enclave_name}" "${tf_sub_id}" "${tf_name}"

# generate a config.vars file
config_vars="${tf_dir}/config.vars"
rm -f "$config_vars"
touch "$config_vars"
{
echo "tenant_id=${mlz_tenantid}"
echo "mlz_cfg_sub_id=${tf_config_subid}"
echo "mlz_cfg_kv_name=${mlz_kv_name}"
echo "sub_id=${tf_sub_id}"
echo "enclave=${mlz_enclave_name}"
echo "location=${location}"
echo "tf_be_rg_name=${tf_rg_name}"
echo "tf_be_sa_name=${tf_sa_name}"
echo "sp_client_id_secret_name=${mlz_sp_kv_name}"
echo "sp_client_pwd_secret_name=${mlz_sp_kv_password}"
echo "environment=${tf_environment}"
echo "container_name=${container_name}"
} >> "$config_vars"
112 changes: 112 additions & 0 deletions scripts/config/mlz_config_create.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#!/bin/bash
#
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
#
# shellcheck disable=SC1090,SC1091,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 MLZ backend config resources

error_log() {
echo "${1}" 1>&2;
}

usage() {
echo "${0}: Create MLZ config resources"
error_log "usage: ${0} <mlz tf config vars> <enclave name> <location>"
}

if [[ "$#" -lt 3 ]]; then
usage
exit 1
fi

mlz_tf_cfg=$(realpath "${1}")
enclave_name=$2
location=$3

# Source variables
. "${mlz_tf_cfg}"

# generate MLZ configuration names
. "${BASH_SOURCE%/*}"/generate_names.sh "${tf_config_subid}" "${enclave_name}"

# Create Azure AD application registration and Service Principal
echo "Verifying Service Principal is unique (${mlz_sp_name})"
if [[ -z $(az ad sp list --filter "displayName eq '${mlz_sp_name}'" --query "[].displayName" -o tsv) ]];then
echo "Service Principal does not exist...creating"
sp_pwd=$(az ad sp create-for-rbac \
--name "http://${mlz_sp_name}" \
--role Contributor \
--scopes "/subscriptions/${tf_config_subid}" "/subscriptions/${mlz_saca_subid}" "/subscriptions/${mlz_tier0_subid}" "/subscriptions/${mlz_tier1_subid}" "/subscriptions/${mlz_tier2_subid}" \
--query password \
--output tsv)
else
error_log "Service Principal named ${mlz_sp_name} already exists. This must be a unique Service Principal for your use only. Try again with a new enclave name. Exiting script."
exit 1
fi

# Get Service Principal AppId
sp_clientid=$(az ad sp show \
--id "http://${mlz_sp_name}" \
--query appId \
--output tsv)

# Get Service Principal ObjectId
sp_objid=$(az ad sp show \
--id "http://${mlz_sp_name}" \
--query objectId \
--output tsv)

# Validate or create Terraform Config resource group
if [[ -z $(az group show --name "${mlz_rg_name}" --subscription "${tf_config_subid}" --query name --output tsv) ]];then
echo "Resource Group does not exist...creating resource group ${mlz_rg_name}"
az group create \
--subscription "${tf_config_subid}" \
--location "${location}" \
--name "${mlz_rg_name}"
else
echo "Resource Group already exists...getting resource group"
fi

# Create Key Vault
if [[ -z $(az keyvault show --name "${mlz_kv_name}" --subscription "${tf_config_subid}" --query name --output tsv) ]];then
echo "Key Vault ${mlz_kv_name} does not exist...creating Key Vault"
az keyvault create \
--name "${mlz_kv_name}" \
--subscription "${tf_config_subid}" \
--resource-group "${mlz_rg_name}" \
--location "${location}" \
--output none
echo "Key Vault ${mlz_kv_name} created!"
fi

# Create Key Vault Access Policy for Service Principal
echo "Setting Access Policy for Service Principal..."
az keyvault set-policy \
--name "${mlz_kv_name}" \
--subscription "${tf_config_subid}" \
--resource-group "${mlz_rg_name}" \
--object-id "${sp_objid}" \
--secret-permissions get list set \
--output none
echo "Access Policy for Service Principal set!"

# Set Key Vault Secrets
echo "Updating KeyVault with Service Principal secrets..."
az keyvault secret set \
--name "${mlz_sp_kv_password}" \
--subscription "${tf_config_subid}" \
--vault-name "${mlz_kv_name}" \
--value "${sp_pwd}" \
--output none

az keyvault secret set \
--name "${mlz_sp_kv_name}" \
--subscription "${tf_config_subid}" \
--vault-name "${mlz_kv_name}" \
--value "${sp_clientid}" \
--output none
echo "KeyVault updated with Service Principal secrets!"
4 changes: 2 additions & 2 deletions scripts/destroy_terraform.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ plugin_dir="$(dirname "$(dirname "$(realpath "$0")")")/src/provider_cache"
. "${BASH_SOURCE%/*}"/util/checkforterraform.sh

# Validate necessary Azure resources exist
. "${BASH_SOURCE%/*}"/mlz_config_validate.sh "${tf_dir}"
. "${BASH_SOURCE%/*}"/config/config_validate.sh "${tf_dir}"

# Get the .tfvars file matching the terraform directory name
if [[ ! -f "${tfvars}" ]]
Expand Down Expand Up @@ -114,4 +114,4 @@ terraform destroy \
-var-file="${globalvars}" \
-var-file="${tfvars}" \
-var "mlz_clientid=${client_id}" \
-var "mlz_clientsecret=${client_secret}"
-var "mlz_clientsecret=${client_secret}"
2 changes: 1 addition & 1 deletion scripts/init_terraform.sh
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ plugin_dir="$(dirname "$(dirname "$(realpath "$0")")")/src/provider_cache"
. "${BASH_SOURCE%/*}"/util/checkforterraform.sh

# Validate necessary Azure resources exist
. "${BASH_SOURCE%/*}"/mlz_config_validate.sh "${tf_dir}"
. "${BASH_SOURCE%/*}"/config/config_validate.sh "${tf_dir}"

# Get the .tfvars file matching the terraform directory name
if [[ ! -f "${tfvars}" ]]
Expand Down
Loading

0 comments on commit 95d631f

Please sign in to comment.