Prepend insecure to user and CR variables names.

This commit is contained in:
Mariano Cano 2020-07-14 17:12:07 -07:00
parent 69902b0153
commit b2ca3176f5
3 changed files with 54 additions and 31 deletions

View file

@ -19,9 +19,18 @@ func (fn certificateOptionsFunc) Options(so Options) []x509util.Option {
return fn(so) return fn(so)
} }
// ProvisionerOptions are a collection of custom options that can be added to
// each provisioner.
type ProvisionerOptions struct { type ProvisionerOptions struct {
// Template contains a X.509 certificate template. It can be a JSON template
// escaped in a string or it can be also encoded in base64.
Template string `json:"template"` Template string `json:"template"`
// TemplateFile points to a file containing a X.509 certificate template.
TemplateFile string `json:"templateFile"` TemplateFile string `json:"templateFile"`
// TemplateData is a JSON object with variables that can be used in custom
// templates.
TemplateData json.RawMessage `json:"templateData"` TemplateData json.RawMessage `json:"templateData"`
} }
@ -63,11 +72,13 @@ func CustomTemplateOptions(o *ProvisionerOptions, data x509util.TemplateData, de
if len(so.TemplateData) > 0 { if len(so.TemplateData) > 0 {
userObject := make(map[string]interface{}) userObject := make(map[string]interface{})
if err := json.Unmarshal(so.TemplateData, &userObject); err != nil { if err := json.Unmarshal(so.TemplateData, &userObject); err != nil {
data[x509util.UserKey] = map[string]interface{}{} data.SetUserData(map[string]interface{}{})
} else { } else {
data[x509util.UserKey] = userObject data.SetUserData(userObject)
} }
} }
// Load a template from a file if Template is not defined.
if o.Template == "" && o.TemplateFile != "" { if o.Template == "" && o.TemplateFile != "" {
return []x509util.Option{ return []x509util.Option{
x509util.WithTemplateFile(o.TemplateFile, data), x509util.WithTemplateFile(o.TemplateFile, data),

View file

@ -3,6 +3,7 @@ package x509util
import ( import (
"bytes" "bytes"
"crypto/x509" "crypto/x509"
"encoding/base64"
"io/ioutil" "io/ioutil"
"text/template" "text/template"
@ -47,6 +48,19 @@ func WithTemplate(text string, data TemplateData) Option {
} }
} }
// WithTemplateBase64 is an options that executes the given template base64
// string with the given data.
func WithTemplateBase64(s string, data TemplateData) Option {
return func(cr *x509.CertificateRequest, o *Options) error {
b, err := base64.StdEncoding.DecodeString(s)
if err != nil {
return errors.Wrap(err, "error decoding template")
}
fn := WithTemplate(string(b), data)
return fn(cr, o)
}
}
// WithTemplateFile is an options that reads the template file and executes it // WithTemplateFile is an options that reads the template file and executes it
// with the given data. // with the given data.
func WithTemplateFile(path string, data TemplateData) Option { func WithTemplateFile(path string, data TemplateData) Option {
@ -56,18 +70,7 @@ func WithTemplateFile(path string, data TemplateData) Option {
if err != nil { if err != nil {
return errors.Wrapf(err, "error reading %s", path) return errors.Wrapf(err, "error reading %s", path)
} }
fn := WithTemplate(string(b), data)
tmpl, err := template.New(path).Funcs(sprig.TxtFuncMap()).Parse(string(b)) return fn(cr, o)
if err != nil {
return errors.Wrapf(err, "error parsing %s", path)
}
buf := new(bytes.Buffer)
data.SetCertificateRequest(cr)
if err := tmpl.Execute(buf, data); err != nil {
return errors.Wrapf(err, "error executing %s", path)
}
o.CertBuffer = buf
return nil
} }
} }

View file

@ -3,10 +3,11 @@ package x509util
import "crypto/x509" import "crypto/x509"
const ( const (
UserKey = "User"
SubjectKey = "Subject" SubjectKey = "Subject"
SANsKey = "SANs" SANsKey = "SANs"
TokenKey = "Token" TokenKey = "Token"
InsecureKey = "Insecure"
UserKey = "User"
CertificateRequestKey = "CR" CertificateRequestKey = "CR"
) )
@ -33,12 +34,16 @@ func (t TemplateData) Set(key string, v interface{}) {
t[key] = v t[key] = v
} }
func (t TemplateData) SetUserData(v Subject) { func (t TemplateData) SetInsecure(key string, v interface{}) {
t[UserKey] = v if m, ok := t[InsecureKey].(TemplateData); ok {
m[key] = v
} else {
t[InsecureKey] = TemplateData{key: v}
}
} }
func (t TemplateData) SetSubject(v Subject) { func (t TemplateData) SetSubject(v Subject) {
t[SubjectKey] = v t.Set(SubjectKey, v)
} }
func (t TemplateData) SetCommonName(cn string) { func (t TemplateData) SetCommonName(cn string) {
@ -48,15 +53,19 @@ func (t TemplateData) SetCommonName(cn string) {
} }
func (t TemplateData) SetSANs(sans []string) { func (t TemplateData) SetSANs(sans []string) {
t[SANsKey] = CreateSANs(sans) t.Set(SANsKey, CreateSANs(sans))
} }
func (t TemplateData) SetToken(v interface{}) { func (t TemplateData) SetToken(v interface{}) {
t[TokenKey] = v t.Set(TokenKey, v)
}
func (t TemplateData) SetUserData(v interface{}) {
t.SetInsecure(UserKey, v)
} }
func (t TemplateData) SetCertificateRequest(cr *x509.CertificateRequest) { func (t TemplateData) SetCertificateRequest(cr *x509.CertificateRequest) {
t[CertificateRequestKey] = newCertificateRequest(cr) t.SetInsecure(CertificateRequestKey, newCertificateRequest(cr))
} }
// DefaultLeafTemplate is the default templated used to generate a leaf // DefaultLeafTemplate is the default templated used to generate a leaf
@ -79,14 +88,14 @@ const DefaultLeafTemplate = `{
// keys. // keys.
const DefaultIIDLeafTemplate = `{ const DefaultIIDLeafTemplate = `{
{{- if .SANs }} {{- if .SANs }}
"subject": {"commonName": "{{ .CR.Subject.CommonName }}"}, "subject": {"commonName": "{{ .Insecure.CR.Subject.CommonName }}"},
"sans": {{ toJson .SANs }}, "sans": {{ toJson .SANs }},
{{- else }} {{- else }}
"subject": {{ toJson .CR.Subject }}, "subject": {{ toJson .Insecure.CR.Subject }},
"dnsNames": {{ toJson .CR.DNSNames }}, "dnsNames": {{ toJson .Insecure.CR.DNSNames }},
"emailAddresses": {{ toJson .CR.EmailAddresses }}, "emailAddresses": {{ toJson .Insecure.CR.EmailAddresses }},
"ipAddresses": {{ toJson .CR.IPAddresses }}, "ipAddresses": {{ toJson .Insecure.CR.IPAddresses }},
"uris": {{ toJson .CR.URIs }}, "uris": {{ toJson .Insecure.CR.URIs }},
{{- end }} {{- end }}
"keyUsage": ["keyEncipherment", "digitalSignature"], "keyUsage": ["keyEncipherment", "digitalSignature"],
"extKeyUsage": ["serverAuth", "clientAuth"] "extKeyUsage": ["serverAuth", "clientAuth"]
@ -117,4 +126,4 @@ const DefaultRootTemplate = `{
// CertificateRequestTemplate is a template that will sign the given certificate // CertificateRequestTemplate is a template that will sign the given certificate
// request. // request.
const CertificateRequestTemplate = `{{ toJson .CR }}` const CertificateRequestTemplate = `{{ toJson .Insecure.CR }}`