Конфигурация IAM¶
Справочник по настройке iam-service: переменные окружения сервиса с
дефолтами, как они задаются в корневом compose.yml, переменные локального
клиента, bootstrap-токен, ключ подписи, миграции и типичные проблемы
конфигурации. Для администраторов инсталляции.
Переменные сервиса¶
Сервис читает настройки из окружения с префиксом IAM_ (pydantic-settings,
регистр не важен, неизвестные переменные игнорируются).
| Переменная | По умолчанию | Описание |
|---|---|---|
IAM_DATABASE_URL |
postgresql+psycopg://iam:iam@localhost:5435/iam |
Строка подключения SQLAlchemy (async, драйвер psycopg). Используется и сервисом, и Alembic |
IAM_BOOTSTRAP_TOKEN |
"" |
Секрет административного API (заголовок X-IAM-Bootstrap-Token). Пусто — административные эндпоинты закрыты |
IAM_ISSUER |
http://localhost:8010 |
Значение iss в выпускаемых токенах; должно совпадать с настройкой issuer у всех сервисов |
IAM_TOKEN_TTL_SECONDS |
300 |
Срок жизни access token (и expiresIn в ответах обмена) |
IAM_SIGNING_PRIVATE_KEY |
"" |
RSA private key в PEM (без пароля) строкой |
IAM_SIGNING_PRIVATE_KEY_FILE |
"" |
Путь к файлу ключа; используется, если IAM_SIGNING_PRIVATE_KEY пуст |
IAM_SIGNING_KEY_ID |
local-dev |
kid в заголовке токенов и в JWKS |
IAM_CREATE_SCHEMA_ON_STARTUP |
false |
Создавать таблицы при старте (create_all). Только для разработки; в эксплуатации схему меняет только Alembic |
IAM_PAT_DEFAULT_TTL_SECONDS |
2592000 (30 дней) |
Срок PAT, если expiresInSeconds не передан |
IAM_PAT_MAX_TTL_SECONDS |
31536000 (365 дней) |
Максимальный срок PAT |
IAM_PAT_MAX_AUTHENTICATION_AGE_SECONDS |
300 |
Максимальный возраст authentication context человека для выпуска PAT |
IAM_LEGACY_CREDENTIAL_MAX_TTL_SECONDS |
7776000 (90 дней) |
Максимальное окно совместимости импортированного ключа Control Plane |
IAM_SCIM_AUDIENCE |
iam-scim |
Audience токена SCIM-клиента |
IAM_SCIM_SCOPE |
scim:write |
Scope, обязательный для SCIM |
IAM_SCIM_MAX_PAGE_SIZE |
200 |
Максимальный размер страницы выдачи SCIM |
Параметры, которые задаются не переменными
Кэш JWKS внешнего IdP (jwksCacheTtlSeconds, jwksStaleGraceSeconds) и
требования к acr/amr настраиваются на каждом identity provider (см.
Федерация). Реестр audiences и их scopes — данные в базе
(см. Токены).
Как это задано в compose.yml¶
Корневой compose.yml (профиль core) передаёт в контейнер iam-service
только часть переменных; остальные работают с дефолтами:
iam-service:
command: >
sh -c "alembic upgrade head &&
uvicorn iam_service.app:app --host 0.0.0.0 --port 8010"
environment:
IAM_DATABASE_URL: postgresql+psycopg://iam:${IAM_POSTGRES_PASSWORD}@iam-db:5432/iam
IAM_BOOTSTRAP_TOKEN: ${IAM_BOOTSTRAP_TOKEN:?set IAM_BOOTSTRAP_TOKEN}
IAM_ISSUER: ${TAIMEN_PUBLIC_URL:?set TAIMEN_PUBLIC_URL}/iam
IAM_SIGNING_PRIVATE_KEY_FILE: /run/secrets/iam_signing_key
IAM_SIGNING_KEY_ID: ${IAM_SIGNING_KEY_ID:-local-dev}
secrets: [iam_signing_key]
ports: ["127.0.0.1:${IAM_HOST_PORT:-18010}:8010"]
mem_limit: ${IAM_MEM_LIMIT:-256m}
Переменные .env, относящиеся к IAM:
Переменная .env |
По умолчанию | Куда попадает |
|---|---|---|
TAIMEN_PUBLIC_URL |
— (обязательна) | IAM_ISSUER = ${TAIMEN_PUBLIC_URL}/iam; также issuer у всех сервисов (CP_IAM_ISSUER, CB_IAM_ISSUER, …) |
IAM_POSTGRES_PASSWORD |
— (обязательна) | пароль iam-db и IAM_DATABASE_URL |
IAM_BOOTSTRAP_TOKEN |
— (обязательна) | IAM_BOOTSTRAP_TOKEN; также bootstrap-скрипт и чтение журнала IAM policy-service |
IAM_SIGNING_KEY_FILE |
./secrets/iam-signing.pem |
файл docker-секрета iam_signing_key |
IAM_SIGNING_KEY_ID |
local-dev |
IAM_SIGNING_KEY_ID |
IAM_TENANT_ID |
пусто | tenant IAM для шлюза platform-api и runner'ов; заполнить после make bootstrap |
IAM_HOST_PORT |
18010 |
порт IAM на 127.0.0.1 хоста |
IAM_MEM_LIMIT |
256m |
лимит памяти контейнера |
IAM_BUILD_CONTEXT |
./iam-service |
контекст сборки образа |
PG_MEM_LIMIT |
256m |
лимит памяти iam-db (общий для баз) |
VOLUME_IAM_DB |
${COMPOSE_PROJECT_NAME}_iam_db |
имя volume базы |
make secrets создаёт .env из .env.example, заполняет пустые секреты
случайными значениями и генерирует secrets/iam-signing.pem (RSA 3072, 0600).
Изменение параметров, которых нет в compose.yml¶
Чтобы поменять, например, срок access token или PAT, добавьте переменные в
override-файл compose, не правя поставляемый compose.yml:
# compose.override.yml
services:
iam-service:
environment:
IAM_TOKEN_TTL_SECONDS: "600"
IAM_PAT_DEFAULT_TTL_SECONDS: "7776000"
Не увеличивайте TTL access token без нужды
Уже выданный access token IAM не может отозвать: он живёт до exp.
Чем длиннее IAM_TOKEN_TTL_SECONDS, тем шире окно, в течение которого
отключённый пользователь ещё проходит проверку у сервисов без собственной
revocation-проекции. Режим TokenLifetimeWindow в platform-auth-sdk по
умолчанию отклоняет токены, которым осталось жить больше 900 с.
Bootstrap-токен¶
IAM_BOOTSTRAP_TOKEN — единственная граница административного API IAM:
- сравнивается в постоянном времени с заголовком
X-IAM-Bootstrap-Token; - пустое значение переменной закрывает все административные эндпоинты
(
401 unauthorized); - заголовок
Authorization: Bearer …для административных операций не принимается — толькоX-IAM-Bootstrap-Token; - в audit действие записывается от имени
bootstrap.
Рекомендации:
- Генерируйте длинное случайное значение (
make secretsделает это сам) и храните только в.envс правами0600. - Не передавайте его клиентам, агентам и в CI, которым нужны только PAT.
- Ограничьте административные пути IAM на периметре (см. API и Периметр и TLS).
- При подозрении на компрометацию смените значение в
.env, пересоздайтеiam-service(docker compose up -d iam-service) и проверьте журналGET /api/v1/eventsна неожиданныеprincipal.created,platform_access_token.issued,service_account.created.
Токен не для разработки в общих средах
Самостоятельный docker-compose.yml репозитория iam-service по
умолчанию использует dev-bootstrap-token-change-me. Это значение только
для локальной разработки — в любой общей среде его нужно заменить.
Ключ подписи¶
| Требование | Почему |
|---|---|
| RSA, PEM, без пароля | IAM загружает ключ без passphrase и отвергает не-RSA ключи |
Файл 0600, владелец uid 10001 (Linux) |
контейнер работает под пользователем iam (uid 10001); root-овый 0600 он не прочитает |
Уникальный IAM_SIGNING_KEY_ID на каждый ключ |
сервисы кешируют ключи по kid |
| Файл вне git | secrets/ в .gitignore |
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 -out secrets/iam-signing.pem
chmod 600 secrets/iam-signing.pem
sudo chown 10001:10001 secrets/iam-signing.pem # Linux
Процедура смены ключа — в статье Токены, audiences, scopes.
Issuer¶
IAM_ISSUER определяет iss каждого токена и должен точно совпадать с
issuer, настроенным в сервисах (CP_IAM_ISSUER, CB_IAM_ISSUER,
ENT_IAM_ISSUER, PR_IAM_ISSUER, POL_IAM_ISSUER, …). В compose.yml все
они выводятся из одного TAIMEN_PUBLIC_URL, поэтому совпадают автоматически.
Смена TAIMEN_PUBLIC_URL меняет issuer
Binding principal в Control Plane хранится по паре
(issuer, iam_principal_id). После смены публичного адреса старые
bindings перестают находиться, и вход закрывается для всех. Переносите
bindings тем же изменением — см. Обновление и миграции.
База данных и миграции¶
- Отдельная база PostgreSQL 16 (
iam-db, пользователь и базаiam). - Схема управляется Alembic; контейнер выполняет
alembic upgrade headперед запуском API.alembicберёт строку подключения изIAM_DATABASE_URL. -
Ручной запуск миграций (например, из исходников против базы на хосте):
| Ревизия | Содержимое |
|---|---|
0001 |
tenants, principals, memberships, external identities, группы, audiences, service accounts, outbox, audit |
0002 |
identity providers, федерация, проекция групп |
0003 |
Platform Access Tokens и authentication contexts |
0004 |
SCIM: provisioning sources, SCIM-пользователи и группы |
Резервное копирование — обычный pg_dump базы iam (см.
Резервное копирование). В базе хранятся только хэши
секретов; ключ подписи в базу не входит и копируется отдельно.
Переменные локального клиента¶
Используются CLI iam и клиентами на control-plane-client (MCP-плагин,
runner). Подробно — в Credentials и PAT.
| Переменная | По умолчанию | Описание |
|---|---|---|
IAM_CREDENTIAL_MODE |
пусто | environment (или ci) — брать PAT из IAM_PLATFORM_ACCESS_TOKEN |
IAM_PLATFORM_ACCESS_TOKEN |
пусто | PAT в режиме environment; без режима — ошибка |
IAM_PRINCIPAL |
пусто | чей credential использовать, если на машине их несколько для одной пары IAM + tenant |
IAM_NO_KEYCHAIN |
пусто | 1 — не использовать macOS Keychain (только файл) |
IAM_BINDING_FILE |
пусто | явный путь к binding.json вместо поиска .iam/binding.json |
XDG_CONFIG_HOME |
~/.config |
база пути iam/credentials.json |
CONTROL_PLANE_IAM_URL |
пусто | адрес IAM для клиента Control Plane |
CONTROL_PLANE_IAM_TENANT |
пусто | tenant IAM |
CONTROL_PLANE_IAM_AUDIENCE |
control-plane |
audience обмена |
CONTROL_PLANE_IAM_SCOPES |
пусто | scopes через пробел или запятую |
Типичные проблемы конфигурации¶
| Симптом | Причина | Что сделать |
|---|---|---|
401 unauthorized на административных вызовах |
неверный/пустой X-IAM-Bootstrap-Token, пустой IAM_BOOTSTRAP_TOKEN в контейнере, или использован Authorization: Bearer |
передавайте именно X-IAM-Bootstrap-Token; проверьте переменные контейнера: docker compose exec iam-service env (ищите IAM_BOOTSTRAP_TOKEN) |
500 на /.well-known/jwks.json и на любом обмене |
ключ подписи не задан или не читается | проверьте IAM_SIGNING_KEY_FILE, наличие файла и владельца uid 10001 |
500 при обмене после смены ключа, PermissionError в логах |
файл ключа root:root 0600 |
chown 10001:10001 на хосте, права оставить 0600 |
Сервис отвечает 401 на свежий токен |
iss в токене не равен issuer сервиса |
сверить IAM_ISSUER и *_IAM_ISSUER; оба должны выводиться из TAIMEN_PUBLIC_URL |
Сервис отвечает 503 verification_unavailable |
сервис не может получить JWKS дольше stale_after |
проверить доступность http://iam-service:8010/.well-known/jwks.json из контейнера сервиса |
| Все токены отклоняются несколько минут после смены ключа | kid не изменён |
задать новый IAM_SIGNING_KEY_ID и пересоздать iam-service |
403 scope_not_allowed при обмене |
scope без префикса (write вместо control-plane:write) или вне потолка |
запрашивать полные имена scopes из allowedScopes |
403 authentication_context_required/expired при выпуске PAT человеку |
нет входа или прошло больше 300 с | записать authentication context и сразу выпустить PAT |
400 idempotency_key_required |
не передан Idempotency-Key |
добавить заголовок с новым UUID |
422 principal_kind_not_allowed |
PAT для service account | использовать client credentials |
iam_environment_mode_required у клиента |
задан IAM_PLATFORM_ACCESS_TOKEN без режима |
добавить IAM_CREDENTIAL_MODE=environment |
credential_ambiguous / iam_credential_ambiguous |
несколько credentials одной пары IAM + tenant на машине | задать IAM_PRINCIPAL для каждого процесса |
credentials_file_permissions |
credentials.json доступен группе/всем |
chmod 600 ~/.config/iam/credentials.json |
503 identity_provider_unavailable при федерации |
IAM не достаёт discovery/JWKS IdP | проверить, что IAM разрешает адрес issuer; при необходимости задать jwksUri |
| Вход через браузер создаёт второй principal | external identity не привязана к существующему principal | привязать заранее, см. Федерация |
Больше сценариев — в Диагностике: аутентификация и доступ.