git.iko.soy/typeable/oauth2-proxy
on master help sign in
Merge branch 'master' into enhanced_logging
commit88c518885ce09c017c2c89075e4d9784fcfe1248 authorMister Wil <1091741+MisterWil@users.noreply.github.com> dateTue 16 Apr 2019, 06:53 (8 years ago) parent79bcfeb46a0d7c
7 files changed+62−10
CHANGELOG.md+2 Dockerfile+8−2 Dockerfile.arm64+8−2 Dockerfile.armv6+8−2 README.md+12−1 main.go+2−1 options.go+22−2
CHANGELOG.md+2
@@ -16,6 +16,8 @@
1616 - `-standard-logging-format` Sets the format for standard logging
1717 - `-auth-logging-format` Sets the format for auth logging
1818
19+- [#111](https://github.com/pusher/oauth2_proxy/pull/111) Add option for telling where to find a login.gov JWT key file (@timothy-spencer)
20+
1921# v3.2.0
2022
2123## Release highlights
Dockerfile+8−2
@@ -11,13 +11,19 @@ COPY . .
1111# Fetch dependencies
1212RUN dep ensure --vendor-only
1313
14−# Build binary
15−RUN ./configure && make build
14+# Build binary and make sure there is at least an empty key file.
15+# This is useful for GCP App Engine custom runtime builds, because
16+# you cannot use multiline variables in their app.yaml, so you have to
17+# build the key into the container and then tell it where it is
18+# by setting OAUTH2_PROXY_JWT_KEY_FILE=/etc/ssl/private/jwt_signing_key.pem
19+# in app.yaml instead.
20+RUN ./configure && make build && touch jwt_signing_key.pem
1621
1722# Copy binary to alpine
1823FROM alpine:3.8
1924COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
2025COPY --from=builder /go/src/github.com/pusher/oauth2_proxy/oauth2_proxy /bin/oauth2_proxy
26+COPY --from=builder /go/src/github.com/pusher/oauth2_proxy/jwt_signing_key.pem /etc/ssl/private/jwt_signing_key.pem
2127
2228RUN addgroup -S -g 2000 oauth2proxy && adduser -S -u 2000 oauth2proxy -G oauth2proxy
2329USER oauth2proxy
Dockerfile.arm64+8−2
@@ -11,13 +11,19 @@ COPY . .
1111# Fetch dependencies
1212RUN dep ensure --vendor-only
1313
14−# Build binary
15−RUN ./configure && GOARCH=arm64 make build
14+# Build binary and make sure there is at least an empty key file.
15+# This is useful for GCP App Engine custom runtime builds, because
16+# you cannot use multiline variables in their app.yaml, so you have to
17+# build the key into the container and then tell it where it is
18+# by setting OAUTH2_PROXY_JWT_KEY_FILE=/etc/ssl/private/jwt_signing_key.pem
19+# in app.yaml instead.
20+RUN ./configure && GOARCH=arm64 make build && touch jwt_signing_key.pem
1621
1722# Copy binary to alpine
1823FROM arm64v8/alpine:3.8
1924COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
2025COPY --from=builder /go/src/github.com/pusher/oauth2_proxy/oauth2_proxy /bin/oauth2_proxy
26+COPY --from=builder /go/src/github.com/pusher/oauth2_proxy/jwt_signing_key.pem /etc/ssl/private/jwt_signing_key.pem
2127
2228RUN addgroup -S -g 2000 oauth2proxy && adduser -S -u 2000 oauth2proxy -G oauth2proxy
2329USER oauth2proxy
Dockerfile.armv6+8−2
@@ -11,13 +11,19 @@ COPY . .
1111# Fetch dependencies
1212RUN dep ensure --vendor-only
1313
14−# Build binary
15−RUN ./configure && GOARCH=arm GOARM=6 make build
14+# Build binary and make sure there is at least an empty key file.
15+# This is useful for GCP App Engine custom runtime builds, because
16+# you cannot use multiline variables in their app.yaml, so you have to
17+# build the key into the container and then tell it where it is
18+# by setting OAUTH2_PROXY_JWT_KEY_FILE=/etc/ssl/private/jwt_signing_key.pem
19+# in app.yaml instead.
20+RUN ./configure && GOARCH=arm GOARM=6 make build && touch jwt_signing_key.pem
1621
1722# Copy binary to alpine
1823FROM arm32v6/alpine:3.8
1924COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
2025COPY --from=builder /go/src/github.com/pusher/oauth2_proxy/oauth2_proxy /bin/oauth2_proxy
26+COPY --from=builder /go/src/github.com/pusher/oauth2_proxy/jwt_signing_key.pem /etc/ssl/private/jwt_signing_key.pem
2127
2228RUN addgroup -S -g 2000 oauth2proxy && adduser -S -u 2000 oauth2proxy -G oauth2proxy
2329USER oauth2proxy
README.md+12−1
@@ -216,6 +216,13 @@ Now start the proxy up with the following options:
216216 -jwt-key="${OAUTH2_PROXY_JWT_KEY}"
217217```
218218You can also set all these options with environment variables, for use in cloud/docker environments.
219+One tricky thing that you may encounter is that some cloud environments will pass in environment
220+variables in a docker env-file, which does not allow multiline variables like a PEM file.
221+If you encounter this, then you can create a `jwt_signing_key.pem` file in the top level
222+directory of the repo which contains the key in PEM format and then do your docker build.
223+The docker build process will copy that file into your image which you can then access by
224+setting the `OAUTH2_PROXY_JWT_KEY_FILE=/etc/ssl/private/jwt_signing_key.pem`
225+environment variable, or by setting `-jwt-key-file=/etc/ssl/private/jwt_signing_key.pem` on the commandline.
219226
220227Once it is running, you should be able to go to `http://localhost:4180/` in your browser,
221228get authenticated by the login.gov integration server, and then get proxied on to your
@@ -261,6 +268,7 @@ An example [oauth2_proxy.cfg](contrib/oauth2_proxy.cfg.example) config file is i
261268
262269```
263270Usage of oauth2_proxy:
271+ -acr-values string: optional, used by login.gov (default "http://idmanagement.gov/ns/assurance/loa/1")
264272 -approval-prompt string: OAuth approval_prompt (default "force")
265273 -auth-logging: Log authentication attempts (default true)
266274 -auth-logging-format string: Template for authentication log lines (see "Logging Configuration" paragraph below)
@@ -271,10 +279,10 @@ Usage of oauth2_proxy:
271279 -client-secret string: the OAuth Client Secret
272280 -config string: path to config file
273281 -cookie-domain string: an optional cookie domain to force cookies to (ie: .yourcompany.com)
274− -cookie-path string: an optional cookie path to force cookies to (ie: /foo)
275282 -cookie-expire duration: expire timeframe for cookie (default 168h0m0s)
276283 -cookie-httponly: set HttpOnly cookie flag (default true)
277284 -cookie-name string: the name of the cookie that the oauth_proxy creates (default "_oauth2_proxy")
285+ -cookie-path string: an optional cookie path to force cookies to (ie: /poc/)* (default "/")
278286 -cookie-refresh duration: refresh the cookie after this duration; 0 to disable
279287 -cookie-secret string: the seed string for secure cookies (optionally base64 encoded)
280288 -cookie-secure: set secure (HTTPS) cookie flag (default true)
@@ -298,6 +306,8 @@ Usage of oauth2_proxy:
298306 -logging-max-age int: Maximum number of days to retain old log files (default 7)
299307 -logging-max-backups int: Maximum number of old log files to retain; 0 to disable (default 0)
300308 -logging-max-size int: Maximum size in megabytes of the log file before rotation (default 100)
309+ -jwt-key string: private key in PEM format used to sign JWT, so that you can say something like -jwt-key="${OAUTH2_PROXY_JWT_KEY}": required by login.gov
310+ -jwt-key-file string: path to the private key file in PEM format used to sign the JWT so that you can say something like -jwt-key-file=/etc/ssl/private/jwt_signing_key.pem: required by login.gov
301311 -login-url string: Authentication endpoint
302312 -oidc-issuer-url: the OpenID Connect issuer URL. ie: "https://accounts.google.com"
303313 -oidc-jwks-url string: OIDC JWKS URI for token verification; required if OIDC discovery is disabled
@@ -310,6 +320,7 @@ Usage of oauth2_proxy:
310320 -provider string: OAuth provider (default "google")
311321 -proxy-prefix string: the url root path that this proxy should be nested under (e.g. /<oauth2>/sign_in) (default "/oauth2")
312322 -proxy-websockets: enables WebSocket proxying (default true)
323+ -pubjwk-url string: JWK pubkey access endpoint: required by login.gov
313324 -redeem-url string: Token redemption endpoint
314325 -redirect-url string: the OAuth Redirect URL. ie: "https://internalapp.yourcompany.com/oauth2/callback"
315326 -request-logging: Log requests to stdout (default true)
main.go+2−1
@@ -105,7 +105,8 @@ func main() {
105105
106106 flagSet.String("signature-key", "", "GAP-Signature request signature key (algorithm:secretkey)")
107107 flagSet.String("acr-values", "http://idmanagement.gov/ns/assurance/loa/1", "acr values string: optional, used by login.gov")
108− flagSet.String("jwt-key", "", "private key used to sign JWT: required by login.gov")
108+ flagSet.String("jwt-key", "", "private key in PEM format used to sign JWT, so that you can say something like -jwt-key=\"${OAUTH2_PROXY_JWT_KEY}\": required by login.gov")
109+ flagSet.String("jwt-key-file", "", "path to the private key file in PEM format used to sign the JWT so that you can say something like -jwt-key-file=/etc/ssl/private/jwt_signing_key.pem: required by login.gov")
109110 flagSet.String("pubjwk-url", "", "JWK pubkey access endpoint: required by login.gov")
110111 flagSet.Bool("gcp-healthchecks", false, "Enable GCP/GKE healthcheck endpoints")
111112
options.go+22−2
@@ -6,6 +6,7 @@ import (
66 "crypto/tls"
77 "encoding/base64"
88 "fmt"
9+ "io/ioutil"
910 "net/http"
1011 "net/url"
1112 "os"
@@ -103,6 +104,7 @@ type Options struct {
103104 SignatureKey string `flag:"signature-key" cfg:"signature_key" env:"OAUTH2_PROXY_SIGNATURE_KEY"`
104105 AcrValues string `flag:"acr-values" cfg:"acr_values" env:"OAUTH2_PROXY_ACR_VALUES"`
105106 JWTKey string `flag:"jwt-key" cfg:"jwt_key" env:"OAUTH2_PROXY_JWT_KEY"`
107+ JWTKeyFile string `flag:"jwt-key-file" cfg:"jwt_key_file" env:"OAUTH2_PROXY_JWT_KEY_FILE"`
106108 PubJWKURL string `flag:"pubjwk-url" cfg:"pubjwk_url" env:"OAUTH2_PROXY_PUBJWK_URL"`
107109 GCPHealthChecks bool `flag:"gcp-healthchecks" cfg:"gcp_healthchecks" env:"OAUTH2_PROXY_GCP_HEALTHCHECKS"`
108110
@@ -352,15 +354,33 @@ func parseProviderInfo(o *Options, msgs []string) []string {
352354 case *providers.LoginGovProvider:
353355 p.AcrValues = o.AcrValues
354356 p.PubJWKURL, msgs = parseURL(o.PubJWKURL, "pubjwk", msgs)
355− if o.JWTKey == "" {
357+
358+ // JWT key can be supplied via env variable or file in the filesystem, but not both.
359+ switch {
360+ case o.JWTKey != "" && o.JWTKeyFile != "":
361+ msgs = append(msgs, "cannot set both jwt-key and jwt-key-file options")
362+ case o.JWTKey == "" && o.JWTKeyFile == "":
356363 msgs = append(msgs, "login.gov provider requires a private key for signing JWTs")
357− } else {
364+ case o.JWTKey != "":
365+ // The JWT Key is in the commandline argument
358366 signKey, err := jwt.ParseRSAPrivateKeyFromPEM([]byte(o.JWTKey))
359367 if err != nil {
360368 msgs = append(msgs, "could not parse RSA Private Key PEM")
361369 } else {
362370 p.JWTKey = signKey
363371 }
372+ case o.JWTKeyFile != "":
373+ // The JWT key is in the filesystem
374+ keyData, err := ioutil.ReadFile(o.JWTKeyFile)
375+ if err != nil {
376+ msgs = append(msgs, "could not read key file: "+o.JWTKeyFile)
377+ }
378+ signKey, err := jwt.ParseRSAPrivateKeyFromPEM(keyData)
379+ if err != nil {
380+ msgs = append(msgs, "could not parse private key from PEM file:"+o.JWTKeyFile)
381+ } else {
382+ p.JWTKey = signKey
383+ }
364384 }
365385 }
366386 return msgs