Nodejs AWS SDK S3 génère une URL prédéfinie

112

J'utilise le SDK NodeJS AWS pour générer une URL S3 prédéfinie. La documentation donne un exemple de génération d'une URL prédéfinie .

Voici mon code exact (avec les informations sensibles omises):

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)

L'URL qui génère ressemble à ceci:

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

Je copie cette URL dans mon navigateur et j'obtiens la réponse suivante:

<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>

Je sais que le seau existe. Lorsque je navigue vers cet élément via l'interface graphique Web AWS et que je double-clique dessus, cela ouvre l'objet avec l'URL et fonctionne très 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]

Je suis donc amené à croire que je dois faire quelque chose de mal avec la façon dont j'utilise le SDK.

Dustin
la source
1
Examinez attentivement votre URL générée. NoSuchBucketsignifie que le nom du compartiment affiché https://>>>here<<<.s3-us-west-2.amazonaws.comdans l'URL n'existe pas. Rien dans votre processus de signature, stratégie, autorisations, clé ou secret ne peut générer cette erreur particulière.
Michael - sqlbot
8
Le lien vers l'exemple de document a été déplacé vers docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/…
Joël
@Dustin comment est-il sûr si la clé ACCESS est exposée dans l'URL et change d'URL à chaque appel de fonction
kailash yogeshwar
Il n'est pas sûr de mettre le secretAccessKey dans un lieu public, tel que l'URL et oui, je crois que l'URL change à chaque fois. @kailashyogeshwar
Dustin
5
Pour ceux qui viennent ici comme moi et qui n'ont pas obtenu la réponse exacte, c'est ce dont j'avais besoin. Une version de signature différente est utilisée dans chacune des URL ci-dessus. Définissez la version de signature avant de créer l'instance S3 ou définissez-la sur la configuration de S3. new AWS.S3({ signatureVersion: 'v4' })force la Signature Version 4. C'était une exigence pour moi avec un objet chiffré SSE KMS.
Eric E.

Réponses:

99

Dustin,

Votre code est correct, revérifiez ce qui suit:

  1. Votre politique d'accès au bucket.

  2. Votre autorisation de bucket via votre clé API.

  3. Votre clé API et votre secret.

  4. Le nom et la clé de votre bucket.

Reza Mousavi
la source
92
Embarrassant, j'avais une faute de frappe dans mon nom de seau.
Dustin
36
Classique. Cela arrive aux meilleurs d'entre nous.
Vlad A. Ionescu
2

J'ai eu un cas d'utilisation où utiliser node.js; Je voulais obtenir un objet de s3 et le télécharger dans un emplacement temporaire, puis le donner en pièce jointe à un service tiers! Voici comment j'ai cassé le code:

  1. obtenir l'URL signée de s3
  2. faire un appel de repos pour obtenir un objet
  3. écrivez cela dans l'emplacement local

Cela peut aider n'importe qui; s'il y a le même cas d'utilisation; chekout ci - dessous lien ; https://medium.com/@prateekgawarle183/fetch-file-from-aws-s3-using-pre-signed-url-and-store-it-into-local-system-879194bfdcf4

Prateek G
la source
-1

Essayez cette fonction avec promesse.

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
la source