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

crypto/x509: Convenient, efficient way to reload a certificate pool after on-disk changes #35887

Open
wking opened this issue Nov 28, 2019 · 4 comments

Comments

@wking
Copy link
Contributor

@wking wking commented Nov 28, 2019

From #24254:

I wonder if there is any real use case for reloading the system cert pool.

One use case is long-running processes that now have to jump through hoops to update their view of the system cert pool (e.g. openshift/cloud-credential-operator#113). On Unix, the loading logic is expensive, traversing multiple directories. But for processes who know they can load certs from a single file, it would be nice to have a way to reload if the backing file had changed but not otherwise. For example, something like:

// NewCertPoolsFromFile parses a series of PEM encoded certificates from the file at the
// given path and records the Stat ModTime of the loaded file.  When the pool is used to
// verify a certificate, it has been more than a minute since the last Stat, and a fresh
// Stat gives a ModTime newer than the cached value, the file is reloaded before being
// used to perform the verification.
func NewCertPoolFromFile(path string) *CertPool

Obviously the "don't bother Stating again" time could be configurable if that seemed important. Or maybe checking the current time is about as expensive as running the Stat, so we should just call Stat on every contains. Or maybe there would be no auto-refresh in contains, but CertPool would become an interface:

type CertPool interface {
  BySubjectKeyID(key string) []*Certificate
  ByName(name string) []*Certificate
}

In which case there could be a from-file CertPool implementation with a Refresh method to trigger the Stat check and possible reload. Or something ;). But having something in the stdlib that could be dropped into tls.Config.RootCAs to get efficient reloads without the caller having to babysit the CertPool would be great. Thoughts?

@dmitshur
Copy link
Contributor

@dmitshur dmitshur commented Dec 2, 2019

@andrewpmartinez
Copy link

@andrewpmartinez andrewpmartinez commented Oct 14, 2021

Have a scenario where I am running with a set of internal CAs that can change (updates, removes, etc). These are not system CAs rather instance-specific CAs. GetClientCertificate and GetCertificate are great for updating client/server certs on the fly w/o starting/stopping listeners. However, there is no equivalent for RootCAs.

GetConfigForClient is the closest thing but at that point access to the original tls.Config isn't provided and a whole-cloth tls.Config needs to be returned. The way the code I am dealing with works, the tls.Config may have been modified or configured and I can not lose those changes.

Adding a function field that can be set (GetRootCas) would be very nice.

@FiloSottile
Copy link
Contributor

@FiloSottile FiloSottile commented Oct 14, 2021

GetConfigForClient is the closest thing but at that point access to the original tls.Config isn't provided and a whole-cloth tls.Config needs to be returned. The way the code I am dealing with works, the tls.Config may have been modified or configured and I can not lose those changes.

Remember that you can't modify most of tls.Config after it's in use.

Anyway, you can make GetConfigForClient a closure that has access to the lexical scope in which the tls.Config is defined, so it can access it and Clone it.

Is the performance motivation for not fully reloading the CertPool still there since we redid the certificate parser? It should be significantly faster now.

@andrewpmartinez
Copy link

@andrewpmartinez andrewpmartinez commented Oct 14, 2021

Anyway, you can make GetConfigForClient a closure that has access to the lexical scope in which the tls.Config is defined, so it can access it and Clone it.

A closure would work for accessing the tls.Config .

Is the performance motivation for not fully reloading the CertPool still there since we redid the certificate parser? It should be significantly faster now.

Performance isn't motivating me. My motivation is to avoid disconnecting clients that have persistent connections. As far as I knew, the only way to provide a new x509.CertPool was to cycle the listener.

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

Successfully merging a pull request may close this issue.

None yet
4 participants