2020-07-02 01:30:41 +00:00
|
|
|
package x509util
|
|
|
|
|
2020-07-16 19:24:57 +00:00
|
|
|
import (
|
|
|
|
"crypto/x509"
|
|
|
|
)
|
2020-07-09 18:40:37 +00:00
|
|
|
|
2020-07-08 01:56:05 +00:00
|
|
|
const (
|
2020-07-09 18:40:37 +00:00
|
|
|
SubjectKey = "Subject"
|
|
|
|
SANsKey = "SANs"
|
|
|
|
TokenKey = "Token"
|
2020-07-15 00:12:07 +00:00
|
|
|
InsecureKey = "Insecure"
|
|
|
|
UserKey = "User"
|
2020-07-09 18:40:37 +00:00
|
|
|
CertificateRequestKey = "CR"
|
2020-07-08 01:56:05 +00:00
|
|
|
)
|
|
|
|
|
2020-07-17 02:43:22 +00:00
|
|
|
// TemplateError represents an error in a template produced by the fail
|
|
|
|
// function.
|
2020-07-16 19:25:40 +00:00
|
|
|
type TemplateError struct {
|
|
|
|
Message string
|
|
|
|
}
|
|
|
|
|
2020-07-17 02:43:22 +00:00
|
|
|
// Error implements the error interface and returns the error string when a
|
|
|
|
// template executes the `fail "message"` function.
|
2020-07-16 19:25:40 +00:00
|
|
|
func (e *TemplateError) Error() string {
|
|
|
|
return e.Message
|
|
|
|
}
|
|
|
|
|
2020-07-08 22:53:11 +00:00
|
|
|
// TemplateData is an alias for map[string]interface{}. It represents the data
|
|
|
|
// passed to the templates.
|
|
|
|
type TemplateData map[string]interface{}
|
|
|
|
|
2020-07-09 22:17:32 +00:00
|
|
|
// NewTemplateData creates a new map for templates data.
|
|
|
|
func NewTemplateData() TemplateData {
|
|
|
|
return TemplateData{}
|
|
|
|
}
|
|
|
|
|
|
|
|
// CreateTemplateData creates a new TemplateData with the given common name and SANs.
|
|
|
|
func CreateTemplateData(commonName string, sans []string) TemplateData {
|
|
|
|
return TemplateData{
|
|
|
|
SubjectKey: Subject{
|
|
|
|
CommonName: commonName,
|
|
|
|
},
|
|
|
|
SANsKey: CreateSANs(sans),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-08 22:53:11 +00:00
|
|
|
func (t TemplateData) Set(key string, v interface{}) {
|
|
|
|
t[key] = v
|
|
|
|
}
|
|
|
|
|
2020-07-15 00:12:07 +00:00
|
|
|
func (t TemplateData) SetInsecure(key string, v interface{}) {
|
|
|
|
if m, ok := t[InsecureKey].(TemplateData); ok {
|
|
|
|
m[key] = v
|
|
|
|
} else {
|
|
|
|
t[InsecureKey] = TemplateData{key: v}
|
|
|
|
}
|
2020-07-08 22:53:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (t TemplateData) SetSubject(v Subject) {
|
2020-07-15 00:12:07 +00:00
|
|
|
t.Set(SubjectKey, v)
|
2020-07-08 22:53:11 +00:00
|
|
|
}
|
|
|
|
|
2020-07-13 19:47:26 +00:00
|
|
|
func (t TemplateData) SetCommonName(cn string) {
|
|
|
|
s, _ := t[SubjectKey].(Subject)
|
|
|
|
s.CommonName = cn
|
|
|
|
t[SubjectKey] = s
|
|
|
|
}
|
|
|
|
|
2020-07-08 22:53:11 +00:00
|
|
|
func (t TemplateData) SetSANs(sans []string) {
|
2020-07-15 00:12:07 +00:00
|
|
|
t.Set(SANsKey, CreateSANs(sans))
|
2020-07-08 22:53:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (t TemplateData) SetToken(v interface{}) {
|
2020-07-15 00:12:07 +00:00
|
|
|
t.Set(TokenKey, v)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t TemplateData) SetUserData(v interface{}) {
|
|
|
|
t.SetInsecure(UserKey, v)
|
2020-07-08 22:53:11 +00:00
|
|
|
}
|
|
|
|
|
2020-07-09 18:40:37 +00:00
|
|
|
func (t TemplateData) SetCertificateRequest(cr *x509.CertificateRequest) {
|
2020-07-15 00:12:07 +00:00
|
|
|
t.SetInsecure(CertificateRequestKey, newCertificateRequest(cr))
|
2020-07-09 18:40:37 +00:00
|
|
|
}
|
|
|
|
|
2020-07-16 19:24:57 +00:00
|
|
|
// DefaultLeafTemplate is the default template used to generate a leaf
|
|
|
|
// certificate.
|
2020-07-02 01:30:41 +00:00
|
|
|
const DefaultLeafTemplate = `{
|
|
|
|
"subject": {{ toJson .Subject }},
|
2020-07-08 01:56:05 +00:00
|
|
|
"sans": {{ toJson .SANs }},
|
2020-07-16 19:24:57 +00:00
|
|
|
{{- if typeIs "*rsa.PublicKey" .Insecure.CR.PublicKey }}
|
2020-07-02 01:30:41 +00:00
|
|
|
"keyUsage": ["keyEncipherment", "digitalSignature"],
|
2020-07-16 19:24:57 +00:00
|
|
|
{{- else }}
|
|
|
|
"keyUsage": ["digitalSignature"],
|
|
|
|
{{- end }}
|
2020-07-02 01:30:41 +00:00
|
|
|
"extKeyUsage": ["serverAuth", "clientAuth"]
|
|
|
|
}`
|
2020-07-08 23:39:19 +00:00
|
|
|
|
2020-07-13 19:47:26 +00:00
|
|
|
// DefaultIIDLeafTemplate is the template used by default on instance identity
|
|
|
|
// provisioners like AWS, GCP or Azure. By default, those provisioners allow the
|
|
|
|
// SANs provided in the certificate request, but the option `DisableCustomSANs`
|
|
|
|
// can be provided to force only the verified domains, if the option is true
|
|
|
|
// `.SANs` will be set with the verified domains.
|
|
|
|
const DefaultIIDLeafTemplate = `{
|
2020-07-21 00:19:20 +00:00
|
|
|
"subject": {"commonName":"{{ .Insecure.CR.Subject.CommonName }}"},
|
2020-07-16 19:24:57 +00:00
|
|
|
{{- if .SANs }}
|
2020-07-13 19:47:26 +00:00
|
|
|
"sans": {{ toJson .SANs }},
|
2020-07-16 19:24:57 +00:00
|
|
|
{{- else }}
|
2020-07-15 00:12:07 +00:00
|
|
|
"dnsNames": {{ toJson .Insecure.CR.DNSNames }},
|
|
|
|
"emailAddresses": {{ toJson .Insecure.CR.EmailAddresses }},
|
|
|
|
"ipAddresses": {{ toJson .Insecure.CR.IPAddresses }},
|
|
|
|
"uris": {{ toJson .Insecure.CR.URIs }},
|
2020-07-16 19:24:57 +00:00
|
|
|
{{- end }}
|
|
|
|
{{- if typeIs "*rsa.PublicKey" .Insecure.CR.PublicKey }}
|
2020-07-13 19:47:26 +00:00
|
|
|
"keyUsage": ["keyEncipherment", "digitalSignature"],
|
2020-07-16 19:24:57 +00:00
|
|
|
{{- else }}
|
|
|
|
"keyUsage": ["digitalSignature"],
|
|
|
|
{{- end }}
|
2020-07-13 19:47:26 +00:00
|
|
|
"extKeyUsage": ["serverAuth", "clientAuth"]
|
|
|
|
}`
|
|
|
|
|
|
|
|
// DefaultIntermediateTemplate is a template that can be used to generate an
|
|
|
|
// intermediate certificate.
|
2020-07-08 23:39:19 +00:00
|
|
|
const DefaultIntermediateTemplate = `{
|
|
|
|
"subject": {{ toJson .Subject }},
|
|
|
|
"keyUsage": ["certSign", "crlSign"],
|
|
|
|
"basicConstraints": {
|
|
|
|
"isCA": true,
|
|
|
|
"maxPathLen": 0
|
|
|
|
}
|
|
|
|
}`
|
|
|
|
|
2020-07-13 19:47:26 +00:00
|
|
|
// DefaultRootTemplate is a template that can be used to generate a root
|
|
|
|
// certificate.
|
2020-07-08 23:39:19 +00:00
|
|
|
const DefaultRootTemplate = `{
|
|
|
|
"subject": {{ toJson .Subject }},
|
|
|
|
"issuer": {{ toJson .Subject }},
|
|
|
|
"keyUsage": ["certSign", "crlSign"],
|
|
|
|
"basicConstraints": {
|
|
|
|
"isCA": true,
|
|
|
|
"maxPathLen": 1
|
|
|
|
}
|
|
|
|
}`
|
2020-07-13 21:36:59 +00:00
|
|
|
|
|
|
|
// CertificateRequestTemplate is a template that will sign the given certificate
|
|
|
|
// request.
|
2020-07-15 00:12:07 +00:00
|
|
|
const CertificateRequestTemplate = `{{ toJson .Insecure.CR }}`
|