nats-io / nats-server

High-Performance server for NATS.io, the cloud and edge native messaging system.
https://nats.io
Apache License 2.0
16.03k stars 1.41k forks source link

Server loads incorrect certificate from Windows Certificate Store #6024

Closed wooti closed 1 month ago

wooti commented 1 month ago

Observed behavior

I start nats-server.exe with the following configuration:

tls: {
  cert_store: "WindowsLocalMachine"
  cert_match_by: "Subject"
  cert_match: "MyCertificate"
  timeout: 2
}
jetstream: enabled
host: my.local.machine

My Windows Certificate Store has multiple test certificates defined, with similar subject names. One is called MyCertificate, another MyCertificateForClient. The former is fully trusted (as it is also registered as a Trusted Root CA), and is the certificate I expect the server to load.

Expected behavior

The server loads certificate MyCertificateForClient. I am unable to connect to the server, with the following error:

nats: error: tls: failed to verify certificate: x509: certificate signed by unknown authority

Server and client version

nats-server: v2.10.22

Host environment

Windows 10, AMD64

Steps to reproduce

It looks like this is due to use of CERT_FIND_ISSUER_STR or CERT_FIND_SUBJECT_STR, more details here. The lookup is for a certificate that "contains the specified string", which both of my test certificates satisfy.

Furthermore, certificates within the store are unordered, and I also suspect that the server could retrieve expired, revoked or untrusted certificates in favour of one that can actually be used.

I found a comment with similar issue here. The follow up here makes sense to me - if I could specify a certificate by thumbprint I could guarantee that the correct certificate is loaded.

See also

https://github.com/nats-io/nats-server/issues/2130 https://github.com/nats-io/nats-architecture-and-design/blob/main/adr/ADR-39.md

neilalexander commented 1 month ago

Have prepared a branch that should let you specify the certificate by the SHA1 thumbprint instead:

tls: {
  cert_store: "WindowsLocalMachine"
  cert_match_by: "thumbprint"
  cert_match: "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12"
  timeout: 2
}

Can you please give it a try?

https://binaries.nats.dev/binary/github.com/nats-io/nats-server/v2?os=windows&arch=amd64&version=21ad69a5

wooti commented 4 weeks ago

Can you please give it a try?

Hi @neilalexander, many thanks for having a look at this issue! Unfortunately I wasn't able to make this work with the binary provided.

nats-server: .\nats-streaming.conf:1:0: unable to find certificate in store
wooti commented 4 weeks ago

I wonder if CERT_FIND_SHA1_HASH or CERT_FIND_HASH should be used instead of CERT_FIND_HASH_STR in https://github.com/nats-io/nats-server/blob/main/server/certstore/certstore_windows.go#L63 ?

neilalexander commented 4 weeks ago

Hmm, you could be right, can you try this instead?

https://binaries.nats.dev/binary/github.com/nats-io/nats-server/v2?os=windows&arch=amd64&version=24eefd85

wooti commented 4 weeks ago

No luck I'm afraid, same error message

neilalexander commented 4 weeks ago

Ah, I see the problem. CERT_FIND_HASH_STR is indeed correct but it needs the string input, not the decoded form.

Please give this one a go — I've tested it on a Windows virtual machine:

https://binaries.nats.dev/binary/github.com/nats-io/nats-server/v2?os=windows&arch=amd64&version=7eb387a5

wooti commented 4 weeks ago

Amazing! That one is working great

neilalexander commented 4 weeks ago

Thanks for confirming, have raised PR #6047.