@marcel91200 / caddy Mirror · read-only / commits / 0433f9d0
Fork 0

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 -)