summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorMatthew Holt <mholt@users.noreply.github.com>2020-03-31 17:56:36 -0600
committerMatthew Holt <mholt@users.noreply.github.com>2020-03-31 17:56:36 -0600
commit244b839f9813ae68c5527e6aadadaff0642c1a00 (patch)
tree66c0df8bbf728eed7c511f1023e84b6d4d34ac31 /modules
parent904d9cab390007610a65f648d05314f5826c3979 (diff)
pki: Add trust subcommand to install root cert (closes #3204)
Diffstat (limited to 'modules')
-rw-r--r--modules/caddypki/ca.go22
-rw-r--r--modules/caddypki/command.go44
-rw-r--r--modules/caddypki/pki.go22
3 files changed, 69 insertions, 19 deletions
diff --git a/modules/caddypki/ca.go b/modules/caddypki/ca.go
index f15883e..21a8bd5 100644
--- a/modules/caddypki/ca.go
+++ b/modules/caddypki/ca.go
@@ -24,6 +24,7 @@ import (
"github.com/caddyserver/caddy/v2"
"github.com/caddyserver/certmagic"
+ "github.com/smallstep/truststore"
"go.uber.org/zap"
)
@@ -323,6 +324,27 @@ func (ca CA) newReplacer() *caddy.Replacer {
return repl
}
+// installRoot installs this CA's root certificate into the
+// local trust store(s) if it is not already trusted. The CA
+// must already be provisioned.
+func (ca CA) installRoot() error {
+ // avoid password prompt if already trusted
+ if trusted(ca.root) {
+ ca.log.Info("root certificate is already trusted by system",
+ zap.String("path", ca.rootCertPath))
+ return nil
+ }
+
+ ca.log.Warn("installing root certificate (you might be prompted for password)",
+ zap.String("path", ca.rootCertPath))
+
+ return truststore.Install(ca.root,
+ truststore.WithDebug(),
+ truststore.WithFirefox(),
+ truststore.WithJava(),
+ )
+}
+
const (
defaultCAID = "local"
defaultCAName = "Caddy Local Authority"
diff --git a/modules/caddypki/command.go b/modules/caddypki/command.go
index 9276fcb..9117f3f 100644
--- a/modules/caddypki/command.go
+++ b/modules/caddypki/command.go
@@ -15,6 +15,7 @@
package caddypki
import (
+ "context"
"flag"
"fmt"
"os"
@@ -27,6 +28,25 @@ import (
func init() {
caddycmd.RegisterCommand(caddycmd.Command{
+ Name: "trust",
+ Func: cmdTrust,
+ Short: "Installs a CA certificate into local trust stores",
+ Long: `
+Adds a root certificate into the local trust stores. Intended for
+development environments only.
+
+Since Caddy will install its root certificates into the local trust
+stores automatically when they are first generated, this command is
+only necessary if you need to pre-install the certificates before
+using them; for example, if you have elevated privileges at one
+point but not later, you will want to use this command so that a
+password prompt is not required later.
+
+This command installs the root certificate only for Caddy's
+default CA.`,
+ })
+
+ caddycmd.RegisterCommand(caddycmd.Command{
Name: "untrust",
Func: cmdUntrust,
Usage: "[--ca <id> | --cert <path>]",
@@ -57,6 +77,30 @@ If no flags are specified, --ca=local is assumed.`,
})
}
+func cmdTrust(fs caddycmd.Flags) (int, error) {
+ // we have to create a sort of dummy context so that
+ // the CA can provision itself...
+ ctx, cancel := caddy.NewContext(caddy.Context{Context: context.Background()})
+ defer cancel()
+
+ // provision the CA, which generates and stores a root
+ // certificate if one doesn't already exist in storage
+ ca := CA{
+ storage: caddy.DefaultStorage,
+ }
+ err := ca.Provision(ctx, defaultCAID, caddy.Log())
+ if err != nil {
+ return caddy.ExitCodeFailedStartup, err
+ }
+
+ err = ca.installRoot()
+ if err != nil {
+ return caddy.ExitCodeFailedStartup, err
+ }
+
+ return caddy.ExitCodeSuccess, nil
+}
+
func cmdUntrust(fs caddycmd.Flags) (int, error) {
ca := fs.String("ca")
cert := fs.String("cert")
diff --git a/modules/caddypki/pki.go b/modules/caddypki/pki.go
index 562fae2..f9aa372 100644
--- a/modules/caddypki/pki.go
+++ b/modules/caddypki/pki.go
@@ -18,7 +18,6 @@ import (
"fmt"
"github.com/caddyserver/caddy/v2"
- "github.com/smallstep/truststore"
"go.uber.org/zap"
)
@@ -71,30 +70,15 @@ func (p *PKI) Start() error {
// install roots to trust store, if not disabled
for _, ca := range p.CAs {
if ca.InstallTrust != nil && !*ca.InstallTrust {
- ca.log.Warn("root certificate trust store installation disabled; local clients may show warnings",
+ ca.log.Warn("root certificate trust store installation disabled; unconfigured clients may show warnings",
zap.String("path", ca.rootCertPath))
continue
}
- // avoid password prompt if already trusted
- if trusted(ca.root) {
- ca.log.Info("root certificate is already trusted by system",
- zap.String("path", ca.rootCertPath))
- continue
- }
-
- ca.log.Warn("trusting root certificate (you might be prompted for password)",
- zap.String("path", ca.rootCertPath))
-
- err := truststore.Install(ca.root,
- truststore.WithDebug(),
- truststore.WithFirefox(),
- truststore.WithJava(),
- )
- if err != nil {
+ if err := ca.installRoot(); err != nil {
// could be some system dependencies that are missing;
// shouldn't totally prevent startup, but we should log it
- p.log.Error("failed to install root certificate",
+ ca.log.Error("failed to install root certificate",
zap.Error(err),
zap.String("certificate_file", ca.rootCertPath))
}