diff --git a/cmd/pomerium/main.go b/cmd/pomerium/main.go index 3a265ff1a..8dcd50eb1 100644 --- a/cmd/pomerium/main.go +++ b/cmd/pomerium/main.go @@ -113,17 +113,23 @@ func main() { KeyFile: mainOpts.KeyFile, } - // redirect http to https - srv := &http.Server{ - ReadTimeout: 5 * time.Second, - WriteTimeout: 5 * time.Second, - Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Connection", "close") - url := fmt.Sprintf("https://%s%s", r.Host, r.URL.String()) - http.Redirect(w, r, url, http.StatusMovedPermanently) - }), + if mainOpts.HTTPRedirectAddr != "" { + // stand up another http server that just redirect HTTP to HTTPS traffic + srv := &http.Server{ + Addr: mainOpts.HTTPRedirectAddr, + ReadTimeout: 5 * time.Second, + WriteTimeout: 5 * time.Second, + Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Connection", "close") + url := fmt.Sprintf("https://%s%s", urlutil.StripPort(r.Host), r.URL.String()) + http.Redirect(w, r, url, http.StatusMovedPermanently) + }), + } + log.Info().Str("Addr", mainOpts.HTTPRedirectAddr).Msg("cmd/pomerium: http redirect server started") + go func() { log.Fatal().Err(srv.ListenAndServe()).Msg("cmd/pomerium: http server") }() + } else { + log.Debug().Msg("cmd/pomerium: http redirect server not started") } - go func() { log.Fatal().Err(srv.ListenAndServe()).Msg("cmd/pomerium: http server") }() log.Fatal().Err(https.ListenAndServeTLS(httpOpts, topMux, grpcServer)).Msg("cmd/pomerium: https server") diff --git a/cmd/pomerium/options.go b/cmd/pomerium/options.go index 8c7689901..4abf7334e 100644 --- a/cmd/pomerium/options.go +++ b/cmd/pomerium/options.go @@ -38,6 +38,11 @@ type Options struct { // CertFile and KeyFile specifies the TLS certificates to use. CertFile string `envconfig:"CERTIFICATE_FILE"` KeyFile string `envconfig:"CERTIFICATE_KEY_FILE"` + + // HttpRedirectAddr, if set, specifies the host and port to run the HTTP + // to HTTPS redirect server on. For example, ":http" would start a server + // on port 80. If empty, no redirect server is started. + HTTPRedirectAddr string `envconfig:"HTTP_REDIRECT_ADDR"` } var defaultOptions = &Options{ diff --git a/docs/reference/readme.md b/docs/reference/readme.md index 53064312b..0dbcf53a0 100644 --- a/docs/reference/readme.md +++ b/docs/reference/readme.md @@ -31,6 +31,17 @@ Service mode sets the pomerium service(s) to run. If testing, you may want to se Address specifies the host and port to serve HTTPS and gRPC requests from. If empty, `:https`/`:443` is used. + +### HTTP Redirect Address + +- Environmental Variable: `HTTP_REDIRECT_ADDR` +- Type: `string` +- Default: `` (no serevr is started) +- Example: `:80` +- Optional + +If set, the HTTP Redirect Address specifies the host and port to redirect http to https traffic on. If not set, no redirect server is started. + ### Shared Secret - Environmental Variable: `SHARED_SECRET` diff --git a/internal/urlutil/url.go b/internal/urlutil/url.go index 6182ddc18..7f5d8caa9 100644 --- a/internal/urlutil/url.go +++ b/internal/urlutil/url.go @@ -2,6 +2,11 @@ package urlutil // import "github.com/pomerium/pomerium/internal/urlutil" import "strings" +// StripPort returns a host, without any port number. +// +// If Host is an IPv6 literal with a port number, Hostname returns the +// IPv6 literal without the square brackets. IPv6 literals may include +// a zone identifier. func StripPort(hostport string) string { colon := strings.IndexByte(hostport, ':') if colon == -1 {