Заставьте grafana использовать JWT-токен в локальном хранилище

У меня есть веб-приложение React + DRF с аутентификацией JWT, в котором я использую djangorestframework-simplejwt.

Я храню токены доступа и обновления в localStorage. Можно ли использовать эти токены для аутентификации в Grafana? Если да, то как я могу это сделать? Когда я перехожу по адресу /grafana (с помощью nginx), я хочу видеть, что мой пользователь в моем приложении вошел в Grafana, при необходимости создав пользователя для Grafana.

Не совсем понятно, что такое "JWT аутентификация" и как был создан JWT. Я предполагаю, что это аутентификация Open ID Connect, и тогда ничто не мешает вам использовать Grafana OIDC auth с тем же OIDC identuty provider, чтобы иметь бесшовный пользовательский опыт единого входа.

Позвольте мне объяснить все детали для тех, кто ищет решение проблемы использования общего JWT для своего приложения и Grafana. Вы можете пропустить начало, если вас интересует только сторона Grafana:

Реактивная сторона:

  • У меня есть Django REST Framework API и React UI. Когда токен возвращается пользователю, React UI сохраняет его в локальном хранилище. Я реализовал обработчик onClick для кнопки перехода к Grafana следующим образом:
// read token value from local storage
const refToken = localStorage.getItem("refresh_token");
window.location.href = `/grafana/login/?mytoken=${refToken}`;

Сторона Django REST Framework (djangorestframework-simplejwt):

  • API может генерировать и проверять токены JWT, используя алгоритм подписи RS256. Поскольку используется RSA, API необходимо сгенерировать 2 ключа, закрытый и открытый. Я сгенерировал их с помощью jwcrypto. Я задал SIGNING_KEY содержимое закрытого ключа .pem и задал VERIFYING_KEY содержимое открытого ключа .pem.
from jwcrypto import jwk
import uuid

keyid = str(uuid.uuid4())
key = jwk.JWK.generate(kty='RSA', alg='RS256', size=2048, kid=keyid, use='sig')

# export to PEM files
priv_pem = key.export_to_pem(private_key=True, password=None)
pub_pem = key.export_to_pem()

with open("rsa_pub.pem", "wb") as f:
    f.write(pub_pem)

with open("rsa.pem", "wb") as f:
    f.write(priv_pem)
SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': timedelta(hours=1),
    'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
    'SIGNING_KEY': open("/path/to/folder/which/has/keys/rsa.pem").read(),
    'VERIFYING_KEY': open("/path/to/folder/which/has/keys/rsa_pub.pem").read(),
    'ALGORITHM': 'RS256',
    'USER_ID_FIELD': 'username',
    'USER_ID_CLAIM': 'username',
    'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
}

Графанская сторона:

  • Чтобы убедиться, что это работает, вам нужно создать пользователей с тем же именем пользователя для Grafana. В противном случае вы получите ответ Invalid JWT. auto_sign_up Настройка еще не работает для аутентификации JWT.

    .
  • Затем я добавил эти конфигурации для контейнера Grafana. header_name может быть любой строкой, но вам нужно использовать ее и на стороне nginx:

version: "3"
services:
  ...
  ...
  grafana:
    image:  grafana/grafana:8.2.2
    volumes:
      - ...
      - "/path/to/folder/which/has/keys:/key_set"
    environment:
      - "GF_SERVER_ROOT_URL=/grafana/"
      - "GF_SERVER_SERVE_FROM_SUB_PATH=true"
      - "GF_AUTH_PROXY_ENABLED=true"
      - "GF_AUTH_PROXY_ENABLE_LOGIN_TOKEN=true"
      - "GF_AUTH_JWT_ENABLED=true"
      - "GF_AUTH_JWT_HEADER_NAME=X-JWT-Assertion"
      - "GF_AUTH_JWT_USERNAME_CLAIM=username"
      - "GF_AUTH_JWT_KEY_FILE=/key_set/rsa_pub.pem"

Сторона Nginx:

location /grafana/ {
    try_files /dev/null @proxy_grafana;
}

location /grafana/login/ {
    try_files /dev/null @proxy_grafana_login;
}

location @proxy_grafana {
    ...
    proxy_pass   http://grafana:3000;
}

location @proxy_grafana_login {
    ...
    proxy_set_header X-JWT-Assertion "${arg_mytoken}";
    proxy_pass   http://grafana:3000;
}
Вернуться на верх