add --proxy-host-header option
This commit is contained in:
parent
24ef555547
commit
263e16eeea
@ -72,6 +72,7 @@ Usage of google_auth_proxy:
|
|||||||
-htpasswd-file="": additionally authenticate against a htpasswd file. Entries must be created with "htpasswd -s" for SHA encryption
|
-htpasswd-file="": additionally authenticate against a htpasswd file. Entries must be created with "htpasswd -s" for SHA encryption
|
||||||
-http-address="127.0.0.1:4180": [http://]<addr>:<port> or unix://<path> to listen on for HTTP clients
|
-http-address="127.0.0.1:4180": [http://]<addr>:<port> or unix://<path> to listen on for HTTP clients
|
||||||
-pass-basic-auth=true: pass HTTP Basic Auth, X-Forwarded-User and X-Forwarded-Email information to upstream
|
-pass-basic-auth=true: pass HTTP Basic Auth, X-Forwarded-User and X-Forwarded-Email information to upstream
|
||||||
|
-pass-host-header=true: pass the request Host Header to upstream
|
||||||
-redirect-url="": the OAuth Redirect URL. ie: "https://internalapp.yourcompany.com/oauth2/callback"
|
-redirect-url="": the OAuth Redirect URL. ie: "https://internalapp.yourcompany.com/oauth2/callback"
|
||||||
-skip-auth-regex=: bypass authentication for requests path's that match (may be given multiple times)
|
-skip-auth-regex=: bypass authentication for requests path's that match (may be given multiple times)
|
||||||
-upstream=: the http url(s) of the upstream endpoint. If multiple, routing is based on path
|
-upstream=: the http url(s) of the upstream endpoint. If multiple, routing is based on path
|
||||||
|
@ -14,6 +14,9 @@
|
|||||||
|
|
||||||
## pass HTTP Basic Auth, X-Forwarded-User and X-Forwarded-Email information to upstream
|
## pass HTTP Basic Auth, X-Forwarded-User and X-Forwarded-Email information to upstream
|
||||||
# pass_basic_auth = true
|
# pass_basic_auth = true
|
||||||
|
## pass the request Host Header to upstream
|
||||||
|
## when disabled the upstream Host is used as the Host Header
|
||||||
|
# pass_host_header = true
|
||||||
|
|
||||||
## Google Apps Domains to allow authentication for
|
## Google Apps Domains to allow authentication for
|
||||||
# google_apps_domains = [
|
# google_apps_domains = [
|
||||||
|
1
main.go
1
main.go
@ -29,6 +29,7 @@ func main() {
|
|||||||
flagSet.String("redirect-url", "", "the OAuth Redirect URL. ie: \"https://internalapp.yourcompany.com/oauth2/callback\"")
|
flagSet.String("redirect-url", "", "the OAuth Redirect URL. ie: \"https://internalapp.yourcompany.com/oauth2/callback\"")
|
||||||
flagSet.Var(&upstreams, "upstream", "the http url(s) of the upstream endpoint. If multiple, routing is based on path")
|
flagSet.Var(&upstreams, "upstream", "the http url(s) of the upstream endpoint. If multiple, routing is based on path")
|
||||||
flagSet.Bool("pass-basic-auth", true, "pass HTTP Basic Auth, X-Forwarded-User and X-Forwarded-Email information to upstream")
|
flagSet.Bool("pass-basic-auth", true, "pass HTTP Basic Auth, X-Forwarded-User and X-Forwarded-Email information to upstream")
|
||||||
|
flagSet.Bool("pass-host-header", true, "pass the request Host Header to upstream")
|
||||||
flagSet.Var(&skipAuthRegex, "skip-auth-regex", "bypass authentication for requests path's that match (may be given multiple times)")
|
flagSet.Var(&skipAuthRegex, "skip-auth-regex", "bypass authentication for requests path's that match (may be given multiple times)")
|
||||||
|
|
||||||
flagSet.Var(&googleAppsDomains, "google-apps-domain", "authenticate against the given Google apps domain (may be given multiple times)")
|
flagSet.Var(&googleAppsDomains, "google-apps-domain", "authenticate against the given Google apps domain (may be given multiple times)")
|
||||||
|
@ -47,13 +47,14 @@ type OauthProxy struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewReverseProxy(target *url.URL) (proxy *httputil.ReverseProxy) {
|
func NewReverseProxy(target *url.URL) (proxy *httputil.ReverseProxy) {
|
||||||
proxy = httputil.NewSingleHostReverseProxy(target)
|
return httputil.NewSingleHostReverseProxy(target)
|
||||||
director := proxy.Director
|
}
|
||||||
proxy.Director = func(req *http.Request) {
|
func setProxyUpstreamHostHeader(proxy *httputil.ReverseProxy, target *url.URL) {
|
||||||
director(req)
|
director := proxy.Director
|
||||||
req.Host = target.Host
|
proxy.Director = func(req *http.Request) {
|
||||||
}
|
director(req)
|
||||||
return proxy
|
req.Host = target.Host
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewOauthProxy(opts *Options, validator func(string) bool) *OauthProxy {
|
func NewOauthProxy(opts *Options, validator func(string) bool) *OauthProxy {
|
||||||
@ -64,7 +65,11 @@ func NewOauthProxy(opts *Options, validator func(string) bool) *OauthProxy {
|
|||||||
path := u.Path
|
path := u.Path
|
||||||
u.Path = ""
|
u.Path = ""
|
||||||
log.Printf("mapping path %q => upstream %q", path, u)
|
log.Printf("mapping path %q => upstream %q", path, u)
|
||||||
serveMux.Handle(path, NewReverseProxy(u))
|
proxy := NewReverseProxy(u)
|
||||||
|
if !opts.PassHostHeader {
|
||||||
|
setProxyUpstreamHostHeader(proxy, u)
|
||||||
|
}
|
||||||
|
serveMux.Handle(path, proxy)
|
||||||
}
|
}
|
||||||
for _, u := range opts.CompiledRegex {
|
for _, u := range opts.CompiledRegex {
|
||||||
log.Printf("compiled skip-auth-regex => %q", u)
|
log.Printf("compiled skip-auth-regex => %q", u)
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
func TestNewReverseProxy(t *testing.T) {
|
func TestNewReverseProxy(t *testing.T) {
|
||||||
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.WriteHeader(200)
|
w.WriteHeader(200)
|
||||||
hostname, _, _ := net.SplitHostPort(r.Host)
|
hostname, _, _ := net.SplitHostPort(r.Host)
|
||||||
w.Write([]byte(hostname))
|
w.Write([]byte(hostname))
|
||||||
}))
|
}))
|
||||||
defer backend.Close()
|
defer backend.Close()
|
||||||
@ -24,6 +24,7 @@ func TestNewReverseProxy(t *testing.T) {
|
|||||||
proxyURL, _ := url.Parse(backendURL.Scheme + "://" + backendHost + "/")
|
proxyURL, _ := url.Parse(backendURL.Scheme + "://" + backendHost + "/")
|
||||||
|
|
||||||
proxyHandler := NewReverseProxy(proxyURL)
|
proxyHandler := NewReverseProxy(proxyURL)
|
||||||
|
setProxyUpstreamHostHeader(proxyHandler, proxyURL)
|
||||||
frontend := httptest.NewServer(proxyHandler)
|
frontend := httptest.NewServer(proxyHandler)
|
||||||
defer frontend.Close()
|
defer frontend.Close()
|
||||||
|
|
||||||
|
39
options.go
39
options.go
@ -10,22 +10,26 @@ import (
|
|||||||
|
|
||||||
// Configuration Options that can be set by Command Line Flag, or Config File
|
// Configuration Options that can be set by Command Line Flag, or Config File
|
||||||
type Options struct {
|
type Options struct {
|
||||||
HttpAddress string `flag:"http-address" cfg:"http_address"`
|
HttpAddress string `flag:"http-address" cfg:"http_address"`
|
||||||
RedirectUrl string `flag:"redirect-url" cfg:"redirect_url"`
|
RedirectUrl string `flag:"redirect-url" cfg:"redirect_url"`
|
||||||
ClientID string `flag:"client-id" cfg:"client_id" env:"GOOGLE_AUTH_PROXY_CLIENT_ID"`
|
ClientID string `flag:"client-id" cfg:"client_id" env:"GOOGLE_AUTH_PROXY_CLIENT_ID"`
|
||||||
ClientSecret string `flag:"client-secret" cfg:"client_secret" env:"GOOGLE_AUTH_PROXY_CLIENT_SECRET"`
|
ClientSecret string `flag:"client-secret" cfg:"client_secret" env:"GOOGLE_AUTH_PROXY_CLIENT_SECRET"`
|
||||||
PassBasicAuth bool `flag:"pass-basic-auth" cfg:"pass_basic_auth"`
|
|
||||||
HtpasswdFile string `flag:"htpasswd-file" cfg:"htpasswd_file"`
|
AuthenticatedEmailsFile string `flag:"authenticated-emails-file" cfg:"authenticated_emails_file"`
|
||||||
DisplayHtpasswdForm bool `flag:"display-htpasswd-form" cfg:"display_htpasswd_form"`
|
GoogleAppsDomains []string `flag:"google-apps-domain" cfg:"google_apps_domains"`
|
||||||
CookieSecret string `flag:"cookie-secret" cfg:"cookie_secret" env:"GOOGLE_AUTH_PROXY_COOKIE_SECRET"`
|
HtpasswdFile string `flag:"htpasswd-file" cfg:"htpasswd_file"`
|
||||||
CookieDomain string `flag:"cookie-domain" cfg:"cookie_domain" env:"GOOGLE_AUTH_PROXY_COOKIE_DOMAIN"`
|
DisplayHtpasswdForm bool `flag:"display-htpasswd-form" cfg:"display_htpasswd_form"`
|
||||||
CookieExpire time.Duration `flag:"cookie-expire" cfg:"cookie_expire" env:"GOOGLE_AUTH_PROXY_COOKIE_EXPIRE"`
|
|
||||||
CookieHttpsOnly bool `flag:"cookie-https-only" cfg:"cookie_https_only"`
|
CookieSecret string `flag:"cookie-secret" cfg:"cookie_secret" env:"GOOGLE_AUTH_PROXY_COOKIE_SECRET"`
|
||||||
CookieHttpOnly bool `flag:"cookie-httponly" cfg:"cookie_httponly"`
|
CookieDomain string `flag:"cookie-domain" cfg:"cookie_domain" env:"GOOGLE_AUTH_PROXY_COOKIE_DOMAIN"`
|
||||||
AuthenticatedEmailsFile string `flag:"authenticated-emails-file" cfg:"authenticated_emails_file"`
|
CookieExpire time.Duration `flag:"cookie-expire" cfg:"cookie_expire" env:"GOOGLE_AUTH_PROXY_COOKIE_EXPIRE"`
|
||||||
GoogleAppsDomains []string `flag:"google-apps-domain" cfg:"google_apps_domains"`
|
CookieHttpsOnly bool `flag:"cookie-https-only" cfg:"cookie_https_only"`
|
||||||
Upstreams []string `flag:"upstream" cfg:"upstreams"`
|
CookieHttpOnly bool `flag:"cookie-httponly" cfg:"cookie_httponly"`
|
||||||
SkipAuthRegex []string `flag:"skip-auth-regex" cfg:"skip_auth_regex"`
|
|
||||||
|
Upstreams []string `flag:"upstream" cfg:"upstreams"`
|
||||||
|
SkipAuthRegex []string `flag:"skip-auth-regex" cfg:"skip_auth_regex"`
|
||||||
|
PassBasicAuth bool `flag:"pass-basic-auth" cfg:"pass_basic_auth"`
|
||||||
|
PassHostHeader bool `flag:"pass-host-header" cfg:"pass_host_header"`
|
||||||
|
|
||||||
// internal values that are set after config validation
|
// internal values that are set after config validation
|
||||||
redirectUrl *url.URL
|
redirectUrl *url.URL
|
||||||
@ -39,8 +43,9 @@ func NewOptions() *Options {
|
|||||||
DisplayHtpasswdForm: true,
|
DisplayHtpasswdForm: true,
|
||||||
CookieHttpsOnly: true,
|
CookieHttpsOnly: true,
|
||||||
CookieHttpOnly: true,
|
CookieHttpOnly: true,
|
||||||
PassBasicAuth: true,
|
|
||||||
CookieExpire: time.Duration(168) * time.Hour,
|
CookieExpire: time.Duration(168) * time.Hour,
|
||||||
|
PassBasicAuth: true,
|
||||||
|
PassHostHeader: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"net/url"
|
|
||||||
|
|
||||||
"github.com/bmizerany/assert"
|
"github.com/bmizerany/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func testOptions() (*Options) {
|
func testOptions() *Options {
|
||||||
o := NewOptions()
|
o := NewOptions()
|
||||||
o.Upstreams = append(o.Upstreams, "http://127.0.0.1:8080/")
|
o.Upstreams = append(o.Upstreams, "http://127.0.0.1:8080/")
|
||||||
o.CookieSecret = "foobar"
|
o.CookieSecret = "foobar"
|
||||||
@ -17,7 +17,7 @@ func testOptions() (*Options) {
|
|||||||
return o
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
func errorMsg(msgs []string)(string) {
|
func errorMsg(msgs []string) string {
|
||||||
result := make([]string, 0)
|
result := make([]string, 0)
|
||||||
result = append(result, "Invalid configuration:")
|
result = append(result, "Invalid configuration:")
|
||||||
result = append(result, msgs...)
|
result = append(result, msgs...)
|
||||||
|
Loading…
Reference in New Issue
Block a user