Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 14, 05:15 UTC
Fix bugs related to auto HTTPS and alternate port configurations
Matthew Holt committed
Jun 4, 2019 at 22:43 UTC
b79f86f256782be139d4ec09a74e0f75da52876a
3 files changed
+70
-31
modules/caddyhttp/caddyhttp.go
+29
-2
@@ -126,7 +126,8 @@ func (app *App) Start() error {
126
return fmt.Errorf("%s: listening on %s: %v", network, addr, err)
127
}
128
129
- // enable HTTP/2 by default
129
+ // enable HTTP/2 (and support for solving the
130
+ // TLS-ALPN ACME challenge) by default
131
for _, pol := range srv.TLSConnPolicies {
132
if len(pol.ALPN) == 0 {
133
pol.ALPN = append(pol.ALPN, defaultALPN...)
@@ -219,13 +220,38 @@ func (app *App) automaticHTTPS() error {
220
domains = append(domains, d)
221
}
222
223
+ // ensure that these certificates are managed properly;
224
+ // for example, it's implied that the HTTPPort should also
225
+ // be the port the HTTP challenge is solved on, and so
226
+ // for HTTPS port and TLS-ALPN challenge also - we need
227
+ // to tell the TLS app to manage these certs by honoring
228
+ // those port configurations
229
+ acmeManager := &caddytls.ACMEManagerMaker{
230
+ Challenges: caddytls.ChallengesConfig{
231
+ HTTP: caddytls.HTTPChallengeConfig{
232
+ AlternatePort: app.HTTPPort,
233
+ },
234
+ TLSALPN: caddytls.TLSALPNChallengeConfig{
235
+ AlternatePort: app.HTTPSPort,
236
+ },
237
+ },
238
+ }
239
+ acmeManager.SetDefaults()
240
+ tlsApp.Automation.Policies = append(tlsApp.Automation.Policies,
241
+ caddytls.AutomationPolicy{
242
+ Hosts: domains,
243
+ Management: acmeManager,
244
+ })
245
+
246
// manage their certificates
247
err := tlsApp.Manage(domains)
248
if err != nil {
249
return fmt.Errorf("%s: managing certificate for %s: %s", srvName, domains, err)
250
}
251
228
- // tell the server to use TLS
252
+ // tell the server to use TLS by specifying a TLS
253
+ // connection policy (which supports HTTP/2 and the
254
+ // TLS-ALPN ACME challenge as well)
255
srv.TLSConnPolicies = caddytls.ConnectionPolicies{
256
{ALPN: defaultALPN},
257
}
@@ -296,6 +322,7 @@ func (app *App) automaticHTTPS() error {
322
Listen: lnAddrs,
323
Routes: redirRoutes,
324
DisableAutoHTTPS: true,
325
+ tlsApp: tlsApp, // required to solve HTTP challenge
326
}
327
}
328
modules/caddytls/acmemanager.go
+26
-14
@@ -15,13 +15,19 @@ import (
15
func init() {
16
caddy2.RegisterModule(caddy2.Module{
17
Name: "tls.management.acme",
18
- New: func() interface{} { return new(acmeManagerMaker) },
18
+ New: func() interface{} { return new(ACMEManagerMaker) },
19
})
20
}
21
22
-// acmeManagerMaker makes an ACME manager
23
-// for managinig certificates using ACME.
24
-type acmeManagerMaker struct {
22
+// ACMEManagerMaker makes an ACME manager
23
+// for managing certificates using ACME.
24
+// If crafting one manually rather than
25
+// through the config-unmarshal process
26
+// (provisioning), be sure to call
27
+// SetDefaults to ensure sane defaults
28
+// after you have configured this struct
29
+// to your liking.
30
+type ACMEManagerMaker struct {
31
CA string `json:"ca,omitempty"`
32
Email string `json:"email,omitempty"`
33
RenewAhead caddy2.Duration `json:"renew_ahead,omitempty"`
@@ -36,19 +42,22 @@ type acmeManagerMaker struct {
42
keyType certcrypto.KeyType
43
}
44
39
-func (m *acmeManagerMaker) newManager(interactive bool) (certmagic.Manager, error) {
45
+// newManager is a no-op to satisfy the ManagerMaker interface,
46
+// because this manager type is a special case.
47
+func (m *ACMEManagerMaker) newManager(interactive bool) (certmagic.Manager, error) {
48
return nil, nil
49
}
50
43
-func (m *acmeManagerMaker) Provision(ctx caddy2.Context) error {
51
+// Provision sets up m.
52
+func (m *ACMEManagerMaker) Provision(ctx caddy2.Context) error {
53
// DNS providers
54
if m.Challenges.DNS != nil {
46
- val, err := ctx.LoadModuleInline("provider", "tls.dns", m.Challenges.DNS)
55
+ val, err := ctx.LoadModuleInline("provider", "tls.dns", m.Challenges.DNSRaw)
56
if err != nil {
57
return fmt.Errorf("loading TLS storage module: %s", err)
58
}
50
- m.Challenges.dns = val.(challenge.Provider)
51
- m.Challenges.DNS = nil // allow GC to deallocate - TODO: Does this help?
59
+ m.Challenges.DNS = val.(challenge.Provider)
60
+ m.Challenges.DNSRaw = nil // allow GC to deallocate - TODO: Does this help?
61
}
62
63
// policy-specific storage implementation
@@ -65,14 +74,14 @@ func (m *acmeManagerMaker) Provision(ctx caddy2.Context) error {
74
m.Storage = nil // allow GC to deallocate - TODO: Does this help?
75
}
76
68
- m.setDefaults()
77
+ m.SetDefaults()
78
79
return nil
80
}
81
73
-// setDefaults sets necessary values that are
82
+// SetDefaults sets necessary values that are
83
// currently empty to their default values.
75
-func (m *acmeManagerMaker) setDefaults() {
84
+func (m *ACMEManagerMaker) SetDefaults() {
85
if m.CA == "" {
86
m.CA = certmagic.LetsEncryptStagingCA // certmagic.Default.CA // TODO: When not testing, switch to production CA
87
}
@@ -93,7 +102,7 @@ func (m *acmeManagerMaker) setDefaults() {
102
// makeCertMagicConfig converts m into a certmagic.Config, because
103
// this is a special case where the default manager is the certmagic
104
// Config and not a separate manager.
96
-func (m *acmeManagerMaker) makeCertMagicConfig(ctx caddy2.Context) certmagic.Config {
105
+func (m *ACMEManagerMaker) makeCertMagicConfig(ctx caddy2.Context) certmagic.Config {
106
storage := m.storage
107
if storage == nil {
108
storage = ctx.Storage()
@@ -115,7 +124,7 @@ func (m *acmeManagerMaker) makeCertMagicConfig(ctx caddy2.Context) certmagic.Con
124
RenewDurationBefore: time.Duration(m.RenewAhead),
125
AltHTTPPort: m.Challenges.HTTP.AlternatePort,
126
AltTLSALPNPort: m.Challenges.TLSALPN.AlternatePort,
118
- DNSProvider: m.Challenges.dns,
127
+ DNSProvider: m.Challenges.DNS,
128
KeyType: supportedCertKeyTypes[m.KeyType],
129
CertObtainTimeout: time.Duration(m.ACMETimeout),
130
OnDemand: ond,
@@ -133,3 +142,6 @@ var supportedCertKeyTypes = map[string]certcrypto.KeyType{
142
"P256": certcrypto.EC256,
143
"P384": certcrypto.EC384,
144
}
145
+
146
+// Interface guard
147
+var _ managerMaker = (*ACMEManagerMaker)(nil)
modules/caddytls/tls.go
+15
-15
@@ -45,12 +45,12 @@ func (t *TLS) Provision(ctx caddy2.Context) error {
45
46
// automation/management policies
47
for i, ap := range t.Automation.Policies {
48
- val, err := ctx.LoadModuleInline("module", "tls.management", ap.Management)
48
+ val, err := ctx.LoadModuleInline("module", "tls.management", ap.ManagementRaw)
49
if err != nil {
50
return fmt.Errorf("loading TLS automation management module: %s", err)
51
}
52
- t.Automation.Policies[i].management = val.(ManagerMaker)
53
- t.Automation.Policies[i].Management = nil // allow GC to deallocate - TODO: Does this help?
52
+ t.Automation.Policies[i].Management = val.(managerMaker)
53
+ t.Automation.Policies[i].ManagementRaw = nil // allow GC to deallocate - TODO: Does this help?
54
}
55
56
// certificate loaders
@@ -164,9 +164,9 @@ func (t *TLS) getAutomationPolicyForName(name string) AutomationPolicy {
164
}
165
166
// default automation policy
167
- mgmt := new(acmeManagerMaker)
168
- mgmt.setDefaults()
169
- return AutomationPolicy{management: mgmt}
167
+ mgmt := new(ACMEManagerMaker)
168
+ mgmt.SetDefaults()
169
+ return AutomationPolicy{Management: mgmt}
170
}
171
172
// CertificateLoader is a type that can load certificates.
@@ -183,22 +183,22 @@ type AutomationConfig struct {
183
// AutomationPolicy designates the policy for automating the
184
// management of managed TLS certificates.
185
type AutomationPolicy struct {
186
- Hosts []string `json:"hosts,omitempty"`
187
- Management json.RawMessage `json:"management"`
186
+ Hosts []string `json:"hosts,omitempty"`
187
+ ManagementRaw json.RawMessage `json:"management"`
188
189
- management ManagerMaker
189
+ Management managerMaker `json:"-"`
190
}
191
192
func (ap AutomationPolicy) makeCertMagicConfig(ctx caddy2.Context) certmagic.Config {
193
// default manager (ACME) is a special case because of how CertMagic is designed
194
// TODO: refactor certmagic so that ACME manager is not a special case by extracting
195
// its config fields out of the certmagic.Config struct, or something...
196
- if acmeMgmt, ok := ap.management.(*acmeManagerMaker); ok {
196
+ if acmeMgmt, ok := ap.Management.(*ACMEManagerMaker); ok {
197
return acmeMgmt.makeCertMagicConfig(ctx)
198
}
199
200
return certmagic.Config{
201
- NewManager: ap.management.newManager,
201
+ NewManager: ap.Management.newManager,
202
}
203
}
204
@@ -206,9 +206,9 @@ func (ap AutomationPolicy) makeCertMagicConfig(ctx caddy2.Context) certmagic.Con
206
type ChallengesConfig struct {
207
HTTP HTTPChallengeConfig `json:"http"`
208
TLSALPN TLSALPNChallengeConfig `json:"tls-alpn"`
209
- DNS json.RawMessage `json:"dns,omitempty"`
209
+ DNSRaw json.RawMessage `json:"dns,omitempty"`
210
211
- dns challenge.Provider
211
+ DNS challenge.Provider `json:"-"`
212
}
213
214
// HTTPChallengeConfig configures the ACME HTTP challenge.
@@ -232,8 +232,8 @@ type OnDemandConfig struct {
232
AskStarlark string `json:"ask_starlark,omitempty"`
233
}
234
235
-// ManagerMaker makes a certificate manager.
236
-type ManagerMaker interface {
235
+// managerMaker makes a certificate manager.
236
+type managerMaker interface {
237
newManager(interactive bool) (certmagic.Manager, error)
238
}
239