1

I am trying to invoke a PowerShell script from Puppet. The issue is even if the PowerShell script fails on remote box, it still shows successful run as shown below:

Notice: /Stage[main]/Main/Node[dev.abc.com]/Exec[Check UAC]/returns: executed successfully

Content of my node block in site.pp:

exec { 'Check UAC':
  command   => '& C:\temp\check_uac.ps1',
  provider  => powershell,
  logoutput => 'on_failure',
}

The script failed when I tried running from PowerShell console stating that execution policy was set to Restricted.

PS C:\> C:\temp\check_uac.ps1
C:\temp\check_uac.ps1 : File C:\temp\check_uac.ps1 cannot be loaded because running
scripts is disabled on this system. For more information, see about_Execution_Policies
at http://go.microsoft.com/fwlink/?LinkID=135170.
At line:1 char:1
+ C:\temp\check_uac.ps1
+ ~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : SecurityError: (:) [], PSSecurityException
    + FullyQualifiedErrorId : UnauthorizedAccess

How can I capture the above error when invoking the script from Puppet to avoid surprises later?

Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
Technext
  • 7,887
  • 9
  • 48
  • 76

1 Answers1

1

You need to set an exit code to have Puppet pick up failures:

exec { 'Check UAC':
  command   => '& C:\temp\check_uac.ps1; exit (1 - [int]$?)',
  provider  => powershell,
  logoutput => 'on_failure',
}

However, since the powershell provider should normally bypass execution policies, the error you observed means that the execution policy is enforced via group policy.

A better approach would be to fix the execution policy in your environment, so that it doesn't prohibit script execution, and have your script return an exit code to indicate whether or not UAC is enabled.

If for some obscure reason you cannot fix the actual problem and have to deal with the symptoms instead, you need to exec PowerShell directly, like this:

exec { 'Check UAC':
  command   => 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -NoProfile -NoLogo -NonInteractive -Command "& {C:\temp\check_uac.ps1; exit (1 - [int]$?)}"',
  logoutput => 'on_failure',
}

The powershell provider won't work in this scenario.


If all you want is to determine whether or not execution of PowerShell scripts is restricted, I would consider a dynamic fact a better way to determine that information, e.g. with a batch script in %AllUsersProfile%\PuppetLabs\facter\facts.d:

@echo off

for /f "tokens=* delims=" %%p in (
  'powershell -NoProfile -NonInteractive -NoLogo -Command "Get-ExecutionPolicy"'
) do set "policy=%%p"

if /i "%policy%"=="restricted" (
  echo ExecutionRestricted=true
) else (
  echo ExecutionRestricted=false
)
Community
  • 1
  • 1
Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
  • I tried your suggestion but the issue persists. Still getting successful execution message despite having `Execution Policy` set to `Restrcited`. We do fix the policy issue before running Powershell script but i just missed on one instance and that's when i noticed the issue i posted above. – Technext Feb 27 '17 at 12:08
  • What do you mean "despite having execution policy set to Restricted"? Restricted means that execution of unsigned scripts is forbidden. You need at least RemoteSigned to allow execution of local unsigned scripts. Otherwise you need to sign the scripts you want to execute. – Ansgar Wiechers Feb 27 '17 at 13:09
  • If execution policy is set to Restricted and i get error while running my powershell (PS) script from PS command line, then i `should also get the same error` when i try to invoke the PS script from Puppet but that's not happening. Puppet output shows that it worked successfully which is not the case. – Technext Feb 27 '17 at 13:37
  • 1
    I don't know what you think that second resource is going to do, but whatever it is, that is not what the resource is doing. – Matthew Schuchard Feb 27 '17 at 23:43
  • @MattSchuchard You're right. I misread the provider documention. Updated answer. – Ansgar Wiechers Feb 28 '17 at 11:54
  • My only aim is to get the same error (in this case, Execution Policy restriction) displayed/captured on Puppet console which i might get if i run the script directly on Powershell on the remote box. Is it possible to capture such kind of error directly within Puppet? – Technext Feb 28 '17 at 12:27
  • Yes, i did. The command you've specified `explicitly` sets ExecutionPolicy in the command line itself to avoid running into error. That's a belt and suspenders approach. I am not averse to using it but what i was looking for is a way to trap the error in the first place. Putting this in all exec commands doesn't seem right. And i am not talking about the extra chars that it will add in each exec but it's about the approach. – Technext Feb 28 '17 at 14:11
  • 1
    Despite the `-ExecutionPolicy` parameter the PowerShell command will fail if execution is restricted via group policy. If you remove the parameter it will also fail if the regular execution policy is set to `Restricted`. But either way the trailing `exit` statement in the command will return a non-zero exit code if that happens. However, if all you want is to determine whether or not the execution policy allows script execution, a dynamic fact might be more suitable. See updated answer. – Ansgar Wiechers Feb 28 '17 at 15:18
  • The _solution_ provided in the [bypass](http://stackoverflow.com/questions/40592641/how-to-set-powershell-executionpolicy-via-puppet-exec-command-with-unless-proper/40612299#40612299) link is what i execute on any machine before running any `exec` command and it _works_. In this particular case, i forgot executing that command and unfortunately, Puppet didn't complain about the restriction policy. So, the policy is _not_ enforced via group policy. – Technext Feb 28 '17 at 16:38
  • With this detail i mentioned in my last comment, i don't see any difference in the first and second exec resource suggestions made by you. Please correct me if i'm wrong. I obviously understand that your second exec suggestion was made based on the details i provided earlier. Now, i'm confused why the first suggestion made by you doesn't produce the same error message as the second one (if i remove the `-ExecutionPolicy` parameter and run) does. – Technext Feb 28 '17 at 16:44
  • They're not the same, because the first one uses the `powershell` provider, which from a quick glance seems to work slightly differently than the second one that directly executes a command string with PowerShell. – Ansgar Wiechers Feb 28 '17 at 17:04
  • Thanks @AnsgarWiechers! I think i will go with the second resource without `-ExecutionPolicy` parameter. At least i get the actual error message and the execution stops. Just one query: `$?` is for status of last command but i didn't understand why you did this: `1 - [int]$?` – Technext Feb 28 '17 at 18:16
  • 2
    The [automatic variable](https://msdn.microsoft.com/en-us/powershell/reference/3.0/microsoft.powershell.core/about/about_automatic_variables) `$?` contains a boolean value indicating the status of the last operation. [Casting](https://blogs.msdn.microsoft.com/powershell/2006/12/24/boolean-values-and-operators/) the value to an integer produces 0 for `$false` and 1 for `$true`. Subtract that value from 1 to get an exit code of 0 for success and 1 for error. – Ansgar Wiechers Mar 01 '17 at 10:33