mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-16 21:56:40 -05:00
pki: Add trust subcommand to install root cert (closes #3204)
This commit is contained in:
parent
904d9cab39
commit
244b839f98
5 changed files with 73 additions and 20 deletions
2
caddy.go
2
caddy.go
|
@ -372,7 +372,7 @@ func run(newCfg *Config, start bool) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if newCfg.storage == nil {
|
if newCfg.storage == nil {
|
||||||
newCfg.storage = &certmagic.FileStorage{Path: AppDataDir()}
|
newCfg.storage = DefaultStorage
|
||||||
}
|
}
|
||||||
certmagic.Default.Storage = newCfg.storage
|
certmagic.Default.Storage = newCfg.storage
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ import (
|
||||||
|
|
||||||
"github.com/caddyserver/caddy/v2"
|
"github.com/caddyserver/caddy/v2"
|
||||||
"github.com/caddyserver/certmagic"
|
"github.com/caddyserver/certmagic"
|
||||||
|
"github.com/smallstep/truststore"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -323,6 +324,27 @@ func (ca CA) newReplacer() *caddy.Replacer {
|
||||||
return repl
|
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 (
|
const (
|
||||||
defaultCAID = "local"
|
defaultCAID = "local"
|
||||||
defaultCAName = "Caddy Local Authority"
|
defaultCAName = "Caddy Local Authority"
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
package caddypki
|
package caddypki
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
@ -26,6 +27,25 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
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{
|
caddycmd.RegisterCommand(caddycmd.Command{
|
||||||
Name: "untrust",
|
Name: "untrust",
|
||||||
Func: cmdUntrust,
|
Func: cmdUntrust,
|
||||||
|
@ -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) {
|
func cmdUntrust(fs caddycmd.Flags) (int, error) {
|
||||||
ca := fs.String("ca")
|
ca := fs.String("ca")
|
||||||
cert := fs.String("cert")
|
cert := fs.String("cert")
|
||||||
|
|
|
@ -18,7 +18,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/caddyserver/caddy/v2"
|
"github.com/caddyserver/caddy/v2"
|
||||||
"github.com/smallstep/truststore"
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -71,30 +70,15 @@ func (p *PKI) Start() error {
|
||||||
// install roots to trust store, if not disabled
|
// install roots to trust store, if not disabled
|
||||||
for _, ca := range p.CAs {
|
for _, ca := range p.CAs {
|
||||||
if ca.InstallTrust != nil && !*ca.InstallTrust {
|
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))
|
zap.String("path", ca.rootCertPath))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// avoid password prompt if already trusted
|
if err := ca.installRoot(); err != nil {
|
||||||
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 {
|
|
||||||
// could be some system dependencies that are missing;
|
// could be some system dependencies that are missing;
|
||||||
// shouldn't totally prevent startup, but we should log it
|
// 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.Error(err),
|
||||||
zap.String("certificate_file", ca.rootCertPath))
|
zap.String("certificate_file", ca.rootCertPath))
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,3 +155,6 @@ func AppDataDir() string {
|
||||||
|
|
||||||
// ConfigAutosavePath is the default path to which the last config will be persisted.
|
// ConfigAutosavePath is the default path to which the last config will be persisted.
|
||||||
var ConfigAutosavePath = filepath.Join(AppConfigDir(), "autosave.json")
|
var ConfigAutosavePath = filepath.Join(AppConfigDir(), "autosave.json")
|
||||||
|
|
||||||
|
// DefaultStorage is Caddy's default storage module.
|
||||||
|
var DefaultStorage = &certmagic.FileStorage{Path: AppDataDir()}
|
||||||
|
|
Loading…
Reference in a new issue