diff --git a/helm/templates/deployment.yaml b/helm/templates/deployment.yaml index 66994c660..0c8f62c73 100644 --- a/helm/templates/deployment.yaml +++ b/helm/templates/deployment.yaml @@ -74,6 +74,13 @@ spec: name: {{ template "pomerium.fullname" . }} key: certificate-key {{- end }} +{{- if .Values.config.ca }} + - name: CERTIFICATE_AUTHORITY + valueFrom: + secretKeyRef: + name: {{ template "pomerium.fullname" . }} + key: certificate-authority +{{- end }} {{- if or (eq .Values.config.services "authenticate") (eq .Values.config.services "all") }} - name: REDIRECT_URL value: {{ .Values.authenticate.redirectUrl }} diff --git a/helm/templates/secret.yaml b/helm/templates/secret.yaml index c73dc1353..0182d662d 100644 --- a/helm/templates/secret.yaml +++ b/helm/templates/secret.yaml @@ -22,3 +22,6 @@ data: {{- if .Values.config.key }} certificate-key: {{ .Values.config.key | b64enc | quote }} {{- end }} +{{- if .Values.config.ca }} + certificate-authority: {{ .Values.config.ca | b64enc | quote }} +{{- end }} diff --git a/helm/values.yaml b/helm/values.yaml index ffd140dd4..e06396bea 100644 --- a/helm/values.yaml +++ b/helm/values.yaml @@ -19,13 +19,14 @@ authenticate: # All below required if config.serviceModes is "proxy" or "all" proxy: authenticateServiceUrl: https://example.com/oauth2/callback - routes: - "http.corp.example.com": "httpbin.org" + routes: {} + # routes: + # "http.corp.example.com": "httpbin.org" # For any other settings that are optional -# ADDRESS, POMERIUM_DEBUG, CERTIFICATE_FILE, CERTIFICATE_KEY_FILE +# ADDRESS, POMERIUM_DEBUG, CERTIFICATE_FILE, CERTIFICATE_KEY_FILE, CERTIFICATE_AUTHORITY_FILE, # PROXY_ROOT_DOMAIN, COOKIE_DOMAIN, COOKIE_EXPIRE, COOKIE_REFRESH, COOKIE_SECURE, COOKIE_HTTP_ONLY, IDP_SCOPES -# DEFAULT_UPSTREAM_TIMEOUT, PASS_ACCESS_TOKEN, SESSION_VALID_TTL, SESSION_LIFETIME_TTL, GRACE_PERIOD_TTL +# AUTHENTICATE_INTERNAL_URL, AUTHENTICATE_SERVICE_PORT, OVERRIDE_CERTIFICATE_NAME, DEFAULT_UPSTREAM_TIMEOUT, COOKIE_LIFETIME, extraEnv: {} extraArgs: {} diff --git a/proxy/authenticator/authenticator.go b/proxy/authenticator/authenticator.go index c9b505f1a..ce019db10 100644 --- a/proxy/authenticator/authenticator.go +++ b/proxy/authenticator/authenticator.go @@ -31,6 +31,10 @@ type Options struct { OverrideCertificateName string // Shared secret is used to authenticate a authenticate-client with a authenticate-server. SharedSecret string + // CA specifies the base64 encoded TLS certificate authority to use. + CA string + // CAFile specifies the TLS certificate authority file to use. + CAFile string } // New returns a new authenticate service client. Takes a client implementation name as an argument. diff --git a/proxy/authenticator/grpc.go b/proxy/authenticator/grpc.go index dcdcf4558..aa918da3e 100644 --- a/proxy/authenticator/grpc.go +++ b/proxy/authenticator/grpc.go @@ -3,8 +3,10 @@ import ( "context" "crypto/tls" "crypto/x509" + "encoding/base64" "errors" "fmt" + "io/ioutil" "strings" "time" @@ -39,9 +41,31 @@ func NewGRPC(opts *Options) (p *AuthenticateGRPC, err error) { connAddr = fmt.Sprintf("%s:%d", connAddr, opts.Port) } - cp, err := x509.SystemCertPool() - if err != nil { - return nil, err + var cp *x509.CertPool + if opts.CA != "" || opts.CAFile != "" { + cp = x509.NewCertPool() + var ca []byte + var err error + if opts.CA != "" { + ca, err = base64.StdEncoding.DecodeString(opts.CA) + if err != nil { + return nil, fmt.Errorf("failed to decode certificate authority: %v", err) + } + } else { + ca, err = ioutil.ReadFile(opts.CAFile) + if err != nil { + return nil, fmt.Errorf("certificate authority file %v not readable: %v", opts.CAFile, err) + } + } + if ok := cp.AppendCertsFromPEM(ca); !ok { + return nil, fmt.Errorf("failed to append CA cert to certPool") + } + } else { + newCp, err := x509.SystemCertPool() + if err != nil { + return nil, err + } + cp = newCp } log.Info(). diff --git a/proxy/proxy.go b/proxy/proxy.go index 23aabd6fe..c2277a6b6 100755 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -37,6 +37,8 @@ type Options struct { AuthenticateInternalAddr string `envconfig:"AUTHENTICATE_INTERNAL_URL"` OverrideCertificateName string `envconfig:"OVERRIDE_CERTIFICATE_NAME"` AuthenticatePort int `envconfig:"AUTHENTICATE_SERVICE_PORT"` + CA string `envconfig:"CERTIFICATE_AUTHORITY"` + CAFile string `envconfig:"CERTIFICATE_AUTHORITY_FILE"` // SigningKey is a base64 encoded private key used to add a JWT-signature to proxied requests. // See : https://www.pomerium.io/guide/signed-headers.html @@ -207,6 +209,8 @@ func New(opts *Options) (*Proxy, error) { OverrideCertificateName: opts.OverrideCertificateName, SharedSecret: opts.SharedKey, Port: opts.AuthenticatePort, + CA: opts.CA, + CAFile: opts.CAFile, }) return p, nil }