From 99590c044654fd3bff1992d651a2fa56f4074f5a Mon Sep 17 00:00:00 2001 From: brunton Date: Sun, 11 Jun 2017 16:40:39 -0400 Subject: [PATCH 1/4] adding in some proxyification adjustments --- underpants.go | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/underpants.go b/underpants.go index e1de201..858d0b7 100644 --- a/underpants.go +++ b/underpants.go @@ -98,6 +98,10 @@ type conf struct { // A special group, `*`, may be specified which allows any authenticated // user. AllowedGroups []string `json:"allowed-groups"` + + // Fix the host header on the requst to the backend proxied service to match + // what came in through the front door. + FixHost bool } } @@ -219,6 +223,9 @@ type disp struct { // The groups which may access this backend. groups []string + + // if the host header is to be fixed for this dispatcher or not + fixhost bool } // Construct a URL to the oauth provider that with carry the provided URL as state @@ -319,6 +326,10 @@ func serveHttpProxy(d *disp, w http.ResponseWriter, r *http.Request) { br.Header.Add("Underpants-Email", url.QueryEscape(u.Email)) br.Header.Add("Underpants-Name", url.QueryEscape(u.Name)) + if d.fixhost { + br.Host = d.host + } + bp, err := http.DefaultTransport.RoundTrip(br) if err != nil { panic(err) @@ -434,6 +445,9 @@ func addSecurityHeaders(c *conf, next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if c.HasCerts() { w.Header().Add("Strict-Transport-Security", "max-age=16070400; includeSubDomains") + r.Header.Add("X-Forwarded-Proto", "https") + } else { + r.Header.Add("X-Forwarded-Proto", "http") } w.Header().Add("X-Frame-Options", "SAMEORIGIN") @@ -470,12 +484,13 @@ func setup(c *conf, port int) (*http.ServeMux, error) { } m.Handle(fmt.Sprintf("%s/", host), addSecurityHeaders(c, &disp{ - config: c, - route: &route{host: uri.Host, scheme: uri.Scheme}, - host: host, - key: key, - oauth: oc, - groups: r.AllowedGroups, + config: c, + route: &route{host: uri.Host, scheme: uri.Scheme}, + host: host, + key: key, + oauth: oc, + groups: r.AllowedGroups, + fixhost: r.FixHost, })) } From f31cdf29f86a5636fa221b2e1604ee9339059180 Mon Sep 17 00:00:00 2001 From: brunton Date: Sun, 11 Jun 2017 17:00:47 -0400 Subject: [PATCH 2/4] updated X-Forwarded-Proto header setting to check if there is already one there. in case underpants is part of a request chain. --- underpants.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/underpants.go b/underpants.go index 858d0b7..af10354 100644 --- a/underpants.go +++ b/underpants.go @@ -443,11 +443,14 @@ func hostOf(name string, port int) string { func addSecurityHeaders(c *conf, next http.Handler) http.Handler { if c.AddSecurityHeaders { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var proto = "http" if c.HasCerts() { w.Header().Add("Strict-Transport-Security", "max-age=16070400; includeSubDomains") - r.Header.Add("X-Forwarded-Proto", "https") - } else { - r.Header.Add("X-Forwarded-Proto", "http") + proto = "https" + } + + if r.Header.Get("X-Forwarded-Proto") != "" { + r.Header.Add("X-Forwarded-Proto", proto) } w.Header().Add("X-Frame-Options", "SAMEORIGIN") From 3edd9ca79e038c5886737a3686b57b7b1d52bd6b Mon Sep 17 00:00:00 2001 From: brunton Date: Wed, 14 Jun 2017 13:42:22 -0400 Subject: [PATCH 3/4] fixed typo --- underpants.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/underpants.go b/underpants.go index af10354..d5b5e4b 100644 --- a/underpants.go +++ b/underpants.go @@ -99,7 +99,7 @@ type conf struct { // user. AllowedGroups []string `json:"allowed-groups"` - // Fix the host header on the requst to the backend proxied service to match + // Fix the host header on the request to the backend proxied service to match // what came in through the front door. FixHost bool } @@ -480,6 +480,7 @@ func setup(c *conf, port int) (*http.ServeMux, error) { // setup routes oc := oauthConfig(c, port) for _, r := range c.Routes { + fmt.Printf("setting up for host : %s\n", r.From) host := hostOf(r.From, port) uri, err := url.Parse(r.To) if err != nil { @@ -503,6 +504,7 @@ func setup(c *conf, port int) (*http.ServeMux, error) { // setup admin m.Handle("/", addSecurityHeadersFunc(c, func(w http.ResponseWriter, r *http.Request) { + fmt.Printf("host is : %s\n", r.Host) switch r.URL.Path { case "/": u := userFrom(r, key) From e79c7ebd68ecedff372519a8f797f3848a111739 Mon Sep 17 00:00:00 2001 From: brunton Date: Sat, 8 Jul 2017 15:53:45 -0400 Subject: [PATCH 4/4] updates based on PR feedback and update to README explaining what the host flag is for. --- README.md | 3 +++ underpants.go | 23 +++++++++++------------ underpants.sample.host.json | 16 ++++++++++++++++ 3 files changed, 30 insertions(+), 12 deletions(-) create mode 100644 underpants.sample.host.json diff --git a/README.md b/README.md index ea98d9e..115666f 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,9 @@ are not a member of one of the authorized groups by default. The special `*` group can be used to allow any authenticated user access to the route. See `underpants.sample.groups.json` for a configuration sample. +If your backend is a build system or some other platform that will build URLs on the fly based on the request and needs +the original `Host` header add in the `retain-host-header` flag and it will be passed through. + ## Running Just run it; it's an executable. diff --git a/underpants.go b/underpants.go index d5b5e4b..aba3ca2 100644 --- a/underpants.go +++ b/underpants.go @@ -101,7 +101,7 @@ type conf struct { // Fix the host header on the request to the backend proxied service to match // what came in through the front door. - FixHost bool + RetainHost bool `json:"retain-host-header"` } } @@ -225,7 +225,7 @@ type disp struct { groups []string // if the host header is to be fixed for this dispatcher or not - fixhost bool + RetainHost bool } // Construct a URL to the oauth provider that with carry the provided URL as state @@ -326,7 +326,7 @@ func serveHttpProxy(d *disp, w http.ResponseWriter, r *http.Request) { br.Header.Add("Underpants-Email", url.QueryEscape(u.Email)) br.Header.Add("Underpants-Name", url.QueryEscape(u.Name)) - if d.fixhost { + if d.RetainHost { br.Host = d.host } @@ -449,7 +449,7 @@ func addSecurityHeaders(c *conf, next http.Handler) http.Handler { proto = "https" } - if r.Header.Get("X-Forwarded-Proto") != "" { + if r.Header.Get("X-Forwarded-Proto") == "" { r.Header.Add("X-Forwarded-Proto", proto) } @@ -480,7 +480,6 @@ func setup(c *conf, port int) (*http.ServeMux, error) { // setup routes oc := oauthConfig(c, port) for _, r := range c.Routes { - fmt.Printf("setting up for host : %s\n", r.From) host := hostOf(r.From, port) uri, err := url.Parse(r.To) if err != nil { @@ -488,13 +487,13 @@ func setup(c *conf, port int) (*http.ServeMux, error) { } m.Handle(fmt.Sprintf("%s/", host), addSecurityHeaders(c, &disp{ - config: c, - route: &route{host: uri.Host, scheme: uri.Scheme}, - host: host, - key: key, - oauth: oc, - groups: r.AllowedGroups, - fixhost: r.FixHost, + config: c, + route: &route{host: uri.Host, scheme: uri.Scheme}, + host: host, + key: key, + oauth: oc, + groups: r.AllowedGroups, + RetainHost: r.RetainHost, })) } diff --git a/underpants.sample.host.json b/underpants.sample.host.json new file mode 100644 index 0000000..ec03219 --- /dev/null +++ b/underpants.sample.host.json @@ -0,0 +1,16 @@ +{ + "host" : "underpants.company.com", + "oauth" : { + "domain" : "company.com", + "client-id" : "oauth-client-id", + "client-secret" : "oauth-client-secret" + }, + "use-strict-security-headers": true, + "routes" : [ + { + "from" : "builder.company.com", + "to" : "http://localhost:8080", + "retain-host-header" : true + } + ] +}