Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 14, 05:15 UTC
pki: Add trust subcommand to install root cert (closes #3204)
Matthew Holt committed
Mar 31, 2020 at 17:56 UTC
244b839f9813ae68c5527e6aadadaff0642c1a00
5 files changed
+73
-20
caddy.go
+1
-1
@@ -372,7 +372,7 @@ func run(newCfg *Config, start bool) error {
372
}
373
374
if newCfg.storage == nil {
375
- newCfg.storage = &certmagic.FileStorage{Path: AppDataDir()}
375
+ newCfg.storage = DefaultStorage
376
}
377
certmagic.Default.Storage = newCfg.storage
378
modules/caddypki/ca.go
+22
@@ -24,6 +24,7 @@ import (
24
25
"github.com/caddyserver/caddy/v2"
26
"github.com/caddyserver/certmagic"
27
+ "github.com/smallstep/truststore"
28
"go.uber.org/zap"
29
)
30
@@ -323,6 +324,27 @@ func (ca CA) newReplacer() *caddy.Replacer {
324
return repl
325
}
326
327
+// installRoot installs this CA's root certificate into the
328
+// local trust store(s) if it is not already trusted. The CA
329
+// must already be provisioned.
330
+func (ca CA) installRoot() error {
331
+ // avoid password prompt if already trusted
332
+ if trusted(ca.root) {
333
+ ca.log.Info("root certificate is already trusted by system",
334
+ zap.String("path", ca.rootCertPath))
335
+ return nil
336
+ }
337
+
338
+ ca.log.Warn("installing root certificate (you might be prompted for password)",
339
+ zap.String("path", ca.rootCertPath))
340
+
341
+ return truststore.Install(ca.root,
342
+ truststore.WithDebug(),
343
+ truststore.WithFirefox(),
344
+ truststore.WithJava(),
345
+ )
346
+}
347
+
348
const (
349
defaultCAID = "local"
350
defaultCAName = "Caddy Local Authority"
modules/caddypki/command.go
+44
@@ -15,6 +15,7 @@
15
package caddypki
16
17
import (
18
+ "context"
19
"flag"
20
"fmt"
21
"os"
@@ -26,6 +27,25 @@ import (
27
)
28
29
func init() {
30
+ caddycmd.RegisterCommand(caddycmd.Command{
31
+ Name: "trust",
32
+ Func: cmdTrust,
33
+ Short: "Installs a CA certificate into local trust stores",
34
+ Long: `
35
+Adds a root certificate into the local trust stores. Intended for
36
+development environments only.
37
+
38
+Since Caddy will install its root certificates into the local trust
39
+stores automatically when they are first generated, this command is
40
+only necessary if you need to pre-install the certificates before
41
+using them; for example, if you have elevated privileges at one
42
+point but not later, you will want to use this command so that a
43
+password prompt is not required later.
44
+
45
+This command installs the root certificate only for Caddy's
46
+default CA.`,
47
+ })
48
+
49
caddycmd.RegisterCommand(caddycmd.Command{
50
Name: "untrust",
51
Func: cmdUntrust,
@@ -57,6 +77,30 @@ If no flags are specified, --ca=local is assumed.`,
77
})
78
}
79
80
+func cmdTrust(fs caddycmd.Flags) (int, error) {
81
+ // we have to create a sort of dummy context so that
82
+ // the CA can provision itself...
83
+ ctx, cancel := caddy.NewContext(caddy.Context{Context: context.Background()})
84
+ defer cancel()
85
+
86
+ // provision the CA, which generates and stores a root
87
+ // certificate if one doesn't already exist in storage
88
+ ca := CA{
89
+ storage: caddy.DefaultStorage,
90
+ }
91
+ err := ca.Provision(ctx, defaultCAID, caddy.Log())
92
+ if err != nil {
93
+ return caddy.ExitCodeFailedStartup, err
94
+ }
95
+
96
+ err = ca.installRoot()
97
+ if err != nil {
98
+ return caddy.ExitCodeFailedStartup, err
99
+ }
100
+
101
+ return caddy.ExitCodeSuccess, nil
102
+}
103
+
104
func cmdUntrust(fs caddycmd.Flags) (int, error) {
105
ca := fs.String("ca")
106
cert := fs.String("cert")
modules/caddypki/pki.go
+3
-19
@@ -18,7 +18,6 @@ import (
18
"fmt"
19
20
"github.com/caddyserver/caddy/v2"
21
- "github.com/smallstep/truststore"
21
"go.uber.org/zap"
22
)
23
@@ -71,30 +70,15 @@ func (p *PKI) Start() error {
70
// install roots to trust store, if not disabled
71
for _, ca := range p.CAs {
72
if ca.InstallTrust != nil && !*ca.InstallTrust {
74
- ca.log.Warn("root certificate trust store installation disabled; local clients may show warnings",
73
+ ca.log.Warn("root certificate trust store installation disabled; unconfigured clients may show warnings",
74
zap.String("path", ca.rootCertPath))
75
continue
76
}
77
79
- // avoid password prompt if already trusted
80
- if trusted(ca.root) {
81
- ca.log.Info("root certificate is already trusted by system",
82
- zap.String("path", ca.rootCertPath))
83
- continue
84
- }
85
-
86
- ca.log.Warn("trusting root certificate (you might be prompted for password)",
87
- zap.String("path", ca.rootCertPath))
88
-
89
- err := truststore.Install(ca.root,
90
- truststore.WithDebug(),
91
- truststore.WithFirefox(),
92
- truststore.WithJava(),
93
- )
94
- if err != nil {
78
+ if err := ca.installRoot(); err != nil {
79
// could be some system dependencies that are missing;
80
// shouldn't totally prevent startup, but we should log it
97
- p.log.Error("failed to install root certificate",
81
+ ca.log.Error("failed to install root certificate",
82
zap.Error(err),
83
zap.String("certificate_file", ca.rootCertPath))
84
}
storage.go
+3
@@ -155,3 +155,6 @@ func AppDataDir() string {
155
156
// ConfigAutosavePath is the default path to which the last config will be persisted.
157
var ConfigAutosavePath = filepath.Join(AppConfigDir(), "autosave.json")
158
+
159
+// DefaultStorage is Caddy's default storage module.
160
+var DefaultStorage = &certmagic.FileStorage{Path: AppDataDir()}