У меня есть лямбда-функция, которая получает изображение из одного сегмента, изменяет его размер и помещает в другое. Лямбда-функция настроена на запуск при создании файла исходного блока. Довольно стандартный материал для учебного уровня.
Когда я использую веб-интерфейс aws, чтобы поместить изображение в исходную корзину, все работает как положено.
Однако, когда я использую xhr из своего веб-приложения для помещения изображения в тот же контейнер, я получаю следующую ошибку (выдается из моего вызова s3.getObject):
AccessDenied: Access Denied
at Request.extractError (/var/runtime/node_modules/aws-sdk/lib/services/s3.js:585:35
ИмеяОбширные поиски, большинство людей говорят, что 403 ошибки обычно сводятся к роли / политике разрешений для лямбда-функции. Но когда я траляю журналы, единственное различие, которое я вижу между моей загрузкой xhr и загрузкой веб-интерфейса aws, - это eventName и userIdentity.
Для загрузки веб-интерфейса это Put и PrincipalId:
eventName: 'ObjectCreated:Put',
userIdentity: { principalId: 'AWS:AIDAJ2VMZPNX5NJD2VBLM' }
Но при вызове xhr это сообщение и аноним:
eventName: 'ObjectCreated:Post',
userIdentity: { principalId: 'Anonymous' }
Моя роль Lambda имеет две политики:
AWSLambdaExecute
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:*"
],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::*"
}
]
}
AWSLambdaBasicExecutionRole
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
Мои корзины S3 имеют следующие политики:
Исходная корзина:
{
"Version": "2012-10-17",
"Id": "Lambda access bucket policy",
"Statement": [
{
"Sid": "All on objects in bucket lambda",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:*",
"Resource": "arn:aws:s3:::source-bucket-name/*"
},
{
"Sid": "All on bucket by lambda",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:*",
"Resource": "arn:aws:s3:::source-bucket-name"
}
]
}
Целевая корзина:
{
"Version": "2012-10-17",
"Id": "Lambda access bucket policy",
"Statement": [
{
"Sid": "All on objects in bucket lambda",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:*",
"Resource": "arn:aws:s3:::destination-bucket-name/*"
},
{
"Sid": "All on bucket by lambda",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:*",
"Resource": "arn:aws:s3:::destination-bucket-name"
}
]
}
Нужно ли как-то передавать(или назначить) идентификатор участника для моего вызова xhr, чтобы он заработал? Или мне нужно добавить разрешения / политики / роли к моей функции, чтобы она могла запускать функцию без основного идентификатора, привязанного к триггеру?
РЕДАКТИРОВАТЬ: Вот код JS, который отправляет файл POST в файлисходное ведро:
function uploadFileAttachment(attachment, form) {
var formButtons = document.querySelectorAll("form.form--trix button.btn");
formButtons.forEach((button) => {
button.setAttribute("disabled", "disabled");
});
uploadFile(attachment.file, setProgress, setAttributes)
function setProgress(progress) {
attachment.setUploadProgress(progress)
}
function setAttributes(attributes) {
attachment.setAttributes(attributes)
formButtons.forEach((button) => {
button.removeAttribute("disabled");
});
}
}
function uploadFile(file, progressCallback, successCallback) {
var key = createStorageKey(file)
var formData = createFormData(key, file)
var xhr = new XMLHttpRequest()
xhr.open("POST", global.s3url, true)
xhr.upload.addEventListener("progress", function(event) {
var progress = event.loaded / event.total * 100
progressCallback(progress)
})
xhr.addEventListener("load", function(event) {
if (xhr.status == 204) {
var attributes = {
url: global.s3url + key,
href: global.s3url + key + "?content-disposition=attachment"
}
successCallback(attributes)
}
})
xhr.send(formData);
}
function createStorageKey(file) {
var date = new Date()
var day = date.toISOString().slice(0,10)
var name = date.getTime() + "-" + file.name
return [ "trix", day, name ].join("/")
}
function createFormData(key, file) {
var data = new FormData()
data.append("key", key)
data.append("Content-Type", file.type)
data.append("file", file)
return data
}