PlanPolicy for tiered service offerings
You can use a PlanPolicy object to implement tiered service offerings where different users receive different rate limits based on their subscription plan or other attributes.
|
Note
|
The |
A PlanPolicy works in conjunction with AuthPolicy and RateLimitPolicy custom resources (CRs) in the following sequence:
-
An
AuthPolicyCR authenticates a user request with stored identity metadata, including their plan information. -
The
PlanPolicyobject evaluates CEL predicate expressions against the authenticated identity to determine the user’s plan tier. -
Connectivity Link then enforces the rate limits defined for the user-matched plan tier.
The PlanPolicy object has the following known limitations:
-
A
PlanPolicyobject can only targetHTTPRoute,GRPCRoute, andGatewaycustom resources defined in the same namespace as thePlanPolicyobject. -
Plan predicates are evaluated in order. More specific predicates must appear before more general ones to ensure correct plan assignment.
-
Plan identification requires authentication to be configured through an AuthPolicy.
Create an AuthPolicy with API key authentication
You can configure API key authentication on an HTTPRoute object by deploying an AuthPolicy custom resource (CR) and creating per-plan API key secrets, so that Connectivity Link can identify which rate-limiting plan applies to each request.
-
You installed Connectivity Link.
-
You installed OpenShift CLI (
oc). -
You are logged in to your cluster.
-
You created the
HTTPRouteobject for your deployment.
|
Note
|
A |
-
Create an
AuthPolicyCR that targets theHTTPRouteobject and enables API key authentication by using the following example:Example API keyAuthPolicyCRapiVersion: kuadrant.io/v1 kind: AuthPolicy metadata: name: <sample_app> namespace: ${KUADRANT_DEVELOPER_NS} spec: targetRef: group: gateway.networking.k8s.io kind: HTTPRoute name: <sample_app> rules: authentication: "api-key-plan": apiKey: selector: matchLabels: app: <sample_app> allNamespaces: true credentials: authorizationHeader: prefix: APIKEY-
Replace
<sample_app>with the name of your application. -
Replace
$KUADRANT_DEVELOPER_NSwith the namespace for the object. -
The
spec.rules.authentication."api-key-plan".apiKey.selector.matchLabelsfield value points to the API keySecretsobjects that carry theapp: <sample_app>label. -
Setting
spec.rules.rules.authentication."api-key-plan".apiKey.selector.allNamespaces: trueallows secrets from any namespace to be matched.
-
-
Apply the policy by running the following command:
$ oc apply -f <authpolicy.yaml>Replace
<authpolicy.yaml>with the name of your YAML.
Verify the acceptance of the AuthPolicy CR
You can confirm the acceptance of the AuthPolicy custom resource (CR) by running a command.
-
Confirm that the
AuthPolicyCR was accepted by checking its status by running the following command:$ oc get authpolicy <sample_app> -n $(KUADRANT_DEVELOPER_NS) -o jsonpath='{.status.conditions[?(@.type=="Accepted")].message}{"\n"}{.status.conditions[?(@.type=="Enforced")].message}'-
Replace
<sample_app>with the name of your application. -
Replace
$(KUADRANT_DEVELOPER_NS)with the namespace for the object.Example outputAuthPolicy has been accepted AuthPolicy has been successfully enforced
-
Create API key Secret objects
You can create API key 'Secret` objects for each plan tier.
|
Important
|
The following example creates API key |
-
Create API key
Secretobjects for each plan tier that you want to use. EachSecretmust carry theauthorino.kuadrant.io/managed-by: authorinolabel and asecret.kuadrant.io/plan-idannotation that identifies the plan tier as shown in the following example:ExampleSecretobject for plan tiersapiVersion: v1 kind: Secret metadata: name: <gold_key> namespace: ${KUADRANT_DEVELOPER_NS} labels: authorino.kuadrant.io/managed-by: authorino app: <sample_app> annotations: secret.kuadrant.io/plan-id: gold stringData: api_key: <gold_api_key_value> type: Opaque --- apiVersion: v1 kind: Secret metadata: name: <silver_key> namespace: ${KUADRANT_DEVELOPER_NS} labels: authorino.kuadrant.io/managed-by: authorino app: <sample_app> annotations: secret.kuadrant.io/plan-id: silver stringData: api_key: <silver_api_key_value> type: Opaque --- apiVersion: v1 kind: Secret metadata: name: <bronze_key> namespace: ${KUADRANT_DEVELOPER_NS} labels: authorino.kuadrant.io/managed-by: authorino app: <sample_app> annotations: secret.kuadrant.io/plan-id: bronze stringData: api_key: <bronze_api_key_value> type: Opaque-
Replace 'KUADRANT_DEVELOPER_NS' with the namespace for the object.
-
Replace
<sample_app>with the name of your application. -
Replace
<gold_key>,<silver_key>, and<bronze_key>with the actual API keys for each tier. -
Replace
<gold_api_key_value>,<silver_api_key_value>, and<bronze_api_key_value>with the actual API key strings you want to assign to each tier.
-
-
Apply the
Secretobjects by running the following command:$ oc apply -f <secrets.yaml>Replace
<secrets.yaml>with the name of your YAML.
Verify the presence of the API key secrets
You can confirm the presence of the API key secrets by running a few commands.
-
Confirm that all three API key secrets are present in the gateway namespace by running the following command:
$ oc get secrets -n ${KUADRANT_DEVELOPER_NS} -l app=<sample_app>-
Replace
${KUADRANT_DEVELOPER_NS}with the developer namespace for Connectivity Link. -
Replace
<sample_app>with the name of your application.Example outputbronze_key Opaque 1 2 mins gold_key Opaque 1 2 mins silver_key Opaque 1 2 mins
-
-
Send a request without an API key and confirm that it is rejected by running the following command:
$ curl http://<gateway_hostname>/toy -iReplace
<gateway_hostname>with the hostname for your API.Example outputHTTP/1.1 401 Unauthorized -
Send a request with a valid API key and confirm that it succeeds by running the following command:
$ curl -H "Authorization: <gold_api_key_value>" http://<gateway_hostname>/toy -i-
Replace
<gold_api_key_value>with the actual API key string. -
Replace
<gateway_hostname>with the hostname for your API.Example outputHTTP/1.1 200 OK
-
Deploy plan-based rate limiting with a PlanPolicy
After you create your AuthPolicy and Secret objects, you can create a PlanPolicy object to enforce tiered rate limits on specific authenticated users.
|
Note
|
You can create a |
-
You installed Connectivity Link
-
You installed OpenShift CLI (
oc). -
You are logged in to your cluster.
-
You created the
HTTPRouteobject for your deployment. -
You configured API key-based authentication.
|
Note
|
A |
-
Create a
PlanPolicyobject to enforce plan-based rate limits on theHTTPRouteobject by using the following example:ExamplePlanPolicyobjectapiVersion: extensions.kuadrant.io/v1alpha1 kind: PlanPolicy metadata: name: <sample_app> namespace: ${KUADRANT_DEVELOPER_NS} spec: targetRef: group: gateway.networking.k8s.io kind: HTTPRoute name: <sample_app> plans: - tier: gold predicate: | has(auth.identity) && auth.identity.metadata.annotations["secret.kuadrant.io/plan-id"] == "gold" limits: daily: 5 - tier: silver predicate: | has(auth.identity) && auth.identity.metadata.annotations["secret.kuadrant.io/plan-id"] == "silver" limits: daily: 2 - tier: bronze predicate: | has(auth.identity) && auth.identity.metadata.annotations["secret.kuadrant.io/plan-id"] == "bronze" limits: daily: 1NoteThe
PlanPolicyobject uses thespec.plans.limitsparameter to enforce rate limits at the plan tier level instead of the individual subscriber level.-
Replace
<sample_app>with the name of your application. -
Replace 'KUADRANT_DEVELOPER_NS' with the namespace for your object.
-
Each
spec.plans.predicateis a CEL expression. Thepredicatesare evaluated in order, and the first matching plan is applied to the authenticated user.NoteThe Common Expression Language (CEL) expressions can be anything that applies to your use case. You can use an expression different from the
secret.kuadrant.io/plan-idexpression. -
The
limitsfield supports the following windows:daily,weekly,monthly,yearly, andcustom. Custom limits take alimitvalue and awindowduration string, for example:limits: daily: 100 weekly: 500 monthly: 2000 custom: - limit: 10 window: "1m"
-
-
Apply the
PlanPolicyobject by running the following command:$ oc apply -f <planpolicy.yaml>Replace
<planpolicy.yaml>with the name of your YAML.
Verify the acceptance of the PlanPolicy CR
You can confirm the acceptance of the PlanPolicy custom resource (CR) by running a command.
-
Confirm that the
PlanPolicyCR is accepted by running the following command:$ oc get planpolicy <sample_app> -n ${KUADRANT_DEVELOPER_NS} -o jsonpath='{.status.conditions[?(@.type=="Accepted")].message}{"\n"}{.status.conditions[?(@.type=="Enforced")].message}'-
Replace
<sample_app>with the name of your application. -
Replace
${KUADRANT_DEVELOPER_NS}with the namespace for your object.Example outputPlanPolicy has been accepted PlanPolicy has been successfully enforced
-
Verify the PlanPolicy enforcement of ratelimiting
You can verify that rate limiting is enforced by the PlanPolicy object by running several commands.
-
Confirm that the
AuthConfigobject was updated with plan data from thePlanPolicyobject by running the following command:$ oc get authconfig -n <kuadrant_system> -o yaml-
Replace
<kuadrant_system>with the namespace where your Connectivity Link instance is deployed. -
The output is expected to include plan information in the response section of the
AuthConfigobject.
-
-
Send a request without an API key and confirm that it is rejected by running the following command:
$ curl <gateway_hostname>/toy -iReplace
<gateway_hostname>with the hostname for your API.Example outputHTTP/1.1 401 Unauthorized -
Send a request using the
bronze-tierAPI key and confirm that it succeeds by running the following command:$ curl -H 'Authorization: <bronze_api_key_value>' <gateway_hostname>/toy -i-
Replace
<bronze_api_key_value>with the actual API key string. -
Replace
<gateway_hostname>with the hostname for your API.Example outputHTTP/1.1 200 OK
-
-
Send a second request using the
bronze-tierAPI key and confirm that it is rate limited by running the following command:$ curl -H 'Authorization: <bronze_api_key_value>' <gateway_hostname>/toy -i-
Replace
<bronze_api_key_value>with the actual API key string. -
Replace
<gateway_hostname>with the hostname for your API.Example outputHTTP/1.1 429 Too Many Requests
-
-
Confirm that the
gold-tierkey allows up to 5 requests per day before the limit is enforced.