From 1741a5b3fdf0c5e80656fa64e4a88756d57a390d Mon Sep 17 00:00:00 2001 From: Rohith Jayawardene <gambol99@gmail.com> Date: Fri, 4 Aug 2017 23:58:21 +0100 Subject: [PATCH] Upstream CA TLS Verification (#260) - addresses the feature from https://github.com/gambol99/keycloak-proxy/issues/256 - permits the user to load a root ca in order to verify the upstream endpoint - updated the README and the CHANGELOG to reflect the changes --- CHANGELOG.md | 1 + README.md | 3 ++- config.go | 6 ++++-- doc.go | 2 ++ server.go | 14 ++++++++++++++ 5 files changed, 23 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 82bfc9a..f2065b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ FEATURES * updated the base image to apline 3.6 in commit [0fdebaf821](https://github.com/gambol99/keycloak-proxy/pull/236/commits/0fdebaf8215e9480896f01ec7ab2ef7caa242da1) * moved to use zap for the logging [#PR237](https://github.com/gambol99/keycloak-proxy/pull/237) * making the X-Auth-Token optional in the upstream headers via the --enable-token-header [#PR247](https://github.com/gambol99/keycloak-proxy/pull/247) +* adding the ability to load a CA authority to provide trust on upstream endpoint [#PR248](https://github.com/gambol99/keycloak-proxy/pull/248) BREAKING CHANGES: * the proxy no longer uses prefixes for resources, if you wish to use wildcard urls you need diff --git a/README.md b/README.md index 0cf12d6..63ecb08 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ USAGE: keycloak-proxy [options] VERSION: - v2.1.0-rc2 (git+sha: ffe2fc4, built: 21-07-2017) + v2.1.0-rc2 (git+sha: 6782490-dirty, built: 06-07-2017) AUTHOR: Rohith <gambol99@gmail.com> @@ -54,6 +54,7 @@ GLOBAL OPTIONS: --skip-openid-provider-tls-verify skip the verification of any TLS communication with the openid provider (default: false) --scopes value list of scopes requested when authenticating the user --upstream-url value url for the upstream endpoint you wish to proxy [$PROXY_UPSTREAM_URL] + --upstream-ca value the path to a file container a CA certificate to validate the upstream tls endpoint --resources value list of resources 'uri=/admin|methods=GET,PUT|roles=role1,role2' --headers value custom headers to the upstream request, key=value --enable-token-header enables the token authentication header X-Auth-Token to upstream (default: true) diff --git a/config.go b/config.go index d969185..c98c0ed 100644 --- a/config.go +++ b/config.go @@ -65,11 +65,9 @@ func (r *Config) isValid() error { if r.TLSCaCertificate != "" && !fileExists(r.TLSCaCertificate) { return fmt.Errorf("the tls ca certificate file %s does not exist", r.TLSCaCertificate) } - if r.TLSClientCertificate != "" && !fileExists(r.TLSClientCertificate) { return fmt.Errorf("the tls client certificate %s does not exist", r.TLSClientCertificate) } - if r.UseLetsEncrypt && r.LetsEncryptCacheDir == "" { return fmt.Errorf("the letsencrypt cache dir has not been set") } @@ -100,6 +98,10 @@ func (r *Config) isValid() error { if _, err := url.Parse(r.Upstream); err != nil { return fmt.Errorf("the upstream endpoint is invalid, %s", err) } + if r.SkipUpstreamTLSVerify && r.UpstreamCA != "" { + return fmt.Errorf("you cannot skip upstream tls and load a root ca: %s to verify it", r.UpstreamCA) + } + // step: if the skip verification is off, we need the below if !r.SkipTokenVerification { if r.ClientID == "" { diff --git a/doc.go b/doc.go index 4d21a52..0a27bf0 100644 --- a/doc.go +++ b/doc.go @@ -125,6 +125,8 @@ type Config struct { Scopes []string `json:"scopes" yaml:"scopes" usage:"list of scopes requested when authenticating the user"` // Upstream is the upstream endpoint i.e whom were proxying to Upstream string `json:"upstream-url" yaml:"upstream-url" usage:"url for the upstream endpoint you wish to proxy" env:"UPSTREAM_URL"` + // UpstreamCA is the path to a CA certificate in PEM format to validate the upstream certificate + UpstreamCA string `json:"upstream-ca" yaml:"upstream-ca" usage:"the path to a file container a CA certificate to validate the upstream tls endpoint"` // Resources is a list of protected resources Resources []*Resource `json:"resources" yaml:"resources" usage:"list of resources 'uri=/admin|methods=GET,PUT|roles=role1,role2'"` // Headers permits adding customs headers across the board diff --git a/server.go b/server.go index b95e460..fddd051 100644 --- a/server.go +++ b/server.go @@ -529,6 +529,20 @@ func (r *oauthProxy) createUpstreamProxy(upstream *url.URL) error { tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert } + { + // @check if we have a upstream ca to verify the upstream + if r.config.UpstreamCA != "" { + r.log.Info("loading the upstream ca", zap.String("path", r.config.UpstreamCA)) + ca, err := ioutil.ReadFile(r.config.UpstreamCA) + if err != nil { + return err + } + pool := x509.NewCertPool() + pool.AppendCertsFromPEM(ca) + tlsConfig.RootCAs = pool + } + } + // create the forwarding proxy proxy := goproxy.NewProxyHttpServer() proxy.Logger = httplog.New(ioutil.Discard, "", 0) -- GitLab