As an Operator, I want to use the ACME protocol, so that I have a standards based way to manage PKI.
SYNOPSIS
Use the ACME protocol to generate TLS PKI.
DESCRIPTION
Below is an example startup configuration for using the ACME protocol in golang
and distributing the key material using file storage. The file storage should be
replaced with a distributed blob storage that is locked down. This also uses
the STEPPATH environment variable to access an internal root certificate
authority.
func WithAcmeTLS(ctx context.Context, directoryURL string, cacheDir string) cfg.Option {
storageFor := func(config *cfg.Config) certmagic.Storage {
return &certmagic.FileStorage{Path: cacheDir}
}
return func(config *cfg.Config) {
host := os.Getenv("HOST")
tls := srv.NewTLS(ctx, host, storageFor(config), []certmagic.ACMEIssuer{
{
Agreed: true,
CA: directoryURL,
DisableHTTPChallenge: true,
Email: "everyone@example.com",
TestCA: directoryURL,
TrustedRoots: newCertPool(),
AltTLSALPNPort: bindingPort(),
},
})
config.TLS = x.Must(tls.Config())
}
}
func newCertPool() *x509.CertPool {
certPool := x.Must(x509.SystemCertPool())
certPool.AddCert(func() *x509.Certificate {
block, _ := pem.Decode(x.Must(ioutil.ReadFile(
filepath.Join(os.ExpandEnv("$STEPPATH"), "/certs/root_ca.crt"),
)))
return x.Must(x509.ParseCertificate(block.Bytes))
}())
return certPool
}
func bindingPort() int {
parts := strings.SplitN(os.Getenv("BIND_ADDR"), ":", 2)
bindPort, err := strconv.Atoi(parts[1])
if err != nil {
bindPort = 0
}
return bindPort
}
SEE ALSO
Tasks
- TBD
Acceptance Criteria
- TBD