certificates icon indicating copy to clipboard operation
certificates copied to clipboard

Ability to have multiple Intermediate Certs

Open willanta opened this issue 5 years ago • 16 comments

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.

willanta avatar Feb 11 '20 00:02 willanta

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

mmalone avatar Feb 11 '20 16:02 mmalone

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

dopey avatar Apr 15 '20 16:04 dopey

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.

wagnerflo avatar Feb 24 '21 20:02 wagnerflo

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

voanhduy1512 avatar Feb 25 '21 11:02 voanhduy1512

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).

AluisioASG avatar Mar 01 '21 22:03 AluisioASG

@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.

dopey avatar Mar 01 '21 23:03 dopey

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?

TheSecMaven avatar Sep 17 '21 13:09 TheSecMaven

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.

mmalone avatar Sep 17 '21 15:09 mmalone

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": "[email protected]",
            "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

TheSecMaven avatar Sep 18 '21 14:09 TheSecMaven

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.

dopey avatar Sep 20 '21 17:09 dopey

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).

mmalone avatar Sep 20 '21 19:09 mmalone

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.

sergeysedoy97 avatar Jul 27 '22 18:07 sergeysedoy97

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.

tashian avatar Jul 27 '22 23:07 tashian

@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

sergeysedoy97 avatar Jul 28 '22 17:07 sergeysedoy97

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

tashian avatar Aug 01 '22 18:08 tashian

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.

andsens avatar Apr 28 '24 06:04 andsens