Skip to content

For the complete documentation index, see llms.txt. Markdown versions of all docs pages are available by appending .md to any docs URL.

Page as Markdown

    

Restrict access based on claims

Use an rbac policy with Common Expression Language (CEL) expressions to allow or deny requests based on the claims in a verified JWT. The JWT filter writes the verified token payload to Envoy dynamic metadata, and your CEL expressions read the claims from that metadata. Because the rules depend on a verified token, configure rbac together with jwtAuth in the same TrafficPolicy.

Before you begin

  1. Follow the Get started guide to install kgateway.

  2. Follow the Sample app guide to create a gateway proxy with an HTTP listener and deploy the httpbin sample app.

  3. Get the external address of the gateway and save it in an environment variable.

    export INGRESS_GW_ADDRESS=$(kubectl get svc -n kgateway-system http -o jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}")
    echo $INGRESS_GW_ADDRESS  

  1. Complete the Basic JWT policy guide to set up JWT auth with an inline JWKS key. Save the sample JWT token in an environment variable.
    export TOKEN=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InNvbG8tcHVibGljLWtleS0wMDEifQ.eyJpc3MiOiJzb2xvLmlvIiwib3JnIjoic29sby5pbyIsInN1YiI6ImFsaWNlIiwidGVhbSI6ImRldiIsImV4cCI6MjA3NDI3NDg4NCwibGxtcyI6eyJvcGVuYWkiOlsiZ3B0LTMuNS10dXJibyJdfX0.il5Rjsad65jpQR_pyRzBdEKFSj-ERmBf4K2VksvGvswWVv4n79lYERslr4KCECuiz9y_T-xUiQ9IkhW3YHzl5zo1kajhhIg7Nhnl1AvAqODbnF6wYpLRk0Npna_2T6lK3Yj54qQGi6vXG3IMRpo1_o2DrbdlKx2k_WFegCoQyyYazb4z3ZXfWvTiWqQDJA5wWcM3-jKzAWfNM8zgZWa-1BeAHDvpLcfWtuXEGSjkdCW0FQJOTjgIEqACnnXb2Jio0tWgelh9hDPILI-tvanj3iKCjpf3uF6g8QWSBNoVFfu7F1jJgj5Aj1sX8AV-CQVu2aQx3EHRZ1mL_3w3qSRWPw

Allow access based on a claim

  1. Create a TrafficPolicy that enforces JWT authentication and allows only requests with a valid JWT that contains the team=dev claim. If the JWT does not include this claim, the request is denied.

    kubectl apply -f- <<EOF
    apiVersion: gateway.kgateway.dev/v1alpha1
    kind: TrafficPolicy
    metadata:
      name: jwt-policy
      namespace: kgateway-system
    spec:
      targetRefs:
        - group: gateway.networking.k8s.io
          kind: Gateway
          name: http
      jwtAuth:
        extensionRef:
          name: selfminted-jwt
      rbac:
        action: Allow
        policy:
          matchExpressions:
            - "metadata.filter_metadata['envoy.filters.http.jwt_authn']['payload']['team'] == 'dev'"
    EOF
    Field Description
    rbac.actionThe action to take when a request matches the policy, either Allow or Deny. Defaults to Allow, which permits only matching requests and denies all others.
    rbac.policy.matchExpressionsA list of CEL expressions. The policy matches when any one of the expressions evaluates to true. Reference verified JWT claims through the envoy.filters.http.jwt_authn filter metadata, in the form metadata.filter_metadata['envoy.filters.http.jwt_authn']['payload']['<claim>'].
  2. Send a request with the sample token from the previous guide. Because the JWT has a team claim that equals dev, the request matches the policy and is allowed with a 200 HTTP response. A request with a token where the team claim does not equal dev, or that has no team claim, is denied with a 403 HTTP response.

    curl -vik http://$INGRESS_GW_ADDRESS:8080/headers \
      -H "host: www.example.com:8080" \
      --header "Authorization: Bearer $TOKEN"

    Verify that you get a 200 OK response.

Other configurations

The following examples show other ways to write the rbac policy. Each one replaces the rbac block in the TrafficPolicy from the previous section.

Deny access based on a claim

Set action to Deny to deny requests that match the expressions and allow everything else. The following policy denies requests with a JWT where the team claim equals ops.

rbac:
  action: Deny
  policy:
    matchExpressions:
      - "metadata.filter_metadata['envoy.filters.http.jwt_authn']['payload']['team'] == 'ops'"

Match more than one claim

List multiple expressions to match on more than one condition. The policy matches when any expression evaluates to true (OR logic). The following policy allows requests if the JWT has a team=dev or sub=alice claim.

rbac:
  action: Allow
  policy:
    matchExpressions:
      - "metadata.filter_metadata['envoy.filters.http.jwt_authn']['payload']['team'] == 'dev'"
      - "metadata.filter_metadata['envoy.filters.http.jwt_authn']['payload']['sub'] == 'alice'"

To require multiple conditions in a single rule instead (AND logic), combine them in one expression with &&. The following policy allows a request only when the JWT contains the team=dev and org=solo.io claims.

rbac:
  action: Allow
  policy:
    matchExpressions:
      - "metadata.filter_metadata['envoy.filters.http.jwt_authn']['payload']['team'] == 'dev' && metadata.filter_metadata['envoy.filters.http.jwt_authn']['payload']['org'] == 'solo.io'"

Match an OAuth scope

You can authorize requests based on an OAuth scope, such as one that is issued by an identity provider. Unlike the single-value claims in the previous examples, the scope is conventionally a single string of space-delimited scopes, such as read write admin. To match one scope without accidentally matching a longer scope that contains it (for example, matching admin but not superadmin), split the string on spaces and test for membership in the resulting list. The following policy allows requests with a JWT where the scope includes admin.

rbac:
  action: Allow
  policy:
    matchExpressions:
      - "'admin' in metadata.filter_metadata['envoy.filters.http.jwt_authn']['payload']['scope'].split(' ')"
The sample token in the Basic JWT policy guide does not include a scope claim, so this example does not match that token. To try it out, use a token that carries a space-delimited scope claim. If your identity provider issues scope as a list instead of a string, drop the .split(' ') and match the list directly: "'admin' in metadata.filter_metadata['envoy.filters.http.jwt_authn']['payload']['scope']".

Cleanup

kubectl delete TrafficPolicy jwt-policy -n kgateway-system
kubectl delete gatewayextension selfminted-jwt -n kgateway-system
Was this page helpful?