From 507efda4f4e74f15c94dc86778e7379bb2d0c3fc Mon Sep 17 00:00:00 2001 From: Chris Bednarski Date: Fri, 4 Mar 2016 01:22:20 -0800 Subject: [PATCH] Finalized azure-setup for creating all of the requisite resources in the target subscription --- contrib/azure-setup.sh | 181 +++++++++++++++++++++++++++++++++-------- 1 file changed, 149 insertions(+), 32 deletions(-) mode change 100644 => 100755 contrib/azure-setup.sh diff --git a/contrib/azure-setup.sh b/contrib/azure-setup.sh old mode 100644 new mode 100755 index 388020722..917e94995 --- a/contrib/azure-setup.sh +++ b/contrib/azure-setup.sh @@ -1,40 +1,43 @@ #!/usr/bin/env bash set -e -AZURE_APP_NAME= -AZURE_RESOURCE_GROUP= -AZURE_STORAGE_ACCOUNT= -AZURE_APPLICATION_NAME= -AZURE_APPLICATION_URL= +meta_name= +azure_client_id= # Derived from application after creation +azure_client_name= # Application name +azure_client_secret= # Application password +azure_group_name= +azure_storage_name= +azure_subscription_id= # Derived from the account after login +azure_tenant_id= # Derived from the account after login showhelp() { + echo "azure-setup" echo "" - echo " azure-setup helps automate setting up an Azure account for packer builds" + echo " azure-setup helps you generate packer credentials for Azure" echo "" - echo " The script walks through the process of creating a resource group," - echo " storage account, application, service principal, and permissions" - echo " and then creates the account and shows you the identifiers you need" - echo " to configure packer." + echo " The script creates a resource group, storage account, application" + echo " (client), service principal, and permissions and displays a snippet" + echo " for use in your packer templates." echo "" - echo " azure-setup is meant to be run interactively and will prompt you" - echo " for input. Also, it assumes you will run this against an account" - echo " that has not previously been configured, or that you are OK with" - echo " creating all new resources in Azure. If you want to skip or" - echo " customize these steps, please use the azure-cli directly." + echo " For simplicity we make a lot of assumptions and choose reasonable" + echo " defaults. If you want more control over what happens, please use" + echo " the azure-cli directly." echo "" - echo " If the script fails partway through you will have to clean up the" - echo " lingering resources yourself." + echo " Note that you must already have an Azure account, username," + echo " password, and subscription. You can create those here:" + echo "" + echo " - https://account.windowsazure.com/" echo "" echo "REQUIREMENTS" echo "" - echo " You must install the azure-cli from" - echo " https://azure.microsoft.com/en-us/documentation/articles/xplat-cli-install/" - echo " and jq from https://stedolan.github.io/jq/" + echo " - azure-cli" + echo " - jq" echo "" - echo " azure-setup will verify these tools are available before starting" + echo " Use the requirements command (below) for more info." echo "" echo "USAGE" echo "" + echo " ./azure-setup.sh requirements" echo " ./azure-setup.sh setup" echo "" } @@ -65,21 +68,135 @@ requirements() { fi } -askResourceGroup() { - echo -n "Choose a name for the resource" - read +askSubscription() { + azure account list + echo "" + echo "Please enter the Id of the account you wish to use. If you do not see" + echo "a valid account in the list press Ctrl+C to abort and create one." + echo "If you leave this blank we will use the Current account." + echo -n "> " + read azure_subscription_id + if [ "$azure_subscription_id" != "" ]; then + azure account set $azure_subscription_id + else + azure_subscription_id=$(azure account show --json | jq -r .[].id) + fi + azure_tenant_id=$(azure account show --json | jq -r .[].tenantId) + echo "Using subscription_id: $azure_subscription_id" + echo "Using tenant_id: $azure_tenant_id" +} + +askName() { + echo "" + echo "Choose a name for your resource group, storage account, and client" + echo "client. This is arbitrary, but it must not already be in use by" + echo "any of those resources. ALPHANUMERIC ONLY. Ex: mypackerbuild" + echo -n "> " + read meta_name +} + +askSecret() { + echo "" + echo "Enter a secret for your application. We recommend generating one with" + echo "openssl rand -base64 24. If you leave this blank we will attempt to" + echo "generate one for you using openssl. THIS WILL BE SHOWN IN PLAINTEXT." + echo "Ex: mypackersecret8734" + echo -n "> " + read azure_client_secret + if [ "$azure_client_secret" = "" ]; then + azure_client_secret=$(openssl rand -base64 24) + if [ $? -ne 0 ]; then + echo "Error generating secret" + exit 1 + fi + echo "Generated client_secret: $azure_client_secret" + fi +} + +createResourceGroup() { + echo "==> Creating resource group" + azure group create -n $meta_name -l westus + if [ $? -eq 0 ]; then + azure_group_name=$meta_name + else + echo "Error creating resource group: $meta_name" + exit 1 + fi +} + +createStorageAccount() { + echo "==> Creating storage account" + azure storage account create -g $meta_name -l westus --type LRS $meta_name + if [ $? -eq 0 ]; then + azure_storage_name=$meta_name + else + echo "Error creating storage account: $meta_name" + exit 1 + fi +} + +createApplication() { + echo "==> Creating application" + azure_client_id=$(azure ad app create -n $meta_name -i http://$meta_name --home-page http://$meta_name -p $azure_client_secret --json | jq -r .appId) + if [ $? -ne 0 ]; then + echo "Error creating application: $meta_name @ http://$meta_name" + exit 1 + fi +} + +createServicePrinciple() { + echo "==> Creating service principal" + azure ad sp create $azure_client_id + if [ $? -ne 0 ]; then + echo "Error creating service principal: $azure_client_id" + exit 1 + fi +} + +createPermissions() { + echo "==> Creating permissions" + azure role assignment create -o "Owner" --spn http://$meta_name -c /subscriptions/$azure_subscription_id + # We want to use this more conservative scope but it does not work with the + # current implementation which uses temporary resource groups + # azure role assignment create --spn http://$meta_name -g $azure_group_name -o "API Management Service Contributor" + if [ $? -ne 0 ]; then + echo "Error creating permissions for: http://$meta_name" + exit 1 + fi +} + +showConfigs() { + echo "" + echo "Use the following configuration for your packer template:" + echo "" + echo " \"tenant_id\": \"$azure_tenant_id\"," + echo " \"subscription_id\": \"$azure_subscription_id\"," + echo " \"client_id\": \"$azure_client_id\"," + echo " \"client_secret\": \"$azure_client_secret\"," + echo " \"resource_group_name\": \"$azure_group_name\"," + echo " \"storage_account\": \"$azure_storage_name\"," + echo "" } setup() { requirements - echo "" - echo "Note: Please only use alphanumeric names for Azure resources. For" - echo "example:" - echo "" - echo " Good: packertest" - echo " Bad: packer-test" - echo "" - + + azure login + + askSubscription + askName + askSecret + + createResourceGroup + createStorageAccount + createApplication + createServicePrinciple + # It seems that if we continue to the next step too quickly this resource + # is not actually available, so let's wait a few seconds. + sleep 5 + createPermissions + + showConfigs } case "$1" in