2016-03-04 00:46:51 -05:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
set -e
|
|
|
|
|
2016-03-04 04:22:20 -05:00
|
|
|
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
|
2016-08-16 08:53:23 -04:00
|
|
|
location=
|
2016-08-18 11:01:23 -04:00
|
|
|
azure_object_id=
|
2016-11-08 03:00:15 -05:00
|
|
|
azureversion=
|
2016-03-04 00:46:51 -05:00
|
|
|
|
|
|
|
showhelp() {
|
2016-03-04 04:22:20 -05:00
|
|
|
echo "azure-setup"
|
2016-03-04 00:46:51 -05:00
|
|
|
echo ""
|
2016-03-04 04:22:20 -05:00
|
|
|
echo " azure-setup helps you generate packer credentials for Azure"
|
2016-03-04 00:46:51 -05:00
|
|
|
echo ""
|
2016-03-04 04:22:20 -05:00
|
|
|
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."
|
2016-03-04 00:46:51 -05:00
|
|
|
echo ""
|
2016-03-04 04:22:20 -05:00
|
|
|
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."
|
2016-03-04 00:46:51 -05:00
|
|
|
echo ""
|
2016-03-04 04:22:20 -05:00
|
|
|
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/"
|
2016-03-04 00:46:51 -05:00
|
|
|
echo ""
|
|
|
|
echo "REQUIREMENTS"
|
|
|
|
echo ""
|
2016-03-04 04:22:20 -05:00
|
|
|
echo " - azure-cli"
|
|
|
|
echo " - jq"
|
2016-03-04 00:46:51 -05:00
|
|
|
echo ""
|
2016-03-04 04:22:20 -05:00
|
|
|
echo " Use the requirements command (below) for more info."
|
2016-03-04 00:46:51 -05:00
|
|
|
echo ""
|
|
|
|
echo "USAGE"
|
|
|
|
echo ""
|
2016-03-04 04:22:20 -05:00
|
|
|
echo " ./azure-setup.sh requirements"
|
2016-03-04 00:46:51 -05:00
|
|
|
echo " ./azure-setup.sh setup"
|
|
|
|
echo ""
|
|
|
|
}
|
|
|
|
|
|
|
|
requirements() {
|
|
|
|
found=0
|
|
|
|
|
|
|
|
azureversion=$(azure -v)
|
|
|
|
if [ $? -eq 0 ]; then
|
|
|
|
found=$((found + 1))
|
|
|
|
echo "Found azure-cli version: $azureversion"
|
|
|
|
else
|
|
|
|
echo "azure-cli is missing. Please install azure-cli from"
|
|
|
|
echo "https://azure.microsoft.com/en-us/documentation/articles/xplat-cli-install/"
|
|
|
|
fi
|
|
|
|
|
|
|
|
jqversion=$(jq --version)
|
|
|
|
if [ $? -eq 0 ]; then
|
|
|
|
found=$((found + 1))
|
|
|
|
echo "Found jq version: $jqversion"
|
|
|
|
else
|
|
|
|
echo "jq is missing. Please install jq from"
|
|
|
|
echo "https://stedolan.github.io/jq/"
|
|
|
|
fi
|
2016-11-08 02:14:15 -05:00
|
|
|
|
2016-03-04 00:46:51 -05:00
|
|
|
if [ $found -lt 2 ]; then
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2016-03-04 04:22:20 -05:00
|
|
|
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"
|
2016-03-04 00:46:51 -05:00
|
|
|
}
|
|
|
|
|
2016-03-04 04:22:20 -05:00
|
|
|
askName() {
|
2016-03-04 00:46:51 -05:00
|
|
|
echo ""
|
2016-08-18 11:01:23 -04:00
|
|
|
echo "Choose a name for your resource group, storage account and client"
|
2016-03-04 04:22:20 -05:00
|
|
|
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() {
|
2016-03-04 00:46:51 -05:00
|
|
|
echo ""
|
2016-03-04 04:22:20 -05:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2016-08-16 08:53:23 -04:00
|
|
|
askLocation() {
|
|
|
|
azure location list
|
|
|
|
echo ""
|
|
|
|
echo "Choose which region your resource group and storage account will be created."
|
|
|
|
echo -n "> "
|
|
|
|
read location
|
|
|
|
}
|
|
|
|
|
2016-03-04 04:22:20 -05:00
|
|
|
createResourceGroup() {
|
|
|
|
echo "==> Creating resource group"
|
2016-08-16 08:53:23 -04:00
|
|
|
azure group create -n $meta_name -l $location
|
2016-03-04 04:22:20 -05:00
|
|
|
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"
|
2016-08-16 08:53:23 -04:00
|
|
|
azure storage account create -g $meta_name -l $location --sku-name LRS --kind Storage $meta_name
|
2016-03-04 04:22:20 -05:00
|
|
|
if [ $? -eq 0 ]; then
|
|
|
|
azure_storage_name=$meta_name
|
|
|
|
else
|
|
|
|
echo "Error creating storage account: $meta_name"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2016-11-08 02:14:15 -05:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2016-11-06 19:15:25 -05:00
|
|
|
createServicePrincipal() {
|
2016-03-04 04:22:20 -05:00
|
|
|
echo "==> Creating service principal"
|
2016-11-08 03:00:15 -05:00
|
|
|
# Azure CLI 0.10.2 introduced a breaking change, where appId must be supplied with the -a switch
|
|
|
|
# prior version accepted appId as the only parameter without a switch
|
2016-11-08 03:09:23 -05:00
|
|
|
newer_syntax=false
|
2016-11-08 03:00:15 -05:00
|
|
|
IFS='.' read -ra azureversionsemver <<< "$azureversion"
|
2016-11-08 03:05:20 -05:00
|
|
|
if [ ${azureversionsemver[0]} -ge 0 ] && [ ${azureversionsemver[1]} -ge 10 ] && [ ${azureversionsemver[2]} -ge 2 ]; then
|
2016-11-08 03:09:23 -05:00
|
|
|
newer_syntax=true
|
2016-11-08 03:00:15 -05:00
|
|
|
fi
|
|
|
|
|
2016-11-08 03:02:31 -05:00
|
|
|
if [ "${newer_syntax}" = true ]; then
|
2016-11-08 03:20:45 -05:00
|
|
|
azure_object_id=$(azure ad sp create -a $azure_client_id --json | jq -r .objectId)
|
2016-11-08 03:00:15 -05:00
|
|
|
else
|
2016-11-08 03:20:45 -05:00
|
|
|
azure_object_id=$(azure ad sp create $azure_client_id --json | jq -r .objectId)
|
2016-11-08 03:00:15 -05:00
|
|
|
fi
|
|
|
|
|
2016-03-04 04:22:20 -05:00
|
|
|
if [ $? -ne 0 ]; then
|
|
|
|
echo "Error creating service principal: $azure_client_id"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
createPermissions() {
|
|
|
|
echo "==> Creating permissions"
|
2016-08-18 11:01:23 -04:00
|
|
|
azure role assignment create --objectId $azure_object_id -o "Owner" -c /subscriptions/$azure_subscription_id
|
2016-03-04 04:22:20 -05:00
|
|
|
# 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 ""
|
2016-08-18 11:01:23 -04:00
|
|
|
echo "{"
|
2016-03-04 04:22:20 -05:00
|
|
|
echo " \"client_id\": \"$azure_client_id\","
|
|
|
|
echo " \"client_secret\": \"$azure_client_secret\","
|
2016-08-18 11:01:23 -04:00
|
|
|
echo " \"object_id\": \"$azure_object_id\","
|
|
|
|
echo " \"subscription_id\": \"$azure_subscription_id\","
|
|
|
|
echo " \"tenant_id\": \"$azure_tenant_id\","
|
2016-03-04 04:22:20 -05:00
|
|
|
echo " \"resource_group_name\": \"$azure_group_name\","
|
|
|
|
echo " \"storage_account\": \"$azure_storage_name\","
|
2016-08-18 11:01:23 -04:00
|
|
|
echo "}"
|
2016-03-04 00:46:51 -05:00
|
|
|
echo ""
|
2016-03-04 04:22:20 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
setup() {
|
|
|
|
requirements
|
|
|
|
|
2016-03-14 20:20:29 -04:00
|
|
|
azure config mode arm
|
2016-03-04 04:22:20 -05:00
|
|
|
azure login
|
|
|
|
|
|
|
|
askSubscription
|
|
|
|
askName
|
|
|
|
askSecret
|
2016-08-16 08:53:23 -04:00
|
|
|
askLocation
|
2016-03-04 04:22:20 -05:00
|
|
|
|
2016-03-14 20:20:29 -04:00
|
|
|
# Some of the resources take a while to converge in the API. To make the
|
|
|
|
# script more reliable we'll add a sleep after we create each resource.
|
|
|
|
|
2016-03-04 04:22:20 -05:00
|
|
|
createResourceGroup
|
2016-03-14 20:20:29 -04:00
|
|
|
sleep 5
|
2016-03-04 04:22:20 -05:00
|
|
|
createStorageAccount
|
2016-03-14 20:20:29 -04:00
|
|
|
sleep 5
|
2016-11-08 02:18:10 -05:00
|
|
|
createApplication
|
|
|
|
sleep 5
|
2016-11-06 19:15:25 -05:00
|
|
|
createServicePrincipal
|
2016-03-04 04:22:20 -05:00
|
|
|
sleep 5
|
|
|
|
createPermissions
|
|
|
|
|
|
|
|
showConfigs
|
2016-03-04 00:46:51 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
case "$1" in
|
|
|
|
requirements)
|
|
|
|
requirements
|
|
|
|
;;
|
|
|
|
setup)
|
|
|
|
setup
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
showhelp
|
|
|
|
;;
|
|
|
|
esac
|