Nodejs AWS SDK S3 Generar URL preseleccionada

112

Estoy usando el SDK de AWS de NodeJS para generar una URL de S3 preestablecida. Los documentos dan un ejemplo de cómo generar una URL pre-firmada .

Aquí está mi código exacto (con información confidencial omitida):

const AWS = require('aws-sdk')

const s3 = new AWS.S3()
AWS.config.update({accessKeyId: 'id-omitted', secretAccessKey: 'key-omitted'})

// Tried with and without this. Since s3 is not region-specific, I don't
// think it should be necessary.
// AWS.config.update({region: 'us-west-2'})

const myBucket = 'bucket-name'
const myKey = 'file-name.pdf'
const signedUrlExpireSeconds = 60 * 5

const url = s3.getSignedUrl('getObject', {
    Bucket: myBucket,
    Key: myKey,
    Expires: signedUrlExpireSeconds
})

console.log(url)

La URL que genera se ve así:

https://bucket-name.s3-us-west-2.amazonaws.com/file-name.pdf?AWSAccessKeyId=[access-key-omitted]&Expires=1470666057&Signature=[signature-omitted]

Estoy copiando esa URL en mi navegador y obtengo la siguiente respuesta:

<Error>
  <Code>NoSuchBucket</Code>
  <Message>The specified bucket does not exist</Message>
  <BucketName>[bucket-name-omitted]</BucketName>
  <RequestId>D1A358D276305A5C</RequestId>
  <HostId>
    bz2OxmZcEM2173kXEDbKIZrlX508qSv+CVydHz3w6FFPFwC0CtaCa/TqDQYDmHQdI1oMlc07wWk=
  </HostId>
</Error>

Sé que el balde existe. Cuando navego hasta este elemento a través de la GUI web de AWS y hago doble clic en él, abre el objeto con la URL y funciona bien:

https://s3-us-west-2.amazonaws.com/[bucket-name-omitted]/[file-name-omitted].pdf?X-Amz-Date=20160808T141832Z&X-Amz-Expires=300&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Signature=[signature-omitted]&X-Amz-Credential=ASIAJKXDBR5CW3XXF5VQ/20160808/us-west-2/s3/aws4_request&X-Amz-SignedHeaders=Host&x-amz-security-token=[really-long-key]

Así que me hacen creer que debo estar haciendo algo mal con la forma en que estoy usando el SDK.

Dustin
fuente
1
Examine cuidadosamente su URL generada. NoSuchBucketsignifica que el nombre del depósito que se muestra https://>>>here<<<.s3-us-west-2.amazonaws.comen la URL no existe. Nada en su proceso de firma, política, permisos, clave o secreto puede generar este error en particular.
Michael - sqlbot
8
El enlace al ejemplo de documento se ha movido a docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/…
Joël
@Dustin, ¿qué tan seguro es si la clave ACCESS está expuesta en la url y la url cambia en cada llamada de función?
kailash yogeshwar
No es seguro poner secretAccessKey en un lugar público, como la URL y sí, creo que la URL cambia cada vez. @kailashyogeshwar
Dustin
5
Para aquellos que vienen aquí como yo y no obtuvieron la respuesta exacta, esto es lo que necesitaba. Se está utilizando una versión de firma diferente en cada una de las URL anteriores. Configure la versión de la firma antes de crear la instancia de S3 o configure la configuración de S3. new AWS.S3({ signatureVersion: 'v4' })fuerza la Signature Version 4. Este era un requisito para mí con un objeto cifrado SSE KMS.
Eric E.

Respuestas:

99

Dustin,

Su código es correcto, verifique lo siguiente:

  1. Su política de acceso al depósito.

  2. Su permiso de depósito a través de su clave API.

  3. Tu clave y secreto de API.

  4. El nombre y la clave de su depósito.

Reza Mousavi
fuente
92
Vergonzosamente, tuve un error tipográfico en el nombre de mi cubo.
Dustin
36
Clásico. A los mejores nos pasa.
Vlad A. Ionescu
2

Tuve un caso de uso en el que usaba node.js; Quería obtener el objeto de s3 y descargarlo en una ubicación temporal y luego adjuntarlo a un servicio de terceros. Así es como rompí el código:

  1. obtener URL firmada desde s3
  2. hacer una llamada de descanso para obtener el objeto
  3. escribir eso en la ubicación local

Puede ayudar a cualquiera; si hay el mismo caso de uso; chekout debajo del enlace ; https://medium.com/@prateekgawarle183/fetch-file-from-aws-s3-using-pre-signed-url-and-store-it-into-local-system-879194bfdcf4

Prateek G
fuente
-1

Pruebe esta función con promesa.

const AWS = require("aws-sdk");
const s3 = new AWS.S3({
  accessKeyId: 'AK--------------6U',
  secretAccessKey: 'kz---------------------------oGp',
  Bucket: 'bucket-name'
});

const getSingedUrl = async () => {    
  const params = {
    Bucket: 'bucket_name',
    Key: 'file-name.pdf',
    Expires: 60 * 5
  };

  try {
    const url = await new Promise((resolve, reject) => {
      s3.getSignedUrl('getObject', params, (err, url) => {
        err ? reject(err) : resolve(url);
      });
    });
    console.log(url)
  } catch (err) {
    if (err) {
      console.log(err)
    }
  }
}


getSingedUrl()
Ankit Kumar Rajpoot
fuente