forked from TrueCloudLab/certificates
Make pki initialization more flexible.
This commit is contained in:
parent
384be6e205
commit
721459210e
2 changed files with 243 additions and 66 deletions
307
pki/pki.go
307
pki/pki.go
|
@ -19,12 +19,16 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"github.com/smallstep/certificates/authority"
|
||||||
|
"github.com/smallstep/certificates/authority/admin"
|
||||||
|
admindb "github.com/smallstep/certificates/authority/admin/db/nosql"
|
||||||
authconfig "github.com/smallstep/certificates/authority/config"
|
authconfig "github.com/smallstep/certificates/authority/config"
|
||||||
"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"
|
||||||
"github.com/smallstep/certificates/cas/apiv1"
|
"github.com/smallstep/certificates/cas/apiv1"
|
||||||
"github.com/smallstep/certificates/db"
|
"github.com/smallstep/certificates/db"
|
||||||
|
"github.com/smallstep/nosql"
|
||||||
"go.step.sm/cli-utils/config"
|
"go.step.sm/cli-utils/config"
|
||||||
"go.step.sm/cli-utils/errs"
|
"go.step.sm/cli-utils/errs"
|
||||||
"go.step.sm/cli-utils/fileutil"
|
"go.step.sm/cli-utils/fileutil"
|
||||||
|
@ -32,9 +36,26 @@ import (
|
||||||
"go.step.sm/crypto/jose"
|
"go.step.sm/crypto/jose"
|
||||||
"go.step.sm/crypto/keyutil"
|
"go.step.sm/crypto/keyutil"
|
||||||
"go.step.sm/crypto/pemutil"
|
"go.step.sm/crypto/pemutil"
|
||||||
|
"go.step.sm/linkedca"
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DeploymentType defines witch type of deployment a user is initializing
|
||||||
|
type DeploymentType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// StandaloneDeployment is a deployment where all the components like keys,
|
||||||
|
// provisioners, admins, certificates and others are managed by the user.
|
||||||
|
StandaloneDeployment DeploymentType = iota
|
||||||
|
// LinkedDeployment is a deployment where the keys are managed by the user,
|
||||||
|
// but provisioners, admins and the record of certificates are managed in
|
||||||
|
// the cloud.
|
||||||
|
LinkedDeployment
|
||||||
|
// HostedDeployment is a deployment where all the components are managed in
|
||||||
|
// the cloud by smallstep.com/certificate-manager.
|
||||||
|
HostedDeployment
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// ConfigPath is the directory name under the step path where the configuration
|
// ConfigPath is the directory name under the step path where the configuration
|
||||||
// files will be stored.
|
// files will be stored.
|
||||||
|
@ -134,9 +155,88 @@ func GetProvisionerKey(caURL, rootFile, kid string) (string, error) {
|
||||||
return resp.Key, nil
|
return resp.Key, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type options struct {
|
||||||
|
address string
|
||||||
|
caURL string
|
||||||
|
dnsNames []string
|
||||||
|
provisioner string
|
||||||
|
enableACME bool
|
||||||
|
enableSSH bool
|
||||||
|
enableAdmin bool
|
||||||
|
noDB bool
|
||||||
|
deploymentType DeploymentType
|
||||||
|
}
|
||||||
|
|
||||||
|
// PKIOption is the type of a configuration option on the pki constructor.
|
||||||
|
type PKIOption func(o *options)
|
||||||
|
|
||||||
|
// WithAddress sets the listen address of step-ca.
|
||||||
|
func WithAddress(s string) PKIOption {
|
||||||
|
return func(o *options) {
|
||||||
|
o.address = s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithCaUrl sets the default ca-url of step-ca.
|
||||||
|
func WithCaUrl(s string) PKIOption {
|
||||||
|
return func(o *options) {
|
||||||
|
o.caURL = s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithDNSNames sets the SANs of step-ca.
|
||||||
|
func WithDNSNames(s []string) PKIOption {
|
||||||
|
return func(o *options) {
|
||||||
|
o.dnsNames = s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithProvisioner defines the name of the default provisioner.
|
||||||
|
func WithProvisioner(s string) PKIOption {
|
||||||
|
return func(o *options) {
|
||||||
|
o.provisioner = s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithACME enables acme provisioner in step-ca.
|
||||||
|
func WithACME() PKIOption {
|
||||||
|
return func(o *options) {
|
||||||
|
o.enableACME = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithSSH enables ssh in step-ca.
|
||||||
|
func WithSSH() PKIOption {
|
||||||
|
return func(o *options) {
|
||||||
|
o.enableSSH = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithAdmin enables the admin api in step-ca.
|
||||||
|
func WithAdmin() PKIOption {
|
||||||
|
return func(o *options) {
|
||||||
|
o.enableAdmin = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithNoDB disables the db in step-ca.
|
||||||
|
func WithNoDB() PKIOption {
|
||||||
|
return func(o *options) {
|
||||||
|
o.noDB = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithDeploymentType defines the deployment type of step-ca.
|
||||||
|
func WithDeploymentType(dt DeploymentType) PKIOption {
|
||||||
|
return func(o *options) {
|
||||||
|
o.deploymentType = dt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 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 {
|
||||||
casOptions apiv1.Options
|
casOptions apiv1.Options
|
||||||
|
caService apiv1.CertificateAuthorityService
|
||||||
caCreator apiv1.CertificateAuthorityCreator
|
caCreator apiv1.CertificateAuthorityCreator
|
||||||
root, rootKey, rootFingerprint string
|
root, rootKey, rootFingerprint string
|
||||||
intermediate, intermediateKey string
|
intermediate, intermediateKey string
|
||||||
|
@ -145,20 +245,25 @@ type PKI struct {
|
||||||
config, defaults string
|
config, defaults string
|
||||||
ottPublicKey *jose.JSONWebKey
|
ottPublicKey *jose.JSONWebKey
|
||||||
ottPrivateKey *jose.JSONWebEncryption
|
ottPrivateKey *jose.JSONWebEncryption
|
||||||
provisioner string
|
options *options
|
||||||
address string
|
|
||||||
dnsNames []string
|
|
||||||
caURL string
|
|
||||||
enableSSH bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new PKI configuration.
|
// New creates a new PKI configuration.
|
||||||
func New(opts apiv1.Options) (*PKI, error) {
|
func New(o apiv1.Options, opts ...PKIOption) (*PKI, error) {
|
||||||
caCreator, err := cas.NewCreator(context.Background(), opts)
|
caService, err := cas.New(context.Background(), o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var caCreator apiv1.CertificateAuthorityCreator
|
||||||
|
if o.IsCreator {
|
||||||
|
creator, ok := caService.(apiv1.CertificateAuthorityCreator)
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.Errorf("cas type '%s' does not implements CertificateAuthorityCreator", o.Type)
|
||||||
|
}
|
||||||
|
caCreator = creator
|
||||||
|
}
|
||||||
|
|
||||||
public := GetPublicPath()
|
public := GetPublicPath()
|
||||||
private := GetSecretsPath()
|
private := GetSecretsPath()
|
||||||
config := GetConfigPath()
|
config := GetConfigPath()
|
||||||
|
@ -180,12 +285,19 @@ func New(opts apiv1.Options) (*PKI, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
p := &PKI{
|
p := &PKI{
|
||||||
casOptions: opts,
|
casOptions: o,
|
||||||
caCreator: caCreator,
|
caCreator: caCreator,
|
||||||
provisioner: "step-cli",
|
caService: caService,
|
||||||
address: "127.0.0.1:9000",
|
options: &options{
|
||||||
dnsNames: []string{"127.0.0.1"},
|
provisioner: "step-cli",
|
||||||
|
address: "127.0.0.1:9000",
|
||||||
|
dnsNames: []string{"127.0.0.1"},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
for _, fn := range opts {
|
||||||
|
fn(p.options)
|
||||||
|
}
|
||||||
|
|
||||||
if p.root, err = getPath(public, "root_ca.crt"); err != nil {
|
if p.root, err = getPath(public, "root_ca.crt"); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -233,23 +345,31 @@ func (p *PKI) GetRootFingerprint() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetProvisioner sets the provisioner name of the OTT keys.
|
// SetProvisioner sets the provisioner name of the OTT keys.
|
||||||
|
//
|
||||||
|
// Deprecated: this method is deprecated in favor of WithProvisioner.
|
||||||
func (p *PKI) SetProvisioner(s string) {
|
func (p *PKI) SetProvisioner(s string) {
|
||||||
p.provisioner = s
|
p.options.provisioner = s
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetAddress sets the listening address of the CA.
|
// SetAddress sets the listening address of the CA.
|
||||||
|
//
|
||||||
|
// Deprecated: this method is deprecated in favor of WithAddress.
|
||||||
func (p *PKI) SetAddress(s string) {
|
func (p *PKI) SetAddress(s string) {
|
||||||
p.address = s
|
p.options.address = s
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDNSNames sets the dns names of the CA.
|
// SetDNSNames sets the dns names of the CA.
|
||||||
|
//
|
||||||
|
// Deprecated: this method is deprecated in favor of WithDNSNames.
|
||||||
func (p *PKI) SetDNSNames(s []string) {
|
func (p *PKI) SetDNSNames(s []string) {
|
||||||
p.dnsNames = s
|
p.options.dnsNames = s
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetCAURL sets the ca-url to use in the defaults.json.
|
// 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) {
|
func (p *PKI) SetCAURL(s string) {
|
||||||
p.caURL = s
|
p.options.caURL = s
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateKeyPairs generates the key pairs used by the certificate authority.
|
// GenerateKeyPairs generates the key pairs used by the certificate authority.
|
||||||
|
@ -379,7 +499,7 @@ func (p *PKI) CreateCertificateAuthorityResponse(cert *x509.Certificate, key cry
|
||||||
// GetCertificateAuthority attempts to load the certificate authority from the
|
// GetCertificateAuthority attempts to load the certificate authority from the
|
||||||
// RA.
|
// RA.
|
||||||
func (p *PKI) GetCertificateAuthority() error {
|
func (p *PKI) GetCertificateAuthority() error {
|
||||||
srv, ok := p.caCreator.(apiv1.CertificateAuthorityGetter)
|
srv, ok := p.caService.(apiv1.CertificateAuthorityGetter)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -427,7 +547,7 @@ func (p *PKI) GenerateSSHSigningKeys(password []byte) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.enableSSH = true
|
p.options.enableSSH = true
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -440,7 +560,8 @@ func (p *PKI) askFeedback() {
|
||||||
ui.Println(" phone home. But your feedback is extremely valuable. Any information you")
|
ui.Println(" phone home. But your feedback is extremely valuable. Any information you")
|
||||||
ui.Println(" can provide regarding how you’re using `step` helps. Please send us a")
|
ui.Println(" can provide regarding how you’re using `step` helps. Please send us a")
|
||||||
ui.Println(" sentence or two, good or bad: \033[1mfeedback@smallstep.com\033[0m or join")
|
ui.Println(" sentence or two, good or bad: \033[1mfeedback@smallstep.com\033[0m or join")
|
||||||
ui.Println(" \033[1mhttps://github.com/smallstep/certificates/discussions\033[0m.")
|
ui.Println(" \033[1mhttps://github.com/smallstep/certificates/discussions\033[0m and our Discord")
|
||||||
|
ui.Println(" \033[1mhttps://bit.ly/step-discord\033[0m.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// TellPKI outputs the locations of public and private keys generated
|
// TellPKI outputs the locations of public and private keys generated
|
||||||
|
@ -465,7 +586,7 @@ func (p *PKI) tellPKI() {
|
||||||
} else {
|
} else {
|
||||||
ui.Printf(`{{ "%s" | red }} {{ "Root certificate:" | bold }} failed to retrieve it from RA`+"\n", ui.IconBad)
|
ui.Printf(`{{ "%s" | red }} {{ "Root certificate:" | bold }} failed to retrieve it from RA`+"\n", ui.IconBad)
|
||||||
}
|
}
|
||||||
if p.enableSSH {
|
if p.options.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)
|
||||||
ui.PrintSelected("SSH host root certificate", p.sshHostPubKey)
|
ui.PrintSelected("SSH host root certificate", p.sshHostPubKey)
|
||||||
|
@ -485,6 +606,8 @@ type Option func(c *authconfig.Config) error
|
||||||
|
|
||||||
// WithDefaultDB is a configuration modifier that adds a default DB stanza to
|
// WithDefaultDB is a configuration modifier that adds a default DB stanza to
|
||||||
// the authority config.
|
// the authority config.
|
||||||
|
//
|
||||||
|
// Deprecated: this method is deprecated because this is the default behavior.
|
||||||
func WithDefaultDB() Option {
|
func WithDefaultDB() Option {
|
||||||
return func(c *authconfig.Config) error {
|
return func(c *authconfig.Config) error {
|
||||||
c.DB = &db.Config{
|
c.DB = &db.Config{
|
||||||
|
@ -497,6 +620,8 @@ func WithDefaultDB() Option {
|
||||||
|
|
||||||
// WithoutDB is a configuration modifier that adds a default DB stanza to
|
// WithoutDB is a configuration modifier that adds a default DB stanza to
|
||||||
// the authority config.
|
// the authority config.
|
||||||
|
//
|
||||||
|
// De[recated: this method is deprecated in favor or WithNoDB.
|
||||||
func WithoutDB() Option {
|
func WithoutDB() Option {
|
||||||
return func(c *authconfig.Config) error {
|
return func(c *authconfig.Config) error {
|
||||||
c.DB = nil
|
c.DB = nil
|
||||||
|
@ -506,18 +631,6 @@ func WithoutDB() Option {
|
||||||
|
|
||||||
// GenerateConfig returns the step certificates configuration.
|
// GenerateConfig returns the step certificates configuration.
|
||||||
func (p *PKI) GenerateConfig(opt ...Option) (*authconfig.Config, error) {
|
func (p *PKI) GenerateConfig(opt ...Option) (*authconfig.Config, error) {
|
||||||
key, err := p.ottPrivateKey.CompactSerialize()
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "error serializing private key")
|
|
||||||
}
|
|
||||||
|
|
||||||
prov := &provisioner.JWK{
|
|
||||||
Name: p.provisioner,
|
|
||||||
Type: "JWK",
|
|
||||||
Key: p.ottPublicKey,
|
|
||||||
EncryptedKey: key,
|
|
||||||
}
|
|
||||||
|
|
||||||
var authorityOptions *apiv1.Options
|
var authorityOptions *apiv1.Options
|
||||||
if !p.casOptions.Is(apiv1.SoftCAS) {
|
if !p.casOptions.Is(apiv1.SoftCAS) {
|
||||||
authorityOptions = &p.casOptions
|
authorityOptions = &p.casOptions
|
||||||
|
@ -528,8 +641,8 @@ func (p *PKI) GenerateConfig(opt ...Option) (*authconfig.Config, error) {
|
||||||
FederatedRoots: []string{},
|
FederatedRoots: []string{},
|
||||||
IntermediateCert: p.intermediate,
|
IntermediateCert: p.intermediate,
|
||||||
IntermediateKey: p.intermediateKey,
|
IntermediateKey: p.intermediateKey,
|
||||||
Address: p.address,
|
Address: p.options.address,
|
||||||
DNSNames: p.dnsNames,
|
DNSNames: p.options.dnsNames,
|
||||||
Logger: []byte(`{"format": "text"}`),
|
Logger: []byte(`{"format": "text"}`),
|
||||||
DB: &db.Config{
|
DB: &db.Config{
|
||||||
Type: "badger",
|
Type: "badger",
|
||||||
|
@ -538,44 +651,109 @@ func (p *PKI) GenerateConfig(opt ...Option) (*authconfig.Config, error) {
|
||||||
AuthorityConfig: &authconfig.AuthConfig{
|
AuthorityConfig: &authconfig.AuthConfig{
|
||||||
Options: authorityOptions,
|
Options: authorityOptions,
|
||||||
DisableIssuedAtCheck: false,
|
DisableIssuedAtCheck: false,
|
||||||
Provisioners: provisioner.List{prov},
|
EnableAdmin: false,
|
||||||
},
|
|
||||||
TLS: &authconfig.TLSOptions{
|
|
||||||
MinVersion: authconfig.DefaultTLSMinVersion,
|
|
||||||
MaxVersion: authconfig.DefaultTLSMaxVersion,
|
|
||||||
Renegotiation: authconfig.DefaultTLSRenegotiation,
|
|
||||||
CipherSuites: authconfig.DefaultTLSCipherSuites,
|
|
||||||
},
|
},
|
||||||
|
TLS: &authconfig.DefaultTLSOptions,
|
||||||
Templates: p.getTemplates(),
|
Templates: p.getTemplates(),
|
||||||
}
|
}
|
||||||
if p.enableSSH {
|
|
||||||
enableSSHCA := true
|
// On standalone deployments add the provisioners to either the ca.json or
|
||||||
config.SSH = &authconfig.SSHConfig{
|
// the database.
|
||||||
HostKey: p.sshHostKey,
|
var provisioners []provisioner.Interface
|
||||||
UserKey: p.sshUserKey,
|
if p.options.deploymentType == StandaloneDeployment {
|
||||||
|
key, err := p.ottPrivateKey.CompactSerialize()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "error serializing private key")
|
||||||
}
|
}
|
||||||
// Enable SSH authorization for default JWK provisioner
|
|
||||||
prov.Claims = &provisioner.Claims{
|
prov := &provisioner.JWK{
|
||||||
EnableSSHCA: &enableSSHCA,
|
Name: p.options.provisioner,
|
||||||
|
Type: "JWK",
|
||||||
|
Key: p.ottPublicKey,
|
||||||
|
EncryptedKey: key,
|
||||||
}
|
}
|
||||||
// Add default SSHPOP provisioner
|
provisioners = append(provisioners, prov)
|
||||||
sshpop := &provisioner.SSHPOP{
|
|
||||||
Type: "SSHPOP",
|
// Add default ACME provisioner if enabled
|
||||||
Name: "sshpop",
|
if p.options.enableACME {
|
||||||
Claims: &provisioner.Claims{
|
provisioners = append(provisioners, &provisioner.ACME{
|
||||||
|
Type: "ACME",
|
||||||
|
Name: "acme",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.options.enableSSH {
|
||||||
|
enableSSHCA := true
|
||||||
|
config.SSH = &authconfig.SSHConfig{
|
||||||
|
HostKey: p.sshHostKey,
|
||||||
|
UserKey: p.sshUserKey,
|
||||||
|
}
|
||||||
|
// Enable SSH authorization for default JWK provisioner
|
||||||
|
prov.Claims = &provisioner.Claims{
|
||||||
EnableSSHCA: &enableSSHCA,
|
EnableSSHCA: &enableSSHCA,
|
||||||
},
|
}
|
||||||
|
|
||||||
|
// Add default SSHPOP provisioner
|
||||||
|
provisioners = append(provisioners, &provisioner.SSHPOP{
|
||||||
|
Type: "SSHPOP",
|
||||||
|
Name: "sshpop",
|
||||||
|
Claims: &provisioner.Claims{
|
||||||
|
EnableSSHCA: &enableSSHCA,
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
config.AuthorityConfig.Provisioners = append(config.AuthorityConfig.Provisioners, sshpop)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply configuration modifiers
|
// Apply configuration modifiers
|
||||||
for _, o := range opt {
|
for _, o := range opt {
|
||||||
if err = o(config); err != nil {
|
if err := o(config); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set authority.enableAdmin to true
|
||||||
|
if p.options.enableAdmin {
|
||||||
|
config.AuthorityConfig.EnableAdmin = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.options.deploymentType == StandaloneDeployment {
|
||||||
|
if !config.AuthorityConfig.EnableAdmin {
|
||||||
|
config.AuthorityConfig.Provisioners = provisioners
|
||||||
|
} else {
|
||||||
|
db, err := db.New(config.DB)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
adminDB, err := admindb.New(db.(nosql.DB), admin.DefaultAuthorityID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Add all the provisioners to the db.
|
||||||
|
var adminID string
|
||||||
|
for i, p := range provisioners {
|
||||||
|
prov, err := authority.ProvisionerToLinkedca(p)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := adminDB.CreateProvisioner(context.Background(), prov); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if i == 0 {
|
||||||
|
adminID = prov.Id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Add the first provisioner as an admin.
|
||||||
|
if err := adminDB.CreateAdmin(context.Background(), &linkedca.Admin{
|
||||||
|
AuthorityId: admin.DefaultAuthorityID,
|
||||||
|
Subject: "step",
|
||||||
|
Type: linkedca.Admin_SUPER_ADMIN,
|
||||||
|
ProvisionerId: adminID,
|
||||||
|
}); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return config, nil
|
return config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -599,17 +777,16 @@ func (p *PKI) Save(opt ...Option) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate the CA URL.
|
// Generate the CA URL.
|
||||||
if p.caURL == "" {
|
if p.options.caURL == "" {
|
||||||
p.caURL = p.dnsNames[0]
|
p.options.caURL = p.options.dnsNames[0]
|
||||||
var port string
|
_, port, err := net.SplitHostPort(p.options.address)
|
||||||
_, port, err = net.SplitHostPort(p.address)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "error parsing %s", p.address)
|
return errors.Wrapf(err, "error parsing %s", p.options.address)
|
||||||
}
|
}
|
||||||
if port == "443" {
|
if port == "443" {
|
||||||
p.caURL = fmt.Sprintf("https://%s", p.caURL)
|
p.options.caURL = fmt.Sprintf("https://%s", p.options.caURL)
|
||||||
} else {
|
} else {
|
||||||
p.caURL = fmt.Sprintf("https://%s:%s", p.caURL, port)
|
p.options.caURL = fmt.Sprintf("https://%s:%s", p.options.caURL, port)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -617,7 +794,7 @@ func (p *PKI) Save(opt ...Option) error {
|
||||||
defaults := &caDefaults{
|
defaults := &caDefaults{
|
||||||
Root: p.root,
|
Root: p.root,
|
||||||
CAConfig: p.config,
|
CAConfig: p.config,
|
||||||
CAUrl: p.caURL,
|
CAUrl: p.options.caURL,
|
||||||
Fingerprint: p.rootFingerprint,
|
Fingerprint: p.rootFingerprint,
|
||||||
}
|
}
|
||||||
b, err = json.MarshalIndent(defaults, "", "\t")
|
b, err = json.MarshalIndent(defaults, "", "\t")
|
||||||
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
|
|
||||||
// getTemplates returns all the templates enabled
|
// getTemplates returns all the templates enabled
|
||||||
func (p *PKI) getTemplates() *templates.Templates {
|
func (p *PKI) getTemplates() *templates.Templates {
|
||||||
if !p.enableSSH {
|
if !p.options.enableSSH {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return &templates.Templates{
|
return &templates.Templates{
|
||||||
|
|
Loading…
Reference in a new issue