proxy: make http headers configurable (#108)

- http headers can be disabled via an env config
- http headers can be configured by k/v map env config
- pomerium/envconfig updated to use original syntax v1.5.0
- go.mod / go.sum patches updated
This commit is contained in:
Bobby DeSimone 2019-05-07 12:05:25 -07:00 committed by GitHub
parent 0086fa05f8
commit 5e37c29dfe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 79 additions and 43 deletions

View file

@ -33,7 +33,6 @@ 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. Address specifies the host and port to serve HTTPS and gRPC requests from. If empty, `:https`/`:443` is used.
### HTTP Redirect Address ### HTTP Redirect Address
- Environmental Variable: `HTTP_REDIRECT_ADDR` - Environmental Variable: `HTTP_REDIRECT_ADDR`
@ -41,7 +40,7 @@ Address specifies the host and port to serve HTTPS and gRPC requests from. If em
- Example: `:80`, `:http`, `:8080` - Example: `:80`, `:http`, `:8080`
- Optional - Optional
If set, the HTTP Redirect Address specifies the host and port to redirect http to https traffic on. If unset, no redirect server is started. If set, the HTTP Redirect Address specifies the host and port to redirect http to https traffic on. If unset, no redirect server is started.
### Shared Secret ### Shared Secret
@ -206,7 +205,7 @@ Authenticate Service URL is the externally accessible URL for the authenticate s
- Optional - Optional
- Example: `pomerium-authenticate-service.pomerium.svc.cluster.local` - Example: `pomerium-authenticate-service.pomerium.svc.cluster.local`
Authenticate Internal Service URL is the internally routed dns name of the authenticate service. This setting is typically used with load balancers that do not gRPC, thus allowing you to specify an internally accessible name. Authenticate Internal Service URL is the internally routed dns name of the authenticate service. This setting is typically used with load balancers that do not gRPC, thus allowing you to specify an internally accessible name.
### Authorize Service URL ### Authorize Service URL
@ -215,9 +214,9 @@ Authenticate Internal Service URL is the internally routed dns name of the authe
- Required - Required
- Example: `https://access.corp.example.com` or `pomerium-authorize-service.pomerium.svc.cluster.local` - Example: `https://access.corp.example.com` or `pomerium-authorize-service.pomerium.svc.cluster.local`
Authorize Service URL is the location of the internally accessible authorize service. NOTE: Unlike authenticate, authorize has no publicly accessible http handlers so this setting is purely for gRPC communication. Authorize Service URL is the location of the internally accessible authorize service. NOTE: Unlike authenticate, authorize has no publicly accessible http handlers so this setting is purely for gRPC communication.
If your load balancer does not support gRPC pass-through you'll need to set this value to an internally routable location (`pomerium-authorize-service.pomerium.svc.cluster.local`) instead of an externally routable one (`https://access.corp.example.com`). If your load balancer does not support gRPC pass-through you'll need to set this value to an internally routable location (`pomerium-authorize-service.pomerium.svc.cluster.local`) instead of an externally routable one (`https://access.corp.example.com`).
### Override Certificate Name ### Override Certificate Name
@ -236,6 +235,19 @@ When Authenticate Internal Service Address is set, secure service communication
Certificate Authority is set when behind-the-ingress service communication uses self-signed certificates. Be sure to include the intermediary certificate. Certificate Authority is set when behind-the-ingress service communication uses self-signed certificates. Be sure to include the intermediary certificate.
### Headers
- Environmental Variable: `HEADERS`
- Type: map of `strings` key value pairs
- Example: `X-Content-Type-Options:nosniff,X-Frame-Options:SAMEORIGIN`
- To disable: `disable:true`
Headers specifies a mapping of [HTTP Header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers) to be added to proxied requests. *Nota bene* Downstream application headers will be overwritten by Pomerium's headers on conflict.
By default, conservative [secure HTTP headers](https://www.owasp.org/index.php/OWASP_Secure_Headers_Project) are set.
![pomerium security headers](./security-headers.png)
[base64 encoded]: https://en.wikipedia.org/wiki/Base64 [base64 encoded]: https://en.wikipedia.org/wiki/Base64
[environmental variables]: https://en.wikipedia.org/wiki/Environment_variable [environmental variables]: https://en.wikipedia.org/wiki/Environment_variable
[identity provider]: ./identity-providers.md [identity provider]: ./identity-providers.md

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

9
go.mod
View file

@ -5,8 +5,8 @@ go 1.12
require ( require (
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/golang/mock v1.2.0 github.com/golang/mock v1.2.0
github.com/golang/protobuf v1.3.0 github.com/golang/protobuf v1.3.1
github.com/pomerium/envconfig v1.4.0 github.com/pomerium/envconfig v1.5.0
github.com/pomerium/go-oidc v2.0.0+incompatible github.com/pomerium/go-oidc v2.0.0+incompatible
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect
github.com/rs/zerolog v1.12.0 github.com/rs/zerolog v1.12.0
@ -14,8 +14,9 @@ require (
golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25 golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25
golang.org/x/net v0.0.0-20190228165749-92fc7df08ae7 golang.org/x/net v0.0.0-20190228165749-92fc7df08ae7
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421
golang.org/x/text v0.3.2 // indirect
google.golang.org/api v0.1.0 google.golang.org/api v0.1.0
google.golang.org/grpc v1.19.0 google.golang.org/grpc v1.19.1
gopkg.in/square/go-jose.v2 v2.3.0 gopkg.in/square/go-jose.v2 v2.3.1
gopkg.in/yaml.v2 v2.2.2 gopkg.in/yaml.v2 v2.2.2
) )

19
go.sum
View file

@ -17,8 +17,8 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk= github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.0 h1:kbxbvI4Un1LUWKxufD+BiE6AEExYYgkQLQmLFqA1LFk= github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
@ -26,8 +26,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pomerium/envconfig v1.4.0 h1:o+WY/E/9M4fh0nDX7oJodU7N9p1hcHPsTnNLYjlbQA8= github.com/pomerium/envconfig v1.5.0 h1:OeYS/p6AUxKFqCZHM5BG7pUb0m3MkaC1ZhRLPTHbk8g=
github.com/pomerium/envconfig v1.4.0/go.mod h1:1Kz8Ca8PhJDtLYqgvbDZGn6GsJCvrT52SxQ3sPNJkDc= github.com/pomerium/envconfig v1.5.0/go.mod h1:1Kz8Ca8PhJDtLYqgvbDZGn6GsJCvrT52SxQ3sPNJkDc=
github.com/pomerium/go-oidc v2.0.0+incompatible h1:gVvG/ExWsHQqatV+uceROnGmbVYF44mDNx5nayBhC0o= github.com/pomerium/go-oidc v2.0.0+incompatible h1:gVvG/ExWsHQqatV+uceROnGmbVYF44mDNx5nayBhC0o=
github.com/pomerium/go-oidc v2.0.0+incompatible/go.mod h1:DRsGVw6MOgxbfq4Y57jKOE8lbEfayxeiY0A8/4vxjBM= github.com/pomerium/go-oidc v2.0.0+incompatible/go.mod h1:DRsGVw6MOgxbfq4Y57jKOE8lbEfayxeiY0A8/4vxjBM=
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU= github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU=
@ -67,7 +67,10 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.1.0 h1:K6z2u68e86TPdSdefXdzvXgR1zEMa+459vBSfWYAZkI= google.golang.org/api v0.1.0 h1:K6z2u68e86TPdSdefXdzvXgR1zEMa+459vBSfWYAZkI=
@ -83,12 +86,12 @@ google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8= google.golang.org/grpc v1.19.1 h1:TrBcJ1yqAl1G++wO39nD/qtgpsW9/1+QGrluyMGEYgM=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/square/go-jose.v2 v2.3.0 h1:nLzhkFyl5bkblqYBoiWJUt5JkWOzmiaBtCxdJAqJd3U= gopkg.in/square/go-jose.v2 v2.3.1 h1:SK5KegNXmKmqE342YYN2qPHEnUYeoMiXXl1poUlI+o4=
gopkg.in/square/go-jose.v2 v2.3.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View file

@ -1,23 +1,23 @@
- from: httpbin.corp.beyondperimeter.com - from: httpbin.corp.beyondperimeter.com
to: http://httpbin to: http://httpbin
allowed_domains: allowed_domains:
- pomerium.io - pomerium.io
- from: external-httpbin.corp.beyondperimeter.com - from: external-httpbin.corp.beyondperimeter.com
to: httpbin.org to: httpbin.org
allowed_domains: allowed_domains:
- gmail.com - gmail.com
- from: weirdlyssl.corp.beyondperimeter.com - from: weirdlyssl.corp.beyondperimeter.com
to: http://neverssl.com to: http://neverssl.com
allowed_users: allowed_users:
- bdd@pomerium.io - bdd@pomerium.io
allowed_groups: allowed_groups:
- admins - admins
- developers - developers
- from: hello.corp.beyondperimeter.com - from: hello.corp.beyondperimeter.com
to: http://hello:8080 to: http://hello:8080
allowed_groups: allowed_groups:
- admins - admins
- from: cross-origin.corp.beyondperimeter.com - from: cross-origin.corp.beyondperimeter.com
to: httpbin.org to: httpbin.org
allowed_domains: allowed_domains:
- gmail.com - gmail.com

View file

@ -24,13 +24,6 @@ var (
ErrUserNotAuthorized = errors.New("user not authorized") ErrUserNotAuthorized = errors.New("user not authorized")
) )
var securityHeaders = map[string]string{
"X-Content-Type-Options": "nosniff",
"X-Frame-Options": "SAMEORIGIN",
"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.
type StateParameter struct { type StateParameter struct {
SessionID string `json:"session_id"` SessionID string `json:"session_id"`
@ -63,7 +56,7 @@ func (p *Proxy) Handler() http.Handler {
Str("pomerium-email", r.Header.Get(HeaderEmail)). Str("pomerium-email", r.Header.Get(HeaderEmail)).
Msg("proxy: request") Msg("proxy: request")
})) }))
c = c.Append(middleware.SetHeaders(securityHeaders)) c = c.Append(middleware.SetHeaders(p.headers))
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"))

View file

@ -31,6 +31,8 @@ const (
HeaderEmail = "x-pomerium-authenticated-user-email" HeaderEmail = "x-pomerium-authenticated-user-email"
// HeaderGroups is the header key containing the user's groups. // HeaderGroups is the header key containing the user's groups.
HeaderGroups = "x-pomerium-authenticated-user-groups" HeaderGroups = "x-pomerium-authenticated-user-groups"
// DisableHeaderKey is the key used to check whether to disable setting header
DisableHeaderKey = "disable"
) )
// Options represents the configurations available for the proxy service. // Options represents the configurations available for the proxy service.
@ -70,6 +72,9 @@ type Options struct {
CookieExpire time.Duration `envconfig:"COOKIE_EXPIRE"` CookieExpire time.Duration `envconfig:"COOKIE_EXPIRE"`
CookieRefresh time.Duration `envconfig:"COOKIE_REFRESH"` CookieRefresh time.Duration `envconfig:"COOKIE_REFRESH"`
// Headers to set on all proxied requests. Add a 'disable' key map to turn off.
Headers map[string]string `envconfig:"HEADERS"`
// Sub-routes // Sub-routes
Routes map[string]string `envconfig:"ROUTES"` Routes map[string]string `envconfig:"ROUTES"`
DefaultUpstreamTimeout time.Duration `envconfig:"DEFAULT_UPSTREAM_TIMEOUT"` DefaultUpstreamTimeout time.Duration `envconfig:"DEFAULT_UPSTREAM_TIMEOUT"`
@ -83,6 +88,12 @@ var defaultOptions = &Options{
CookieExpire: time.Duration(14) * time.Hour, CookieExpire: time.Duration(14) * time.Hour,
CookieRefresh: time.Duration(30) * time.Minute, CookieRefresh: time.Duration(30) * time.Minute,
DefaultUpstreamTimeout: time.Duration(30) * time.Second, DefaultUpstreamTimeout: time.Duration(30) * time.Second,
Headers: map[string]string{
"X-Content-Type-Options": "nosniff",
"X-Frame-Options": "SAMEORIGIN",
"X-XSS-Protection": "1; mode=block",
"Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload",
},
} }
// OptionsFromEnvConfig builds the identity provider service's configuration // OptionsFromEnvConfig builds the identity provider service's configuration
@ -175,6 +186,7 @@ type Proxy struct {
redirectURL *url.URL redirectURL *url.URL
templates *template.Template templates *template.Template
routeConfigs map[string]*routeConfig routeConfigs map[string]*routeConfig
headers map[string]string
} }
type routeConfig struct { type routeConfig struct {
@ -212,6 +224,12 @@ func New(opts *Options) (*Proxy, error) {
return nil, err return nil, err
} }
// if the disable key is found in the security header map, clear the map
if _, disable := opts.Headers[DisableHeaderKey]; disable {
opts.Headers = make(map[string]string)
}
log.Debug().Interface("headers", opts.Headers).Msg("proxy: security headers")
p := &Proxy{ p := &Proxy{
routeConfigs: make(map[string]*routeConfig), routeConfigs: make(map[string]*routeConfig),
// services // services
@ -223,6 +241,7 @@ func New(opts *Options) (*Proxy, error) {
SharedKey: opts.SharedKey, SharedKey: opts.SharedKey,
redirectURL: &url.URL{Path: "/.pomerium/callback"}, redirectURL: &url.URL{Path: "/.pomerium/callback"},
templates: templates.New(), templates: templates.New(),
headers: opts.Headers,
} }
var policies []policy.Policy var policies []policy.Policy
if opts.Policy != "" { if opts.Policy != "" {

View file

@ -124,6 +124,7 @@ func testOptions() *Options {
SharedKey: "80ldlrU2d7w+wVpKNfevk6fmb8otEx6CqOfshj2LwhQ=", SharedKey: "80ldlrU2d7w+wVpKNfevk6fmb8otEx6CqOfshj2LwhQ=",
CookieSecret: "OromP1gurwGWjQPYb1nNgSxtbVB5NnLzX6z5WOKr0Yw=", CookieSecret: "OromP1gurwGWjQPYb1nNgSxtbVB5NnLzX6z5WOKr0Yw=",
CookieName: "pomerium", CookieName: "pomerium",
Headers: defaultOptions.Headers,
} }
} }
@ -205,20 +206,23 @@ func TestNew(t *testing.T) {
shortCookieLength.CookieSecret = "gN3xnvfsAwfCXxnJorGLKUG4l2wC8sS8nfLMhcStPg==" shortCookieLength.CookieSecret = "gN3xnvfsAwfCXxnJorGLKUG4l2wC8sS8nfLMhcStPg=="
badRoutedProxy := testOptions() badRoutedProxy := testOptions()
badRoutedProxy.SigningKey = "YmFkIGtleQo=" badRoutedProxy.SigningKey = "YmFkIGtleQo="
disableHeaders := testOptions()
disableHeaders.Headers = map[string]string{"disable": "true"}
tests := []struct { tests := []struct {
name string name string
opts *Options opts *Options
optFuncs []func(*Proxy) error wantProxy bool
wantProxy bool numRoutes int
numRoutes int wantErr bool
wantErr bool numHeaders int
}{ }{
{"good", good, nil, true, 1, false}, {"good", good, true, 1, false, len(defaultOptions.Headers)},
{"empty options", &Options{}, nil, false, 0, true}, {"empty options", &Options{}, false, 0, true, 0},
{"nil options", nil, nil, false, 0, true}, {"nil options", nil, false, 0, true, 0},
{"short secret/validate sanity check", shortCookieLength, nil, false, 0, true}, {"short secret/validate sanity check", shortCookieLength, false, 0, true, 0},
{"invalid ec key, valid base64 though", badRoutedProxy, nil, false, 0, true}, {"invalid ec key, valid base64 though", badRoutedProxy, false, 0, true, 0},
{"test disabled headers", disableHeaders, false, 1, false, 0},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
@ -233,6 +237,10 @@ func TestNew(t *testing.T) {
if got != nil && len(got.routeConfigs) != tt.numRoutes { if got != nil && len(got.routeConfigs) != tt.numRoutes {
t.Errorf("New() = num routeConfigs \n%+v, want \n%+v", got, tt.numRoutes) t.Errorf("New() = num routeConfigs \n%+v, want \n%+v", got, tt.numRoutes)
} }
if got != nil && len(got.headers) != tt.numHeaders {
t.Errorf("New() = num Headers \n%+v, want \n%+v", got.headers, tt.numHeaders)
}
}) })
} }
} }