Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Windows Certificate Store as well as cert_file and key_file #2130

Closed
DavidSimner opened this issue Apr 20, 2021 · 10 comments · Fixed by #3802
Closed

Support Windows Certificate Store as well as cert_file and key_file #2130

DavidSimner opened this issue Apr 20, 2021 · 10 comments · Fixed by #3802
Assignees

Comments

@DavidSimner
Copy link
Contributor

Feature Request

Currently, NATS Server has the options cert_file and key_file for a certificate and its corresponding private key in PEM format. This is great for Linux, but this feature request is for NATS Server on Windows to add additional functionality to support the Windows idiomatic approach.

Windows has a system Certificate Store, and there are various Go libraries to interact with it, e.g. https://github.com/github/certstore and also https://github.com/google/certtostore

I propose that NATS Server supports certificates and their corresponding private keys in the Windows Certificate Store.

Use Case:

In corporate Windows environments, domain administrators will typically run their own CA using the functionality provided by Active Directory Certificate Services (ADCS). For domain-joined machines, this has the capability to automatically generate a private key in the Windows Certificate Store, and then automatically deploy a certificate into that store signed by an ADCS Intermediate/Root CA.

The private key is generated within the Windows Certificate Store, and for the most security the option "Allow private key to be exported" is not allowed. The reason that an administrator does not allow exporting the private key is to help defend against key compromise:
image

The reason for this NATS Server feature request is that NATS Server does not play nicely with this setting. Currently, the NATS Server option key_file requires the private key to be in a PEM file, but in the situation above there is no way to generate that PEM file because the private key can't be exported. Domain certificate administrators are often reluctant to make changes that they feel weaken their security, so it is often intractable to enable export on the template or to generate an exportable certificate using an ad-hoc approach.

Proposed Change:

I propose that NATS Server supports certificates and their corresponding private keys in the Windows Certificate Store. I would like this change to apply to all of the NATS Server features that support TLS.

There are various Go libraries such as https://github.com/github/certstore and also https://github.com/google/certtostore that should hopefully make this relatively easy.

Windows has a separate Certificate Store for the current user as well as for the local machine, and it also has various ways of identifying certificates, e.g. thumbprints, their subjects, their SAN DNS names, etc... There will need to be new NATS Server configuration options to specify which Windows Certificate Store and which certificate (and corresponding private key) in that store.

Who Benefits From The Change(s)?

This will be incredibly beneficial in corporate Windows environments where the certificate (and its corresponding non-exportable private key) is stored in the Windows Certificate Store.

Alternative Approaches

The Windows Certificate Store is the idiomatic approach to store certificates and their corresponding private keys on Windows, and as discussed above the alternative approach of using PEM files is often difficult due to organisational constraints regarding non-exportable private keys.

@philpennock
Copy link
Member

This seems like a reasonable feature request. This comment is just scoping out some of the other things to do to make this viable, since supported features require more than just the glue logic to use a library. So nothing here is an objection, just points to help with scheduling and planning. I am not a Windows programmer, so can't speak to specifics there.

We should probably also support PKCS11 so as to support smartcards and HSMs on POSIX systems, which neither of the listed repositories supports. At least that's easy enough to test with SoftHSM. If we schedule this into feature planning then that should be developed alongside this request.

We'd need to enumerate the failure modes for things like "needs user interaction" to make sure that the nats-server as a service does not start asking for interaction unexpectedly. Against that, we probably would want support in the client side for this feature, for loading either/both TLS client key/cert data or/and JWT credentials from such a trust store, and how to wire in confirmation prompting as part of the library. That would be a feature on nats.go, but is not a blocking feature: just the server-side is a reasonable facet of the work to stand alone.

The hard part here is likely to be testing it and making sure we prevent regressions while having test runners which can exercise it. Neither of the Windows integration repos listed seems to describe how integrators should test that their logic is working or provide working patterns, that I can spot in a quick skim.

So minimally we'd need to have a Windows-specific test which generates keys from an account privileged enough to do so, then deletes them when done, and then we'd need to check we can use them during the test suite. We'd also need to figure out if there are any differences in Windows policy (or how to tune the policy for this) between a locally generated key/cert and a key/cert coming from an AD deployment, to make sure that we're testing the right things.

At present, all of the nats-server testing is done on Ubuntu. If we're adding platform-specific features for other platforms then we should look into expanding our test matrix too, as another requirement.

We'd probably want to update the documentation with screenshots and walkthroughs.

I can't find anything classifying platforms and their support levels: which ones must work for a release, which ones we promise to test with, etc. This WCS feature is a good one to have even if Windows is "minimally" supported and would be a good milestone for moving Windows to "fully supported" if it isn't already.

@dungpa
Copy link

dungpa commented Jan 17, 2023

@philpennock Is there any further progress on this feature request?

@tbeets
Copy link
Contributor

tbeets commented Jan 17, 2023

@dungpa Yes. This feature is planned for the server 2.10.0 release.

You can read about the design here: https://github.com/nats-io/nats-architecture-and-design/blob/certstore/adr/ADR-33.md

Check out the wincert branch of nats-server and build on Windows to try it out.

@dungpa
Copy link

dungpa commented Jan 18, 2023

@tbeets That's excellent news.
We have a new security vulnerability due to NATS's unencrypted PEM files on disk.
So far, we have yet to find an adequate remedy.

Would you happen to know the tentative timeline for the 2.10.0 release?

@tbeets
Copy link
Contributor

tbeets commented Jan 19, 2023

@dungpa We're not too far out on the release. Finishing touches to 2.10.0 feature set now.

@dungpa
Copy link

dungpa commented Jan 22, 2023

@tbeets I have read the ADR on nats-io/nats-architecture-and-design#169.
Kudos for writing it.
It will help solve our existing security vulnerability.

Fingers crossed that the wincert branch makes the cut for the 2.10.0 release.

@dmpriso
Copy link

dmpriso commented Jul 28, 2023

The new cert store feature fits our needs perfectly, but there's an issue with configuration. Some admins don't cleanup their certificate store by removing expired certificates, so selection based on subject or issuer may be ambiguos.

We already configure a certificate for https using httpcfg on the same server, identified by it's fingerprint and want to use that same certificate for NATS.

So it would be great to be able to configure:

tls {
   cert_match_by: "Fingerprint"
   cert_match: "..."
}

@tbeets
Copy link
Contributor

tbeets commented Jul 28, 2023

Makes sense @dmpriso.

Assuming "Fingerprint" here is a SHA-1 hash of the raw certificate bytes? Assuming cert_match would contain the hash in hex representation?

We can look into using the CERT_FIND_SHA1_HASH search option in the underlying windows store.

@tbeets
Copy link
Contributor

tbeets commented Aug 4, 2023

The Cert Store feature for Windows was back ported from the 2.10 train and released in 2.9.20.

@dmpriso I think your issue/ER is a good one. I am going to close this issue. Please create a new issue for adding fingerprint search to Cert Store.

@philpennock
Copy link
Member

To help future spelunkers: the ADR was merged to main with a different number, and the final correct URL is:

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants