diff --git a/README.md b/README.md index 29f7ebd..49d1670 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,150 @@ +<<<<<<< HEAD + +# Setup + +The artifacts used to deploy this project include bash scripts and Terraform templates. The sections below provide guidance to deploy this project into your Azure environment. + +> The setup instructions below assume the following requirements: +> - bash v4.0 (or newer) +> - **NOTE FOR MAC!** The default version of bash installed on Mac is older than 4.0. Be sure to update bash using brew before executing the script. Instructions to update bash can be found [here](http://macappstore.org/bash/). +> - Terraform v0.11.13 (or newer) + + +## Setup the Azure Container Registry and Service Principals + +1. Open a bash command prompt. +2. Navigate to the `./setup` folder. +3. Run `acr-sp-init.sh`. For example, the command below will provdision an Azure Container Registry (ACR) in East US and configure the two service principals in Azure Active Directory; one with AcrPush permission and another with AcrPull permission scoped to the ACR. The company name parameter ( `-c` ) is used to construct the name of the resource group, ACR, and service principals. + + ``` bash + $ ./acr-sp-init.sh -c Cobalt -l eastus + ``` + + > Note: The script configures service principals in Azure AD and therefore requires elevated privileges. As such, it is recommended that an interactive user with permissions to configure Azure AD run the script. + + +## Setup Shared / Core Infrastructure + +### Requirements + +- Azure Subscription User (with deployment rights) +- [Terraform](https://www.terraform.io/downloads.html) + +### Resources + +The following respources will be deployed +- Azure Resource Group + +### Deployment + +1. Authenticate using your Azure Principal or an Azure account with privileges to deploy resource groups. + +``` bash +$ az login +``` + +2. Execute the following commands: + +``` bash +$ cd ./shared +$ terraform init +$ terraform apply +``` + +### Environmental Variables + +To stop the command line from prompting questions use a .env file with the following environmental variables: + +``` +export TF_VAR_app_name=cblt +export TF_VAR_org=cse +export TF_VAR_env=dev +export TF_VAR_location=eastus +``` + +After saving the file set environment using: + +``` bash +. .env +``` + +Alternative use the variable.tf files in the directories and add the default key on the file as shown on the example below: + +``` json +variable "location" { + type = "string" + description = "The name of the target location" + default = "eastus" +} +variable "env" { + type = "string", + description = "The short name of the target env (i.e. dev, staging, or prod)" + defailt = "dev" +} +variable "org" { + type = "string", + description = "The short name of the organization" + default = "cse" +} +variable "app_name" { + type = "string", + description = "The short name of the application" + default = "cblt" +} + +``` + +## Setup Application Infrastructure + +> Coming soon! + + +# Contributing + +This project welcomes contributions and suggestions. Most contributions require you to agree to a +Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us +the rights to use your contribution. For details, visit https://cla.microsoft.com. + +When you submit a pull request, a CLA-bot will automatically determine whether you need to provide +a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions +provided by the bot. You will only need to do this once across all repos using our CLA. + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or +contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. +======= + +# Setup + +The artifacts used to deploy this project include bash scripts and Terraform templates. The sections below provide guidance to deploy this project into your Azure environment. + +> The setup instructions below assume the following requirements: +> - bash v4.0 (or newer) +> - **NOTE FOR MAC!** The default version of bash installed on Mac is older than 4.0. Be sure to update bash using brew before executing the script. Instructions to update bash can be found [here](http://macappstore.org/bash/). +> - Terraform v0.11.13 (or newer) + + +## Setup the Azure Container Registry and Service Principals + +1. Open a bash command prompt. +2. Navigate to the `./setup` folder. +3. Run `acr-sp-init.sh`. For example, the command below will provdision an Azure Container Registry (ACR) in East US and configure the two service principals in Azure Active Directory; one with AcrPush permission and another with AcrPull permission scoped to the ACR. The company name parameter ( `-c` ) is used to construct the name of the resource group, ACR, and service principals. + + ``` bash + $ ./acr-sp-init.sh -c Cobalt -l eastus + ``` + + > Note: The script configures service principals in Azure AD and therefore requires elevated privileges. As such, it is recommended that an interactive user with permissions to configure Azure AD run the script. + + +## Setup Shared / Core Infrastructure + +> Coming soon! + +## Setup Application Infrastructure + +> Coming soon! + # Contributing @@ -12,3 +159,4 @@ provided by the bot. You will only need to do this once across all repos using o This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. +>>>>>>> master diff --git a/setup/acr-sp-init.sh b/setup/acr-sp-init.sh new file mode 100755 index 0000000..42f13c9 --- /dev/null +++ b/setup/acr-sp-init.sh @@ -0,0 +1,141 @@ +#!/bin/bash -e + +while getopts "c:l:" opt; do + case $opt in + c) + # Company name + company=$OPTARG + ;; + l) + # Location/region where resource group will deploy to + location=$OPTARG + ;; + esac +done + +# If user did not provide required parameters then show usage. +[[ $# -eq 0 || -z $company || -z $location ]] && +{ + echo "Usage:"; + echo " $0 -c -l "; + echo " Use \"az account list-locations --query '[].name'\" to list supported regions for a subscription.'" + echo ""; + echo "Example:"; + echo " $0 -c contoso -l eastus"; + exit 1; +} + +# Convert to lowercase, remove whitespace, and trim lenght if needed. +location=${location// /} +location=${location,,} + +company=${company// /} +company=${company,,} +company=${company:0:8} + +# Translate location to an abbreviated location code. +locationCode="" +declare -A locationCodes=( + # Asia + ["eastasia"]="asea" + ["southeastasia"]="assw" + + # Australia + ["australiaeast"]="auea" + ["australiasoutheast"]="ause" + + # Brazil + ["brazilsouth"]="brso" + + # Canada + ["canadacentral"]="cace" + ["canadaeast"]="caea" + ["uksouth"]="ukso" + ["ukwest"]="ukwe" + ["koreacentral"]="koce" + ["koreasouth"]="koso" + ["francecentral"]="frce" + ["francesouth"]="frso" + ["australiacentral"]="auce" + ["australiacentral2"]="auc2" + ["southafricanorth"]="sano" + ["southafricawest"]="sawe" + + # Europe + ["northeurope"]="euno" + ["westeurope"]="euwe" + + # India + ["southindia"]="inso" + ["centralindia"]="ince" + ["westindia"]="inwe" + + # Japan + ["japanwest"]="jawe" + ["japaneast"]="jaea" + + # US + ["centralus"]="usce" + ["eastus"]="usea" + ["eastus2"]="use2" + ["westus"]="uswe" + ["westus2"]="usw2" + ["northcentralus"]="usnc" + ["southcentralus"]="ussc" + ["westcentralus"]="uswc" +) + +locationCode=${locationCodes[$location]} + +[[ -z ${locationCode} ]] && { + echo "Invalid value '${location}' for location parameter."; + exit 1; +} + +# Authenticate user. +az login + +# Create the resource group. +rgName="acr-${locationCode}-${company}" +az group create --name $rgName --location $location + +# Create the container registry. +acrName=${rgName//-/} +acrId=$(az acr create --resource-group $rgName --name $acrName --sku Standard --query id) +acrId="${acrId//\"}" +# ToDo: Should parameterize 'sku' in the future + +# Used to find/create service principals and role assignments to ACR. +declare -A spAcrNameAndRole=( + ["http://acr-${company}-pull"]="AcrPull" + ["http://acr-${company}-push"]="AcrPush" +) + +for spName in ${!spAcrNameAndRole[@]} +do + # Get the appId of the service principal if it already exists. + spAppId="" + spAppId=$(az ad sp show --id ${spName} --query appId || true) + spAppId="${spAppId//\"}" + + # Create a new service principal if it doesn't already exist. + [[ -z ${spAppId} ]] && { + echo "Creating service principal '${spName}'." + az ad sp create-for-rbac --name $spName --skip-assignment + + echo "Waiting for service principal '${spName}' to propagate in Azure AD." + sleep 20s + } + + # Get the role assignment scoped to the ACR for the service principal if it already exists. + roleAssignment="" + roleAssignment=$(az role assignment list --assignee ${spName} --scope ${acrId} --role ${spAcrNameAndRole[$spName]} --query 'length(@)') + + # Create a new role assignment if it doesn't already exist. + [[ $roleAssignment -eq 0 ]] && { + echo "Creating role assignment for service principal '${spName}'." + az role assignment create --assignee $spName --scope $acrId --role ${spAcrNameAndRole[$spName]} + } +done + +echo "Successfully completed" diff --git a/shared/README.md b/shared/README.md index 58c7a20..3984e02 100644 --- a/shared/README.md +++ b/shared/README.md @@ -1,3 +1,4 @@ + # Resource deployment ## Requirements @@ -39,7 +40,19 @@ $ terraform apply To stop the command line from prompting questions use a .env file with the following environmental variables: ``` -export TF_VAR_resource_group_location=eastus -export TF_VAR_env=prod -export TF_VAR_org=myorg +export TF_VAR_location=eastus +export TF_VAR_company=myCompany +``` + +After saving the file set environment using: + +``` bash +. .env +``` + +Alternatively, use the cluster.tfvars file to set parameter values as shown below: + +``` +location="esatus" +company="myCompany" ``` diff --git a/shared/azure/provider/main.tf b/shared/azure/provider/main.tf new file mode 100644 index 0000000..0143636 --- /dev/null +++ b/shared/azure/provider/main.tf @@ -0,0 +1,11 @@ +provider "azurerm" { + version = "~>1.21.0" +} + +provider "null" { + version = "~>2.0.0" +} + +terraform { + required_version = "~> 0.11.11" +} diff --git a/shared/main.tf b/shared/main.tf index 0114f56..d8301f0 100644 --- a/shared/main.tf +++ b/shared/main.tf @@ -10,55 +10,54 @@ terraform { locals { location_suffixes = { - eastasia = "asea", - southeastasia = "assw", - centralus = "usce", - eastus = "usea", - eastus2 = "use2", - westus = "uswe", - westus2 = "usw2", - northcentralus = "usnc", - southcentralus = "ussc", - westcentralus = "uswc", - northeurope = "euno", - westeurope = "euwe", - japanwest = "jawe", - japaneast = "jaea", - brazilsouth = "brso", - australiaeast = "auea", - australiasoutheast = "ause", - southindia = "inso", - centralindia = "ince", - westindia = "inwe", - canadacentral = "cace", - canadaeast = "caea", - uksouth = "ukso", - ukwest = "ukwe", - koreacentral = "koce", - koreasouth = "koso", - francecentral = "frce", - francesouth = "frso", - australiacentral = "auce", - australiacentral2 = "auc2", - southafricanorth= "sano", - southafricawest = "sawe", - } + eastasia = "asea", + southeastasia = "assw", + centralus = "usce", + eastus = "usea", + eastus2 = "use2", + westus = "uswe", + westus2 = "usw2", + northcentralus = "usnc", + southcentralus = "ussc", + westcentralus = "uswc", + northeurope = "euno", + westeurope = "euwe", + japanwest = "jawe", + japaneast = "jaea", + brazilsouth = "brso", + australiaeast = "auea", + australiasoutheast = "ause", + southindia = "inso", + centralindia = "ince", + westindia = "inwe", + canadacentral = "cace", + canadaeast = "caea", + uksouth = "ukso", + ukwest = "ukwe", + koreacentral = "koce", + koreasouth = "koso", + francecentral = "frce", + francesouth = "frso", + australiacentral = "auce", + australiacentral2 = "auc2", + southafricanorth = "sano", + southafricawest = "sawe", + } - location_suffix = "${local.location_suffixes[var.resource_group_location]}" - suffix = "-infra-${var.env}-${local.location_suffix}-${var.org}" + location_suffix = "${local.location_suffixes[var.location]}" } resource "azurerm_resource_group" "rg_core" { - name = "rg${local.suffix}" - location = "${var.resource_group_location}" + name = "core-${local.location_suffix}-rg-${var.company}" + location = "${var.location}" } data "azurerm_client_config" "current" {} resource "azurerm_key_vault" "keyvault" { - name = "kv${local.suffix}" - location = "${var.resource_group_location}" - resource_group_name = "rg${local.suffix}" + name = "core-${local.location_suffix}-kv-${var.company}" + location = "${var.location}" + resource_group_name = "${azurerm_resource_group.rg_core.name}" tenant_id = "${data.azurerm_client_config.current.tenant_id}" depends_on = ["azurerm_resource_group.rg_core"] diff --git a/shared/shared.tfvars b/shared/shared.tfvars index 937b0ef..ccd240f 100644 --- a/shared/shared.tfvars +++ b/shared/shared.tfvars @@ -1,4 +1,3 @@ -resource_group_location="" -env="" -org="" +location="" +company="" keyvault_sku="" diff --git a/shared/variables.tf b/shared/variables.tf index a56d544..ccae97e 100644 --- a/shared/variables.tf +++ b/shared/variables.tf @@ -1,16 +1,11 @@ -variable "resource_group_location" { +variable "location" { type = "string" description = "The name of the target location" default = "eastus" } -variable "env" { +variable "company" { type = "string", - description = "The short name of the target env (i.e. dev, staging, or prod)" - default = "dev" -} -variable "org" { - type = "string", - description = "The short name of the organization" + description = "The short name of the company/app" default = "msft" }