Skip to content

Commit

Permalink
Add support for set and set-file in certificate create and sign
Browse files Browse the repository at this point in the history
Fixes @719
  • Loading branch information
maraino committed Aug 17, 2022
1 parent 86eb2d1 commit 99a4891
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 12 deletions.
33 changes: 26 additions & 7 deletions command/certificate/create.go
Expand Up @@ -41,7 +41,8 @@ func createCommand() cli.Command {
Action: command.ActionFunc(createAction),
Usage: "create a certificate or certificate signing request",
UsageText: `**step certificate create** <subject> <crt-file> <key-file>
[**--kms**=<uri>] [**--csr**] [**--profile**=<profile>] [**--template**=<file>]
[**--kms**=<uri>] [**--csr**] [**--profile**=<profile>]
[**--template**=<file>] [**--set**=<key=value>] [**--set-file**=<file>]
[**--not-before**=<duration>] [**--not-after**=<duration>]
[**--password-file**=<file>] [**--ca**=<issuer-cert>]
[**--ca-key**=<issuer-key>] [**--ca-password-file**=<file>]
Expand Down Expand Up @@ -263,21 +264,32 @@ $ step certificate create --template root.tpl \
'''
Create an intermediate certificate using the previous root. This intermediate
will be able to sign also new intermediate certificates:
will be able to sign also new intermediate certificates. We will also make the
subject configurable using the **--set** and **--set-file** flags.
'''
$ cat intermediate.tpl
{
"subject": {
"commonName": "Acme Corporation Intermediate CA"
"country": {{ toJson .Insecure.User.country }},
"organization": {{ toJson .Insecure.User.organization }},
"organizationalUnit": {{ toJson .Insecure.User.organizationUnit }},
"commonName": {{toJson .Subject.CommonName }}
},
"keyUsage": ["certSign", "crlSign"],
"basicConstraints": {
"isCA": true,
"maxPathLen": 1
}
}
$ cat organization.json
{
"country": "US",
"organization": "Acme Corporation",
"organizationUnit": "HQ"
}
$ step certificate create --template intermediate.tpl \
--ca root_ca.crt --ca-key root_ca_key \
--set-file organization.json --set organizationUnit=Engineering \
"Acme Corporation Intermediate CA" intermediate_ca.crt intermediate_ca_key
'''
Expand Down Expand Up @@ -367,10 +379,9 @@ $ step certificate create \
This profile requires the **--subtle** flag because the use of self-signed leaf
certificates is discouraged unless absolutely necessary.`,
},
cli.StringFlag{
Name: "template",
Usage: `The certificate template <file>, a JSON representation of the certificate to create.`,
},
flags.Template,
flags.TemplateSet,
flags.TemplateSetFile,
cli.StringFlag{
Name: "password-file",
Usage: `The <file> to the file containing the password to
Expand Down Expand Up @@ -494,6 +505,12 @@ func createAction(ctx *cli.Context) error {
template = string(b)
}

// Parse --set and --set-file
userData, err := flags.GetTemplateData(ctx)
if err != nil {
return err
}

// Read or generate key pair
pub, priv, err := parseOrCreateKey(ctx)
if err != nil {
Expand Down Expand Up @@ -536,6 +553,7 @@ func createAction(ctx *cli.Context) error {

// Create certificate request
data := x509util.CreateTemplateData(subject, sans)
data.SetUserData(userData)
csr, err := x509util.NewCertificateRequest(priv, x509util.WithTemplate(template, data))
if err != nil {
return err
Expand Down Expand Up @@ -620,6 +638,7 @@ func createAction(ctx *cli.Context) error {

// Create X.509 certificate
templateData := x509util.CreateTemplateData(subject, sans)
templateData.SetUserData(userData)
certificate, err := x509util.NewCertificate(cr, x509util.WithTemplate(template, templateData))
if err != nil {
return err
Expand Down
49 changes: 44 additions & 5 deletions command/certificate/sign.go
Expand Up @@ -37,7 +37,8 @@ func signCommand() cli.Command {
Action: cli.ActionFunc(signAction),
Usage: "sign a certificate signing request (CSR)",
UsageText: `**step certificate sign** <csr-file> <crt-file> <key-file>
[**--profile**=<profile>] [**--template**=<file>]
[**--profile**=<profile>] [**--template**=<file>]
[**--set**=<key=value>] [**--set-file**=<file>]
[**--password-file**=<file>] [**--path-len**=<maximum>]
[**--not-before**=<time|duration>] [**--not-after**=<time|duration>]
[**--bundle**]`,
Expand Down Expand Up @@ -112,6 +113,37 @@ $ step certificate create --csr coyote@acme.corp coyote.csr coyote.key
$ step certificate sign --template coyote.tpl coyote.csr issuer.crt issuer.key
'''
Sign a CSR using a template and allow configuring the subject using the
**--set** and **--set-file** flags.
'''
$ cat rocket.tpl
{
"subject": {
"country": {{ toJson .Insecure.User.country }},
"organization": {{ toJson .Insecure.User.organization }},
"organizationalUnit": {{ toJson .Insecure.User.organizationUnit }},
"commonName": {{toJson .Subject.CommonName }}
},
"sans": {{ toJson .SANs }},
{{- if typeIs "*rsa.PublicKey" .Insecure.CR.PublicKey }}
"keyUsage": ["keyEncipherment", "digitalSignature"],
{{- else }}
"keyUsage": ["digitalSignature"],
{{- end }}
"extKeyUsage": ["serverAuth", "clientAuth"]
}
$ cat organization.json
{
"country": "US",
"organization": "Acme Corporation",
"organizationUnit": "HQ"
}
$ step certificate create --csr rocket.acme.corp rocket.csr rocket.key
$ step certificate sign --template rocket.tpl \
--set-file organization.json --set organizationUnit=Engineering \
rocket.csr issuer.crt issuer.key
'''
Sign a CSR using <step-kms-plugin>:
'''
$ step certificate sign \
Expand Down Expand Up @@ -139,10 +171,9 @@ $ step certificate sign \
**csr**
: Signs a x.509 certificate without modifying the CSR.`,
},
cli.StringFlag{
Name: "template",
Usage: `The certificate template <file>, a JSON representation of the certificate to create.`,
},
flags.Template,
flags.TemplateSet,
flags.TemplateSetFile,
flags.PasswordFile,
cli.StringFlag{
Name: "not-before",
Expand Down Expand Up @@ -234,12 +265,19 @@ func signAction(ctx *cli.Context) error {

// Read template if passed. If not use a template depending on the profile.
var template string
var userData map[string]interface{}
if templateFile != "" {
b, err := utils.ReadFile(templateFile)
if err != nil {
return err
}
template = string(b)

// Parse --set and --set-file
userData, err = flags.GetTemplateData(ctx)
if err != nil {
return err
}
} else {
switch profile {
case profileLeaf:
Expand Down Expand Up @@ -290,6 +328,7 @@ func signAction(ctx *cli.Context) error {

// Create certificate template from csr.
data := createTemplateData(csr, maxPathLen)
data.SetUserData(userData)
tpl, err := x509util.NewCertificate(csr, x509util.WithTemplate(template, data))
if err != nil {
return err
Expand Down

0 comments on commit 99a4891

Please sign in to comment.