forked from TrueCloudLab/certificates
Integrate simple templates in the JWK provisioner.
This commit is contained in:
parent
d1d9ae42d6
commit
ef0ed0ff95
4 changed files with 85 additions and 3 deletions
|
@ -8,6 +8,7 @@ import (
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/smallstep/certificates/errs"
|
"github.com/smallstep/certificates/errs"
|
||||||
|
"github.com/smallstep/certificates/x509util"
|
||||||
"github.com/smallstep/cli/jose"
|
"github.com/smallstep/cli/jose"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -25,7 +26,7 @@ type stepPayload struct {
|
||||||
// JWK is the default provisioner, an entity that can sign tokens necessary for
|
// JWK is the default provisioner, an entity that can sign tokens necessary for
|
||||||
// signature requests.
|
// signature requests.
|
||||||
type JWK struct {
|
type JWK struct {
|
||||||
*base
|
base
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Key *jose.JSONWebKey `json:"key"`
|
Key *jose.JSONWebKey `json:"key"`
|
||||||
|
@ -151,7 +152,14 @@ func (p *JWK) AuthorizeSign(ctx context.Context, token string) ([]SignOption, er
|
||||||
claims.SANs = []string{claims.Subject}
|
claims.SANs = []string{claims.Subject}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data := x509util.CreateTemplateData(claims.Subject, claims.SANs)
|
||||||
|
templateOptions, err := TemplateOptions(p.Options, data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errs.Wrap(http.StatusInternalServerError, err, "jwk.AuthorizeSign")
|
||||||
|
}
|
||||||
|
|
||||||
return []SignOption{
|
return []SignOption{
|
||||||
|
templateOptions,
|
||||||
// modifiers / withOptions
|
// modifiers / withOptions
|
||||||
newProvisionerExtensionOption(TypeJWK, p.Name, p.Key.KeyID),
|
newProvisionerExtensionOption(TypeJWK, p.Name, p.Key.KeyID),
|
||||||
profileDefaultDuration(p.claimer.DefaultTLSCertDuration()),
|
profileDefaultDuration(p.claimer.DefaultTLSCertDuration()),
|
||||||
|
|
72
authority/provisioner/options.go
Normal file
72
authority/provisioner/options.go
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
package provisioner
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/smallstep/certificates/x509util"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CertificateOptions is an interface that returns a list of options passed when
|
||||||
|
// creating a new certificate.
|
||||||
|
type CertificateOptions interface {
|
||||||
|
Options(Options) []x509util.Option
|
||||||
|
}
|
||||||
|
|
||||||
|
type certificateOptionsFunc func(Options) []x509util.Option
|
||||||
|
|
||||||
|
func (fn certificateOptionsFunc) Options(so Options) []x509util.Option {
|
||||||
|
return fn(so)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProvisionerOptions struct {
|
||||||
|
Template string `json:"template"`
|
||||||
|
TemplateFile string `json:"templateFile`
|
||||||
|
TemplateData json.RawMessage `json:"templateData"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TemplateOptions generate a CertificateOptions with the template and data
|
||||||
|
// defined in the ProvisionerOptions, the provisioner generated data, and the
|
||||||
|
// user data provided in the request.
|
||||||
|
func TemplateOptions(o *ProvisionerOptions, data x509util.TemplateData) (CertificateOptions, error) {
|
||||||
|
if o != nil {
|
||||||
|
if data == nil {
|
||||||
|
data = make(x509util.TemplateData)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add template data if any.
|
||||||
|
if len(o.TemplateData) > 0 {
|
||||||
|
if err := json.Unmarshal(o.TemplateData, data); err != nil {
|
||||||
|
return nil, errors.Wrap(err, "error unmarshaling template data")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return certificateOptionsFunc(func(so Options) []x509util.Option {
|
||||||
|
// We're not provided user data without custom templates.
|
||||||
|
if o == nil || (o.Template == "" && o.TemplateFile == "") {
|
||||||
|
return []x509util.Option{
|
||||||
|
x509util.WithTemplate(x509util.DefaultLeafTemplate, data),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add user provided data.
|
||||||
|
if len(so.UserData) > 0 {
|
||||||
|
userObject := make(map[string]interface{})
|
||||||
|
if err := json.Unmarshal(so.UserData, userObject); err != nil {
|
||||||
|
data[x509util.UserKey] = map[string]interface{}{}
|
||||||
|
} else {
|
||||||
|
data[x509util.UserKey] = userObject
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if o.Template == "" && o.TemplateFile != "" {
|
||||||
|
return []x509util.Option{
|
||||||
|
x509util.WithTemplateFile(o.TemplateFile, data),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return []x509util.Option{
|
||||||
|
x509util.WithTemplateFile(o.Template, data),
|
||||||
|
}
|
||||||
|
}), nil
|
||||||
|
}
|
|
@ -279,7 +279,9 @@ func SanitizeSSHUserPrincipal(email string) string {
|
||||||
}, strings.ToLower(email))
|
}, strings.ToLower(email))
|
||||||
}
|
}
|
||||||
|
|
||||||
type base struct{}
|
type base struct {
|
||||||
|
Options *ProvisionerOptions `json:"options"`
|
||||||
|
}
|
||||||
|
|
||||||
// AuthorizeSign returns an unimplemented error. Provisioners should overwrite
|
// AuthorizeSign returns an unimplemented error. Provisioners should overwrite
|
||||||
// this method if they will support authorizing tokens for signing x509 Certificates.
|
// this method if they will support authorizing tokens for signing x509 Certificates.
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/Masterminds/sprig"
|
"github.com/Masterminds/sprig/v3"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/smallstep/cli/config"
|
"github.com/smallstep/cli/config"
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue