Bolt: Running a ps-script making a web request with credentials

429 views
Skip to first unread message

Andreas Torbiörnsson

unread,
Nov 22, 2019, 2:09:05 PM11/22/19
to Puppet Users
Hi group!

Hoping that someone can help me with  an issue I'm having. It's in a windows environment.
I'm trying to run a script on a remote windows machine using Bolt. The script looks up the latest version of chocolatey from a on prem nuget feed, downloads and installs chocolatey.

Running the script with this command:
bolt script run .\chocolatey_install.ps1 --nodes winrm://xxxxxxx --user userx--password --no-ssl

It returns a 401 error when making a web request to the nuget feed, using System.Net.Webclient from .Net:
Querying latest package from http://xxx.xxxx.xxx/DefaultCollection/_packaging/Testfeed/nuget/v2/Packages()?$filter=(Id%20eq%20%27chocolatey%27)%20and%20IsLatestVersion
  STDERR
:
    $invokeArgs
= @{
     
: System.Management.Automation.MethodInvocationException: Exception calling "DownloadString" with "1" argument(s): "The remote server returned an error: (401) Unauthorized." ---> System.Net.WebException: The remote server returned an error: (401) Unauthorized.
       at
System.Net.WebClient.DownloadDataInternal(Uri address, WebRequest& request)
       at
System.Net.WebClient.DownloadString(Uri address)
       at
CallSite.Target(Closure , CallSite , Object , String )
       
--- End of inner exception stack trace ---
       at
System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext funcContext, Exception exception)
       at
System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame frame)
       at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
       at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
       at System.Management.Automation.Interpreter.Interpreter.Run(InterpretedFrame frame)
       at System.Management.Automation.Interpreter.LightLambda.RunVoid1[T0](T0 arg0)
       at System.Management.Automation.ScriptBlock.InvokeWithPipeImpl(ScriptBlockClauseToInvoke clauseToInvoke, Boolean createLocalScope, Dictionary`
2 functionsToDefine, List`1 variablesToDefine, ErrorHandlingBehavior errorHandlingBehavior, Object dollarUnder, Object input, Object scriptThis, Pipe outputPipe, InvocationInfo invocationInfo, Object[] args)
       at System.Management.Automation.ScriptBlock.<>c__DisplayClass57_0.<InvokeWithPipe>b__0()
       at System.Management.Automation.Runspaces.RunspaceBase.RunActionIfNoRunningPipelinesWithThreadCheck(Action action)
       at System.Management.Automation.ScriptBlock.InvokeWithPipe(Boolean useLocalScope, ErrorHandlingBehavior errorHandlingBehavior, Object dollarUnder, Object input, Object scriptThis, Pipe outputPipe, InvocationInfo invocationInfo, Boolean propagateAllExceptionsToTop, List`
1 variablesToDefine, Dictionary`2 functionsToDefine, Object[] args)
       at System.Management.Automation.ScriptBlock.InvokeUsingCmdlet(Cmdlet contextCmdlet, Boolean useLocalScope, ErrorHandlingBehavior errorHandlingBehavior, Object dollarUnder, Object input, Object scriptThis, Object[] args)
       at Microsoft.PowerShell.Commands.InvokeCommandCommand.EndProcessing()
       at System.Management.Automation.CommandProcessorBase.Complete()
        + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
        + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException




Here are the relevant parts of the code:
function Get-Downloader {
param
(
 
[string]$url
 
)
  $downloader
= new-object System.Net.WebClient
  $downloader
.UseDefaultCredentials  = $true
 
 
return $downloader
}



function Download-Package {
param
(
 
[string]$packageODataSearchUrl,
 
[string]$file
 
)
  $downloader
= Get-Downloader $packageODataSearchUrl
 
 
Write-Output "Querying latest package from $packageODataSearchUrl"
NEXT LINE IS WHERE IT CRASHES
 
[xml]$pkg = $downloader.DownloadString($packageODataSearchUrl)


 I have verified that userx is allowed to query the server. I have also tested to manually move the script to the remote machine and run it locally as userx AND THAT WORKS.
Does anyone know if there is a problem/bug when accessing the credentials of the user running a script (through WebClient.UseDefaultCredentials) when the script is run by Bolt? I can think of many workaround, but I can't understand why this won't work.

Cheers!
Toband, the frustrated developer

Glenn Sarti

unread,
Nov 24, 2019, 8:15:27 PM11/24/19
to puppet...@googlegroups.com
Hi  Toband,

This sounds exactly like the Double Hop problem with WinRM authentication




You can test that this is the case outside of Bolt.  Create a PowerShell session to the remote server and run the script within that session.

There a few ways to work around this issue but it really depends on your environment. Note, that you may see a bunch of articles recommending the use of CredSSP, that should be your last resort though.

Glenn.

--
You received this message because you are subscribed to the Google Groups "Puppet Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-users/7d5f7bdd-fa0c-4d9e-b95f-59d6d9e0df61%40googlegroups.com.

KevinR

unread,
Nov 25, 2019, 5:01:17 AM11/25/19
to Puppet Users
Yep you've run into the second-hop problem as Glenn mentioned. I tried your script in a remote Powershell session and it has the same problem.
Basically the issue is that the credential cache is empty on the remote machine (as a security precaution), which prevents you from use the DefaultCredentials on anything but an interactive logon.

Be aware that for Kerberos delegation to work, you need to be authenticated to the remote machine via Kerberos, which is something Bolt doesn't typically do.

-Kevin

On Monday, November 25, 2019 at 2:15:27 AM UTC+1, Glenn Sarti wrote:
Hi  Toband,

This sounds exactly like the Double Hop problem with WinRM authentication




You can test that this is the case outside of Bolt.  Create a PowerShell session to the remote server and run the script within that session.

There a few ways to work around this issue but it really depends on your environment. Note, that you may see a bunch of articles recommending the use of CredSSP, that should be your last resort though.

Glenn.

To unsubscribe from this group and stop receiving emails from it, send an email to puppet...@googlegroups.com.

Andreas Torbiörnsson

unread,
Nov 25, 2019, 5:32:30 AM11/25/19
to Puppet Users
Thanks a lot, KevinR and Glenn! Was definitely the second-hop problem.

Toband
Reply all
Reply to author
Forward
0 new messages