smallstep / certificates

🛡️ A private certificate authority (X.509 & SSH) & ACME server for secure automated certificate management, so you can use TLS everywhere & SSO for SSH.
https://smallstep.com/certificates
Apache License 2.0
6.67k stars 433 forks source link

Ability to have multiple Intermediate Certs #186

Open willanta opened 4 years ago

willanta commented 4 years ago

It would be handy to have an easy way of generating intermediate certificates after the ca init step and then choose which one to sign with when generating certs (maybe by provisioner).

Not everything can do online renewal and obey the standards enforced so having a shorter lived intermediate for signing this legacy stuff would be super useful. A lot of devices also don't support the proper cert chain so I'm having to distribute the intermediate cert with the root cert to clients and I'd rather keep that separate from the intermediate doing online provisioning.

mmalone commented 4 years ago

Related: https://github.com/smallstep/cli/issues/213

dopey commented 4 years ago

Duplicate / Related to https://github.com/smallstep/certificates/issues/87.

wagnerflo commented 3 years ago

Yes. Being able to select the intermediate (or rather chain of intermediates to be able to ship it with the issued leaf if I understood #440 correctly) a provisioner uses would be nice.

voanhduy1512 commented 3 years ago

Unfortunately I can't find any doc on how to use #440 functionality.

AluisioASG commented 3 years ago

As far as I can tell, #440 is only about having multiple intermediates in a single chain, not about having multiple/per-provisioner chains (which is this issue).

dopey commented 3 years ago

@voanhduy1512 @AluisioASG is correct. #440 allows step-ca to use a certificate chain that is longer than just root -> intermediate -> leaf. It does not give you the ability to set different signing CA's per provisioner.

TheSecMaven commented 3 years ago

So just to confirm I understand this right, the ability to sign certs with one subordinate CA for a provisioner, and a different subordinate CA for another provisioner, is not currently possible?

Any thoughts as to how that would be enabled, if someone was able to work on it?

mmalone commented 3 years ago

Hey Miclain,

Correct. That's not currently possible. Hypothetically, I could see the intermediate signing key / certificate configured on a per-provisioner basis. Practically, there are a bunch of little complications & details that need to be sorted out to get that to work. It needs to be done in a way that doesn't complicate the user experience for more typical use cases. I think we'd need a thorough design document that we could stare at before we can even size this one. At the moment, it's not on the top of the priority list.

Internally, we have a piece of technology that runs many instances of step-ca in a single process. We use this in our commercial product. That serves a similar purpose, except that each subordinate ends up with a different domain name. Instances of step-ca are pretty lightweight. Would running multiple instances (e.g., in containers, or on the same VM behind an SNI-routing TCP proxy) work here?

I encourage anyone in the community who wants this feature implemented to express interest here by giving the issue a thumbs up or, even better, responding with a brief description of their use case / requirements to help us prioritize.

TheSecMaven commented 3 years ago

Thanks for the thoughts. I agree that this certainly wouldn't be the normal, to me it seems like an "override" because you are saying you want to use a specific signing authority for this provisioner, but not others.

I took a swag at getting this working, and it looks somewhat low code. The idea is simple, provide options in the provisioner that allow one to override the signing CA for that provisioner only. Otherwise, use the default signing authority used everywhere else.

For my example, this looked like

   "authority": {
      "provisioners": [
         {
                "options": {
                    "x509": {
                        "crt": "certs/override_provisioner_ca.crt",
                        "key": "secrets/override_provisioner_ca_key",
                        "password": "changeit",
                        "templateData": {
                            "OrganizationalUnit": "My Team"
                        }
                    }
                },
            "type": "JWK",
            "name": "me@autozone.com",
            "key": {
               ...            },
            "encryptedKey": ...
         }

Where the special sauce is crt, key and password being defined in that section of the config.

Works like a charm for me with the simplest use case (signing a cert with JWK), obviously would still need to flesh out renew/revoke and others if the method outlined above was acceptable. Would love thoughts on the idea, and whether people think it keeps the use case simple.

Very rough just to prove the use case, but here was the hardest part where IF an override was defined, we have to create the new key manager on the fly https://github.com/mkkeffeler/certificates/blob/byProvisionerSigningAuthority/cas/softcas/softcas.go#L77

dopey commented 3 years ago

My reluctance with accepting file params for an alternative signer is that we'll be opening ourselves up to accept all the different signer types that we accept for the intermediate key. The intermediate key can be delivered as a file on disk, cloud HSM, physical HSM ... I assume that if we're going to support an alternative signer per provisioner then it needs to be a first class citizen and support all the existing signer types.

mmalone commented 3 years ago

Yea, we'd definitely want to support the different signer types.

As an MVP, I get what you did here. This does look like the lightest-weight thing that could be done to deliver the core functionality you're after. But, in this case, that's the easy part. I'm more concerned about how this would interact with things like renewal (step ca renew / step ca rekey), revocation (step ca revoke), root distribution (step ca bootstrap / step ca root), provisioner management, certificate bundling, etc (I'm probably missing corner cases). For each of these concerns, I think there will be changes on both the client- and server-side (step and step-ca).

I don't think there are any dealbreakers in all of this... there's just a lot of little stuff. Enough little stuff that I wonder whether it'd be better / easier to understand to just have two authorities.

FYI, we do have some ongoing work around "contexts", which let you configure the CLI to connect to multiple authorities and switch between them more naturally (e.g., you can run step ca certificate ... --context foo to select an authority called foo, or you can step context switch foo to change your default context).

sergeysedoy97 commented 2 years ago

Will this be implemented? Nice idea: https://github.com/smallstep/certificates/issues/186#issuecomment-922287243

Now, there is no way to sign CSR with different intermediate certs.

tashian commented 2 years ago

Hi @sergeysedoy97, this feature is not on our short-term road map. The current best option is to run a CA for each intermediate. It's now easier to manage this on the client side, since the the --context flag that @mmalone mentioned above has been added to both step and step-ca.

sergeysedoy97 commented 2 years ago

@tashian could I run one step server with many contexts? Seems like I need to run step-ca few times with different contexts. I also tried step-ca in RA mode, but it uses intermediate of step-ca in CA mode. Is it possible to setup RA with one more intermediate certificate? E.g.

[ Root -> Intermediate A ] --> [ Intermediate B ]
[ CA                     ] --> [ RA             ]

There is Intermediate A is signed by Root and Intermediate B is signed by Intermediate A

tashian commented 2 years ago

@sergeysedoy97 You'd need to run multiple instances of step-ca on different ports or domains, with different contexts & intermediates.

andsens commented 5 months ago

This would be super useful in securing access to a Kubernetes cluster when combined with kube-apiserver X.509 client certificates (--client-ca-file).
The apiserver accepts whatever the CN of a cert says and authenticates you as the user account with the same name. Trouble is that step-ca has limited flexibility when restricting CNs (understandably) and the apiserver doesn't look for any other special fields (also understandable). This means that simply adding the smallstep intermediate to the list of CAs trusted by the kube-apiserver can be incredibly restricting because you'd need to tightly lock down what provisioners are allowed to issue.
If instead you had a single provisioner that has exclusive access to a different intermediate you could safely add that one to the kube-apiserver list of trusted CAs.