Bug #3143
Puppet should correctly support CA trust chains
| Status: | Accepted | Start date: | 02/03/2010 | |
|---|---|---|---|---|
| Priority: | High | Due date: | ||
| Assignee: | - | % Done: | 0% |
|
| Category: | SSL | |||
| Target version: | Telly | |||
| Affected Puppet version: | 0.25.3 | Branch: | ||
| Keywords: | ||||
| Votes: | 3 |
Description
It would be very, very useful for Puppet to use existing enterprise-deployed PKI systems, rather than relying somewhat on the creation of its own self-signed CA.
Here is some background:
For a few months, I have been using 0.24.8 in production. I used the techniques described in the wiki (multiple CA certificates) to override the local CA certificate, setting localcacert in puppet.conf to the PEM bundle. This required a slight hack to prevent Puppet from overwriting the file, but it worked and verified correctly.
My PKI setup is fairly simple: I have a global root, which has a subordinate network CA, which has signed the Puppet CA (A->B->C).
I have recently upgraded to 0.25.4 and this has broken entirely (see http://pastebin.ca/1776458 for a client debug; the server side never sees the request because it doesn’t even get that far). I have tried both with a brand new client and an upgrade of an existing one – the errors are the same, failure to validate certificates.
From looking at cert_setup in network/http_pool.rb, Puppet will set the ca_file and SSL store as appropriate, but neither of these are seemingly sufficient to verify a trust chain. However, when I commented out usage of the certificate store and CA file (http://pastebin.ca/1776467) and used ca_path instead (set to an OpenSSL-hashed cert dir) containing A,B, and C’s PEM files, the verification succeeds, which confuses me greatly.
I also tried directly modifying the certificate store passed to the http object to load my certificates directly into the store (via add_file) and this also does not verify.
I notice that WEBrick deals with this issue by modifying the SSL context directly (extra_chain_cert). Is it possible for Puppet to do something similar? The property is not directly exposed from http.rb. When I have done testing with Puppet using WEBrick, modifying the appropriate WEBrick code to set the property to the appropriate trust chain (A and B) also works correctly, allowing the verification to succeed.
I apologize in advance if if I am overlooking something or doing it wrong.
In addition, I am happy to diagnose/debug/investigate this issue, if it is helpful, and write a patch for it if necessary, but my ruby/ruby openssl familiarity is minimal.
Related issues
History
Updated by Justin Baugh about 2 years ago
- Priority changed from High to Normal
Updated by James Turnbull about 2 years ago
- Status changed from Unreviewed to Investigating
- Assignee set to Markus Roberts
Updated by Nicholas Veeser about 2 years ago
- Affected Puppet version changed from 0.25.4 to 0.25.3
I will throw in my two cents, since I am up against the exact same problem. I am using a Cert chain that is part of an existing PKI solution.
The issue as I have diagnosed it is related to CRL being found
I have filed two bugs related to this:
All puppetmasterd will run in CA mode http://projects.reductivelabs.com/issues/3141 As such, the server will respond to REST requests for a CRL, creating one if necessary.
I cannot seem to find a way to tell the Client (Configurer/Agent) to stop looking for and using the CRL returned by its puppetmaster. http://projects.reductivelabs.com/issues/3168
Detail At some point, the Puppet::SSL::Host.ssl_store will initialize a OpenSSL::X509::Store with the certificate from Puppet[:localcert]
Optionally it will look for a CRL which is either cached locally or pulled from REST. If a CRL is found, it then enables “CRL checking” by flag in the SSL store (for use during SSL verification process). And given the above bugs, some a CRL can almost always be found.
if crl = Puppet::SSL::CertificateRevocationList.find("ca")
Puppet.info "USING CRL: #{crl.content.issuer} Revoked: #{crl.content.revoked}"
@ssl_store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL|OpenSSL::X509::V_FLAG_CRL_CHECK
@ssl_store.add_crl(crl.content)
end
I think (though I don’t know openssl that well), that for each cert in the verification chain, there must exist a CRL (named by ‘issuer’) signed by that cert. And with only 1 CRL and 3 certs in the CA chain, all verification will fail. For me, the failure happens when the current cert is Cert 2, (where 0 is the identity cert to verify, 1 signed 0, 2 signed 1, etc…) and the error returned during verify is (3): unable to get certificate CRL
Summary In the standard “Puppet is the CA” use case, the Cert chain is only one deep, so only one CRL (from the CA) is needed. If the cert chain is deeper, the CRL solution, as implemented breaks down, and Cert verification will always fail.
Sidenote FWIW I also filed this request: http://projects.reductivelabs.com/issues/3169
The code I added showed much more clearly what is happening in the X509 verification process which happens as part of SSL negotiation. ruby/OpenSSL does not seem to be very informative at this level. It may not be worth actually putting in the released code, but it may help you determine what is really going wrong.
Updated by Nigel Kersten about 1 year ago
- Target version set to 2.7.x
Updated by Nigel Kersten about 1 year ago
To be clear, we’re going to spend some time investigating this in the immediate future because it’s important to a paying customer, and the results of that investigation will inform whether we can realistically resolve this in 2.6.x, or whether it needs to wait for another major version.
Updated by Daniel Pittman 12 months ago
- Assignee changed from Markus Roberts to Nigel Kersten
After investigating this the R&D team have concluded that we don’t have the ability to reduce this to a small, safe fix that would match the 2.6 branch guidelines, so our strong recommendations are:
- We should make this a statler feature, rather than a 2.6 feature.
- We need some sort of radical improvement; half our pain comes from the Ruby libraries for managing SSL, and their special behaviour in terms of mutating what we say into what they think we intended to say internally.
Updated by Nigel Kersten 12 months ago
- Status changed from Investigating to Accepted
- Assignee deleted (
Nigel Kersten) - Priority changed from Normal to High
Perfect. Thank you for the research time.
Updated by Nigel Kersten 9 months ago
- Target version changed from 2.7.x to Telly
Updated by Daniel Pittman 2 months ago
I wanted to update the world: this has some technically challenging aspects, thanks to the Ruby OpenSSL bindings, and is especially security sensitive. That makes it a significant amount of work to get done, which is why this is taking longer than we might like to get resolved.