github.com/StackPointCloud/packer@v0.10.2-0.20180716202532-b28098e0f79b/website/source/docs/builders/azure-setup.html.md (about)

     1  ---
     2  description: |
     3      In order to build VMs in Azure, Packer needs various configuration options.
     4      These options and how to obtain them are documented on this page.
     5  layout: docs
     6  page_title: 'Setup - Azure - Builders'
     7  sidebar_current: 'docs-builders-azure-setup'
     8  ---
     9  
    10  # Authorizing Packer Builds in Azure
    11  
    12  In order to build VMs in Azure Packer needs 6 configuration options to be specified:
    13  
    14  -   `subscription_id` - UUID identifying your Azure subscription (where billing is handled)
    15  
    16  -   `client_id` - UUID identifying the Active Directory service principal that will run your Packer builds
    17  
    18  -   `client_secret` - service principal secret / password
    19  
    20  -   `resource_group_name` - name of the resource group where your VHD(s) will be stored
    21  
    22  -   `storage_account` - name of the storage account where your VHD(s) will be stored
    23  
    24  -&gt; Behind the scenes Packer uses the OAuth protocol to authenticate against Azure Active Directory and authorize requests to the Azure Service Management API. These topics are unnecessarily complicated so we will try to ignore them for the rest of this document.<br /><br />You do not need to understand how OAuth works in order to use Packer with Azure, though the Active Directory terms "service principal" and "role" will be useful for understanding Azure's access policies.
    25  
    26  In order to get all of the items above, you will need a username and password for your Azure account.
    27  
    28  ## Device Login
    29  
    30  Device login is an alternative way to authorize in Azure Packer. Device login only requires you to know your
    31  Subscription ID. (Device login is only supported for Linux based VMs.) Device login is intended for those who are first
    32  time users, and just want to ''kick the tires.'' We recommend the SPN approach if you intend to automate Packer.
    33  
    34  > Device login is for **interactive** builds, and SPN is **automated** builds.
    35  
    36  There are three pieces of information you must provide to enable device login mode.
    37  
    38  1.  SubscriptionID
    39  2.  Resource Group - parent resource group that Packer uses to build an image.
    40  3.  Storage Account - storage account where the image will be placed.
    41  
    42  > Device login mode is enabled by not setting client\_id and client\_secret.
    43  
    44  > Device login mode is for the Public and US Gov clouds only.
    45  
    46  The device login flow asks that you open a web browser, navigate to <http://aka.ms/devicelogin>, and input the supplied
    47  code. This authorizes the Packer for Azure application to act on your behalf. An OAuth token will be created, and stored
    48  in the user's home directory (~/.azure/packer/oauth-TenantID.json). This token is used if the token file exists, and it
    49  is refreshed as necessary. The token file prevents the need to continually execute the device login flow. Packer will ask
    50  for two device login auth, one for service management endpoint and another for accessing temp keyvault secrets that it creates.
    51  
    52  ## Install the Azure CLI
    53  
    54  To get the credentials above, we will need to install the Azure CLI. Please refer to Microsoft's official [installation guide](https://azure.microsoft.com/en-us/documentation/articles/xplat-cli-install/).
    55  
    56  -&gt; The guides below also use a tool called [`jq`](https://stedolan.github.io/jq/) to simplify the output from the Azure CLI, though this is optional. If you use homebrew you can simply `brew install node jq`.
    57  
    58  If you already have node.js installed you can use `npm` to install `azure-cli`:
    59  
    60  ``` shell
    61  $ npm install -g azure-cli --no-progress
    62  ```
    63  
    64  You can also use the Python-based Azure CLI in Docker. It also comes with `jq` pre-installed:
    65  
    66  ```shell
    67  $ docker run -it azuresdk/azure-cli-python
    68  ```
    69  
    70  As there are differences between the node.js client and the Python client, we've included commands for the Python client underneath each node.js command.
    71  
    72  ## Guided Setup
    73  
    74  The Packer project includes a [setup script](https://github.com/hashicorp/packer/blob/master/contrib/azure-setup.sh) that can help you setup your account. It uses an interactive bash script to log you into Azure, name your resources, and export your Packer configuration.
    75  
    76  ## Manual Setup
    77  
    78  If you want more control or the script does not work for you, you can also use the manual instructions below to setup your Azure account. You will need to manually keep track of the various account identifiers, resource names, and your service principal password.
    79  
    80  ### Identify Your Tenant and Subscription IDs
    81  
    82  Login using the Azure CLI
    83  
    84  ``` shell
    85  $ azure config mode arm
    86  $ azure login -u USERNAME
    87  ```
    88  
    89  If you're using the Python client:
    90  
    91  ```shell
    92  $ az login
    93  # To sign in, use a web browser to open the page https://aka.ms/devicelogin and enter the code CODE_PROVIDED to authenticate
    94  ```
    95  
    96  Once you've completed logging in, you should get a JSON array like the one below:
    97  
    98  ```shell
    99  [
   100    {
   101      "cloudName": "AzureCloud",
   102      "id": "$uuid",
   103      "isDefault": false,
   104      "name": "Pay-As-You-Go",
   105      "state": "Enabled",
   106      "tenantId": "$tenant_uuid",
   107      "user": {
   108        "name": "my_email@anywhere.com",
   109        "type": "user"
   110      }
   111    }
   112  ]
   113  
   114  ```
   115  Get your account information
   116  
   117  ``` shell
   118  $ azure account list --json | jq -r '.[].name'
   119  $ azure account set ACCOUNTNAME
   120  $ azure account show --json | jq -r ".[] | .id"
   121  ```
   122  
   123  Python:
   124  ``` shell
   125  $ az account set "$(az account list | jq -r '.[].name')"
   126  ```
   127  
   128  -&gt; Throughout this document when you see a command pipe to `jq` you may instead omit `--json` and everything after it, but the output will be more verbose. For example you can simply run `azure account list` instead.
   129  
   130  This will print out one line that look like this:
   131  
   132      4f562e88-8caf-421a-b4da-e3f6786c52ec
   133  
   134  This is your `subscription_id`. Note it for later.
   135  
   136  ### Create a Resource Group
   137  
   138  A [resource group](https://azure.microsoft.com/en-us/documentation/articles/resource-group-overview/#resource-groups) is used to organize related resources. Resource groups and storage accounts are tied to a location. To see available locations, run:
   139  
   140  ``` shell
   141  $ azure location list
   142  # ...
   143  
   144  $ azure group create -n GROUPNAME -l LOCATION
   145  ```
   146  
   147  Python:
   148  
   149  ```shell
   150  $ az group create -n GROUPNAME -l LOCATION
   151  ```
   152  
   153  Your storage account (below) will need to use the same `GROUPNAME` and `LOCATION`.
   154  
   155  ### Create a Storage Account
   156  
   157  We will need to create a storage account where your Packer artifacts will be stored. We will create a `LRS` storage account which is the least expensive price/GB at the time of writing.
   158  
   159  ``` shell
   160  $ azure storage account create \
   161    -g GROUPNAME \
   162    -l LOCATION \
   163    --sku-name LRS \
   164    --kind storage STORAGENAME
   165  ```
   166  
   167  Python:
   168  
   169  ```shell
   170  $ az storage account create -n STORAGENAME -g GROUPNAME -l LOCATION --sku Standard_LRS
   171  ```
   172  
   173  -&gt; `LRS` and `Standard_LRS` are meant as literal "LRS" or "Standard_LRS" and not as variables.
   174  
   175  Make sure that `GROUPNAME` and `LOCATION` are the same as above. Also, ensure that `GROUPNAME` is less than 24 characters long and contains only lowercase letters and numbers.
   176  
   177  ### Create an Application
   178  
   179  An application represents a way to authorize access to the Azure API. Note that you will need to specify a URL for your application (this is intended to be used for OAuth callbacks) but these do not actually need to be valid URLs.
   180  
   181  ``` shell
   182  $ azure ad app create \
   183    -n APPNAME \
   184    -i APPURL \
   185    --home-page APPURL \
   186    -p PASSWORD
   187  ```
   188  
   189  Python:
   190  
   191  ```shell
   192  az ad app create --display-name APPNAME --identifier-uris APPURL --homepage APPURL --password PASSWORD
   193  ```
   194  
   195  Password is your `client_secret` and can be anything you like. I recommend using `openssl rand -base64 24`.
   196  
   197  ### Create a Service Principal
   198  
   199  You cannot directly grant permissions to an application. Instead, you create a service principal associated with the application and assign permissions to the service principal.
   200  
   201  First, get the `APPID` for the application we just created.
   202  
   203  ``` shell
   204  $ azure ad app list --json \
   205    | jq '.[] | select(.displayName | contains("APPNAME")) | .appId'
   206  # ...
   207  
   208  $ azure ad sp create --applicationId APPID
   209  ```
   210  
   211  Python:
   212  
   213  ```shell
   214  $ id=$(az ad app list | jq -r '.[] | select(.displayName == "Packer") | .appId')
   215  $ az ad sp create --id "$id"
   216  ```
   217  
   218  ### Grant Permissions to Your Application
   219  
   220  Finally, we will associate the proper permissions with our application's service principal. We're going to assign the `Owner` role to our Packer application and change the scope to manage our whole subscription. (The `Owner` role can be scoped to a specific resource group to further reduce the scope of the account.) This allows Packer to create temporary resource groups for each build.
   221  
   222  ``` shell
   223  $ azure role assignment create \
   224    --spn APPURL \
   225    -o "Owner" \
   226    -c /subscriptions/SUBSCRIPTIONID
   227  ```
   228  
   229  Python:
   230  
   231  ```shell
   232  # NOTE: Trying to assign the role to the service principal by name directly yields a HTTP 400 error. See: https://github.com/Azure/azure-cli/issues/4911
   233  $ az role assignment create --assignee "$(az ad sp list | jq -r '.[] | select(.displayName == "APPNAME") | .objectId')" --role Owner
   234  ```
   235  
   236  There are a lot of pre-defined roles and you can define your own with more granular permissions, though this is out of scope. You can see a list of pre-configured roles via:
   237  
   238  ``` shell
   239  $ azure role list --json \
   240    | jq ".[] | {name:.Name, description:.Description}"
   241  ```
   242  
   243  ### Configuring Packer
   244  
   245  Now (finally) everything has been setup in Azure. Let's get our configuration keys together:
   246  
   247  Python:
   248  
   249  ```shell
   250  $ cat <<EOF
   251  > {
   252  >   "subscription_id": $(az account show | jq '.id'),
   253  >   "client_id": $(az ad app list | jq '.[] | select(.displayName == "Packer") | .appId'),
   254  >   "client_secret": "$password",
   255  >   "location": "$location",
   256  >   "tenant_id": $(az account show | jq '.tenantId')
   257  >   "object_id": $(az ad app list | jq '.[] | select(.displayName == "Packer") | .objectId')
   258  > }
   259  > EOF
   260  ```
   261  
   262  node.js:
   263  
   264  Get `subscription_id`:
   265  
   266  ``` shell
   267  $ azure account show --json \
   268    | jq ".[] | .id"
   269  ```
   270  
   271  Get `client_id`
   272  
   273  ``` shell
   274  $ azure ad app list --json \
   275    | jq '.[] | select(.displayName | contains("APPNAME")) | .appId'
   276  ```
   277  
   278  
   279  Get `client_secret`
   280  
   281  This cannot be retrieved. If you forgot this, you will have to delete and re-create your service principal and the associated permissions.
   282  
   283  Get `object_id` (OSTYpe=Windows only)
   284  
   285  ``` shell
   286  azure ad sp show -n CLIENT_ID
   287  ```
   288  
   289  Get `resource_group_name`
   290  
   291  ``` shell
   292  $ azure group list
   293  ```
   294  
   295  Get `storage_account`
   296  
   297  ``` shell
   298  $ azure storage account list
   299  ```