Before you begin

Complete the guide to set up credential management for APIs by using API keys or an OAuth client.

Step 1: Set up a default rate limit for an API

You can enforce basic rate limits for an API that automatically applies to all subscriptions to that API. The following example walks you through how to set up a default rate limit for the tracks API.

  1. Create a RateLimitConfig to limit requests to 5 per minute.

      kubectl apply -f- <<EOF   
    apiVersion: ratelimit.solo.io/v1alpha1
    kind: RateLimitConfig
    metadata:
      name: tracks-rl
      namespace: gloo-system
    spec:
      raw:
        setDescriptors:
          - simpleDescriptors:
              - key: generic_key
                value: counter
            rateLimit:
              requestsPerUnit: 5
              unit: MINUTE
        rateLimits:
          - setActions:
              - genericKey:
                  descriptorValue: counter
    EOF
      
  2. Add the RateLimitConfig to the same RouteOption resource that you used when you set up credential management for an API.

      kubectl apply -f- <<EOF
    apiVersion: gateway.solo.io/v1
    kind: RouteOption
    metadata:
      name: tracks
      namespace: gloo-system
    spec:
      options:
        extauth:
          configRef:
            name: tracks-auth
            namespace: gloo-system
        rateLimitConfigs:
          refs:
            - name: tracks-rl
              namespace: gloo-system
        cors: 
          allowCredentials: true
          allowHeaders:
          - "*"
          allowMethods:
          - GET
          allowOriginRegex:
          - ".*"
    EOF
      
  3. Verify that the rate limit is applied. For example, Portal users can follow the steps in Test API access to send multiple requests to the tracks API via the frontend app. If you have a valid API key or ID token, you can also use the following curl requests. Verify that you are rate limited after 5 successful requests and that a 429 HTTP response code is returned.

    • API key:
      for i in {1..6}; do curl -I https://tracks.example.com/tracks -H "api-key: <apikey>"; done
      
    • ID token:
      for i in {1..6}; do curl -vik https://tracks.example.com/tracks -H "Authorization: Bearer <id_token>"; done
      

    Example output:

      HTTP/2 200 
    x-powered-by: tinyhttp
    access-control-allow-origin: *
    access-control-allow-methods: GET, HEAD, PUT, PATCH, POST, DELETE
    access-control-allow-headers: content-type
    content-type: text/html; charset=utf-8
    etag: W/"627-v25siNUZqtFMwVFrEcJ5PHKH9xk"
    date: Thu, 12 Dec 2024 16:25:53 GMT
    x-envoy-upstream-service-time: 3
    server: envoy
    
    HTTP/2 200 
    x-powered-by: tinyhttp
    access-control-allow-origin: *
    access-control-allow-methods: GET, HEAD, PUT, PATCH, POST, DELETE
    access-control-allow-headers: content-type
    content-type: text/html; charset=utf-8
    etag: W/"627-v25siNUZqtFMwVFrEcJ5PHKH9xk"
    date: Thu, 12 Dec 2024 16:25:54 GMT
    x-envoy-upstream-service-time: 2
    server: envoy
    
    HTTP/2 200 
    x-powered-by: tinyhttp
    access-control-allow-origin: *
    access-control-allow-methods: GET, HEAD, PUT, PATCH, POST, DELETE
    access-control-allow-headers: content-type
    content-type: text/html; charset=utf-8
    etag: W/"627-v25siNUZqtFMwVFrEcJ5PHKH9xk"
    date: Thu, 12 Dec 2024 16:25:54 GMT
    x-envoy-upstream-service-time: 1
    server: envoy
    
    HTTP/2 200 
    x-powered-by: tinyhttp
    access-control-allow-origin: *
    access-control-allow-methods: GET, HEAD, PUT, PATCH, POST, DELETE
    access-control-allow-headers: content-type
    content-type: text/html; charset=utf-8
    etag: W/"627-v25siNUZqtFMwVFrEcJ5PHKH9xk"
    date: Thu, 12 Dec 2024 16:25:54 GMT
    x-envoy-upstream-service-time: 1
    server: envoy
    
    HTTP/2 200 
    x-powered-by: tinyhttp
    access-control-allow-origin: *
    access-control-allow-methods: GET, HEAD, PUT, PATCH, POST, DELETE
    access-control-allow-headers: content-type
    content-type: text/html; charset=utf-8
    etag: W/"627-v25siNUZqtFMwVFrEcJ5PHKH9xk"
    date: Thu, 12 Dec 2024 16:25:54 GMT
    x-envoy-upstream-service-time: 2
    server: envoy
    
    HTTP/2 429 
    x-envoy-ratelimited: true
    date: Thu, 12 Dec 2024 16:25:54 GMT
    server: envoy
      

Step 2: Allow overwriting default rate limits via the frontend app

You might want to customize the rate limiting settings for a particular team or app and not use the default rate limiting settings that you applied earlier. With Gloo Portal, you can use the dynamicMetadata feature in a RateLimitConfig to overwrite any default rate limits with the limits that were configured via the Portal frontend app for a particular API subscription. If no custom rate limit exists for an API subscription, the default rate limits are still enforced.

  1. Update the RateLimitConfig that you created earlier to add the dynamicMetadata feature. In this example, you instruct Gloo Portal to overwrite the default rate limit settings with the settings for a particular API subscription. For Gloo Portal to identify an API subscription, you must add a key that maps to the name of the portalAuth spec in the AuthConfig that you used when you set up credential management for the API. This way, Portal automatically handles all the dynamic metadata that is required to enforce rate limiting for a particular API subscription.

      kubectl apply -f- <<EOF   
    apiVersion: ratelimit.solo.io/v1alpha1
    kind: RateLimitConfig
    metadata:
      name: tracks-rl
      namespace: gloo-system
    spec:
      raw:
        setDescriptors:
          - simpleDescriptors:
              - key: generic_key
                value: counter
            rateLimit:
              requestsPerUnit: 5
              unit: MINUTE
        rateLimits:
          - setActions:
              - genericKey:
                  descriptorValue: counter
            limit:
              dynamicMetadata:
                metadataKey:
                  key: "envoy.filters.http.ext_authz"
                  path:
                    - key: "tracksAuth"
                    - key: "rateLimit"
    EOF
      
  2. Log in to the portal frontend app by using an admin user.

  3. In the frontend app, go to Subscriptions and find the subscription for which you want to rate limit requests.

  4. Click Edit Rate Limit.

  5. Select the number of requests that you want to allow in the Requests Per Unit field and the Unit. For example, you might want to allow a maximum of 5 requests per minute.

  6. Click Save to save your settings.

  7. Verify that the rate limit is applied. For example, Portal users can follow the steps in Test API access to send multiple requests to the tracks API via the frontend app. If you have a valid API key or ID token, you can also use the following curl requests. Verify that you are rate limited after 2 successful requests and that a 429 HTTP response code is returned.

    • API key:
      for i in {1..3}; do curl -I https://tracks.example.com/tracks -H "api-key: <apikey>"; done
      
    • ID token:
      for i in {1..3}; do curl -vik https://tracks.example.com/tracks -H "Authorization: Bearer <id_token>"; done
      

    Example output:

      HTTP/2 200 
    x-powered-by: tinyhttp
    access-control-allow-origin: *
    access-control-allow-methods: GET, HEAD, PUT, PATCH, POST, DELETE
    access-control-allow-headers: content-type
    content-type: text/html; charset=utf-8
    etag: W/"627-v25siNUZqtFMwVFrEcJ5PHKH9xk"
    date: Thu, 12 Dec 2024 16:30:39 GMT
    x-envoy-upstream-service-time: 3
    server: envoy
    
    HTTP/2 200 
    x-powered-by: tinyhttp
    access-control-allow-origin: *
    access-control-allow-methods: GET, HEAD, PUT, PATCH, POST, DELETE
    access-control-allow-headers: content-type
    content-type: text/html; charset=utf-8
    etag: W/"627-v25siNUZqtFMwVFrEcJ5PHKH9xk"
    date: Thu, 12 Dec 2024 16:30:40 GMT
    x-envoy-upstream-service-time: 2
    server: envoy
    
    HTTP/2 429 
    x-envoy-ratelimited: true
    date: Thu, 12 Dec 2024 16:30:39 GMT
    server: envoy