package autocert import ( "context" "crypto/tls" "fmt" "net" "code.crute.us/mcrute/golib/log" "code.crute.us/mcrute/golib/service" "golang.org/x/net/idna" ) type CertProvider interface { GetCertificate(*tls.ClientHelloInfo) (*tls.Certificate, error) Listener() net.Listener TLSConfig() *tls.Config } type PrimingCertProvider interface { CertProvider PrimeCache() error PrimingReporter(log.LeveledLogger) service.RunnerFunc } type ACMEHostList struct { hosts map[string]bool } func NewACMEHostList(hosts ...string) *ACMEHostList { hl := make(map[string]bool, len(hosts)) for _, h := range hosts { if h, err := idna.Lookup.ToASCII(h); err == nil { hl[h] = true } } return &ACMEHostList{hl} } func (h *ACMEHostList) HostPolicy(_ context.Context, host string) error { if !h.hosts[host] { return fmt.Errorf("acme/autocert: host %q not configured in HostWhitelist", host) } return nil } func (h *ACMEHostList) Hosts() []string { out := []string{} for k, _ := range h.hosts { out = append(out, k) } return out } // PrimeCache makes a request to the autocert.Manager.GetCertificate function // for each host in the host list. It will request ECDSA certificates. This // will fill a certificate cache if it has not yet been filled and has the side // effect of starting renewal goroutines for each allowed host. // // If reportcb is not nil it will be called with a log message for each host // that is being primed. func (h *ACMEHostList) PrimeCache(m CertProvider, report chan<- string) error { for k, _ := range h.hosts { if report != nil { report <- fmt.Sprintf("Priming certificate cache for %s", k) } // ECDSA Version if _, err := m.GetCertificate(&tls.ClientHelloInfo{ ServerName: k, SignatureSchemes: []tls.SignatureScheme{tls.ECDSAWithP256AndSHA256}, }); err != nil { return err } // RSA Version if _, err := m.GetCertificate(&tls.ClientHelloInfo{ ServerName: k, }); err != nil { return err } } return nil }