Russian version (русскоязычная версия)
This plugin is a fork of kong-upstream-jwt and extends its features.
This plugin will add a signed JSON Web Token (JWT)
into the HTTP Header Authorization
of proxied requests through the Kong Gateway.
The purpose of this, is to provide means of Authentication, Authorization and Non-Repudiation to API providers
(APIs for which Kong is a gateway).
In short, API Providers require a means of cryptographically validating that requests they receive were: A. proxied by Kong, and B. not tampered with during transmission from Kong to API Provider. This token accomplishes both as follows:
-
Authentication & Authorization - Provided by means of JWT signature validation using RS256 algorithm. The API Provider will validate the signature on the JWT token (which is generated using Kong's RSA private key), using Kong's X.509 public key certificate. This X.509 public key certificate can be maintained in a keystore, or sent with the token in the field
x5c
provided API providers validate the signature chain against their truststore. -
Non-Repudiation - SHA256 is used to hash the body of the HTTP request and query string of the НТТР request URL. The resulting digests are included in the
bodyhash
andqueryhash
elements of the fieldkong
of JWT payload. API Providers will take the SHA256 hashes of the HTTP request body and HTTP request URL query string to compare the digests to that found in the JWT payload. If they are identical, the request remaines intact during transmission. Also, information about consumer, credentials, route and service can be added to fieldkong
of JWT payload.
- Kong >= 1.0.x
This plugin is available on LuaRocks.
Recommended:
$ luarocks install kong-upstream-jwt-extended
Other:
$ git clone https://github.com/andrey-tech/kong-upstream-jwt-extended.git /path/to/kong/plugins/kong-upstream-jwt-extended
$ cd /path/to/kong/plugins/kong-upstream-jwt-extended
$ luarocks make *.rockspec
Field | Configuration | Description |
---|---|---|
typ |
Token type (JWT) | |
alg |
Message authentication code algorithm (RS256) | |
x5c |
x5c | A X.509 certificate chain in RFC4945 format corresponding to the private key used to generate the token signature for use by API providers to validate the JWT |
kid |
key id | A hint indicating which key the client used to generate the token signature |
The following is an example of the contents of the decoded JWT header:
{
"typ": "JWT",
"alg": "RS256",
"kid": "key-id-001",
"x5c": ["...X.509 public key certificate data..."]
}
Field | Configuration | Description |
---|---|---|
aud |
aud | Identifies the recipients that the JWT is intended for (Kong service name) |
iss |
issuer | Identifies principal that issued the JWT |
iat |
iat | Identifies the time at which the JWT was issued |
jti |
jwt | Case sensitive unique identifier of the token even among different issuers (unique to every request - UUID) |
exp |
exp | Identifies the expiration time on and after which the JWT must not be accepted for processing |
kong |
consumer, credentials, route, service, body hash, query hash |
Non RFC 7519 field with information about consumer, credentials, route, service and request from Kong (object). |
The following is an example of the contents of the decoded JWT payload:
{
"aud": "Service-1",
"iss": "issuer",
"iat": 1550258274,
"exp": 1550258334,
"jti": "d4f10edb-c4f0-47d3-b7e0-90a30a885a0b",
"kong": {
"request": {
"bodyhash": "4d2c0c087cdb197604b99938e6b8fcc4226c3a75b6206954d13c843c9524f863",
"queryhash": "1a5ab7324675b344a37e70445b587cee340a490d14e9a20ea68cd6b34009bd40"
},
"consumer": {
"username": "Company A",
"id": "e96dcb71-4322-490d-b6c6-b9ba1a24b6e3"
},
"credentials": {
"key": "q2QiVe24S6ABaO2L9dEA9y1epX25B9gr"
},
"route": {
"name": "Route-1",
"id": "cc04e82e-8b20-40f0-9081-830caa4cf13e"
},
"service": {
"name": "Service-1",
"id": "d0395ad5-9e53-47c4-a5f2-a4c3c5250c8a"
}
}
}
If body of the HTTP request is empty, then bodyhash
is empty string.
If query string of the HTTP request URL is empty, then queryhash
is empty string.
Parameter | Type | Description |
---|---|---|
issuer | string | Identifies principal that issued the JWT. Present in JWT payload if not blank |
private key location | string | The path to your Kong's private key file (.key) to sign the JWT |
public key location | string | The path to your Kong's X.509 public key certificate file (.crt) |
key id | string | A hint indicating which key the client used to generate the token signature. Present in JWT header if not blank |
header | string | Key of НТТР header (Authorization) |
include bearer | boolean | Controls "Bearer " + JWT or just JWT in header |
exp | integer | Controls expiration time of token (between 0 and 86400). If 0, then exp field is not present in JWT payload |
consumer | array | List of keys of currently authenticated consumer entity to show in kong.consumer object of JWT payload * |
credentials | array | List of keys of credentials of the currently authenticated consumer entity to show in kong.credentials object of JWT payload * |
route | array | List of keys of current route entity to show in kong.route object of JWT payload * |
service | array | List of keys of current service entity to show in kong.service object of JWT payload * |
x5c | boolean | Controls x5c field in JWT header |
aud | boolean | Controls aud field in JWT payload |
iat | boolean | Controls iat field in JWT payload |
jti | boolean | Controls jti field in JWT payload |
body hash | boolean | Controls bodyhash field in kong.request object of JWT payload |
query hash | boolean | Controls queryhash field in kong.request object of JWT payload |
Notes:
* Use *
to include all available keys.
The plugin requires that Kong's private key be accessible in order to sign the JWT (configuration parameter "private key location"). X.509 public key certificate can be included in the x5c JWT header for use by API providers to validate the JWT (configuration parameter "public key location").
To maintain backwards compatibility, support for passing the key locations through environment variables is also available.
We access these via Kong's overriding environment variables KONG_SSL_CERT_KEY
for the private key as well as KONG_SSL_CERT_DER
for the X.509 public key certificate.
If not already set, these can be done so as follows:
$ export KONG_SSL_CERT_KEY="/path/to/kong/ssl/private.key"
$ export KONG_SSL_CERT_DER="/path/to/kong/ssl/public.crt"
One last step is to make the environment variables accessible by an nginx worker. To do this, simply add these line to your nginx.conf.
env KONG_SSL_CERT_KEY;
env KONG_SSL_CERT_DER;
The basics command line to generate a private key and X.509 public key certificate using OpenSSL in one command:
openssl req -x509 -newkey rsa:2048 -keyout private.key -out public.crt -days 365 -nodes
It generates:
- 2048 bits unprotected by passphrase private key in file private.key in PEM format.
- Self-signed X.509 public key certificate with an expiration of 365 days in file public.crt in PEM format.
⚠ Self-signed certificates are not validated with any third party. If you need more security, you should use a certificate signed by a certificate authority (CA).
issuer = "Issuer"
private_key_location = "/home/kong/ssl/private.key"
public_key_location = "/home/kong/ssl/public.crt"
key_id = "keyId"
header = "Authorization"
include_bearer = true
exp = 60
consumer = { "id", "name" }
credentials = { "key" }
route = { "id", "name" }
service = { "id", "name" }
x5c = false
aud = false
iat = false
jti = false
body_hash = false
query_hash = false
The original authors and maintainers of kong-upstream-jwt plugin:
The author and maintainer of kong-upstream-jwt-extended plugin:
This plugin is licensed under the Apache License Version 2.0.
Данный плагин является форком плагина kong-upstream-jwt и расширяет его возможности.
Плагин добавляет подписанный токен типа JSON Web Token (JWT)
(RFC 7519) в заголовок Authorization
НТТР-запросов, прошедших через шлюз Kong Gateway,
в целях обеспечения аутентификации, авторизации и удостоверения подлинности и неоспоримости данных,
передаваемых в HTTP-запросе от шлюза Kong к API.
Зачастую API требуют средства криптографической проверки того, что полученные ими запросы, во-первых, действительно прошли через шлюз Kong и, во-вторых, не подделаны при передаче от шлюза Kong к API.
Формируемый токен JWT позволяет выполнить обе эти проверки:
-
Аутентификация и авторизация. Обеспечивается посредством проверки подписи токена с помощью алгоритма RS256. API может проверить подпись токена, которая была создана с использованием закрытого RSA-ключа шлюза Kong, при помощи сертификата открытого ключа X.509. Сертификат открытого ключа X.509 шлюза Kong может храниться в хранилище ключей, доступном API, или передаваться вместе с токеном в поле заголовка
x5c
, при обязательном условии, что API проверяет цепочку подписей по своему хранилищу доверенных сертификатов. -
Подлинность и неоспоримость данных. Обеспечивается посредством хеширования тела НТТР-запроса и строки параметров запроса с использованием алгоритма SHA-256. Полученные дайджесты включаются в элементы
bodyhash
andqueryhash
поляkong
полезной нагрузки (payload) токена. API может вычислить хеши тела НТТР-запроса и строки параметров запроса и сравнить их с дайджестами, полученными с полезной нагрузкой токена. Если они идентичны, то тело и строка параметров запроса не были изменены при передаче от шлюза Kong к API.Кроме того информация о следующих объектах (сущностях) шлюза Kong может быть включена в поле
kong
полезной нагрузки токена: consumer, credentials, route и service.
- Kong >= 1.0.x
Установка из репозитория LuaRocks (рекомендуемый вариант):
$ luarocks install kong-upstream-jwt-extended
Установка из репозитория GitHub:
$ git clone https://github.com/andrey-tech/kong-upstream-jwt-extended.git /path/to/kong/plugins/kong-upstream-jwt-extended
$ cd /path/to/kong/plugins/kong-upstream-jwt-extended
$ luarocks make *.rockspec
Поле | Параметр конфигурации | Описание |
---|---|---|
typ |
Тип токена (JWT) | |
alg |
Алгоритм, используемый при подписании токена (RS256) | |
x5c |
x5c | Сертификат открытого ключа X.509, представленный в виде массива из одной строки, закодированной по стандарту Base64 |
kid |
key id | Указывает какой именно ключ был использован для защиты токена и позволяет уведомлять об изменении ключа |
Пример декодированного заголовка токена:
{
"typ": "JWT",
"alg": "RS256",
"kid": "key-id-001",
"x5c": ["...X.509 public key certificate data..."]
}
Поле | Параметр конфигурации | Описание |
---|---|---|
aud |
aud | Идентификатор получателя токена (имя сервиса Kong) |
iss |
issuer | Идентификатор стороны, генерирующей токен |
iat |
iat | Время создания токена в формате Unix time |
jti |
jwt | Уникальный идентификатор токена (UUID) |
exp |
exp | Время когда токен станет недействительным в формате Unix time |
kong |
consumer, credentials, route, service, body hash, query hash |
Поле с информацией об объектах Kong и запросе (объект) |
Пример декодированной полезной нагрузки токена:
{
"aud": "Service-1",
"iss": "issuer",
"iat": 1550258274,
"exp": 1550258334,
"jti": "d4f10edb-c4f0-47d3-b7e0-90a30a885a0b",
"kong": {
"request": {
"bodyhash": "4d2c0c087cdb197604b99938e6b8fcc4226c3a75b6206954d13c843c9524f863",
"queryhash": "1a5ab7324675b344a37e70445b587cee340a490d14e9a20ea68cd6b34009bd40"
},
"consumer": {
"username": "Company A",
"id": "e96dcb71-4322-490d-b6c6-b9ba1a24b6e3"
},
"credentials": {
"key": "q2QiVe24S6ABaO2L9dEA9y1epX25B9gr"
},
"route": {
"name": "Route-1",
"id": "cc04e82e-8b20-40f0-9081-830caa4cf13e"
},
"service": {
"name": "Service-1",
"id": "d0395ad5-9e53-47c4-a5f2-a4c3c5250c8a"
}
}
}
Если тело HTTP-запроса пусто, то дайджест тела запроса bodyhash
- это путая строка.
Если строка параметров НТТР-запроса отсутствует, то дайджест строки параметров запроса queryhash
- это путая строка.
Параметр | Тип | Описание |
---|---|---|
issuer | string | Идентификатор стороны, генерирующей токен (присутствует в полезной нагрузке токена, если не пустая строка) |
private key location | string | Абсолютный путь к файлу (.key) на сервере Kong, содержащему закрытый ключ для подписания токена |
public key location | string | Абсолютный путь к файлу (.crt) на сервере Kong, содержащему сертификат публичного ключа X.509 |
key id | string | Указывает какой именно ключ был использован для защиты токена и позволяет уведомлять об изменении ключа (присутствует в заголовке токена, если не пустая строка) |
header | string | Имя НТТР-заголовка (Authorization ) токена |
include bearer | boolean | Управляет добавлением строки Bearer к токену в HTTP-заголовке Authorization |
exp | integer | Время истечения токена в интервале между 0 и 86400 (присутствует в полезной нагрузке токена, если не 0) |
consumer | array | Список ключей аутентифицированного потребителя (consumer), включаемых в объект kong.consumer в полезной нагрузке токена * |
credentials | array | Список ключей полномочий (credentials) аутентифицированного потребителя (consumer), включаемых в объект kong.credentials в полезной нагрузке токена * |
route | array | Список ключей текущего маршрута (route), включаемых в объект kong.route в полезной нагрузке токена * |
service | array | Список ключей текущего сервиса (service), включаемых в объект kong.service в полезной нагрузке токена * |
x5c | boolean | Управляет включением поля x5c в заголовок токена |
aud | boolean | Управляет включением поля aud в полезную нагрузку токена |
iat | boolean | Управляет включением поля iat в полезную нагрузку токена |
jti | boolean | Управляет включением поля jti в полезную нагрузку токена |
body hash | boolean | Управляет включением поля bodyhash в объект kong.request в полезной нагрузке токена |
query hash | boolean | Управляет включением поля queryhash в объект kong.request в полезной нагрузке токена |
Примечания:
* Если список содержит *
, то включаются все доступные ключи. Если список пуст,
то параметр не включается в полезную нагрузку токена.
Плагин требует, чтобы закрытый ключ был доступен для подписания токена (см. параметр конфигурации "private key location").
Сертификат публичного ключа X.509 может быть включен в поле заголовка x5c токена для проверки его подписи, но при обязательном условии, что API проверяет цепочку подписей по своему хранилищу доверенных сертификатов (см. параметр конфигурации "public key location").
Для обеспечения обратной совместимости, поддерживается передача абсолютных путей к файлам закрытого и открытого ключей через переменные окружения, которые переопределяют значения, установленные в параметрах конфигурации плагина:
KONG_SSL_CERT_KEY
- закрытый ключ,KONG_SSL_CERT_DER
- сертификат публичного ключа X.509.
Пример установки переменных окружения:
$ export KONG_SSL_CERT_KEY="/path/to/kong/ssl/private.key"
$ export KONG_SSL_CERT_DER="/path/to/kong/ssl/public.crt"
Для того, чтобы переменные окружения были доступны в nginx, необходимо добавить в его файл конфигурации nginx.conf:
env KONG_SSL_CERT_KEY;
env KONG_SSL_CERT_DER;
Создание закрытого ключа и самоподписанного сертификата открытого ключа X.509 с использованием утилиты OpenSSL может быть выполнено одной командой:
openssl req -x509 -newkey rsa:2048 -keyout private.key -out public.crt -days 365 -nodes
Команда выполняет:
- создание закрытого RSA-ключа длиной 2048 бит в формате PEM не защищенного парольной фразой в файле private.key:
- создание самоподписанного сертификата X.509 в формате PEM со сроком действия 365 дней в файле public.crt.
⚠ Самоподписанный сертификат не проверяется третьими лицами. Если требуется дополнительная безопасность, то необходимо использовать сертификат открытого ключа, подписанный центром сертификации (CA).
issuer = "Issuer"
private_key_location = "/home/kong/ssl/private.key"
public_key_location = "/home/kong/ssl/public.crt"
key_id = "keyId"
header = "Authorization"
include_bearer = true
exp = 60
consumer = { "id", "name" }
credentials = { "key" }
route = { "id", "name" }
service = { "id", "name" }
x5c = false
aud = false
iat = false
jti = false
body_hash = false
query_hash = false
Авторы оригинального плагина kong-upstream-jwt:
Автор плагина kong-upstream-jwt-extended:
Данный плагин распространяется по лицензии Apache License Version 2.0.