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
caddytls: Clean up some code related to automation
Matthew Holt committed
Mar 15, 2020 at 21:22 UTC
0433f9d075452d78ac93c72bad37856dc1b5b6f7
4 files changed
+318
-299
caddyconfig/httpcaddyfile/httptype.go
+7
-7
@@ -195,7 +195,7 @@ func (st ServerType) Setup(originalServerBlocks []caddyfile.ServerBlock,
195
tlsApp.Automation = new(caddytls.AutomationConfig)
196
}
197
tlsApp.Automation.Policies = append(tlsApp.Automation.Policies, &caddytls.AutomationPolicy{
198
- Hosts: sblockHosts,
198
+ Subjects: sblockHosts,
199
IssuerRaw: caddyconfig.JSONModuleObject(issuer, "module", issuer.(caddy.Module).CaddyModule().ID.Name(), &warnings),
200
})
201
} else {
@@ -768,17 +768,17 @@ func consolidateAutomationPolicies(aps []*caddytls.AutomationPolicy) []*caddytls
768
// if the policy is the same, we can keep just one, but we have
769
// to be careful which one we keep; if only one has any hostnames
770
// defined, then we need to keep the one without any hostnames,
771
- // otherwise the one without any hosts (a catch-all) would be
772
- // eaten up by the one with hosts; and if both have hosts, we
771
+ // otherwise the one without any subjects (a catch-all) would be
772
+ // eaten up by the one with subjects; and if both have subjects, we
773
// need to combine their lists
774
if reflect.DeepEqual(aps[i].IssuerRaw, aps[j].IssuerRaw) &&
775
aps[i].ManageSync == aps[j].ManageSync {
776
- if len(aps[i].Hosts) == 0 && len(aps[j].Hosts) > 0 {
776
+ if len(aps[i].Subjects) == 0 && len(aps[j].Subjects) > 0 {
777
aps = append(aps[:j], aps[j+1:]...)
778
- } else if len(aps[i].Hosts) > 0 && len(aps[j].Hosts) == 0 {
778
+ } else if len(aps[i].Subjects) > 0 && len(aps[j].Subjects) == 0 {
779
aps = append(aps[:i], aps[i+1:]...)
780
} else {
781
- aps[i].Hosts = append(aps[i].Hosts, aps[j].Hosts...)
781
+ aps[i].Subjects = append(aps[i].Subjects, aps[j].Subjects...)
782
aps = append(aps[:j], aps[j+1:]...)
783
}
784
i--
@@ -789,7 +789,7 @@ func consolidateAutomationPolicies(aps []*caddytls.AutomationPolicy) []*caddytls
789
790
// ensure any catch-all policies go last
791
sort.SliceStable(aps, func(i, j int) bool {
792
- return len(aps[i].Hosts) > len(aps[j].Hosts)
792
+ return len(aps[i].Subjects) > len(aps[j].Subjects)
793
})
794
795
return aps
modules/caddyhttp/autohttps.go
+3
-3
@@ -235,7 +235,7 @@ uniqueDomainsLoop:
235
// one automation policy would be confusing and an error
236
if app.tlsApp.Automation != nil {
237
for _, ap := range app.tlsApp.Automation.Policies {
238
- for _, apHost := range ap.Hosts {
238
+ for _, apHost := range ap.Subjects {
239
if apHost == d {
240
continue uniqueDomainsLoop
241
}
@@ -424,7 +424,7 @@ func (app *App) createAutomationPolicies(ctx caddy.Context, publicNames, interna
424
// custom CA endpoint, for example - whichever one we choose must
425
// have a host list that is a superset of the policy we make...
426
// the policy with no host filter is guaranteed to qualify
427
- if len(ap.Hosts) == 0 {
427
+ if len(ap.Subjects) == 0 {
428
basePolicy = ap
429
break
430
}
@@ -451,7 +451,7 @@ func (app *App) createAutomationPolicies(ctx caddy.Context, publicNames, interna
451
}
452
}
453
newPolicy.Issuer = issuer
454
- newPolicy.Hosts = hosts
454
+ newPolicy.Subjects = hosts
455
456
return app.tlsApp.AddAutomationPolicy(newPolicy)
457
}
modules/caddytls/automation.go
new
+301
@@ -0,0 +1,301 @@
1
+// Copyright 2015 Matthew Holt and The Caddy Authors
2
+//
3
+// Licensed under the Apache License, Version 2.0 (the "License");
4
+// you may not use this file except in compliance with the License.
5
+// You may obtain a copy of the License at
6
+//
7
+// http://www.apache.org/licenses/LICENSE-2.0
8
+//
9
+// Unless required by applicable law or agreed to in writing, software
10
+// distributed under the License is distributed on an "AS IS" BASIS,
11
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+// See the License for the specific language governing permissions and
13
+// limitations under the License.
14
+
15
+package caddytls
16
+
17
+import (
18
+ "encoding/json"
19
+ "fmt"
20
+ "net/http"
21
+ "time"
22
+
23
+ "github.com/caddyserver/caddy/v2"
24
+ "github.com/caddyserver/certmagic"
25
+ "github.com/go-acme/lego/v3/challenge"
26
+)
27
+
28
+// AutomationConfig designates configuration for the
29
+// construction and use of ACME clients.
30
+type AutomationConfig struct {
31
+ // The list of automation policies. The first matching
32
+ // policy will be applied for a given certificate/name.
33
+ Policies []*AutomationPolicy `json:"policies,omitempty"`
34
+
35
+ // On-Demand TLS defers certificate operations to the
36
+ // moment they are needed, e.g. during a TLS handshake.
37
+ // Useful when you don't know all the hostnames up front.
38
+ // Caddy was the first web server to deploy this technology.
39
+ OnDemand *OnDemandConfig `json:"on_demand,omitempty"`
40
+
41
+ // Caddy staples OCSP (and caches the response) for all
42
+ // qualifying certificates by default. This setting
43
+ // changes how often it scans responses for freshness,
44
+ // and updates them if they are getting stale.
45
+ OCSPCheckInterval caddy.Duration `json:"ocsp_interval,omitempty"`
46
+
47
+ // Every so often, Caddy will scan all loaded, managed
48
+ // certificates for expiration. This setting changes how
49
+ // frequently the scan for expiring certificates is
50
+ // performed. If your certificate lifetimes are very
51
+ // short (less than ~24 hours), you should set this to
52
+ // a low value.
53
+ RenewCheckInterval caddy.Duration `json:"renew_interval,omitempty"`
54
+
55
+ defaultAutomationPolicy *AutomationPolicy
56
+}
57
+
58
+// AutomationPolicy designates the policy for automating the
59
+// management (obtaining, renewal, and revocation) of managed
60
+// TLS certificates.
61
+//
62
+// An AutomationPolicy value is not valid until it has been
63
+// provisioned; use the `AddAutomationPolicy()` method on the
64
+// TLS app to properly provision a new policy.
65
+type AutomationPolicy struct {
66
+ // Which subjects (hostnames or IP addresses) this policy applies to.
67
+ Subjects []string `json:"subjects,omitempty"`
68
+
69
+ // The module that will issue certificates. Default: acme
70
+ IssuerRaw json.RawMessage `json:"issuer,omitempty" caddy:"namespace=tls.issuance inline_key=module"`
71
+
72
+ // If true, certificates will be requested with MustStaple. Not all
73
+ // CAs support this, and there are potentially serious consequences
74
+ // of enabling this feature without proper threat modeling.
75
+ MustStaple bool `json:"must_staple,omitempty"`
76
+
77
+ // How long before a certificate's expiration to try renewing it,
78
+ // as a function of its total lifetime. As a general and conservative
79
+ // rule, it is a good idea to renew a certificate when it has about
80
+ // 1/3 of its total lifetime remaining. This utilizes the majority
81
+ // of the certificate's lifetime while still saving time to
82
+ // troubleshoot problems. However, for extremely short-lived certs,
83
+ // you may wish to increase the ratio to ~1/2.
84
+ RenewalWindowRatio float64 `json:"renewal_window_ratio,omitempty"`
85
+
86
+ // The type of key to generate for certificates.
87
+ // Supported values: `ed25519`, `p256`, `p384`, `rsa2048`, `rsa4096`.
88
+ KeyType string `json:"key_type,omitempty"`
89
+
90
+ // Optionally configure a separate storage module associated with this
91
+ // manager, instead of using Caddy's global/default-configured storage.
92
+ StorageRaw json.RawMessage `json:"storage,omitempty" caddy:"namespace=caddy.storage inline_key=module"`
93
+
94
+ // If true, certificates will be managed "on demand"; that is, during
95
+ // TLS handshakes or when needed, as opposed to at startup or config
96
+ // load.
97
+ OnDemand bool `json:"on_demand,omitempty"`
98
+
99
+ // If true, certificate management will be conducted
100
+ // in the foreground; this will block config reloads
101
+ // and return errors if there were problems with
102
+ // obtaining or renewing certificates. This is often
103
+ // not desirable, especially when serving sites out
104
+ // of your control. Default: false
105
+ // TODO: is this really necessary per-policy? why not a global setting...
106
+ ManageSync bool `json:"manage_sync,omitempty"`
107
+
108
+ // Issuer stores the decoded issuer parameters. This is only
109
+ // used to populate an underlying certmagic.Config's Issuer
110
+ // field; it is not referenced thereafter.
111
+ Issuer certmagic.Issuer `json:"-"`
112
+
113
+ magic *certmagic.Config
114
+ storage certmagic.Storage
115
+}
116
+
117
+// provision converts ap into a CertMagic config.
118
+func (ap *AutomationPolicy) provision(tlsApp *TLS) error {
119
+ // policy-specific storage implementation
120
+ if ap.StorageRaw != nil {
121
+ val, err := tlsApp.ctx.LoadModule(ap, "StorageRaw")
122
+ if err != nil {
123
+ return fmt.Errorf("loading TLS storage module: %v", err)
124
+ }
125
+ cmStorage, err := val.(caddy.StorageConverter).CertMagicStorage()
126
+ if err != nil {
127
+ return fmt.Errorf("creating TLS storage configuration: %v", err)
128
+ }
129
+ ap.storage = cmStorage
130
+ }
131
+
132
+ var ond *certmagic.OnDemandConfig
133
+ if ap.OnDemand {
134
+ var onDemand *OnDemandConfig
135
+ if tlsApp.Automation != nil {
136
+ onDemand = tlsApp.Automation.OnDemand
137
+ }
138
+
139
+ ond = &certmagic.OnDemandConfig{
140
+ DecisionFunc: func(name string) error {
141
+ if onDemand != nil {
142
+ if onDemand.Ask != "" {
143
+ err := onDemandAskRequest(onDemand.Ask, name)
144
+ if err != nil {
145
+ return err
146
+ }
147
+ }
148
+ // check the rate limiter last because
149
+ // doing so makes a reservation
150
+ if !onDemandRateLimiter.Allow() {
151
+ return fmt.Errorf("on-demand rate limit exceeded")
152
+ }
153
+ }
154
+ return nil
155
+ },
156
+ }
157
+ }
158
+
159
+ if ap.IssuerRaw != nil {
160
+ val, err := tlsApp.ctx.LoadModule(ap, "IssuerRaw")
161
+ if err != nil {
162
+ return fmt.Errorf("loading TLS automation management module: %s", err)
163
+ }
164
+ ap.Issuer = val.(certmagic.Issuer)
165
+ }
166
+
167
+ keySource := certmagic.StandardKeyGenerator{
168
+ KeyType: supportedCertKeyTypes[ap.KeyType],
169
+ }
170
+
171
+ storage := ap.storage
172
+ if storage == nil {
173
+ storage = tlsApp.ctx.Storage()
174
+ }
175
+
176
+ template := certmagic.Config{
177
+ MustStaple: ap.MustStaple,
178
+ RenewalWindowRatio: ap.RenewalWindowRatio,
179
+ KeySource: keySource,
180
+ OnDemand: ond,
181
+ Storage: storage,
182
+ Issuer: ap.Issuer, // if nil, certmagic.New() will set default in returned Config
183
+ }
184
+ if rev, ok := ap.Issuer.(certmagic.Revoker); ok {
185
+ template.Revoker = rev
186
+ }
187
+ ap.magic = certmagic.New(tlsApp.certCache, template)
188
+
189
+ // sometimes issuers may need the parent certmagic.Config in
190
+ // order to function properly (for example, ACMEIssuer needs
191
+ // access to the correct storage and cache so it can solve
192
+ // ACME challenges -- it's an annoying, inelegant circular
193
+ // dependency that I don't know how to resolve nicely!)
194
+ if configger, ok := ap.Issuer.(ConfigSetter); ok {
195
+ configger.SetConfig(ap.magic)
196
+ }
197
+
198
+ return nil
199
+}
200
+
201
+// ChallengesConfig configures the ACME challenges.
202
+type ChallengesConfig struct {
203
+ // HTTP configures the ACME HTTP challenge. This
204
+ // challenge is enabled and used automatically
205
+ // and by default.
206
+ HTTP *HTTPChallengeConfig `json:"http,omitempty"`
207
+
208
+ // TLSALPN configures the ACME TLS-ALPN challenge.
209
+ // This challenge is enabled and used automatically
210
+ // and by default.
211
+ TLSALPN *TLSALPNChallengeConfig `json:"tls-alpn,omitempty"`
212
+
213
+ // Configures the ACME DNS challenge. Because this
214
+ // challenge typically requires credentials for
215
+ // interfacing with a DNS provider, this challenge is
216
+ // not enabled by default. This is the only challenge
217
+ // type which does not require a direct connection
218
+ // to Caddy from an external server.
219
+ DNSRaw json.RawMessage `json:"dns,omitempty" caddy:"namespace=tls.dns inline_key=provider"`
220
+
221
+ DNS challenge.Provider `json:"-"`
222
+}
223
+
224
+// HTTPChallengeConfig configures the ACME HTTP challenge.
225
+type HTTPChallengeConfig struct {
226
+ // If true, the HTTP challenge will be disabled.
227
+ Disabled bool `json:"disabled,omitempty"`
228
+
229
+ // An alternate port on which to service this
230
+ // challenge. Note that the HTTP challenge port is
231
+ // hard-coded into the spec and cannot be changed,
232
+ // so you would have to forward packets from the
233
+ // standard HTTP challenge port to this one.
234
+ AlternatePort int `json:"alternate_port,omitempty"`
235
+}
236
+
237
+// TLSALPNChallengeConfig configures the ACME TLS-ALPN challenge.
238
+type TLSALPNChallengeConfig struct {
239
+ // If true, the TLS-ALPN challenge will be disabled.
240
+ Disabled bool `json:"disabled,omitempty"`
241
+
242
+ // An alternate port on which to service this
243
+ // challenge. Note that the TLS-ALPN challenge port
244
+ // is hard-coded into the spec and cannot be changed,
245
+ // so you would have to forward packets from the
246
+ // standard TLS-ALPN challenge port to this one.
247
+ AlternatePort int `json:"alternate_port,omitempty"`
248
+}
249
+
250
+// OnDemandConfig configures on-demand TLS, for obtaining
251
+// needed certificates at handshake-time. Because this
252
+// feature can easily be abused, you should set up rate
253
+// limits and/or an internal endpoint that Caddy can
254
+// "ask" if it should be allowed to manage certificates
255
+// for a given hostname.
256
+type OnDemandConfig struct {
257
+ // An optional rate limit to throttle the
258
+ // issuance of certificates from handshakes.
259
+ RateLimit *RateLimit `json:"rate_limit,omitempty"`
260
+
261
+ // If Caddy needs to obtain or renew a certificate
262
+ // during a TLS handshake, it will perform a quick
263
+ // HTTP request to this URL to check if it should be
264
+ // allowed to try to get a certificate for the name
265
+ // in the "domain" query string parameter, like so:
266
+ // `?domain=example.com`. The endpoint must return a
267
+ // 200 OK status if a certificate is allowed;
268
+ // anything else will cause it to be denied.
269
+ // Redirects are not followed.
270
+ Ask string `json:"ask,omitempty"`
271
+}
272
+
273
+// RateLimit specifies an interval with optional burst size.
274
+type RateLimit struct {
275
+ // A duration value. A certificate may be obtained 'burst'
276
+ // times during this interval.
277
+ Interval caddy.Duration `json:"interval,omitempty"`
278
+
279
+ // How many times during an interval a certificate can be obtained.
280
+ Burst int `json:"burst,omitempty"`
281
+}
282
+
283
+// ConfigSetter is implemented by certmagic.Issuers that
284
+// need access to a parent certmagic.Config as part of
285
+// their provisioning phase. For example, the ACMEIssuer
286
+// requires a config so it can access storage and the
287
+// cache to solve ACME challenges.
288
+type ConfigSetter interface {
289
+ SetConfig(cfg *certmagic.Config)
290
+}
291
+
292
+// These perpetual values are used for on-demand TLS.
293
+var (
294
+ onDemandRateLimiter = certmagic.NewRateLimiter(0, 0)
295
+ onDemandAskClient = &http.Client{
296
+ Timeout: 10 * time.Second,
297
+ CheckRedirect: func(req *http.Request, via []*http.Request) error {
298
+ return fmt.Errorf("following http redirects is not allowed")
299
+ },
300
+ }
301
+)
modules/caddytls/tls.go
+7
-289
@@ -28,7 +28,6 @@ import (
28
29
"github.com/caddyserver/caddy/v2"
30
"github.com/caddyserver/certmagic"
31
- "github.com/go-acme/lego/v3/challenge"
31
"go.uber.org/zap"
32
)
33
@@ -183,7 +182,7 @@ func (t *TLS) Validate() error {
182
// isn't useful and is probably a mistake
183
hostSet := make(map[string]int)
184
for i, ap := range t.Automation.Policies {
186
- for _, h := range ap.Hosts {
185
+ for _, h := range ap.Subjects {
186
if first, ok := hostSet[h]; ok {
187
return fmt.Errorf("automation policy %d: cannot apply more than one automation policy to host: %s (first match in policy %d)", i, h, first)
188
}
@@ -300,7 +299,7 @@ func (t *TLS) AddAutomationPolicy(ap *AutomationPolicy) error {
299
for i, other := range t.Automation.Policies {
300
// if a catch-all policy (or really, any policy with
301
// fewer names) exists, prioritize this new policy
303
- if len(other.Hosts) < len(ap.Hosts) {
302
+ if len(other.Subjects) < len(ap.Subjects) {
303
t.Automation.Policies = append(t.Automation.Policies[:i],
304
append([]*AutomationPolicy{ap}, t.Automation.Policies[i+1:]...)...)
305
return nil
@@ -318,10 +317,10 @@ func (t *TLS) getConfigForName(name string) *certmagic.Config {
317
318
func (t *TLS) getAutomationPolicyForName(name string) *AutomationPolicy {
319
for _, ap := range t.Automation.Policies {
321
- if len(ap.Hosts) == 0 {
320
+ if len(ap.Subjects) == 0 {
321
return ap // no host filter is an automatic match
322
}
324
- for _, h := range ap.Hosts {
323
+ for _, h := range ap.Subjects {
324
if h == name {
325
return ap
326
}
@@ -399,261 +398,6 @@ type Certificate struct {
398
Tags []string
399
}
400
402
-// AutomationConfig designates configuration for the
403
-// construction and use of ACME clients.
404
-type AutomationConfig struct {
405
- // The list of automation policies. The first matching
406
- // policy will be applied for a given certificate/name.
407
- Policies []*AutomationPolicy `json:"policies,omitempty"`
408
-
409
- // On-Demand TLS defers certificate operations to the
410
- // moment they are needed, e.g. during a TLS handshake.
411
- // Useful when you don't know all the hostnames up front.
412
- // Caddy was the first web server to deploy this technology.
413
- OnDemand *OnDemandConfig `json:"on_demand,omitempty"`
414
-
415
- // Caddy staples OCSP (and caches the response) for all
416
- // qualifying certificates by default. This setting
417
- // changes how often it scans responses for freshness,
418
- // and updates them if they are getting stale.
419
- OCSPCheckInterval caddy.Duration `json:"ocsp_interval,omitempty"`
420
-
421
- // Every so often, Caddy will scan all loaded, managed
422
- // certificates for expiration. This setting changes how
423
- // frequently the scan for expiring certificates is
424
- // performed. If your certificate lifetimes are very
425
- // short (less than ~24 hours), you should set this to
426
- // a low value.
427
- RenewCheckInterval caddy.Duration `json:"renew_interval,omitempty"`
428
-
429
- defaultAutomationPolicy *AutomationPolicy
430
-}
431
-
432
-// AutomationPolicy designates the policy for automating the
433
-// management (obtaining, renewal, and revocation) of managed
434
-// TLS certificates.
435
-//
436
-// An AutomationPolicy value is not valid until it has been
437
-// provisioned; use the `AddAutomationPolicy()` method on the
438
-// TLS app to properly provision a new policy.
439
-type AutomationPolicy struct {
440
- // Which hostnames this policy applies to.
441
- Hosts []string `json:"hosts,omitempty"`
442
-
443
- // The module that will issue certificates. Default: acme
444
- IssuerRaw json.RawMessage `json:"issuer,omitempty" caddy:"namespace=tls.issuance inline_key=module"`
445
-
446
- // If true, certificates will be requested with MustStaple. Not all
447
- // CAs support this, and there are potentially serious consequences
448
- // of enabling this feature without proper threat modeling.
449
- MustStaple bool `json:"must_staple,omitempty"`
450
-
451
- // How long before a certificate's expiration to try renewing it,
452
- // as a function of its total lifetime. As a general and conservative
453
- // rule, it is a good idea to renew a certificate when it has about
454
- // 1/3 of its total lifetime remaining. This utilizes the majority
455
- // of the certificate's lifetime while still saving time to
456
- // troubleshoot problems. However, for extremely short-lived certs,
457
- // you may wish to increase the ratio to ~1/2.
458
- RenewalWindowRatio float64 `json:"renewal_window_ratio,omitempty"`
459
-
460
- // The type of key to generate for certificates.
461
- // Supported values: `ed25519`, `p256`, `p384`, `rsa2048`, `rsa4096`.
462
- KeyType string `json:"key_type,omitempty"`
463
-
464
- // Optionally configure a separate storage module associated with this
465
- // manager, instead of using Caddy's global/default-configured storage.
466
- StorageRaw json.RawMessage `json:"storage,omitempty" caddy:"namespace=caddy.storage inline_key=module"`
467
-
468
- // If true, certificates will be managed "on demand", that is, during
469
- // TLS handshakes or when needed, as opposed to at startup or config
470
- // load.
471
- OnDemand bool `json:"on_demand,omitempty"`
472
-
473
- // If true, certificate management will be conducted
474
- // in the foreground; this will block config reloads
475
- // and return errors if there were problems with
476
- // obtaining or renewing certificates. This is often
477
- // not desirable, especially when serving sites out
478
- // of your control. Default: false
479
- // TODO: is this really necessary per-policy? why not a global setting...
480
- ManageSync bool `json:"manage_sync,omitempty"`
481
-
482
- // Issuer stores the decoded issuer parameters. This is only
483
- // used to populate an underlying certmagic.Config's Issuer
484
- // field; it is not referenced thereafter.
485
- Issuer certmagic.Issuer `json:"-"`
486
-
487
- magic *certmagic.Config
488
- storage certmagic.Storage
489
-}
490
-
491
-// provision converts ap into a CertMagic config.
492
-func (ap *AutomationPolicy) provision(tlsApp *TLS) error {
493
- // policy-specific storage implementation
494
- if ap.StorageRaw != nil {
495
- val, err := tlsApp.ctx.LoadModule(ap, "StorageRaw")
496
- if err != nil {
497
- return fmt.Errorf("loading TLS storage module: %v", err)
498
- }
499
- cmStorage, err := val.(caddy.StorageConverter).CertMagicStorage()
500
- if err != nil {
501
- return fmt.Errorf("creating TLS storage configuration: %v", err)
502
- }
503
- ap.storage = cmStorage
504
- }
505
-
506
- var ond *certmagic.OnDemandConfig
507
- if ap.OnDemand {
508
- var onDemand *OnDemandConfig
509
- if tlsApp.Automation != nil {
510
- onDemand = tlsApp.Automation.OnDemand
511
- }
512
-
513
- ond = &certmagic.OnDemandConfig{
514
- DecisionFunc: func(name string) error {
515
- if onDemand != nil {
516
- if onDemand.Ask != "" {
517
- err := onDemandAskRequest(onDemand.Ask, name)
518
- if err != nil {
519
- return err
520
- }
521
- }
522
- // check the rate limiter last because
523
- // doing so makes a reservation
524
- if !onDemandRateLimiter.Allow() {
525
- return fmt.Errorf("on-demand rate limit exceeded")
526
- }
527
- }
528
- return nil
529
- },
530
- }
531
- }
532
-
533
- if ap.IssuerRaw != nil {
534
- val, err := tlsApp.ctx.LoadModule(ap, "IssuerRaw")
535
- if err != nil {
536
- return fmt.Errorf("loading TLS automation management module: %s", err)
537
- }
538
- ap.Issuer = val.(certmagic.Issuer)
539
- }
540
-
541
- keySource := certmagic.StandardKeyGenerator{
542
- KeyType: supportedCertKeyTypes[ap.KeyType],
543
- }
544
-
545
- storage := ap.storage
546
- if storage == nil {
547
- storage = tlsApp.ctx.Storage()
548
- }
549
-
550
- template := certmagic.Config{
551
- MustStaple: ap.MustStaple,
552
- RenewalWindowRatio: ap.RenewalWindowRatio,
553
- KeySource: keySource,
554
- OnDemand: ond,
555
- Storage: storage,
556
- Issuer: ap.Issuer, // if nil, certmagic.New() will set default in returned Config
557
- }
558
- if rev, ok := ap.Issuer.(certmagic.Revoker); ok {
559
- template.Revoker = rev
560
- }
561
- ap.magic = certmagic.New(tlsApp.certCache, template)
562
-
563
- // sometimes issuers may need the parent certmagic.Config in
564
- // order to function properly (for example, ACMEIssuer needs
565
- // access to the correct storage and cache so it can solve
566
- // ACME challenges -- it's an annoying, inelegant circular
567
- // dependency that I don't know how to resolve nicely!)
568
- if configger, ok := ap.Issuer.(ConfigSetter); ok {
569
- configger.SetConfig(ap.magic)
570
- }
571
-
572
- return nil
573
-}
574
-
575
-// ChallengesConfig configures the ACME challenges.
576
-type ChallengesConfig struct {
577
- // HTTP configures the ACME HTTP challenge. This
578
- // challenge is enabled and used automatically
579
- // and by default.
580
- HTTP *HTTPChallengeConfig `json:"http,omitempty"`
581
-
582
- // TLSALPN configures the ACME TLS-ALPN challenge.
583
- // This challenge is enabled and used automatically
584
- // and by default.
585
- TLSALPN *TLSALPNChallengeConfig `json:"tls-alpn,omitempty"`
586
-
587
- // Configures the ACME DNS challenge. Because this
588
- // challenge typically requires credentials for
589
- // interfacing with a DNS provider, this challenge is
590
- // not enabled by default. This is the only challenge
591
- // type which does not require a direct connection
592
- // to Caddy from an external server.
593
- DNSRaw json.RawMessage `json:"dns,omitempty" caddy:"namespace=tls.dns inline_key=provider"`
594
-
595
- DNS challenge.Provider `json:"-"`
596
-}
597
-
598
-// HTTPChallengeConfig configures the ACME HTTP challenge.
599
-type HTTPChallengeConfig struct {
600
- // If true, the HTTP challenge will be disabled.
601
- Disabled bool `json:"disabled,omitempty"`
602
-
603
- // An alternate port on which to service this
604
- // challenge. Note that the HTTP challenge port is
605
- // hard-coded into the spec and cannot be changed,
606
- // so you would have to forward packets from the
607
- // standard HTTP challenge port to this one.
608
- AlternatePort int `json:"alternate_port,omitempty"`
609
-}
610
-
611
-// TLSALPNChallengeConfig configures the ACME TLS-ALPN challenge.
612
-type TLSALPNChallengeConfig struct {
613
- // If true, the TLS-ALPN challenge will be disabled.
614
- Disabled bool `json:"disabled,omitempty"`
615
-
616
- // An alternate port on which to service this
617
- // challenge. Note that the TLS-ALPN challenge port
618
- // is hard-coded into the spec and cannot be changed,
619
- // so you would have to forward packets from the
620
- // standard TLS-ALPN challenge port to this one.
621
- AlternatePort int `json:"alternate_port,omitempty"`
622
-}
623
-
624
-// OnDemandConfig configures on-demand TLS, for obtaining
625
-// needed certificates at handshake-time. Because this
626
-// feature can easily be abused, you should set up rate
627
-// limits and/or an internal endpoint that Caddy can
628
-// "ask" if it should be allowed to manage certificates
629
-// for a given hostname.
630
-type OnDemandConfig struct {
631
- // An optional rate limit to throttle the
632
- // issuance of certificates from handshakes.
633
- RateLimit *RateLimit `json:"rate_limit,omitempty"`
634
-
635
- // If Caddy needs to obtain or renew a certificate
636
- // during a TLS handshake, it will perform a quick
637
- // HTTP request to this URL to check if it should be
638
- // allowed to try to get a certificate for the name
639
- // in the "domain" query string parameter, like so:
640
- // `?domain=example.com`. The endpoint must return a
641
- // 200 OK status if a certificate is allowed;
642
- // anything else will cause it to be denied.
643
- // Redirects are not followed.
644
- Ask string `json:"ask,omitempty"`
645
-}
646
-
647
-// RateLimit specifies an interval with optional burst size.
648
-type RateLimit struct {
649
- // A duration value. A certificate may be obtained 'burst'
650
- // times during this interval.
651
- Interval caddy.Duration `json:"interval,omitempty"`
652
-
653
- // How many times during an interval a certificate can be obtained.
654
- Burst int `json:"burst,omitempty"`
655
-}
656
-
401
// AutomateLoader is a no-op certificate loader module
402
// that is treated as a special case: it uses this app's
403
// automation features to load certificates for the
@@ -669,26 +413,6 @@ func (AutomateLoader) CaddyModule() caddy.ModuleInfo {
413
}
414
}
415
672
-// ConfigSetter is implemented by certmagic.Issuers that
673
-// need access to a parent certmagic.Config as part of
674
-// their provisioning phase. For example, the ACMEIssuer
675
-// requires a config so it can access storage and the
676
-// cache to solve ACME challenges.
677
-type ConfigSetter interface {
678
- SetConfig(cfg *certmagic.Config)
679
-}
680
-
681
-// These perpetual values are used for on-demand TLS.
682
-var (
683
- onDemandRateLimiter = certmagic.NewRateLimiter(0, 0)
684
- onDemandAskClient = &http.Client{
685
- Timeout: 10 * time.Second,
686
- CheckRedirect: func(req *http.Request, via []*http.Request) error {
687
- return fmt.Errorf("following http redirects is not allowed")
688
- },
689
- }
690
-)
691
-
416
// Variables related to storage cleaning.
417
var (
418
storageCleanInterval = 12 * time.Hour
@@ -697,15 +421,16 @@ var (
421
storageCleanMu sync.Mutex
422
)
423
424
+const automateKey = "automate"
425
+
426
// Interface guards
427
var (
428
_ caddy.App = (*TLS)(nil)
429
_ caddy.Provisioner = (*TLS)(nil)
430
+ _ caddy.Validator = (*TLS)(nil)
431
_ caddy.CleanerUpper = (*TLS)(nil)
432
)
433
707
-const automateKey = "automate"
708
-
434
// TODO: This is temporary until the release candidates
435
// (beta 16 changed the storage path for certificates),
436
// after which this function can be deleted
@@ -823,10 +548,3 @@ func (t *TLS) moveCertificates() error {
548
549
return nil
550
}
826
-
827
-// Interface guards
828
-var (
829
- _ caddy.Provisioner = (*TLS)(nil)
830
- _ caddy.Validator = (*TLS)(nil)
831
- _ caddy.App = (*TLS)(nil)
832
-)