I have the following trivial docker file:
FROM mcr.microsoft.com/windows/servercore:ltsc2019
WORKDIR /azp
COPY test.ps1 .
CMD powershell .\test.ps1
Where test.ps1 is:
C:\test> cat .\test.ps1
curl https://cnn.com -UseBasicParsing
The script can run just fine on my machine, but not in a docker container:
C:\test> docker build -t test:latest .
Sending build context to Docker daemon 75.26kB
Step 1/4 : FROM mcr.microsoft.com/windows/servercore:ltsc2019
---> 782a75e44953
Step 2/4 : WORKDIR /azp
---> Using cache
---> b43270631602
Step 3/4 : COPY test.ps1 .
---> Using cache
---> 10cfc66cff37
Step 4/4 : CMD powershell .\test.ps1
---> Using cache
---> 187be18c5495
Successfully built 187be18c5495
Successfully tagged test:latest
C:\test> docker run test
curl : The underlying connection was closed: Could not establish trust
relationship for the SSL/TLS secure channel.
At C:\azp\test.ps1:1 char:1
+ curl https://cnn.com -UseBasicParsing
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:Htt
pWebRequest) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShe
ll.Commands.InvokeWebRequestCommand
Note that replacing https://cnn.com (https) with http://google.com (http) works, so this is clearly something about the https.
What am I missing?
P.S.
I am using Windows 10 with the most recent docker switched to use windows containers.
So I managed to make it work for https://google.com by following these steps:
Navigate to https://google.com and check what is the root certificate. It is a certificate with thumbprint 75E0ABB6138512271C04F85FDDDE38E4B7242EFE
Export the aforementioned certificate as well as the ZScaler root certificate (D72F47D87420E3F0F9BDCAC6F03A566743C481B9) to a special directory that will be included in the image under C:\containers.
Modify the test.ps1 script - see below.
Modify the Dockerfile script - see below.
test.ps1
Get-ChildItem /certificates | ForEach-Object {
$null = Import-Certificate -FilePath $_.FullName -CertStoreLocation Cert:\LocalMachine\Root
}
$res = Invoke-WebRequest https://google.com -UseBasicParsing
$res.StatusDescription
Dockerfile
FROM mcr.microsoft.com/windows/servercore:ltsc2019
COPY certificates certificates
WORKDIR /azp
COPY test.ps1 .
CMD powershell .\test.ps1
So, on the host machine I run the following commands:
C:\test> $certs = dir Cert:\LocalMachine\Root |? { $_.Thumbprint -eq '75E0ABB6138512271C04F85FDDDE38E4B7242EFE' -or $_.Thumbprint -eq 'D72F47D87420E3F0F9BDCAC6F03A566743C481B9' }
C:\test> $certs
PSParentPath: Microsoft.PowerShell.Security\Certificate::LocalMachine\Root
Thumbprint Subject
---------- -------
D72F47D87420E3F0F9BDCAC6F03A566743C481B9 E=support#zscaler.com, CN=Zscaler Root CA, OU=Zscaler Inc., O=Zscaler Inc., L=San Jose, S=California, C=US
75E0ABB6138512271C04F85FDDDE38E4B7242EFE CN=GlobalSign, O=GlobalSign, OU=GlobalSign Root CA - R2
C:\test> $certs |% { Export-Certificate -FilePath "c:\test\certificates\$($_.Thumbprint).cer" -Cert $_ }
Directory: C:\test\certificates
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 1/5/2020 8:40 PM 1239 D72F47D87420E3F0F9BDCAC6F03A566743C481B9.cer
-a---- 1/5/2020 8:40 PM 958 75E0ABB6138512271C04F85FDDDE38E4B7242EFE.cer
C:\test> docker run test
OK
C:\test>
It looks like your container is not able to verify TLS server certificate. Probably CA certificates (maybe they have different technical term in the Windows) are missing in the container.
You can:
-SkipCertificateCheck (available from PowerShell V6.0+), so TLS cert verification will be skipped - good choice for development, but it will sacrifice security partially
"mount Windows hosts certificate store in container" - Docker forum
Related
I am trying to use the Web Administration module in a powershell script to deploy a handful of IIS websites and application pools using the visual studio post build event command line. When I run the script without using the web administration module the script succeeds, however I get an access denied error when they are included.
I have visual studio running as administrator
I have tried all sorts of flavor of setting the execution policy, but right now this is what I have (I have tried running both 32 and 64 bit versions of powershell):
cd $(ProjectDir)
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -NoProfile -NonInteractive -File "SetupLocalEnvironment.ps1" 2> nul
Looking for some assistance as my research is starting to reach the fruitless point. Thanks!
Here is the powershell script:
Import-Module WebAdministration
$FNMAWorkSpaceDirectory = "x"
# Do not edit below
Remove-Website -Name EDI
Remove-Website -Name WebAPI
Remove-WebAppPool -Name EDIAppPool
Remove-WebAppPool -Name WebAPIAppPool
New-WebAppPool EDIAppPool
New-WebSite -Name EDI -Port 124 -PhysicalPath "thePath" -ApplicationPool "thePool"
New-WebBinding -Name "EDI" -Protocol "https" -IPAddress "*" -Port 125
New-WebAppPool WebAPIAppPool
New-WebSite -Name WebAPI -Port 123 -PhysicalPath "thePath" -ApplicationPool "WebAPIAppPool"
Set-Location Cert:\LocalMachine\My
$certHash = (Get-ChildItem -DnsName "theCertName").Thumbprint
$guid = [guid]::NewGuid()
$Command = "http add sslcert ipport=0.0.0.0:125 certhash=$certHash appid={$guid}"
$Command | netsh
exit
I have an installed Windows Server 2016 Technical Preview 4 on VMware
Warkstation.
It has 2 GB RAM and 60 GB disk space.
I try to install Windows Server Host for Docker according to official Microsoft instruction.
Instruction in general in the picture
I don't need a Hyper-V Containers technology so for this guide i don't have to make steps marked with a one asterisk '*'
So we have six steps that we have to do for install Windows Server Host and Docker:
Install the Container Feature
Create Virtual Switch
Configure NAT
Configure MAC Address Spoofing
Install Container OS Images
Install Docker **
I have a problem in step two: Creat Virtual Switch while typing next cmdlet in PowerShell:
PS C:\> New-VMSwitch -Name "Virtual Switch" -SwitchType NAT -NATSubnetAddress 172.16.0.0/12
New-VMSwitch : Failed while adding virtual Ethernet switch connections.
Internal miniport create failed, name = '8A407781-1BF5-4BB0-8538-35CFF056C598', friendly name = 'vEthernet (Virtual Switch)', MAC = 'DYNAMIC': One or more arguments are invalid
(0x80070057).
At line:1 char:1
+ New-VMSwitch -Name "Virtual Switch" -SwitchType NAT -NATSubnetAddress ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [New-VMSwitch], VirtualizationException
+ FullyQualifiedErrorId : InvalidParameter,Microsoft.HyperV.PowerShell.Commands.NewVMSwitch
What should I do in this case?
I was able to install docker using Microsoft guide about auto-install instead of using manual guide:
# Auto-install instruction.
PS C:\> powershell.exe
PS C:\> start-process powershell -Verb runas
PS C:\> wget -uri https://aka.ms/tp4/Install-ContainerHost -OutFile C:\Install-ContainerHost.ps1
PS C:\> C:\Install-ContainerHost.ps1 -HyperV
# Wrong!
But there is an error in the last line in key -HyperV.
We need to ingore it, so the last line looks like:
PS C:\> powershell.exe
PS C:\> start-process powershell -Verb runas
PS C:\> wget -uri https://aka.ms/tp4/Install-ContainerHost -OutFile C:\Install-ContainerHost.ps1
PS C:\> C:\Install-ContainerHost.ps1
# Currect!
Using correct instruction i was able to install docker.
I had the same error on a Nano Server the first time I ran:
PS C:\> New-VMSwitch -Name "Virtual Switch" -SwitchType NAT -NATSubnetAddress 172.16.0.0/12
SwitchType NAT is definitely correct because the command doesn't accept the NATSubnetAddress parameter for anything other then a NAT switchtype.
Run it a second time and then it worked on my Nano Server.
I'm new to programming and am trying to write a powershell script.
I'm in a windows domain environment with over 50 remote offices. Each office has 4 computers. One computer, "Computer A," has dropbox installed that we use for backups, and now software updates. I want to execute a script from my local machine that copies a folder (~1 GB) to the other computers in that LAN, and runs the setup.exe file in the directory to update software on these computers.
As far as I can tell in order to use the Enter-pssession cmdlet & run a copy-item and start process, I have to:
On remote machine enable winrm by: enable-psremoting -force
On remote machine enable CredSSP authentication by: enable-smancredssp -role server -force
On local machine enable CredSSP authentication by: enable-SmanCredSSP -role
client -force
From here I can enter the Power shell session and begin the copy and install. Here is the code I'm running:
#Allow my computer to send credentials to remote computers
Enable-WSManCredSSP -Role Client -DelegateComputer * -Force
$credential = Get-Credential -Credential domain\user
#Getting Content
$path = "C:\computernames.csv"
Import-Csv -path $path |
foreach-object {
$computername = $_.Name
if (Test-Connection -cn $_.Name -quiet) {
#copy the batch file that allows remote powershell access
$source = "c:\"
$destination = "\\$computername\c$\install files\remoteaccess"
robocopy $source $destination
#open file to allow remote PS access
& psexec \\$computername -a runas -u domain\user -p password -c -f -h "\\$computername\c$\install files\remoteaccess\remoteaccess.bat"
#Initiates Power Shell session with remote computer
Enter-PSSession -cn $_.Name -Credential $credential -Authentication Credssp
#begin copy
#be sure to refine destination
copy-item -path $_.Source -Destination $_.Destination -force -verbose -recurse | out-file c:\copylog.txt
#begin silent install
#code here
#stop wsmancredssp accep
disable-wsmancredssp -role server
#close pssession
exit-pssession
} else {
"$computername is not online"
}
}
Disable-wsmancredssp -role client
The computernames.csv has the headers: Name, Source, Destination with UNC directories for each LAN's computer with dropbox and where to copy the file.
The "remoteaccess.bat" file contains the following two lines of code:
powershell.exe enable-psremoting -force >>c:\remotelog.txt
powershell.exe Enable-WSManCredSSP -role Server -force >>c:\remotelog.txt
The powershell window freezes after initiating the psexec session with the remote computer and sends the first powershell command to enable remoting. No error is generated, or input requested. The output of this command is saved in the remotelog text file:
"WinRM has been updated to receive requests.
WinRM service started.
WinRM already is set up for remote management on this machine."
It appears the powershell command to enable wsmancredssp is never received. When I run the batch file on the remote computer from remote access software, both commands execute and are logged successfully. Where is my psexec command going wrong, or how can I setup these computers to allow remote sessions with a remote command without using GPO?
I was testing some nodejs server code and wanted to test the urls from windows power shell using the curl command. Some things to note here:
1. I have mingw and git bash installed in my system, and curl works fine from normal command prompt and git bash prompt.
2. Additionally I have downloaded the latest version of cURL from curl official web site and added the path of bin directory to the system's PATH variable.
But it seems like it is no good for power shell. However, powershell still recognizes cURL command regardless of additional cURL program or git bash present in the system or not. But it does not work as I expected it to be, for example I have tried the following command and:
Windows PowerShell
Copyright (C) 2013 Microsoft Corporation. All rights reserved.
PS C:\Users\Zobayer Hasan> curl -X GET -i localhost:8080
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'X'.
At line:1 char:6
+ curl -X GET -i localhost:8080
+ ~~
+ CategoryInfo : InvalidArgument: (:) [Invoke-WebRequest], ParameterBindingException
+ FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
PS C:\Users\Zobayer Hasan> curl GET -i localhost:8080
curl : Cannot find drive. A drive with the name 'localhost' does not exist.
At line:1 char:1
+ curl GET -i localhost:8080
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (localhost:String) [Invoke-WebRequest], DriveNotFoundException
+ FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
PS C:\Users\Zobayer Hasan> curl GET -i http://localhost:8080
curl : Cannot find drive. A drive with the name 'http' does not exist.
At line:1 char:1
+ curl GET -i http://localhost:8080
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (http:String) [Invoke-WebRequest], DriveNotFoundException
+ FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
PS C:\Users\Zobayer Hasan>
But when I try it in normal command prompt, it works fine:
C:\Users\Zobayer Hasan>curl -X GET -i localhost:8080
HTTP/1.1 200 OK
Date: Wed, 31 Dec 2014 09:35:31 GMT
Connection: keep-alive
Transfer-Encoding: chunked
Server connection was called
C:\Users\Zobayer Hasan>
I also get the same output when I try it from git bash.
My question here is what do I need to do if I want everything to run smooth in windows power shell as well? I have done a little bit of searching on the net, and could not find much helpful resources. Also I have not any prior experience with windows powershell. Usually use linux as development environment.
It looks like you already have curl as an alias to Ivoke-WebRequest:
Invoke-WebRequest : A parameter cannot be found that matches parameter
name 'X'.
Try running remove-item alias:\curl and see if you now get the right curl being invoked. Alternatively, try by specifying the absolute path, i.e. c:\curl\curl.exe ....
Since I updated to PowerShell 4.0, an Alias was created to point to Invoke-WebRequest with the name of curl, so what I've done is I added my own alias to the curl.exe executable I want to use instead:
set-alias mcurl "C:\cygwin\bin\curl.exe"
Powershell 4.0
Get-Alias curl
CommandType Name ModuleName
----------- ---- ----------
Alias curl -> Invoke-WebRequest
My new Alias:
Get-Alias mcurl
CommandType Name ModuleName
----------- ---- ----------
Alias mcurl -> curl.exe
I have written a powershell script which creates a powershell script or a batch script depending on the remote host on which this script should be started remotely (either via powershell invoke-command or psexec).
The script creates either a powershell or a batch script, because not all hosts on which these created scripts should be run support WinRM (Windows Remote Management).
The created scripts include some psexec lines which executes a command on another remote host. The created batch script works as expected, but from the created powershell script i get the following errors from the psexec calls.
NotSpecified: (:String) [], RemoteException
+ CategoryInfo : NotSpecified: (:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
+ PSComputerName : <HOSTNAME REPLACED>
PsExec v2.1 - Execute processes remotely
Copyright (C) 2001-2013 Mark Russinovich
Sysinternals - www.sysinternals.com
The handle is invalid.
Access is denied.
Connecting to 10.XXX.XXX.127...Couldn't access 10.XXX.XXX.127:
Starting PSEXESVC service on 10.XXX.XXX.127...Could not start PSEXESVC service on 10.XXX.XXX.127:
Connecting to 10.XXX.XXX.127...Starting PSEXESVC service on 10.XXX.XXX.127...
Here is a small overview of what is done:
Powershell script on deployment host creates the rollout script (ps1 or batch) depending on the destination host
Powershell script on deployment host starts the created rollout script on the destination host
Powershell will be started via Invoke-Command -ComputerName <destination host> -FilePath <path to created script> -Authentication default
Batch will be started via & psexec.exe \\<destination host> -n 60 -accepteula -c -f <path to created script>
Created rollout script on the destination host executes a psexec command to start a service on a third host (this fails only if the rollout script is powershell)
This is the psexec command which fails if executed via a remotely started powershell script.
& psexec.exe \\<destination host> -n 60 -accepteula -u <user> -p <password> net stop <servicename>
The same command psexec.exe \\<destination host> -n 60 -accepteula -u <user> -p <password> net stop <servicename> executed via a remotely started batch script works without problems.
Update #1
Also if i connect to the destination host with rdp and start a powershell shell and paste the command it works without issues. The problem only occurs if started remotely.
I already tried the following variants of starting psexec, all without luck!
& psexec.exe \\<destination host> -n 60 -accepteula -s -u <user> -p <password> net stop <servicename>
Start-Process cmd.exe -Credential "<domain>\<user>" -WorkingDirectory $env:systemdrive -ArgumentList "/C psexec.exe \\<destination host> -n 60 -accepteula -u <user> -p <password> net stop <servicename>"
Start-Process powershell.exe -WorkingDirectory $env:systemdrive -Verb Runas -ArgumentList "cmd.exe /C psexec.exe \\<destination host> -n 60 -accepteula -u <user> -p <password> net stop <servicename>"
can you try to replace your psexec command, and use cmd.exe like thisn also add -s to psexec so it will run as system user. My testing command :
icm -cn computer1 -ScriptBlock{ cmd.exe "/c psexec -s -u <login> -p <password> /accepteula /n 10 \\computer2 net start audiosrv"}
You are running into the Second Hop problem:
http://blogs.technet.com/b/heyscriptingguy/archive/2012/11/14/enable-powershell-quot-second-hop-quot-functionality-with-credssp.aspx
The answer is to enable the appropriate relationship between the two computers involved (see previous link or just search google for 'powershell' and 'second hop') and to add to Invoke-Command:
-Authentication Credssp -Credential
What worked for me was:
Start-Process -FilePath .\PsExec.exe -ArgumentList "/acceptEula /s \$Computer program.exe /arg"