github.com/hashicorp/packer@v1.14.3/website/content/docs/templates/legacy_json_templates/user-variables.mdx (about)

     1  ---
     2  description: |
     3    The `variables` block contains parameterized values for your templates. Learn how to configure `variables` to improve a template's security, portability, and shareability.
     4  page_title: variables reference for JSON templates
     5  ---
     6  
     7  # `variables` reference for JSON templates
     8  
     9  This topic describes how to use user variables in Packer templates written in JSON.
    10  
    11  `@include 'from-1.5/legacy-json-warning.mdx'`
    12  
    13  ## Description
    14  
    15  The `variables` block lets you further configure a template with variables
    16  from the command-line, environment variables, Vault, or files. This lets you
    17  parameterize your templates so that you can keep secret tokens,
    18  environment-specific data, and other types of information out of your
    19  templates. This maximizes the portability of the template.
    20  
    21  Using user variables expects you to know how [configuration
    22  templates](/packer/docs/templates/legacy_json_templates/engine) work. If you don't know how
    23  configuration templates work yet, please read that page first.
    24  
    25  ## Usage
    26  
    27  In order to set a user variable, you must define it either within the
    28  `variables` section within your template, or using the command-line `-var` or
    29  `-var-file` flags.
    30  
    31  Even if you want a user variable to default to an empty string, it is best to
    32  explicitly define it. This explicitness helps reduce the time it takes for
    33  newcomers to understand what can be modified using variables in your template.
    34  
    35  The `variables` section is a key/value mapping of the user variable name to a
    36  default value. A default value can be the empty string. An example is shown
    37  below:
    38  
    39  ```json
    40  {
    41    "variables": {
    42      "aws_access_key": "",
    43      "aws_secret_key": ""
    44    },
    45  
    46    "builders": [
    47      {
    48        "type": "amazon-ebs",
    49        "access_key": "{{user `aws_access_key`}}",
    50        "secret_key": "{{user `aws_secret_key`}}"
    51        // ...
    52      }
    53    ]
    54  }
    55  ```
    56  
    57  In the above example, the template defines two user variables: `aws_access_key`
    58  and `aws_secret_key`. They default to empty values. Later, the variables are
    59  used within the builder we defined in order to configure the actual keys for
    60  the Amazon builder.
    61  
    62  If the default value is `null`, then the user variable will be _required_. This
    63  means that the user must specify a value for this variable or template
    64  validation will fail.
    65  
    66  User variables are used by calling the `{{user}}` function in the form of
    67  `{{user 'variable'}}`. This function can be used in _any value_ but `type`
    68  within the template: in builders, provisioners, _anywhere outside the `variables` section_.
    69  User variables are available globally within the rest of the template.
    70  
    71  ## Environment variables
    72  
    73  Environment variables can be used within your template using user variables.
    74  The `env` function is available _only_ within the default value of a user
    75  variable, allowing you to default a user variable to an environment variable.
    76  An example is shown below:
    77  
    78  ```json
    79  {
    80    "variables": {
    81      "my_secret": "{{env `MY_SECRET`}}"
    82    }
    83  }
    84  ```
    85  
    86  This will default "my_secret" to be the value of the "MY_SECRET" environment
    87  variable (or an empty string if it does not exist).
    88  
    89  -> **Why can't I use environment variables elsewhere?** User variables are
    90  the single source of configurable input to a template. We felt that having
    91  environment variables used _anywhere_ in a template would confuse the user
    92  about the possible inputs to a template. By allowing environment variables only
    93  within default values for user variables, user variables remain as the single
    94  source of input to a template that a user can easily discover using
    95  `packer inspect`.
    96  
    97  -> **Why can't I use `~` for home variable?** `~` is an special variable
    98  that is evaluated by shell during a variable expansion. As Packer doesn't run
    99  inside a shell, it won't expand `~`.
   100  
   101  ## Consul keys
   102  
   103  Consul keys can be used within your template using the `consul_key` function.
   104  This function is available _only_ within the default value of a user variable,
   105  for reasons similar to environment variables above.
   106  
   107  ```json
   108  {
   109    "variables": {
   110      "soft_versions": "{{ consul_key `my_image/softs_versions/next` }}"
   111    }
   112  }
   113  ```
   114  
   115  This will default `soft_versions` to the value of the key
   116  `my_image/softs_versions/next` in consul.
   117  
   118  The configuration for consul (address, tokens, ...) must be specified as
   119  environment variables, as specified in the
   120  [Documentation](/consul/docs/commands#environment-variables).
   121  
   122  ## Vault variables
   123  
   124  Packer can read secrets read from HashiCorp Vault and add them to your template as user variables. You can only use the `vault` function 
   125  in the default value of a user variable. This allows you to default a user variable to a Vault secret. Refer to the [Vault documentation](https://developer.hashicorp.com/vault/docs/secrets) for additional information about integrating with Vault secrets engines. 
   126  
   127  An example of using a v2 kv engine:
   128  
   129  If you store a value in vault using `vault kv put secret/hello foo=world`, you
   130  can access it using the following template engine:
   131  
   132  ```json
   133  {
   134    "variables": {
   135      "my_secret": "{{ vault `/secret/data/hello` `foo`}}"
   136    }
   137  }
   138  ```
   139  
   140  which will assign "my_secret": "world"
   141  
   142  An example of using a v1 kv engine:
   143  
   144  If you store a value in vault using:
   145  
   146      vault secrets enable -version=1 -path=secrets kv
   147      vault kv put secrets/hello foo=world
   148  
   149  You can access it using the following template engine:
   150  
   151      {
   152        "variables": {
   153          "VAULT_SECRETY_SECRET": "{{ vault `secrets/hello` `foo`}}"
   154        }
   155      }
   156  
   157  This example accesses the Vault path `secret/data/foo` and returns the value
   158  stored at the key `bar`, storing it as "my_secret".
   159  
   160  In order for this to work, you must set the environment variables `VAULT_TOKEN`
   161  and `VAULT_ADDR` to valid values.
   162  
   163  The api tool we use allows for more custom configuration of the Vault client via
   164  environment variables.
   165  
   166  The full list of available environment variables is:
   167  
   168  ```text
   169  "VAULT_ADDR"
   170  "VAULT_AGENT_ADDR"
   171  "VAULT_CACERT"
   172  "VAULT_CAPATH"
   173  "VAULT_CLIENT_CERT"
   174  "VAULT_CLIENT_KEY"
   175  "VAULT_CLIENT_TIMEOUT"
   176  "VAULT_SKIP_VERIFY"
   177  "VAULT_NAMESPACE"
   178  "VAULT_TLS_SERVER_NAME"
   179  "VAULT_WRAP_TTL"
   180  "VAULT_MAX_RETRIES"
   181  "VAULT_TOKEN"
   182  "VAULT_MFA"
   183  "VAULT_RATE_LIMIT"
   184  ```
   185  
   186  and detailed documentation for usage of each of those variables can be found
   187  [here](/vault/docs/commands#environment-variables).
   188  
   189  ## AWS Secrets Manager variables
   190  
   191  Secrets can be read from [AWS Secrets Manager](https://aws.amazon.com/secrets-manager/)
   192  and used within your template as user variables. The `aws_secretsmanager` function is
   193  available _only_ within the default value of a user variable, allowing you to default
   194  a user variable to an AWS Secrets Manager secret.
   195  
   196  ### Plaintext secrets
   197  
   198  ```json
   199  {
   200    "variables": {
   201      "password": "{{ aws_secretsmanager `globalpassword` }}"
   202    }
   203  }
   204  ```
   205  
   206  In the example above it is assumed that the secret `globalpassword` is not
   207  stored as a key pair but as a single non-JSON string value. Which the
   208  `aws_secretsmanager` function will return as a raw string.
   209  
   210  ### Single key secrets
   211  
   212  ```json
   213  {
   214    "variables": {
   215      "password": "{{ aws_secretsmanager `sample/app/password` }}"
   216    }
   217  }
   218  ```
   219  
   220  In the example above it is assumed that only one key is stored in
   221  `sample/app/password` if there are multiple keys stored in it then you need
   222  to indicate the specific key you want to fetch as shown below.
   223  
   224  ### Multiple key secrets
   225  
   226  ```json
   227  {
   228    "variables": {
   229      "db_password": "{{ aws_secretsmanager `sample/app/passwords` `db` }}",
   230      "api_key": "{{ aws_secretsmanager `sample/app/passwords` `api_key` }}"
   231    }
   232  }
   233  ```
   234  
   235  In order to use this function you have to configure valid AWS credentials using
   236  one of the following methods:
   237  
   238  - [Environment Variables](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html)
   239  - [CLI Configuration Files](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html)
   240  - [Container Credentials](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html)
   241  - [Instance Profile Credentials](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html)
   242  
   243  ## Use array values
   244  
   245  Some templates call for array values. You can use template variables for these,
   246  too. For example, the `amazon-ebs` builder has a configuration parameter called
   247  `ami_regions`, which takes an array of regions that it will copy the AMI to.
   248  You can parameterize this by using a variable that is a list of regions, joined
   249  by a `,`. For example:
   250  
   251  ```json
   252  {
   253    "variables": {
   254      "destination_regions": "us-west-1,us-west-2"
   255    },
   256    "builders": [
   257      {
   258        "ami_name": "packer-qs-{{timestamp}}",
   259        "instance_type": "t2.micro",
   260        "region": "us-east-1",
   261        "source_ami_filter": {
   262          "filters": {
   263            "name": "*ubuntu-xenial-16.04-amd64-server-*",
   264            "root-device-type": "ebs",
   265            "virtualization-type": "hvm"
   266          },
   267          "most_recent": true,
   268          "owners": ["099720109477"]
   269        },
   270        "ami_regions": "{{user `destination_regions`}}",
   271        "ssh_username": "ubuntu",
   272        "type": "amazon-ebs"
   273      }
   274    ]
   275  }
   276  ```
   277  
   278  ## Set variables
   279  
   280  Now that we covered how to define and use user variables within a template, the
   281  next important point is how to actually set these variables. Packer exposes two
   282  methods for setting user variables: from the command line or from a file.
   283  
   284  ### CLI
   285  
   286  To set user variables from the command line, the `-var` flag is used as a
   287  parameter to `packer build` (and some other commands). Continuing our example
   288  above, we could build our template using the command below. The command is
   289  split across multiple lines for readability, but can of course be a single
   290  line.
   291  
   292  ```shell-session
   293  $ packer build \
   294      -var 'aws_access_key=foo' \
   295      -var 'aws_secret_key=bar' \
   296      template.json
   297  ```
   298  
   299  As you can see, the `-var` flag can be specified multiple times in order to set
   300  multiple variables. Also, variables set later on the command-line override any
   301  earlier set variable of the same name.
   302  
   303  **warning** If you are calling Packer from cmd.exe, you should double-quote
   304  your variables rather than single-quoting them. For example:
   305  
   306  `packer build -var "aws_secret_key=foo" template.json`
   307  
   308  ### From file
   309  
   310  Variables can also be set from an external JSON file. The `-var-file` flag
   311  reads a file containing a key/value mapping of variables to values and sets
   312  those variables. An example JSON file may look like this:
   313  
   314  ```json
   315  {
   316    "aws_access_key": "foo",
   317    "aws_secret_key": "bar"
   318  }
   319  ```
   320  
   321  It is a single JSON object where the keys are variables and the values are the
   322  variable values. Assuming this file is in `variables.json`, we can build our
   323  template using the following command:
   324  
   325  ```text
   326  On Linux :
   327  $ packer build -var-file=variables.json template.json
   328  On Windows :
   329  packer build -var-file variables.json template.json
   330  ```
   331  
   332  The `-var-file` flag can be specified multiple times and variables from
   333  multiple files will be read and applied. As you'd expect, variables read from
   334  files specified later override a variable set earlier.
   335  
   336  Combining the `-var` and `-var-file` flags together also works how you'd
   337  expect. Variables set later in the command override variables set earlier. So,
   338  for example, in the following command with the above `variables.json` file:
   339  
   340  ```shell-session
   341  $ packer build \
   342      -var 'aws_access_key=bar' \
   343      -var-file=variables.json \
   344      -var 'aws_secret_key=baz' \
   345      template.json
   346  ```
   347  
   348  Results in the following variables:
   349  
   350  | Variable       | Value |
   351  | -------------- | ----- |
   352  | aws_access_key | foo   |
   353  | aws_secret_key | baz   |
   354  
   355  ## Sensitive variables
   356  
   357  If you use the environment to set a variable that is sensitive, you probably
   358  don't want that variable printed to the Packer logs. You can make sure that
   359  sensitive variables won't get printed to the logs by adding them to the
   360  "sensitive-variables" list within the Packer template:
   361  
   362  ```json
   363  {
   364    "variables": {
   365      "my_secret": "{{env `MY_SECRET`}}",
   366      "not_a_secret": "plaintext",
   367      "foo": "bar"
   368    },
   369  
   370    "sensitive-variables": ["my_secret", "foo"],
   371    ...
   372  }
   373  ```
   374  
   375  The above snippet of code will function exactly the same as if you did not set
   376  "sensitive-variables", except that the Packer UI and logs will replace all
   377  instances of "bar" and of whatever the value of "my_secret" is with
   378  `<sensitive>`. This allows you to be confident that you are not printing
   379  secrets in plaintext to our logs by accident.
   380  
   381  ## Recipes
   382  
   383  ### Make a provisioner step conditional on the value of a variable
   384  
   385  There is no specific syntax in Packer templates for making a provisioner step
   386  conditional, depending on the value of a variable. However, you may be able to
   387  do this by referencing the variable within a command that you execute. For
   388  example, here is how to make a `shell-local` provisioner only run if the
   389  `do_nexpose_scan` variable is non-empty.
   390  
   391  ```json
   392  {
   393    "type": "shell-local",
   394    "command": "if [ ! -z \"{{user `do_nexpose_scan`}}\" ]; then python -u trigger_nexpose_scan.py; fi"
   395  }
   396  ```
   397  
   398  ### Using HOME Variable
   399  
   400  In order to use `$HOME` variable, you can create a `home` variable in Packer:
   401  
   402  ```json
   403  {
   404    "variables": {
   405      "home": "{{env `HOME`}}"
   406    }
   407  }
   408  ```
   409  
   410  And this will be available to be used in the rest of the template, i.e.:
   411  
   412  ```json
   413  {
   414    "builders": [
   415      {
   416        "type": "google",
   417        "account_file": "{{ user `home` }}/.secrets/gcp-{{ user `env` }}.json"
   418      }
   419    ]
   420  }
   421  ```