Ошибка AccessDenied не всегда означает отсутствие одной галочки. Итоговое решение доступа складывается из личности запроса, IAM-policy, bucket policy, resource path, условий, временной сессии и иногда прав на ключ шифрования.

Сначала выясните, от имени какого principal реально выполняется запрос. Затем проверьте конкретное действие над конкретным ARN/ресурсом и явные Deny. Не выдавайте администраторские права приложению ради проверки: используйте симуляцию и минимальную тестовую policy.

Что проверить в первую очередь

Сначала зафиксируйте точный сценарий, время ошибки и последнее известное рабочее состояние. Не меняйте несколько настроек одновременно: один контролируемый шаг должен подтверждать или исключать одну гипотезу. Перед работой с данными и конфигурацией подготовьте резервную копию и понятный способ отката.

  • Получите identity/assumed role текущего процесса, account/project и срок временных credentials.
  • Зафиксируйте действие: ListBucket, GetObject, PutObject, DeleteObject или multipart.
  • Сравните bucket, prefix, регион/endpoint и фактический ключ объекта.
  • Проверьте явные Deny в IAM, bucket policy, organization policy и KMS.

Почему возникает проблема

Внешний симптом обычно появляется на границе нескольких компонентов: интерфейса, backend, базы, фоновой очереди или внешнего сервиса. Поэтому важно найти первое место, где состояние становится неверным, а не исправлять последнее сообщение об ошибке.

  • Приложение ожидает одну роль, но runtime использует instance/service role другого проекта.
  • Policy разрешает object ARN, но не bucket ARN для ListBucket или наоборот.
  • Условие prefix, source VPC, IP или principal не совпадает с запросом.
  • Объект зашифрован KMS-ключом, к которому роль не имеет Encrypt/Decrypt.
  • Временные credentials истекли или не обновляются процессом.

Пошаговая диагностика

Диагностику проводите на тестовой записи или отдельном окружении. В журналах скрывайте токены, пароли и персональные данные. Для каждого шага сохраняйте измеримый результат: идентификатор события, код ответа, версию записи, состояние процесса или контрольную сумму.

  • Выполните безопасный identity call из того же контейнера/процесса.
  • Повторите одну минимальную операцию CLI/SDK с debug metadata без вывода секретов.
  • Проверьте policy simulator или audit log для точного action/resource.
  • Сравните разрешения ListBucket и Get/PutObject отдельно.
  • Проверьте session policy, permission boundary и organization-level restrictions.

Как складывается решение IAM

Разрешение в одной policy не перекрывает явный Deny и не предоставляет доступ к связанному KMS-ключу. Нужно проверить всю цепочку.

  • Principal — пользователь, сервисная учетная запись или assumed role, фактически подписавшая запрос.
  • Action должен точно соответствовать операции SDK, включая multipart и list.
  • Resource различается для самого bucket и объектов внутри него.
  • Conditions ограничивают prefix, теги, сеть, шифрование и другие параметры.
  • KMS key policy и IAM должны совместно разрешать криптографическую операцию.

Как исправить проблему

Исправление лучше разбить на небольшие обратимые изменения. Сначала устраните подтвержденную причину, затем повторите исходный сценарий и проверьте соседние функции. Массовую обработку данных запускайте на ограниченной выборке с отчетом и только после сверки расширяйте на весь объем.

  • Назначьте приложению правильную runtime role вместо статических ключей.
  • Добавьте только нужные actions и prefixes для bucket/object ресурсов.
  • Исправьте bucket policy, сохраняя public access block и явные ограничения.
  • Предоставьте минимальные права на KMS-ключ либо используйте согласованный ключ хранилища.
  • Настройте автоматическое обновление временных credentials и обработку их истечения.

Безопасный порядок внедрения

  • Сохраните затрагиваемые данные, конфигурацию и текущие журналы, заранее проверив способ отката.
  • Повторите проблему на тестовом объекте без реальных списаний, рассылок и изменений клиентских данных.
  • Внесите одно логическое изменение и зафиксируйте его в системе контроля версий или журнале работ.
  • Не отключайте авторизацию, валидацию, шифрование и другие защитные механизмы ради быстрого исчезновения ошибки.
  • После выкладки контролируйте логи, метрики и полный пользовательский сценарий, а не только один успешный запрос.

Как проверить результат

Разовый успешный тест недостаточен. Повторите операцию, проверьте крайние значения, параллельные действия и восстановление после перезапуска или временного сбоя. Для важного сценария сохраните автоматический тест либо короткий регрессионный чек-лист.

  • Приложение выполняет необходимые List/Get/Put и не может обращаться к соседнему prefix.
  • Доступ работает после ротации/истечения временной сессии.
  • Публичный анонимный запрос остается запрещенным.
  • Audit log показывает ожидаемый principal, action и resource без AccessDenied.

Типичные ошибки при исправлении

  • Выдавать AdministratorAccess и оставлять его после диагностики.
  • Хранить access key в репозитории или образе контейнера.
  • Разрешать s3:* на все ресурсы ради одной папки.
  • Игнорировать KMS и organization policy, бесконечно расширяя bucket policy.

Как предотвратить повторение

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

  • Управляйте IAM как кодом и проверяйте изменения review.
  • Используйте короткоживущие роли workload identity вместо постоянных ключей.
  • Добавьте тест положительных и отрицательных действий для каждого сервиса.
  • Мониторьте AccessDenied, неожиданные principals и изменения policy.

Что подготовить для технического разбора

  • Описание ожидаемого и фактического поведения, а также точную последовательность действий.
  • Время проблемы, идентификатор тестового объекта и версии затронутых компонентов.
  • Фрагменты журналов до и после ошибки без секретов и персональных данных.
  • Перечень последних изменений и уже выполненных проверок.
  • Безопасный доступ к тестовой среде или способ воспроизвести сбой без влияния на клиентов.

Частые вопросы

Почему GetObject разрешен, а список файлов нет?

GetObject действует на объект, а ListBucket — на ресурс bucket и часто требует отдельного разрешения с условием prefix.

Может ли bucket policy запретить разрешение IAM?

Да. Явный Deny имеет приоритет, а cross-account доступ обычно требует согласованного разрешения с обеих сторон.

Когда нужна помощь специалиста

Если приложение получает AccessDenied и непонятно, какая роль работает, я могу проследить principal, action и resource, исправить IAM/bucket/KMS policy по принципу минимальных прав и проверить отрицательные сценарии.