Your cert is either not importing correctly (so that it is associated with its private key), or it's in the wrong place, or it's not the right type of cert.
If you are installing it correctly the properties will tell you that it is associated with it private key, you will also see the key overlay on the cert icon indicating the same thing. If you're not seeing that then it isn't going to work.
As far as location is concerned it should be in the Personal Certificate store for the machine not the user. The correct way to import it so that it goes in the right place is to open the MMC as administrator, add the Certificates plug in and select the option to use the computer account. Then select the personal store, right click, All Tasks and then import from there.
However it seems most likely to me that the certificate does not have the correct Extended Key Usage OID value in the EKU list. For a certificate to be used for RDP it must have Server Authentication ( 1.3.6.1.5.5.7.3.1 ) somewhere in the list. This is mentioned as the required OID in this Technet article that expands on the requirements for TS certificates in a bit more detail.
There is also a chance that you may have problems if the server name does not match the certificate name - I can't find anything that says they must match but it wouldn't surprise me if they had to.
Keeping the same private key on your root CA allows for all certificates to continue to validate successfully against the new root; all that's required of you is to trust the new root.
The certificate signing relationship is based on a signature from the private key; keeping the same private key (and, implicitly, the same public key) while generating a new public certificate, with a new validity period and any other new attributes changed as needed, keeps the trust relationship in place. CRLs, too, can continue over from the old cert to the new, as they are, like certificates, signed by the private key.
So, let's verify!
Make a root CA:
openssl req -new -x509 -keyout root.key -out origroot.pem -days 3650 -nodes
Generate a child certificate from it:
openssl genrsa -out cert.key 1024
openssl req -new -key cert.key -out cert.csr
Sign the child cert:
openssl x509 -req -in cert.csr -CA origroot.pem -CAkey root.key -create_serial -out cert.pem
rm cert.csr
All set there, normal certificate relationship. Let's verify the trust:
# openssl verify -CAfile origroot.pem -verbose cert.pem
cert.pem: OK
Ok, so, now let's say 10 years passed. Let's generate a new public certificate from the same root private key.
openssl req -new -key root.key -out newcsr.csr
openssl x509 -req -days 3650 -in newcsr.csr -signkey root.key -out newroot.pem
rm newcsr.csr
And.. did it work?
# openssl verify -CAfile newroot.pem -verbose cert.pem
cert.pem: OK
But.. why? They're different files, right?
# sha1sum newroot.pem
62577e00309e5eacf210d0538cd79c3cdc834020 newroot.pem
# sha1sum origroot.pem
c1d65a6cdfa6fc0e0a800be5edd3ab3b603e1899 origroot.pem
Yes, but, that doesn't mean that the new public key doesn't cryptographically match the signature on the certificate. Different serial numbers, same modulus:
# openssl x509 -noout -text -in origroot.pem
Serial Number:
c0:67:16:c0:8a:6b:59:1d
...
RSA Public Key: (1024 bit)
Modulus (1024 bit):
00:bd:56:b5:26:06:c1:f6:4c:f4:7c:14:2c:0d:dd:
3c:eb:8f:0a:c0:9d:d8:b4:8c:b5:d9:c7:87:4e:25:
8f:7c:92:4d:8f:b3:cc:e9:56:8d:db:f7:fd:d3:57:
1f:17:13:25:e7:3f:79:68:9f:b5:20:c9:ef:2f:3d:
4b:8d:23:fe:52:98:15:53:3a:91:e1:14:05:a7:7a:
9b:20:a9:b2:98:6e:67:36:04:dd:a6:cb:6c:3e:23:
6b:73:5b:f1:dd:9e:70:2b:f7:6e:bd:dc:d1:39:98:
1f:84:2a:ca:6c:ad:99:8a:fa:05:41:68:f8:e4:10:
d7:a3:66:0a:45:bd:0e:cd:9d
# openssl x509 -noout -text -in newroot.pem
Serial Number:
9a:a4:7b:e9:2b:0e:2c:32
...
RSA Public Key: (1024 bit)
Modulus (1024 bit):
00:bd:56:b5:26:06:c1:f6:4c:f4:7c:14:2c:0d:dd:
3c:eb:8f:0a:c0:9d:d8:b4:8c:b5:d9:c7:87:4e:25:
8f:7c:92:4d:8f:b3:cc:e9:56:8d:db:f7:fd:d3:57:
1f:17:13:25:e7:3f:79:68:9f:b5:20:c9:ef:2f:3d:
4b:8d:23:fe:52:98:15:53:3a:91:e1:14:05:a7:7a:
9b:20:a9:b2:98:6e:67:36:04:dd:a6:cb:6c:3e:23:
6b:73:5b:f1:dd:9e:70:2b:f7:6e:bd:dc:d1:39:98:
1f:84:2a:ca:6c:ad:99:8a:fa:05:41:68:f8:e4:10:
d7:a3:66:0a:45:bd:0e:cd:9d
Let's go a little further to verify that it's working in real world certificate validation.
Fire up an Apache instance, and let's give it a go (debian file structure, adjust as needed):
# cp cert.pem /etc/ssl/certs/
# cp origroot.pem /etc/ssl/certs/
# cp newroot.pem /etc/ssl/certs/
# cp cert.key /etc/ssl/private/
We'll set these directives on a VirtualHost
listening on 443 - remember, the newroot.pem
root certificate didn't even exist when cert.pem
was generated and signed.
SSLEngine on
SSLCertificateFile /etc/ssl/certs/cert.pem
SSLCertificateKeyFile /etc/ssl/private/cert.key
SSLCertificateChainFile /etc/ssl/certs/newroot.pem
Let's check out how openssl sees it:
# openssl s_client -showcerts -CAfile newroot.pem -connect localhost:443
Certificate chain
0 s:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=server.lan
i:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=root
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
1 s:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=root
i:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=root
-----BEGIN CERTIFICATE-----
MIICHzCCAYgCCQCapHvpKw4sMjANBgkqhkiG9w0BAQUFADBUMQswCQYDVQQGEwJB
...
-----END CERTIFICATE-----
(this should match the actual contents of newroot.pem)
...
Verify return code: 0 (ok)
Ok, and how about a browser using MS's crypto API? Gotta trust the root, first, then it's all good, with the new root's serial number:
And, we should still be working with the old root, too. Switch Apache's config around:
SSLEngine on
SSLCertificateFile /etc/ssl/certs/cert.pem
SSLCertificateKeyFile /etc/ssl/private/cert.key
SSLCertificateChainFile /etc/ssl/certs/origroot.pem
Do a full restart on Apache, a reload won't switch the certs properly.
# openssl s_client -showcerts -CAfile origroot.pem -connect localhost:443
Certificate chain
0 s:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=server.lan
i:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=root
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
1 s:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=root
i:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=root
-----BEGIN CERTIFICATE-----
MIIC3jCCAkegAwIBAgIJAMBnFsCKa1kdMA0GCSqGSIb3DQEBBQUAMFQxCzAJBgNV
...
-----END CERTIFICATE-----
(this should match the actual contents of origroot.pem)
...
Verify return code: 0 (ok)
And, with the MS crypto API browser, Apache's presenting the old root, but the new root's still in the computer's trusted root store. It'll automatically find it and validate the cert against the trusted (new) root, despite Apache presenting a different chain (the old root). After stripping the new root from trusted roots and adding the original root cert, all is well:
So, that's it! Keep the same private key when you renew, swap in the new trusted root, and it pretty much all just works. Good luck!
Best Answer
Sometimes RDS loose certificate binding for static certificates (which are not assigned via GPO). You may need to execute the following command:
Replace
<RDS Server Name>
with actual server name (if executed remotely) and<Thumbprint>
with actual certificate's thumbprint. Thumbprint must specified in hex with no spaces, e.g.F02B346CDC02165543936A37B50F2ED9D5285F62
.For internal machines (which are part of AD forest and accessed via internal names), it is recommended to use GPO-assigned RDS certificates: Configuring Remote Desktop certificates