Como tornar 10.000 arquivos públicos no S3

92

Eu tenho uma pasta em um balde com 10.000 arquivos. Parece não haver maneira de enviá-los e torná-los públicos imediatamente. Então, carreguei todos eles, são privados e preciso torná-los públicos.

Eu tentei o console do aws, ele apenas dá um erro (funciona bem com pastas com menos arquivos).

Já tentei usar a organização S3 no Firefox, mesma coisa.

Existe algum software ou script que posso executar para tornar tudo isso público?

PeterV
fonte
4
Todas as ferramentas que experimentei travaram, então acabei escrevendo um script PHP que demorou algumas horas e apenas fez um loop em cada objeto no intervalo e o tornou público.
PeterV 01 de

Respostas:

119

Você pode gerar uma política de bucket (veja o exemplo abaixo) que dá acesso a todos os arquivos no bucket. A política de bucket pode ser adicionada a um bucket por meio do console AWS.

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

Veja também a seguinte ferramenta de geração de políticas fornecida pela Amazon.

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

Rajiv
fonte
5
Isto não funcionou para mim. Alguns objetos ainda estão retornando a resposta 'acesso negado', mesmo com a política de intervalo em vigor. É copiado e colado do acima, apenas com o nome do intervalo alterado. Acho que é hora de escrever um script para percorrer todos os 1,3 milhões de objetos ... um pouco irritante
Blake Miller
você precisa mudar "bucket" para o nome do seu bucket
karnage
11
Eu me ressinto de ter que fazer assim. Isso é um JSON feio.
superluminário de
6
Apenas uma nota: Pode parecer óbvio, mas você também pode optar por limitar o acesso a determinados pastas : bucket/avatars/*. (Não se esqueça do *no final. Eu fiz e corri em círculos por um tempo.)
bschaeffer
2
@Benjamin O que é configuração "básica" para você é inapropriado para os outros, porque os requisitos de segurança de cada pessoa são diferentes. A AWS fornece uma maneira uniforme de personalizar essas políticas. Portanto, é preciso ter tempo para aprender as políticas de segurança de forma adequada e não se esquivar de algumas linhas simples de JSON.
afilina
68

Se você estiver enviando pela primeira vez, poderá definir os arquivos como públicos no upload na linha de comando:

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

Conforme documentado em Uso de comandos s3 de alto nível com a AWS Command Line Interface

Infelizmente, ele só aplica a ACL quando os arquivos são carregados. Ele não aplica (em meu teste) a ACL a arquivos já carregados.

Se você deseja atualizar os objetos existentes, costumava ser capaz de sincronizar o bloco com ele mesmo, mas parece que isso parou de funcionar.

[Não funciona mais] Isso pode ser feito na linha de comando:

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

(Portanto, isso não responde mais à pergunta, mas deixando a resposta para referência, como costumava funcionar.)

David Roussel
fonte
Este comando é efetuado em arquivos que já foram enviados, mas ainda não foram lidos publicamente?
Alston,
10
Quando testei, parece que só adiciona a ACL aos arquivos recém-sincronizados.
David Roussel
Obrigado por repetir, eu testei também. Existe alguma maneira de alterar em lote a permissão dos arquivos carregados?
Alston
Oh, não admira. Eu estava confuso com isso. Agradeço muito seu esclarecimento.
Sridhar Sarnobat
Resposta atualizada para incluir como alterar arquivos existentes.
David Roussel
34

Tive que mudar várias centenas de milhares de objetos. Acionei uma instância EC2 para executar isso, o que torna tudo mais rápido. Você vai querer instalar a aws-sdkgema primeiro.

Aqui está o 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
fonte
1
A maneira simples é carregá-los com o sinalizador public_read definido em primeiro lugar, mas, se isso falhar, essa é uma boa opção.
superluminário de
Este código cortado está desatualizado, consulte minha resposta
ksarunas
26

Tive o mesmo problema, solução de @DanielVonFange está desatualizada, pois nova versão do SDK saiu.

Adicionando snippet de código que funciona para mim agora com o SDK do AWS Ruby:

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
fonte
1
Resposta fantástica - apenas o roteiro que eu precisava em uma situação
difícil
@ksarunas No meu caso, preciso alterar as permissões públicas para privadas, então substitua public-read por private e o acesso foi alterado, mas ainda assim, consigo acessar a URL?
Rahul
19

Só queria adicionar isso com o novo console S3, você pode selecionar sua (s) pasta (s) e Make publicfazer com que todos os arquivos dentro das pastas sejam públicos. Ele funciona como uma tarefa em segundo plano, portanto, deve lidar com qualquer número de arquivos.

Tornar público

Selcuk
fonte
5
Infelizmente, leva muito tempo e você não pode fechar o navegador enquanto o comando está em execução. Seu navegador está enviando 2 solicitações para cada arquivo, no meu caso as duas solicitações demoraram 500ms. Se você tiver muitos arquivos vai demorar muito tempo = (
Herlon Aguiar
2
E, há outro problema: isso tornará totalmente público. Se você deseja apenas acesso de leitura pública, isso é um problema.
Marcelo Agimóvel 09/11/18
ESTEJA MUITO CIENTE - Fiz este Tornar Público e a "barra de progresso" que aparece é tão sutil que pensei que estava feito. Eu verifiquei e provavelmente passei uma hora trabalhando nisso antes de perceber que você clica em Tornar público e uma pequena e sutil "barra de progresso aparece" ... grrr ... já que fechei a janela do navegador cerca de 10 vezes, presumo que a matei todas as vezes . Estou executando agora - é muito rápido - talvez 20 minutos para imagens de 120 mil
Scott,
11

Usando o 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
fonte
3
você não poderia simplesmente usar um pipe para grep em vez de gravar no disco com todos os arquivos.txt? Isso pode 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
2

Dê uma olhada no BucketExplorer, ele gerencia muito bem as operações em massa e é um cliente S3 sólido.

vontade
fonte
3
Agora também é possível alterar permissões em massa no Cyberduck (gratuito) por meio da paleta Informações.
Taylor Edmiston
BucketExplorer só é útil se você tiver permissão para listar todos os intervalos. É muito melhor usar a CLI ou um SDK para esta operação e deixar seus usuários com permissões restritas.
perilandmishap
2

Tive essa necessidade, mas o número de arquivos torna muito lento para fazer em série. Então eu escrevi um script que faz isso em iron.io 's IRONWORKER serviço. Suas 500 horas de computação gratuitas por mês são suficientes para lidar até mesmo com grandes intervalos (e se você exceder esse valor, o preço é razoável). Como é feito em paralelo, ele é concluído em menos de um minuto para os 32.000 objetos que eu tinha. Também acredito que seus servidores rodam em EC2 então a comunicação entre o trabalho e S3 é rápida.

Qualquer pessoa pode usar meu script para atender às suas próprias necessidades.

Eric Anderson
fonte
0

Você pensaria que eles tornariam público a leitura do comportamento padrão, não é? :) Compartilhei sua frustração ao construir uma API personalizada para fazer a interface com o S3 a partir de uma solução C #. Aqui está o snippet que realiza o upload de um objeto S3 e a configuração para acesso de leitura pública por padrão:

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));
     }
}

A função ToACLString (acl) retorna leitura pública , BASE_SERVICE_URL é s3.amazonaws.com e a constante AWS_ACL_HEADER é x-amz-acl . O plug e o DreamMessage provavelmente parecerão estranhos para você, já que estamos usando a estrutura do Dream para agilizar nossas comunicações http. Basicamente, estamos fazendo um http PUT com os cabeçalhos especificados e uma assinatura de cabeçalho especial de acordo com as especificações do aws (consulte esta página na documentação do aws para exemplos de como construir o cabeçalho de autorização).

Para alterar ACLs de 1000 objetos existentes, você pode escrever um script, mas provavelmente é mais fácil usar uma ferramenta de GUI para corrigir o problema imediato. O melhor que usei até agora é de uma empresa chamada cloudberry for S3; parece que eles têm uma avaliação gratuita de 15 dias para pelo menos um de seus produtos. Acabei de verificar que isso permitirá que você selecione vários objetos de uma vez e defina sua ACL como pública por meio do menu de contexto. Aproveite a nuvem!

Tahbaza
fonte