Authentication
Envoy Gateway supports a number of distinct authentication mechanisms, including JWT, OIDC, external authorization, and basic auth.
In this exercise, we keep things simple and demonstrate basic auth.
Once more, we are dealing with a feature that is outside the current Gateway API specification, and so we use a SecurityPolicy attachment against the route we wish to protect, which in this case is the httpbin
route.
| ---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: httpbin-basicauth
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: httpbin
basicAuth:
users:
name: httpbin-users
|
The value of the name
field on line 13 refers a secret containing an htpasswd
file.
-
Create the htpasswd file:
htpasswd -cs .htpasswd eitan
-
Create the secret from the generated file:
kubectl create secret generic httpbin-users --from-file=.htpasswd
-
Apply the security policy:
kubectl apply -f auth/basic.yaml
Test it
Access the application, or:
-
Request without credentials return a 401 (Forbidden)
HTTP/2 401
content-length: 58
content-type: text/plain
date: Tue, 07 May 2024 23:18:11 GMT
-
Authenticated requests succeed:
HTTP/2 200
server: gunicorn/19.9.0
date: Tue, 07 May 2024 23:18:20 GMT
content-type: text/html; charset=utf-8
content-length: 9593
access-control-allow-origin: *
access-control-allow-credentials: true
-
Bad credentials produce a 401 (Forbidden):
HTTP/2 401
content-length: 66
content-type: text/plain
date: Tue, 07 May 2024 23:18:23 GMT
Inspect the Proxy configuration
We can look at the Envoy listeners configuration and inspect the HTTP connection manager's filter chain to confirm that the basic auth filter is installed.
egctl config envoy-proxy listener -n envoy-gateway-system \
-l gateway.envoyproxy.io/owning-gateway-name=eg \
-l gateway.envoyproxy.io/owning-gateway-namespace=default \
-o yaml | bat -l yaml
Here is sanitized output for the HTTPS listener:
| ...
filterChains:
- filterChainMatch:
serverNames:
- httpbin.esuez.org
filters:
- name: envoy.filters.network.http_connection_manager
typedConfig:
httpFilters:
- name: envoy.filters.http.basic_auth_httproute/default/httpbin/rule/0/match/0/httpbin_esuez_org
disabled: true
typedConfig:
'@type': type.googleapis.com/envoy.extensions.filters.http.basic_auth.v3.BasicAuth
users:
inlineBytes: W3JlZGFjdGVkXQ==
- name: envoy.filters.http.ratelimit
typedConfig:
'@type': type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit
domain: default/eg/https
enableXRatelimitHeaders: DRAFT_VERSION_03
rateLimitService:
grpcService:
envoyGrpc:
clusterName: ratelimit_cluster
transportApiVersion: V3
- name: envoy.filters.http.router
typedConfig:
'@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
suppressEnvoyHeaders: true
...
|
The basic auth filter is configured at the level of the listener, but disabled there.
Since the authentication rule is applied at the route level, we need to look at the route.
egctl config envoy-proxy route -n envoy-gateway-system \
-l gateway.envoyproxy.io/owning-gateway-name=eg \
-l gateway.envoyproxy.io/owning-gateway-namespace=default \
-o yaml | bat -l yaml
Here is the salient part of the output:
| envoy-gateway-system:
envoy-default-eg-e41e7b31-c7657fcf5-tmsdt:
dynamicRouteConfigs:
...
- routeConfig:
name: default/eg/https
virtualHosts:
- domains:
- httpbin.esuez.org
name: default/eg/https/httpbin_esuez_org
routes:
- match:
prefix: /
name: httproute/default/httpbin/rule/0/match/0/httpbin_esuez_org
route:
cluster: httproute/default/httpbin/rule/0
rateLimits:
...
typedPerFilterConfig:
envoy.filters.http.basic_auth:
'@type': type.googleapis.com/envoy.extensions.filters.http.basic_auth.v3.BasicAuthPerRoute
users:
inlineBytes: W3JlZGFjdGVkXQ==
|