-
Notifications
You must be signed in to change notification settings - Fork 210
/
acme.go
115 lines (84 loc) · 1.94 KB
/
acme.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package service
import (
"context"
"fmt"
"net/http"
"sync"
"github.com/yyyar/gobetween/config"
"github.com/yyyar/gobetween/core"
"github.com/yyyar/gobetween/server/tcp"
"golang.org/x/crypto/acme/autocert"
)
/**
* AcmeService listens on http port (default 80) for incoming acme challenges from letsencrypt.org
* and updates it's certificate manager's hotpolicy depending on acme hosts configured for
* each core.Server instance with [acme] section in config
*/
type AcmeService struct {
certMan *autocert.Manager
hosts map[string]bool
sync.RWMutex
}
func init() {
registry["acme"] = NewAcmeService
}
func NewAcmeService(cfg config.Config) core.Service {
if cfg.Acme == nil {
return nil
}
a := &AcmeService{
certMan: &autocert.Manager{
Cache: autocert.DirCache(cfg.Acme.CacheDir),
Prompt: autocert.AcceptTOS,
},
hosts: make(map[string]bool),
}
a.certMan.HostPolicy = func(_ context.Context, host string) error {
a.RLock()
defer a.RUnlock()
if a.hosts[host] {
return nil
}
return fmt.Errorf("Acme: host %s is not configured", host)
}
//accept http challenge
if cfg.Acme.Challenge == "http" {
go http.ListenAndServe(cfg.Acme.HttpBind, a.certMan.HTTPHandler(nil))
}
return a
}
func (a *AcmeService) Enable(server core.Server) error {
if a == nil {
return nil
}
serverCfg := server.Cfg()
if serverCfg.Tls == nil {
return nil
}
tcpServer, ok := server.(*tcp.Server)
if !ok {
return nil
}
tcpServer.GetCertificate = a.certMan.GetCertificate
a.Lock()
defer a.Unlock()
for _, host := range serverCfg.Tls.AcmeHosts {
if a.hosts[host] {
return fmt.Errorf("Acme host %s is already configured", host)
}
a.hosts[host] = true
}
return nil
}
func (a *AcmeService) Disable(server core.Server) error {
serverCfg := server.Cfg()
if serverCfg.Tls == nil {
return nil
}
a.Lock()
defer a.Unlock()
for _, host := range serverCfg.Tls.AcmeHosts {
delete(a.hosts, host)
}
return nil
}