diff --git a/ca/ca.go b/ca/ca.go index 5ba81e9e..b99b02d8 100644 --- a/ca/ca.go +++ b/ca/ca.go @@ -23,9 +23,10 @@ import ( ) type options struct { - configFile string - password []byte - database db.AuthDB + configFile string + password []byte + issuerPassword []byte + database db.AuthDB } func (o *options) apply(opts []Option) { @@ -53,6 +54,14 @@ func WithPassword(password []byte) Option { } } +// WithIssuer sets the given password as the configured certificate issuer +// password in the CA options. +func WithIssuerPassword(password []byte) Option { + return func(o *options) { + o.issuerPassword = password + } +} + // WithDatabase sets the given authority database to the CA options. func WithDatabase(db db.AuthDB) Option { return func(o *options) { @@ -82,10 +91,18 @@ func New(config *authority.Config, opts ...Option) (*CA, error) { // Init initializes the CA with the given configuration. func (ca *CA) Init(config *authority.Config) (*CA, error) { - if l := len(ca.opts.password); l > 0 { + // Intermediate Password. + if len(ca.opts.password) > 0 { ca.config.Password = string(ca.opts.password) } + // Certificate issuer password for RA mode. + if len(ca.opts.issuerPassword) > 0 { + if ca.config.AuthorityConfig != nil && ca.config.AuthorityConfig.CertificateIssuer != nil { + ca.config.AuthorityConfig.CertificateIssuer.Password = string(ca.opts.issuerPassword) + } + } + var opts []authority.Option if ca.opts.database != nil { opts = append(opts, authority.WithDatabase(ca.opts.database)) @@ -213,6 +230,7 @@ func (ca *CA) Reload() error { newCA, err := New(config, WithPassword(ca.opts.password), + WithIssuerPassword(ca.opts.issuerPassword), WithConfigFile(ca.opts.configFile), WithDatabase(ca.auth.GetDatabase()), ) diff --git a/cmd/step-ca/main.go b/cmd/step-ca/main.go index a243022a..eca57e8e 100644 --- a/cmd/step-ca/main.go +++ b/cmd/step-ca/main.go @@ -106,7 +106,7 @@ func main() { app.HelpName = "step-ca" app.Version = config.Version() app.Usage = "an online certificate authority for secure automated certificate management" - app.UsageText = `**step-ca** [**--password-file**=] [**--resolver**=] [**--help**] [**--version**]` + app.UsageText = `**step-ca** [**--password-file**=] [**--issuer-password-file**=] [**--resolver**=] [**--help**] [**--version**]` app.Description = `**step-ca** runs the Step Online Certificate Authority (Step CA) using the given configuration. See the README.md for more detailed configuration documentation. diff --git a/commands/app.go b/commands/app.go index 55e88abe..aff9d473 100644 --- a/commands/app.go +++ b/commands/app.go @@ -22,13 +22,17 @@ var AppCommand = cli.Command{ Name: "start", Action: appAction, UsageText: `**step-ca** - [**--password-file**=] - [**--resolver**=]`, +[**--password-file**=] [**--issuer-password-file**=] [**--resolver**=]`, Flags: []cli.Flag{ cli.StringFlag{ Name: "password-file", Usage: `path to the containing the password to decrypt the intermediate private key.`, + }, + cli.StringFlag{ + Name: "issuer-password-file", + Usage: `path to the containing the password to decrypt the +certificate issuer private key used in the RA mode.`, }, cli.StringFlag{ Name: "resolver", @@ -40,6 +44,7 @@ intermediate private key.`, // AppAction is the action used when the top command runs. func appAction(ctx *cli.Context) error { passFile := ctx.String("password-file") + issuerPassFile := ctx.String("issuer-password-file") resolver := ctx.String("resolver") // If zero cmd line args show help, if >1 cmd line args show error. @@ -64,6 +69,14 @@ func appAction(ctx *cli.Context) error { password = bytes.TrimRightFunc(password, unicode.IsSpace) } + var issuerPassword []byte + if issuerPassFile != "" { + if issuerPassword, err = ioutil.ReadFile(issuerPassFile); err != nil { + fatal(errors.Wrapf(err, "error reading %s", issuerPassFile)) + } + issuerPassword = bytes.TrimRightFunc(issuerPassword, unicode.IsSpace) + } + // replace resolver if requested if resolver != "" { net.DefaultResolver.PreferGo = true @@ -72,7 +85,10 @@ func appAction(ctx *cli.Context) error { } } - srv, err := ca.New(config, ca.WithConfigFile(configFile), ca.WithPassword(password)) + srv, err := ca.New(config, + ca.WithConfigFile(configFile), + ca.WithPassword(password), + ca.WithIssuerPassword(issuerPassword)) if err != nil { fatal(err) }