eas (pronounced eez) is primarily focused on lowering the barrier to
using various authentication schemes in a kubernetes environment (but it works
with any reverse proxy supporting external/forward auth). eas can be
deployed once and protect many services using disperse authentication methods
and providers. The goal is to make enabling authentication as easy as:
- generating a new
config_token(see below) - configuring the reverse proxy to use the service for external authentication
- benefit
Various authentication plugins are supported. Within a single
config_token you can enable as many as you would like which results in a
pipeline of authentication mechanisms being invoked. The first plugin to result
in a 2XX response code will allow the request to be serviced. If all
plugins fail, then by default the result from the final plugin defined in the
config_token will be returned to the client. You can however alter that on
a service-by-service basis by setting the fallback_plugin=plugin index (0
indexed) parameter on the authentication URL.
- htpasswd
- LDAP
- OpenID Connect
- oauth2
- request param
- request header
- request js
- jwt
- firebase jwt
- works with any proxy server (traefik, nginx, ambassador, istio, envoy, etc) that supports forward/external auth
- works with any
OpenID Connect/oauth2provider (tested predominantly withkeycloakbut it should be agnostic) - only requires 1 installation to service any number of providers/configurations/vhosts/domains
- passes tokens to the backing service via headers
- automatically refreshes tokens
- server-side
config_tokens CONFIG_TOKENS
If running multiple instances (HA) you will need a shared cache/store (see redis below). You only really need redis if:
- You are running HA
- You are using the
oidcoroauth2plugins
Refer to the HOWTO for a more detailed overview.
-
easmust be able to accessOIDC Provider -
user-agentmust be able to accessOIDC Provider -
user-agentmust be able to accessproxy -
user-agentmust be able to accesseas(ifredirect_uriis directly pointing toeasservice/oauth/callbackendpoint) -
proxymust be able to accesseas -
proxymust sendX-Forwarded-Host(localhost:8000) toeasin sub-request -
proxymust sendX-Forwarded-Uri(/anything/foo/bar?test=foo) toeasin sub-request -
proxymust sendX-Forwarded-Proto(http) toeasin sub-request -
proxyshould sendX-Forwarded-Method(GET) toeasin sub-request -
proxymust return non2XXresponses fromeasto browser -
proxymay forward2XXauth headerX-Id-Tokento backing service -
proxymay forward2XXauth headerX-Userinfoto backing service -
proxymay forward2XXauth headerX-Access-Tokento backing service -
proxymay forward2XXauth headerAuthorizationto backing service
EAS_CONFIG_TOKEN_SIGN_SECRET="foo" \
EAS_CONFIG_TOKEN_ENCRYPT_SECRET="bar" \
EAS_ISSUER_SIGN_SECRET="super secret" \
EAS_ISSUER_ENCRYPT_SECRET="blah" \
EAS_COOKIE_SIGN_SECRET="hello world" \
EAS_COOKIE_ENCRYPT_SECRET="something" \
EAS_SESSION_ENCRYPT_SECRET="baz" \
EAS_CONFIG_TOKEN_STORES='{}' \
EAS_LOG_LEVEL="info" \
EAS_PORT=8080 \
node src/server.js
docker run -d --name eas -p 8080:8080 \
-e EAS_CONFIG_TOKEN_SIGN_SECRET="foo" \
-e EAS_CONFIG_TOKEN_ENCRYPT_SECRET="bar" \
-e EAS_ISSUER_SIGN_SECRET="super secret" \
-e EAS_ISSUER_ENCRYPT_SECRET="blah" \
-e EAS_COOKIE_SIGN_SECRET="hello world" \
-e EAS_COOKIE_ENCRYPT_SECRET="something" \
-e EAS_SESSION_ENCRYPT_SECRET="baz" \
-e EAS_CONFIG_TOKEN_STORES='{}' \
-e EAS_LOG_LEVEL="info" \
-e EAS_PORT=8080 \
travisghansen/external-auth-server
A helm chart is supplied in the repo directly. Reviewing
values.yaml is highly
recommended as examples are provided for common use-cases.
helm repo add eas https://travisghansen.github.io/external-auth-server
helm repo update
helm upgrade \
--install \
--namespace=external-auth-server \
\
--set configTokenSignSecret=<random> \
--set configTokenEncryptSecret=<random> \
--set issuerSignSecret=<random> \
--set issuerEncryptSecret=<random> \
--set cookieSignSecret=<random> \
--set cookieEncryptSecret=<random> \
--set sessionEncryptSecret=<random> \
--set logLevel="info" \
\
--set redis-ha.enabled=true \
--set redis-ha.auth=true \
--set redis-ha.redisPassword=53c237 \
\
--set storeOpts.store=ioredis \
--set storeOpts.password=53c237 \
--set storeOpts.name=mymaster \
--set storeOpts.sentinels[0].host=eas-redis-ha-announce-0 \
--set storeOpts.sentinels[0].port=26379 \
--set storeOpts.sentinels[1].host=eas-redis-ha-announce-1 \
--set storeOpts.sentinels[1].port=26379 \
--set storeOpts.sentinels[2].host=eas-redis-ha-announce-2 \
--set storeOpts.sentinels[2].port=26379 \
--set storeOpts.keyPrefix="eas:" \
\
--set ingress.enabled=true \
--set ingress.hosts[0]=eas.example.com \
--set ingress.paths[0]=/ \
eas eas/external-auth-server
# please edit the values in bin/generate-config-token.js to your situation
# ie: issuer disovery URL, client_id, client_secret, etc
# also make sure to use the same secrets used when launching the server
EAS_CONFIG_TOKEN_SIGN_SECRET="foo" \
EAS_CONFIG_TOKEN_ENCRYPT_SECRET="bar" \
node bin/generate-config-token.js
# alternatively you may use the following to create tokens
# files can be either json or yaml
cat config-token.json | docker run --rm -i -e EAS_CONFIG_TOKEN_SIGN_SECRET=foo -e EAS_CONFIG_TOKEN_ENCRYPT_SECRET=bar travisghansen/external-auth-server generate-config-token
cat config-token.json | EAS_CONFIG_TOKEN_SIGN_SECRET=foo EAS_CONFIG_TOKEN_ENCRYPT_SECRET=bar npm run generate-config-token
# See full examples in the ./examples/ directory
# particularly nginx has some particular requirements
# NOTE: run over https in production
# NOTE: take care to NOT authenticate `eas` with itself (this is particularly
# possible to happen in service mesh scenarios), whatever tool you use should
# ensure access to the `eas` service bypasses authentication thereby avoiding
# recursive behavior
# traefik
address = http://<eas server ip>:8080/verify?config_token=<token output from above>
# nginx (see examples/nginx.conf)
proxy_pass "http://<eas server ip>:8080/verify?redirect_http_code=401&config_token=<token output from above>";
# ingress-nginx (see examples/ingress-nginx.yaml)
# nginx-ingress-controller (see examples/nginx-ingress-controller.yaml)
# traefik ingress
ingress.kubernetes.io/auth-type: forward
ingress.kubernetes.io/auth-url: "https://eas.example.com/verify?config_token=CONFIG_TOKEN_HERE"
ingress.kubernetes.io/auth-response-headers: X-Userinfo, X-Id-Token, X-Access-Token, Authorization
# ambassador (see file in examples directory)
# istio (see file in examples directory)
# haproxy-ingress (see file in examples directory)
# contour (see file in examples directory)
# envoy (see file in examples directory)
Configure the external auth URL to point to the services /verify
endpoint. The URL supports the following query params:
config_token=the encrypted configuration tokenredirect_http_code=code(only use with nginx to overcome external auth module limitations (should be set to401), otherwise omitted)fallback_plugin=plugin indexif all plugins fail authentication which plugin response should be returned to the client
If your provider does not support wildcards you may expose eas directly and
set the config_token redirect_uri to the eas service at the
/oauth/callback path.
EAS_SSL_CERTpath to ssl cert file to enable httpsEAS_SSL_KEYpath to ssl key file to enable httpsEAS_GRPC_ADDRESSthe address to start the grpc server on (default is0.0.0.0)EAS_GRPC_PORTport the grpc server is bound to (default is50051)EAS_GRPC_SSL_CERTpath to ssl cert file to enable httpsEAS_GRPC_SSL_KEYpath to ssl key file to enable httpsEAS_ALLOW_EVALallow for potentially unsafe execution of untrusted code (enablesrequest_jsandjsquery engine)EAS_ALLOW_PLAIN_SERVER_SIDE_TOKENSallows server-side token to be unsigned (ie: store plain json/yaml in the store(s))
Support for sentinel, see bin/generate-store-opts.js with further options.
EAS_STORE_OPTS='{"store":"ioredis","host":"localhost"}'
No support for sentinel currently, see bin/generate-store-opts.js with further options.
EAS_STORE_OPTS='{"store":"redis","host":"localhost"}'