Vault: The PKI backend is not well-suited to creating CA certificates

Created on 2 Jul 2015  Â·  65Comments  Â·  Source: hashicorp/vault

The PKI backend has no option for generating certificates with the CA:TRUE extension set. This limits that backend's utility for generating subordinate CA certificates. Is this an intentional omission, or just evidence of very new code?

Most helpful comment

I think it would actually be a very useful feature to enable intermediate CAs and self-signed root CAs on demand, so I'll give the issue a :+1:

I'm evaluating using vault vs. https://github.com/cloudflare/cfssl for an internal PKI solution right now, and the biggest reason to _not_ use vault at the moment is this issue

In our situation, we need to create a separate intermediate CA per client for issuance of client certificates. This is then used to generate certs for each customer device, so that we can revoke an entire customer in one go, along with using the crl for individual compromised client certificates. Unfortunately, this requires using some outside process aside from vault to generate CA certs, even though the actual mounting of the new pki can be entirely managed via the API...

It seems rather arbitrary, and weakens the security of the cert chain because we now need some alternative secure manner of generating the intermediate certs and getting them loaded into vault initially.

Personally, I would feel safest if I never even had to see an exposed private key, aside from what's ultimately bundled with the leaf client/server certs.

All 65 comments

I'm not sure that the PKI backend was/is intended for generation of intermediate CA certs — I'm still struggling to wrap my head around the best use cases for it (paging @jefferai!), but at its core it seems to be intended for generation of short-duration client and server certs for mutual authentication, rather than generation of certs for a larger server TLS infrastructure. But I could be totally wrong... as I said, I have spent a bit of time today trying to figure out what the intended use is for quickly-expiring (relatively speaking) certs is...

The reason intermediate certificates were not supported were for exactly the reason @delfuego mentioned. The primary goal was for short lived TLS keys for the end consumers, like services or public facing servers. The idea being that no other server but Vault is issuing certificates.

@hashbrowncipher You are correct that it does not support generating CA certificates. It's possible that at some point it could do so, however, it requires a lot of thought as to whether Vault is the right place to perform that task.

This is partly because Vault currently generates certificates from a CA cert by copying over information about e.g. CRL and OCSP endpoints, and in many enterprise settings those values are going to be very different for a root CA vs. an intermediate CA. As a result, for an intermediate CA certificate, you are very likely to want to set these manually (and in particular, right now Vault can't handle OCSP so can't even make a reasonable assumption as to what those endpoints should be if not set manually). There are also other settable values for CA certificates that don't have great guessing options.

So at this point there is kind of an assumption that users of the PKI backend are going to be familiar with certificate concepts anyways, and can handle generating the few CA certificates necessary and let Vault handle the few hundreds or thousands more for clients.

It is more likely that at some point the backend could be extended to generate a fully self-signed root certificate and issue certificates based upon that (but in the documentation for the backend you'll see an argument for why that's not the best idea). I'd prefer to wait until Vault gains the capabilities necessary for OCSP before doing adding that in.

@delfuego You are pretty much correct there. A good way to think of this capability is for authentication, like any other backend in Vault, and gaining the same benefits from Vault that you get for any other service. I have worked in places where client certificates are used to grant access to a service, but because generating and rotating many certs is such a pain, the _same_ certificate is used by _every_ service for both serving and client auth. That's better than nothing, but like saying that the same user/password pair for your database across all services is better than nothing -- if you think that's true, you don't need to bother with Vault in the first place.

Granted, you probably want a second factor, so if you are connecting to e.g. Cassandra with the certificate you'll also want to be using a username/password; but one of the nice things is that if the TLS auth fails, you never even have to open a connection to the backend of the database, which both limits the possibility of exploits against the DB auth code and keeps resource utilization lower.

Plus, there are some services out there where TLS is basically the _only_ option available. For instance, Apache Kafka has very little in the way of security right now, but you could put wrap a connection to Kafka between the client to the server with TLS (for instance, with HAproxy and its TCP proxying capability) and perform mutual auth. Far better than nothing.

I find myself agreeing with all of what has been said so far, and work I've done since filing this issue has shown that I probably wouldn't want to use Vault for issuing CA certs anyway.

Should we close the ticket? Treat it as a docs request?

@hashbrowncipher I don't think it needs to be marked as a docs request...there is no documentation in the API indicating that you _can_ generate a certificate that is a CA (only client, server, code signing).

I think it would actually be a very useful feature to enable intermediate CAs and self-signed root CAs on demand, so I'll give the issue a :+1:

I'm evaluating using vault vs. https://github.com/cloudflare/cfssl for an internal PKI solution right now, and the biggest reason to _not_ use vault at the moment is this issue

In our situation, we need to create a separate intermediate CA per client for issuance of client certificates. This is then used to generate certs for each customer device, so that we can revoke an entire customer in one go, along with using the crl for individual compromised client certificates. Unfortunately, this requires using some outside process aside from vault to generate CA certs, even though the actual mounting of the new pki can be entirely managed via the API...

It seems rather arbitrary, and weakens the security of the cert chain because we now need some alternative secure manner of generating the intermediate certs and getting them loaded into vault initially.

Personally, I would feel safest if I never even had to see an exposed private key, aside from what's ultimately bundled with the leaf client/server certs.

@EricMCornelius I'm not opposed to this kind of workflow, but as explained above generating _intermediate_ CA certs in Vault is actually quite tricky because there are a wide range of parameters people might want to toggle.

Keep in mind is that you can mount the PKI backend at an arbitrary number of mount points. So one question is: if the backend can generate its own self-signed root CA, do you need an intermediate CA? Or would mounting the PKI backend at a new location for each client, generating a self-signed root CA for that backend, and issuing certs from that self-signed root CA work for your needs?

Even just having the ability to internally generate those root CAs would go a very long way towards utility for us. Ultimately we'd prefer to have the ability to also generate intermediate CAs, given that's actually representative of the trust structure, but it's not strictly necessary with the ability to easily mount multiple backends, as you mention.

@EricMCornelius See the section "Never use Root CAs" in https://vaultproject.io/docs/secrets/pki/index.html :-)

If you are putting your root CA in Vault to generate intermediate CAs, you may as well simply use the root CA as-is, as you've already lowered the bar for the root CA's security; the private key is in storage and available to the unsealed Vault daemon.

It seems like having Vault self-generate root CAs is a good compromise for the near term. Maybe at some point some workflows for intermediate CAs can be worked up (such as generating intermediate CAs in one backend that are then used as the CAs in other mounts of the pki backend), but this will allow a way forward without having to figure out all of the thorny intermediate CA stuff.

So, I think we are on the same page here. I can't make any promises on a due date for this, but it is definitely on my radar and I will get to it as I am able.

Well, the actual model we'd want is a root CA vault instance running in a heavily secured environment, which is used to generate intermediates for the separate vault instance used to sign our client certs and back our public api. But, for now just having the root would simplify a lot. (Though to make that viable we really just need a couple additional configuration options for the root generation)

@EricMCornelius So what I'm worried about is the "couple additional configuration options". Not _yours_ per se, but the giant scope of possible options that could quickly turn into soup: Country, Organization, Organizational Unit, Locality, Province, Street Address, Postal Code, Serial Number, Common Name, Names, OCSP Server, CRL Distribution Points, etc.

So, I have an alternate proposal:

What if the facility in Vault for generating a self-signed certificate was relatively simple and geared towards using it for direct issuance of certificates (only exposing necessary options, and assuming Vault-hosted CRL endpoint, etc.) -- keep in mind that you can still of course generate a root cert elsewhere and load it in -- but, the backend was enhanced to allow signing CSRs? This is something I've wanted to add as an enhancement anyways, but it just didn't make it into the initial release.

I know you said that you said you "would feel safest if I never even had to see an exposed private key", but the usage you described ("the actual model we'd want is a root CA vault instance running in a heavily secured environment, which is used to generate intermediates for the separate vault instance") requires transporting a private key anyways. Since you could create the CSR inside a program and keep everything in-memory this is still better than writing it down to disk.

That way the CSR can be programmatically crafted for intermediate CA certificates that have values specified just the way you need them, and it avoids the potential option soup for generating CA certs within Vault (which may be fine for you, but might be daunting to others).

That's actually exactly what I meant - don't think I worded it clearly
though.

The CA keys don't ever need to be exposed to the outside world, if we have
an api with the ability to generate a csr, and another to accept a csr and
return a newly signed certificate. As for CA certs, the most critical
configuration fields (in our case anyway, I am definitely not a PKI expert)
is really just the CA and pathlen basicConstraints to control how many
intermediate levels are allowed in the trust chain.

So, if we had the ability to generate a self-signed root CA cert with a
specified pathlen, and then the ability to generate CA and non-CA csrs on
demand (no need to ever even expose the key) - I think we're in very good
shape.

On Fri, Jul 24, 2015 at 11:05 AM Jeff Mitchell [email protected]
wrote:

@EricMCornelius https://github.com/EricMCornelius So what I'm worried
about is the "couple additional configuration options". Not _yours_ per
se, but the giant scope of possible options that could quickly turn into
soup: Country, Organization, Organizational Unit, Locality, Province,
Street Address, Postal Code, Serial Number, Common Name, Names, OCSP
Server, CRL Distribution Points, etc.

So, I have an alternate proposal:

What if the facility in Vault for generating a self-signed certificate was
relatively simple and geared towards using it for direct issuance of
certificates (only exposing necessary options, and assuming Vault-hosted
CRL endpoint, etc.) -- keep in mind that you can still of course generate a
root cert elsewhere and load it in -- but, the backend was enhanced to
allow signing CSRs? This is something I've wanted to add as an enhancement
anyways, but it just didn't make it into the initial release.

I know you said that you said you "would feel safest if I never even had
to see an exposed private key", but the usage you described ("the actual
model we'd want is a root CA vault instance running in a heavily secured
environment, which is used to generate intermediates for the separate vault
instance") requires transporting a private key anyways. Since you could
create the CSR inside a program and keep everything in-memory this is still
better than writing it down to disk.

That way the CSR can be programmatically crafted for intermediate CA
certificates that have values specified just the way you need them, and it
avoids the potential option soup for generating CA certs within Vault
(which may be fine for you, but might be daunting to others).

—
Reply to this email directly or view it on GitHub
https://github.com/hashicorp/vault/issues/388#issuecomment-124552543.

OK, so see if this is all agreeable. Note that these may not all be useful for you, I'm just writing down the enhancements I think are valuable for various use-cases, and at the end see if you think this meets all of your needs:

1) A way to use the Vault backend to generate a root CA. Max pathlen and lifetime, and maybe a few others as I look through the options can be specified, but it will assume you will be using the Vault CRL endpoint, and won't allow setting of most options. This is designed for "easy bootstrapping", and may not fit your particular use-case, but you can always generate your own highly customized root cert and add it into Vault.

2) An API for signing CSRs. Note that I say signing, not generating; Go for instance already has good facilities for generating CSRs (see http://golang.org/pkg/crypto/x509/#CreateCertificateRequest) and I am assuming other languages do as well. Transferring all of that capability into a backend API path is what I'd like to avoid. The one wrinkle is that if you want Vault to manage your CRL you'll need to code that in ahead of time, but as it is a well-known path you can simply code in the path appropriate to where you have that particular backend mount. On the other hand, having you do that (which is easy to do in a programmatic fashion) avoids having to do guesswork inside Vault, which is good. Currently there is /pki/issue/[role]; I will probably lodge this at pki/sign/[role].

3) Some kind of (not yet quite determined, need to think about it) way of defining the roles that allow this behavior. It may be as simple as adding a flag to allow signing CA certs, just as there are currently flags to allow server usage, client usage, etc. I don't think this will be problematic, just need to think through it.

The only thing major downside about not exposing an api to generate the CSRs, is that you need to expose the private key of the intermediate CAs under that model. Less than ideal, but a good feature to add down the line.

@EricMCornelius Can you explain this? CSRs don't carry private key information with them; by having a signing only API you _don't_ need to provide private keys back and forth over the Vault API. If Vault was generating CSRs you would need to provide private keys (or have Vault generate them for you and return them to you, putting the info over the wire).

I meant it would be nice to have vault generate the private keys for the
root and intermediate ca and not expose them to clients at all. Other than
their use for signing, there's no need for them to be exposed under normal
operation, so a csr creation api means that key can remain entirely hidden
from clients for its entire lifetime.

On Tue, Aug 4, 2015, 8:43 AM Jeff Mitchell [email protected] wrote:

@EricMCornelius https://github.com/EricMCornelius Can you explain this?
CSRs don't carry private key information with them; by having a signing
only API you _don't_ need to provide private keys back and forth over the
Vault API. If Vault was generating CSRs you would need to provide private
keys.

—
Reply to this email directly or view it on GitHub
https://github.com/hashicorp/vault/issues/388#issuecomment-127589244.

This is unfortunately slipping to 0.4, not because it's not a high priority (it is!) but because other items needed fixing first, and time has simply run out for 0.3. As this is worked on, I'll keep this ticket updated.

Another +1 for this feature.

Our use case is Vault as an Intermediate CA, signing requests for downstream intermediate CAs (FreeIPA in this case).

I'm in the same position as @EricMCornelius here. We already use Vault for secrets, would like to use it to handle dynamic CA/cert issuing too. https://github.com/cloudflare/cfssl looks like a good alternative at the moment.

Good news: this is nearly complete. Lucky #666

The documentation has not yet been updated, but anyone that wants to look at it and take it for a spin (the documentation of the API fields in the code _has_ been updated) is welcome to, and I'd be happy to have feedback.

It does seem to work nicely with very simple CSRs - however it seems to choke on examples with more features/restrictions.

eg.

[root@foo play]# cat input-csr.txt 
-----BEGIN NEW CERTIFICATE REQUEST-----
MIIDLDCCAhQCAQAwGjEYMBYGA1UEAxMPZm9vLmV4YW1wbGUuY29tMIIBIjANBgkq
hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsGvtECFZ7LgOhp6AgDKvuTpSn3kaMoO+
UczEwy2AGNwgHLG3lUulASa6FnM14uwimBPT8GHJmHQD4wTUUxGdWMIDJoY2+VIu
bma8DOqgUDTACnGSYr8B4Evu/8ZCD0zZR1J9Djiv+W0KphPbGqQB5HHbc4Jem0CL
Cn1ov3qiINzWqfsIZpq65ZiqIBOptHs44dsH0lWsv8I/6SRRCsLF52FmHqrblsbQ
INqNHOdbkHQUtJcaF4FE+3cVoY5GaT9GHQQs4LqaIlEIA+AuIjuGa9zG8t5nWfdp
TfzD1quZ/sQrUdy1qqj3bJXSbWOPdWI2Kq5TsygOacY+xloxnqc8awIDAQABoIHM
MFcGCSqGSIb3DQEJFDFKHkgANwA4ADkAMwAwAGIANQA3AF8ANgBiADkAYgBfADQA
NwBiADIAXwBiADkAMgA2AF8AOAA1ADQAZgAwADkAZgBkADAAOABkADkwcQYJKoZI
hvcNAQkOMWQwYjAMBgNVHRMBAf8EAjAAMCAGA1UdDgEBAAQWBBSLCw+AVGbMq8kS
MuW6qlFENn45QjAwBgkrBgEEAYI3FAIBAQAEIB4eAGUAeABhAG0AcABsAGUALQBk
AG8AdAAtAGMAbwBtMA0GCSqGSIb3DQEBCwUAA4IBAQCX3xfg6n54G3wxLYLPP76/
cH1wK8j3puvoYCZRLWaVOt1rcexuOtxlJHTpy7i2LVpiTuy7DPpKpZ41b/gaiy+R
388YBZJsqPmRYAUPzCX9d3q7o9KMsihlf2r5gv7sOGqR0rPy3P+K69RatJNofGX+
/YKlvFUDbCzSsI1Y04C7BwvykKH9mZN1A6Gd7hKRXyf/JFS4u6e+EVqq8c4dV/xr
LsbQhFr5D6x5PB69BbgQLOU5XyQMFciqelVMILsFzUl/nTMzcDX6escg/FPfIyrD
eTa/1xWX1zb9D5E8Yg9xJ16QPYvmtmieZAduMoE+0SsjBdvNhLXE0m3gm0jNeuXh
-----END NEW CERTIFICATE REQUEST-----
[root@foo play]# vault write  pki/sign/example-dot-com csr="@input-csr.txt"  common_name="foo.example.com"
Error writing data to pki/sign/example-dot-com: Error making API request.

URL: PUT https://127.0.0.1:8200/v1/pki/sign/example-dot-com
Code: 400. Errors:

* certificate request could not be parsed
[root@foo play]# 

What exactly is in that CSR? Parsing it with OpenSSL is odd:

Certificate Request:
    Data:
        Version: 0 (0x0)
        Subject: C=AU, ST=Some-State, O=Internet Widgits Pty Ltd
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:99:9f:90:43:1e:2d:8d:f4:25:b5:fb:18:46:e9:
                    b4:00:d8:09:31:65:bd:dd:10:a9:9d:59:8a:b4:b3:
                    b6:c9:60:7f:a5:7c:2e:a7:00:78:ac:d5:3d:27:f1:
                    75:7e:fe:c3:0a:f5:ad:ca:09:55:20:d4:a6:25:51:
                    0e:57:dd:eb:7d:36:ba:18:99:96:fe:d6:a0:16:83:
                    51:9d:34:42:c2:fc:8b:36:fe:59:97:41:7b:f6:1c:
                    3c:fb:4d:b3:2e:aa:08:a6:0a:65:13:14:18:61:c3:
                    8a:be:85:de:b9:46:23:56:16:7f:bd:b9:90:44:ec:
                    6f:0b:0f:bd:a3:4e:2a:e9:ff:9c:4e:cf:1d:92:f0:
                    38:4e:7b:bd:e2:8c:40:a6:42:6f:c3:7c:85:51:84:
                    f3:d3:5a:36:65:98:c4:a5:d9:10:f2:e3:f3:f9:db:
                    a4:11:14:fb:6b:68:cd:f7:38:d3:d0:0a:75:fb:70:
                    dc:f4:fd:e8:ec:81:d0:38:bf:65:85:d2:6b:28:7d:
                    e2:4d:94:82:a3:10:fe:b9:88:98:a0:57:51:67:78:
                    65:a9:f7:72:16:fc:26:9f:0c:34:79:ff:d2:45:a1:
                    d4:ff:34:45:eb:65:2c:1a:1f:66:39:e5:3d:2f:40:
                    90:91:9d:19:07:2a:ce:89:bb:fa:fe:51:da:d8:6d:
                    25:47
                Exponent: 65537 (0x10001)
        Attributes:
            a0:00
    Signature Algorithm: sha256WithRSAEncryption
         5e:e8:65:ef:4b:ca:b1:0d:ed:69:46:6a:a6:cc:ba:1d:f6:1b:
         0d:a8:5b:6c:a4:6d:ac:9c:88:ee:86:f9:63:ee:72:51:c0:cf:
         fd:e7:6f:23:fc:7d:d3:4a:61:92:4b:91:50:5e:0a:d2:4d:1d:
         b7:ac:a1:9b:2a:db:32:41:74:0d:c4:20:1d:13:e4:7c:c7:1b:
         04:cc:e5:d9:c6:16:ca:53:ae:c7:f2:00:ce:5a:e2:81:1b:92:
         ac:3d:24:e6:9d:77:17:43:f2:ce:71:8e:a7:7f:f3:c1:14:47:
         b9:e5:0d:8b:0c:f8:d9:06:01:e7:e5:dd:1f:f7:8e:50:c6:57:
         cf:e7:fc:a6:b8:86:2c:81:8c:ee:cf:6e:3f:32:9c:8e:a6:e7:
         2d:17:4a:84:e9:55:2a:c4:11:67:b0:ff:59:2b:a5:90:08:8e:
         fe:0a:e9:b6:df:c7:9a:24:5c:69:3d:45:5a:df:b8:d0:cc:6e:
         62:52:2d:71:18:37:42:3c:8a:f6:1b:27:9b:f2:a1:f0:04:67:
         36:3e:c7:ba:a5:cf:3b:f2:af:41:85:53:48:29:a9:f1:17:86:
         69:3d:aa:c1:99:cd:cc:eb:3d:e1:a6:cf:3b:7f:af:a7:c9:2e:
         5e:59:9a:9e:1d:d4:03:42:23:f9:2c:09:18:54:bb:49:07:a4:
         d8:89:11:ff

In particular the "Attributes" section is wonky. Here's an example of my own; note the difference with Attributes and Requested Extensions:

$ openssl req -in csr.pem -noout -text
Certificate Request:
    Data:
        Version: 0 (0x0)
        Subject: CN=example.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:a8:82:fe:8f:51:26:5e:b3:f3:c3:bb:ec:f7:e2:
                    d3:ec:2e:9a:17:74:91:fd:fb:7c:be:60:23:df:20:
                    2f:da:58:ab:aa:db:5d:26:1d:36:30:4f:01:bd:4a:
                    3d:f2:e5:0e:57:3c:56:56:30:21:ec:28:2a:7e:57:
                    c4:e5:5e:cf:32:6d:30:be:3c:10:6e:8e:05:cc:5f:
                    8f:54:79:aa:d9:aa:be:e4:17:23:8e:af:3f:a5:47:
                    bd:8d:41:d4:12:a4:3e:58:cd:52:e1:87:b8:47:85:
                    63:0a:d5:aa:66:9e:17:4e:fd:a4:a1:a4:2c:d6:01:
                    84:20:99:5f:cb:32:9b:ee:e5:20:98:89:83:05:80:
                    95:bc:12:7d:e3:bc:29:e1:90:b2:5d:a8:96:be:e8:
                    4f:c6:24:e8:98:41:85:be:8b:b1:74:fa:3a:3a:21:
                    af:b3:72:1a:da:ec:df:c5:a9:fa:e4:29:03:e0:b5:
                    11:8e:29:65:5f:4c:16:db:8d:06:e7:b1:24:9b:9c:
                    76:b2:b7:36:c3:6c:48:6e:ee:31:de:0f:61:62:f2:
                    40:ce:11:7c:27:0f:7d:f0:62:28:e4:d7:63:da:9c:
                    42:fb:6f:5a:1e:86:ca:9f:52:ec:21:ca:59:aa:c2:
                    10:a2:5c:63:05:8f:21:8e:08:d8:44:56:d4:55:5a:
                    40:e7
                Exponent: 65537 (0x10001)
        Attributes:
        Requested Extensions:
            X509v3 Subject Alternative Name: 
                DNS:example.com
    Signature Algorithm: sha256WithRSAEncryption
         62:dc:f0:95:3b:c3:0d:91:18:b2:19:fa:5d:38:65:0c:04:9b:
         3a:7d:97:e3:b2:fb:80:59:d8:d7:e1:c4:4c:6c:d8:d1:d1:3a:
         92:d0:1e:82:b6:ab:90:54:87:82:38:82:ce:8f:97:ab:b0:d0:
         1a:ce:6d:c9:d2:8d:6e:f0:b4:bf:1c:51:b4:b7:8e:37:50:04:
         0b:15:d7:86:f0:cd:d9:46:2e:40:c6:ac:b5:b0:bc:b8:23:7e:
         06:0e:16:64:c3:7e:60:98:38:f3:10:b6:9d:37:c8:d0:32:4a:
         9d:10:c8:39:8e:d7:f5:bb:a0:fe:53:b5:02:67:dc:69:fe:6c:
         64:96:bc:55:51:c5:0d:b2:30:c5:b6:de:af:14:e2:6d:a1:41:
         39:dd:8c:03:63:34:72:45:16:57:9b:87:75:ae:13:d5:04:58:
         08:00:76:ca:ce:2b:04:b8:e7:85:86:08:b8:21:e6:d1:62:13:
         02:32:ba:7c:23:7b:48:97:72:0e:63:9f:e6:d9:7e:3d:bd:76:
         04:e1:78:5e:32:d4:25:34:19:19:95:5f:d1:65:83:ca:f1:f8:
         be:1b:c6:ff:6c:bc:75:d7:24:8b:57:62:92:a2:55:23:f2:91:
         7c:86:84:9a:80:58:58:db:d8:ac:dd:5a:66:01:43:b0:d7:41:
         4c:23:28:8e

This really looks like a problem with your CSR, not the backend. How did you create it?

The CSR is generated automatically with Certmonger. Dogtag, easy-rsa, certmaster etc. all sign it correctly.
If there's something wrong with it, happy to raise it with them.

The openssl (openssl-1.0.1e-42.el7.9.x86_64) parsed csr output on my test system looks quite different.

Certificate Request:
    Data:
        Version: 0 (0x0)
        Subject: CN=foo.example.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:b0:6b:ed:10:21:59:ec:b8:0e:86:9e:80:80:32:
                    af:b9:3a:52:9f:79:1a:32:83:be:51:cc:c4:c3:2d:
                    80:18:dc:20:1c:b1:b7:95:4b:a5:01:26:ba:16:73:
                    35:e2:ec:22:98:13:d3:f0:61:c9:98:74:03:e3:04:
                    d4:53:11:9d:58:c2:03:26:86:36:f9:52:2e:6e:66:
                    bc:0c:ea:a0:50:34:c0:0a:71:92:62:bf:01:e0:4b:
                    ee:ff:c6:42:0f:4c:d9:47:52:7d:0e:38:af:f9:6d:
                    0a:a6:13:db:1a:a4:01:e4:71:db:73:82:5e:9b:40:
                    8b:0a:7d:68:bf:7a:a2:20:dc:d6:a9:fb:08:66:9a:
                    ba:e5:98:aa:20:13:a9:b4:7b:38:e1:db:07:d2:55:
                    ac:bf:c2:3f:e9:24:51:0a:c2:c5:e7:61:66:1e:aa:
                    db:96:c6:d0:20:da:8d:1c:e7:5b:90:74:14:b4:97:
                    1a:17:81:44:fb:77:15:a1:8e:46:69:3f:46:1d:04:
                    2c:e0:ba:9a:22:51:08:03:e0:2e:22:3b:86:6b:dc:
                    c6:f2:de:67:59:f7:69:4d:fc:c3:d6:ab:99:fe:c4:
                    2b:51:dc:b5:aa:a8:f7:6c:95:d2:6d:63:8f:75:62:
                    36:2a:ae:53:b3:28:0e:69:c6:3e:c6:5a:31:9e:a7:
                    3c:6b
                Exponent: 65537 (0x10001)
        Attributes:
            friendlyName             :unable to print attribute
        Requested Extensions:
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Subject Key Identifier: 
                8B:0B:0F:80:54:66:CC:AB:C9:12:32:E5:BA:AA:51:44:36:7E:39:42
            1.3.6.1.4.1.311.20.2: 
                ...e.x.a.m.p.l.e.-.d.o.t.-.c.o.m
    Signature Algorithm: sha256WithRSAEncryption
         97:df:17:e0:ea:7e:78:1b:7c:31:2d:82:cf:3f:be:bf:70:7d:
         70:2b:c8:f7:a6:eb:e8:60:26:51:2d:66:95:3a:dd:6b:71:ec:
         6e:3a:dc:65:24:74:e9:cb:b8:b6:2d:5a:62:4e:ec:bb:0c:fa:
         4a:a5:9e:35:6f:f8:1a:8b:2f:91:df:cf:18:05:92:6c:a8:f9:
         91:60:05:0f:cc:25:fd:77:7a:bb:a3:d2:8c:b2:28:65:7f:6a:
         f9:82:fe:ec:38:6a:91:d2:b3:f2:dc:ff:8a:eb:d4:5a:b4:93:
         68:7c:65:fe:fd:82:a5:bc:55:03:6c:2c:d2:b0:8d:58:d3:80:
         bb:07:0b:f2:90:a1:fd:99:93:75:03:a1:9d:ee:12:91:5f:27:
         ff:24:54:b8:bb:a7:be:11:5a:aa:f1:ce:1d:57:fc:6b:2e:c6:
         d0:84:5a:f9:0f:ac:79:3c:1e:bd:05:b8:10:2c:e5:39:5f:24:
         0c:15:c8:aa:7a:55:4c:20:bb:05:cd:49:7f:9d:33:33:70:35:
         fa:7a:c7:20:fc:53:df:23:2a:c3:79:36:bf:d7:15:97:d7:36:
         fd:0f:91:3c:62:0f:71:27:5e:90:3d:8b:e6:b6:68:9e:64:07:
         6e:32:81:3e:d1:2b:23:05:db:cd:84:b5:c4:d2:6d:e0:9b:48:
         cd:7a:e5:e1

I still think your CSR is problematic:

 Attributes:
            friendlyName             :unable to print attribute

The Attributes section is where my openssl (1.0.2d-0ubuntu1) shows wonky output -- yours above shows unable to print attribute. There have been a lot of openssl vulns in the past related to incorrect parsing or failing to properly handle malformed data, so I wouldn't be surprised if this is a change related to my newer openssl version.

The key here is that Go has its own crypto library, it doesn't use openssl. I wouldn't at all be surprised if it is much stricter about its parsing, and as such it bails when it hits the problematic friendlyName attribute. The other tools probably sign it because they're all using openssl.

This is mostly guesswork, but I don't think it's at all unreasonable. I still think it's a malformed CSR, and Go is simply being strict about it.

Here's another example CSR. OpenSSL happily decodes all the fields. Vault still returns a "400 - certificate request could not be parsed"

-----BEGIN CERTIFICATE REQUEST-----
MIICsTCCAZkCAQAwOjEYMBYGA1UECgwPRk9PLkVYQU1QTEUuQ09NMR4wHAYDVQQDDBVDZXJ0aWZp
Y2F0ZSBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDP6+PlbKReGO5G
2x5WU6TEgPtVb5CZsXdt2Df7rUmbz9SMxhE+u6DdU0qI1q02hzQ2WszAL3nxm7+QazLWNAHpXyan
b/w7ESDZ0m8hivaK1Nd5nm0WWXQ8/y1HpdXeDV0hXQtpn1dLlKtVd/G1KTlqCSuNhRF+DmBx4efD
a2DXgNzRmECJII9LlIkeOwH4EO8f985UdLjurOZt6A4J4SW3IPAXU+h3ZG2oguM+Pd2+3oB0hO4B
Q1+D06awS4cdmMbJxDST1FtNzeIJvsu1aLDQwvVR74cZVzOLEfASIoQzhn+6Zk8ORvLaxP0RMT/z
aG5eJkOHTY5dP05icFU11STHAgMBAAGgMjAwBgkqhkiG9w0BCQ4xIzAhMA8GA1UdEwEB/wQFMAMB
Af8wDgYDVR0PAQH/BAQDAgHGMA0GCSqGSIb3DQEBCwUAA4IBAQBjrF9bIh3qds41c0RrBdy64Bze
8QeN0kDzQMg2WX3T1VDR3SZ/so/6X0O2kZeaWxpHNewxdsMEgnlSIHsExz6UO5+M999l6GQmQPJN
unJyysNw7UQxt9DPwwkHTFvvZoeod9ZQE0ayauLZdhmlqoHIE2pUu4eg3h9l6fjjO6HQLTlV2t+6
WEW0WCXKxVFlB0MvCQOEbTlMQAWdo1AwktBBQYjQ66slUz2h56VmaW+b2BGKlOzdwuyKlrFDTN4D
NR2AQEtAuG17u3bVy5Lu6nF4zzw+zCLBMB58hk6VGit7kkTaFRL57hYv2KwQ3IRyj2WRj7B78FGa
2jRgGCvrPlzG
-----END CERTIFICATE REQUEST-----

This link seems interesting - http://grokbase.com/t/gg/golang-nuts/14c5pazcn4/go-nuts-problem-with-x-509-certificate-signing-request-parsing-structure-error-sequence-tag-mismatch

Perhaps the problem is the "Critical" flag set on attributes?

Interestingly, this may be similar to something I filed earlier with cfssl - https://github.com/cloudflare/cfssl/issues/346

This may be a problem with Golang's CSR handling in general.

This seems to confirm it - https://github.com/letsencrypt/boulder/issues/565

Confirmed - Golang HEAD fixes this - I can issue certs from both the problem cases.

Yuck. I will see internally if we want to fork the stdlib but I highly doubt we'll want to be doing that, so that might be a Go 1.6 issue.

FWIW, the new CSR you pasted above doesn't cause openssl errors for me:

$ openssl req -in req.csr -noout -textCertificate Request:
    Data:
        Version: 0 (0x0)
        Subject: O=FOO.EXAMPLE.COM, CN=Certificate Authority
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:cf:eb:e3:e5:6c:a4:5e:18:ee:46:db:1e:56:53:
                    a4:c4:80:fb:55:6f:90:99:b1:77:6d:d8:37:fb:ad:
                    49:9b:cf:d4:8c:c6:11:3e:bb:a0:dd:53:4a:88:d6:
                    ad:36:87:34:36:5a:cc:c0:2f:79:f1:9b:bf:90:6b:
                    32:d6:34:01:e9:5f:26:a7:6f:fc:3b:11:20:d9:d2:
                    6f:21:8a:f6:8a:d4:d7:79:9e:6d:16:59:74:3c:ff:
                    2d:47:a5:d5:de:0d:5d:21:5d:0b:69:9f:57:4b:94:
                    ab:55:77:f1:b5:29:39:6a:09:2b:8d:85:11:7e:0e:
                    60:71:e1:e7:c3:6b:60:d7:80:dc:d1:98:40:89:20:
                    8f:4b:94:89:1e:3b:01:f8:10:ef:1f:f7:ce:54:74:
                    b8:ee:ac:e6:6d:e8:0e:09:e1:25:b7:20:f0:17:53:
                    e8:77:64:6d:a8:82:e3:3e:3d:dd:be:de:80:74:84:
                    ee:01:43:5f:83:d3:a6:b0:4b:87:1d:98:c6:c9:c4:
                    34:93:d4:5b:4d:cd:e2:09:be:cb:b5:68:b0:d0:c2:
                    f5:51:ef:87:19:57:33:8b:11:f0:12:22:84:33:86:
                    7f:ba:66:4f:0e:46:f2:da:c4:fd:11:31:3f:f3:68:
                    6e:5e:26:43:87:4d:8e:5d:3f:4e:62:70:55:35:d5:
                    24:c7
                Exponent: 65537 (0x10001)
        Attributes:
        Requested Extensions:
            X509v3 Basic Constraints: critical
                CA:TRUE
            X509v3 Key Usage: critical
                Digital Signature, Non Repudiation, Certificate Sign, CRL Sign
    Signature Algorithm: sha256WithRSAEncryption
         63:ac:5f:5b:22:1d:ea:76:ce:35:73:44:6b:05:dc:ba:e0:1c:
         de:f1:07:8d:d2:40:f3:40:c8:36:59:7d:d3:d5:50:d1:dd:26:
         7f:b2:8f:fa:5f:43:b6:91:97:9a:5b:1a:47:35:ec:31:76:c3:
         04:82:79:52:20:7b:04:c7:3e:94:3b:9f:8c:f7:df:65:e8:64:
         26:40:f2:4d:ba:72:72:ca:c3:70:ed:44:31:b7:d0:cf:c3:09:
         07:4c:5b:ef:66:87:a8:77:d6:50:13:46:b2:6a:e2:d9:76:19:
         a5:aa:81:c8:13:6a:54:bb:87:a0:de:1f:65:e9:f8:e3:3b:a1:
         d0:2d:39:55:da:df:ba:58:45:b4:58:25:ca:c5:51:65:07:43:
         2f:09:03:84:6d:39:4c:40:05:9d:a3:50:30:92:d0:41:41:88:
         d0:eb:ab:25:53:3d:a1:e7:a5:66:69:6f:9b:d8:11:8a:94:ec:
         dd:c2:ec:8a:96:b1:43:4c:de:03:35:1d:80:40:4b:40:b8:6d:
         7b:bb:76:d5:cb:92:ee:ea:71:78:cf:3c:3e:cc:22:c1:30:1e:
         7c:86:4e:95:1a:2b:7b:92:44:da:15:12:f9:ee:16:2f:d8:ac:
         10:dc:84:72:8f:65:91:8f:b0:7b:f0:51:9a:da:34:60:18:2b:
         eb:3e:5c:c6

So I do still think something was weird with your first one. But clearly there is a real problem in the Go std lib.

My two cents: it will be useful to generate new roots and intermediates on-the-fly for use at different deployment locations. So I like this idea/feature. I am OK with a constrained configuration model AFAIK.

@theonewolf You will be able to (and you can look in the as-yet-undocumented PR if you want to test it out now!)

When this gets merged I'll probably publish a blog post showing how to use two different mounts and the new methods added to securely host a root and any intermediates you like, signed by that root. Because you can add as many pki mounts as you like, you can have an arbitrary number of roots and intermediate CAs.

@jefferai this will seriously notch Vault up a couple levels in functionality. I see Vault as an all-encompassing PKI management solution for organizations of all sizes---which is incredibly attractive to me.

Keep up the great work :+1:

@theonewolf I've got a bunch of things I'm juggling right now so the documentation for the PKI backend update has fallen away; however, if you care to look at the changed source in the PR and either let me know what you think about the various paths and options (the options themselves are documented) or even try it out, that would be useful.

If you want to give that a try, here's a gist with some commands you could use for testing; you could also look at the backend_test.go file which has a hugely expanded set of unit tests to cover all of the new functionality; it does assume you have http (from the httpie package) and jq installed. Otherwise you could do it a bit more manually using the normal Vault CLI.

https://gist.github.com/jefferai/a9b02179da554475b859

3) Some kind of (not yet quite determined, need to think about it) way of defining the roles that allow this behavior. It may be as simple as adding a flag to allow signing CA certs, just as there are currently flags to allow server usage, client usage, etc. I don't think this will be problematic, just need to think through it.

Any hints on when the ability to sign Sub-CA CSRs is coming?

At the moment, the /pki/sign endpoint ignores...

        Requested Extensions:
            X509v3 Basic Constraints: critical
                CA:TRUE

... and issues certs without that extension.

Another thought...

[root@foo ~]# vault write pki/sign/local  csr="@/root/ipa.csr"  ttl=3600s
Error writing data to pki/sign/local: Error making API request.

URL: PUT https://127.0.0.1:8200/v1/pki/sign/local
Code: 400. Errors:

* The common_name field is required

common_name shouldn't be _required_ for CSRs - it's data that the CSR already provides. _optional_ makes sense.

The current common_name handling is not well suited to more complex examples.

eg.
Subject: O=LOCAL, CN=Certificate Authority

It assumes I'm only providing the _CN_.

Any hints on when the ability to sign Sub-CA CSRs is coming?

0.4. You can look at the current state in #666 . Regarding your other queries, note that, like some (many? most?) other CAs, the code completely ignores any attributes in the CSR other than the key. The various attributes in the final cert are chosen via parameters during submission. CA cert issuing is restricted to root/sudo tokens; other types of CSR-based issuing are not and honor normal role parameters.

Regarding your other queries, note that, like some (many? most?) other CAs, the code completely ignores any attributes in the CSR other than the key. The various attributes in the final cert are chosen via parameters during submission.

I've not seen any CAs dump the common name. I agree it's normal for CSR attributes to be dumped if they're not included in the signing profile - hence I'm not surprised that the CA extension is dumped. However, virtually every profile will have a common name.

CA cert issuing is restricted to root/sudo tokens; other types of CSR-based issuing are not and honor normal role parameters.

I am using a root token. Just to be clear, are you referring to /pki/sign/ or /pki/config/ca/sign ?

Is it the intent that Sub-CAs can never be issued from a call to /pki/sign/ ? To me, a particular CSR may require a different policy, but a Sub-CA CSR is still just a CSR that needs to be signed.

/pki/config/ca/sign does get me a Sub-CA cert, but I still run in to the restricted naming problem caused by the common name requirement. I'm also left with the impression that /pki/config/ca/sign is meant for Vault CA use, rather than as a general purpose CSR endpoint?

I've not seen any CAs dump the common name. I agree it's normal for CSR attributes to be dumped if they're not included in the signing profile - hence I'm not surprised that the CA extension is dumped. However, virtually every profile will have a common name.

Given that any SANs need to be specified as well as other attributes like TTL, is there a reason why requiring the common name to be specified at this point is problematic? Any person or system handling the CSR could easily see the requested common name on it and simply pass it in.

I am using a root token. Just to be clear, are you referring to /pki/sign/ or /pki/config/ca/sign ?

/pki/config/ca/sign -- all /pki/config paths require a root token.

Is it the intent that Sub-CAs can never be issued from a call to /pki/sign/ ? To me, a particular CSR may require a different policy, but a Sub-CA CSR is still just a CSR that needs to be signed.

Yes, that is the intent, just like you cannot issue CA certificates from /pki/issue.

/pki/config/ca/sign does get me a Sub-CA cert, but I still run in to the restricted naming problem caused by the common name requirement

Can you explain what you mean by "restricted naming problem"?

I'm also left with the impression that /pki/config/ca/sign is meant for Vault CA use, rather than as a general purpose CSR endpoint?

It's meant for signing certificates with the configured CA in the mount. Most organizations consider CAs to be quite special and restricting access to it makes sense, especially as it prevents accidentally creating a role that allows CA-requesting CSRs to be signed. Is this not fitting your use-case somehow?

I'm trying to get a Sub-CA certificate issued to Subject: O=LOCAL, CN=Certificate Authority - this is what is in the CSR. The Subject in the certificate returned from Vault must match this.

Vault prepends everything inside common_name= with _CN_

Hence:

vault write pki/config/ca/sign csr="@/root/old-ipa.csr" pki_address="https://localhost:8200/v1/pki" exported=internal common_name="O=LOCAL, CN=Certificate Authority" ttl=3600s

results in Subject: CN=O=LOCAL, CN=Certificate Authority/serialNumber=42772552752638260542852938902294199611385901481

I understand why this has happened, as you're expecting a CN, not a DN here.

Hence my query as to why common_name is always required, when the necessary Subject identifier is provided in the CSR anyway. I accept that your most common use case is _CN=servername_.

So, what you're saying here is that you want the PKIX Subject information left intact. It isn't currently kept because it's not a security-sensitive property; in fact, it's more of a security anti-pattern, because if a CA signs a CSR and has no way of properly verifying the subject information (which in most cases they don't), someone could attempt to use that signed information to misrepresent a site, even if the CN doesn't match.

As a point of reference, Let's Encrypt's ACME spec (https://letsencrypt.github.io/acme-spec/) says:

The CSR encodes the client’s requests with regard to the content of the certificate to be issued. The CSR MUST indicate the requested identifiers, either in the commonName portion of the requested subject name, or in an extensionRequest attribute [RFC2985] requesting a subjectAltName extension.

The values provided in the CSR are only a request, and are not guaranteed. The server or CA may alter any fields in the certificate before issuance. For example, the CA may remove identifiers that are not authorized for the account key that signed the request.

I'm bringing this up only to point out the rationale for why values in the CSR are ignored; it's pretty wide industry practice. However, let me know if the following two changes are acceptable to you:

  1. Make common_name optional for CSRs; if the value is passed in, use it, otherwise use the CN value from the CSR.
  2. For CA signing _only_ (/pki/config/ca/sign, not /pki/sign/), add a flag allowing the PKIX Subject information to be copied over into the final certificate. For reference, this means the fields in https://golang.org/pkg/crypto/x509/pkix/#Name -- although obviously not the serial number. The question here then becomes whether the Names and ExtraNames values should be copied over as well, or the values passed in via alt_names and ip_sans should be honored instead. I'll probably make it all-or-nothing -- either you want the CSR as-is, or you want to use parameters.

I'm thinking about how to handle CA certs issued for CSRs with respect to CRL distribution points. For generating the root cert, you need to tell it the base address, which is fine since if you don't want a self-signed generated root cert, you'll have a preconfigured one that you're uploading anyways. I think when uploading a signed intermediate CA into Vault, I'll need to require the address to be specified. I think currently I was encoding that into the certificate when signing, but that's not actually correct; it needs to be the issuer's address.

Would this meet all of your needs?

The values provided in the CSR are only a request, and are not guaranteed.

Yes - I 100% agree with this. Vault should be free to override CSR fields by policy.

eg. the policy you're using excludes CRLs - the cert that's issued shouldn't have it. Domain needs to start with "foo.com"? Reject any CNs without it.

However, it shouldn't force me to have to override something that doesn't need overriding - and override it in an incompatible way:-) It sounds like our differences in approach are "by default use data from CSR" vs. "only trust Vault parameters".

Thanks for offering to make the changes - it sounds like what I need.

It sounds like our differences in approach are "by default use data from CSR" vs. "only trust Vault parameters".

Vault don't trust nobody. :-D

@james-masson FYI, at the moment I don't see the need, when generating a self-signed root certificate in Vault, to allow specifying CA or CRL paths; if Vault isn't the destination for the self-signed root, there's really no point using Vault to generate it.

In my case I'm looking at offline Root, Vault as 1st level online Sub-CA, FreeIPA as 2nd level Sub-CAs.

OK. So yes, there definitely needs to be a way to tell Vault what CA/CRL endpoints to use, if any.

Sorry for launching you down the rabbit hole on this request :)

This all sounds fantastic though, should be able to replace the custom
alternative I rolled in the interim.

Keep up the good work!

On Fri, Oct 9, 2015 at 12:20 PM Jeff Mitchell [email protected]
wrote:

OK. So yes, there definitely needs to be a way to tell Vault what CA/CRL
endpoints to use, if any.

—
Reply to this email directly or view it on GitHub
https://github.com/hashicorp/vault/issues/388#issuecomment-146916506.

@EricMCornelius No problem! The 0.2 version was always meant as a first cut. It's a big win to have Vault be a real, flexible CA.

@james-masson I've pushed up changes that I think address everything we discussed before. Looking forward to feedback!

Thanks for the quick turn-around.

I can now submit a CSR to the pki/config/ca/sign/ endpoint, with no requirements for any overrides.

Unfortunately, the end behaviour is the same - The Subject in the CSR is not the same as the Subject in the Certificate generated by Vault.

_CSR_

Certificate Request:
    Data:
        Version: 0 (0x0)
        Subject: O=LOCAL, CN=Certificate Authority
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:

vault write pki/config/ca/sign csr="@/root/ipa.csr" ttl=3600s
_CRT_

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            0b:e7:77:ac:53:de:76:27:51:03:58:ce:33:4c:97:6f:33:77:33:3f
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN=myca.example.com/serialNumber=646271000807585604804762811702134499045838636910
        Validity
            Not Before: Oct 12 08:28:12 2015 GMT
            Not After : Oct 12 09:28:12 2015 GMT
        Subject: CN=Certificate Authority/serialNumber=67960795621996808575072647604165847337072538431
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:

@james-masson When you're signing the CSR you need to set use_csr_subject to true if you want to keep the CSR's subject information.

Missed that flag - sorry...

Getting a little further - vault write pki/config/ca/sign csr="@ipa.csr" ttl=3600s use_csr_subject=true

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            69:ac:7c:08:16:83:de:9f:09:f7:0d:72:80:03:77:89:de:74:5b:9f
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN=myca.example.com/serialNumber=646271000807585604804762811702134499045838636910
        Validity
            Not Before: Oct 12 13:59:16 2015 GMT
            Not After : Oct 12 14:59:16 2015 GMT
        Subject: O=LOCAL, CN=Certificate Authority/serialNumber=603290563786292612953946235113058061601364794271

I now have the full DN in the Cert subject, but also still the serial number.

Sadly, I've gone back to reading RFCs. https://tools.ietf.org/html/rfc5280#section-4.1.2.6

It's pretty clear that for a CA, the Subject must be a DN - it doesn't mention it can't contain anything else, but for the applications we're using, if CSR Subject doesn't exactly match the subsequent Cert Subject, certificate import fails.

@james-masson I was setting the serial number in the subject explicitly with the serial number of the new certicficate so that if someone gave a CSR with a serial number baked-in, it wouldn't be disjoint with the final serial number of the certificate. But it's true, it does mean that the subject isn't _exactly_ the same, so I'll remove that.

I just pushed a change to stop that.

Yes - getting a bit further now. Subject is now correct.

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            30:08:30:e4:2c:af:cf:df:24:d1:c1:5a:da:a5:2f:4e:28:c3:47:59
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN=myca.example.com/serialNumber=646271000807585604804762811702134499045838636910
        Validity
            Not Before: Oct 12 14:20:03 2015 GMT
            Not After : Oct 12 15:20:03 2015 GMT
        Subject: O=LOCAL, CN=Certificate Authority
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)

Next problem :-)

CSR asks for

        Requested Extensions:
            X509v3 Basic Constraints: critical
                CA:TRUE
            X509v3 Key Usage: critical
                Digital Signature, Non Repudiation, Certificate Sign, CRL Sign

CRT comes back with

        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment, Key Agreement, Certificate Sign, CRL Sign
            X509v3 Extended Key Usage: 
                OCSP Signing
            X509v3 Basic Constraints: critical
                CA:TRUE
            X509v3 Subject Key Identifier: 
                A9:97:53:10:A7:C2:8B:FC:D5:79:6F:8B:3B:3F:BB:58:BC:33:3A:FA
            X509v3 Authority Key Identifier: 
                keyid:2C:34:8B:05:AE:08:E9:54:71:2E:99:20:F3:3C:5F:9D:1F:D6:72:E7

We're missing the non-repudiation key usage.

I only copied the CSR subject since in the previous discussion you indicated that this was sufficient. Non repudiation isn't used at all right now because it's basically meaningless in the real world.

You're also getting a number of other things -- key encipherment, key agreement, OCSP signing. For pretty much any certificate, you need the former two, and you probably want the latter on a CA cert. So what is the actual need here -- that you want the _exact_ set of key usages that you asked for? Or that you need non repudiation? Basically,can you provide:

1) The list of things you want taken from the CSR
2) For each item in (1), a list of values you do, and don't, care about staying the same.

For example, for the pkix Subject, you wanted it taken straight from the CSR, and you wanted _every_ value exactly the same -- even the serial number. However, for key usage, you only indicated that non-repudiation not being copied over is a problem (and again, I would generally argue that non-repudiation is useless anyways), so unlike Subject it doesn't seem like you care about an exact copy.

I'm kind of shooting in the dark here guessing what behavior you want, so if you can help fill in the gaps on what your exact needs are, that would be helpful.

@james-masson As discussed, use_csr_subject -> use_csr_values and now uses CSR subject, alternate names, and extensions (such as requested key usages) copied verbatim from the CSR. I tested this against your CSR posted above and non-repudation carried over. See my email w.r.t. path length; tomorrow I'll separate out pki_address into something settable separately, possibly ca_urls and crl_urls.

I've now added the ability to set the path length on issued certificates, and the ability to individually set one or multiple URLs for issuing CA, CRL distribution points, and OCSP servers.

Thanks again - use_csr_values is just what I need.

I still can't get the resulting certificate accepted by FreeIPA though. It looks fine - I've raised the issue on their mailing list and will report back. Certificates signed by Dogtag work just fine from the same CSR.

I did make a couple changes to that code when I committed the
pathlen/urls paths, so if you pulled before my latest commits late
yesterday, be sure to pull again and see if that helps.

(meta-note: removing from 0.4 milestone only because #666 is in there as well; this is still scheduled for 0.4)

For anyone who would like to try a build of #666, I've created a docker image at dsvolition/vault and a github repository with the Dockerfiles I used to build it at: https://github.com/volition-inc/vault

@jefferai Thank you for doing this work, it's going to benefit the project I am working on immediately.

Sure! I'm mostly waiting on @james-masson to make more forward-progress on this; the certs being generated are not being liked by FreeIPA but it's unclear why, yet, and he's following up with them. Other than that, I think the code is basically done at this point, although the documentation needs updating.

@jwthomp If you have any feedback on the changed code, by all means please send it along. Easier to make changes now before it's all codified in a release :-)

Don't get hung-up waiting for me - I'm waiting for Redhat to make some progress on my issue, no ETA available.

@james-masson 0.4 is still a bit away, so it's not really hung up. I'll let you know if this is becoming a major blocker. But there's still time.

@james-masson Any update?

Sorry - nothing new here.

@james-masson and others,

I just pushed a super large commit. Among other things:

  • Full documentation
  • Removal of the config/pathlength endpoint. Instead these are rolled straight into the root generation and intermediate signing endpoints. Also, path length is now checked when issuing certs; if the path length of the CA cert is zero, no cert will be issued.
  • When generating a CSR for an intermediate CA cert, the common_name is now required, even if you override it when issuing (makes things easier to reason about)
  • More values can now be put into the intermediate CA generation endpoint, notable SANs
  • Normal cert signing/issuing can now be returned in b64-encoded DER
  • Some other random bugfixes

Although I have enhanced unit tests and hand testing along the way, I'd certainly appreciate it. I hope to have this merged by early next week; we're planning an RC soon.

Hi All, I am trying to set custom DN for the certificates. I have setup Root CA and Intermediate CA. I followed this blog http://cuddletech.com/?p=959
Also closely looked at https://www.vaultproject.io/api/secret/pki/index.html.
I did not find a way to provide custom Subject for certificates except O, OU and CN fields.
I want more fields in the cert e.g C=US, ST=MA likewise.
Can you please suggest how can I do that?

Steps I followed:

  1. Created Root CA
  2. Created CSR for Intermediate CA
  3. Generated certificate for intermediate CA and imported for intermediate CA.
  4. Created Certificate Role (Provided "O" and "OU" fields_
  5. Generating Server certificate using Intermediate CA and Role.
Was this page helpful?
0 / 5 - 0 ratings

Related issues

justintime picture justintime  Â·  55Comments

emk picture emk  Â·  79Comments

TopherGopher picture TopherGopher  Â·  36Comments

mwitkow picture mwitkow  Â·  142Comments

ekristen picture ekristen  Â·  34Comments