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
import (
"context"
"crypto"
"crypto/sha256"
"crypto/x509"
@ -20,6 +21,8 @@ import (
"github.com/smallstep/certificates/authority"
"github.com/smallstep/certificates/authority/provisioner"
"github.com/smallstep/certificates/ca"
"github.com/smallstep/certificates/cas"
"github.com/smallstep/certificates/cas/apiv1"
"github.com/smallstep/certificates/db"
"github.com/smallstep/cli/config"
"github.com/smallstep/cli/errs"
@ -157,6 +160,7 @@ type PKI struct {
dnsNames []string
caURL string
enableSSH bool
authorityOptions *apiv1.Options
}
// New creates a new PKI configuration.
@ -233,6 +237,12 @@ func (p *PKI) GetRootFingerprint() string {
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.
func (p *PKI) SetProvisioner(s string) {
p.provisioner = s
@ -307,10 +317,12 @@ func (p *PKI) WriteRootCertificate(rootCrt *x509.Certificate, rootKey interface{
return err
}
if rootKey != nil {
_, err := pemutil.Serialize(rootKey, pemutil.WithPassword(pass), pemutil.ToFile(p.rootKey, 0600))
if err != nil {
return err
}
}
sum := sha256.Sum256(rootCrt.Raw)
p.rootFingerprint = strings.ToLower(hex.EncodeToString(sum[:]))
@ -318,6 +330,37 @@ func (p *PKI) WriteRootCertificate(rootCrt *x509.Certificate, rootKey interface{
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
// the given name.
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() {
ui.Println()
if p.authorityOptions == nil || p.authorityOptions.Is(apiv1.SoftCAS) {
ui.PrintSelected("Root certificate", p.root)
ui.PrintSelected("Root private key", p.rootKey)
ui.PrintSelected("Root fingerprint", p.rootFingerprint)
ui.PrintSelected("Intermediate certificate", p.intermediate)
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 {
ui.PrintSelected("SSH user root certificate", p.sshUserPubKey)
ui.PrintSelected("SSH user root private key", p.sshUserKey)
@ -485,6 +535,7 @@ func (p *PKI) GenerateConfig(opt ...Option) (*authority.Config, error) {
DataSource: GetDBPath(),
},
AuthorityConfig: &authority.AuthConfig{
Options: p.authorityOptions,
DisableIssuedAtCheck: false,
Provisioners: provisioner.List{prov},
},
@ -591,7 +642,11 @@ func (p *PKI) Save(opt ...Option) error {
ui.PrintSelected("Default configuration", p.defaults)
ui.PrintSelected("Certificate Authority configuration", p.config)
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'.")
} else {
ui.Println("Your registration authority is ready to go. To generate certificates for individual services see 'step help ca'.")
}
p.askFeedback()