Can't Bind Certificate to SSL When Imported using .NET API - powershell

I've created a self-signed SSL certificate using openssl. When I import the certificate using the .NET APIs, I can't bind it to my website with netsh. I'm importing the certificate with PowerShell:
$Certificate = New-Object 'security.Cryptography.X509Certificates.X509Certificate2' $PathToCertificate
$keyFlags = [Security.Cryptography.X509Certificates.X509KeyStorageFlags]::MachineKeySet
$keyFlags = $keyFlags -bor [Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet
$keyFlags = $keyFlags -bor [Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable
$store = New-Object 'Security.Cryptography.X509Certificates.X509Store' 'My','LocalComputer'
$store.Open( 'ReadWrite' )
$store.Remove( $Certificate )
$store.Add( $Certificate )
$store.Close()
I then use netsh to bind to the certificate:
netsh http add sslcert ipport=0.0.0.0:443 certhash=<thumbprint> appid=<app ID>
Which succeeds the first time run, but fails on subsequent attempt with this error:
SSL Certificate add failed, Error: 1312
A specified logon session does not exist. It may already have been terminated.
However, when I import the certificate manually through the Certificates MMC/snap-in, I never have any problems running the netsh command.
I'm seeing this error on some of our Windows 7 and Windows 2012 R2 computers. Strangely, more than half our computers don't have this problem. Am I adding the cert incorrectly? Could I have generated a bad certificate?

I lied. Looks like I thought I was setting the key storage flags in the code above. Turns out I was loading the certificate in a different part of our script, and it wasn't specifying the correct key storage flags. After correcting my script so it actually does what I claimed it did, everything works.

Related

Add certificates the same way the Certificate Import Wizard does [Powershell]

I have configured a powershell script, which creates a vpn conection profile.
To make it work i need to add proper certificate.
Everything works fine when i add a certificate manually to local machine:
More detailed regarding importing certificate manualy:
Info
I'm trying to perform this task via powershell, but it doesn't work (script seems to work, but i am not sure to which stores should i copy certificate). In contrary to manual method - the certificate added by my powershell script is invisible for vpn connection.
#add certificate
$cert_name=$env:USERNAME+"#vpn.contoso.com.p12"
$cert_loc="\\ad\deploy\other\certs\"+$cert_name
$secure_pwd = ConvertTo-SecureString "contoso987%#" -AsPlainText -Force
Import-PfxCertificate -FilePath $cert_loc -CertStoreLocation Cert:\LocalMachine\My -Password $secure_pwd
# Add vpn connection
Add-VpnConnection -Name "Example VPNX" -ServerAddress "vpn.example.com" -AuthenticationMethod "MachineCertificate" -TunnelType "IKEv2" -EncryptionLevel "Maximum" -SplitTunneling $True
I would like to do it the same way the certificate import wizard does. Does anyone have experience in that ?
PS
I've changed addresses in codes etc.
Kind Regards,
Tamara
I've decided to post the solution. Although it is not developed in powershell it solves the problem completely. It is possible to import these kind of certificates from command prompt:
certutil -f -p Some_password -importpfx "\\ad\somepath\certificate.p12"

TeamCity Remote Powershell Access Denied Suddenly

Disclaimer: I am not a DevOps guy so please forgive any ignorance. I'm learning this stuff to expand my understanding.
I've enabled remote Powershell on a Windows Server 2019 instance in order to stop/start scheduled tasks during deployment of files from my build server (also Windows Server 2019).
I followed the below steps in an Administrator Powershell as the Adminstrator user on the remote server:
1. Enable RSRemoting.
2. Remove existing listener.
3. Create self-signed certificate and export to crt file.
$Cert = New-SelfSignedCertificate -CertstoreLocation Cert:\LocalMachine\My -DnsName "<subdomain.domain.com>"
Create listener.
Create firewall rules to allow secure PSRemoting and disable unsecure connections.
Copy certificate to build server.
Import certificate on build server.
From the build server, I've tested the configuration using the following commands in Powershell:
$username = 'Administrator'
$pass = ConvertTo-SecureString -string '<password here>' -AsPlainText -Force
$cred = New-Object -typename System.Management.Automation.PSCredential -argumentlist $username, $pass
Invoke-Command -ComputerName <subdomain.domain.com> -UseSSL -ScriptBlock {whoami} -Credential $cred
Which responds nicely with win-<some stuff>\administrator. However, when I execute a remote Powersehll command from within a TeamCity build step, I get a big ugly Connecting to remote server <subdomain.domain.com> failed with the following error message : Access is denied..
The weird part is, this worked two days ago and I have several builds that were able to complete all remote operations. From this morning, it's just stopped working - poof!
If I fudge the credentials, I do get an incorrect username/password error so it is definitely reaching the server.
Another interesting find is that if I run
[bool](Test-WSMan)
on the remote server, I get True returned, but if I run the same command with -ComputerName <subdomain.domain.com> on the build server, I get
WinRM cannot complete the operation. Verify that the specified computer name is
valid, that the computer is accessible over the network, and that a firewall exception for the WinRM service is enabled and allows access from this computer. By default, the WinRM firewall exception for public profiles limits
access to remote computers within the same local subnet. returned.
Both the remote host and build server are logged on as the default Administrator.
Any ideas?
After more research and calling in a few favours, I was advised to tweak the TeamCity Build Agent and TeamCity Server services. These need to Log On As a User and not Local System. I can't explain how my previous settings worked. The Access is denied error I experienced has nothing to do with the Remote Powershell configuration mentioned above.

IIS 10 - Import SSL certificate using Powershell - "A specified logon session does not exist"

Importing a .pfx-file to IIS using Powershell is pretty straight forward thanks to guidelines such as this one Use PowerShell to install SSL certificate on IIS. But I do run into an issue when trying to bind port 443 using the imported certificate:
Error: "A specified logon session does not exist. It may already have been terminated. (Exception from HRESULT: 0x80070520)".
This due to "...If you don't already have a cer version, or you do but it includes the private key, enable Allow this certificate to be exported..." (ref. Setup of SharePoint 2013 High-Trust On-premise Add-In Developer / Production environment)
This is how it is set in the GUI
But, looking at the following line in the code which I got from dejanstojanovic.net.
pfx.Import($certPath,$certPass,"Exportable,PersistKeySet")
it is set to Exportable. Removing PersistKeyset does not make a difference. So what could causing this?
The script is not able to set it to Exportable as in the GUI "Allow this certificate to be exported"
...I'm all out of options...
Update
I did tweak the code a bit, using constants and such, but still same issue
$certPath = "D:\ssl\cert-export-to-iis-10.pfx"
$certPass = "password"
$pfx = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$KeyStorageFlags = [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable -bxor [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet
$pfx.Import($certPath,$certPass,$KeyStorageFlags)
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store("WebHosting","LocalMachine")
$store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite)
$store.Add($pfx)
$store.Close()
$store.Dispose()

Self-signed certificates limited to a host?

I am generating self-signed .pfx certificates for a java application running on a couple of Windows servers. These certificates will be imported into their respective java keystores.
My question is: Can I generate a self-signed certificates for server2, server3 and server4 on server1? Is there anything in a certificate, apart from the dns name, that would bind it to the machine on which it was generated?
My concern is that if I generate the certificate for server2 on server1, the certificate will still be somehow bound to server 1 only.
I am using the following powershell script to generate the certificates:
$cert = New-SelfSignedCertificate -keyfriendlyname server1 -certstorelocation cert:\localmachine\my -dnsname server1.mydomain.com
Export-PfxCertificate -cert ‘cert:\localMachine\my\’ -FilePath C:\Certificates\server1.pfx -Password dummypassword
My idea was to simplify the process of generating the certificates by running the script on a single server and just altering the dnsname, alias and file name for each certificate.
You can generate a certificate on any machine for any machine, just set the common name correctly (certificate's CN field).
See parameter -Subject of the PowerShell command
Note that moving private keys around is a bad practice, you should instead generate the key-pair on the same machine that it is to be used by.

Importing certificate to certificate store with power shell script doesn't work but manually works

I am creating SSL certificate to bind to my website. I am using power shell script to automate my process from creation to importing the certificate to Certificate store. Once I bind the certificate to my website, my website does not work. but if I manually import the certificates to the certificate store and bind it to my website. I do no face any issues.
I am calling a script which adds root certificate to Trusted Root and client certificate to Personal store.
$pfx = new-object System.Security.Cryptography.X509Certificates.X509Certificate2
$rootCertImportPath = $runtimeDirPath + $rootCertName
$pfx.import($rootCertImportPath,$rootCAPass,"Exportable,PersistKeySet")
$store = new-object System.Security.Cryptography.X509Certificates.X509Store(
[System.Security.Cryptography.X509Certificates.StoreName]::Root,
"localmachine"
)
$store.open("MaxAllowed")
$store.add($pfx)
$store.close()
I am trying to import .cer file extension using $pfx.import call.
Do i need to pass additional arguments to the below mentioned function ?
$pfx.import($rootCertImportPath,$rootCAPass,"Exportable,PersistKeySet")
Please help me out!
You aren't importing the PFX, you are importing only public certificate without private key. So the correct call is:
$pfx.import($rootCertImportPath)
no other arguments are used.