gopkg.in/mitchellh/packer.v1@v1.3.2/contrib/azure-setup.sh (about)

     1  #!/usr/bin/env bash
     2  set -e
     3  
     4  meta_name=
     5  azure_client_id=       # Derived from application after creation
     6  azure_client_name=     # Application name
     7  azure_client_secret=   # Application password
     8  azure_group_name=
     9  azure_storage_name=
    10  azure_subscription_id= # Derived from the account after login
    11  azure_tenant_id=       # Derived from the account after login
    12  location=
    13  azure_object_id=
    14  azureversion=
    15  create_sleep=10
    16  
    17  showhelp() {
    18      echo "azure-setup"
    19      echo ""
    20      echo "  azure-setup helps you generate packer credentials for azure"
    21      echo ""
    22      echo "  The script creates a resource group, storage account, application"
    23      echo "  (client), service principal, and permissions and displays a snippet"
    24      echo "  for use in your packer templates."
    25      echo ""
    26      echo "  For simplicity we make a lot of assumptions and choose reasonable"
    27      echo "  defaults. If you want more control over what happens, please use"
    28      echo "  the azure-cli directly."
    29      echo ""
    30      echo "  Note that you must already have an Azure account, username,"
    31      echo "  password, and subscription. You can create those here:"
    32      echo ""
    33      echo "  - https://account.windowsazure.com/"
    34      echo ""
    35      echo "REQUIREMENTS"
    36      echo ""
    37      echo "  - azure-cli"
    38      echo "  - jq"
    39      echo ""
    40      echo "  Use the requirements command (below) for more info."
    41      echo ""
    42      echo "USAGE"
    43      echo ""
    44      echo "  ./azure-setup.sh requirements"
    45      echo "  ./azure-setup.sh setup"
    46      echo ""
    47  }
    48  
    49  requirements() {
    50      found=0
    51  
    52      azureversion=$(az --version)
    53      if [ $? -eq 0 ]; then
    54          found=$((found + 1))
    55          echo "Found azure-cli version: $azureversion"
    56      else
    57          echo "azure-cli is missing. Please install azure-cli from"
    58          echo "https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest"
    59          echo "Alternatively, you can use the Cloud Shell https://docs.microsoft.com/en-us/azure/cloud-shell/overview right from the Azure Portal or even VS Code."
    60      fi
    61  
    62      jqversion=$(jq --version)
    63      if [ $? -eq 0 ]; then
    64          found=$((found + 1))
    65          echo "Found jq version: $jqversion"
    66      else
    67          echo "jq is missing. Please install jq from"
    68          echo "https://stedolan.github.io/jq/"
    69      fi
    70  
    71      if [ $found -lt 2 ]; then
    72          exit 1
    73      fi
    74  }
    75  
    76  askSubscription() {
    77      az account list -otable
    78      echo ""
    79      echo "Please enter the Id of the account you wish to use. If you do not see"
    80      echo "a valid account in the list press Ctrl+C to abort and create one."
    81      echo "If you leave this blank we will use the Current account."
    82      echo -n "> "
    83      read azure_subscription_id
    84  
    85      if [ "$azure_subscription_id" != "" ]; then
    86          az account set --subscription $azure_subscription_id
    87      else
    88          azure_subscription_id=$(az account list --output json | jq -r '.[] | select(.isDefault==true) | .id')
    89      fi
    90      azure_tenant_id=$(az account list --output json | jq -r '.[] | select(.id=="'$azure_subscription_id'") |  .tenantId')
    91      echo "Using subscription_id: $azure_subscription_id"
    92      echo "Using tenant_id: $azure_tenant_id"
    93  }
    94  
    95  askName() {
    96      echo ""
    97      echo "Choose a name for your resource group, storage account and client"
    98      echo "client. This is arbitrary, but it must not already be in use by"
    99      echo "any of those resources. ALPHANUMERIC ONLY. Ex: mypackerbuild"
   100      echo -n "> "
   101      read meta_name
   102  }
   103  
   104  askSecret() {
   105      echo ""
   106      echo "Enter a secret for your application. We recommend generating one with"
   107      echo "openssl rand -base64 24. If you leave this blank we will attempt to"
   108      echo "generate one for you using openssl. THIS WILL BE SHOWN IN PLAINTEXT."
   109      echo "Ex: mypackersecret8734"
   110      echo -n "> "
   111      read azure_client_secret
   112      if [ "$azure_client_secret" = "" ]; then
   113          azure_client_secret=$(openssl rand -base64 24)
   114          if [ $? -ne 0 ]; then
   115              echo "Error generating secret"
   116              exit 1
   117          fi
   118          echo "Generated client_secret: $azure_client_secret"
   119      fi
   120  }
   121  
   122  askLocation() {
   123      az account list-locations -otable
   124      echo ""
   125      echo "Choose which region your resource group and storage account will be created.  example: westus"
   126      echo -n "> "
   127      read location
   128  }
   129  
   130  createResourceGroup() {
   131      echo "==> Creating resource group"
   132      az group create -n $meta_name -l $location
   133      if [ $? -eq 0 ]; then
   134          azure_group_name=$meta_name
   135      else
   136          echo "Error creating resource group: $meta_name"
   137          return 1
   138      fi
   139  }
   140  
   141  createStorageAccount() {
   142      echo "==> Creating storage account"
   143      az storage account create --name $meta_name --resource-group $meta_name --location $location --kind Storage --sku Standard_LRS
   144      if [ $? -eq 0 ]; then
   145          azure_storage_name=$meta_name
   146      else
   147          echo "Error creating storage account: $meta_name"
   148          return 1
   149      fi
   150  }
   151  
   152  createApplication() {
   153      echo "==> Creating application"
   154      echo "==> Does application exist?"
   155      azure_client_id=$(az ad app list --output json | jq -r '.[] | select(.displayName | contains("'$meta_name'")) ')
   156  
   157      if [ "$azure_client_id" != "" ]; then
   158          echo "==> application already exist, grab appId"
   159          azure_client_id=$(az ad app list --output json | jq -r '.[] | select(.displayName | contains("'$meta_name'")) .appId')
   160      else
   161          echo "==> application does not exist"
   162          azure_client_id=$(az ad app create --display-name $meta_name --identifier-uris http://$meta_name --homepage http://$meta_name --password $azure_client_secret --output json | jq -r .appId)
   163      fi
   164  
   165      if [ $? -ne 0 ]; then
   166          echo "Error creating application: $meta_name @ http://$meta_name"
   167          return 1
   168      fi
   169  }
   170  
   171  createServicePrincipal() {
   172      echo "==> Creating service principal"
   173      azure_object_id=$(az ad sp create --id $azure_client_id --output json | jq -r .objectId)
   174      echo $azure_object_id "was selected."
   175  
   176      if [ $? -ne 0 ]; then
   177          echo "Error creating service principal: $azure_client_id"
   178          return 1
   179      fi
   180  }
   181  
   182  createPermissions() {
   183      echo "==> Creating permissions"
   184      az role assignment create --assignee $azure_object_id --role "Owner" --scope /subscriptions/$azure_subscription_id
   185      # If the user wants to use a more conservative scope, she can.  She must
   186      # configure the Azure builder to use build_resource_group_name.  The
   187      # easiest solution is subscription wide permission.
   188      # az role assignment create --spn http://$meta_name -g $azure_group_name -o "API Management Service Contributor"
   189      if [ $? -ne 0 ]; then
   190          echo "Error creating permissions for: http://$meta_name"
   191          return 1
   192      fi
   193  }
   194  
   195  showConfigs() {
   196      echo ""
   197      echo "Use the following configuration for your packer template:"
   198      echo ""
   199      echo "{"
   200      echo "      \"client_id\": \"$azure_client_id\","
   201      echo "      \"client_secret\": \"$azure_client_secret\","
   202      echo "      \"object_id\": \"$azure_object_id\","
   203      echo "      \"subscription_id\": \"$azure_subscription_id\","
   204      echo "      \"tenant_id\": \"$azure_tenant_id\","
   205      echo "      \"resource_group_name\": \"$azure_group_name\","
   206      echo "      \"storage_account\": \"$azure_storage_name\","
   207      echo "}"
   208      echo ""
   209  }
   210  
   211  doSleep() {
   212      local sleep_time=${PACKER_SLEEP_TIME-$create_sleep}
   213      echo ""
   214      echo "Sleeping for ${sleep_time} seconds to wait for resources to be "
   215      echo "created. If you get an error about a resource not existing, you can "
   216      echo "try increasing the amount of time we wait after creating resources "
   217      echo "by setting PACKER_SLEEP_TIME to something higher than the default."
   218      echo ""
   219      sleep $sleep_time
   220  }
   221  
   222  retryable() {
   223      n=0
   224      until [ $n -ge $1 ]
   225      do
   226          $2 && return 0
   227          echo "$2 failed. Retrying..."
   228          n=$[$n+1]
   229          doSleep
   230      done
   231      echo "$2 failed after $1 tries. Exiting."
   232      exit 1
   233  }
   234  
   235  
   236  setup() {
   237      requirements
   238  
   239      az login
   240  
   241      askSubscription
   242      askName
   243      askSecret
   244      askLocation
   245  
   246      # Some of the resources take a while to converge in the API. To make the
   247      # script more reliable we'll add a sleep after we create each resource.
   248  
   249      retryable 3 createResourceGroup
   250      retryable 3 createStorageAccount
   251      retryable 3 createApplication
   252      retryable 3 createServicePrincipal
   253      retryable 3 createPermissions
   254  
   255      showConfigs
   256  }
   257  
   258  case "$1" in
   259      requirements)
   260          requirements
   261          ;;
   262      setup)
   263          setup
   264          ;;
   265      *)
   266          showhelp
   267          ;;
   268  esac