You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
If you want to implement this feature, comment to let us know (we'll work with you on design, scheduling, etc.)
Issue details
Although this can be done via template, it would be more useful to have it in the cli and to have it available to the csr as well (sign the csr as is, but add some constraints).
Why is this needed?
Particularly useful for signing an intermediate certificate offline and limiting it to a subset of domains like in my previous example #717
Although it would be possible to create a CSR with the same extension, you will need to encode the extension itself manually and sign with a template that takes the RAW certificate request like this:
{{ toJson .Insecure.CR }}
This process can be tedious, and I see the case for #717. But at the same time, I see more benefit of adding --template to step ca init and perhaps another flag to pass the intermediate key. In any case, all this can be achieved with a little bit of scripting.
If we add --template to step ca init, would that address your concerns? Would you like to be able to pass the intermediate key too?
Regarding this part of the issue, using the template we do not preserve the same fields that the csr was requesting right? That's why I was considering better as a flag in order to use it together with --csr just like --not-after works. Alternatively, we could add a functionality that --template and --csr flags together copy all of the original fields first, then override them with template values.
About templates, it can be tedious to design one for each use-case, so how about something more similar to how openstack does it. I.e., they provide a giant template with all features they support, then we enable/define each feature by passing --environment that are just json/yaml of the necessary fields you want to define/override. For example here instead of --template original --environment with:
Another (not exclusive) way to allow these extension is to use jinja modules and add template jinja files that simply override each module section. The only potential confusion there would be, when does the jinja file override the base, and when does it extend. Although, this feature might not even be available in go's engine.
Regarding this part of the issue, using the template we do not preserve the same fields that the csr was requesting right?
It actually depends on the template, you can achieve that if you want, my template doesn't do that, but you have access to the CSR using .Insecure.CR.
Our templates have already the ability to use variables and replace values on it from a file from a key=value flag. I thought it was available in step certificate create and step certificate sign, but it doesn't look like it. I will create an issue to add it.
I can also provide you with a template with all or most of the features if you want. You can always see the JSON tags and types here
Ok, I think we're almost there. .Insecure.CR is the full certificate or a flag? If it's the former how do we override dictionary items afterwards? If it's the latter this would get the csr + constraints right:
.Insecure.CR is the full certificate signing request as we see it CertificateRequest, very similar to x509.CertificateRequest, so you cannot use it exactly like that as it will not create a valid JSON.
Manipulating the JSON directly might be difficult, so it will be better to access the properties you're interested in, e.g. the subject is {{ .Inscure.CR.Subject }}, using the Go fields, not the JSON names. And extend that with name and basic constraints extensions, here for example I'm doing that including also extensions present if the CSR:
Hmm, isn't this a compelling reason to change the behavior of hot step certificate sign behaves when combining --template and --csr? I.e.:
Scenario 1: We want to override all/most csr fields: we use only --template and access what we want to keep via .Insecure.CR (Currently implemented)
Scenario 2: We want only the original csr fields: we use only --csr (Currently implemented)
Scenario 3: We want to override some csr fields: combine --csr and --template flags (Not implemented)
This should cover any ambiguity in the template when fields are not specified: if we want to include them, add --csr, if we want to make sure nothing else is included, do not add --csr. I only took a quick look at the relevant code, and I can't find a quick way to implement this, so it might take some re-coding to achieve this.
You can do Scenario 3 too. You can for example loop through all the extensions in the template and include only the ones that you want to use.
Scenario 3 is the opposite. For example, you want to include all the subject, basicConstraints, extensions of the original csr, but you want to add on top of that one more extension. Or in the case of this issue, you want all of the csr mentioned fields, but add namedConstraints.
If we wanted to override the extensions, that would be Scenario 1.
But about #719, that should solve most Scenario 3 usecases, but setting extensions would overwrite the whole list, right? We would still need a functionality of combining --profile csr with either --template or --set so that it merges instead of overwrites.
And just to clarify, with --csr you're referring to --profile csr in step certificate sign, right?
Hi @LecrisUT, I've added a PR with some of the things we've been talking about, the --set and --set-file flags in step certificate sign and step certificate create.
For example, if you have two labs you can use those flags to customize the automation of different certificates without modifying the template:
Activity
maraino commentedon Aug 10, 2022
Hi @LecrisUT, one of the reasons that we created templates was to avoid adding flags for all things that can go in a certificate.
To do this, you will create a template:
{ "subject": {{ toJson .Subject }}, "keyUsage": ["certSign", "crlSign"], "basicConstraints": { "isCA": true, "maxPathLen": 0 }, "nameConstraints": { "critical": true, "permittedDNSDomains": [".example.com"] } }And run this:
Although it would be possible to create a CSR with the same extension, you will need to encode the extension itself manually and sign with a template that takes the RAW certificate request like this:
{{ toJson .Insecure.CR }}This process can be tedious, and I see the case for #717. But at the same time, I see more benefit of adding
--templatetostep ca initand perhaps another flag to pass the intermediate key. In any case, all this can be achieved with a little bit of scripting.If we add
--templatetostep ca init, would that address your concerns? Would you like to be able to pass the intermediate key too?LecrisUT commentedon Aug 11, 2022
Regarding this part of the issue, using the template we do not preserve the same fields that the csr was requesting right? That's why I was considering better as a flag in order to use it together with
--csrjust like--not-afterworks. Alternatively, we could add a functionality that--templateand--csrflags together copy all of the original fields first, then override them with template values.About templates, it can be tedious to design one for each use-case, so how about something more similar to how openstack does it. I.e., they provide a giant template with all features they support, then we enable/define each feature by passing
--environmentthat are just json/yaml of the necessary fields you want to define/override. For example here instead of--templateoriginal--environmentwith:Another (not exclusive) way to allow these extension is to use jinja modules and add template jinja files that simply override each module section. The only potential confusion there would be, when does the jinja file override the base, and when does it extend. Although, this feature might not even be available in go's engine.
maraino commentedon Aug 11, 2022
It actually depends on the template, you can achieve that if you want, my template doesn't do that, but you have access to the CSR using
.Insecure.CR.Our templates have already the ability to use variables and replace values on it from a file from a key=value flag. I thought it was available in
step certificate createandstep certificate sign, but it doesn't look like it. I will create an issue to add it.I can also provide you with a template with all or most of the features if you want. You can always see the JSON tags and types here
maraino commentedon Aug 11, 2022
FYI, just added this #719
LecrisUT commentedon Aug 12, 2022
Ok, I think we're almost there.
.Insecure.CRis the full certificate or a flag? If it's the former how do we override dictionary items afterwards? If it's the latter this would get the csr + constraints right:Isn't that the case for the built-in template? Doesn't the template engine support if expansions?
maraino commentedon Aug 15, 2022
.Insecure.CRis the full certificate signing request as we see it CertificateRequest, very similar tox509.CertificateRequest, so you cannot use it exactly like that as it will not create a valid JSON.Manipulating the JSON directly might be difficult, so it will be better to access the properties you're interested in, e.g. the subject is
{{ .Inscure.CR.Subject }}, using the Go fields, not the JSON names. And extend that with name and basic constraints extensions, here for example I'm doing that including also extensions present if the CSR:{ "subject": {{ toJson .Insecure.CR.Subject }}, "extensions": {{ toJson .Insecure.CR.Extensions }}, "nameConstraints": { "permittedDNSDomains": [".example.com"] }, "basicConstraints": { "isCA": true, "maxPathLen": 0 } }In most cases, you will not need the extensions in CSR extensions as you can define them in the certificate template.
And then:
step certificate sign --template my.tpl my.csr root_ca.crt root_ca.keyLecrisUT commentedon Aug 17, 2022
Hmm, isn't this a compelling reason to change the behavior of hot
step certificate signbehaves when combining--templateand--csr? I.e.:--templateand access what we want to keep via.Insecure.CR(Currently implemented)--csr(Currently implemented)--csrand--templateflags (Not implemented)This should cover any ambiguity in the template when fields are not specified: if we want to include them, add
--csr, if we want to make sure nothing else is included, do not add--csr. I only took a quick look at the relevant code, and I can't find a quick way to implement this, so it might take some re-coding to achieve this.maraino commentedon Aug 17, 2022
You can do Scenario 3 too. You can for example loop through all the extensions in the template and include only the ones that you want to use.
And just to clarify, with
--csryou're referring to--profile csrinstep certificate sign, right?LecrisUT commentedon Aug 17, 2022
Scenario 3 is the opposite. For example, you want to include all the
subject,basicConstraints,extensionsof the original csr, but you want to add on top of that one more extension. Or in the case of this issue, you want all of the csr mentioned fields, but addnamedConstraints.If we wanted to override the
extensions, that would be Scenario 1.But about #719, that should solve most Scenario 3 usecases, but setting
extensionswould overwrite the whole list, right? We would still need a functionality of combining--profile csrwith either--templateor--setso that it merges instead of overwrites.yes
maraino commentedon Aug 17, 2022
Hi @LecrisUT, I've added a PR with some of the things we've been talking about, the
--setand--set-fileflags instep certificate signandstep certificate create.For example, if you have two labs you can use those flags to customize the automation of different certificates without modifying the template:
The same is available on
step certificate sign, which includes.Insecure.CR.