github.com/hashicorp/packer@v1.14.3/website/content/docs/provisioners/powershell.mdx (about)

     1  ---
     2  description: |
     3    The `powershell` Packer provisioner runs PowerShell scripts on Windows machines.
     4    Learn how to use the provisioner with WinRM and SSH communicators.
     5  page_title: powershell provisioner reference
     6  ---
     7  
     8  <BadgesHeader>
     9    <PluginBadge type="official" />
    10  </BadgesHeader>
    11  
    12  # `powershell` provisioner
    13  
    14  The `powershell` Packer provisioner runs PowerShell scripts on Windows machines.
    15  The provisioner is designed for machines using WinRM as the communicator, but you can also use the provisioner with the SSH communicator. Refer to the [Combining the PowerShell Provisioner with the SSH Communicator](#combining-the-powershell-provisioner-with-the-ssh-communicator) for
    16  details.
    17  
    18  `@include 'path/separator-note.mdx'`
    19  
    20  ## Basic Example
    21  
    22  The example below is fully functional.
    23  
    24  <Tabs>
    25  <Tab heading="HCL2">
    26  
    27  ```hcl
    28  provisioner "powershell" {
    29    inline = ["dir c:/"]
    30  }
    31  ```
    32  
    33  </Tab>
    34  <Tab heading="JSON">
    35  
    36  ```json
    37  {
    38    "type": "powershell",
    39    "inline": ["dir c:/"]
    40  }
    41  ```
    42  
    43  </Tab>
    44  </Tabs>
    45  
    46  ## Configuration Reference
    47  
    48  @include 'provisioners/shell-config.mdx'
    49  
    50  - `debug_mode` - If set, sets PowerShell's [PSDebug mode](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/set-psdebug?view=powershell-7)
    51    in order to make script debugging easier. For instance, setting the value to 1
    52    results in adding this to the execute command:
    53  
    54    ```powershell
    55    Set-PSDebug -Trace 1
    56    ```
    57  
    58  - `elevated_execute_command` (string) - The command to use to execute the
    59    elevated script. By default this is as follows:
    60  
    61    ```powershell
    62    powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }"
    63    ```
    64  
    65    This is a [template engine](/packer/docs/templates/legacy_json_templates/engine).
    66    Therefore, you may use user variables and template functions in this field. In
    67    addition, you may use two extra variables:
    68  
    69    - `Path`: The path to the script to run
    70    - `Vars`: The location of a temp file containing the list of
    71      `environment_vars`, if configured.
    72  
    73  - `env` (map of strings) - A map of key/value pairs to inject prior to the
    74    execute_command. Packer injects some environmental variables by default into
    75    the environment, as well, which are covered in the section below. Duplicate
    76    `env` settings override `environment_vars` settings. This is not a JSON
    77    template engine enabled function. HCL interpolation works as usual.
    78  
    79  - `environment_vars` (array of strings) - An array of key/value pairs to
    80    inject prior to the execute_command. The format should be `key=value`.
    81    Packer injects some environmental variables by default into the
    82    environment, as well, which are covered in the section below.
    83  
    84  - `use_pwsh` (boolean) - Run `pwsh.exe` instead of `powershell.exe`. Defaults to false.
    85  
    86    This is a [template engine](/packer/docs/templates/legacy_json_templates/engine). Therefore, you
    87    may use user variables and template functions in this field. If you are
    88    running on AWS, Azure, Google Compute, or OpenStack and would like to access
    89    the autogenerated password that Packer uses to connect to the instance via
    90    WinRM, you can use the `build` template engine to inject it using
    91    `` {{ build `Password` }} ``. In HCL templates, you can do the same thing by
    92    accessing the `build` variables For example:
    93  
    94  <Tabs>
    95  <Tab heading="HCL2">
    96  
    97  ```hcl
    98  provisioner "powershell" {
    99    environment_vars = ["WINRMPASS=${build.Password}"]
   100    inline = ["Write-Host \"Automatically generated aws password is: $Env:WINRMPASS\""]
   101  }
   102  ```
   103  
   104  </Tab>
   105  <Tab heading="JSON">
   106  
   107  ```json
   108  {
   109    "type": "powershell",
   110    "environment_vars": ["WINRMPASS={{ build `Password` }}"],
   111    "inline": ["Write-Host \"Automatically generated aws password is: $Env:WINRMPASS\""]
   112  },
   113  ```
   114  
   115  </Tab>
   116  </Tabs>
   117  
   118  - `execute_command` (string) - The command to use to execute the script. By
   119    default this is as follows:
   120  
   121    ```powershell
   122    powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }"
   123    ```
   124  
   125    This is a [template engine](/packer/docs/templates/legacy_json_templates/engine).
   126    Therefore, you may use user variables and template functions in this field. In
   127    addition, you may use two extra variables:
   128  
   129    - `Path`: The path to the script to run
   130    - `Vars`: The location of a temp file containing the list of
   131      `environment_vars`, if configured.
   132      The value of both `Path` and `Vars` can be manually configured by setting
   133      the values for `remote_path` and `remote_env_var_path` respectively.
   134  
   135    If you use the SSH communicator and have changed your default shell, you
   136    may need to modify your `execute_command` to make sure that the command is
   137    valid and properly escaped; the default assumes that you have not changed
   138    the default shell away from cmd.
   139  
   140  - `elevated_user` and `elevated_password` (string) - If specified, the
   141    PowerShell script will be run with elevated privileges using the given
   142    Windows user.
   143  
   144    This is a [template engine](/packer/docs/templates/legacy_json_templates/engine). Therefore, you
   145    may use user variables and template functions in this field. If you are
   146    running on AWS, Azure, Google Compute, or OpenStack and would like to access
   147    the autogenerated password that Packer uses to connect to the instance via
   148    WinRM, you can use the `build` template engine to inject it using
   149    `` {{ build `Password` }} ``. In HCL templates, you can do the same thing by
   150    accessing the `build` variables For example:
   151  
   152  <Tabs>
   153  <Tab heading="HCL2">
   154  
   155  ```hcl
   156  provisioner "powershell" {
   157      elevated_user = "Administrator"
   158      elevated_password = build.Password
   159  }
   160  ```
   161  
   162  </Tab>
   163  <Tab heading="JSON">
   164  
   165  ```json
   166  {
   167    "type": "powershell",
   168    "elevated_user": "Administrator",
   169    "elevated_password": "{{ build `Password` }}",
   170    ...
   171  },
   172  ```
   173  
   174  </Tab>
   175  </Tabs>
   176  
   177  If you specify an empty `elevated_password` value then the PowerShell
   178  script is run as a service account. For example:
   179  
   180  <Tabs>
   181  <Tab heading="HCL2">
   182  
   183  ```hcl
   184  provisioner "powershell" {
   185    elevated_user = "SYSTEM"
   186    elevated_password = ""
   187  }
   188  ```
   189  
   190  </Tab>
   191  <Tab heading="JSON">
   192  
   193  ```json
   194  {
   195    "type": "powershell",
   196    "elevated_user": "SYSTEM",
   197    "elevated_password": "",
   198    ...
   199  },
   200  ```
   201  
   202  </Tab>
   203  </Tabs>
   204  
   205  - `execution_policy` - To run ps scripts on Windows, Packer defaults this to
   206    "bypass" and wraps the command to run. Setting this to "none" will prevent
   207    wrapping, allowing to see exit codes on Docker for Windows. Possible values
   208    are `bypass`, `allsigned`, `default`, `remotesigned`, `restricted`,
   209    `undefined`, `unrestricted`, and `none`.
   210  
   211  - `remote_path` (string) - The path where the PowerShell script will be
   212    uploaded to within the target build machine. This defaults to
   213    `C:/Windows/Temp/script-UUID.ps1` where UUID is replaced with a dynamically
   214    generated string that uniquely identifies the script.
   215  
   216    This setting allows users to override the default upload location. The
   217    value must be a writable location and any parent directories must already
   218    exist.
   219  
   220  - `remote_env_var_path` (string) - Environment variables required within the
   221    remote environment are uploaded within a PowerShell script and then enabled
   222    by 'dot sourcing' the script immediately prior to execution of the main
   223    command or script.
   224  
   225    The path the environment variables script will be uploaded to defaults to
   226    `C:/Windows/Temp/packer-ps-env-vars-UUID.ps1` where UUID is replaced with a
   227    dynamically generated string that uniquely identifies the script.
   228  
   229    This setting allows users to override the location the environment variable
   230    script is uploaded to. The value must be a writable location and any parent
   231    directories must already exist.
   232  
   233  - `skip_clean` (bool) - Whether to clean scripts up after executing the provisioner.
   234    Defaults to false. When true any script created by a non-elevated Powershell
   235    provisioner will be removed from the remote machine. Elevated scripts,
   236    along with the scheduled tasks, will always be removed regardless of the
   237    value set for `skip_clean`.
   238  
   239  - `start_retry_timeout` (string) - The amount of time to attempt to _start_
   240    the remote process. By default this is `5m` or 5 minutes. This setting
   241    exists in order to deal with times when SSH may restart, such as a system
   242    reboot. Set this to a higher value if reboots take a longer amount of time.
   243  
   244  - `pause_after` (string) - Wait the amount of time after provisioning a PowerShell
   245    script, this pause be taken if all previous steps were successful.
   246  
   247  @include 'provisioners/common-config.mdx'
   248  
   249  ## Default Environmental Variables
   250  
   251  In addition to being able to specify custom environmental variables using the
   252  `environment_vars` configuration, the provisioner automatically defines certain
   253  commonly useful environmental variables:
   254  
   255  - `PACKER_BUILD_NAME` is set to the [name of the
   256    build](/packer/docs/templates/legacy_json_templates/builders#named-builds) that Packer is running.
   257    This is most useful when Packer is making multiple builds and you want to
   258    distinguish them slightly from a common provisioning script.
   259  
   260  - `PACKER_BUILDER_TYPE` is the type of the builder that was used to create
   261    the machine that the script is running on. This is useful if you want to
   262    run only certain parts of the script on systems built with certain
   263    builders.
   264  
   265  - `PACKER_HTTP_ADDR` If using a builder that provides an HTTP server for file
   266    transfer (such as `hyperv`, `parallels`, `qemu`, `virtualbox`, and `vmware`), this
   267    will be set to the address. You can use this address in your provisioner to
   268    download large files over HTTP. This may be useful if you're experiencing
   269    slower speeds using the default file provisioner. A file provisioner using
   270    the `winrm` communicator may experience these types of difficulties.
   271  
   272  ## Combining the PowerShell Provisioner with the SSH Communicator
   273  
   274  The good news first. If you are using the [Microsoft port of
   275  OpenSSH](https://github.com/PowerShell/Win32-OpenSSH/wiki) then the provisioner
   276  should just work as expected - no extra configuration effort is required.
   277  
   278  Now the caveats. If you are using an alternative configuration, and your SSH
   279  connection lands you in a \*nix shell on the remote host, then you will most
   280  likely need to manually set the `execute_command`; The default
   281  `execute_command` used by Packer will not work for you. When configuring the
   282  command you will need to ensure that any dollar signs or other characters that
   283  may be incorrectly interpreted by the remote shell are escaped accordingly.
   284  
   285  The following example shows how the standard `execute_command` can be
   286  reconfigured to work on a remote system with
   287  [Cygwin/OpenSSH](https://cygwin.com/) installed. The `execute_command` has each
   288  dollar sign backslash escaped so that it is not interpreted by the remote Bash
   289  shell - Bash being the default shell for Cygwin environments.
   290  
   291  <Tabs>
   292  <Tab heading="HCL2">
   293  
   294  ```hcl
   295  provisioner "powershell" {
   296      execute_command = "powershell -executionpolicy bypass \"& { if (Test-Path variable:global:ProgressPreference){\\$ProgressPreference='SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit \\$LastExitCode }\""
   297      inline          = [ "Write-Host \"Hello from PowerShell\""]
   298  }
   299  ```
   300  
   301  </Tab>
   302  <Tab heading="JSON">
   303  
   304  ```json
   305  "provisioners": [
   306    {
   307      "type": "powershell",
   308      "execute_command": "powershell -executionpolicy bypass \"& { if (Test-Path variable:global:ProgressPreference){\\$ProgressPreference='SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit \\$LastExitCode }\"",
   309      "inline": ["Write-Host \"Hello from PowerShell\""]
   310    }
   311  ]
   312  ```
   313  
   314  </Tab>
   315  </Tabs>
   316  
   317  ## Packer's Handling of Characters Special to PowerShell
   318  
   319  The escape character in PowerShell is the `backtick`, also sometimes referred
   320  to as the `grave accent`. When, and when not, to escape characters special to
   321  PowerShell is probably best demonstrated with a series of examples.
   322  
   323  ### When To Escape...
   324  
   325  Users need to deal with escaping characters special to PowerShell when they
   326  appear _directly_ in commands used in the `inline` PowerShell provisioner and
   327  when they appear _directly_ in the users own scripts. Note that where double
   328  quotes appear within double quotes, the addition of a backslash escape is
   329  required for the JSON template to be parsed correctly.
   330  
   331  <Tabs>
   332  <Tab heading="HCL2">
   333  
   334  ```hcl
   335  provisioner "powershell" {
   336      inline = [
   337          "Write-Host \"A literal dollar `$ must be escaped\"",
   338          "Write-Host \"A literal backtick `` must be escaped\"",
   339          "Write-Host \"Here `\"double quotes`\" must be escaped\"",
   340          "Write-Host \"Here `'single quotes`' don`'t really need to be\"",
   341          "Write-Host \"escaped... but it doesn`'t hurt to do so.\"",
   342      ]
   343  }
   344  ```
   345  
   346  </Tab>
   347  <Tab heading="JSON">
   348  
   349  ```json
   350    "provisioners": [
   351      {
   352        "type": "powershell",
   353        "inline": [
   354            "Write-Host \"A literal dollar `$ must be escaped\"",
   355            "Write-Host \"A literal backtick `` must be escaped\"",
   356            "Write-Host \"Here `\"double quotes`\" must be escaped\"",
   357            "Write-Host \"Here `'single quotes`' don`'t really need to be\"",
   358            "Write-Host \"escaped... but it doesn`'t hurt to do so.\""
   359        ]
   360      }
   361    ]
   362  ```
   363  
   364  </Tab>
   365  </Tabs>
   366  
   367  The above snippet should result in the following output on the Packer console:
   368  
   369  ```shell-session
   370  ==> amazon-ebs: Provisioning with Powershell...
   371  ==> amazon-ebs: Provisioning with PowerShell script: /var/folders/15/d0f7gdg13rnd1cxp7tgmr55c0000gn/T/packer-powershell-provisioner508190439
   372      amazon-ebs: A literal dollar $ must be escaped
   373      amazon-ebs: A literal backtick ` must be escaped
   374      amazon-ebs: Here "double quotes" must be escaped
   375      amazon-ebs: Here 'single quotes' don't really need to be
   376      amazon-ebs: escaped... but it doesn't hurt to do so.
   377  ```
   378  
   379  ### When Not To Escape...
   380  
   381  Special characters appearing in user environment variable values and in the
   382  `elevated_user` and `elevated_password` fields will be automatically dealt with
   383  for the user. There is no need to use escapes in these instances.
   384  
   385  <Tabs>
   386  <Tab heading="HCL2">
   387  
   388  ```hcl
   389  variable "psvar" {
   390    type    = string
   391    default = "My$tring"
   392  }
   393  
   394  build {
   395    sources = ["source.amazon-ebs.example"]
   396  
   397    provisioner "powershell" {
   398        elevated_user     = "Administrator"
   399        elevated_password = "Super$3cr3t!"
   400        inline            = ["Write-Output \"The dollar in the elevated_password is interpreted correctly\""]
   401    }
   402    provisioner "powershell" {
   403      environment_vars = [
   404          "VAR1=A$Dollar",
   405          "VAR2=A`Backtick",
   406          "VAR3=A'SingleQuote",
   407          "VAR4=A\"DoubleQuote",
   408          "VAR5=${var.psvar}",
   409      ]
   410      inline = [
   411        "Write-Output \"In the following examples the special character is interpreted correctly:\"",
   412        "Write-Output \"The dollar in VAR1:                            $Env:VAR1\"",
   413        "Write-Output \"The backtick in VAR2:                          $Env:VAR2\"",
   414        "Write-Output \"The single quote in VAR3:                      $Env:VAR3\"",
   415        "Write-Output \"The double quote in VAR4:                      $Env:VAR4\"",
   416        "Write-Output \"The dollar in VAR5 (expanded from a user var): $Env:VAR5\"",
   417      ]
   418    }
   419  }
   420  ```
   421  
   422  </Tab>
   423  <Tab heading="JSON">
   424  
   425  ```json
   426  {
   427    "variables": {
   428      "psvar": "My$tring"
   429    },
   430    ...
   431    "provisioners": [
   432      {
   433        "type": "powershell",
   434        "elevated_user": "Administrator",
   435        "elevated_password": "Super$3cr3t!",
   436        "inline": "Write-Output \"The dollar in the elevated_password is interpreted correctly\""
   437      },
   438      {
   439        "type": "powershell",
   440        "environment_vars": [
   441          "VAR1=A$Dollar",
   442          "VAR2=A`Backtick",
   443          "VAR3=A'SingleQuote",
   444          "VAR4=A\"DoubleQuote",
   445          "VAR5={{user `psvar`}}"
   446        ],
   447        "inline": [
   448          "Write-Output \"In the following examples the special character is interpreted correctly:\"",
   449          "Write-Output \"The dollar in VAR1:                            $Env:VAR1\"",
   450          "Write-Output \"The backtick in VAR2:                          $Env:VAR2\"",
   451          "Write-Output \"The single quote in VAR3:                      $Env:VAR3\"",
   452          "Write-Output \"The double quote in VAR4:                      $Env:VAR4\"",
   453          "Write-Output \"The dollar in VAR5 (expanded from a user var): $Env:VAR5\""
   454        ]
   455      }
   456    ]
   457    ...
   458  }
   459  ```
   460  
   461  </Tab>
   462  </Tabs>
   463  
   464  The above snippet should result in the following output on the Packer console:
   465  
   466  ```shell-session
   467  ==> amazon-ebs: Provisioning with Powershell...
   468  ==> amazon-ebs: Provisioning with PowerShell script: /var/folders/15/d0f7gdg13rnd1cxp7tgmr55c0000gn/T/packer-powershell-provisioner961728919
   469      amazon-ebs: The dollar in the elevated_password is interpreted correctly
   470  ==> amazon-ebs: Provisioning with Powershell...
   471  ==> amazon-ebs: Provisioning with PowerShell script: /var/folders/15/d0f7gdg13rnd1cxp7tgmr55c0000gn/T/packer-powershell-provisioner142826554
   472      amazon-ebs: In the following examples the special character is interpreted correctly:
   473      amazon-ebs: The dollar in VAR1:                            A$Dollar
   474      amazon-ebs: The backtick in VAR2:                          A`Backtick
   475      amazon-ebs: The single quote in VAR3:                      A'SingleQuote
   476      amazon-ebs: The double quote in VAR4:                      A"DoubleQuote
   477      amazon-ebs: The dollar in VAR5 (expanded from a user var): My$tring
   478  ```