From 91b03dccb0094d96652def8a9c70016fd53d1006 Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Wed, 26 Jun 2019 10:49:32 -0600 Subject: [PATCH] Refactor automatic HTTPS configuration; ability to skip certain names --- modules/caddyhttp/caddyhttp.go | 21 +++++++---- modules/caddyhttp/server.go | 69 ++++++++++++++++++++++++---------- 2 files changed, 63 insertions(+), 27 deletions(-) diff --git a/modules/caddyhttp/caddyhttp.go b/modules/caddyhttp/caddyhttp.go index 036a3ab8..850501fb 100644 --- a/modules/caddyhttp/caddyhttp.go +++ b/modules/caddyhttp/caddyhttp.go @@ -48,16 +48,23 @@ func (app *App) Provision(ctx caddy.Context) error { repl := caddy.NewReplacer() for _, srv := range app.Servers { + if srv.AutoHTTPS == nil { + // avoid nil pointer dereferences + srv.AutoHTTPS = new(AutoHTTPSConfig) + } + // TODO: Test this function to ensure these replacements are performed for i := range srv.Listen { srv.Listen[i] = repl.ReplaceAll(srv.Listen[i], "") } + if srv.Routes != nil { err := srv.Routes.Provision(ctx) if err != nil { return fmt.Errorf("setting up server routes: %v", err) } } + if srv.Errors != nil { err := srv.Errors.Routes.Provision(ctx) if err != nil { @@ -187,7 +194,7 @@ func (app *App) automaticHTTPS() error { for srvName, srv := range app.Servers { srv.tlsApp = tlsApp - if srv.DisableAutoHTTPS { + if srv.AutoHTTPS.Disabled { continue } @@ -203,7 +210,7 @@ func (app *App) automaticHTTPS() error { for _, m := range matcherSet { if hm, ok := m.(*MatchHost); ok { for _, d := range *hm { - if certmagic.HostQualifies(d) { + if certmagic.HostQualifies(d) && !srv.AutoHTTPS.HostSkipped(d) { domainSet[d] = struct{}{} } } @@ -256,7 +263,7 @@ func (app *App) automaticHTTPS() error { {ALPN: defaultALPN}, } - if srv.DisableAutoHTTPSRedir { + if srv.AutoHTTPS.DisableRedir { continue } @@ -324,10 +331,10 @@ func (app *App) automaticHTTPS() error { lnAddrs = append(lnAddrs, addr) } app.Servers["auto_https_redirects"] = &Server{ - Listen: lnAddrs, - Routes: redirRoutes, - DisableAutoHTTPS: true, - tlsApp: tlsApp, // required to solve HTTP challenge + Listen: lnAddrs, + Routes: redirRoutes, + AutoHTTPS: &AutoHTTPSConfig{Disabled: true}, + tlsApp: tlsApp, // required to solve HTTP challenge } } diff --git a/modules/caddyhttp/server.go b/modules/caddyhttp/server.go index 94fd4d47..be46d6da 100644 --- a/modules/caddyhttp/server.go +++ b/modules/caddyhttp/server.go @@ -14,19 +14,17 @@ import ( // Server is an HTTP server. type Server struct { - Listen []string `json:"listen,omitempty"` - ReadTimeout caddy.Duration `json:"read_timeout,omitempty"` - ReadHeaderTimeout caddy.Duration `json:"read_header_timeout,omitempty"` - WriteTimeout caddy.Duration `json:"write_timeout,omitempty"` - IdleTimeout caddy.Duration `json:"idle_timeout,omitempty"` - MaxHeaderBytes int `json:"max_header_bytes,omitempty"` - Routes RouteList `json:"routes,omitempty"` - Errors *httpErrorConfig `json:"errors,omitempty"` - // TODO: Having a separate connection policy to act as a default or template would be handy... then override using first matching conn policy... - TLSConnPolicies caddytls.ConnectionPolicies `json:"tls_connection_policies,omitempty"` - DisableAutoHTTPS bool `json:"disable_auto_https,omitempty"` - DisableAutoHTTPSRedir bool `json:"disable_auto_https_redir,omitempty"` - MaxRehandles int `json:"max_rehandles,omitempty"` + Listen []string `json:"listen,omitempty"` + ReadTimeout caddy.Duration `json:"read_timeout,omitempty"` + ReadHeaderTimeout caddy.Duration `json:"read_header_timeout,omitempty"` + WriteTimeout caddy.Duration `json:"write_timeout,omitempty"` + IdleTimeout caddy.Duration `json:"idle_timeout,omitempty"` + MaxHeaderBytes int `json:"max_header_bytes,omitempty"` + Routes RouteList `json:"routes,omitempty"` + Errors *HTTPErrorConfig `json:"errors,omitempty"` + TLSConnPolicies caddytls.ConnectionPolicies `json:"tls_connection_policies,omitempty"` + AutoHTTPS *AutoHTTPSConfig `json:"automatic_https,omitempty"` + MaxRehandles int `json:"max_rehandles,omitempty"` tlsApp *caddytls.TLS } @@ -121,13 +119,44 @@ func (s *Server) listenersUseAnyPortOtherThan(otherPort int) bool { return false } -type httpErrorConfig struct { - Routes RouteList `json:"routes,omitempty"` - // TODO: some way to configure the logging of errors, probably? standardize - // the logging configuration first. +// AutoHTTPSConfig is used to disable automatic HTTPS +// or certain aspects of it for a specific server. +type AutoHTTPSConfig struct { + // If true, automatic HTTPS will be entirely disabled. + Disabled bool `json:"disable,omitempty"` + + // If true, only automatic HTTP->HTTPS redirects will + // be disabled. + DisableRedir bool `json:"disable_redirects,omitempty"` + + // Hosts/domain names listed here will not be included + // in automatic HTTPS (they will not have certificates + // loaded nor redirects applied). + Skip []string `json:"skip,omitempty"` } -const ServerCtxKey caddy.CtxKey = "server" +// HostSkipped returns true if name is supposed to be skipped +// when setting up automatic HTTPS. +func (ahc AutoHTTPSConfig) HostSkipped(name string) bool { + for _, n := range ahc.Skip { + if name == n { + return true + } + } + return false +} -// TableCtxKey is the context key for the request's variable table. TODO: implement this -const TableCtxKey caddy.CtxKey = "table" +// HTTPErrorConfig determines how to handle errors +// from the HTTP handlers. +type HTTPErrorConfig struct { + Routes RouteList `json:"routes,omitempty"` +} + +// Context keys for HTTP request context values. +const ( + // For referencing the server instance + ServerCtxKey caddy.CtxKey = "server" + + // For the request's variable table (TODO: implement this) + TableCtxKey caddy.CtxKey = "table" +)