Protect your APIs
Create external auth and rate limit policies to protect your APIs.
Previously, you set up a developer portal in which your end users can discover your API products. Now, you protect your APIs by enforcing external auth and rate limiting policies. Together, these policies make up the usage plans for your API products. For more information, see About usage plans.
Before you begin
Complete the portal setup tutorial.
Complete the API product tutorial.
Optional: Complete the portal tutorial. You can also complete the portal tutorial after this tutorial, if you want to see the usage plans in the frontend portal.
Get the labels of your routes to use to apply policies to, such as with the example query.
kubectl get rt -n gloo-mesh-gateways -o=jsonpath='{range .items[*]}[{.metadata.name}, {.spec.http[*].name}, {.spec.http[*].labels}]{"\n"}{end}'
Example output:
- The
api-example-com-rt
route table does not have any route-level labels. To apply policies, you can add labels to those routes. - The
petstore-rt
route table has ausagePlans: dev-portal
label on itspets-api
,users-api
, andstore-api
routes. - The
tracks-rt
route table has ausagePlans: dev-portal
label on itstracks-api
route.
[api-example-com-rt, , ] [petstore-rt, pets-api users-api store-api, {"usagePlans":"dev-portal"} {"usagePlans":"dev-portal"} {"usagePlans":"dev-portal"} ] [tracks-rt, tracks-api, {"usagePlans":"dev-portal"}]
- The
Set up API key external auth
Require users to authenticate in requests to your API products. The following steps set up external authentication through API keys. The API keys are stored in Kubernetes secrets for simplicity. If you have a portal set up, your users can generate these API keys for themselves through the frontend portal. For more information about API keys, other backing storage options, or other external auth options such as OAuth, see the External auth for portal guide.
Step 1: Create the API key policy
To enforce external auth on the routes to your API products, create an external auth policy.
Select the external auth server to use. The example uses the default external auth server that you created when you installed Gloo Mesh Gateway.
kubectl apply -f - << EOF apiVersion: admin.gloo.solo.io/v2 kind: ExtAuthServer metadata: name: ext-auth-server namespace: gloo-mesh spec: destinationServer: ref: cluster: $CLUSTER_NAME name: ext-auth-service namespace: gloo-mesh port: name: grpc EOF
Create an API key external auth policy.
kubectl apply -f - << EOF apiVersion: security.policy.gloo.solo.io/v2 kind: ExtAuthPolicy metadata: name: api-key-auth namespace: default spec: applyToRoutes: - route: labels: usagePlans: dev-portal config: server: name: ext-auth-server namespace: gloo-mesh cluster: $CLUSTER_NAME glooAuth: configs: - apiKeyAuth: headerName: api-key headersFromMetadataEntry: x-solo-plan: name: usagePlan required: true k8sSecretApikeyStorage: labelSelector: extauth: apikey EOF
For more information, see the API docs.
Setting Description metadata.namespace
Create the external auth policy in the same namespace or import it into the same Gloo workspace as the external auth server. In this example, the policy is in the default namespace. applyToRoutes
Apply the policy to the tracks-api
route that you previously created in the API product’s route table. You apply policies by labels. Thetracks-api
route has theusagePlans: dev-portal
label.config.server
Select the external auth server that you configured in the previous step. headerName
Set the name of the header. In this example, requests must include the API key in the api-key
header.k8sSecretApikeyStorage
Select the Kubernetes secret where the API key details are stored. This value is only required if you use local Kubernetes secrets for testing. If you configured the external auth server to use Redis as a backing database, omit this value. Verify that requests to your API now require external auth. The following request fails because you do not have the API key details stored in a local Kubernetes secret.
curl -v -H 'api-key: apikey1' --resolve api.example.com:80:${INGRESS_GW_IP} http://api.example.com/trackapi/tracks
Example output:
< HTTP/1.1 401 Unauthorized < www-authenticate: API key is missing or invalid
Step 2: Verify authentication with an API key
Now that you applied an external auth policy to your routes, requests must include a valid API key in the X-Solo-Plan header. Gloo Mesh Gateway must be able to check the API keys in requests against valid API keys that are stored somewhere. In this example, you store the API key in a Kubernetes secret.
Create a Kubernetes secret with the details of your API key.
apikey1
is the API key that you later include in the request header. You can choose any string value for your API key.user1
is the user ID that must be included in the request metadata.user1@solo.io
is the email for the user.gold
is the name of a usage plan that matches the usage plans you set up as part of rate limiting.
kubectl apply -f - <<EOF apiVersion: v1 kind: Secret metadata: name: user1 namespace: default labels: extauth: apikey type: extauth.solo.io/apikey stringData: # apikey1 api-key: apikey1 # user1 user-id: user1 # user1@solo.io user-email: user1@solo.io # gold usagePlan: gold EOF
Verify that the secret is created.
kubectl get secret
Repeat the request with your API key details. Make sure to use the API key string value that you encoded earlier. The request now succeeds!
curl -v -H 'api-key: apikey1' --resolve api.example.com:80:${INGRESS_GW_IP} http://api.example.com/trackapi/tracks
Example output:
< HTTP/1.1 200 OK ... [ { "id": "c_0", "thumbnail": "https://res.cloudinary.com/dety84pbu/image/upload/v1598465568/nebula_cat_djkt9r.jpg", "topic": "Cat-stronomy", "authorId": "cat-1", "title": "Cat-stronomy, an introduction", "description": "Curious to learn what Cat-stronomy is all about? Explore the planetary and celestial alignments and how they have affected our space missions.", "numberOfViews": 163, "createdAt": "2018-09-10T07:13:53.020Z", "length": 2377, "modulesCount": 10, "modules": [ "l_0", "l_1", "l_2", "l_3", "l_4", "l_5", "l_6", "l_7", "l_8", "l_9" ] }, ...
Set up rate limiting
Control how many requests within a time period are allowed to your API products, such as 100 requests per minute. The rate limits form a key part of the usage plan for your API products. For more information about rate limiting or for other options such as dynamic rate limiting, see the Rate limiting for portal guide.
Select the rate limiting server to use. The example uses the default rate limiting server that you created when you installed Gloo Mesh Gateway. For more information, see Rate limit server settings.
kubectl apply -f - << EOF apiVersion: admin.gloo.solo.io/v2 kind: RateLimitServerSettings metadata: name: rl-server namespace: gloo-mesh labels: portal: rate-limit spec: destinationServer: port: name: grpc ref: cluster: $CLUSTER_NAME name: rate-limiter namespace: gloo-mesh EOF
Set up the rate limit client config to define the
usagePlan
descriptor key and extract details from thex-solo-plan
header that is set up in your matching external auth policy. The configuration varies depending on the type of external auth policy that you applied: API key or OAuth. For more information, see Rate limit client config.kubectl apply -f - <<EOF apiVersion: trafficcontrol.policy.gloo.solo.io/v2 kind: RateLimitClientConfig metadata: name: usage-plans namespace: gloo-mesh labels: portal: rate-limit spec: raw: rateLimits: - setActions: - requestHeaders: descriptorKey: usagePlan headerName: x-solo-plan - metadata: descriptorKey: userId metadataKey: key: envoy.filters.http.ext_authz path: - key: userId EOF
Use the RateLimitServerConfig to define the values of the descriptors that are the usage plan names, that match the
usagePlan
descriptor key that you configured in the RateLimitClientConfig. TheuserId
andusagePlan
details are extracted from the API key details in the request header that is required by the API key external auth policy. The following rate limit server config example creates three usage plans as follows:- Bronze: Requests to your APIs are limited to 1 per minute.
- Silver: Requests to your APIs are limited to 3 per minute.
- Gold: Requests to your APIs are limited to 5 per minute.
For more information, see Rate limit server config.
kubectl apply -f - << EOF apiVersion: admin.gloo.solo.io/v2 kind: RateLimitServerConfig metadata: name: usage-plans namespace: gloo-mesh labels: portal: rate-limit spec: destinationServers: - port: name: grpc ref: cluster: $CLUSTER_NAME name: rate-limiter namespace: gloo-mesh raw: setDescriptors: - simpleDescriptors: - key: userId - key: usagePlan value: bronze rateLimit: requestsPerUnit: 1 unit: MINUTE - simpleDescriptors: - key: userId - key: usagePlan value: silver rateLimit: requestsPerUnit: 3 unit: MINUTE - simpleDescriptors: - key: userId - key: usagePlan value: gold rateLimit: requestsPerUnit: 5 unit: MINUTE EOF
Apply the rate limit policy to the
tracks-api
route that you previously created in the API product’s route table. You apply policies by labels. Thetracks-api
route has theusagePlans: dev-portal
label.kubectl apply -f - << EOF apiVersion: trafficcontrol.policy.gloo.solo.io/v2 kind: RateLimitPolicy metadata: name: tracks-rate-limit namespace: default labels: portal: rate-limit spec: applyToRoutes: - route: labels: usagePlans: dev-portal config: ratelimitServerConfig: name: usage-plans namespace: gloo-mesh cluster: $CLUSTER_NAME ratelimitClientConfig: name: usage-plans namespace: gloo-mesh cluster: $CLUSTER_NAME serverSettings: name: rl-server namespace: gloo-mesh cluster: $CLUSTER_NAME phase: postAuthz: priority: 1 EOF
Verify that your rate limiting is in place by repeating the following request 6 times in a row. Because your user ID is limited to the
gold
usage plan’s limit of 5 requests per minute, the sixth time your request is blocked. Note that this step requires you to have set up API key external auth already.curl -v -H 'api-key: apikey1' --resolve api.example.com:80:${INGRESS_GW_IP} http://api.example.com/trackapi/tracks
Example output:
< HTTP/1.1 429 Too Many Requests < x-envoy-ratelimited: true
Next steps
Good job! Now, your APIs are secured by external auth and rate limit policies. Together, you can think of these policies as the usage plan for the API products in your developer portal.
Next, Secure access to the portal by requiring users to log in through an OpenID Connect (OIDC) provider.