Skip to content
Snippets Groups Projects
Verified Commit 6cbb7582 authored by Janne Mareike Koschinski's avatar Janne Mareike Koschinski
Browse files

Fix header injection bug

parent ee5c21ff
No related branches found
No related tags found
No related merge requests found
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
......@@ -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
......
......@@ -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))
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment