OIDC-розширення для Kong API Gateway
🌐 Цей документ доступний українською та англійською мовами. Використовуйте перемикач у правому верхньому куті, щоб змінити версію. |
1. Загальний опис компонента
kong-oidc це розширення для Kong API Gateway, що імплементує функціональність Довірчої Сторони (Relying Party) протоколу OpenID Connect
Дане розширення використовується як зворотний проксі-сервер, завершуючий OAuth/OpenID Connect перед цільовим сервісом, щоб цільовий сервіс можна було захистити відповідними стандартами, не імплементуючи їх на самому сервісі.
2. Функції компоненту
Розширення автентифікує користувачів через OpenID Connect Provider (KeyCloak IAM) використовуючи OpenID Connect Discovery і базовий профіль клієнта (Authorization Code flow).
Також воно підтримує сеанси для автентифікованих користувачів використовуючи бібліотеку lua-resty-openidc. Таким чином пропонуючи настроюваний вибір між збереженням стану сеансу на стороні клієнта в cookie браузера та використанням
одного з доступних механізмів збереження на стороні сервера: shared-memory|memcache|redis
.
Функція перевірки JWT токену доступу додає можливість для вже автентифікованих користувачів та/або програм, які вже мають токен доступу для проходу через kong. Фактична перевірка токена в такому випадку виконується Сервером Ресурсів (Resource Server).
3. Принципи реалізації компоненту
Даний компонент є розширенням nokia/kong-oidc плагіна який в свою чергу базується на бібліотеці lua-resty-openidc.
Діаграма нижче ілюструє обмін повідомленнями між залученими сторонами в процесі автентифікації.
![kong_oidc_flow](../../../../../_images/architecture/registry/operational/ext-api-management/kong_oidc_flow.drawio.png)
Після автентифікації та перед тим як направити запит до цільового сервісу kong-oidc плагін додає до запиту наступні заголовки:
-
X-Access-Token
- містить токен доступу -
X-Id-Token
- містить OIDC токен -
X-Userinfo
- містить тіло відповіді з /userinfo ендпоінта.
X-Userinfo: {"preferred_username":"alice","id":"60f65308-3510-40ca-83f0-e9c0151cc680","sub":"60f65308-3510-40ca-83f0-e9c0151cc680"}
Плагін також встановлює змінну ngx.ctx.authenticated_consumer
яка може бути використана в інших Kong плагінах:
ngx.ctx.authenticated_consumer = {
id = "60f65308-3510-40ca-83f0-e9c0151cc680", -- sub field from Userinfo
username = "alice" -- preferred_username from Userinfo
}
5. Використання
Плагін підтримує наступні налаштування:
Параметр |
Значення за замовчуванням |
Обов’язковий |
Опис |
|
так |
ім’я плагіну, повинно бути |
|
|
так |
OIDC Client ID |
|
|
ні |
Ім’я змінної оточення в якій міститься OIDC Client secret. |
|
|
ні |
OIDC Client secret. Може також встановлюватися через змінну оточення. В такому випадку має бути встановлено config.client_secret_var_name |
|
|
ні |
OIDC Discovery Endpoint ( |
|
|
openid |
ні |
OAuth2 Token scope. Для того щоб використовувати OIDC, має містити |
|
false |
ні |
Вмикає перевірку SSL до OIDC провайдера |
|
ні |
Token introspection endpoint |
|
|
false |
ні |
Дозволяє доступ з Bearer токеном. Якщо дозволений, introspection_endpoint має бути встановлений. |
|
ні |
таймаут виклику OIDC endpoint |
|
|
client_secret_basic |
ні |
метод автентифікації для Token introspection. resty-openidc підтримує |
|
no |
ні |
Лише перевірка токена без переадресації. |
|
kong |
ні |
Рілм що використовується в |
|
/logout |
ні |
абсолютний шлях для виходу (logout) з OIDC RP |
|
deny |
так |
Поведінка якщо користувач неавтентифікований:nil - переадресація на сторінку автентифікації, pass - не переадресовувати, deny - не переадресовувати але повернути помилку натомість. |
|
X-Access-Token |
так |
Ім’я для заголовку з токеном доступу. |
|
"no" |
так |
Використовувати bearer токен доступу. |
|
X-ID-Token |
так |
Ім’я для заголовку з ID токеном. |
|
X-Userinfo |
так |
Ім’я для заголовку з інформацією про користувача. |
|
ні |
JSON стрічка з конфігурацією для сесії користувача. Управління сесією побудовано на базі [lua-resty-session](https://github.com/bungle/lua-resty-session). Детальний опис конфігураційних параметрів для управління сесіями вказано в документації до бібліотеки. |
|
|
true |
ні |
Дозволити авторизацію базуючись на таких атрибутах JWT токену доступу як issuer, scope та roles. |
|
ні |
Перелік дозволених видавців токена доступу (iss claim). Приклад: issuers_allowed:\["https://domain/issuer1", "https://domain/issuer2"] |
|
|
nil |
ні |
Меже (scopes) що мають бути присутні в токені доступу для успішної авторизації. |
|
nil |
ні |
Ролі (roles_claim claim) що мають бути присутні (принаймні одна) в токені доступу для успішної авторизації. |
|
nil |
ні |
Ролі рілма (realm_access.roles claim) що мають бути присутні (принаймні одна) в токені доступу для успішної авторизації. |
|
nil |
ні |
Клієнтські ролі (resource_access claim) що мають бути присутні (принаймні одна) в токені доступу для успішної авторизації. |
|
ні |
Назва атрибуту (token claim) токена доступа чиє значення буде додане в заголовок запиту "token-claim". Значення цього заголовку в подальшому може використовуватися іншими плагінами, наприклад, для обчислення лімітів запитів для автентифікованого користувача чи групи таких користувачів. |
При використанні змінних оточення для встановлення конфігураційних параметрів які дозволяють такий механізм, необхідно додатково встановлювати ще одну змінну оточення KONG_NGINX_MAIN_ENV в значеннях якої необхідно перелічити інші змінні оточення читання яких ми хочемо дозволити OIDC плагіну. KONG_NGINX_MAIN_ENV використовує NGINX Injected Directives для того щоб оголосити в nginx.conf змінні оточення що містять секрети через команду env і таким чином дозволити OIDC плагіну прочитати їхні значення.
|
5.1. Запит до цільового сервісу
Плагін за замовчуванням додає 3 додаткові заголовки до оригінального запиту: X-Userinfo
, X-Access-Token
та X-Id-Token
які можуть використовуватися сервісами. Всі вони закодовані в base64.
GET / HTTP/1.1
Host: netcat:9000
Connection: keep-alive
X-Forwarded-For: 172.19.0.1
X-Forwarded-Proto: http
X-Forwarded-Host: localhost
X-Forwarded-Port: 8000
X-Real-IP: 172.19.0.1
Cache-Control: max-age=0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36
Upgrade-Insecure-Requests: 1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: pl-PL,pl;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: session=KOn1am4mhQLKazlCA.....
X-Userinfo: eyJnaXZlbl9uYW1lIjoixITEmMWaw5PFgcW7xbnEhiIsInN1YiI6ImM4NThiYzAxLTBiM2ItNDQzNy1hMGVlLWE1ZTY0ODkwMDE5ZCIsInByZWZlcnJlZF91c2VybmFtZSI6ImFkbWluIiwibmFtZSI6IsSExJjFmsOTxYHFu8W5xIYiLCJ1c2VybmFtZSI6ImFkbWluIiwiaWQiOiJjODU4YmMwMS0wYjNiLTQ0MzctYTBlZS1hNWU2NDg5MDAxOWQifQ==
X-Access-Token: eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJGenFSY0N1Ry13dzlrQUJBVng1ZG9sT2ZwTFhBNWZiRGFlVDRiemtnSzZRIn0.eyJqdGkiOiIxYjhmYzlkMC1jMjlmLTQwY2ItYWM4OC1kNzMyY2FkODcxY2IiLCJleHAiOjE1NDg1MTA4MjksIm5iZiI6MCwiaWF0IjoxNTQ4NTEwNzY5LCJpc3MiOiJodHRwOi8vMTkyLjE2OC4wLjk6ODA4MC9hdXRoL3JlYWxtcy9tYXN0ZXIiLCJhdWQiOlsibWFzdGVyLXJlYWxtIiwiYWNjb3VudCJdLCJzdWIiOiJhNmE3OGQ5MS01NDk0LTRjZTMtOTU1NS04NzhhMTg1Y2E0YjkiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJrb25nIiwibm9uY2UiOiJmNGRkNDU2YzBjZTY4ZmFmYWJmNGY4ZDA3YjQ0YWE4NiIsImF1dGhfdGltZSI6…IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIGVtYWlsIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhZG1pbiJ9.GWuguFjSEDGxw_vbD04UMKxtai15BE2lwBO0YkSzp-NKZ2SxAzl0nyhZxpP0VTzk712nQ8f_If5-mQBf_rqEVnOraDmX5NOXP0B8AoaS1jsdq4EomrhZGqlWmuaV71Cnqrw66iaouBR_6Q0s8bgc1FpCPyACM4VWs57CBdTrAZ2iv8dau5ODkbEvSgIgoLgBbUvjRKz1H0KyeBcXlVSgHJ_2zB9q2HvidBsQEIwTP8sWc6er-5AltLbV8ceBg5OaZ4xHoramMoz2xW-ttjIujS382QQn3iekNByb62O2cssTP3UYC747ehXReCrNZmDA6ecdnv8vOfIem3xNEnEmQw
X-Id-Token: eyJuYmYiOjAsImF6cCI6ImtvbmciLCJpYXQiOjE1NDg1MTA3NjksImlzcyI6Imh0dHA6XC9cLzE5Mi4xNjguMC45OjgwODBcL2F1dGhcL3JlYWxtc1wvbWFzdGVyIiwiYXVkIjoia29uZyIsIm5vbmNlIjoiZjRkZDQ1NmMwY2U2OGZhZmFiZjRmOGQwN2I0NGFhODYiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhZG1pbiIsImF1dGhfdGltZSI6MTU0ODUxMDY5NywiYWNyIjoiMSIsInNlc3Npb25fc3RhdGUiOiJiNDZmODU2Ny0zODA3LTQ0YmMtYmU1Mi1iMTNiNWQzODI5MTQiLCJleHAiOjE1NDg1MTA4MjksImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwianRpIjoiMjI1ZDRhNDItM2Y3ZC00Y2I2LTkxMmMtOGNkYzM0Y2JiNTk2Iiwic3ViIjoiYTZhNzhkOTEtNTQ5NC00Y2UzLTk1NTUtODc4YTE4NWNhNGI5IiwidHlwIjoiSUQifQ==
Імена цих заголовків можуть бути змінені в налаштуваннях плагіна за допомогою відповідних параметрів: config.access_token_header_name
, config.id_token_header_name
та config.user_header_name
. Додатково, токен доступу можна зробити bearer
токеном встановивши значення параметра config.bearer_access_token
рівним yes
.
Приклад:
config:
...
access_token_header_name: Authorization
bearer_access_token: 'yes'
kind: KongPlugin
Результатом такого налаштування буде додавання до оригінального запиту заголовку Authorization
що міститиме beaer
токен доступу:
Authorization: bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJGenFSY0N1Ry13dzlrQUJBVng1ZG9sT2ZwTFhBNWZiRGFlVDRiemtnSzZRIn0.eyJqdGkiOiIxYjhmYzlkMC1jMjlmLTQwY2ItYWM4OC1kNzMyY2FkODcxY2IiLCJleHAiOjE1NDg1MTA4MjksIm5iZiI6MCwiaWF0IjoxNTQ4NTEwNzY5LCJpc3MiOiJodHRwOi8vMTkyLjE2OC4wLjk6ODA4MC9hdXRoL3JlYWxtcy9tYXN0ZXIiLCJhdWQiOlsibWFzdGVyLXJlYWxtIiwiYWNjb3VudCJdLCJzdWIiOiJhNmE3OGQ5MS01NDk0LTRjZTMtOTU1NS04NzhhMTg1Y2E0YjkiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJrb25nIiwibm9uY2UiOiJmNGRkNDU2YzBjZTY4ZmFmYWJmNGY4ZDA3YjQ0YWE4NiIsImF1dGhfdGltZSI6…IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIGVtYWlsIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhZG1pbiJ9.GWuguFjSEDGxw_vbD04UMKxtai15BE2lwBO0YkSzp-NKZ2SxAzl0nyhZxpP0VTzk712nQ8f_If5-mQBf_rqEVnOraDmX5NOXP0B8AoaS1jsdq4EomrhZGqlWmuaV71Cnqrw66iaouBR_6Q0s8bgc1FpCPyACM4VWs57CBdTrAZ2iv8dau5ODkbEvSgIgoLgBbUvjRKz1H0KyeBcXlVSgHJ_2zB9q2HvidBsQEIwTP8sWc6er-5AltLbV8ceBg5OaZ4xHoramMoz2xW-ttjIujS382QQn3iekNByb62O2cssTP3UYC747ehXReCrNZmDA6ecdnv8vOfIem3xNEnEmQw
6. Управління сесіями користувачів
Для управління сесіями користувачів плагін використовує бібліотеку lua-resty-session яка дозволяє зберігати JWT токени користувача як на стороні клієнта в куці так і на стороні сервера в одному з підтримуваних сховищ: shared-memory|memcache|redis(single or cluster)
. Інструкція по налаштуванню роботи з наведеними сховищами є в репозиторії бібліотеки за посиланням вище.
6.1. Збереження сесій в Redis Sentinel
Додатково функціонал бібліотеки був розширений можливістю зберігати сесію в Redis Sentinel.
Приклад налаштування OIDC плагіна для збереження сесій в Redis Sentinel:
config:
session_opts:
{"storage":"sentinel",
"sentinel":{"sentinel_master_name":"mymaster",
"sentinel_db":"sessions",
"sentinel_host":"my-sentinel-host.env-dev.svc",
"sentinel_port":"26379",
"uselocking":false}}
Секрет доступу до Redis задається через змінну оточення REDIS_AUTH_SECRET
REDIS_AUTH_SECRET = some_secret_value
KONG_NGINX_MAIN_ENV = REDIS_AUTH_SECRET
6.2. Встановлення секрету сесії
Бібліотека lua-resty-session для управління сесіями та обрахунку HMAC дайджесту за замовчуванням використовує автозгенерований секрет довжиною 32 байти. Проте якщо інсталяція Kong передбачає декілька екземплярів то кожен з них згенерую власний секрет. Це призведе до того, що сесія створена одним екземпляром Kong не зможе бути прочитана іншими екземплярами. Для вирішення цієї проблеми можна або використовувати концепцію sticky session (запити користувача завжди потрапляють на один екземпляр Kong) або явно встановити однаковий секрет на всіх екземплярах Kong. Секрет можна встановити або передавши його в конфігурації OIDC плагіна як додатковий параметр для session_opts:
config:
session_opts:
{"secret":"c29tZV9zZWNyZXRfdmFsdWU="}
або через змінну оточення OIDC_SESSION_SECRET
:
OIDC_SESSION_SECRET = some_secret_value
KONG_NGINX_MAIN_ENV = OIDC_SESSION_SECRET
В разі використання конфігурації OIDC, значення параметру session_opts.secret має бути закодовано в Base64. При використанні змінної оточення кодувати секрет в Base64 не потрібно.