Je vais avoir un sacré moment pour que S3 accepte les envois via la requête CORS POST générée par PhoneGap (Cordova) FileTransfer.upload(). Toute suggestion sur ce que je pourrais manquer serait appréciée. Actuellement, j'obtiens une réponse 403 AccessDenied en utilisant le code ci-dessous. J'ai été à plusieurs reprises comparé à la documentation de S3, et ne peux pas comprendre le problème.Générer une signature CORS Amazon S3 avec Python
Voici le code Python qui génère la signature:
# Create policy document for S3.
policy_obj = {"expiration": "2014-01-01T00:00:00Z",
"conditions": [
{"bucket": "<my.bucket.name>"},
["starts-with", "$key", "story_"],
{"acl": "public-read"},
["eq", "$Content-Type", "audio/mp4"],
["content-length-range", str(0), str(2097152)]
]
}
policy = base64.b64encode(json.dumps(policy_obj))
# Create signature for S3
signature = base64.b64encode(
hmac.new(
key=app.config['AWS_SECRET_KEY'],
msg=policy,
digestmod=hashlib.sha1
).digest()
)
La signature générée par ce procédé correspond à la signature produite par S3 Signature Tester (convertissant la politique de base64 dans Hex puis de celle à travers l'appareil d'essai de signature avec le clef secrète).
La signature politique & résultant sont transmis au client, et la demande de S3 est construit avec cet appel PhoneGap FileTransfer:
// Upload file to Amazon S3
// r is the response object generated by Python
var options = new FileUploadOptions();
options.chunkedMode = false;
options.mimeType="audio/mp4";
options.fileKey='file';
options.fileName='story_' + uniqueKey + '.m4a';
options.params={
"key": "${filename}",
"acl": "public-read",
"AWSAccessKeyId": r.aws_access_key,
"Policy": r.policy,
"Signature": r.signature,
};
var ft = new FileTransfer();
ft.upload(path, "http://<my.bucket.name>.s3.amazonaws.com/", uploadSuccess, uploadFail, options);
Ceci est la configuration CORS (oui, je prévois de le verrouiller une fois Je reçois les ajouts de travail):
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
Voici la politique du seau:
{
"Version": "2008-10-17",
"Id": "Policy1356975063803",
"Statement": [
{
"Sid": "Stmt1357234455973",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::<my.bucket.name>/*"
},
{
"Sid": "Stmt1356975061658",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::293855469575:root"
},
"Action": "s3:*",
"Resource": "arn:aws:s3:::<my.bucket.name>"
}
]
}
MISE À JOUR:
C'est ce que la politique elle-même ressemble après Python a converti l'objet en JSON:
{
"conditions": [
{
"bucket": "<my.bucket.name>"
},
[
"starts-with",
"$key",
"story_"
],
{
"acl": "public-read"
},
[
"eq",
"$Content-Type",
"audio/mp4"
],
[
"content-length-range",
"0",
"6291456"
]
],
"expiration": "2014-01-01T00:00:00Z"
}
Voici un script S3 pour Django, ne peut pas voir de différence significative entre ce qu'ils font et ce que je fais (j'ai essayé le paramètre 'indent = 2' sans chance): http://djangosnippets.org/snippets/2829/ – bjudson