diff --git a/CHANGELOG.md b/CHANGELOG.md index c8207802..f78b24f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,16 +1,19 @@ # Vx.x.x (Pre-release) ## Changes since v4.0.0 - +- [#292](https://github.com/pusher/oauth2_proxy/pull/292) Added bash >= 4.0 dependency to configure script (@jmfrank63) - [#227](https://github.com/pusher/oauth2_proxy/pull/227) Add Keycloak provider (@Ofinka) - [#259](https://github.com/pusher/oauth2_proxy/pull/259) Redirect to HTTPS (@jmickey) - [#273](https://github.com/pusher/oauth2_proxy/pull/273) Support Go 1.13 (@dio) - [#275](https://github.com/pusher/oauth2_proxy/pull/275) docker: build from debian buster (@syscll) - [#258](https://github.com/pusher/oauth2_proxy/pull/258) Add IDToken for Azure provider - This PR adds the IDToken into the session for the Azure provider allowing requests to a backend to be identified as a specific user. As a consequence, if you are using a cookie to store the session the cookie will now exceed the 4kb size limit and be split into multiple cookies. This can cause problems when using nginx as a proxy, resulting in no cookie being passed at all. Either increase the proxy_buffer_size in nginx or implement the redis session storage (see https://pusher.github.io/oauth2_proxy/configuration#redis-storage) -- [#274](https://github.com/pusher/oauth2_proxy/pull/274) Supports many github teams with api pagination support (@toshi-miura,@apratina) - [#286](https://github.com/pusher/oauth2_proxy/pull/286) Requests.go updated with useful error messages (@biotom) - +- [#274](https://github.com/pusher/oauth2_proxy/pull/274) Supports many github teams with api pagination support (@toshi-miura, @apratina) +- [#302](https://github.com/pusher/oauth2_proxy/pull/302) Rewrite dist script (@syscll) +- [#304](https://github.com/pusher/oauth2_proxy/pull/304) Add new Logo! :tada: (@JoelSpeed) +- [#300](https://github.com/pusher/oauth2_proxy/pull/300) Added userinfo endpoint (@kbabuadze) +- [#309](https://github.com/pusher/oauth2_proxy/pull/309) Added support for custom CA when connecting to Redis cache # v4.0.0 diff --git a/Makefile b/Makefile index 18283f94..f0f83b44 100644 --- a/Makefile +++ b/Makefile @@ -61,29 +61,4 @@ test: lint .PHONY: release release: lint test - mkdir release - mkdir release/$(BINARY)-$(VERSION).darwin-amd64.$(GO_VERSION) - mkdir release/$(BINARY)-$(VERSION).linux-amd64.$(GO_VERSION) - mkdir release/$(BINARY)-$(VERSION).linux-arm64.$(GO_VERSION) - mkdir release/$(BINARY)-$(VERSION).linux-armv6.$(GO_VERSION) - mkdir release/$(BINARY)-$(VERSION).windows-amd64.$(GO_VERSION) - GO111MODULE=on GOOS=darwin GOARCH=amd64 go build -ldflags="-X main.VERSION=${VERSION}" \ - -o release/$(BINARY)-$(VERSION).darwin-amd64.$(GO_VERSION)/$(BINARY) github.com/pusher/oauth2_proxy - GO111MODULE=on GOOS=linux GOARCH=amd64 go build -ldflags="-X main.VERSION=${VERSION}" \ - -o release/$(BINARY)-$(VERSION).linux-amd64.$(GO_VERSION)/$(BINARY) github.com/pusher/oauth2_proxy - GO111MODULE=on GOOS=linux GOARCH=arm64 go build -ldflags="-X main.VERSION=${VERSION}" \ - -o release/$(BINARY)-$(VERSION).linux-arm64.$(GO_VERSION)/$(BINARY) github.com/pusher/oauth2_proxy - GO111MODULE=on GOOS=linux GOARCH=arm GOARM=6 go build -ldflags="-X main.VERSION=${VERSION}" \ - -o release/$(BINARY)-$(VERSION).linux-armv6.$(GO_VERSION)/$(BINARY) github.com/pusher/oauth2_proxy - GO111MODULE=on GOOS=windows GOARCH=amd64 go build -ldflags="-X main.VERSION=${VERSION}" \ - -o release/$(BINARY)-$(VERSION).windows-amd64.$(GO_VERSION)/$(BINARY) github.com/pusher/oauth2_proxy - shasum -a 256 release/$(BINARY)-$(VERSION).darwin-amd64.$(GO_VERSION)/$(BINARY) > release/$(BINARY)-$(VERSION).darwin-amd64-sha256sum.txt - shasum -a 256 release/$(BINARY)-$(VERSION).linux-amd64.$(GO_VERSION)/$(BINARY) > release/$(BINARY)-$(VERSION).linux-amd64-sha256sum.txt - shasum -a 256 release/$(BINARY)-$(VERSION).linux-arm64.$(GO_VERSION)/$(BINARY) > release/$(BINARY)-$(VERSION).linux-arm64-sha256sum.txt - shasum -a 256 release/$(BINARY)-$(VERSION).linux-armv6.$(GO_VERSION)/$(BINARY) > release/$(BINARY)-$(VERSION).linux-armv6-sha256sum.txt - shasum -a 256 release/$(BINARY)-$(VERSION).windows-amd64.$(GO_VERSION)/$(BINARY) > release/$(BINARY)-$(VERSION).windows-amd64-sha256sum.txt - tar -C release -czvf release/$(BINARY)-$(VERSION).darwin-amd64.$(GO_VERSION).tar.gz $(BINARY)-$(VERSION).darwin-amd64.$(GO_VERSION) - tar -C release -czvf release/$(BINARY)-$(VERSION).linux-amd64.$(GO_VERSION).tar.gz $(BINARY)-$(VERSION).linux-amd64.$(GO_VERSION) - tar -C release -czvf release/$(BINARY)-$(VERSION).linux-arm64.$(GO_VERSION).tar.gz $(BINARY)-$(VERSION).linux-arm64.$(GO_VERSION) - tar -C release -czvf release/$(BINARY)-$(VERSION).linux-armv6.$(GO_VERSION).tar.gz $(BINARY)-$(VERSION).linux-armv6.$(GO_VERSION) - tar -C release -czvf release/$(BINARY)-$(VERSION).windows-amd64.$(GO_VERSION).tar.gz $(BINARY)-$(VERSION).windows-amd64.$(GO_VERSION) + BINARY=${BINARY} VERSION=${VERSION} ./dist.sh diff --git a/README.md b/README.md index 09fde41e..daae04cc 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# oauth2_proxy +![OAuth2 Proxy](/docs/logos/OAuth2_Proxy_horizontal.svg) [![Build Status](https://secure.travis-ci.org/pusher/oauth2_proxy.svg?branch=master)](http://travis-ci.org/pusher/oauth2_proxy) [![Go Report Card](https://goreportcard.com/badge/github.com/pusher/oauth2_proxy)](https://goreportcard.com/report/github.com/pusher/oauth2_proxy) diff --git a/configure b/configure index 26db8fea..10af15e6 100755 --- a/configure +++ b/configure @@ -5,6 +5,10 @@ GREEN='\033[0;32m' BLUE='\033[0;34m' NC='\033[0m' +if [ -z "${BASH_VERSINFO}" ] || [ -z "${BASH_VERSINFO[0]}" ] || [ ${BASH_VERSINFO[0]} -lt 4 ]; then + echo "This script requires Bash version >= 4"; exit 1; +fi + declare -A tools=() declare -A desired=() diff --git a/contrib/oauth2_proxy_autocomplete.sh b/contrib/oauth2_proxy_autocomplete.sh new file mode 100644 index 00000000..fd9d87a4 --- /dev/null +++ b/contrib/oauth2_proxy_autocomplete.sh @@ -0,0 +1,30 @@ +# +# Autocompletion for oauth2_proxy +# +# To install this, copy/move this file to /etc/bash.completion.d/ +# or add a line to your ~/.bashrc | ~/.bash_profile that says ". /path/to/oauth2_proxy/contrib/oauth2_proxy_autocomplete.sh" +# + +_oauth2_proxy() { + _oauth2_proxy_commands=$(oauth2_proxy -h 2>&1 | sed -n '/^\s*-/s/ \+/ /gp' | awk '{print $1}' | tr '\n' ' ') + local cur prev + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + case "$prev" in + -@(config|tls-cert-file|tls-key-file|authenticated-emails-file|htpasswd-file|custom-templates-dir|logging-filename|jwt-key-file)) + _filedir + return 0 + ;; + -provider) + COMPREPLY=( $(compgen -W "google azure facebook github keycloak gitlab linkedin login.gov" -- ${cur}) ) + return 0 + ;; + -@(http-address|https-address|redirect-url|upstream|basic-auth-password|skip-auth-regex|flush-interval|extra-jwt-issuers|email-domain|whitelist-domain|keycloak-group|azure-tenant|bitbucket-team|bitbucket-repository|github-org|github-team|gitlab-group|google-group|google-admin-email|google-service-account-json|client-id|client_secret|banner|footer|proxy-prefix|ping-path|cookie-name|cookie-secret|cookie-domain|cookie-path|cookie-expire|cookie-refresh|redist-sentinel-master-name|redist-sentinel-connection-urls|logging-max-size|logging-max-age|logging-max-backups|standard-logging-format|request-logging-format|exclude-logging-paths|auth-logging-format|oidc-issuer-url|oidc-jwks-url|login-url|redeem-url|profile-url|resource|validate-url|scope|approval-prompt|signature-key|acr-values|jwt-key|pubjwk-url)) + return 0 + ;; + esac + COMPREPLY=( $(compgen -W "${_oauth2_proxy_commands}" -- ${cur}) ) + return 0; +} +complete -F _oauth2_proxy oauth2_proxy diff --git a/dist.sh b/dist.sh index a00318bb..e5be8180 100755 --- a/dist.sh +++ b/dist.sh @@ -1,45 +1,46 @@ -#!/bin/bash -# build binary distributions for linux/amd64 and darwin/amd64 -set -e +#!/usr/bin/env bash -DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -echo "working dir $DIR" -mkdir -p $DIR/dist -dep ensure || exit 1 +set -o errexit -os=$(go env GOOS) -arch=$(go env GOARCH) -version=$(cat $DIR/version.go | grep "const VERSION" | awk '{print $NF}' | sed 's/"//g') -goversion=$(go version | awk '{print $3}') -sha256sum=() - -echo "... running tests" -./test.sh - -for os in windows linux darwin; do - echo "... building v$version for $os/$arch" - EXT= - if [ $os = windows ]; then - EXT=".exe" - fi - BUILD=$(mktemp -d ${TMPDIR:-/tmp}/oauth2_proxy.XXXXXX) - TARGET="oauth2_proxy-$version.$os-$arch.$goversion" - FILENAME="oauth2_proxy-$version.$os-$arch$EXT" - GOOS=$os GOARCH=$arch CGO_ENABLED=0 \ - go build -ldflags="-s -w" -o $BUILD/$TARGET/$FILENAME || exit 1 - pushd $BUILD/$TARGET - sha256sum+=("$(shasum -a 256 $FILENAME || exit 1)") - cd .. && tar czvf $TARGET.tar.gz $TARGET - mv $TARGET.tar.gz $DIR/dist - popd -done - -checksum_file="sha256sum.txt" -cd $DIR/dist -if [ -f $checksum_file ]; then - rm $checksum_file +if [[ -z ${BINARY} ]] || [[ -z ${VERSION} ]]; then + echo "Missing required env var: BINARY=X VERSION=X $(basename $0)" + exit 1 fi -touch $checksum_file -for checksum in "${sha256sum[@]}"; do - echo "$checksum" >> $checksum_file + +# Check for Go version 1.13.* +GO_VERSION=$(go version | awk '{print $3}') +if [[ ! "${GO_VERSION}" =~ ^go1.13.* ]]; then + echo "Go version must be >= go1.13" + exit 1 +fi + +ARCHS=(darwin-amd64 linux-amd64 linux-arm64 linux-armv6 windows-amd64) + +mkdir -p release + +# Create architecture specific release dirs +for ARCH in "${ARCHS[@]}"; do + mkdir -p release/${BINARY}-${VERSION}.${ARCH}.${GO_VERSION} + + GO_OS=$(echo $ARCH | awk -F- '{print $1}') + GO_ARCH=$(echo $ARCH | awk -F- '{print $2}') + + # Create architecture specific binaries + if [[ ${GO_ARCH} == "armv6" ]]; then + GO111MODULE=on GOOS=${GO_OS} GOARCH=arm GOARM=6 go build -ldflags="-X main.VERSION=${VERSION}" \ + -o release/${BINARY}-${VERSION}.${ARCH}.${GO_VERSION}/${BINARY} github.com/pusher/oauth2_proxy + else + GO111MODULE=on GOOS=${GO_OS} GOARCH=${GO_ARCH} go build -ldflags="-X main.VERSION=${VERSION}" \ + -o release/${BINARY}-${VERSION}.${ARCH}.${GO_VERSION}/${BINARY} github.com/pusher/oauth2_proxy + fi + + cd release + + # Create sha256sum for architecture specific binary + shasum -a 256 ${BINARY}-${VERSION}.${ARCH}.${GO_VERSION}/${BINARY} > ${BINARY}-${VERSION}.${ARCH}-sha256sum.txt + + # Create tar file for architecture specific binary + tar -czvf ${BINARY}-${VERSION}.${ARCH}.${GO_VERSION}.tar.gz ${BINARY}-${VERSION}.${ARCH}.${GO_VERSION} + + cd .. done diff --git a/docs/0_index.md b/docs/0_index.md index 376bd754..e0e3227d 100644 --- a/docs/0_index.md +++ b/docs/0_index.md @@ -5,7 +5,7 @@ permalink: / nav_order: 0 --- -# oauth2_proxy +![OAuth2 Proxy](/logos/OAuth2_Proxy_horizontal.svg) A reverse proxy and static file server that provides authentication using Providers (Google, GitHub, and others) to validate accounts by email, domain or group. diff --git a/docs/1_installation.md b/docs/1_installation.md index 9eb3939f..8ed72b81 100644 --- a/docs/1_installation.md +++ b/docs/1_installation.md @@ -9,7 +9,7 @@ nav_order: 1 1. Choose how to deploy: - a. Download [Prebuilt Binary](https://github.com/pusher/oauth2_proxy/releases) (current release is `v3.2.0`) + a. Download [Prebuilt Binary](https://github.com/pusher/oauth2_proxy/releases) (current release is `v4.0.0`) b. Build with `$ go get github.com/pusher/oauth2_proxy` which will put the binary in `$GOROOT/bin` @@ -18,8 +18,8 @@ nav_order: 1 Prebuilt binaries can be validated by extracting the file and verifying it against the `sha256sum.txt` checksum file provided for each release starting with version `v3.0.0`. ``` -sha256sum -c sha256sum.txt 2>&1 | grep OK -oauth2_proxy-3.2.0.linux-amd64: OK +$ sha256sum -c sha256sum.txt 2>&1 | grep OK +oauth2_proxy-4.0.0.linux-amd64: OK ``` 2. [Select a Provider and Register an OAuth Application with a Provider](auth-configuration) diff --git a/docs/5_endpoints.md b/docs/5_endpoints.md index 6733cb14..75b8f16f 100644 --- a/docs/5_endpoints.md +++ b/docs/5_endpoints.md @@ -14,4 +14,5 @@ OAuth2 Proxy responds directly to the following endpoints. All other endpoints w - /oauth2/sign_in - the login page, which also doubles as a sign out page (it clears cookies) - /oauth2/start - a URL that will redirect to start the OAuth cycle - /oauth2/callback - the URL used at the end of the OAuth cycle. The oauth app will be configured with this as the callback url. +- /oauth2/userinfo - the URL is used to return user's email from the session in JSON format. - /oauth2/auth - only returns a 202 Accepted response or a 401 Unauthorized response; for use with the [Nginx `auth_request` directive](#nginx-auth-request) diff --git a/docs/_config.yml b/docs/_config.yml index 87f026c8..a53e9e14 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -14,6 +14,7 @@ # You can create any custom variable you would like, and they will be accessible # in the templates via {{ site.myvariable }}. title: OAuth2_Proxy +logo: /logos/OAuth2_Proxy_horizontal.svg description: >- # this means to ignore newlines until "baseurl:" OAuth2_Proxy documentation site baseurl: "/oauth2_proxy" # the subpath of your site, e.g. /blog diff --git a/docs/configuration/configuration.md b/docs/configuration/configuration.md index 332c2238..2f5d049a 100644 --- a/docs/configuration/configuration.md +++ b/docs/configuration/configuration.md @@ -117,7 +117,7 @@ See below for provider specific options ### Upstreams Configuration -`oauth2_proxy` supports having multiple upstreams, and has the option to pass requests on to HTTP(S) servers or serve static files from the file system. HTTP and HTTPS upstreams are configured by providing a URL such as `http://127.0.0.1:8080/` for the upstream parameter, that will forward all authenticated requests to be forwarded to the upstream server. If you instead provide `http://127.0.0.1:8080/some/path/` then it will only be requests that start with `/some/path/` which are forwarded to the upstream. +`oauth2_proxy` supports having multiple upstreams, and has the option to pass requests on to HTTP(S) servers or serve static files from the file system. HTTP and HTTPS upstreams are configured by providing a URL such as `http://127.0.0.1:8080/` for the upstream parameter, this will forward all authenticated requests to the upstream server. If you instead provide `http://127.0.0.1:8080/some/path/` then it will only be requests that start with `/some/path/` which are forwarded to the upstream. Static file paths are configured as a file:// URL. `file:///var/www/static/` will serve the files from that directory at `http://[oauth2_proxy url]/var/www/static/`, which may not be what you want. You can provide the path to where the files should be available by adding a fragment to the configured URL. The value of the fragment will then be used to specify which path the files are available at. `file:///var/www/static/#/static/` will ie. make `/var/www/static/` available at `http://[oauth2_proxy url]/static/`. diff --git a/docs/logos/OAuth2_Proxy_horizontal.png b/docs/logos/OAuth2_Proxy_horizontal.png new file mode 100644 index 00000000..1020c52d Binary files /dev/null and b/docs/logos/OAuth2_Proxy_horizontal.png differ diff --git a/docs/logos/OAuth2_Proxy_horizontal.svg b/docs/logos/OAuth2_Proxy_horizontal.svg new file mode 100644 index 00000000..4df740f6 --- /dev/null +++ b/docs/logos/OAuth2_Proxy_horizontal.svg @@ -0,0 +1 @@ +OAuth2_Proxy_logo_v3 \ No newline at end of file diff --git a/docs/logos/OAuth2_Proxy_icon.png b/docs/logos/OAuth2_Proxy_icon.png new file mode 100644 index 00000000..720f4ce3 Binary files /dev/null and b/docs/logos/OAuth2_Proxy_icon.png differ diff --git a/docs/logos/OAuth2_Proxy_icon.svg b/docs/logos/OAuth2_Proxy_icon.svg new file mode 100644 index 00000000..5b0837f9 --- /dev/null +++ b/docs/logos/OAuth2_Proxy_icon.svg @@ -0,0 +1 @@ +OAuth2_Proxy_logo_v3 \ No newline at end of file diff --git a/docs/logos/OAuth2_Proxy_vertical.png b/docs/logos/OAuth2_Proxy_vertical.png new file mode 100644 index 00000000..994cd0b7 Binary files /dev/null and b/docs/logos/OAuth2_Proxy_vertical.png differ diff --git a/docs/logos/OAuth2_Proxy_vertical.svg b/docs/logos/OAuth2_Proxy_vertical.svg new file mode 100644 index 00000000..bf48ab0f --- /dev/null +++ b/docs/logos/OAuth2_Proxy_vertical.svg @@ -0,0 +1 @@ +OAuth2_Proxy_logo_v3 \ No newline at end of file diff --git a/main.go b/main.go index e84a796e..7cf562bd 100644 --- a/main.go +++ b/main.go @@ -91,6 +91,8 @@ func main() { flagSet.String("redis-connection-url", "", "URL of redis server for redis session storage (eg: redis://HOST[:PORT])") flagSet.Bool("redis-use-sentinel", false, "Connect to redis via sentinels. Must set --redis-sentinel-master-name and --redis-sentinel-connection-urls to use this feature") flagSet.String("redis-sentinel-master-name", "", "Redis sentinel master name. Used in conjunction with --redis-use-sentinel") + flagSet.String("redis-ca-path", "", "Redis custom CA path") + flagSet.Bool("redis-insecure-skip-tls-verify", false, "Use insecure TLS connection to redis") flagSet.Var(&redisSentinelConnectionURLs, "redis-sentinel-connection-urls", "List of Redis sentinel connection URLs (eg redis://HOST[:PORT]). Used in conjunction with --redis-use-sentinel") flagSet.String("logging-filename", "", "File to log requests to, empty for stdout") diff --git a/oauthproxy.go b/oauthproxy.go index 01c18c39..3c665db7 100644 --- a/oauthproxy.go +++ b/oauthproxy.go @@ -4,6 +4,7 @@ import ( "context" "crypto/tls" b64 "encoding/base64" + "encoding/json" "errors" "fmt" "html/template" @@ -75,6 +76,7 @@ type OAuthProxy struct { OAuthStartPath string OAuthCallbackPath string AuthOnlyPath string + UserInfoPath string redirectURL *url.URL // the url to receive requests at whitelistDomains []string @@ -266,6 +268,7 @@ func NewOAuthProxy(opts *Options, validator func(string) bool) *OAuthProxy { OAuthStartPath: fmt.Sprintf("%s/start", opts.ProxyPrefix), OAuthCallbackPath: fmt.Sprintf("%s/callback", opts.ProxyPrefix), AuthOnlyPath: fmt.Sprintf("%s/auth", opts.ProxyPrefix), + UserInfoPath: fmt.Sprintf("%s/userinfo", opts.ProxyPrefix), ProxyPrefix: opts.ProxyPrefix, provider: opts.provider, @@ -557,6 +560,8 @@ func (p *OAuthProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { p.OAuthCallback(rw, req) case path == p.AuthOnlyPath: p.AuthenticateOnly(rw, req) + case path == p.UserInfoPath: + p.UserInfo(rw, req) default: p.Proxy(rw, req) } @@ -585,6 +590,22 @@ func (p *OAuthProxy) SignIn(rw http.ResponseWriter, req *http.Request) { } } +//UserInfo endpoint outputs session email in JSON format +func (p *OAuthProxy) UserInfo(rw http.ResponseWriter, req *http.Request) { + + session, err := p.getAuthenticatedSession(rw, req) + if err != nil { + http.Error(rw, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) + return + } + userInfo := struct { + Email string `json:"email"` + }{session.Email} + rw.Header().Set("Content-Type", "application/json") + rw.WriteHeader(http.StatusOK) + json.NewEncoder(rw).Encode(userInfo) +} + // SignOut sends a response to clear the authentication cookie func (p *OAuthProxy) SignOut(rw http.ResponseWriter, req *http.Request) { p.ClearSessionCookie(rw, req) diff --git a/oauthproxy_test.go b/oauthproxy_test.go index 8dd3adfb..ce56e8a3 100644 --- a/oauthproxy_test.go +++ b/oauthproxy_test.go @@ -746,6 +746,32 @@ func TestProcessCookieFailIfRefreshSetAndCookieExpired(t *testing.T) { } } +func NewUserInfoEndpointTest() *ProcessCookieTest { + pcTest := NewProcessCookieTestWithDefaults() + pcTest.req, _ = http.NewRequest("GET", + pcTest.opts.ProxyPrefix+"/userinfo", nil) + return pcTest +} + +func TestUserInfoEndpointAccepted(t *testing.T) { + test := NewUserInfoEndpointTest() + startSession := &sessions.SessionState{ + Email: "john.doe@example.com", AccessToken: "my_access_token"} + test.SaveSession(startSession) + + test.proxy.ServeHTTP(test.rw, test.req) + assert.Equal(t, http.StatusOK, test.rw.Code) + bodyBytes, _ := ioutil.ReadAll(test.rw.Body) + assert.Equal(t, "{\"email\":\"john.doe@example.com\"}\n", string(bodyBytes)) +} + +func TestUserInfoEndpointUnauthorizedOnNoCookieSetError(t *testing.T) { + test := NewUserInfoEndpointTest() + + test.proxy.ServeHTTP(test.rw, test.req) + assert.Equal(t, http.StatusUnauthorized, test.rw.Code) +} + func NewAuthOnlyEndpointTest(modifiers ...OptionsModifier) *ProcessCookieTest { pcTest := NewProcessCookieTestWithOptionsModifiers(modifiers...) pcTest.req, _ = http.NewRequest("GET", diff --git a/pkg/apis/options/sessions.go b/pkg/apis/options/sessions.go index c96d490c..dbbb1cba 100644 --- a/pkg/apis/options/sessions.go +++ b/pkg/apis/options/sessions.go @@ -27,4 +27,6 @@ type RedisStoreOptions struct { UseSentinel bool `flag:"redis-use-sentinel" cfg:"redis_use_sentinel" env:"OAUTH2_PROXY_REDIS_USE_SENTINEL"` SentinelMasterName string `flag:"redis-sentinel-master-name" cfg:"redis_sentinel_master_name" env:"OAUTH2_PROXY_REDIS_SENTINEL_MASTER_NAME"` SentinelConnectionURLs []string `flag:"redis-sentinel-connection-urls" cfg:"redis_sentinel_connection_urls" env:"OAUTH2_PROXY_REDIS_SENTINEL_CONNECTION_URLS"` + RedisCAPath string `flag:"redis-ca-path" cfg:"redis_ca_path" env:"OAUTH2_PROXY_REDIS_CA_PATH"` + RedisInsecureTLS bool `flag:"redis-insecure-skip-tls-verify" cfg:"redis_insecure_skip_tls_verify" env:"OAUTH2_PROXY_REDIS_INSECURE_SKIP_TLS_VERIFY"` } diff --git a/pkg/sessions/redis/redis_store.go b/pkg/sessions/redis/redis_store.go index ed33d72d..fdeebf6b 100644 --- a/pkg/sessions/redis/redis_store.go +++ b/pkg/sessions/redis/redis_store.go @@ -4,10 +4,12 @@ import ( "crypto/aes" "crypto/cipher" "crypto/rand" + "crypto/x509" "encoding/base64" "encoding/hex" "fmt" "io" + "io/ioutil" "net/http" "strings" "time" @@ -17,6 +19,7 @@ import ( "github.com/pusher/oauth2_proxy/pkg/apis/sessions" "github.com/pusher/oauth2_proxy/pkg/cookies" "github.com/pusher/oauth2_proxy/pkg/encryption" + "github.com/pusher/oauth2_proxy/pkg/logger" ) // TicketData is a structure representing the ticket used in server session storage @@ -64,6 +67,31 @@ func newRedisClient(opts options.RedisStoreOptions) (*redis.Client, error) { return nil, fmt.Errorf("unable to parse redis url: %s", err) } + if opts.RedisInsecureTLS != false { + opt.TLSConfig.InsecureSkipVerify = true + } + + if opts.RedisCAPath != "" { + rootCAs, err := x509.SystemCertPool() + if err != nil { + logger.Printf("failed to load system cert pool for redis connection, falling back to empty cert pool") + } + if rootCAs == nil { + rootCAs = x509.NewCertPool() + } + certs, err := ioutil.ReadFile(opts.RedisCAPath) + if err != nil { + return nil, fmt.Errorf("failed to load %q, %v", opts.RedisCAPath, err) + } + + // Append our cert to the system pool + if ok := rootCAs.AppendCertsFromPEM(certs); !ok { + logger.Printf("no certs appended, using system certs only") + } + + opt.TLSConfig.RootCAs = rootCAs + } + client := redis.NewClient(opt) return client, nil }