Why are Windows proxy lost when executing code via Ansible (remote WinRM)? - windows

In automating Windows (2012R2 and 2016) builds, I found that even though I set a system-wide proxy via netsh, I still had to set the HKCU values for IE because some commands would not work without those values set. I would have to open IE and visit a site, any site, to initialize those settings, which was annoying.
I was able to find some PowerShell code that could "initialize" the IE proxy settings so I did not have to open IE and visit a site, shown below:
$Source=#"
[DllImport("wininet.dll")]
public static extern bool InternetSetOption(int hInternet, int dwOption, int lpBuffer, int dwBufferLength);
"#
$wininet = Add-Type -memberDefinition $Source -passthru -name InternetSettings
$wininet::InternetSetOption([IntPtr]::Zero, 95, [IntPtr]::Zero, 0)|out-null
$wininet::InternetSetOption([IntPtr]::Zero, 37, [IntPtr]::Zero, 0)|out-null
The above code is from https://vanderpaal.com.au/2016/09/30/live-proxy-setting-change/ (thanks!)
The above code works great when executed manually via RDP session. I set the IE proxy values correctly, I run the above code, and I can then do whatever I want - it all works. The commands that require the IE settings work fine.
I have been trying to run more code via remote WinRM using things like Ansible and SSM (in AWS). When I do, weird things happen.
Specifically, the IE proxy registry entries get deleted and reset back to defaults. So, the order of doing things via script is:
Write IE proxy values to the registry via script called by Ansible or SSM.
Run the initialize proxy code listed above.
IE values from #1 are gone...
I am at a loss as to why the registry values get deleted. I am 100% sure they get deleted - I can script a reg query before and after the initialize proxy commands - before the commands they exist, and after the commands they do not. This does not happen when I run the same scripts manually on the server in an RDP session - that is, the proxy command does NOT delete the entries.
I have replicated this in both Ansible and SSM, both of which use PowerShell and WinRM to run commands. The scripts reside on the actual server, and Ansible/SSM tell the system to execute the scripts.
I have verified that HKCU actually exists during Ansible execution of the scripts.
Because the IE values get deleted, the initialize command does me no good when the following commands that require the IE values execute. Those commands fail with errors like so:
PackageManagement\Install-Package : No match was found for the specified
search criteria and module name ''
The commands I am running (which fail) are just install module commands, like so:
Install-Module -Name PSWindowsUpdate -Proxy http://proxy.foo.com:80 -Confirm:$false -Force
Install-Module -Name PowerShellGet -Proxy http://proxy.foo.com:80 -Confirm:$false -Force
Anyone know why the IE proxy registry values get deleted when I run the code above via Ansible or SSM? The proxy values in question are:
"HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyEnable" - this gets reset to 0
"HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyServer" - this gets deleted
"HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyOverride" - this gets deleted

had the same problem. and found out that the damned ie wizard was the root cause.
u have to add following key to registry before u can access ie components...:
desc: "Remove IE 11 first run Wizard"
path: "HKLM:\\Software\\Policies\\Microsoft\\Internet Explorer\\Main"
name: "DisableFirstRunCustomize"
data: "1"
type: "dword"

Related

Powershell Closes Instantly

I've looked all of the the internet and I cannot find any information that applies to this situation.
Powershell closes immediately upon starting. When I run it in Command Prompt I get the following:
Windows PowerShell terminated with the following error:
Unable to cast object of type 'System.String' to type 'System.String[]'.
I have checked the following folders and no profiles exist:
c:\users\me\appdata\microsoft\windows\powershell
c:\windows\system32\windowspowershell\v1.0\
c:\windows\systwow64\windowspowershell\v1.0\
I have tried to run with the following commands and have no luck:
powershell -noexit
powershell -noprofile
I have run the following commands and have no luck:
sfc.exe /scannow
DISM.exe /Online /Cleanup-image /Restorehealth
I also have gone to Control Panel -> Uninstall a Program -> Turn Windows features on or off then,
Removed Powershell, rebooted, then re-installed it.
After doing all of these steps I still am not able to run Powershell. ISE does not work either.
This may be related to Powershell logging settings. I had the exact same issue after implementing Powershell Module logging using the wrong path for ModuleNames.
Check the values set in HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging
In my case, I made the mistake of adding a value of ModuleNames set to * - not realizing it should be a KEY named ModuleNames - which resulted in an error
Windows PowerShell terminated with the following error:
Unable to cast object of type 'System.String' to type 'System.String[]'.
By adding the right path HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging\ModuleNames\ with a REG_SZ value named * and with a value of * I got Powershell working again.
Note that if this setting comes from a GPO (Group Policy Object) in the domain, it will need to be fixed there, rather than in the registry. Otherwise, the GPO will just overwrite the local settings the next time it applies.
Whenever you run powershell, it loads the default modules present in the Modules directory. One of these modules (most likely a custom one you wrote) is causing errors and not allowing you to start.
Without knowing anything about the modules you have present in the directory located at: C:\windows\system32\windowspowershell\v1.0\Modules, it would be hard for anyone to tell you the solution.
Recommendation
Remove any custom modules you have in there and add each module you need one at a time to see which one breaks your powershell.exe. You will need to check each path you have defined for custom modules to be loaded as well.
Other way would be to clear out the PSModulePath from Environment variables and add one location at a time until you see which Modules directory is causing error.
NOTE: Write down the paths on a notepad somewhere before you clear it.
From the error it seems like a .net library class (dll) that is not correctly written.

Powershell - new-website cmdlet not working when called via web interface

I hope someone can help me with the following :
I’ve created a script to install a web site based on an existing site.
The script performs several steps - copy dirs, restore a DB, create website and application pool etc. It runs fine from the Powershell CLI under an Administrator account.
I created a WinForms frontend for this script that references Powershell and also executes that script just fine.
Now I want to create a web frontend for it. (as explained here : http://devinfra-us.blogspot.com/2011/02/using-powershell-20-from-aspnet-part-1.html)
However I can’t get the ‘new-website’ cmdlet to work via the web frontend. All the other steps in the script work, including ‘new-WebappPool’ (I can see the new appPool in IIS manager). I don’t get any errors..
I’ve made sure the script runs with Administrator rights (security is not a concern at this point)
Below is some output from the Powershell transcript :
**********************
Windows PowerShell transcript start
Start time: 20200106164117
Username: NNN-WEB\adminArr <-- Administrator account
RunAs User: NNN-WEB\adminArr
Machine: NNN-WEB (Microsoft Windows NT 10.0.14393.0)
Host Application: c:\windows\system32\inetsrv\w3wp.exe -ap DefaultAppPool -v v4.0 -l webengine4.dll -a \\.\pipe\iisipmd4bdced8-d455-428b-b9ef-8b3e2bfb38dd -h C:\inetpub\temp\apppools\DefaultAppPool\DefaultAppPool.config -w -m 0 -t 20 -ta 0
Process ID: 8448
PSVersion: 5.1.14393.3383
PSEdition: Desktop
PSCompatibleVersions: 1.0, 2.0, 3.0, 4.0, 5.0, 5.1.14393.3383
BuildVersion: 10.0.14393.3383
CLRVersion: 4.0.30319.42000
WSManStackVersion: 3.0
PSRemotingProtocolVersion: 2.3
SerializationVersion: 1.1.0.1
You could use the below PowerShell command to create a site in iis:
Import-Module WebAdministration
New-WebAppPool NewAppPool
New-Website -Name "mike" -Port 8086 -PhysicalPath c:\casp -ApplicationPool NewAppPool
Do not forget to refresh the iis after running the command.
Although in my script I also used the commands mentioned in Jalpa's example, I tried his example script anyway. I got the error 'Cannot add duplicate collection entry of type 'site' with unique key attributes 'name, id' respectively set to 'mike3, 2' - which I didn't get using my own script...
Thanks to this error, I figured out that if there are already some existing sites, you also have to specify the 'ID' parameter of the new-website command - so like 'new-website -Name "testsite" -Id 4 etc.'. The ID has to be a number not in use by any other sites.
This made it work :-)

Jenkins job with batch stage has a zombie environment variable

I have a python command line program that can retrieve passwords for me.
I can run it from the command line and get the passwords.
Example command:
passwordmanpro_cli javaprops OpenWeatherMap_DEV
The response comes back fine.
I have the Jenkins agent installed on the machine. I have a "Execute Windows Batch Command" step which calls exactly the same commandline.
This USED to work without an issue. A month ago it stopped working. With an error:
ERROR Success not returned from passwordmanagerpro
Using URL - https://icsecpws.cc.ic.ac.uk:443/restapi/json/v1/resources (AUTHTOKEN ommitted - 36)
ResponseCode - 200
resJSON - {'operation': {'name': 'Authentication', 'result': {'status': 'Failed', 'message': 'User is not allowed to access from this host'}}}
IP Being used to send message might be: 155.198.31.184
Something is different from how this request is sent via a windows terminal and how it is sent from a windows batch step in Jenkins.
I have verified the windows batch command is being run as a correct user.
I have verified the username and password credentials being passed are the same
I have verified the source IP by adding debug lines in python.
The password manager we are using has an API user setup and you enter an IP address the API is allowed to be called from. Apparently the restriction is not done on source IP but a reverse hostname lookup.
Can anyone give me advice on how to debug this further?
Update 1
More debugging has revealed that the cause is the environment is being set wrong. The host machine is windows 10. I have an environment variable called PASSMANCLI_AUTHTOKEN and another called PASSMANCLI_URL
In control panel I am setting both variables system wide. NOT for a particular user.
What is really strange is that the PASSMANCLI_URL is changing and being picked up ok, but the PASSMANCLI_AUTHTOKEN variable is not. I have added a "set" windows batch command in the config and I have confirmed that the PASSMANCLI_AUTHTOKEN value is NOT coming from the system setting but somewhere else. I am wondering if Jenkins does anything special with this.
BTW: I have also used the whoami command as part of the project config and confirmed Jenkins is running as the same user.
Update 2
I have gone through the entire windows registery and looked at all Environment entries and deleted PASSMANCLI_AUTHTOKEN. I have confirmed it is not in the environment console. I have restarted the Jenkins agent and the entire server. I then run my jenkins job with a single command "Set" and it reads back the OLD value of the token!
update 3
I have created a brand new Jenkins job with 1 step which is the windows batch command. It simply has "set" so displays the environment variables. I can see PASSMANCLI_AUTHTOKEN is still being set even though I have completely wiped it from the machine.
update 4
I thought it might be something to do with the way the Jenkins runner uses JAVA. (Our Jenkins runner is using Java 8 32 bit). I wrote a Java program which runs
processBuilder.command("cmd.exe", "/c", "set");
and outputs the result.
I checked the output and the variable is NOT set, as expected.
I still don't know where this variable is coming from when executed via Jenkins.

Can't use Get-Service –ComputerName on remote computer

I have a windows 2003 box setup with virtual box and I can't powershell to work with it.
I try this on my windows 7 machine
Get-Service –ComputerName myserver
I get back
Get-Service : Cannot open Service Control Manager on computer 'myserver'. This operation might require other privileges.
At Script1.ps1:2 char:4
+ gsv <<<< -cn myserver
+ CategoryInfo : NotSpecified: (:) [Get-Service], InvalidOperationException
+ FullyQualifiedErrorId : System.InvalidOperationException,Microsoft.PowerShell.Commands.GetServiceCommand
While searching around I found I should try and use Enable-PSRemoting.
I did this and now when I try to use it I get
WinRM already is set up to receive requests on this machine. WinRM
already is set up for remote management on this machine.
Yet I still get the same error. Is this because I am using a virtual machine? I setup the virtual OS to be on my domain and I can even use my AD account credentials to log in.
I can get other information back from it.
So it is not like I can't connect to it with powershell.
With PowerShell V2 you've got two approachs for remote commands.
Commands with built-in remoting :
A small set of commands in PowerShell v2 have a -ComputerName parameter, which allows you to specify the target machine to access.
Get-Process
Get-Service
Set-Service
Clear-EventLog
Get-Counter
Get-EventLog
Show-EventLog
Limit-EventLog
New-EventLog
Remove-EventLog
Write-EventLog
Restart-Computer
Stop-Computer
Get-HotFix
These commands do their own remoting either because the underlying infrastructure already supports remoting or they address scenarios that are of particular importance to system management. They are built on the top of DCOM and, on the access point of view, you can use them when you can establish a session with the remote machine with commands like NET.exe or PSExec.exe.
You are trying to use one of them and you've got a problem with credentials (-cred parameter), because your token credentials can't be used to establish an admin session to the remote machine.
The PowerShell remoting subsystem :
Before you can use PowerShell remoting to access a remote computer, the remoting service on that computer has to be explicitly enabled. You do so using the Enable-PSRemoting cmdlet. If you are working in workgroup you also need to enable the server to enter on your client computer with this command (on your client computer as administrator):
Set-Item WSMan:\localhost\Client\TrustedHosts *
Then, you will use New-PSSession Cmdlet (with -computername and -credentials) to create a session object. Then Invoke-Command (with -session and -scriptblock) cmdlet allows you to remotely invoke a scriptblock on another computer. This is the base element for most of the features in remoting. You can also use Enter-PSSession to establish an interactive (SSL like) PowerShell command line with the server.
Useful link : Layman’s guide to PowerShell 2.0 remoting
Test this :
$sess = New-PSSession -ComputerName myServer-Credential (Get-Credential)
Invoke-Command -Session $sess -ScriptBlock {get-service}
...
Remove-PSSession -Session $sess
If it is still important, here is my workaround:
I got an unprivileged user called 'usser' who wants powershell(v2) remoting from client A to server B.
Steps:
enable-psremoting on Targetserver B as admin
Set-PSSessionConfiguration -Name Microsoft.PowerShell -ShowSecurityDescriptorUI on Targetserver B as admin
Add "usser" with full privileges
Now comes the exciting part:
sc sdshow scmanager on Targetserver B as admin
Copy the SDDL output
sc sdset scmanager (f.e.:)"D:(A;;CC;;;AU)(A;;CCLCRPRC;;;IU)(A;;CCLCRPRC;;;SU)(A;;CCLCRPWPRC;;;SY)(A;;KA;;;BA)S:(AU;FA;KA;;;WD)(AU;OIIOFA;GA;;;WD)" , in the Output you have to fill after this part (A;;CCLCRPWPRC;;;SY) this = (A;;KA;;;SID)
SID stands of course for the SID of the unprivileged "usser"-user
when everything should be fine, it will similiar looks like this :
D:(A;;CC;;;AU)(A;;CCLCRPRC;;;IU)(A;;CCLCRPRC;;;SU)(A;;CCLCRPWPRC;;;SY)(A;;KA;;;S-1-5-21-4233383628-1788409597-1873130553-1161)(A;;KA;;;BA)S:(AU;FA;KA;;;WD)(AU;OIIOFA;GA;;;WD)
Hope you will enjoy that little but complicated workaround.
Viewing and manipulating services requires administrative privileges on the target machine.
I was able to duplicate your error message by attempting to run Get-Service -ComputerName MyServer while logged in as a user account that doesn't have administrative rights to the server in question.
You can resolve this by either granting the workstation user account administrative privileges on the target server or by creating a a local group on the server and granting invocation privileges to members of that group. If you want to do the latter, see the following article.
msgoodies: Using a PS Session without having Administrative Permissions
Building on #scusi marcus's brilliant answer here:
Let's say I have an unprivileged/limited user called 'user1' who wants powershell(v2+) remoting from client machine A to targetserver B.
Steps:
From elevated powershell prompt on targetserver B, run enable-psremoting. Accept several Y/N dialog confirmations or else run with -force switch.
In same elevated prompt as step 1, Set-PSSessionConfiguration -Name Microsoft.PowerShell -ShowSecurityDescriptorUI
In the resulting dialog, add "user1". Read privileges should be sufficient unless you are planning on remotely manipulating services, in which case you will want Full Control.
On targetserver B, from an elevated (non-powershell) prompt or as an administrator, run sc sdshow scmanager. Copy the SDDL output. May look something like this: D:(A;;CC;;;AU)(A;;CCLCRPRC;;;IU)(A;;CCLCRPRC;;;SU)(A;;CCLCRPWPRC;;;SY)(A;;KA;;;BA)S:(AU;FA;KA;;;WD)(AU;OIIOFA;GA;;;WD)
UPDATE: If we add the limited user to the target computer's Remote Management Users group, we can add (A;;LCRPWPDTLO;;;RM) to the D: portion of the above SDDL string, and skip steps 5 and 6 below.
Determine the SID of the underprivileged user account (in our case, "user1"). (Hint: try wmic useraccount where name='user1' get sid)
Insert the following text into the output we copied in step 5: (A;;KA;;;*SID*) where *SID* is the SID of the user determined in step 5. Insert it somewhere in a place before the S: part of the SDDL string retrieved in step 4. So now you should have a string looking something like this: D:(A;;CC;;;AU)(A;;CCLCRPRC;;;IU)(A;;CCLCRPRC;;;SU)(A;;CCLCRPWPRC;;;SY)(A;;KA;;;S-1-5-21-4233383628-1788409597-1873130553-1161)(A;;KA;;;BA)S:(AU;FA;KA;;;WD)(AU;OIIOFA;GA;;;WD)
On targetserver B, run sc sdset scmanager followed by our new modified SDDL string. So the entire command would look something like this:
sc sdset scmanager D:(A;;CC;;;AU)(A;;CCLCRPRC;;;IU)(A;;CCLCRPRC;;;SU)(A;;CCLCRPWPRC;;;SY)(A;;KA;;;S-1-5-21-4233383628-1788409597-1873130553-1161)(A;;KA;;;BA)S:(AU;FA;KA;;;WD)(AU;OIIOFA;GA;;;WD)
You should now be able to remotely access the Service Control Manager on the remote server while logged into client machine A as "user1".
On client machine A, you may find that when you run Get-Service –ComputerName remoteserver not all services are listed. You may need to repeat the above process (starting at step 4) for a specific service that you need remote access to, but which is not listed in your Get-Service output on client machine A. For instance, if the sqlserveragent service is not listed (but you know it is present on the targetserver), you would again log in to targetserver B and execute sc sdshow but this time not for scmanager but for the sqlserveragent service, so sc sdshow sqlserveragent. You would again receive some SDDL output that would need to be manipulated as above. At this point, it may be worth learning more about SDDL (Google it - this link was helpful for me), with the main caveat to watch for the D: and S: portions of the SDDL string and make sure you aren't messing with the S: part.
I know that this isn't the ideal answer to this question, but I was having a similar issue trying to use PowerShell to talk to a Windows 7 box. Turns out, WMI hadn't been installed with the native PSv2 that comes with Win7.
As soon as I installed v3 as part of the WMI 3.0 package, the problem solved itself. I'd suggest making sure that all the relevant WMI services are running on your server. Unless you have conflicts, I'd also recommend upgrading to WMI 3.0.

How do I set the http proxy in a subshell launched from a windows service

I am writing a windows service which takes an uploaded file, runs signtool.exe on it to do the signing and timestamping and then serves the signed file back.
The code for this works when run as a standalone server using twisted however if I try and run it as a service it fails with the error "Signing succeeded, but an error occurred while attempting to timestamp".
If I replace the signcode subprocess call with a curl.exe call which explicitly uses the proxy then this succeeds.
I have set the proxy in internet explorer and running the command manually works. Is there another way of setting an http proxy for signtool/signcode or another way of doing this (I am keen for it to be a service for ease of integration in to some other monitoring systems)?
I have the same issue but running signtool via cygwin ssh (using a password). The timestamping only works via the proxy and over ssh if I login at least once through the gui (e.g. via rdesktop). I don't even have to be logged in to the gui after that for it to work via ssh, I just have to make sure I login at least once via the gui. Whatever it's doing upon graphical login survives a reboot too. One difference however is that I'm setting the proxy settings dynamically using the same powershell that I'm launching via ssh :
$reg_key = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings"
Set-ItemProperty -path $reg_key ProxyServer -value 192.168.0.3:8888
Set-ItemProperty -path $reg_key ProxyOverride -value "<local>"
Set-ItemProperty -path $reg_key ProxyEnable -value 1
I tried launching explorer.exe &, notepad &, and iexplorer.exe & from ssh but it didn't help. I'll see about hard coding the proxy settings and also if its possible to have the signing user be logged into the gui after boot. Also will check to make sure ssh is launched with cygrunsrv -i or that it's allowed to interact with the desktop is checked in services.
The system reverts its image if it's halted (vmware delta image) (that's how I'm able to duplicate the problem), but I can always change it, which it looks like I might have to do to figure out this problem.
Finally figured it out with some help from the comment here :
http://blogs.msdn.com/b/askie/archive/2013/05/09/user-proxy-settings-showing-up-in-local-system-account-correct-way-to-apply-proxy-settings.aspx#10606266
Looks like the setting actually has to be set in the binary file :
HKEY_Current_User\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections\DefaultConnectionSettings
This binary file doesn't get created in the registry until after graphical login even with the powershell settings I made above. Easiest way is to login (assuming you have the registry settings I made with powershell above, or set it manually through the internet options ui in the gui), export the HKEY_Current_User\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections path, and the import it with :
regedit /s path_to_proxy_settings.reg
If you want it to apply for all users you need to apply the same file under:
HKEY_LOCAL_MACHINE\\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections
as mentioned in the post. There may be other ways as mentioned here https://serverfault.com/questions/34940/how-do-i-configure-proxy-settings-for-local-system , but the above was the easiest for me.

Resources