Estou implementando um upload direto de arquivo da máquina cliente para o Amazon S3 via API REST usando apenas JavaScript, sem nenhum código do lado do servidor. Tudo funciona bem, mas uma coisa está me preocupando ...
Quando envio uma solicitação para a API REST do Amazon S3, preciso assinar a solicitação e colocar uma assinatura no Authentication
cabeçalho. Para criar uma assinatura, devo usar minha chave secreta. Como tudo acontece do lado do cliente, a chave secreta pode ser facilmente revelada na fonte da página (mesmo que eu ofusque / criptografe minhas fontes).
Como posso lidar com isso? E isso é um problema? Talvez eu possa limitar o uso de chave privada específica apenas às chamadas da API REST de uma origem CORS específica e apenas aos métodos PUT e POST ou talvez vincular a chave apenas ao S3 e ao bucket específico? Pode haver outros métodos de autenticação?
A solução "sem servidor" é ideal, mas posso considerar envolver algum processamento no servidor, excluindo o upload de um arquivo para o meu servidor e enviando para o S3.
Respostas:
Eu acho que o que você deseja é Uploads baseados em navegador usando POST.
Basicamente, você precisa de código do lado do servidor, mas tudo o que faz é gerar políticas assinadas. Depois que o código do lado do cliente tiver a política assinada, ele poderá fazer o upload usando o POST diretamente para o S3 sem que os dados passem pelo servidor.
Aqui estão os links oficiais dos documentos:
Diagrama: http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingHTTPPOST.html
Código de exemplo: http://docs.aws.amazon.com/AmazonS3/latest/dev/HTTPPOSTExamples.html
A política assinada entraria no seu html de uma forma como esta:
Observe que a ação FORM está enviando o arquivo diretamente para o S3 - não pelo servidor.
Toda vez que um de seus usuários deseja fazer upload de um arquivo, você cria o
POLICY
eSIGNATURE
no seu servidor. Você retorna a página ao navegador do usuário. O usuário pode fazer o upload de um arquivo diretamente para o S3 sem passar pelo servidor.Quando você assina a política, normalmente faz com que a política expire após alguns minutos. Isso força seus usuários a conversar com seu servidor antes de fazer o upload. Isso permite monitorar e limitar os uploads, se você desejar.
Os únicos dados que entram ou saem do servidor são os URLs assinados. Suas chaves secretas permanecem secretas no servidor.
fonte
${filename}
o nome da chave, portanto, para o exemplo acima, emuser/eric/${filename}
vez de apenasuser/eric
. Seuser/eric
já existir uma pasta, o upload falhará silenciosamente (você até será redirecionado para o success_action_redirect) e o conteúdo carregado não estará lá. Apenas passei horas depurando esse pensamento, que era um problema de permissão.Você pode fazer isso pelo AWS S3 Cognito, tente este link aqui:
http://docs.aws.amazon.com/AWSJavaScriptSDK/guide/browser-examples.html#Amazon_S3
Experimente também este código
Basta alterar Region, IdentityPoolId e Your bucket name
fonte
Você está dizendo que deseja uma solução "sem servidor". Mas isso significa que você não tem capacidade de inserir nenhum código "seu" no loop. (OBSERVAÇÃO: Depois de fornecer seu código a um cliente, ele é o código "deles" agora.) Bloquear o CORS não ajudará: as pessoas podem escrever facilmente uma ferramenta não baseada na Web (ou um proxy baseado na Web) que adiciona o cabeçalho CORS correto para abusar do seu sistema.
O grande problema é que você não pode diferenciar entre os diferentes usuários. Você não pode permitir que um usuário liste / acesse seus arquivos, mas impede que outros o façam. Se você detectar abuso, não há nada que possa fazer a respeito, exceto alterar a chave. (Que o atacante pode presumivelmente apenas recuperar de novo.)
Sua melhor aposta é criar um "usuário IAM" com uma chave para o seu cliente javascript. Apenas conceda acesso de gravação a apenas um depósito. (mas, idealmente, não ative a operação ListBucket, que a tornará mais atraente para os invasores.)
Se você tivesse um servidor (mesmo uma micro instância simples a US $ 20 / mês), poderá assinar as chaves no servidor enquanto monitora / evita abusos em tempo real. Sem um servidor, o melhor que você pode fazer é monitorar periodicamente o abuso após o fato. Aqui está o que eu faria:
1) gire periodicamente as chaves para esse usuário do IAM: Toda noite, gere uma nova chave para esse usuário do IAM e substitua a chave mais antiga. Como existem 2 chaves, cada chave será válida por 2 dias.
2) habilite o log S3 e faça o download dos logs a cada hora. Defina alertas em "muitos envios" e "muitos downloads". Você deseja verificar o tamanho total do arquivo e o número de arquivos enviados. E você desejará monitorar os totais globais e também os totais por endereço IP (com um limite mais baixo).
Essas verificações podem ser feitas "sem servidor" porque você pode executá-las na área de trabalho. (ou seja, o S3 faz todo o trabalho, esses processos servem apenas para alertá-lo sobre o abuso do seu bucket do S3, para que você não receba uma fatura gigante da AWS no final do mês.)
fonte
Adicionando mais informações à resposta aceita, você pode consultar o meu blog para ver uma versão em execução do código, usando o AWS Signature versão 4.
Resumirá aqui:
Assim que o usuário selecionar um arquivo a ser carregado, faça o seguinte: 1. Faça uma chamada para o servidor da web para iniciar um serviço para gerar parâmetros necessários
Nesse serviço, ligue para o serviço AWS IAM para obter credenciais temporárias
Depois de obter o cred, crie uma política de bucket (sequência codificada de base 64). Em seguida, assine a política de bucket com a chave de acesso secreto temporário para gerar a assinatura final
envie os parâmetros necessários de volta para a interface do usuário
Depois que isso for recebido, crie um objeto de formulário html, defina os parâmetros necessários e POST.
Para informações detalhadas, consulte https://wordpress1763.wordpress.com/2016/10/03/browser-based-upload-aws-signature-version-4/
fonte
É aqui que você entendeu mal. O motivo pelo qual as assinaturas digitais são usadas é para que você possa verificar se algo está correto sem revelar sua chave secreta. Nesse caso, a assinatura digital é usada para impedir que o usuário modifique a política que você definiu para a postagem do formulário.
Assinaturas digitais como a aqui são usadas para segurança em toda a web. Se alguém (NSA?) Realmente fosse capaz de quebrá-los, eles teriam alvos muito maiores do que o seu bucket S3 :)
fonte
Forneci um código simples para fazer upload de arquivos do navegador Javascript para o AWS S3 e listar todos os arquivos no bucket do S3.
Passos:
Para saber como criar o Create IdentityPoolId http://docs.aws.amazon.com/cognito/latest/developerguide/identity-pools.html
Vá para a página do console do S3 e abra a configuração de cors a partir das propriedades do bucket e escreva o código XML a seguir.
Crie um arquivo HTML contendo o seguinte código, altere as credenciais, abra o arquivo no navegador e aproveite.
fonte
Se você não possui nenhum código do lado do servidor, sua segurança depende da segurança do acesso ao seu código JavaScript no lado do cliente (ou seja, todos os que possuem o código podem enviar algo).
Então, eu recomendaria, simplesmente criar um bucket S3 especial que possa ser gravado em público (mas não legível), para que você não precise de nenhum componente assinado no lado do cliente.
O nome do depósito (por exemplo, um GUID) será sua única defesa contra envios mal-intencionados (mas um invasor em potencial não poderá usar seu depósito para transferir dados, porque ele é gravado apenas para ele)
fonte
Aqui está como você gera um documento de política usando nó e sem servidor
O objeto de configuração usado é armazenado no SSM Parameter Store e se parece com isso
fonte
Se você estiver disposto a usar um serviço de terceiros, o auth0.com suporta essa integração. O serviço auth0 troca uma autenticação de serviço SSO de terceiros por um token de sessão temporário da AWS com permissões limitadas.
Consulte: https://github.com/auth0-samples/auth0-s3-sample/
e a documentação auth0.
fonte