Case Study Jobteaser Case Study: Scalable Public APIs with KrakenD

You are viewing a previous version of KrakenD Enterprise Edition (v2.6), go to the latest version

Document updated on Apr 29, 2024

Revoke Server for clusters

The Revoke Server (a.k.a Revoker) is a standalone server that coordinates token revocation in a KrakenD Cluster. When you start the service, it offers a ping endpoint for all KrakenD instances to self-register and pushes token revocation instructions to all nodes in the cluster.

The Revoker passes the instructions to all instances by connecting to their bloom filter RPC port. It offers centralized management despite the size of your cluster. You no longer need to know how many KrakenDs are running using the Revoke Server and interact with them individually.

The interaction with the Revoke Server is through a REST API (described below) that offers several endpoints to administer token expiration from a single place.

Remember that the Revoke Server does not issue tokens. Still, it can communicate to all running gateways, reporting when they need to start rejecting tokens (or types of tokens) that are still valid by looking at their expiration.

The diagram below shows how it works:

Revoke Server

Starting the Revoke Server

To start the Revoke Server you only need to pass the configuration file as described in the sections below. For instance:

Starting the revoke server 

$krakend revoker -c config.json

There are no other additional flags needed, as you can see in the help, as the interaction is through its service:

Starting the revoke server 

$krakend revoker --help
╓▄█                          ▄▄▌                               ╓██████▄µ
▐███  ▄███╨▐███▄██H╗██████▄  ║██▌ ,▄███╨ ▄██████▄  ▓██▌█████▄  ███▀╙╙▀▀███╕
▐███▄███▀  ▐█████▀"╙▀▀"╙▀███ ║███▄███┘  ███▀""▀███ ████▀╙▀███H ███     ╙███
▐██████▌   ▐███⌐  ,▄████████M║██████▄  ║██████████M███▌   ███H ███     ,███
▐███╨▀███µ ▐███   ███▌  ,███M║███╙▀███  ███▄```▄▄` ███▌   ███H ███,,,╓▄███▀
▐███  ╙███▄▐███   ╙█████████M║██▌  ╙███▄`▀███████╨ ███▌   ███H █████████▀
                     ``                     `'`

Version: 2.6

Starts a revocation service.

Usage:
  krakend revoker [flags]

Aliases:
  revoker, revoke

Examples:
krakend revoker -c config.json

Flags:
  -c, --config string   Path to the revoker server configuration file. (default "./revoker.json")
  -h, --help            help for revoker

Revoke Server configuration

The configuration of the Revoke Server can use the same krakend.json file your KrakenD instances use, or you can dedicate a separate file to it (probably a better option). In either case, the configuration file of the Revoker validates against the same KrakenD schema ("$schema": "https://www.krakend.io/schema/v2.6/krakend.json"), and it’s a regular KrakenD configuration file in all aspects.

Whether you recycle your existing gateway configuration for the Revoke Server or not, these are the things you might have in mind:

The Revoke Server needs a listening port as the gateway does. If you intend to run them on a single machine, you must override the port in the file with an environment var KRAKEND_PORT during startup to avoid collisions using the same file.

The Revoke Server uses the auth/revoker section. If you use two configuration files, both must be present and match strictly on both sides. You can also use flexible configuration and the krakend check command for the Revoke Server.

Gateway and revoker configuration must match
Remember that the revoke configuration under auth/revoker for both the gateway and the revoke server must be identical. Otherwise you might have scenarios where you are trying to revoke tokens of unsupported keys, desynchronization, or have communication problems.

Revoke server configuration file

The configuration that the Revoke Server needs, whether it is a krakend.json or dedicated revoke.json file, is:

{
    "version": 3,
    "port": 8081,
    "extra_config": {
        "auth/revoker": {
            "hash_name": "default",
            "N": 10000000,
            "P": 1e-7,
            "port": 1234,
            "token_keys": [
                "jti", "sub"
            ],
            "TTL": 1500,
            "revoke_server_ping_url": "http://localhost:8081/instances",
            "revoke_server_ping_interval": "30s",
            "revoke_server_api_key": "639ee23f-f4c5-40c4-855c-912bf01fae87",
            "revoke_server_max_workers":5
        }
    }
}

In this documentation, we will call:

  • Server: The Revoke server communicates with all the KrakenDs to provide them with instructions.
  • Client(s): The KrakenD gateways reporting to the Revoker.

The configuration is parsed both in the clients and in the server and has the following fields:

port (integer): In the server, the port where the Revoker will expose its API (see endpoints below). In the client, it’s the KrakenD port. Notice there is also a port entry inside the auth/revoker configuration. The latter is for the RPC service to communicate with the bloom filter.

Then, inside the extra_config’s auth/revoker (the Bloom filter configuration):

Fields of Revoke Server
* required fields

N * integer
The maximum Number of elements you want to keep in the bloom filter. Tens of millions work fine on machines with low resources.
Example: 10000000
P * number
The Probability of returning a false positive. E.g.,1e-7 for one false positive every 10 million different tokens. The values N and P determine the size of the resulting bloom filter to fulfill your expectations. E.g: 0.0000001
Examples: 1e-7 , 1e-7
TTL * integer
The lifespan of the JWT you are generating in seconds. The value must match the expiration you are setting in the identity provider when creating the tokens.
hash_name *
Either optimal (recommended) or default. The optimal consumes less CPU but has less entropy when generating the hash, although the loss is negligible.
Possible values are: "optimal" , "default"
port * integer
The port number exposed on each KrakenD instance for the RPC service to interact with the bloomfilter. This port is allocated only to the clients (running KrakenDs).
revoke_server_api_key string
A string used as an exchange API key to secure the communication between the Revoke Server and the KrakenD instances and to consume the REST API of the Revoker Server as well. E.g., a string generated with uuidgen.
Example: "639ee23f-f4c5-40c4-855c-912bf01fae87"
revoke_server_max_retries integer
Maximum number of retries after a connection fails. When the value is less than zero it is changed automatically to zero.
Defaults to 0
revoke_server_max_workers integer
How many workers are used concurrently to execute an action (e.g., push a token) to all registered instances, allowing you to limit the amount of memory consumed by the server. For example, if you have 100 KrakenD servers and need to push 5MB of data each, you need to send 500MB in total. A max_workers=5 will consume a maximum of 5MB x 5 workers = 25MB of memory in a given instant. Defaults to the same number of CPUs available.
Defaults to 5
revoke_server_ping_interval string
Time the server and the client wait to verify they are alive with each other (health check). Defaults to 30s. Do not lower this value a lot; otherwise, you will have a lot of internal traffic.
Specify units using ns (nanoseconds), us or µs (microseconds), ms (milliseconds), s (seconds), m (minutes), or h (hours).
Example: "30s"
revoke_server_ping_url string
The address to the /instances endpoint in the Revoke Server.
Example: "http://revoke-server:8081/instances"
token_keys * array
The list with all the claims in your JWT payload that need watching. These fields establish the criteria to revoke accesses in the future. The Revoker does not use this value, only the clients.
Example: "jti"

Additional configuration

The Revoke Server also accepts settings from:

Revoke Server API Endpoints

The system is eventually consistent, meaning that after a maximum 2 x TTL, the state converges and becomes consistent. Moreover, the operations are idempotent, so it’s safe to resend the same write methods multiple times.

Authentication needed
To access any of the endpoints described below, you need to pass the Authorization: bearer with the same API key you have set in the configuration (except for the /__health/).

POST /tokens/{token_key}/{value}

Adds a new token to revoke in the local bloom filter, and the server will spread it across all registered KrakenD instances.

Parameters:

  • {token_key}: The name of the claim (e.g., jti, sub, aud, etc.)
  • {value}: The claim value you want to revoke

/tokens/{token_key}/{value} 

$curl -iH'Authorization: bearer 639ee23f-f4c5-40c4-855c-912bf01fae87' -XPOST http://localhost:8081/tokens/jti/43b7a832-8337-4b50-a3b3-f221800e42d5
HTTP/1.1 201 Created
Date: Thu, 06 Oct 2022 17:36:10 GMT
Content-Length: 0

The example above invalidates the token with jti=43b7a832-8337-4b50-a3b3-f221800e42d5.

GET /tokens/{token_key}/{value}

The endpoint checks in all registered KrakenD instances the existence of the requested token and returns two keys: the hits or instances recognizing the token as invalid or revoked, and the misses: not present in the revoked set.

Parameters:

  • {token_key}: The name of the claim (e.g., jti, sub, aud, etc.)
  • {value}: The claim value you want to verify

The Revoke Server checks in its bloom filter and every KrakenD’s bloom filter the existence or not of the value. It identifies itself as revoker in the hits or misses list.

/tokens/{token_key}/{value} 

$curl -iH'Authorization: bearer 639ee23f-f4c5-40c4-855c-912bf01fae87' http://localhost:8081/tokens/jti/43b7a832-8337-4b50-a3b3-f221800e42d5
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Thu, 06 Oct 2022 17:15:39 GMT
Content-Length: 49
{"hits":["192.168.23.35:1234","revoker"],"misses":[]}

POST /tokens/{token_key}

Adds a list of tokens to the requested claim. Endpoint used for batch processing.

The body or file you send to the endpoint must contain one value per line.

Term 

$curl -iH'Authorization: bearer 639ee23f-f4c5-40c4-855c-912bf01fae87' -XPOST --data-binary @invalid_tokens.txt http://localhost:8081/tokens/jti
HTTP/1.1 100 Continue
HTTP/1.1 201 Created
Date: Thu, 06 Oct 2022 17:39:07 GMT
Content-Length: 0

GET /instances

Returns the list of all KrakenD instances registered in the Revoke Server.

Term 

$curl -iH'Authorization: bearer 639ee23f-f4c5-40c4-855c-912bf01fae87' http://localhost:8081/instances
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Thu, 06 Oct 2022 17:42:14 GMT
Content-Length: 32
{"instances":["127.0.0.1:1234"]}

POST /instances

Although the system automatically handles instances’ registration, this endpoint allows you to register a new instance manually.

The body of the request must have the following JSON fields:

{
    "instance_id": "string. An UUID for your machine",
    "cluster_id": "string. The MD5 hash or similar of your configuration",
    "cn": "string. Your license CN as shown in 'openssl x509 -in LICENSE -text -noout'",
    "n": "N value as in the configuration",
    "p": "P value as in the configuration",
    "ttl": "integer. TTL value as in the configuration",
    "hash_name": "enum. hash_name value as in the configuration",
    "ip": "string. the IP where to find this new KrakenD",
    "port": "integer. the port where the bloom filter runs",
}

DELETE /instances/{instance}

Use the DELETE method to unregister a KrakenD instance from the Revoke Server. Keep in mind that if you unregister a KrakenD instance using this call, but it keeps running, the instance will rejoin the server on the next health check. The request does not need a body.

Parameters:

  • {instance}: The instance to delete in the format IP:port, e.g., 192.168.1.1:8080.

GET /status

Returns the status of the internal Revoker’s bloom filter and the selected settings.

Term 

$curl -iH'Authorization: bearer 639ee23f-f4c5-40c4-855c-912bf01fae87' http://localhost:8081/status
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Mon, 24 Oct 2022 11:47:46 GMT
Content-Length: 166

{"config":{"Seed":"","N":10000000,"P":1e-7,"HashName":"optimal","TTL":1500,"Workers":5,"PingInterval":30000000000,"CN":"c2d1f2a3-8fc2-4278-b1c1-c002557b6b45","MaxRetries":3},"percentage_consumed":0}

GET /__health

The only endpoint that does not require authentication, returns a 200 status code when the server is running. You can disable this endpoint by setting it in its [router options](/docs/service-settings/router-options/# disable_health).

Docker compose example

The following docker-compose spins up several krakend instances connected to a revoke server:

version: "3"
services:
  revoker:
    image: krakend/krakend-ee:2
    ports:
      - 8081:8081
    volumes:
      - "./:/etc/krakend"
    command: ["revoke", "-c", "revoker.json"]
  krakend:
    image: krakend/krakend-ee:2
    ports:
      - 8080:8080
    volumes:
      - "./:/etc/krakend"
  krakend2:
    image: krakend/krakend-ee:2
    volumes:
      - "./:/etc/krakend"
  krakend3:
    image: krakend/krakend-ee:2
    volumes:
      - "./:/etc/krakend"
  krakend4:
    image: krakend/krakend-ee:2
    volumes:
      - "./:/etc/krakend"

The associated configuration files are left below. Notice they are exact except for the port and the logging prefix:

krakend.json

{
    "$schema": "https://www.krakend.io/schema/v2.6/krakend.json",
    "version": 3,
    "port": 8080,
    "extra_config": {
        "auth/revoker": {
            "hash_name": "default",
            "N": 10000000,
            "P": 1e-7,
            "port": 1234,
            "token_keys": [
                "jti", "sub"
            ],
            "TTL": 1500,
            "revoke_server_ping_url": "http://revoker:8081/instances",
            "revoke_server_ping_interval": "30s",
            "revoke_server_api_key": "639ee23f-f4c5-40c4-855c-912bf01fae87",
            "revoke_server_max_workers":5
        },
        "telemetry/logging": {
            "level": "DEBUG",
            "prefix": "[KRAKEND]",
            "stdout": true
        }
    }
}

revoker.json

{
    "$schema": "https://www.krakend.io/schema/v2.6/krakend.json",
    "version": 3,
    "port": 8081,
    "extra_config": {
        "auth/revoker": {
            "hash_name": "default",
            "N": 10000000,
            "P": 1e-7,
            "port": 1234,
            "token_keys": [
                "jti", "sub"
            ],
            "TTL": 1500,
            "revoke_server_ping_url": "http://revoker:8081/instances",
            "revoke_server_ping_interval": "30s",
            "revoke_server_api_key": "639ee23f-f4c5-40c4-855c-912bf01fae87",
            "revoke_server_max_workers":5
        },
        "telemetry/logging": {
            "level": "DEBUG",
            "prefix": "[REVOKER]",
            "stdout": true
        }
    }
}
Scarf

Unresolved issues?

The documentation is only a piece of the help you can get! Whether you are looking for Open Source or Enterprise support, see more support channels that can help you.

See all support channels