Защита объектов S3 ключом KMS

AWSBeginner
Практиковаться сейчас

Введение

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

Сначала выполните Хранение и получение файлов в S3, Шифрование и расшифровку приватного экспорта с KMS и их предварительные работы по IAM. Эта новая VM предоставляет синтетический экспорт, сеанс роли читателя и независимые эталонные ресурсы.

Связь с сертификацией

Эта лабораторная работа помогает на практике изучить следующие темы экзаменов.

  • Cloud Practitioner (CLF-C02) · Задача 2.2: Шифрование данных S3 в покое и отдельные разрешения объектов и ключей.
  • Solutions Architect – Associate (SAA-C03) · Задача 1.3: Шифрование данных S3 в покое и отдельные разрешения объектов и ключей.
  • Developer – Associate (DVA-C02) · Задача 2.2: Шифрование данных S3 в покое и отдельные разрешения объектов и ключей.
  • CloudOps Engineer – Associate (SOA-C03) · Задача 4.2: Шифрование данных S3 в покое и отдельные разрешения объектов и ключей.
  • Security – Specialty (SCS-C03) · Задача 5.2: Базовая практика: Шифрование данных S3 в покое и отдельные разрешения объектов и ключей.
  • Data Engineer – Associate (DEA-C01) · Задача 4.3: Базовая практика: Шифрование данных S3 в покое и отдельные разрешения объектов и ключей.
  • DevOps Engineer – Professional (DOP-C02) · Задача 6.2: Базовая практика: Шифрование данных S3 в покое и отдельные разрешения объектов и ключей.
  • Solutions Architect – Professional (SAP-C02) · Задача 2.3: Базовая практика: Шифрование данных S3 в покое и отдельные разрешения объектов и ключей.

Подготовка зашифрованного хранилища объектов

На этом шаге вы создадите ключ KMS под управлением клиента и настроите новый бакет на его использование по умолчанию. Бакет хранит объекты; у каждого объекта есть ключ, например exports/private-export.json. Серверное шифрование с KMS (SSE-KMS) позволяет S3 шифровать хранящиеся объекты выбранным вами ключом. Шифрование по умолчанию применяется к новым загрузкам, не требуя от каждого клиента повторять параметры шифрования.

Используйте предоставленный синтетический private-export.json; сеанс роли export-reader изначально не имеет доступа к объекту или ключу. Сохраните эталонные бакет, объект и ключ. Откройте AWS View рядом с Terminal, чтобы сравнивать состояние ключа и бакета, разрешения читателя и безопасные сравнения байтов.

Начните в каталоге проекта и подтвердите предоставленную идентификацию оператора. cd изменяет каталог; запрос вызывающего возвращает ARN идентификации без раскрытия учётных данных.

cd /home/labex/project
aws sts get-caller-identity --query Arn --output text

Ожидайте пользователя labex-sec02-operator. Создайте симметричный ключ под управлением клиента и читаемый псевдоним. --query выбирает ARN, --output text убирает кавычки JSON, а $(...) сохраняет результат в переменной оболочки.

KEY_ARN=$(aws kms create-key \
  --description labex-sec02-owned-export \
  --query KeyMetadata.Arn \
  --output text)
aws kms create-alias \
  --alias-name alias/labex-sec02-private-export \
  --target-key-id "$KEY_ARN"

Используйте временное имя бакета с суффиксом временной метки, чтобы избежать совпадения имён. Префикс labex-sec02-owned- отличает ваш бакет от предоставленного эталона. Работа использует us-east-1, поэтому для создания бакета не требуется ограничение расположения.

BUCKET="labex-sec02-owned-$(date +%s)"
aws s3api create-bucket \
  --bucket "$BUCKET" \
  --region us-east-1 \
  --query Location \
  --output text

Настройте SSE-KMS с точным ARN ключа. S3 Bucket Key может уменьшить повторные запросы KMS; здесь он остаётся отключённым, чтобы каждый объект использовал собственный контекст шифрования KMS. Запишите правило по умолчанию в обычный файл JSON. Here-document подставляет $KEY_ARN; file:// загружает сохранённую конфигурацию.

cat > bucket-encryption.json <<EOF
{
  "Rules": [
    {
      "ApplyServerSideEncryptionByDefault": {
        "SSEAlgorithm": "aws:kms",
        "KMSMasterKeyID": "$KEY_ARN"
      },
      "BucketKeyEnabled": false
    }
  ]
}
EOF

aws s3api put-bucket-encryption --bucket "$BUCKET" \
  --server-side-encryption-configuration file://bucket-encryption.json
aws s3api get-bucket-encryption \
  --bucket "$BUCKET" \
  --query ServerSideEncryptionConfiguration

Ожидайте aws:kms, ARN вашего ключа и BucketKeyEnabled: false. Сохраните KEY_ARN и BUCKET в этом Terminal для последующих команд. В AWS View ключ упражнения включён, а в бакете пока нет объектов.

Предоставление читателю обоих необходимых разрешений

На этом шаге вы загрузите экспорт и позволите роли восстановить его исходные байты. Для загрузки требуется kms:GenerateDataKey для выбранного ключа. SSE-KMS использует ключ данных для шифрования байтов объекта. KMS защищает этот ключ данных; S3 хранит зашифрованный объект и обёрнутый ключ данных, затем запрашивает расшифровку, когда авторизованный читатель скачивает объект. Ключевой материал не должен появляться в выводе CLI.

Разрешения объекта S3 и ключа

Для чтения этого объекта SSE-KMS необходимы и доступ к объекту, и разрешение на расшифровку ключом.

Загрузите предоставленный файл с помощью s3api put-object. Настройки бакета по умолчанию задают шифрование; --body private-export.json читает указанный локальный файл как байты объекта. Для небольшого экспорта используйте этот одночастный API.

aws s3api put-object \
  --bucket "$BUCKET" \
  --key exports/private-export.json \
  --body private-export.json \
  --query '{Encryption:ServerSideEncryption,Key:SSEKMSKeyId,BucketKey:BucketKeyEnabled}'
aws s3api head-object \
  --bucket "$BUCKET" \
  --key exports/private-export.json \
  --query '{Encryption:ServerSideEncryption,Key:SSEKMSKeyId,Bytes:ContentLength}'

Ожидайте aws:kms, ARN ключа упражнения и исходный размер файла. Одни метаданные не показывают, может ли читатель расшифровать данные. Сначала предоставьте только доступ к объекту. ARN объекта включает бакет и ключ объекта; он отличается от ARN бакета. Следующий here-document записывает файл политики и подставляет $BUCKET внутри него.

cat > read-object.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::$BUCKET/exports/private-export.json"
    }
  ]
}
EOF
aws iam put-role-policy \
  --role-name labex-sec02-export-reader \
  --policy-name ReadExportObject \
  --policy-document file://read-object.json

Выберите подготовленный сеанс читателя с --profile export-reader. Эта попытка должна завершиться AccessDenied: роль может читать этот объект, но пока не имеет разрешения расшифровки KMS.

aws \
  --profile export-reader s3api get-object \
  --bucket "$BUCKET" \
  --key exports/private-export.json reader-export.json

Предоставьте этой роли только kms:Decrypt для точного ключа. Для скачивания ей не нужны управление ключом или kms:GenerateDataKey.

cat > decrypt-key.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "kms:Decrypt",
      "Resource": "$KEY_ARN"
    }
  ]
}
EOF
aws iam put-role-policy \
  --role-name labex-sec02-export-reader \
  --policy-name DecryptExportKey \
  --policy-document file://decrypt-key.json
aws \
  --profile export-reader s3api get-object \
  --bucket "$BUCKET" \
  --key exports/private-export.json reader-export.json \
  --query '{Encryption:ServerSideEncryption,Key:SSEKMSKeyId}'
chmod 600 reader-export.json
cmp private-export.json reader-export.json

cmp ничего не выводит и возвращает успех, когда содержимое байтов совпадает. Теперь AWS View должен показывать сохранённый шифротекст и GetObject читателя, возвращённые байты которого совпадают с предоставленным экспортом. Это отдельные наблюдения: зашифрованное хранение защищает байты в покое, а ограниченные разрешения управляют получением данных.

Пример AWS View после разрешения для точного ключа: сохранённый шифротекст и восстановленные читателем исходные байты.

Диагностика ошибок разрешений и состояния ключа

На этом шаге вы отличите отсутствие разрешения расшифровки от отключённого ключа. Сохраните разрешение объекта, чтобы за раз менялось только одно условие.

Удалите разрешение читателя для ключа, затем повторите скачивание того же объекта. У роли по-прежнему есть s3:GetObject, но запрос должен завершиться AccessDenied.

aws iam delete-role-policy \
  --role-name labex-sec02-export-reader \
  --policy-name DecryptExportKey
aws \
  --profile export-reader s3api get-object \
  --bucket "$BUCKET" \
  --key exports/private-export.json reader-export.json

Проверьте оставшуюся политику объекта. Она по-прежнему должна указывать только этот объект экспорта.

aws iam get-role-policy \
  --role-name labex-sec02-export-reader \
  --policy-name ReadExportObject \
  --query PolicyDocument

Восстановите разрешение для точного ключа и отключите свой ключ. Отключённый ключ по-прежнему существует, но не может выполнять криптографические операции. Не изменяйте несвязанный эталонный ключ.

aws iam put-role-policy \
  --role-name labex-sec02-export-reader \
  --policy-name DecryptExportKey \
  --policy-document file://decrypt-key.json
aws kms disable-key --key-id "$KEY_ARN"
aws \
  --profile export-reader s3api get-object \
  --bucket "$BUCKET" \
  --key exports/private-export.json reader-export.json

Ожидайте ошибку отключённого ключа. Наличие разрешения IAM не делает отключённый ключ пригодным к использованию. Подтвердите его состояние непосредственно в сервисе, затем включите его и снова получите объект.

aws kms describe-key --key-id "$KEY_ARN" --query KeyMetadata.KeyState --output text
aws kms enable-key --key-id "$KEY_ARN"
aws \
  --profile export-reader s3api get-object \
  --bucket "$BUCKET" \
  --key exports/private-export.json reader-export.json \
  --query ServerSideEncryption \
  --output text
chmod 600 reader-export.json
cmp private-export.json reader-export.json

Ожидайте aws:kms и успешное сравнение. AWS View сохраняет неудачные запросы вместе с успешным восстановлением, а эталонные бакет и ключ остаются пригодными к использованию. Пример AWS View с ошибками отозванного разрешения и отключённого ключа, после которых следует успешное чтение.

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

Удаление ресурсов упражнения и планирование удаления ключа

На этом шаге вы очистите точно заданные ресурсы экспорта. Сначала завершите предыдущие функциональные проверки. Бакет S3 должен быть пуст перед удалением; ключ KMS под управлением клиента проходит период ожидания удаления, а не исчезает немедленно.

Удалите только ваш указанный экспорт, затем его бакет. Успешно запросите перечень и подтвердите отсутствие вашего $BUCKET и сохранность labex-sec02-reference.

aws s3api delete-object --bucket "$BUCKET" --key exports/private-export.json
aws s3api delete-bucket --bucket "$BUCKET"
aws s3api list-buckets --query 'Buckets[].Name'

Удалите два добавленных вами разрешения и псевдоним упражнения. Предоставленная роль читателя — подготовленный ресурс сеанса; не удаляйте её или несвязанные эталонные ресурсы.

aws iam delete-role-policy \
  --role-name labex-sec02-export-reader \
  --policy-name ReadExportObject
aws iam delete-role-policy \
  --role-name labex-sec02-export-reader \
  --policy-name DecryptExportKey
aws iam list-role-policies --role-name labex-sec02-export-reader --query PolicyNames
aws kms delete-alias --alias-name alias/labex-sec02-private-export

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

aws kms schedule-key-deletion \
  --key-id "$KEY_ARN" \
  --pending-window-in-days 7 \
  --query DeletionDate \
  --output text
aws kms describe-key --key-id "$KEY_ARN" --query KeyMetadata.KeyState --output text
aws kms describe-key \
  --key-id alias/labex-sec02-reference \
  --query KeyMetadata.KeyState \
  --output text

Ожидайте PendingDeletion для вашего ключа и Enabled для эталона. Удалите указанные локальные файлы; эти команды не затрагивают несвязанные файлы проекта.

rm -f private-export.json reader-export.json read-object.json decrypt-key.json bucket-encryption.json

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

rm -f /home/labex/.aws/credentials /home/labex/.aws/config
unset KEY_ARN BUCKET

Резюме

Вы настроили SSE-KMS по умолчанию для бакета, загрузили зашифрованный экспорт и восстановили исходные байты с ролью, ограниченной одним объектом и одним ключом. Отзыв kms:Decrypt и отключение ключа по отдельности препятствовали чтению без изменения разрешения объекта. Вы восстановили доступ, удалили только ресурсы S3 упражнения и запланировали удаление ключа KMS упражнения, сохранив эталонные бакет и ключ.