#!/bin/bash -x # az-create-website - Author: Brent McConnell # # # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for # license information. # # Creates a website using a provided Resource Group and Azure Storage Acct. usage() { echo "`basename $0`" echo " Usage: " echo " -d : Domain name of website." echo " -g : Existing Resource group." echo " -s : Existing Storage account" echo " -n : Does not prompt to continue but will fail if DNS is not correct" exit 1 } # Catch any help requests for arg in "$@"; do case "$arg" in --help| -h) usage ;; esac done while getopts d:g:s:n option do case "${option}" in g) RG_NAME=${OPTARG};; d) DOMAIN_NAME=${OPTARG};; s) STOR_NAME=${OPTARG};; n) PROMPT=0;; *) usage;; : ) usage;; esac done shift "$(($OPTIND -1))" # Check to see if Domain was passed it at least if [ -z "$DOMAIN_NAME" ]; then usage exit 1 fi # Check to see if RG was passed in if [ -z "$STOR_NAME" ]; then usage exit 1 fi # Check to see if RG was passed in if [ -z "$RG_NAME" ]; then usage exit 1 fi # Does the domain name at least look valid VALID_NAME=$(echo $DOMAIN_NAME | perl -nle'print if m{(?=^.{5,254}$)(^(?:(?!\d+\.)[a-zA-Z0-9_\-]{1,63}\.?)+(?:[a-zA-Z]{2,})$)}') if [ -z "$VALID_NAME" ]; then echo "Domain name doesn't look valid to me" exit 1 fi read -r -d '' PROMPT_MESSAGE < $STOR_NAME.blob.core.windows.net www.$DOMAIN_NAME -> $STOR_NAME.azureedge.net [y/N]? EOF if [ -z "$PROMPT" ]; then read -p "$PROMPT_MESSAGE" ANSWER if ! [[ $ANSWER =~ [yY](es)* ]]; then echo "Please create these entries before continuing" exit 0 fi fi echo "Checking for required www.${STOR_NAME} and web.$STOR_NAME records in DNS" (host -t CNAME www.${DOMAIN_NAME} | grep "${STOR_NAME}.azureedge.net" && host -t CNAME web.${DOMAIN_NAME} | grep "${STOR_NAME}.blob.core.windows.net") || { echo "FATAL ERROR: " echo "====== Unable to locate web.${DOMAIN_NAME} or www.${DOMAIN_NAME} server entries in DNS" echo "====== Create a CNAME entry for web.${DOMAIN_NAME} and www.${DOMAIN_NAME} with your DNS provider" echo "====== web.${DOMAIN_NAME} should map to $STOR_NAME.blob.core.windows.net" echo "====== www.${DOMAIN_NAME} should map to $STOR_NAME.azureedge.net" exit 1 } echo "DNS CNAME Records Found!!" # Check if Resource Group has been passed in, if not we will create one echo "Checking Existing Resource Group" EXISTING_RG=`az group show -g $RG_NAME -o json | jq -r '.name'` if [ -z "$EXISTING_RG" ]; then echo "Resource group passed in does not exist" exit 1 fi echo "Cool... Resource Group exists" echo "Checking Existing Storage Account" EXISTING_SA=`az storage account show -g $RG_NAME -n $STOR_NAME -o json | jq -r '.name'` if [ -z "$EXISTING_SA" ]; then echo "ERROR: Storage account does not exist" exit 1 fi echo "Cool... Storage account exists" az storage account show -g $RG_NAME -n $STOR_NAME -o json --query kind | grep StorageV2 >/dev/null if [ $? -ne 0 ]; then echo "ERROR: Storage acct must be of kind StorageV2" exit 1 fi echo "Storage Account being used is $STOR_NAME" # Check Which Cloud WHICH_CLOUD=$(az cloud list --query "[].{Active:isActive, Name:name}[?Active==\`true\`]" -o tsv | awk '{print $2}') echo "Running against $WHICH_CLOUD" if [ -z "$AZURE_AUTH_LOCATION" ]; then echo "AZURE_AUTH_LOCATION not set. Looking for .azureauth file in $HOME as fallback." if [ -f "$HOME/.azureauth" ]; then echo "Using $HOME/.azureauth for authenticating REST calls" AZURE_AUTH_LOCATION=$HOME/.azureauth fi fi if [ -z "$AZURE_AUTH_LOCATION" ]; then echo "ERROR: AZURE_AUTH_LOCATION env variable or .azureauth file not found." echo " Use az ad sp create-for-rback --sdk-auth to create and store" exit 1 else if ! [ -f "$AZURE_AUTH_LOCATION" ]; then echo "$AZURE_AUTH_LOCATION does NOT exist. Ensure that AZURE_AUTH_ENVIRONMENT contains valid sp info" exit 1 fi fi clientId=$(cat $AZURE_AUTH_LOCATION | jq -e -r 'select(.clientId != null) | .clientId') subscriptionId=$(cat $AZURE_AUTH_LOCATION | jq -e -r 'select(.subscriptionId != null) | .subscriptionId') tenantId=$(cat $AZURE_AUTH_LOCATION | jq -e -r 'select(.tenantId != null) | .tenantId') secretKey=$(cat $AZURE_AUTH_LOCATION | jq -e -r 'select(.clientSecret != null) | .clientSecret') activeDirectoryEndpoint=$(cat $AZURE_AUTH_LOCATION | jq -e -r 'select(.activeDirectoryEndpointUrl != null) | .activeDirectoryEndpointUrl') resourceManagerEndpoint=$(cat $AZURE_AUTH_LOCATION | jq -e -r 'select(.resourceManagerEndpointUrl != null) | .resourceManagerEndpointUrl') #echo $activeDirectoryEndpoint #echo $resourceManagerEndpoint if [ -z "$clientId" ] || [ -z "$subscriptionId" ] || [ -z "$tenantId" ] || [ -z "$secretKey" ] ; then echo "File does not contain one or more of the following:" echo "clientId, subscriptionId, tenantId and/or clientSecret" exit 1 fi if [ $WHICH_CLOUD == 'AzureCloud' ]; then TLD="net" REGION="eastus" elif [ $WHICH_CLOUD == 'AzureUSGovernment' ]; then TLD="us" REGION="usgovvirginia" else echo "ERROR: Cloud Not Supported" exit 1 fi RESP=$(curl -s -X POST \ -d"grant_type=client_credentials&client_id=$clientId&client_secret=$secretKey&resource=$resourceManagerEndpoint" \ $activeDirectoryEndpoint/$tenantId/oauth2/token) TOKEN=$(echo $RESP | jq -r ".access_token") echo $TOKEN if [ -z "$TOKEN" ]; then echo "ERROR: Failed to get AUTH Token for REST calls" exit 1 fi echo "Setting storage account property for custom domain" az storage account update --name $STOR_NAME \ --custom-domain web.${DOMAIN_NAME} \ --resource-group $RG_NAME echo "Setting blob properties for static website" az storage blob service-properties update \ --account-name $STOR_NAME \ --static-website \ --404-document error.html \ --index-document index.html || exit 1 WEB_ENDPOINT=$(az storage account show --name $STOR_NAME \ --output json \ --query primaryEndpoints.web) echo "Web endpoint for storage account is $WEB_ENDPOINT" WEB_DOMAIN=$(echo "$WEB_ENDPOINT" | sed -e 's|^[^/]*//||' -e 's|/.*$||') if [ -z "$WEB_DOMAIN" ]; then echo "ERROR: Something horrible has happened and there isn't a web endpoint" exit 1 fi echo $WEB_DOMAIN echo "Creating Microsoft Standard CDN" az cdn profile create --resource-group $RG_NAME \ --name ${STOR_NAME}cdn \ --sku Standard_Microsoft || exit 1 # echo "Creating Premium Verizon CDN" # az cdn profile create --resource-group $RG_NAME \ # --name ${STOR_NAME}cdn \ # --sku Premium_Verizon || exit 1 echo "Creating Endpoint in CDN" az cdn endpoint create --name ${STOR_NAME} \ --profile-name ${STOR_NAME}cdn \ --origin $WEB_DOMAIN \ --resource-group $RG_NAME \ --origin-host-header $WEB_DOMAIN || exit 1 echo "Creating custom domain for endpoint" az cdn custom-domain create --endpoint-name ${STOR_NAME} \ --hostname www.$DOMAIN_NAME \ --name www \ --profile-name ${STOR_NAME}cdn \ --resource-group $RG_NAME echo "Enabling SSL. This will take about 8hrs" az cdn custom-domain enable-https --endpoint-name $STOR_NAME \ --name www \ --profile-name ${STOR_NAME}cdn \ --resource-group $RG_NAME || exit 1 echo "Creating Redirect rule for http to https" az cdn endpoint rule add \ -g $RG_NAME \ -n ${STOR_NAME} \ --profile-name ${STOR_NAME}cdn \ --order 1 \ --rule-name "redirect" \ --match-variable RequestScheme \ --operator Equal \ --match-values HTTPS \ --action-name "UrlRedirect" \ --redirect-protocol Https \ --redirect-type Moved