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. ```golang 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 * [RFC-8555](https://datatracker.ietf.org/doc/html/rfc8555) * [$STEPPATH](https://smallstep.com/docs/step-cli/reference/path/#examples) # Tasks * [ ] TBD # Acceptance Criteria * [ ] TBD