diff --git a/Makefile b/Makefile deleted file mode 100644 index 710df40f3734101b56061cd3d423612d7c159cfa..0000000000000000000000000000000000000000 --- a/Makefile +++ /dev/null @@ -1,153 +0,0 @@ -NAME=keycloak-gatekeeper -AUTHOR=keycloak -REGISTRY=docker.io -GOVERSION ?= 1.10.2 -ROOT_DIR=${PWD} -HARDWARE=$(shell uname -m) -GIT_SHA=$(shell git --no-pager describe --always --dirty) -BUILD_TIME=$(shell date '+%s') -VERSION ?= $(shell awk '/release.*=/ { print $$3 }' doc.go | sed 's/"//g') -DEPS=$(shell go list -f '{{range .TestImports}}{{.}} {{end}}' ./...) -PACKAGES=$(shell go list ./...) -LFLAGS ?= -X main.gitsha=${GIT_SHA} -X main.compiled=${BUILD_TIME} -VETARGS ?= -asmdecl -atomic -bool -buildtags -copylocks -methods -nilfunc -printf -rangeloops -shift -unsafeptr -PLATFORMS=darwin linux windows -ARCHITECTURES=amd64 - -.PHONY: test authors changelog build docker static release lint cover vet glide-install - -default: build - -golang: - @echo "--> Go Version" - @go version - -build: golang - @echo "--> Compiling the project" - @mkdir -p bin - go build -ldflags "${LFLAGS}" -o bin/${NAME} - -static: golang - @echo "--> Compiling the static binary" - @mkdir -p bin - CGO_ENABLED=0 GOOS=linux go build -a -tags netgo -ldflags "-w ${LFLAGS}" -o bin/${NAME} - -docker-build: - @echo "--> Compiling the project" - docker run --rm \ - -v ${ROOT_DIR}:/go/src/github.com/${AUTHOR}/${NAME} \ - -w /go/src/github.com/${AUTHOR}/${NAME} \ - -e GOOS=linux golang:${GOVERSION} \ - make static - -docker-test: - @echo "--> Running the docker test" - docker run --rm -ti -p 3000:3000 \ - -v ${ROOT_DIR}/config.yml:/etc/keycloak/config.yml:ro \ - -v ${ROOT_DIR}/tests:/opt/tests:ro \ - ${REGISTRY}/${AUTHOR}/${NAME}:${VERSION} --config /etc/keycloak/config.yml - -docker-release: - @echo "--> Building a release image" - @$(MAKE) static - @$(MAKE) docker - @docker push ${REGISTRY}/${AUTHOR}/${NAME}:${VERSION} - -docker: - @echo "--> Building the docker image" - docker build -t ${REGISTRY}/${AUTHOR}/${NAME}:${VERSION} . - -certs: - @echo "--> Generating the root CA" - @cfssl gencert -initca tests/ca-csr.json | cfssljson -bare tests/ca - @echo "--> Generating the Test Certs" - cfssl gencert \ - -ca=tests/ca.pem \ - -ca-key=tests/ca-key.pem \ - -config=tests/ca-config.json \ - -profile=server \ - tests/proxy-csr.json | cfssljson -bare tests/proxy - -clean: - rm -rf ./bin/* 2>/dev/null - rm -rf ./release/* 2>/dev/null - -authors: - @echo "--> Updating the AUTHORS" - git log --format='%aN <%aE>' | sort -u > AUTHORS - -vet: - @echo "--> Running go vet $(VETARGS) ." - @go vet 2>/dev/null ; if [ $$? -eq 3 ]; then \ - go get golang.org/x/tools/cmd/vet; \ - fi - # This is required due to break of API compatibility in go vet between version 1.11 and 1.12 - @go version | grep '1.11' 2>/dev/null ; if [[ $$? -eq 0 ]]; then \ - go vet $(VETARGS) -structtags *.go; \ - fi - @go version | grep '1.12' 2>/dev/null ; if [[ $$? -eq 0 ]]; then \ - go vet $(VETARGS) -structtag *.go; \ - fi - -lint: - @echo "--> Running golangci-lint" - @which golangci-lint 2>/dev/null ; if [ $$? -eq 1 ]; then \ - go get -u github.com/golangci/golangci-lint/cmd/golangci-lint; \ - fi - @golint . - -gofmt: - @echo "--> Running gofmt check" - @gofmt -s -l *.go \ - | grep -q \.go ; if [ $$? -eq 0 ]; then \ - echo "You need to runn the make format, we have file unformatted"; \ - gofmt -s -l *.go; \ - exit 1; \ - fi - -verify: - @echo "--> Verifying the code" - golangci-lint run - -format: - @echo "--> Running go fmt" - @gofmt -s -w *.go - -bench: - @echo "--> Running go bench" - @go test -bench=. -benchmem - -coverage: - @echo "--> Running go coverage" - @go test -coverprofile cover.out - @go tool cover -html=cover.out -o cover.html - -cover: - @echo "--> Running go cover" - @go test --cover - -spelling: - @echo "--> Checking the spelling" - @which misspell 2>/dev/null ; if [ $$? -eq 1 ]; then \ - go get -u github.com/client9/misspell/cmd/misspell; \ - fi - @misspell -error *.go - @misspell -error *.md - -test: - @echo "--> Running the tests" - @go test -v - @$(MAKE) golang - @$(MAKE) gofmt - @$(MAKE) spelling - @$(MAKE) vet - @$(MAKE) cover - -all: test - echo "--> Performing all tests" - @${MAKE} verify - @$(MAKE) bench - @$(MAKE) coverage - -changelog: release - git log $(shell git tag | tail -n1)..HEAD --no-merges --format=%B > changelog diff --git a/middleware.go b/middleware.go index 2ec01419a159370968069bc4365de5628cb4218e..a028a47df866737fd710d0e1c54c1d19064e7a59 100644 --- a/middleware.go +++ b/middleware.go @@ -113,7 +113,7 @@ func (r *oauthProxy) requestHeaderSanitizingMiddleware() func(http.Handler) http } // authenticationMiddleware is responsible for verifying the access token -func (r *oauthProxy) authenticationMiddleware(whitelisted bool) func(http.Handler) http.Handler { +func (r *oauthProxy) authenticationMiddleware(loginOptional bool) func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { clientIP := req.RemoteAddr @@ -121,7 +121,7 @@ func (r *oauthProxy) authenticationMiddleware(whitelisted bool) func(http.Handle user, err := r.getIdentity(req) if err != nil { r.log.Error("no session found in request, redirecting for authorization", zap.Error(err)) - if whitelisted { + if loginOptional { return } next.ServeHTTP(w, req.WithContext(r.redirectToAuthorization(w, req))) @@ -141,7 +141,7 @@ func (r *oauthProxy) authenticationMiddleware(whitelisted bool) func(http.Handle zap.String("username", user.name), zap.String("expired_on", user.expiresAt.String())) - if whitelisted { + if loginOptional { return } next.ServeHTTP(w, req.WithContext(r.redirectToAuthorization(w, req))) @@ -157,7 +157,7 @@ func (r *oauthProxy) authenticationMiddleware(whitelisted bool) func(http.Handle zap.String("client_ip", clientIP), zap.Error(err)) - if whitelisted { + if loginOptional { return } next.ServeHTTP(w, req.WithContext(r.accessForbidden(w, req))) @@ -171,7 +171,7 @@ func (r *oauthProxy) authenticationMiddleware(whitelisted bool) func(http.Handle zap.String("email", user.name), zap.String("expired_on", user.expiresAt.String())) - if whitelisted { + if loginOptional { return } next.ServeHTTP(w, req.WithContext(r.redirectToAuthorization(w, req))) @@ -190,7 +190,7 @@ func (r *oauthProxy) authenticationMiddleware(whitelisted bool) func(http.Handle zap.String("email", user.email), zap.Error(err)) - if whitelisted { + if loginOptional { return } next.ServeHTTP(w, req.WithContext(r.redirectToAuthorization(w, req))) @@ -217,7 +217,7 @@ func (r *oauthProxy) authenticationMiddleware(whitelisted bool) func(http.Handle default: r.log.Error("failed to refresh the access token", zap.Error(err)) } - if whitelisted { + if loginOptional { return } next.ServeHTTP(w, req.WithContext(r.redirectToAuthorization(w, req))) @@ -349,7 +349,7 @@ func (r *oauthProxy) checkClaim(user *userContext, claimName string, match *rege } // admissionMiddleware is responsible checking the access token against the protected resource -func (r *oauthProxy) admissionMiddleware(whitelisted bool, resource *Resource) func(http.Handler) http.Handler { +func (r *oauthProxy) admissionMiddleware(loginOptional bool, resource *Resource) func(http.Handler) http.Handler { claimMatches := make(map[string]*regexp.Regexp) for k, v := range r.config.MatchClaims { claimMatches[k] = regexp.MustCompile(v) @@ -373,7 +373,7 @@ func (r *oauthProxy) admissionMiddleware(whitelisted bool, resource *Resource) f zap.String("resource", resource.URL), zap.String("roles", resource.getRoles())) - if whitelisted { + if loginOptional { return } next.ServeHTTP(w, req.WithContext(r.accessForbidden(w, req))) @@ -388,7 +388,7 @@ func (r *oauthProxy) admissionMiddleware(whitelisted bool, resource *Resource) f zap.String("resource", resource.URL), zap.String("groups", strings.Join(resource.Groups, ","))) - if whitelisted { + if loginOptional { return } next.ServeHTTP(w, req.WithContext(r.accessForbidden(w, req))) @@ -398,7 +398,7 @@ func (r *oauthProxy) admissionMiddleware(whitelisted bool, resource *Resource) f // step: if we have any claim matching, lets validate the tokens has the claims for claimName, match := range claimMatches { if !r.checkClaim(user, claimName, match, resource.URL) { - if whitelisted { + if loginOptional { return } next.ServeHTTP(w, req.WithContext(r.accessForbidden(w, req))) @@ -482,7 +482,7 @@ func (r *oauthProxy) identityHeadersMiddleware(custom []string) func(http.Handle // securityMiddleware performs numerous security checks on the request func (r *oauthProxy) securityMiddleware(next http.Handler) http.Handler { r.log.Info("enabling the security filter middleware") - secure := secure.New(secure.Options{ + secureFilter := secure.New(secure.Options{ AllowedHosts: r.config.Hostnames, BrowserXssFilter: r.config.EnableBrowserXSSFilter, ContentSecurityPolicy: r.config.ContentSecurityPolicy, @@ -493,7 +493,7 @@ func (r *oauthProxy) securityMiddleware(next http.Handler) http.Handler { }) return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - if err := secure.Process(w, req); err != nil { + if err := secureFilter.Process(w, req); err != nil { r.log.Warn("failed security middleware", zap.Error(err)) next.ServeHTTP(w, req.WithContext(r.accessForbidden(w, req))) return diff --git a/server.go b/server.go index 2ff7ce1d0d6e6aa0e0ab10830954ddbc119f1a01..552d202574e08789e044cb6512cb9ac3f90aeefe 100644 --- a/server.go +++ b/server.go @@ -265,6 +265,7 @@ func (r *oauthProxy) createReverseProxy() error { r.identityHeadersMiddleware(r.config.AddClaims)) o := engine.With( + r.requestHeaderSanitizingMiddleware(), r.authenticationMiddleware(true), r.admissionMiddleware(true, x), r.identityHeadersMiddleware(r.config.AddClaims))