#amazon-web-services #amazon-s3 #lambda
#amazon-веб-сервисы #amazon-s3 #лямбда
Вопрос:
Я пытаюсь использовать AWS Lambda для резервного копирования объектов из assets.myapp.com
корзины S3 под Account-A
в backup-assets.myapp.com
корзину S3 под Account-B
, но я получаю, Access Denied
независимо от того, IAM
или Bucket Policy
какую конфигурацию я использую.
У меня есть вызванная лямбда-функция Backup-S3-Object
, и она запускается s3:PutObject
триггером события в assets.myapp.com
корзине.
Желаемый результат заключается в том, что Backup-S3-Object
функция выполнит s3.copyObject
to backup-assets.myapp.com
с использованием AWS-SDK для Javascript.
Лямбда-код
var aws = require('aws-sdk');
var s3 = new aws.S3({ apiVersion: '2006-03-01' });
exports.backupObject = function(event, context, callback) {
var data = event.Records[0];
var sourceBucket = data.s3.bucket.name;
var targetBucket = 'backup-' data.s3.bucket.name;
var key = data.s3.object.key;
console.log('BACKUP: ' sourceBucket '/' key ' to ' targetBucket);
s3.copyObject({
Bucket : targetBucket,
CopySource : sourceBucket '/' key,
Key : key,
ACL : 'private',
ServerSideEncryption : 'AES256'
}, function(error, data) {
if (error) return context.done(error);
return context.done(null, 'Successful backup of ' sourceBucket '/' key);
});
};
Политика Lambda-роли S3
У меня есть следующая политика для Backup-S3-Lambda-Role
, которая назначена моей лямбда-функции. Это позволяет функции Lambda получить доступ к List
или Get
любому объекту из любой корзины в Account-A
разделе, который является исходной учетной записью. Таким образом, эта политика позволит лямбда-функции получать объект из assets.myapp.com
, который является исходным блоком.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:ListBucketVersions",
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": [
"arn:aws:s3:::*"
]
}
]
}
backup-assets.myapp.com
Политика корзины
И затем, в Account-B
разделе, у меня есть следующая политика корзины, прикрепленная к backup-assets.myapp.com
, которая предназначена для того, чтобы разрешить функции Lambda, запущенной в Account-A
разделе, выполнять запись в backup-assets.myapp.com
корзину в Account-B
{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "Allow PUT from Account-A Lambda function",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNT-A-NUMBER-HERE:role/Backup-S3-Lambda-Role"
},
"Action": "s3:PutObject",
"Resource": [
"arn:aws:s3:::backup-assets.myapp.com",
"arn:aws:s3:::backup-assets.myapp.com/*"
]
}
]
}
Что происходит?
Триггер в assets.myapp.com
корзине срабатывает просто отлично. Это запускает Backup-S3-Object
функцию Lambda, и функциональная логика способна определить правильные имена корзин и ключ объекта для копирования, но это всегда приводит к сбою с Access Denied
.
Я выполнил тест с использованием той же настройки и переноса в другую корзину, которая также находится под Account-A
, и она работает просто отлично. Итак, проблема, очевидно, в разрешениях для разных учетных записей, но ничего из того, что я пробовал, не работает.
Я также пытался использовать CanonicalID
of Account-A
в качестве Principal
в backup-assets.myapp.com
политике корзины, но все равно получаю Access Denied
результирующую ошибку.
И я попытался использовать "AWS": "arn:aws:iam::ACCOUNT-A-NUMBER-HERE:root"
в качестве основного ту же ошибку.
Есть помощь?
Решение: Как описано Мэттом ниже, решение заключается в том, что вам необходимо включить
s3:PutObject
разрешение в политику роли Lambda. Для меня это немного странно, но общая идея заключается в том, что любые разрешения, которые вы предоставляете роли Lambda в политике корзины вашего целевого корзины, также должны быть реплицированы в политике Lambda под вашей исходной учетной записью. Похоже, что роль Lambda принимается полностью, когда вы ссылаетесь на нее в Политике корзины. Чтобы достичь этого, я добавил вторую встроенную политику к моей роли Lambda, которая позволяетs3:PutObject
использоватьbackup-assets.myapp.com
корзину подAccount-B
. Это запрещает лямбда-функции выполнять запись в любой из исходных сегментов, но позволяет ей выполнять запись в резервный сегмент.
Ответ №1:
Я вижу две возможные проблемы.
- В вашей политике IAM для вашей функции Lambda отсутствуют разрешения на запись в вашу корзину резервного копирования.
Попробуйте добавить s3:PutObject
в свою политику следующим образом:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:ListBucketVersions",
"s3:GetObject",
"s3:GetObjectVersion",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::*"
]
}
]
}
Или, если вы хотите по-прежнему ограничивать свою лямбда-функцию доступом только для чтения в исходных корзинах, вы можете добавить вторую политику к своей роли Lambda, позволяющую ей s3:PutObject
работать в вашей корзине резервного копирования, называя вашу корзину резервного копирования ресурсом, например, так:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::backup-assets.myapp.com",
"arn:aws:s3:::backup-assets.myapp.com/*"
]
}
]
}
- Иногда использование ролей IAM в качестве участников в ваших политиках IAM не так просто, как у вас. Я не говорю, что это проблема, но давайте ослабим ограничения, пока вы не заработаете копирование. Затем вы можете ужесточить политику.
На данный момент просто предоставьте целевой учетной записи доступ к исходной корзине:
{
"Version": "2008-10-17",
"Id": "Backup-Assets",
"Statement": [
{
"Sid": "Allow PUT from Account-A Lambda function",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNT-A-NUMBER-HERE:root"
},
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::backup-assets.myapp.com",
"arn:aws:s3:::backup-assets.myapp.com/*"
]
}
]
}
Как только копирование сработает, вы можете попробовать добавить роль обратно.
Комментарии:
1. Спасибо за ответ @Matt Houser, но я думаю, что вы перепутали политику.
Backup-S3-Object
Лямбда-роль имеет только разрешенияList
иGet
на исходную корзину (assets.myapp.com
), потому что ей просто нужно извлечь объект оттуда, не нужно ничего записывать в эту корзину. Затем я использую политику корзины наbackup-assets.myapp.com
, чтобы разрешить роли Lamba выполнять запись в корзину резервного копирования подAccount-B
. Я уже пробовал предоставитьarn:aws:iam:ACCOUNT-A-NUMBER-HERE:root
, но попробую еще раз. Но я думаю, что лямбда-функция не запускается подroot
, не уверен.2. Да, та же проблема с
root
участником.3. Ладно, это ошибка. Когда я добавляю
s3:PutObject
в политику роли Lambda, это работает. Но почему? Предполагается, что эта политика определяет разрешения, которые лямбда-функция имеет для исходной корзины,assets.myapp.com
из которой требуется только чтение . Почему для копирования объекта вPUT
корзину требуютсяbackup-assets.myapp.com
учетные данные в исходной корзине?4. Это также работает, когда я переключаю участника обратно на
Backup-S3-Object
роль Lambda. Но меня действительно беспокоит, что я должен даватьPutObject
разрешение функции Lambda для моих исходных корзин. Все, что ему нужно сделать, это прочитать из них, а не записать, так почему?5. @AJB это потому, что вы работаете с разными учетными записями. Для предоставления доступа внешней учетной записи недостаточно. Для доступа к ресурсу из внешней учетной записи также требуется разрешение от вашей локальной учетной записи. «Пока у пользователя есть разрешение как от владельца ресурса, так и от родительской учетной записи, пользователь сможет получить доступ к ресурсу». В данном случае локальное разрешение предоставляется ролью. Если все находится в одной учетной записи, это очевидное дублирование необязательно.