¿Cómo configurar los permisos de Abrir / Descargar en un archivo creado en S3 con Amazon Lambda?

Tengo una función de Amazon Lambda que escribe archivos con éxito en un depósito de Amazon S3. Sin embargo, de forma predeterminada, estos archivos no son de acceso público. ¿Cómo los hago automáticamente accesibles cuando están escritos?

¿Hay alguna forma de cambiar el compartimiento para que todos los elementos sean legibles públicamente (abrir / descargar)?

Alternativamente, he deducido que esto se puede hacer con la política de rol de IAM. Esto es lo que tengo:

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": "arn:aws:logs:*:*:*" }, { "Effect": "Allow", "Action": [ "s3:GetObject", "s3:PutObject" ], "Resource": [ "arn:aws:s3:::*" ] } ] } 

Creo que es el “Recurso” lo que necesita ser cambiado, pero no estoy seguro de cómo.

Para completar (en caso de que alguien más necesite hacer algo similar y se esté metiendo en la maraña que es la documentación de Lambda), aquí está mi llamada de ajax en el lado del cliente (estoy escribiendo una imagen en S3 y necesito que me devuelva el nombre de archivo):

 $.ajax({ url: 'https://mylambdafunctionurl/', type: 'POST', crossDomain: true, contentType: 'application/json', data: JSON.stringify(data), dataType: 'json', success: function(data) { var path = "https://myregion.amazonaws.com/mybucket/"; var filename = JSON.parse(data).filename; document.getElementById('finalimage').innerHTML = "Your image"; }, error: function(xhr, ajaxOptions, thrownError) { if (xhr.status == 200) { console.log(ajaxOptions); } else { console.log("Error: "); console.log(xhr.status); console.log(thrownError); } } }); 

Y aquí está la función POST de Lambda (nodejs):

 var AWS = require('aws-sdk'); var s3 = new AWS.S3(); exports.handler = function(event,context) { var s3 = new AWS.S3(); var nowtime = new Date(); var bodycontent = event.image; mykey = nowtime.getTime() + '.png'; var param = {Bucket: 'mybucket', Key: mykey, Body: bodycontent}; var successdata = {filename:mykey}; s3.upload(param, function(e,data) { if (e) { console.log(e,e.stack); } else { console.log(event); } context.done(null,JSON.stringify(successdata)); }); } 

Advertencia: usar la hora actual para el nombre de archivo no está listo para producción. Era solo una forma rápida de producir un nombre de archivo razonablemente único.

según este ejemplo de la página: http://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_examples.html puede establecer una política de rol de IAM como esta

 ... { "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject", "s3:DeleteObject" ], "Resource": "arn:aws:s3:::EXAMPLE-BUCKET-NAME/*" } ... 

Así que puedes combinarlo con una carpeta como arn:aws:s3:::EXAMPLE-BUCKET-NAME/public/* Creo

O puede crear un grupo completo con acceso público a todos los archivos solo para cargar.

O tal vez podría usar getSignedUrl desde el sdk hasta el archivo que acaba de cargar y devolver esa url al cliente, que hará que el archivo sea accesible a través de esa url por un tiempo determinado (no recuerde ahora por cuánto tiempo son válidos), como esta:

 s3.putObject({ Bucket: bucket, Key: key, Body: fs.createReadStream(path), ContentType: contentType, }, function(err, data) { if (err) return callback(err, null); s3.getSignedUrl('getObject', { Bucket: 'mybucket', Key: 'mypublicfiles/myfile.txt' }, function(err, url) { if (err) return callback(err, null) else return callback(null, url) }); }); 

Además de la respuesta de @mithril_knight, también necesitaba una política de depósito (establecida en la consola S3):

 { "Id": "Policyxxxxxxxxxx", "Version": "2012-10-17", "Statement": [ { "Sid": "Stmtxxxxxxxxxx", "Action": [ "s3:GetObject" ], "Effect": "Allow", "Resource": "arn:aws:s3:::mybucket/*", "Principal": { "AWS": [ "*" ] } } ] } 

El mojo que necesitaba era el “Principal” de “*”, que significa “Todos”.