Перейти к содержанию
Новое AiManual теперь в MAX Подписаться
Публикация AiManual

Private Key JWT аутентификация для агентов Amazon Bedrock AgentCore Identity: полное руководство

Пошаговое руководство по настройке Private Key JWT клиентской аутентификации для агентов Amazon Bedrock AgentCore Identity. Создание асимметричного ключа в AWS

Коротко

Что будет в материале

  1. 01

    Почему Private Key JWT - это новый стандарт безопасности для агентов Bedrock

  2. 02

    Архитектура решения: как Bedrock AgentCore Identity работает с KMS

  3. 03

    Пошаговая настройка: от ключа KMS до первого вызова агента

  4. 04

    Поддержка грантовых потоков: machine-to-machine, on-behalf-of и user-delegated

Почему Private Key JWT - это новый стандарт безопасности для агентов Bedrock

Классическая OAuth 2.0 аутентификация с client_secret создает две фундаментальные проблемы для production-агентов. Долгоживущий секрет можно скомпрометировать через утечку репозитория, лог ошибки или внутреннюю атаку. Ротация секрета требует координации между командой безопасности, DevOps и владельцем агента - процесс, который редко выполняется вовремя.

Private Key JWT Client Authentication (RFC 7521, RFC 7523) заменяет статичный секрет на асимметричную криптографию. Агент генерирует подписанный JWT-токен, используя приватный ключ из AWS KMS, а провайдер идентификации проверяет подпись публичным ключом. Приватный ключ никогда не покидает KMS - даже ваш код не имеет к нему доступа. Компрометация подписанного токена ограничена его коротким временем жизни (обычно 5 минут), в отличие от client_secret, который остается валидным до ручного отзыва.

Amazon Bedrock AgentCore Identity интегрирует эту модель напрямую с AWS KMS. Вы создаете асимметричный ключ с операцией SIGN_VERIFY, указываете его ARN в конфигурации credential provider, и Bedrock автоматически подписывает JWT при каждом обращении агента к внешним API. Это соответствует лучшим практикам безопасности AWS Well-Architected Framework и устраняет необходимость хранить секреты в переменных окружения или Secrets Manager.

Архитектура решения: как Bedrock AgentCore Identity работает с KMS

Поток аутентификации состоит из четырех компонентов, взаимодействующих в строгой последовательности.

Агент Bedrock инициирует вызов к защищенному ресурсу. Вместо передачи client_secret он обращается к credential provider - конфигурации, которая определяет, как получить токен доступа. Credential provider формирует JWT с claims (issuer, subject, audience, время жизни) и отправляет его в AWS KMS на подпись. KMS выполняет операцию Sign с указанным асимметричным ключом и возвращает подпись, которая добавляется в JWT.

Подписанный JWT отправляется на token endpoint провайдера идентификации (Okta, Auth0, Azure AD, Amazon Cognito). Провайдер извлекает kid из заголовка JWT, находит соответствующий публичный ключ в своем хранилище JWKS и проверяет подпись. При успешной проверке провайдер возвращает access token, который агент использует для вызова целевого API.

AgentCore Identity выступает прослойкой между агентом и credential provider. Он управляет жизненным циклом JWT: кэширует подписанные assertion-токены до истечения срока, обрабатывает ошибки подписи и автоматически запрашивает refresh token при истечении access token. Для разработчика это выглядит как декларативная конфигурация - код агента не содержит криптографической логики.

Пошаговая настройка: от ключа KMS до первого вызова агента

Шаг 1: Создание асимметричного ключа в AWS KMS

Выбор спецификации ключа зависит от требований провайдера идентификации. ECC_NIST_P256 обеспечивает компактную подпись (64 байта) и высокую производительность. RSA_2048 совместим с более широким спектром legacy-систем. Для Bedrock AgentCore Identity рекомендуется ECC_NIST_P256, если провайдер поддерживает ES256.

Создайте ключ через AWS CLI:

aws kms create-key \
  --key-spec ECC_NIST_P256 \
  --key-usage SIGN_VERIFY \
  --description "Bedrock AgentCore Identity signing key" \
  --tags TagKey=Environment,TagValue=production

Команда возвращает ARN ключа. Создайте алиас для упрощения дальнейших операций:

aws kms create-alias \
  --alias-name alias/bedrock-agentcore-signing-key \
  --target-key-id <key-id>

Настройте key policy, разрешающую сервису Bedrock использовать ключ для подписи. Минимальная политика:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "bedrock.amazonaws.com"
      },
      "Action": "kms:Sign",
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "aws:SourceAccount": "<your-account-id>"
        }
      }
    }
  ]
}

Без этого условия любой ресурс Bedrock в вашем аккаунте сможет использовать ключ. Для production-среды сузьте доступ через SourceArn конкретного credential provider.

Шаг 2: Экспорт публичного ключа и регистрация у провайдера идентификации

Публичный ключ из KMS извлекается в формаме DER. Для регистрации у провайдера его нужно конвертировать в PEM:

aws kms get-public-key \
  --key-id alias/bedrock-agentcore-signing-key \
  --output text \
  --query PublicKey | base64 --decode > public_key.der

openssl ec -inform DER -in public_key.der -pubin -pubout -outform PEM -out public_key.pem

Провайдеры идентификации принимают ключи двумя способами. Ручная загрузка: в настройках OAuth-клиента найдите раздел «Client Authentication», выберите «Private Key JWT» и загрузите содержимое public_key.pem. JWKS endpoint: если провайдер поддерживает динамическое разрешение ключей, опубликуйте JWKS-документ с публичным ключом на HTTPS-эндпоинте, доступном провайдеру.

Для Okta настройка выглядит так: Applications → ваш OIDC-клиент → Client Credentials → Client authentication method → Private Key / JWT → загрузите PEM-файл. Okta автоматически извлечет kid и алгоритм из ключа.

Шаг 3: Конфигурация credential provider в консоли Amazon Bedrock

Credential provider связывает KMS-ключ с параметрами OAuth-клиента. Перейдите в консоли AWS: Bedrock → Agents → AgentCore Identity → Credential providers → Create credential provider.

Заполните обязательные поля:

  • Provider name: логическое имя (например, «okta-production»).
  • KMS key ID: ARN или алиас созданного ключа.
  • Issuer URL: URL провайдера идентификации (https://dev-123456.okta.com).
  • Token endpoint: полный путь к token endpoint (https://dev-123456.okta.com/oauth2/v1/token).
  • Client ID: идентификатор OAuth-клиента, зарегистрированного у провайдера.
  • Subject: субъект JWT - обычно совпадает с client_id для M2M-потоков.
  • Audience: получатель токена - должен совпадать с token endpoint или issuer URL (зависит от провайдера).

После сохранения конфигурации нажмите «Test connection». Bedrock выполнит пробный вызов: сгенерирует JWT, подпишет его в KMS и отправит на token endpoint. Результат теста покажет HTTP-статус и тело ответа - успешный ответ содержит access_token и expires_in.

Критическая ошибка на этом этапе - несовпадение audience. Okta требует audience равным token endpoint, Auth0 - равным issuer URL. Проверьте документацию провайдера. Ошибка «Invalid grant» с кодом invalid_client означает, что публичный ключ не зарегистрирован или не соответствует приватному ключу в KMS.

Поддержка грантовых потоков: machine-to-machine, on-behalf-of и user-delegated

Machine-to-Machine (M2M): агент действует от своего имени

M2M-поток используется для фоновых задач без участия пользователя: nightly-сборка дашбордов, автоматическая модерация контента, синхронизация данных между системами. Агент аутентифицируется как самостоятельный субъект с собственными правами.

Конфигурация credential provider для M2M минимальна. Укажите grant_type = client_credentials в дополнительных параметрах провайдера. JWT, отправляемый на token endpoint, содержит следующие claims:

{
  "iss": "https://dev-123456.okta.com",
  "sub": "0oabc123def456",
  "aud": "https://dev-123456.okta.com/oauth2/v1/token",
  "iat": 1722345600,
  "exp": 1722345900,
  "jti": "unique-jwt-id-abc123"
}

sub равен client_id агента. Провайдер идентификации выпускает access token с claims, соответствующими разрешениям этого клиента. Типичная ошибка - указание audience, отличного от token endpoint. Провайдер возвращает «Invalid audience» и отказывает в выдаче токена.

On-Behalf-Of (OBO): агент выполняет действия от имени пользователя

OBO-поток позволяет агенту получить доступ к ресурсам пользователя после его аутентификации. Пользователь входит в приложение через стандартный OIDC-поток, получает access token и id token. Приложение передает user token агенту, который обменивает его на agent token через token exchange.

Настройка credential provider для OBO требует дополнительных параметров:

  • grant_type: urn:ietf:params:oauth:grant-type:jwt-bearer
  • assertion: user token, полученный от пользователя
  • requested_token_type: urn:ietf:params:oauth:token-type:access_token

JWT, подписанный KMS, выступает как client assertion, а user token передается в параметре assertion. Провайдер проверяет оба токена и выпускает access token с claims пользователя, добавляя поле act (actor) с идентификатором агента:

{
  "sub": "user-789",
  "act": {
    "sub": "agent-456"
  },
  "scope": "read:documents write:documents"
}

Это позволяет аудит-логам различать действия пользователя и агента, действующего от его имени. Refresh token, полученный в OBO-потоке, привязан к цепочке пользователь-агент и может быть использован для продления сессии без повторной аутентификации пользователя.

User-Delegated Access: агент с ограниченными правами пользователя

User-delegated access отличается от OBO тем, что пользователь явно ограничивает права агента через consent-экран. Агент получает не полный доступ пользователя, а только запрошенные scope.

Конфигурация credential provider включает параметр scope с перечнем запрашиваемых разрешений. При первой аутентификации провайдер показывает пользователю consent-экран: «Агент X запрашивает доступ к чтению ваших документов. Разрешить?» Пользователь может согласиться или отклонить отдельные scope.

JWT, выпущенный после consent, содержит поле scp (scope) с фактически предоставленными разрешениями:

{
  "sub": "user-789",
  "act": {
    "sub": "agent-456"
  },
  "scp": ["read:documents"],
  "scope": "read:documents"
}

Агент запрашивал read:documents и write:documents, но пользователь предоставил только чтение. Агент должен проверять scp в токене и обрабатывать отказ в доступе при попытке записи.

Аудит с CloudTrail: отслеживаем каждый вызов агента

CloudTrail автоматически логирует все вызовы KMS Sign, выполняемые Bedrock AgentCore Identity. Для включения расширенного логирования вызовов credential provider перейдите в CloudTrail → Event History → фильтр по Event source = bedrock.amazonaws.com.

Пример лога для успешной M2M-аутентификации

{
  "eventVersion": "1.09",
  "eventTime": "2026-07-30T10:15:30Z",
  "eventSource": "bedrock.amazonaws.com",
  "eventName": "GetAccessToken",
  "userIdentity": {
    "type": "AWSService",
    "invokedBy": "bedrock.amazonaws.com"
  },
  "requestParameters": {
    "credentialProviderArn": "arn:aws:bedrock:us-east-1:123456789:credential-provider/okta-production",
    "grantType": "client_credentials",
    "clientAssertionType": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"
  },
  "responseElements": {
    "tokenType": "Bearer",
    "expiresIn": 3600,
    "scope": "read:data"
  },
  "requestID": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "eventID": "b2c3d4e5-f6a7-8901-bcde-f12345678901"
}

Ключевые поля для мониторинга: eventName = GetAccessToken фиксирует факт запроса токена, requestParameters.credentialProviderArn указывает конкретный провайдер, responseElements.expiresIn позволяет отслеживать аномально короткое время жизни токена (признак проблем с доверием).

Типичные ошибки и их отражение в CloudTrail

InvalidSignatureException возникает, когда KMS не может проверить целостность запроса на подпись. В логе присутствует errorCode = «InvalidSignatureException» и errorMessage с деталями. Причина обычно в несовпадении key spec (используется симметричный ключ вместо асимметричного) или повреждении JWT перед отправкой в KMS.

AccessDeniedException указывает на проблему с KMS key policy. Лог содержит errorCode = «AccessDeniedException», userIdentity.arn роли, пытавшейся выполнить операцию, и resourceArn ключа. Проверьте, что key policy разрешает действие kms:Sign для сервиса bedrock.amazonaws.com с условием SourceAccount.

InvalidGrantException возвращается провайдером идентификации и транслируется Bedrock в CloudTrail. errorMessage содержит ответ провайдера: «Invalid audience», «Client not found», «Invalid client assertion». Проверьте соответствие audience, client_id и зарегистрированного публичного ключа.

Очистка ресурсов: удаляем ключи и провайдеры без последствий

Порядок удаления важен: сначала отключите активные компоненты, затем удалите ключевой материал.

Удалите credential provider. Это немедленно прекращает все вызовы агентов, использующих этот провайдер:

aws bedrock delete-credential-provider \
  --credential-provider-arn arn:aws:bedrock:us-east-1:123456789:credential-provider/okta-production

Запланируйте удаление KMS-ключа. AWS KMS требует окно ожидания 7-30 дней перед безвозвратным удалением:

aws kms schedule-key-deletion \
  --key-id alias/bedrock-agentcore-signing-key \
  --pending-window-in-days 7

В течение этого окна ключ недоступен для использования, но может быть восстановлен командой cancel-key-deletion. После истечения окна ключ и все данные, зашифрованные им, безвозвратно уничтожаются.

Отзовите публичный ключ у провайдера идентификации. В консоли провайдера удалите загруженный PEM-файл из настроек OAuth-клиента или переключите метод аутентификации обратно на client_secret. Без этого шага провайдер продолжит принимать JWT, подписанные удаленным ключом, если злоумышленник сохранил копию подписанного assertion-токена до истечения его срока жизни.

Проверьте через CloudTrail, что вызовы прекратились. Фильтр по eventName = GetAccessToken и credentialProviderArn удаленного провайдера должен показывать нулевую активность после удаления.

Сравнение с альтернативами и лучшие практики

Критерий Private Key JWT + KMS client_secret mTLS
Безопасность хранения Приватный ключ в KMS, недоступен коду Секрет в переменных окружения / Secrets Manager Сертификат на диске агента
Ротация Автоматическая через KMS, прозрачна для агента Ручная, требует координации Ручная, перевыпуск сертификата
Сложность настройки Средняя (KMS + провайдер) Низкая Высокая (PKI, CRL)
Поддержка в Bedrock Нативная через AgentCore Identity Через Secrets Manager Не поддерживается
Аудит операций CloudTrail для каждого вызова KMS Только доступ к секрету Зависит от инфраструктуры
Время жизни токена Короткоживущий JWT (5-10 минут) Постоянный секрет Сертификат на месяцы/годы

Private Key JWT с KMS - обоснованный выбор для production-сред с высокими требованиями безопасности. Аудит каждого вызова через CloudTrail, автоматическая ротация ключей KMS и отсутствие долгоживущих секретов в коде устраняют основные векторы атак на аутентификацию агентов.

client_secret допустим для dev/test-сред, где скорость прототипирования важнее безопасности. В таких сценариях используйте AWS Secrets Manager с автоматической ротацией и никогда не храните секреты в коде или конфигурационных файлах.

mTLS не поддерживается Bedrock AgentCore Identity нативно и требует развертывания дополнительной инфраструктуры (private CA, управление сертификатами агентов). Этот метод оправдан только при интеграции с legacy-системами, которые не поддерживают OAuth 2.0.

Рекомендация: начинайте с Private Key JWT + KMS для всех новых агентов Bedrock. Затраты на первоначальную настройку (около 30 минут по инструкции выше) окупаются отсутствием инцидентов, связанных с утечкой секретов.

Подписаться на канал