Store ssl certificates in vault

Dear Vault community,

I would like to ask if my use case fits vaults functionality.

Use case 1
I have a an nginx web server and I would like to store my ssl domain certificates in vault. The idea is to take the files from vault through an ansible script and put in the nginx ssl folder. I know vault can act as a cert manager but in this case I need to use the certificates provided.

Use case 2
Same issue storing ssl certificates to be used by nginx but in this case the certificates does not leave vault and nginx uses then from there instead of being files in the filesystem

Would either user case 1 or 2 be possible? which secret engine would be suitable for this?

thank you very much

Number 1 is definitely possible. Just store the cert inside the kv secret store and then pull it out using Ansible as needed.

Number 2 would require some sort of plugin for nginx or other adjustment to read the cert directly out of Vault. I don’t know if such a thing exists or is even possible.

1 Like

There will always be a “secret” in a file. You get to pick the file, that’s it.

The certificate is public. The servers hands it to anybody that connects to it, so put it wherever you want. The important part is the private key that goes with the certificate. Let’s concentrate on the private key.

Say a plug-in existed that allowed to store the private key in Vault with TLS in mind. It would work in one of two ways:

  1. Vault hands of the private key when nginx starts (what the kv store actually does)
  2. nginx asks Vault to do the cryptographic operations required for TLS to work (what a plugin would do)

Both options require nginx to have valid credentials in Vault, like an AppRole secret_id. You’ve done nothing but to pick a different file to put your secret in. If you are worried an attacker can read the private key, you are now worried they can read the secret-id that provides the private key. No security gain, just added mere minutes to your hacker’s plan.

Option 2 - setting aside the huge latency and performce issue it brings - would allow the private key to never leave Vault. But you would still credentials to ask Vault to perform the operations. If you absolutely must keep the private key outside your server’s filesystem, you can use a Hardware Security Module (HSM) optimized for that purpose. They are really expensive and hard to manage and usually not worth it in a risk reduction scenario.

The best solution for this is to use short lived certificates issued by Vault. You still need credentials to get them, but at least you get to control and audit what the certificate is used for.

1 Like

Hi ,thank you both for your answers.
It is still not clear to me how the private key will be stored since it needs to have a “specific format” which I don’t think the kv secret engine supports?

The format of your value doesn’t matter. You can always encode it as text and store it. That said, PEM file is text and can be easily stored as such. CRT files, can be uuencoded and stored.

@aram is right, the format does not matter.

To have your reflection going, this is what we do. We do it for public key, the encoding problem is the same.

A private key in PEM format looks like this (using a small, insecure key to save space):

# generated with: openssl genrsa 512 > key.pem

To avoid dealing with newlines, we convert it to DER (binary) format and do a plain old base64 of it.

To key above would look like this in DER format (openssl rsa -in key.pem -outform DER -out key.der):

00000000: 3082 013c 0201 0002 4100 a085 09e3 da47  0..<....A......G
00000010: 3ac6 15b7 db7f 4ed7 6b4d dede fecb 1dbd  :.....N.kM......
00000020: b7b5 a8c5 e1f1 3c41 6c8b fbdd ed51 604a  ......<Al....Q`J
00000030: 2cd2 4a78 0d36 074b c276 80e0 b2de 4577  ,.Jx.6.K.v....Ew
00000040: 6243 18d7 2910 ac36 84d3 0203 0100 0102  bC..)..6........
00000050: 4059 f857 83c3 ab9a f0bd e990 78b9 bb1a  @Y.W........x...
00000060: 64ca 1f99 1645 b439 8cf3 6cfe 6815 0ae2  d....E.9..l.h...
00000070: 886c 107f ccfd f426 808c 0ca4 2829 2458  .l.....&....()$X
00000080: f57e e231 b2ce d57a a660 0b48 761d e556  .~.1...z.`.Hv..V
00000090: 9102 2100 d373 b33f d797 4fac 18b6 47e0  ..!..s.?..O...G.
000000a0: d729 be17 a8cd 9b50 b630 885b 3fe5 db54  .).....P.0.[?..T
000000b0: 09cd c709 0221 00c2 5664 b5ac ae02 9703  .....!..Vd......
000000c0: db3c 219d 20b6 8f72 cb0f a826 8543 9a09  .<!. ..r...&.C..
000000d0: d025 c95b 9227 fb02 2100 8f60 868c a58c  .%.[.'..!..`....
000000e0: edf3 0d96 9bca 735a d490 8a5f 500f 3c5a  ......sZ..._P.<Z
000000f0: 503b 3f6a 867b c762 06b1 0221 00bb dbb7  P;?j.{.b...!....
00000100: cec6 f60f 1adc 6779 6124 fb12 7ee8 80d2  ......gya$..~...
00000110: c9c1 32e1 7e6e 2dff d8fd e3f3 3102 2100  ..2.~n-.....1.!.
00000120: 9856 31f5 5eba 7617 2459 b58f c3ba 9a32  .V1.^.v.$Y.....2
00000130: 0e53 6771 4683 899c eaac cce5 d739 7ab9  .SgqF........9z.

Saved in the KV store like this:

vault kv put secret/my-app private-key=$(openssl base64 -A -in key.der)

More work than a double base64 encode of the PEM format but we found that it was easier than to parse a text format. Besides, libraries we used support DER natively.

If required, here is how we get the key back from Vault in PEM format:

vault kv get -field private-key secret/my-app | openssl base64 -d -A | openssl rsa -inform DER