diff --git a/examples/oidc-k8s-auth/README.md b/examples/oidc-k8s-auth/README.md index 298c10f35..407e6ea57 100644 --- a/examples/oidc-k8s-auth/README.md +++ b/examples/oidc-k8s-auth/README.md @@ -1,8 +1,8 @@ -# Protecting an API with JSON Web Tokens (JWTs) and Kubernetes authnz using Kuadrant +# Rate-limiting and protecting an API with JSON Web Tokens (JWTs) and Kubernetes authnz using Kuadrant -Example of protecting an API (the Toy Store API) with authentication based on ID tokens (signed JWTs) issued by an -OpenId Connect (OIDC) server (Keycloak) and alternative Kubernetes Service Account tokens, and authorization based on -Kubernetes RBAC, with permissions (bindings) stored as Kubernetes Roles and RoleBindings. +Example of rate-limiting and protecting an API (the Toy Store API) with authentication based on ID tokens (signed JWTs) +issued by an OpenId Connect (OIDC) server (Keycloak) and alternative Kubernetes Service Account tokens, and authorization +based on Kubernetes RBAC, with permissions (bindings) stored as Kubernetes Roles and RoleBindings. ## Pre-requisites @@ -10,7 +10,7 @@ Kubernetes RBAC, with permissions (bindings) stored as Kubernetes Roles and Role - [kubectl](https://kubernetes.io/docs/reference/kubectl/) command-line tool - [jq](https://stedolan.github.io/jq/) -## Run the guide ❶ → ❻ +## Run the guide ❶ → ❼ ### ❶ Setup the environment @@ -124,6 +124,15 @@ spec: user: valueFrom: authJSON: auth.identity.sub + response: + - name: rate-limit + json: + properties: + - name: userID + valueFrom: + authJSON: auth.identity.sub + wrapper: envoyDynamicMetadata + wrapperKey: ext_auth_data EOF ``` @@ -270,6 +279,61 @@ curl -H "Authorization: Bearer $SA_TOKEN" -H 'Host: api.toystore.com' -X POST ht # HTTP/1.1 403 Forbidden ``` +### ❼ Create the `RateLimitPolicy` + +```sh +kubectl apply -f -< **Note:** It may take a couple minutes for the RateLimitPolicy to be applied depending on your cluster. + +#### Try the API rate limited + +Send requests as the Keycloak-authenticated user: + +```sh +while :; do curl --write-out '%{http_code}' --silent --output /dev/null -H "Authorization: Bearer $ACCESS_TOKEN" -H 'Host: api.toystore.com' http://localhost:9080/toy | egrep --color "\b(429)\b|$"; sleep 1; done +``` + +Send requests as the service account: + +```sh +while :; do curl --write-out '%{http_code}' --silent --output /dev/null -H "Authorization: Bearer $SA_TOKEN" -H 'Host: api.toystore.com' http://localhost:9080/toy | egrep --color "\b(429)\b|$"; sleep 1; done +``` + +Each user should be entitled to a maximum of 5 requests to the API every 10 seconds. + +> **Note:** You may need to refresh the tokens if they are expired. + ## Cleanup ```sh diff --git a/examples/oidc-k8s-auth/ratelimitpolicy.yaml b/examples/oidc-k8s-auth/ratelimitpolicy.yaml new file mode 100644 index 000000000..1778f7351 --- /dev/null +++ b/examples/oidc-k8s-auth/ratelimitpolicy.yaml @@ -0,0 +1,30 @@ +# Rate limit policy to protect an API +# Each user ID is entitled to a limit of 5 requests to the API every 10 seconds. +apiVersion: kuadrant.io/v1beta1 +kind: RateLimitPolicy +metadata: + name: toystore-rate-limit +spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: toystore + rateLimits: + - configurations: + - actions: + - metadata: + descriptor_key: "userID" + default_value: "no-user" + metadata_key: + key: "envoy.filters.http.ext_authz" + path: + - segment: + key: "ext_auth_data" + - segment: + key: "userID" + limits: + - conditions: [] + maxValue: 5 + seconds: 10 + variables: + - userID