cmd/pomerium: redirect http and add hsts headers (#92)

This commit is contained in:
Bobby DeSimone 2019-04-24 13:29:11 -07:00 committed by GitHub
parent fbe1cae482
commit 857b9e5773
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 24 additions and 29 deletions

View file

@ -16,11 +16,13 @@ import (
"github.com/pomerium/pomerium/internal/version" "github.com/pomerium/pomerium/internal/version"
) )
// securityHeaders corresponds to HTTP response headers that help to protect against protocol // securityHeaders corresponds to HTTP response headers that help to protect
// downgrade attacks and cookie hijacking. // against protocol downgrade attacks and cookie hijacking.
//
// https://www.owasp.org/index.php/OWASP_Secure_Headers_Project#tab=Headers // https://www.owasp.org/index.php/OWASP_Secure_Headers_Project#tab=Headers
// https://https.cio.gov/hsts/
var securityHeaders = map[string]string{ var securityHeaders = map[string]string{
"Strict-Transport-Security": "max-age=31536000", "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload",
"X-Frame-Options": "DENY", "X-Frame-Options": "DENY",
"X-Content-Type-Options": "nosniff", "X-Content-Type-Options": "nosniff",
"X-XSS-Protection": "1; mode=block", "X-XSS-Protection": "1; mode=block",

View file

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"os" "os"
"time"
"google.golang.org/grpc" "google.golang.org/grpc"
@ -102,6 +103,7 @@ func main() {
if proxyService != nil { if proxyService != nil {
topMux.Handle("/", proxyService.Handler()) topMux.Handle("/", proxyService.Handler())
} }
httpOpts := &https.Options{ httpOpts := &https.Options{
Addr: mainOpts.Addr, Addr: mainOpts.Addr,
Cert: mainOpts.Cert, Cert: mainOpts.Cert,
@ -110,6 +112,18 @@ func main() {
KeyFile: mainOpts.KeyFile, KeyFile: mainOpts.KeyFile,
} }
log.Fatal().Err(https.ListenAndServeTLS(httpOpts, topMux, grpcServer)).Msg("cmd/pomerium: https serve failure") // 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)
}),
}
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")
} }

View file

@ -129,27 +129,6 @@ func ValidateHost(mux map[string]http.Handler) func(next http.Handler) http.Hand
} }
} }
// RequireHTTPS reroutes a HTTP request to HTTPS
// todo(bdd) : this is unreliable unless behind another reverser proxy
// todo(bdd) : header age seems extreme
func RequireHTTPS(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Strict-Transport-Security", "max-age=31536000")
// todo(bdd) : scheme and x-forwarded-proto cannot be trusted if not behind another load balancer
if (r.URL.Scheme == "http" && r.Header.Get("X-Forwarded-Proto") == "http") || &r.TLS == nil {
dest := &url.URL{
Scheme: "https",
Host: r.Host,
Path: r.URL.Path,
RawQuery: r.URL.RawQuery,
}
http.Redirect(w, r, dest.String(), http.StatusMovedPermanently)
return
}
next.ServeHTTP(w, r)
})
}
// Healthcheck endpoint middleware useful to setting up a path like // Healthcheck endpoint middleware useful to setting up a path like
// `/ping` that load balancers or uptime testing external services // `/ping` that load balancers or uptime testing external services
// can make a request before hitting any routes. It's also convenient // can make a request before hitting any routes. It's also convenient

View file

@ -24,9 +24,10 @@ var (
) )
var securityHeaders = map[string]string{ var securityHeaders = map[string]string{
"X-Content-Type-Options": "nosniff", "X-Content-Type-Options": "nosniff",
"X-Frame-Options": "SAMEORIGIN", "X-Frame-Options": "SAMEORIGIN",
"X-XSS-Protection": "1; mode=block", "X-XSS-Protection": "1; mode=block",
"Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", // 1 year
} }
// StateParameter holds the redirect id along with the session id. // StateParameter holds the redirect id along with the session id.
@ -62,7 +63,6 @@ func (p *Proxy) Handler() http.Handler {
Msg("proxy: request") Msg("proxy: request")
})) }))
c = c.Append(middleware.SetHeaders(securityHeaders)) c = c.Append(middleware.SetHeaders(securityHeaders))
c = c.Append(middleware.RequireHTTPS)
c = c.Append(middleware.ForwardedAddrHandler("fwd_ip")) c = c.Append(middleware.ForwardedAddrHandler("fwd_ip"))
c = c.Append(middleware.RemoteAddrHandler("ip")) c = c.Append(middleware.RemoteAddrHandler("ip"))
c = c.Append(middleware.UserAgentHandler("user_agent")) c = c.Append(middleware.UserAgentHandler("user_agent"))