diff options
Diffstat (limited to 'crypto/acme/autocert/autocert.go')
-rw-r--r-- | crypto/acme/autocert/autocert.go | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/crypto/acme/autocert/autocert.go b/crypto/acme/autocert/autocert.go new file mode 100644 index 0000000..f99c36e --- /dev/null +++ b/crypto/acme/autocert/autocert.go | |||
@@ -0,0 +1,85 @@ | |||
1 | package autocert | ||
2 | |||
3 | import ( | ||
4 | "context" | ||
5 | "crypto/tls" | ||
6 | "fmt" | ||
7 | "net" | ||
8 | |||
9 | "code.crute.us/mcrute/golib/service" | ||
10 | "golang.org/x/net/idna" | ||
11 | ) | ||
12 | |||
13 | type InfoReporter interface { | ||
14 | Info(...interface{}) | ||
15 | } | ||
16 | |||
17 | type CertProvider interface { | ||
18 | GetCertificate(*tls.ClientHelloInfo) (*tls.Certificate, error) | ||
19 | Listener() net.Listener | ||
20 | TLSConfig() *tls.Config | ||
21 | } | ||
22 | |||
23 | type PrimingCertProvider interface { | ||
24 | CertProvider | ||
25 | PrimeCache() error | ||
26 | PrimingReporter(InfoReporter) service.RunnerFunc | ||
27 | } | ||
28 | |||
29 | type ACMEHostList struct { | ||
30 | hosts map[string]bool | ||
31 | } | ||
32 | |||
33 | func NewACMEHostList(hosts ...string) *ACMEHostList { | ||
34 | hl := make(map[string]bool, len(hosts)) | ||
35 | for _, h := range hosts { | ||
36 | if h, err := idna.Lookup.ToASCII(h); err == nil { | ||
37 | hl[h] = true | ||
38 | } | ||
39 | } | ||
40 | return &ACMEHostList{hl} | ||
41 | } | ||
42 | |||
43 | func (h *ACMEHostList) HostPolicy(_ context.Context, host string) error { | ||
44 | if !h.hosts[host] { | ||
45 | return fmt.Errorf("acme/autocert: host %q not configured in HostWhitelist", host) | ||
46 | } | ||
47 | return nil | ||
48 | } | ||
49 | |||
50 | func (h *ACMEHostList) Hosts() []string { | ||
51 | out := []string{} | ||
52 | for k, _ := range h.hosts { | ||
53 | out = append(out, k) | ||
54 | } | ||
55 | return out | ||
56 | } | ||
57 | |||
58 | // PrimeCache makes a request to the autocert.Manager.GetCertificate function | ||
59 | // for each host in the host list. It will request ECDSA certificates. This | ||
60 | // will fill a certificate cache if it has not yet been filled and has the side | ||
61 | // effect of starting renewal goroutines for each allowed host. | ||
62 | // | ||
63 | // If reportcb is not nil it will be called with a log message for each host | ||
64 | // that is being primed. | ||
65 | func (h *ACMEHostList) PrimeCache(m CertProvider, report chan<- string) error { | ||
66 | for k, _ := range h.hosts { | ||
67 | if report != nil { | ||
68 | report <- fmt.Sprintf("Priming certificate cache for %s", k) | ||
69 | } | ||
70 | // ECDSA Version | ||
71 | if _, err := m.GetCertificate(&tls.ClientHelloInfo{ | ||
72 | ServerName: k, | ||
73 | SignatureSchemes: []tls.SignatureScheme{tls.ECDSAWithP256AndSHA256}, | ||
74 | }); err != nil { | ||
75 | return err | ||
76 | } | ||
77 | // RSA Version | ||
78 | if _, err := m.GetCertificate(&tls.ClientHelloInfo{ | ||
79 | ServerName: k, | ||
80 | }); err != nil { | ||
81 | return err | ||
82 | } | ||
83 | } | ||
84 | return nil | ||
85 | } | ||