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

Auto-generated Vault certs #135

Closed
far-blue opened this issue Jul 26, 2016 · 12 comments
Closed

Auto-generated Vault certs #135

far-blue opened this issue Jul 26, 2016 · 12 comments
Milestone

Comments

@far-blue
Copy link

I'm investigating hooking up Vault with Fabio and I'm a little confused about the cert store config. The documentation suggests Fabio will fetch certs dynamically from Vault but the config seems to imply that the certs are expected to be manually dropped into a generic 'secret' store in Vault. Is there also support for the PKI secret store and its ability to auto-generate certificates?

@magiconair
Copy link
Contributor

Not yet. I'll check what it takes to add that.

@far-blue
Copy link
Author

far-blue commented Jul 26, 2016

I can manually issue a cert using the following:

vault write pki/issue/server-dev common_name=foo.server.dev

In this example I've set up a pki backend with an internally generated root cert for *.server.dev and then I've created a role 'server-dev' that is allowed to serve certs for .server.dev based on the root cert. Using the above command will return both the private and public parts of the new cert as well as a copy of the CA.

The vault cli just wraps the rest api so I assume the http request would be pretty similar.

@blalor
Copy link

blalor commented May 16, 2017

I'd really like to see Vault's PKI backend supported, as well. I've been chewing on this for an hour or so and I think the model of multiple certs per cert store doesn't exactly mesh with Vault's PKI backend, but if each vault-pki certificate source has a single pki secret path instead of multiples, that would probably work fine. One of the config options to the vault-pki cert source would be a list of SANs that would be on the cert, perhaps?

@magiconair
Copy link
Contributor

I'm curious how this would work independent of vault since you could mimic this with a script or LetsEncrypt or something else. The current CertSource model is that certificates exist and that fabio just picks them up. If a cert does not exist fabio will refuse the connection.

In the model of a generated cert that would no longer happen unless the cert provider refuses to generate the cert.

Who controls which certs are permissible? Can fabio just generate any cert? What if I announce urlprefix-www.google.com/ ?

@pschultz
Copy link
Member

The Vault operator defines what certificates can be issued on a given path.

From fabios perspective there is almost no difference to fetching certs from the generic secret backend. In Go, it looks something like this:

import "github.com/hashicorp/vault/api"

var client *api.Client

response, err := client.Logical().Write("pki-fabio/issue/example.com", map[string]interface{}{
	"common_name": "foo.example.com",
	"alt_names": "localhost,127.0.0.1",
	"ttl":         "24h", // uses Vault's default if omitted
})

pemKey := response.Data["private_key"].(string)
certChain := response.Data["certificate"].(string) + "\n"
for _, cert := range response.Data["ca_chain"].([]interface{}) {
	certChain += cert.(string) + "\n"
}

So very similar to what the current vault store does. client.Logical().Read is replaced with client.Logical().Write, and the data structure is a bit different from what the current store expects. The "pki-fabio/issue/com.example" path has to be configured in fabio (like for the Consul store).

Each Write() call generates a new certificate. It will not return previously generated certs. Previously generates certs remain valid. This is different from how Letsencrypt works.

For completeness, this is what a Vault operator might do in advance:

# Mount a pki backend for fabio to use. Certificates will expire after 7 days
# by default (7*24=168), and attempting to issue certificates with a validity 
# period of more than 30 days will be denied (30*24=720).
vault mount \
    -path pki-fabio \
    -default-lease-ttl=168h \
    -max-lease-ttl=720h \
    pki

# Define which certificates can be issued via the pki-fabio/issue/example.com path.
vault write pki-fabio/roles/example.com \
    allowed_domains="example.com" \
    allow_subdomains="true" \
    allow_localhost="true"

Many more role options are available. I omitted the commands for configuring the CA for the pki-fabio mount.

Would you be interested in a PR with a rough draft for an implementation?

@magiconair
Copy link
Contributor

Yes, a PR would be welcome. Generated certs need to be cached for as long as they're valid (or TTL/2) since this method is called per connection. I assume the base path defines the root domain for which you can generate certs. I think that's fine but you should take into account use-cases for multiple domains.

@pschultz
Copy link
Member

In the "pki-fabio/issue/example.com" path, "pki-fabio" represents a single CA, and "example.com" represents the constraints for issuing certs from that CA, such as allowed domains (what Vault calls a role).

@magiconair
Copy link
Contributor

The question is whether you want to allow one or all domains in the pki or whether you want to be able to restrict it to some (e.g. foo.com and bar.com but not google.com for example)

@magiconair
Copy link
Contributor

I don't know how to achieve that and whether that's something you can do within the vault config that fabio just has to send or whether there needs to be something to be done in fabio and/or whether we need to extend the config DSL. Just keep that in mind when creating the PR, please.

pschultz added a commit to classmarkets/fabio that referenced this issue Jul 1, 2017
Add a new cert.Source, VaultPKISource, that issues certficates on demand
from HashiCorp Vault PKI backend.
pschultz added a commit to classmarkets/fabio that referenced this issue Jul 7, 2017
Add a new cert.Source, VaultPKISource, that issues certficates on demand
from a HashiCorp Vault PKI backend.
@manos
Copy link

manos commented Jul 25, 2017

🍿 watching with excitement. Happy to help test.

@manos
Copy link

manos commented Jul 25, 2017

Regarding the authorization of the domain, I don't think fabio needs to be involved. If someone asks for foo.company.com and vault allows that cert to be fetched, fabio can serve the cert it fetches (and cache it). If vault doesn't allow it, fabio can serve a default cert or throw an error?

@pschultz
Copy link
Member

That's exactly what the PR currently implements. If a cert cannot be issued fabio drops the request. There is no default cert because strictmatch is implied with the vault-pki source.

pschultz added a commit to classmarkets/fabio that referenced this issue Oct 10, 2017
Add a new cert.Source, VaultPKISource, that issues certficates on demand
from a HashiCorp Vault PKI backend.
pschultz added a commit to classmarkets/fabio that referenced this issue Oct 10, 2017
Add a new cert.Source, VaultPKISource, that issues certficates on demand
from a HashiCorp Vault PKI backend.
@magiconair magiconair added this to the 1.6.0 milestone Oct 10, 2017
@magiconair magiconair modified the milestones: 1.6, 1.5.3 Nov 3, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants