I am trying to create a Remote PowerShell (RPS) that will form connection between machines to execute RPS Commands. I have this following example setup "HostPC with C# console application (that executes RPS) to form connection between two Remote PCs"
The following link (Certificate (password-less) based authentication in WinRM) was found from one of the comments in answer in separate question. From the article, the author presented with high-level approach to create Certificate (password-less) based authentication in WinRM and they are the following:
- Configure SSL connectivity to winrm on the endpoint
- Generate a user certificate used for authentication
- Enable Certificate authentication on the endpoint. Its disabled by default for server auth and enabled on the client side.
- Add the user certificate and its issuing CA certificate to the certificate store of the endpoint
- Create a user mapping in winrm with the thumbprint of the issuing certificate on the endpoint.
So what I have done are the following:
Certificate Authentication Setup:
- Configured WinRM to work with HTTPS in Remote PCs
- Created Client Certificate in HostPC
- Exported the Client Certificate and imported it on the Remote PCs
- Configured WinRM to enable the Certificate Authentication on the Remote PCs
- Created Certificates in each Remote PC
- Binded the Remote PC certificates to the HTTPS Listener
- Created the winrm user mapping using the HostPC certificate in each Remote PC
Configured WinRM to work with HTTPS
winrm quickconfig -transport:https Certificate Creation
New-SelfSignedCertificate ` -DnsName <PCName> ` -CertStoreLocation <CertificateLocation> ` -KeyLength 2048 ` -NotAfter (Get-Date).AddYears(xx) ` -TextExtension @("2.5.29.37={text}<OID Purpose>") Certificate Authentication
winrm set winrm/config/service/auth @{Certificate="true"} Binding Certificate to HTTPS Listener
winrm create winrm/config/Listener?Address=*+Transport=HTTPS "@{Hostname=<RemotePCName>";CertificateThumbprint=<RemotePC Certificate Thumbprint>"}" User Mapping
New-Item -Path WSMan:\localhost\ClientCertificate ` -Subject '<HostPCName>' ` -URI * ` -Issuer <HostPC Certificate Thumbprint> ` -Credential (Get-Credential) C# Application Side:
<Program.cs Section> connectionInfo = new WSManConnectionInfo(new Uri($"https://{MachineName}:5986/wsman"), "http://schemas.microsoft.com/powershell/Microsoft.PowerShell", (PSCredential?)null); connectionInfo.CertificateThumbprint = CertLoader.CertificateLoad(MachineName); <CertificateLoader> public string? CertificateLoad(string? machinename) { X509Store? store = null; X509Certificate2? cert = null; try { if(machinename == null) { <Console Write Message Error> return null; } store = new X509Store(<CertificateLocation>, <CertificateLocationType>); store.Open(OpenFlags.ReadOnly); cert = store.Certificates.OfType<X509Certificate2>().FirstOrDefault(c => c.Subject.Contains($"{machinename}", StringComparison.OrdinalIgnoreCase)); store.Close(); return cert.Thumbprint; } catch (Exception ex) { <Console Write Message Error> return null; } } <In Separate Class> <PowerShell Execution Function> using (runspace = RunspaceFactory.CreateRunspace(connectioninfo)) { runspace.Open(); using (pipeline = PowerShell.Create()) { However, It keeps on failing when it gets to the using (runspace = RunspaceFactory.CreateRunspace(connectioninfo)) with the following error message:
Exception Message: System.Management.Automation.PSInvalidOperationException: The WS-Management service cannot find the certificate that was requested. at System.Management.Automation.Remoting.Client.WSManClientSessionTransportManager.Initialize(Uri connectionUri, WSManConnectionInfo connectionInfo) at System.Management.Automation.Remoting.Client.WSManClientSessionTransportManager..ctor(Guid runspacePoolInstanceId, WSManConnectionInfo connectionInfo, PSRemotingCryptoHelper cryptoHelper, String sessionName) at System.Management.Automation.Runspaces.WSManConnectionInfo.CreateClientSessionTransportManager(Guid instanceId, String sessionName, PSRemotingCryptoHelper cryptoHelper) at System.Management.Automation.Remoting.ClientRemoteSessionDSHandlerImpl..ctor(ClientRemoteSession session, PSRemotingCryptoHelper cryptoHelper, RunspaceConnectionInfo connectionInfo, URIDirectionReported uriRedirectionHandler) at System.Management.Automation.Remoting.ClientRemoteSessionImpl..ctor(RemoteRunspacePoolInternal rsPool, URIDirectionReported uriRedirectionHandler) at System.Management.Automation.Internal.ClientRunspacePoolDataStructureHandler.CreateClientRemoteSession(RemoteRunspacePoolInternal rsPoolInternal) at System.Management.Automation.Internal.ClientRunspacePoolDataStructureHandler..ctor(RemoteRunspacePoolInternal clientRunspacePool, TypeTable typeTable) at System.Management.Automation.Runspaces.Internal.RemoteRunspacePoolInternal.CreateDSHandler(TypeTable typeTable) at System.Management.Automation.Runspaces.Internal.RemoteRunspacePoolInternal..ctor(Int32 minRunspaces, Int32 maxRunspaces, TypeTable typeTable, PSHost host, PSPrimitiveDictionary applicationArguments, RunspaceConnectionInfo connectionInfo, String name) at System.Management.Automation.Runspaces.RunspacePool..ctor(Int32 minRunspaces, Int32 maxRunspaces, TypeTable typeTable, PSHost host, PSPrimitiveDictionary applicationArguments, RunspaceConnectionInfo connectionInfo, String name) at System.Management.Automation.RemoteRunspace..ctor(TypeTable typeTable, RunspaceConnectionInfo connectionInfo, PSHost host, PSPrimitiveDictionary applicationArguments, String name, Int32 id) at System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace(RunspaceConnectionInfo connectionInfo, PSHost host, TypeTable typeTable, PSPrimitiveDictionary applicationArguments, String name) at System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace(RunspaceConnectionInfo connectionInfo, PSHost host, TypeTable typeTable) at System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace(PSHost host, RunspaceConnectionInfo connectionInfo) at System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace(RunspaceConnectionInfo connectionInfo) In addition, (I can't remember what I have done) Before I got the error above, it failed in the runspace.Open(); part with the following message:
System.Management.Automation.Remoting.PSRemotingTransportException: 'Connecting to remote server xxxxxxxxx failed with the following error message : WS-Management cannot process the request. The operation failed because of an HTTP error. The HTTP error (12186) is: The client certificate credentials were not recognized. . For more information, see the about_Remote_Troubleshooting Help topic.' So, Can anyone help me:
- Identify what I did wrong?
- Understand how to fix these error messages?
CertLoader.CertificateLoad(MachineName);in the client application. The identity of the calling machine doesn't change because the target PC does.