403 ошибка при загрузке в личное хранилище S3 с использованием предварительно подписанного URL-адреса

#amazon-s3 #axios #aws-amplify

Вопрос:

У меня есть приложение React, использующее Amplify, где у каждого пользователя есть личная папка в корзине S3. Пользователи могут загружать и скачивать файлы только в свою личную корзину. Я хотел бы, чтобы некоторые пользователи могли загружать файлы в личные папки других пользователей, используя предварительно подписанные URL-адреса S3.

Я создал лямбда-функцию на серверной части, которая генерирует предварительно подписанный URL-адрес:

 // do some authorization checks...
let key = uuidv4()   '.pdf'
let params = {
   Bucket: config.bucket,
   Key: key,
   ContentType: 'application/pdf',
   Expires: config.signedUrlExpirySeconds,
}
const url = await s3.getSignedUrl('putObject', params)
return url
 

Теперь у меня есть URL-адрес в моем интерфейсе, где

 
const [ file, setFile ] = useState(null)

const handleChange = async (e) => {
   const { target: { value, files }} = e
   setFile(files[0])
}

const getURL = async () => {
   // get the pre-signed URL...
}

const upload = async (url, type) => {
  try {
    const result = await axios.put(url, file, {
      headers: {
        'Content-Type': type
      }
    })
  }
  catch (err) {
    console.log(err)
  }
}

const handleUpload = async () => {
   const url = await getURL()
   await upload(url, 'application/pdf')
}

return (
   <div>
      <input type="file" accept=".pdf" onChange={handleChange} />
      <button onClick={handleUpload}>Upload</button>
   </div>
)

 

Однако это возвращает ошибку 403:

 Error: Request failed with status code 403
    at createError (createError.js:16)
    at settle (settle.js:17)
    at XMLHttpRequest.handleLoad (xhr.js:62)
 

Есть ли что-нибудь, чего мне не хватает ?

Возможно, с политикой корзины или CORS, или я использую useState для хранения загруженного файла (или мне нужно преобразовать его во что-то)?

Если это полезно, моя политика ведра такова:

 {
    "Version": "2012-10-17",
    "Id": "Policy1624459513917",
    "Statement": [
        {
            "Sid": "Stmt1624459491997",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::##########/public/images/*"
        },
        {
            "Sid": "Stmt1624459491997b",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::##########/protected/*/images/*"
        }
    ]
}
 

Комментарии:

1. Есть ли у лямбды s3:PutObject разрешение?

2. Это сработало. Большое спасибо! Я не думал проверять разрешения Лямбда-кода, генерирующего предварительно подписанный URL-адрес, так как он генерировал строку URL-адреса, но похоже, что эта сгенерированная строка содержит разрешения, унаследованные от функций Лямбда.

3. Нп, я рад, что это помогает 🙂 Пожалуйста, подумайте о том, чтобы принять мой ответ ниже.

Ответ №1:

Согласно комментарию ОП, добавление s3:PutObject роли лямбды сработало.