web-dev-qa-db-fra.com

Comment puis-je mettre un objet sur Amazon s3 en utilisant une URL présignée?

J'essaie d'utiliser une URL signée pour télécharger des images dans le compartiment s3. Voici la politique de mon seau: 

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::12345678:user/myuser",
                    "arn:aws:iam::12345678:root"
                ]
            },
        "Action": [
                "s3:List*",
                "s3:Put*",
                "s3:Get*"
            ],
            "Resource": [
                "arn:aws:s3:::myBucket",
                "arn:aws:s3:::myBucket/*"
            ]
        }
    ]
}

Je génère l'URL signée à partir du serveur comme suit:

var aws = require('aws-sdk');
aws.config = {
    accessKeyId: myAccessKeyId,
    secretAccessKey: mySecretAccessKey
};

var s3 = new aws.s3();
s3.getSignedUrl('putObject', {
    Bucket: 'myBucket',
    Expires: 60*60,
    key: 'myKey'
}, function (err, url) {
    console.log(url);
});

Je reçois l'URL. Mais quand j'essaye de mettre un objet, j'obtiens l'erreur suivante: 

<Error>
    <Code>AccessDenied</Code>
    <Message>Access Denied</Message>
    <RequestId>FXXXXXXXXX</RequestId>
    <HostId>fXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</HostId>
</Error>

Mise à jour 1

Voici la politique de myuser:

{
  "Version": "2012-10-17",
  "Statement": [
    {
        "Sid": "",
        "Effect": "Allow",
        "Principal": {
            "AWS": [
                "arn:aws:iam::2xxxxxxxxxxx:user/myuser",
                "arn:aws:iam::2xxxxxxxxxxx:root"
            ]
        },
        "Action": [
            "s3:*"
        ],
        "Resource": [
            "arn:aws:s3:::myBucket",
            "arn:aws:s3:::myBucket/*"
        ]
    }
  ]
}

Update 2 Je peux télécharger uniquement lorsque l'option suivante est définie. Je ne comprends pas ce qui est l'utilisation de la politique de compartiment si seulement la sélection manuelle de permission fonctionne. 

 Permission for everyone

Mise à jour 3 

Le code suivant fonctionne. Maintenant, le seul problème est l'URL signée

 #!/bin/bash

 file="$1"

 bucket="mybucket"
 resource="/${bucket}/${file}"
 contentType="image/png"
 dateValue=`date -R`
 stringToSign="PUT\n\n${contentType}\n${dateValue}\n${resource}"
 s3Key="AKxxxxxxxxxxxxxxxxx"
 s3Secret="/Wuxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
 signature=`echo -en ${stringToSign} | openssl sha1 -hmac ${s3Secret}     -binary | base64`
 curl -X PUT -T "${file}" \
   -H "Host: ${bucket}.s3.amazonaws.com" \
   -H "Date: ${dateValue}" \
   -H "Content-Type: ${contentType}" \
   -H "Authorization: AWS ${s3Key}:${signature}" \
   https://${bucket}.s3.amazonaws.com/${file}
17
Pravin

J'ai réussi à télécharger un fichier avec succès en utilisant votre code. 

Voici les étapes que j'ai suivies:

  1. Création d'un nouveau compartiment et d'un nouvel utilisateur IAM

  2. Définissez la stratégie de l'utilisateur IAM comme suit:

    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "Stmt1418647210000",
                "Effect": "Allow",
                "Action": [
                    "s3:Put*"
                ],
                "Resource": [
                    "arn:aws:s3:::myBucket/*"
                ]
            }
        ]
    }
    
  3. N'a PAS créé de politique de compartiment

  4. Utilisez votre code pour générer l'URL pré-signée:

    var aws = require('aws-sdk');
    aws.config = {
        accessKeyId: myAccessKeyId,
        secretAccessKey: mySecretAccessKey
    };
    
    var s3 = new aws.s3();
    s3.getSignedUrl('putObject', {
        Bucket: 'myBucket',
        Expires: 60*60,
        Key: 'myKey'
    }, function (err, url) {
        console.log(url);
    });
    
  5. Copiez l'URL à l'écran et utilisez curl pour tester le téléchargement comme ci-dessous:

    curl.exe -k -X PUT -T "someFile" "https://myBucket.s3.amazonaws.com/myKey?AWSAccessKeyId=ACCESS_KEY_ID&Expires=1457632663&Signature=Dhgp40j84yfjBS5v5qSNE4Q6l6U%3D"
    

Dans mon cas, il a fallu généralement 5 à 10 secondes pour que les modifications apportées à la stratégie prennent effet. Si cela échoue la première fois, assurez-vous de continuer à l'envoyer pendant un moment.

J'espère que cela t'aides.

12
Volkan Paksoy

Vous avez correctement configuré les autorisations sur le compartiment, afin de permettre l'accès de l'utilisateur.

Mais vous devez également modifier la stratégie de l'utilisateur pour lui permettre d'accéder au service S3.

Modifiez la stratégie IAM de l'utilisateur dont vous utilisez les informations d'identification pour générer l'URL auto-signée. Quelque chose comme ça couvrira définitivement tout:

{
  "Statement": [
    {
      "Sid": "AllowAllS3Access",
      "Action": "s3:*",
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}
2
Rory
  1. Dans votre console IAM, cliquez sur Utilisateurs
  2. Dans la liste de droite, choisissez l'utilisateur IAM que vous avez utilisé (doit être 'myuser')
  3. Choisissez les autorisations sur les sous-onglets
  4. Cliquez sur Attacher la stratégie et choisissez AmazonS3FullAccess.

La dernière page sera comme ceci .

Vous pouvez également consulter le sous-onglet Informations d'identification de sécurité, votre accessKeyId devrait figurer dans la liste. Le secretAccessKey ne peut tout simplement pas se reproduire.

2
Hank Chiu

Cela peut aussi vous aider:) Ajoutez un ContentType property:

s3.getSignedUrl('putObject', {
    Bucket: 'myBucket',
    Expires: 60*60,
    Key: 'myKey',
    ContentType: 'image/jpeg',
}, function (err, url) {
   console.log(url);
});
1
Hugo Mallet