@marcel91200 / caddy Mirror · read-only / commits / b79f86f2
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

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