Cómo hacer públicos 10,000 archivos en S3

92

Tengo una carpeta en un cubo con 10,000 archivos. Parece que no hay forma de subirlos y hacerlos públicos de inmediato. Así que los subí todos, son privados y necesito hacerlos públicos.

Probé la consola de AWS, solo da un error (funciona bien con carpetas con menos archivos).

Intenté usar la organización S3 en Firefox, lo mismo.

¿Existe algún software o script que pueda ejecutar para hacerlos públicos?

PeterV
fuente
4
Todas las herramientas que probé fallaron, así que terminé escribiendo un script PHP que tomó unas horas y simplemente recorrí cada objeto en el cubo y lo hice público.
PeterV

Respuestas:

119

Puede generar una política de depósito (consulte el ejemplo a continuación) que da acceso a todos los archivos del depósito. La política de depósito se puede agregar a un depósito a través de la consola de AWS.

{
    "Id": "...",
    "Statement": [ {
        "Sid": "...",
        "Action": [
            "s3:GetObject"
        ],
        "Effect": "Allow",
        "Resource": "arn:aws:s3:::bucket/*",
        "Principal": {
            "AWS": [ "*" ]
        }
    } ]
}

Consulte también la siguiente herramienta generadora de políticas proporcionada por Amazon.

http://awspolicygen.s3.amazonaws.com/policygen.html

Rajiv
fuente
5
Esto no funcionó para mí. Algunos objetos siguen mostrando la respuesta de "acceso denegado" incluso con la política de depósito en su lugar. Se copia y pega de lo anterior y solo se cambia el nombre del depósito. Supongo que es hora de escribir un guión para recorrer los 1.3 millones de objetos ... un poco irritante
Blake Miller
necesita cambiar "cubo" por el nombre de su cubo
karnage
11
Me molesta tener que hacerlo de esta manera. Eso es un JSON feo.
superluminario
6
Sólo una nota: Puede parecer obvio, pero también se puede optar por limitar el acceso a determinadas carpetas : bucket/avatars/*. (No olvides el *al final. Lo hice y corrí en círculos por un tiempo.)
bschaeffer
2
@Benjamin Lo que es una configuración "básica" para usted no es apropiada para otros, porque los requisitos de seguridad de cada persona son diferentes. AWS proporciona una forma uniforme de personalizar estas políticas. Por lo tanto, uno debe tomarse el tiempo para aprender las políticas de seguridad correctamente y no rehuir algunas líneas simples de JSON.
afilina
69

Si está cargando por primera vez, puede configurar los archivos para que sean públicos al cargarlos en la línea de comando:

aws s3 sync . s3://my-bucket/path --acl public-read

Como se documenta en Uso de comandos s3 de alto nivel con la interfaz de línea de comandos de AWS

Desafortunadamente, solo aplica la ACL cuando se cargan los archivos. No aplica (en mis pruebas) la ACL a archivos ya cargados.

Si desea actualizar los objetos existentes, solía poder sincronizar el depósito consigo mismo, pero parece que ha dejado de funcionar.

[Ya no funciona] Esto se puede hacer desde la línea de comando:

aws s3 sync s3://my-bucket/path s3://my-bucket/path --acl public-read

(Entonces esto ya no responde a la pregunta, sino que deja la respuesta como referencia, ya que solía funcionar).

David Roussel
fuente
¿Este comando se efectúa en archivos que ya se han cargado pero que aún no se han leído públicamente?
Alston
10
Cuando lo probé, parece que solo agrega la ACL a los archivos recién sincronizados.
David Roussel
Gracias por la repetición, también lo probé. ¿Hay alguna forma de cambiar por lotes el permiso de los archivos cargados?
Alston
Oh, no es de extrañar. Estaba confundido por esto. Realmente aprecio tu aclaración.
Sridhar Sarnobat
Respuesta actualizada para incluir cómo cambiar archivos existentes.
David Roussel
34

Tuve que cambiar varios cientos de miles de objetos. Encendí una instancia EC2 para ejecutar esto, lo que hace que todo sea más rápido. aws-sdkPrimero querrás instalar la gema.

Aquí está el código:

require 'rubygems'
require 'aws-sdk'


# Change this stuff.
AWS.config({
    :access_key_id => 'YOURS_HERE',
    :secret_access_key => 'YOURS_HERE',
})
bucket_name = 'YOUR_BUCKET_NAME'


s3 = AWS::S3.new()
bucket = s3.buckets[bucket_name]
bucket.objects.each do |object|
    puts object.key
    object.acl = :public_read
end
Daniel Von Fange
fuente
1
La forma más sencilla es subirlos con la bandera public_read configurada en primer lugar, pero en su defecto, esta es una buena opción.
superluminario
Este código recortado está desactualizado, consulte mi respuesta
ksarunas
26

Tuve el mismo problema, la solución de @DanielVonFange está desactualizada, ya que está disponible una nueva versión de SDK.

Agregando un fragmento de código que me funciona en este momento con AWS Ruby SDK:

require 'aws-sdk'

Aws.config.update({
  region: 'REGION_CODE_HERE',
  credentials: Aws::Credentials.new(
    'ACCESS_KEY_ID_HERE',
    'SECRET_ACCESS_KEY_HERE'
  )
})
bucket_name = 'BUCKET_NAME_HERE'

s3 = Aws::S3::Resource.new
s3.bucket(bucket_name).objects.each do |object|
  puts object.key
  object.acl.put({ acl: 'public-read' })
end
ksarunas
fuente
1
Respuesta fantástica: solo el guión que necesitaba en un aprieto
Phantomwhale
@ksarunas En mi caso, necesito cambiar los permisos públicos a privados, así que reemplace la lectura pública por privada y el acceso cambió, pero aún así, ¿puedo acceder a la URL?
Rahul
19

Solo quería agregar que con la nueva consola S3, puede seleccionar su (s) carpeta (s) y seleccionar Make publichacer públicos todos los archivos dentro de las carpetas. Funciona como una tarea en segundo plano, por lo que debería manejar cualquier cantidad de archivos.

Hacer público

Selcuk
fuente
5
Desafortunadamente, lleva mucho tiempo y no puede cerrar el navegador mientras el comando está en ejecución. Su navegador envía 2 solicitudes por cada archivo, en mi caso las dos solicitudes tardaron 500 ms. Si tiene muchos archivos, tomará mucho tiempo = (
Herlon Aguiar
2
Y hay otro problema: esto se hará completamente público. Si solo desea acceso de lectura pública, eso es un problema.
Marcelo Agimóvel
SEA MUY CONSCIENTE - Hice este Make Public y la "barra de progreso" que aparece es tan sutil que pensé que estaba hecho. Verifiqué y probablemente pasé una hora trabajando en esto antes de darme cuenta de que hiciste clic en Hacer público y una pequeña y sutil "barra de progreso aparece" ... grrr ... ya que cerré la ventana del navegador unas 10 veces, supongo que lo mató cada vez . Lo estoy ejecutando ahora - es bastante rápido - tal vez 20 minutos para imágenes de 120k
Scott
11

Usando el cli:

aws s3 ls s3://bucket-name --recursive > all_files.txt && grep .jpg all_files.txt > files.txt && cat files.txt | awk '{cmd="aws s3api put-object-acl --acl public-read --bucket bucket-name --key "$4;system(cmd)}'

Alexander Vitanov
fuente
3
¿No podría simplemente usar una tubería para grep en lugar de escribir en el disco con todos los files.txt? Esto puede seraws s3 ls s3://bucket-name --recursive | grep .jpg | awk '{cmd="aws s3api put-object-acl --acl public-read --bucket bucket-name --key "$4;system(cmd)}'
sakurashinken
3

Tenía esta necesidad yo mismo, pero la cantidad de archivos hace que sea MUY lento para hacer en serie. Así que escribí un guión que lo hace en iron.io 's cerrajero de servicio. Sus 500 horas de computación gratuitas por mes son suficientes para manejar incluso grandes depósitos (y si lo excede, el precio es razonable). Como se hace en paralelo se completa en menos de un minuto para los 32.000 objetos que tenía. También creo que sus servidores funcionan con EC2, por lo que la comunicación entre el trabajo y S3 es rápida.

Cualquiera puede utilizar mi script para sus propias necesidades.

Eric Anderson
fuente
2

Eche un vistazo a BucketExplorer , gestiona muy bien las operaciones masivas y es un cliente S3 sólido.

Willbt
fuente
3
Ahora también es posible cambiar los permisos de forma masiva en Cyberduck (gratis) a través de la paleta Información.
Taylor Edmiston
BucketExplorer solo es útil si tiene permiso para enumerar todos los depósitos. Es mucho mejor usar la CLI o un SDK para esta operación y dejar a sus usuarios con permisos restringidos.
perilandmishap
0

Pensarías que harían público la lectura del comportamiento predeterminado, ¿no? :) Compartí su frustración mientras creaba una API personalizada para interactuar con S3 desde una solución C #. Aquí está el fragmento que logra cargar un objeto S3 y configurarlo en acceso de lectura pública de forma predeterminada:

public void Put(string bucketName, string id, byte[] bytes, string contentType, S3ACLType acl) {
     string uri = String.Format("https://{0}/{1}", BASE_SERVICE_URL, bucketName.ToLower());
     DreamMessage msg = DreamMessage.Ok(MimeType.BINARY, bytes);
     msg.Headers[DreamHeaders.CONTENT_TYPE] = contentType;
     msg.Headers[DreamHeaders.EXPECT] = "100-continue";
     msg.Headers[AWS_ACL_HEADER] = ToACLString(acl);
     try {
        Plug s3Client = Plug.New(uri).WithPreHandler(S3AuthenticationHeader);
        s3Client.At(id).Put(msg);
     } catch (Exception ex) {
        throw new ApplicationException(String.Format("S3 upload error: {0}", ex.Message));
     }
}

La función ToACLString (acl) devuelve lectura pública , BASE_SERVICE_URL es s3.amazonaws.com y la constante AWS_ACL_HEADER es x-amz-acl . El plug y DreamMessage probablemente le parecerán extraños ya que estamos usando el marco de Dream para optimizar nuestras comunicaciones http. Básicamente, estamos haciendo un http PUT con los encabezados especificados y una firma de encabezado especial según las especificaciones de aws (consulte esta página en los documentos de aws para ver ejemplos de cómo construir el encabezado de autorización).

Para cambiar las ACL de 1000 objetos existentes, puede escribir un script, pero probablemente sea más fácil usar una herramienta GUI para solucionar el problema inmediato. Lo mejor que he usado hasta ahora es de una empresa llamada Cloudberry para S3; parece que tienen una prueba gratuita de 15 días para al menos uno de sus productos. Acabo de verificar que le permitirá seleccionar varios objetos a la vez y establecer su ACL en público a través del menú contextual. ¡Disfruta la nube!

Tahbaza
fuente