Remove deprecated methods and write all pki files at once.

This commit is contained in:
Mariano Cano 2021-08-05 15:57:13 -07:00
parent ad4dbd6764
commit 79cf059447

View file

@ -156,10 +156,8 @@ func GetProvisionerKey(caURL, rootFile, kid string) (string, error) {
} }
type options struct { type options struct {
// address string
// caURL string
// dnsNames []string
provisioner string provisioner string
pkiOnly bool
enableACME bool enableACME bool
enableSSH bool enableSSH bool
enableAdmin bool enableAdmin bool
@ -199,6 +197,13 @@ func WithProvisioner(s string) PKIOption {
} }
} }
// WithPKIOnly will only generate the PKI without the step-ca config files.
func WithPKIOnly() PKIOption {
return func(p *PKI) {
p.options.pkiOnly = true
}
}
// WithACME enables acme provisioner in step-ca. // WithACME enables acme provisioner in step-ca.
func WithACME() PKIOption { func WithACME() PKIOption {
return func(p *PKI) { return func(p *PKI) {
@ -244,17 +249,12 @@ func WithDeploymentType(dt DeploymentType) PKIOption {
// PKI represents the Public Key Infrastructure used by a certificate authority. // PKI represents the Public Key Infrastructure used by a certificate authority.
type PKI struct { type PKI struct {
linkedca.Configuration linkedca.Configuration
Defaults linkedca.Defaults Defaults linkedca.Defaults
casOptions apiv1.Options casOptions apiv1.Options
caService apiv1.CertificateAuthorityService caService apiv1.CertificateAuthorityService
caCreator apiv1.CertificateAuthorityCreator caCreator apiv1.CertificateAuthorityCreator
// root, rootKey, rootFingerprint string config string
// intermediate, intermediateKey string defaults string
// sshHostPubKey, sshHostKey string
// sshUserPubKey, sshUserKey string
config string
defaults string
// rootFingerprint string
ottPublicKey *jose.JSONWebKey ottPublicKey *jose.JSONWebKey
ottPrivateKey *jose.JSONWebEncryption ottPrivateKey *jose.JSONWebEncryption
options *options options *options
@ -386,34 +386,6 @@ func (p *PKI) GetRootFingerprint() string {
return p.Defaults.Fingerprint return p.Defaults.Fingerprint
} }
// SetProvisioner sets the provisioner name of the OTT keys.
//
// Deprecated: this method is deprecated in favor of WithProvisioner.
func (p *PKI) SetProvisioner(s string) {
p.options.provisioner = s
}
// SetAddress sets the listening address of the CA.
//
// Deprecated: this method is deprecated in favor of WithAddress.
func (p *PKI) SetAddress(s string) {
p.Address = s
}
// SetDNSNames sets the dns names of the CA.
//
// Deprecated: this method is deprecated in favor of WithDNSNames.
func (p *PKI) SetDNSNames(s []string) {
p.DnsNames = s
}
// SetCAURL sets the ca-url to use in the defaults.json.
//
// Deprecated: this method is deprecated in favor of WithCaUrl.
func (p *PKI) SetCAURL(s string) {
p.Defaults.CaUrl = s
}
// GenerateKeyPairs generates the key pairs used by the certificate authority. // GenerateKeyPairs generates the key pairs used by the certificate authority.
func (p *PKI) GenerateKeyPairs(pass []byte) error { func (p *PKI) GenerateKeyPairs(pass []byte) error {
var err error var err error
@ -450,22 +422,29 @@ func (p *PKI) GenerateRootCertificate(name, org, resource string, pass []byte) (
return nil, err return nil, err
} }
sum := sha256.Sum256(resp.Certificate.Raw) // PrivateKey will only be set if we have access to it (SoftCAS).
p.Defaults.Fingerprint = strings.ToLower(hex.EncodeToString(sum[:])) if err := p.WriteRootCertificate(resp.Certificate, resp.PrivateKey, pass); err != nil {
p.Files[p.Root[0]] = encodeCertificate(resp.Certificate)
p.Files[p.RootKey[0]], err = encodePrivateKey(resp.PrivateKey, pass)
if err != nil {
return nil, err return nil, err
} }
// PrivateKey will only be set if we have access to it (SoftCAS).
// if err := p.WriteRootCertificate(resp.Certificate, resp.PrivateKey, pass); err != nil {
// return nil, err
// }
return resp, nil return resp, nil
} }
// WriteRootCertificate writes to the buffer the given certificate and key if given.
func (p *PKI) WriteRootCertificate(rootCrt *x509.Certificate, rootKey interface{}, pass []byte) error {
p.Files[p.Root[0]] = encodeCertificate(rootCrt)
if rootKey != nil {
var err error
p.Files[p.RootKey[0]], err = encodePrivateKey(rootKey, pass)
if err != nil {
return err
}
}
sum := sha256.Sum256(rootCrt.Raw)
p.Defaults.Fingerprint = strings.ToLower(hex.EncodeToString(sum[:]))
return nil
}
// GenerateIntermediateCertificate generates an intermediate certificate with // GenerateIntermediateCertificate generates an intermediate certificate with
// the given name and using the default key type. // the given name and using the default key type.
func (p *PKI) GenerateIntermediateCertificate(name, org, resource string, parent *apiv1.CreateCertificateAuthorityResponse, pass []byte) error { func (p *PKI) GenerateIntermediateCertificate(name, org, resource string, parent *apiv1.CreateCertificateAuthorityResponse, pass []byte) error {
@ -494,60 +473,7 @@ func (p *PKI) GenerateIntermediateCertificate(name, org, resource string, parent
p.casOptions.CertificateAuthority = resp.Name p.casOptions.CertificateAuthority = resp.Name
p.Files[p.Intermediate] = encodeCertificate(resp.Certificate) p.Files[p.Intermediate] = encodeCertificate(resp.Certificate)
p.Files[p.IntermediateKey], err = encodePrivateKey(resp.PrivateKey, pass) p.Files[p.IntermediateKey], err = encodePrivateKey(resp.PrivateKey, pass)
if err != nil { return err
return err
}
return nil
// return p.WriteIntermediateCertificate(resp.Certificate, resp.PrivateKey, pass)
}
// WriteRootCertificate writes to disk the given certificate and key.
func (p *PKI) WriteRootCertificate(rootCrt *x509.Certificate, rootKey interface{}, pass []byte) error {
fmt.Println(p.options.isHelm)
if p.options.isHelm {
return nil
}
if err := fileutil.WriteFile(p.Root[0], pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Bytes: rootCrt.Raw,
}), 0600); err != nil {
return err
}
if rootKey != nil {
_, err := pemutil.Serialize(rootKey, pemutil.WithPassword(pass), pemutil.ToFile(p.RootKey[0], 0600))
if err != nil {
return err
}
}
sum := sha256.Sum256(rootCrt.Raw)
p.Defaults.Fingerprint = strings.ToLower(hex.EncodeToString(sum[:]))
return nil
}
// WriteIntermediateCertificate writes to disk the given certificate and key.
func (p *PKI) WriteIntermediateCertificate(crt *x509.Certificate, key interface{}, pass []byte) error {
if p.options.isHelm {
return nil
}
if err := fileutil.WriteFile(p.Intermediate, pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Bytes: crt.Raw,
}), 0600); err != nil {
return err
}
if key != nil {
_, err := pemutil.Serialize(key, pemutil.WithPassword(pass), pemutil.ToFile(p.IntermediateKey, 0600))
if err != nil {
return err
}
}
return nil
} }
// CreateCertificateAuthorityResponse returns a // CreateCertificateAuthorityResponse returns a
@ -610,19 +536,21 @@ func (p *PKI) GenerateSSHSigningKeys(password []byte) error {
if err != nil { if err != nil {
return err return err
} }
// _, err = pemutil.Serialize(priv, pemutil.WithFilename(privNames[i]), pemutil.WithPassword(password))
// if err != nil {
// return err
// }
// if err = fileutil.WriteFile(pubNames[i], ssh.MarshalAuthorizedKey(sshKey), 0600); err != nil {
// return err
// }
} }
p.options.enableSSH = true p.options.enableSSH = true
return nil return nil
} }
// WriteFiles writes on disk the previously generated files.
func (p *PKI) WriteFiles() error {
for fn, b := range p.Files {
if err := fileutil.WriteFile(fn, b, 0600); err != nil {
return err
}
}
return nil
}
func (p *PKI) askFeedback() { func (p *PKI) askFeedback() {
ui.Println() ui.Println()
ui.Printf("\033[1mFEEDBACK\033[0m %s %s\n", ui.Printf("\033[1mFEEDBACK\033[0m %s %s\n",
@ -636,14 +564,6 @@ func (p *PKI) askFeedback() {
ui.Println(" \033[1mhttps://bit.ly/step-discord\033[0m.") ui.Println(" \033[1mhttps://bit.ly/step-discord\033[0m.")
} }
// TellPKI outputs the locations of public and private keys generated
// generated for a new PKI. Generally this will consist of a root certificate
// and key and an intermediate certificate and key.
func (p *PKI) TellPKI() {
p.tellPKI()
p.askFeedback()
}
func (p *PKI) tellPKI() { func (p *PKI) tellPKI() {
ui.Println() ui.Println()
if p.casOptions.Is(apiv1.SoftCAS) { if p.casOptions.Is(apiv1.SoftCAS) {
@ -832,67 +752,67 @@ func (p *PKI) GenerateConfig(opt ...Option) (*authconfig.Config, error) {
// Save stores the pki on a json file that will be used as the certificate // Save stores the pki on a json file that will be used as the certificate
// authority configuration. // authority configuration.
func (p *PKI) Save(opt ...Option) error { func (p *PKI) Save(opt ...Option) error {
// Write pre-generated files. // Write generated files
for fn, b := range p.Files { if err := p.WriteFiles(); err != nil {
if err := fileutil.WriteFile(fn, b, 0600); err != nil { return err
return err
}
} }
// Display only the
p.tellPKI() p.tellPKI()
// Generate and write ca.json // Generate and write ca.json
config, err := p.GenerateConfig(opt...) if !p.options.pkiOnly {
if err != nil { config, err := p.GenerateConfig(opt...)
return err if err != nil {
} return err
}
b, err := json.MarshalIndent(config, "", "\t") b, err := json.MarshalIndent(config, "", "\t")
if err != nil { if err != nil {
return errors.Wrapf(err, "error marshaling %s", p.config) return errors.Wrapf(err, "error marshaling %s", p.config)
} }
if err = fileutil.WriteFile(p.config, b, 0644); err != nil { if err = fileutil.WriteFile(p.config, b, 0644); err != nil {
return errs.FileError(err, p.config) return errs.FileError(err, p.config)
} }
// Generate and write defaults.json // Generate and write defaults.json
defaults := &caDefaults{ defaults := &caDefaults{
Root: p.Defaults.Root, Root: p.Defaults.Root,
CAConfig: p.Defaults.CaConfig, CAConfig: p.Defaults.CaConfig,
CAUrl: p.Defaults.CaUrl, CAUrl: p.Defaults.CaUrl,
Fingerprint: p.Defaults.Fingerprint, Fingerprint: p.Defaults.Fingerprint,
} }
b, err = json.MarshalIndent(defaults, "", "\t") b, err = json.MarshalIndent(defaults, "", "\t")
if err != nil { if err != nil {
return errors.Wrapf(err, "error marshaling %s", p.defaults) return errors.Wrapf(err, "error marshaling %s", p.defaults)
} }
if err = fileutil.WriteFile(p.defaults, b, 0644); err != nil { if err = fileutil.WriteFile(p.defaults, b, 0644); err != nil {
return errs.FileError(err, p.defaults) return errs.FileError(err, p.defaults)
} }
// Generate and write templates // Generate and write templates
if err := generateTemplates(config.Templates); err != nil { if err := generateTemplates(config.Templates); err != nil {
return err return err
} }
if config.DB != nil { if config.DB != nil {
ui.PrintSelected("Database folder", config.DB.DataSource) ui.PrintSelected("Database folder", config.DB.DataSource)
} }
if config.Templates != nil { if config.Templates != nil {
ui.PrintSelected("Templates folder", GetTemplatesPath()) ui.PrintSelected("Templates folder", GetTemplatesPath())
} }
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.casOptions.Is(apiv1.SoftCAS) { if p.casOptions.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 { } else {
ui.Println("Your registration authority is ready to go. To generate certificates for individual services see 'step help ca'.") ui.Println("Your registration authority is ready to go. To generate certificates for individual services see 'step help ca'.")
}
} }
p.askFeedback() p.askFeedback()
return nil return nil
} }