Add support for step ca init with a RA.

This commit is contained in:
Mariano Cano 2020-10-19 18:42:03 -07:00
parent ef92a3a6d7
commit d46990d4c4

View file

@ -1,6 +1,7 @@
package pki package pki
import ( import (
"context"
"crypto" "crypto"
"crypto/sha256" "crypto/sha256"
"crypto/x509" "crypto/x509"
@ -20,6 +21,8 @@ import (
"github.com/smallstep/certificates/authority" "github.com/smallstep/certificates/authority"
"github.com/smallstep/certificates/authority/provisioner" "github.com/smallstep/certificates/authority/provisioner"
"github.com/smallstep/certificates/ca" "github.com/smallstep/certificates/ca"
"github.com/smallstep/certificates/cas"
"github.com/smallstep/certificates/cas/apiv1"
"github.com/smallstep/certificates/db" "github.com/smallstep/certificates/db"
"github.com/smallstep/cli/config" "github.com/smallstep/cli/config"
"github.com/smallstep/cli/errs" "github.com/smallstep/cli/errs"
@ -157,6 +160,7 @@ type PKI struct {
dnsNames []string dnsNames []string
caURL string caURL string
enableSSH bool enableSSH bool
authorityOptions *apiv1.Options
} }
// New creates a new PKI configuration. // New creates a new PKI configuration.
@ -233,6 +237,12 @@ func (p *PKI) GetRootFingerprint() string {
return p.rootFingerprint return p.rootFingerprint
} }
// SetAuthorityOptions sets the authority options object, these options are used
// to configure a registration authority.
func (p *PKI) SetAuthorityOptions(opts *apiv1.Options) {
p.authorityOptions = opts
}
// SetProvisioner sets the provisioner name of the OTT keys. // SetProvisioner sets the provisioner name of the OTT keys.
func (p *PKI) SetProvisioner(s string) { func (p *PKI) SetProvisioner(s string) {
p.provisioner = s p.provisioner = s
@ -307,10 +317,12 @@ func (p *PKI) WriteRootCertificate(rootCrt *x509.Certificate, rootKey interface{
return err return err
} }
if rootKey != nil {
_, err := pemutil.Serialize(rootKey, pemutil.WithPassword(pass), pemutil.ToFile(p.rootKey, 0600)) _, err := pemutil.Serialize(rootKey, pemutil.WithPassword(pass), pemutil.ToFile(p.rootKey, 0600))
if err != nil { if err != nil {
return err return err
} }
}
sum := sha256.Sum256(rootCrt.Raw) sum := sha256.Sum256(rootCrt.Raw)
p.rootFingerprint = strings.ToLower(hex.EncodeToString(sum[:])) p.rootFingerprint = strings.ToLower(hex.EncodeToString(sum[:]))
@ -318,6 +330,37 @@ func (p *PKI) WriteRootCertificate(rootCrt *x509.Certificate, rootKey interface{
return nil return nil
} }
// GetCertificateAuthority attempts to load the certificate authority from the
// RA.
func (p *PKI) GetCertificateAuthority() error {
ca, err := cas.New(context.Background(), *p.authorityOptions)
if err != nil {
return err
}
srv, ok := ca.(apiv1.CertificateAuthorityGetter)
if !ok {
return nil
}
resp, err := srv.GetCertificateAuthority(&apiv1.GetCertificateAuthorityRequest{
Name: p.authorityOptions.CertificateAuthority,
})
if err != nil {
return err
}
if err := p.WriteRootCertificate(resp.RootCertificate, nil, nil); err != nil {
return err
}
// Issuer is in the RA
p.intermediate = ""
p.intermediateKey = ""
return nil
}
// GenerateIntermediateCertificate generates an intermediate certificate with // GenerateIntermediateCertificate generates an intermediate certificate with
// the given name. // the given name.
func (p *PKI) GenerateIntermediateCertificate(name string, rootCrt *x509.Certificate, rootKey interface{}, pass []byte) error { func (p *PKI) GenerateIntermediateCertificate(name string, rootCrt *x509.Certificate, rootKey interface{}, pass []byte) error {
@ -414,11 +457,18 @@ func (p *PKI) TellPKI() {
func (p *PKI) tellPKI() { func (p *PKI) tellPKI() {
ui.Println() ui.Println()
if p.authorityOptions == nil || p.authorityOptions.Is(apiv1.SoftCAS) {
ui.PrintSelected("Root certificate", p.root) ui.PrintSelected("Root certificate", p.root)
ui.PrintSelected("Root private key", p.rootKey) ui.PrintSelected("Root private key", p.rootKey)
ui.PrintSelected("Root fingerprint", p.rootFingerprint) ui.PrintSelected("Root fingerprint", p.rootFingerprint)
ui.PrintSelected("Intermediate certificate", p.intermediate) ui.PrintSelected("Intermediate certificate", p.intermediate)
ui.PrintSelected("Intermediate private key", p.intermediateKey) ui.PrintSelected("Intermediate private key", p.intermediateKey)
} else if p.rootFingerprint != "" {
ui.PrintSelected("Root certificate", p.root)
ui.PrintSelected("Root fingerprint", p.rootFingerprint)
} else {
ui.Printf(`{{ "%s" | red }} {{ "Root certificate:" | bold }} failed to retrieve it from RA`+"\n", ui.IconBad)
}
if p.enableSSH { if p.enableSSH {
ui.PrintSelected("SSH user root certificate", p.sshUserPubKey) ui.PrintSelected("SSH user root certificate", p.sshUserPubKey)
ui.PrintSelected("SSH user root private key", p.sshUserKey) ui.PrintSelected("SSH user root private key", p.sshUserKey)
@ -485,6 +535,7 @@ func (p *PKI) GenerateConfig(opt ...Option) (*authority.Config, error) {
DataSource: GetDBPath(), DataSource: GetDBPath(),
}, },
AuthorityConfig: &authority.AuthConfig{ AuthorityConfig: &authority.AuthConfig{
Options: p.authorityOptions,
DisableIssuedAtCheck: false, DisableIssuedAtCheck: false,
Provisioners: provisioner.List{prov}, Provisioners: provisioner.List{prov},
}, },
@ -591,7 +642,11 @@ func (p *PKI) Save(opt ...Option) error {
ui.PrintSelected("Default configuration", p.defaults) ui.PrintSelected("Default configuration", p.defaults)
ui.PrintSelected("Certificate Authority configuration", p.config) ui.PrintSelected("Certificate Authority configuration", p.config)
ui.Println() ui.Println()
if p.authorityOptions == nil || p.authorityOptions.Is(apiv1.SoftCAS) {
ui.Println("Your PKI is ready to go. To generate certificates for individual services see 'step help ca'.") ui.Println("Your PKI is ready to go. To generate certificates for individual services see 'step help ca'.")
} else {
ui.Println("Your registration authority is ready to go. To generate certificates for individual services see 'step help ca'.")
}
p.askFeedback() p.askFeedback()