mirror of
https://github.com/smallstep/certificates.git
synced 2024-11-17 15:29:21 +00:00
210 lines
6.6 KiB
Go
210 lines
6.6 KiB
Go
package pki
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"text/template"
|
|
|
|
"github.com/pkg/errors"
|
|
"github.com/smallstep/certificates/authority"
|
|
authconfig "github.com/smallstep/certificates/authority/config"
|
|
"github.com/smallstep/certificates/authority/provisioner"
|
|
"github.com/smallstep/certificates/templates"
|
|
"go.step.sm/linkedca"
|
|
)
|
|
|
|
type helmVariables struct {
|
|
*linkedca.Configuration
|
|
Defaults *linkedca.Defaults
|
|
Password string
|
|
EnableSSH bool
|
|
EnableAdmin bool
|
|
TLS authconfig.TLSOptions
|
|
Provisioners []provisioner.Interface
|
|
}
|
|
|
|
// WriteHelmTemplate a helm template to configure the
|
|
// smallstep/step-certificates helm chart.
|
|
func (p *PKI) WriteHelmTemplate(w io.Writer) error {
|
|
tmpl, err := template.New("helm").Funcs(templates.StepFuncMap()).Parse(helmTemplate)
|
|
if err != nil {
|
|
return errors.Wrap(err, "error writing helm template")
|
|
}
|
|
|
|
// Delete ssh section if it is not enabled
|
|
if !p.options.enableSSH {
|
|
p.Ssh = nil
|
|
}
|
|
|
|
// Convert provisioners to ca.json representation
|
|
provisioners := []provisioner.Interface{}
|
|
for _, p := range p.Authority.Provisioners {
|
|
pp, err := authority.ProvisionerToCertificates(p)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
provisioners = append(provisioners, pp)
|
|
}
|
|
|
|
// Add default ACME provisioner if enabled. Note that this logic is similar
|
|
// to what's in p.GenerateConfig(), but that codepath isn't taken when
|
|
// writing the Helm template. The default JWK provisioner is added earlier in
|
|
// the process and that's part of the provisioners above.
|
|
//
|
|
// To prevent name clashes for the default ACME provisioner, we append "-1" to
|
|
// the name if it already exists. See https://github.com/smallstep/cli/issues/1018
|
|
// for the reason.
|
|
//
|
|
// TODO(hs): consider refactoring the initialization, so that this becomes
|
|
// easier to reason about and maintain.
|
|
if p.options.enableACME {
|
|
acmeProvisionerName := "acme"
|
|
for _, prov := range provisioners {
|
|
if prov.GetName() == acmeProvisionerName {
|
|
acmeProvisionerName = fmt.Sprintf("%s-1", acmeProvisionerName)
|
|
break
|
|
}
|
|
}
|
|
provisioners = append(provisioners, &provisioner.ACME{
|
|
Type: "ACME",
|
|
Name: acmeProvisionerName,
|
|
})
|
|
}
|
|
|
|
// Add default SSHPOP provisioner if enabled. Similar to the above, this is
|
|
// the same as what happens in p.GenerateConfig(). To prevent name clashes for the
|
|
// default SSHPOP provisioner, we append "-1" to it if it already exists. See
|
|
// https://github.com/smallstep/cli/issues/1018 for the reason.
|
|
if p.options.enableSSH {
|
|
sshProvisionerName := "sshpop"
|
|
for _, prov := range provisioners {
|
|
if prov.GetName() == sshProvisionerName {
|
|
sshProvisionerName = fmt.Sprintf("%s-1", sshProvisionerName)
|
|
break
|
|
}
|
|
}
|
|
provisioners = append(provisioners, &provisioner.SSHPOP{
|
|
Type: "SSHPOP",
|
|
Name: sshProvisionerName,
|
|
Claims: &provisioner.Claims{
|
|
EnableSSHCA: &p.options.enableSSH,
|
|
},
|
|
})
|
|
}
|
|
|
|
if err := tmpl.Execute(w, helmVariables{
|
|
Configuration: &p.Configuration,
|
|
Defaults: &p.Defaults,
|
|
Password: "",
|
|
EnableSSH: p.options.enableSSH,
|
|
EnableAdmin: p.options.enableAdmin,
|
|
TLS: authconfig.DefaultTLSOptions,
|
|
Provisioners: provisioners,
|
|
}); err != nil {
|
|
return errors.Wrap(err, "error executing helm template")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
const helmTemplate = `# Helm template
|
|
inject:
|
|
enabled: true
|
|
# Config contains the configuration files ca.json and defaults.json
|
|
config:
|
|
files:
|
|
ca.json:
|
|
root: {{ first .Root }}
|
|
federateRoots: []
|
|
crt: {{ .Intermediate }}
|
|
key: {{ .IntermediateKey }}
|
|
{{- if .Kms }}
|
|
kms:
|
|
type: {{ lower (.Kms.Type | toString) }}
|
|
{{- end }}
|
|
{{- if .EnableSSH }}
|
|
ssh:
|
|
hostKey: {{ .Ssh.HostKey }}
|
|
userKey: {{ .Ssh.UserKey }}
|
|
{{- end }}
|
|
address: {{ .Address }}
|
|
dnsNames:
|
|
{{- range .DnsNames }}
|
|
- {{ . }}
|
|
{{- end }}
|
|
logger:
|
|
format: json
|
|
db:
|
|
type: badgerv2
|
|
dataSource: /home/step/db
|
|
authority:
|
|
enableAdmin: {{ .EnableAdmin }}
|
|
provisioners:
|
|
{{- range .Provisioners }}
|
|
- {{ . | toJson }}
|
|
{{- end }}
|
|
tls:
|
|
cipherSuites:
|
|
{{- range .TLS.CipherSuites }}
|
|
- {{ . }}
|
|
{{- end }}
|
|
minVersion: {{ .TLS.MinVersion }}
|
|
maxVersion: {{ .TLS.MaxVersion }}
|
|
renegotiation: {{ .TLS.Renegotiation }}
|
|
|
|
defaults.json:
|
|
ca-url: {{ .Defaults.CaUrl }}
|
|
ca-config: {{ .Defaults.CaConfig }}
|
|
fingerprint: {{ .Defaults.Fingerprint }}
|
|
root: {{ .Defaults.Root }}
|
|
|
|
# Certificates contains the root and intermediate certificate and
|
|
# optionally the SSH host and user public keys
|
|
certificates:
|
|
# intermediate_ca contains the text of the intermediate CA Certificate
|
|
intermediate_ca: |
|
|
{{- index .Files .Intermediate | toString | nindent 6 }}
|
|
|
|
# root_ca contains the text of the root CA Certificate
|
|
root_ca: |
|
|
{{- first .Root | index .Files | toString | nindent 6 }}
|
|
|
|
{{- if .Ssh }}
|
|
# ssh_host_ca contains the text of the public ssh key for the SSH root CA
|
|
ssh_host_ca: {{ index .Files .Ssh.HostPublicKey | toString }}
|
|
|
|
# ssh_user_ca contains the text of the public ssh key for the SSH root CA
|
|
ssh_user_ca: {{ index .Files .Ssh.UserPublicKey | toString }}
|
|
{{- end }}
|
|
|
|
# Secrets contains the root and intermediate keys and optionally the SSH
|
|
# private keys
|
|
secrets:
|
|
# ca_password contains the password used to encrypt x509.intermediate_ca_key, ssh.host_ca_key and ssh.user_ca_key
|
|
# This value must be base64 encoded.
|
|
ca_password: {{ .Password | b64enc }}
|
|
provisioner_password: {{ .Password | b64enc}}
|
|
|
|
x509:
|
|
# intermediate_ca_key contains the contents of your encrypted intermediate CA key
|
|
intermediate_ca_key: |
|
|
{{- index .Files .IntermediateKey | toString | nindent 8 }}
|
|
|
|
# root_ca_key contains the contents of your encrypted root CA key
|
|
# Note that this value can be omitted without impacting the functionality of step-certificates
|
|
# If supplied, this should be encrypted using a unique password that is not used for encrypting
|
|
# the intermediate_ca_key, ssh.host_ca_key or ssh.user_ca_key.
|
|
root_ca_key: |
|
|
{{- first .RootKey | index .Files | toString | nindent 8 }}
|
|
|
|
{{- if .Ssh }}
|
|
ssh:
|
|
# ssh_host_ca_key contains the contents of your encrypted SSH Host CA key
|
|
host_ca_key: |
|
|
{{- index .Files .Ssh.HostKey | toString | nindent 8 }}
|
|
|
|
# ssh_user_ca_key contains the contents of your encrypted SSH User CA key
|
|
user_ca_key: |
|
|
{{- index .Files .Ssh.UserKey | toString | nindent 8 }}
|
|
{{- end }}
|
|
`
|