Assinar e autenticar as solicitações REST
Tópicos
- Uso de credenciais de segurança temporárias
- Cabeçalho de autenticação
- Canonização de solicitação para assinatura
- Criar o elemento CanonicalizedResource
- Criar o elemento CanonicalizedAmzHeaders
- Elementos StringToSign de cabeçalho HTTP posicionais versus nomeados
- Requisito de time stamp
- Exemplos de autenticação
- Problemas de assinatura de solicitação REST
- Alternativa de autenticação de solicitação por string de consulta
nota
Este tópico explica solicitações de autenticação usando o Signature versão 2. O Amazon S3 agora é compatível com o mais recente Signature versão 4. Essa versão mais recente de assinatura é compatível com todas as regiões e qualquer nova região depois de 30 de janeiro de 2014 oferecerá suporte somente ao Signature versão 4. Para obter mais informações, acesse Autenticação de solicitações (AWS Signature versão 4) na Referência de APIs do Amazon Simple Storage Service.
Autenticação é o processo de provar sua identidade ao sistema. A identidade é um fator importante nas decisões de controle de acesso do Amazon S3. As solicitações são permitidas ou negadas em parte com base na identidade do solicitante. Por exemplo, o direito de criar buckets está reservado a desenvolvedores registrados e (por padrão) o direito de criar objetos em um bucket está reservado para o proprietário do bucket em questão. Como um desenvolvedor, você fará solicitações que invocam esses privilégios e, portanto, precisará provar sua identidade ao sistema, autenticando suas solicitações. Esta seção explica como fazer isso.
nota
O conteúdo nesta seção não se aplica a HTTP POST. Para obter mais informações, consulte Uploads baseados no navegador usando POST (AWS Signature Version 2).
A API REST do Amazon S3 usa um esquema HTTP personalizado com base em um HMAC de chave (código de autenticação de mensagem hash) para autenticação. Para autenticar uma solicitação, você primeiro concatena elementos selecionados da solicitação para formar uma string. Depois, você pode usar sua chave de acesso secreta da AWS para calcular o HMAC dessa string. Informalmente, chamamos desse processo de “assinar a solicitação” e chamamos o resultado do algoritmo do HMAC de assinatura, pois ele simula as propriedades de segurança de uma assinatura real. Finalmente, você adiciona esta assinatura como um parâmetro da solicitação usando a sintaxe descrita nesta seção.
Quando o sistema recebe uma solicitação autenticada, ele busca a chave de acesso secreta da AWS que você afirma ter e a usa da mesma forma para computar uma assinatura para a mensagem que recebeu. Então, ele compara a assinatura que calculou com a assinatura apresentada pelo solicitante. Se há correspondência entre as duas assinaturas, o sistema concluirá que o solicitante deve ter acesso à chave de acesso secreta da AWS e, portanto, age com a autoridade do principal para quem a chave foi emitida. Se as duas assinaturas não correspondem, a solicitação é abandonada e o sistema responde com uma mensagem de erro.
exemplo Solicitação REST autenticada do Amazon S3
GET /photos/puppy.jpg HTTP/1.1 Host: awsexamplebucket1.us-west-1.s3.amazonaws.com Date: Tue, 27 Mar 2007 19:36:42 +0000
Authorization: AWS AKIAIOSFODNN7EXAMPLE: qgk2+6Sv9/oM7G3qLEjTH1a1l1g=
Uso de credenciais de segurança temporárias
Se você assinar sua solicitação usando credenciais de segurança temporárias (consulte Fazer solicitações), você deverá incluir o token de segurança correspondente em sua solicitação, adicionando o cabeçalho x-amz-security-token
.
Quando você obtém credenciais de segurança temporárias usando a API do AWS Security Token Service, a resposta inclui credenciais de segurança temporárias e um token de sessão. Forneça o valor do token de sessão no cabeçalho x-amz-security-token
ao enviar solicitações ao Amazon S3. Para obter informações sobre a API do AWS Security Token Service fornecida pelo IAM, acesse Ação no Guia de referência da API do AWS Security Token Service.
Cabeçalho de autenticação
A API REST do Amazon S3 usa o cabeçalho padrão HTTP Authorization
para passar informações de autenticação. (O nome do cabeçalho padrão é infeliz porque ele carrega informações de autenticação, não de autorização.) No esquema de autenticação do Amazon S3, o cabeçalho Autorização tem a seguinte forma:
Authorization: AWS
AWSAccessKeyId
:Signature
Um ID da chave de acesso da AWS e uma chave de acesso secreta da AWS são emitidos para os desenvolvedores quando eles se registram. Para autenticação de solicitação, o elemento AWSAccessKeyId
identifica o ID de chave de acesso que foi usado para computar a assinatura e, indiretamente, o desenvolvedor que fez a solicitação.
O elemento Signature
é o RFC 2104 HMAC-SHA1 dos elementos selecionados da solicitação e, portanto, a parte Signature
do cabeçalho Autorização variará de uma solicitação para outra. Se a assinatura da solicitação calculada pelo sistema corresponder ao elemento Signature
incluído na solicitação, o solicitante terá demonstrado a posse da chave de acesso secreta da AWS. A solicitação será então processada na identidade do desenvolvedor para quem a chave foi emitida e com a autoridade dele.
A seguir está uma pseudogramática que ilustra a criação do cabeçalho da solicitação Authorization
. (No exemplo, \n
significa o ponto do código Unicode U+000A
, geralmente chamado de nova linha).
Authorization = "AWS" + " " + AWSAccessKeyId + ":" + Signature; Signature = Base64( HMAC-SHA1( UTF-8-Encoding-Of(YourSecretAccessKey), UTF-8-Encoding-Of( StringToSign ) ) ); StringToSign = HTTP-Verb + "\n" + Content-MD5 + "\n" + Content-Type + "\n" + Date + "\n" + CanonicalizedAmzHeaders + CanonicalizedResource; CanonicalizedResource = [ "/" + Bucket ] + <HTTP-Request-URI, from the protocol name up to the query string> + [ subresource, if present. For example "?acl", "?location", or "?logging"]; CanonicalizedAmzHeaders = <described below>
O HMAC-SHA1 é um algoritmo definido pelo hash de chave RFC 2104 para autenticação de mensagemYourSecretAccessKey
) como a chave e a codificação UTF-8 do elemento StringToSign
como a mensagem. A saída de HMAC-SHA1 também é uma string de byte, chamada de resumo. O parâmetro de solicitação Signature
é criado pela codificação Base64 desse resumo.
Canonização de solicitação para assinatura
Lembre-se de que quando o sistema recebe uma solicitação autenticada, ele compara a assinatura de solicitação computada com a assinatura fornecida na solicitação em StringToSign
. Por esse motivo, é necessário computar a assinatura usando o mesmo método usado pelo Amazon S3. Nós chamamos o processo de colocar uma solicitação em um formulário estabelecido para assinatura de canonização.
Criar o elemento CanonicalizedResource
CanonicalizedResource
representa o recurso do Amazon S3 visado pela solicitação. Crie-o para uma solicitação REST como se segue:
1 |
Inicie com uma string vazia ( |
2 |
Se a solicitação especificar um bucket usando o cabeçalho de host HTTP (estilo hosted virtual), adicione o nome do bucket precedido por uma Para uma solicitação no estilo de hospedagem virtual "https://awsexamplebucket1.s3.us-west-1.amazonaws.com/photos/puppy.jpg", o Para uma solicitação em estilo de caminho, "https://s3.us-west-1.amazonaws.com/awsexamplebucket1/photos/puppy.jpg", o |
3 |
Adicione a parte do caminho de um URI de solicitação HTTP descodificado, até a query string, mas sem incluí-la. Para uma solicitação no estilo de hospedagem virtual "https://awsexamplebucket1.s3.us-west-1.amazonaws.com/photos/puppy.jpg", o Para uma solicitação no estilo de hospedagem virtual "https://s3.us-west-1.amazonaws.com/awsexamplebucket1/photos/puppy.jpg", o Para uma solicitação que não seja endereçada a um bucket, como GET Service, adicione “/”. |
4 |
Se a solicitação endereça um sub-recurso, como Os sub-recursos que devem ser incluídos ao criar o elemento CanonicalizedResource são acl, lifecycle, location, logging, notification, partNumber, policy, requestPayment, uploadId, uploads, versionId, versioning, versions e website. Se a solicitação especificar os parâmetros de query string que cancelam os valores de cabeçalho da resposta (consulte Objeto GET), adicione os parâmetros de query string e seus valores. Ao assinar, você não codifica esses valores; contudo, ao fazer a solicitação, você deve codificar esses valores de parâmetros. Os parâmetros de query string em uma solicitação GET incluem O parâmetro de query string |
Os elementos do CanonicalizedResource que vêm da URI da solicitação HTTP devem ser assinados literalmente como aparecem na solicitação HTTP, incluindo metacaracteres de codificação de URL.
O CanonicalizedResource
pode ser diferente da URI da solicitação HTTP. Em particular, se sua solicitação usa o cabeçalho HTTP Host
para especificar um bucket, o bucket não aparece na URI da solicitação HTTP. Contudo, o CanonicalizedResource
continua a incluir o bucket. Os parâmetros de query string podem também aparecer na URI da solicitação, mas não estão incluídos em CanonicalizedResource
. Para obter mais informações, consulte Hospedagem virtual de buckets.
Criar o elemento CanonicalizedAmzHeaders
Para criar a parte de CanonicalizedAmzHeaders de StringToSign
, selecione todos os cabeçalhos de solicitações HTTP que comecem com 'x-amz-' (usando uma comparação que não diferencie maiúsculas e minúsculas) e use o processo a seguir.
1 | Converta cada nome de cabeçalho HTTP para minúsculas. Por exemplo, 'X-Amz-Date ' torna-se 'x-amz-date '. |
2 | Classifique a coleção de cabeçalhos por ordem lexicográfica por nome de cabeçalho. |
3 | Combine campos do cabeçalho com o mesmo nome em um par “header-name:comma-separated-value-list” conforme descrito em RFC 2616, seção 4.2, sem qualquer espaço entre os valores. Por exemplo, os dois cabeçalhos de metadados 'x-amz-meta-username: fred ' e 'x-amz-meta-username: barney ' seriam combinados em único cabeçalho 'x-amz-meta-username:
fred,barney '. |
4 | “Desdobre” os cabeçalhos longos que abrangem várias linhas (como permitido em RFC 2616, seção 4.2) substituindo o espaço de dobramento (incluindo a nova linha) por um único espaço. |
5 | Remova todos os espaços ao redor dos dois pontos no cabeçalho. Por exemplo, o cabeçalho 'x-amz-meta-username: fred,barney ' iria se tornar 'x-amz-meta-username:fred,barney ' |
6 | Finalmente, adicione um caractere de nova linha (U+000A ) para cada cabeçalho canonizado na lista resultante. Crie o elemento CanonicalizedResource concatenando todos os cabeçalhos dessa lista em uma única string. |
Elementos StringToSign de cabeçalho HTTP posicionais versus nomeados
Os primeiros elementos de cabeçalho do StringToSign
(Content-Type, Date e Content-MD5) são de natureza posicional. StringToSign
não inclui os nomes desses cabeçalhos, somente seus valores da solicitação. Em contraste, os elementos 'x-amz-
' são nomeados. Os nomes de cabeçalho e os valores de cabeçalho aparecem em StringToSign
.
Se um cabeçalho posicional chamado para a definição de StringToSign
não estiver presente na sua solicitação (por exemplo, Content-Type
ou Content-MD5
são opcionais para solicitações PUT e sem sentido para solicitações GET), substitua a string vazia ("") para essa posição.
Requisito de time stamp
Um time stamp válido (usando o cabeçalho HTTP Date
ou uma alternativa x-amz-date
) é obrigatório para solicitações autenticadas. Além disso, o time stamp do cliente, incluído com uma solicitação autenticada, não deve exceder 15 minutos do tempo do sistema do Amazon S3 quando a solicitação é recebida. Caso contrário, haverá falha na solicitação com o código de erro RequestTimeTooSkewed
. A intenção dessas restrições é limitar a possibilidade de que solicitações interceptadas possam ser reenviadas por um adversário. Para uma proteção mais forte contra espionagem, use o transporte HTTPS para solicitações autenticadas.
nota
A restrição de validação na data da solicitação se aplica somente a solicitações autenticadas que não usem a autenticação por query string. Para obter mais informações, consulte Alternativa de autenticação de solicitação por string de consulta.
Algumas bibliotecas de clientes HTTP não expõem a capacidade para configurar o cabeçalho Date
para uma solicitação. Se tiver problemas para incluir o valor do cabeçalho "Data" nos cabeçalhos canonizados, você pode configurar o time stamp para a solicitação usando um cabeçalho 'x-amz-date
'. O valor do cabeçalho x-amz-date
deve estar em um dos formatos RFC 2616 (http://www.ietf.org/rfc/rfc2616.txtx-amz-date
está presente em uma solicitação, o sistema ignorará qualquer cabeçalho Date
ao calcular a assinatura da solicitação. Portanto, se você incluir o cabeçalho x-amz-date
, use a string vazia para o Date
quando criar o StringToSign
. Consulte a próxima seção para ver um exemplo.
Exemplos de autenticação
Os exemplos nesta seção usam as credenciais (não trabalho) na tabela a seguir.
Parâmetro | Valor |
---|---|
AWSAccessKeyId | AKIAIOSFODNN7EXAMPLE |
AWSSecretAccessKey | wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY |
No exemplo StringToSign
s, o formato não é significativo e \n
significa o ponto de código Unicode U+000A
, chamado geralmente de nova linha. Além disso, os exemplos usam "+0000" para designar o fuso horário. Você pode usar "GMT" para designar o fuso horário, mas as assinaturas mostradas nos exemplos serão diferentes.
Objeto GET
Este exemplo obtém um objeto do bucket awsexamplebucket1.
Solicitação | StringToSign |
---|---|
|
|
Observe que o CanonicalizedResource inclui o nome do bucket, mas a URI da solicitação HTTP não o inclui. (O bucket é especificado pelo cabeçalho de host.)
nota
O script Python a seguir calcula a assinatura precedente, usando os parâmetros fornecidos. É possível usar esse script para criar suas próprias assinaturas, substituindo as chaves e StringToSign conforme apropriado.
import base64 import hmac from hashlib import sha1 access_key = '
AKIAIOSFODNN7EXAMPLE
'.encode("UTF-8") secret_key = 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
'.encode("UTF-8") string_to_sign = 'GET\n\n\nTue, 27 Mar 2007 19:36:42 +0000\n/awsexamplebucket1/photos/puppy.jpg
'.encode("UTF-8") signature = base64.b64encode( hmac.new( secret_key, string_to_sign, sha1 ).digest() ).strip() print(f"AWS {access_key.decode()}:{signature.decode()}")
PUT objeto
Este exemplo coloca um objeto no bucket awsexamplebucket1 bucket.
Solicitação | StringToSign |
---|---|
|
|
Observe o cabeçalho Content-Type na solicitação e em StringToSign. Também observe que o Content-MD5 está em branco em StringToSign porque não está presente na solicitação.
Lista
Este exemplo lista o conteúdo do bucket awsexamplebucket1.
Solicitação | StringToSign |
---|---|
|
|
Observe a barra final no CanonicalizedResource e a ausência de parâmetros de query string.
Fetch
Este exemplo busca o sub-recurso de política de controle de acesso para o bucket “awsexamplebucket1” bucket.
Solicitação | StringToSign |
---|---|
|
|
Observe como o parâmetro de query string do sub-recurso está incluído no CanonicalizedResource.
Delete
Este exemplo exclui um objeto do bucket “awsexamplebucket1” usando o estilo de caminho e a alternativa de data.
Solicitação | StringToSign |
---|---|
|
|
Observe como usamos o método alternativo 'x-amz- data' de especificar a data (porque a biblioteca de cliente nos impediu de configurar a data, por exemplo). Nesse caso, o x-amz-date
tem precedência sobre o cabeçalho Date
. Portanto, entrada de data na assinatura deve conter o valor de cabeçalho x-amz-date
.
Carregar
Este exemplo faz upload de um objeto para um bucket de estilo hosted virtual CNAME com metadados.
Solicitação | StringToSign |
---|---|
|
|
Observe como os cabeçalhos 'x-amz-' são classificados, os espaços são removidos e os cabeçalhos são convertidos em minúsculas. Observe também que vários cabeçalhos com o mesmo nome foram unidos usando vírgulas para separar valores.
Observe como somente os cabeçalhos de entidade HTTP Content-Type
e Content-MD5
aparecem em StringToSign
. Os outros cabeçalhos de entidade Content-*
não aparecem.
Mais uma vez, observe que o CanonicalizedResource
inclui o nome do bucket, mas a URI da solicitação HTTP não o inclui. (O bucket é especificado pelo cabeçalho de host.)
Listar todos os meus buckets
Solicitação | StringToSign |
---|---|
|
|
Chaves Unicode
Solicitação | StringToSign |
---|---|
|
|
nota
Os elementos em StringToSign
que foram derivados da URI de solicitação são obtidos literalmente, incluindo a codificação do URL e a capitalização.
Problemas de assinatura de solicitação REST
Quando a autenticação de solicitação REST falha, o sistema responde à solicitação com um documento de erro em XML. As informações contidas neste documento de erro têm o objetivo de ajudar os desenvolvedores a diagnosticar o problema. Especificamente, o elemento StringToSign
do documento de erro SignatureDoesNotMatch
diz exatamente que canonização de solicitação o sistema está usando.
Alguns toolkits inserem silenciosamente os cabeçalhos que você não conhece antecipadamente, como a adição do cabeçalho Content-Type
durante um PUT. Na maioria desses casos, o valor do cabeçalho inserido permanece constante, permitindo que você descubra os cabeçalhos que faltam, usando ferramentas como Ethereal ou o tcpmon.
Alternativa de autenticação de solicitação por string de consulta
Você pode autenticar determinados tipos de solicitações passando as informações necessárias como parâmetros de query string em vez de usar o cabeçalho HTTP Authorization
. Isso é útil para habilitar o acesso de navegadores de terceiros a seus dados privados do Amazon S3 sem um proxy na solicitação. A ideia é criar uma solicitação "pré-assinada" e codificá-la como um URL que o navegador de um usuário final pode recuperar. Além disso, você pode limitar uma solicitação pré-assinada, especificando um tempo de expiração.
Para obter mais informações sobre como usar parâmetros de consulta para autenticar solicitações, consulte Autenticação de solicitações: uso parâmetros de consulta (AWS Signature Version 4) na Referência de APIs do Amazon Simple Storage Service. Para obter exemplos de uso de AWS SDKs para gerar URLs pré-assinados, consulte Compartilhar objetos com URLs pré-assinados.
Criar uma assinatura
Veja a seguir um exemplo de solicitação REST do Amazon S3 autenticada por query string.
GET /photos/puppy.jpg ?AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE&Expires=1141889120&Signature=vjbyPxybdZaNmGa%2ByT272YEAiv4%3D HTTP/1.1 Host: awsexamplebucket1.s3.us-west-1.amazonaws.com Date: Mon, 26 Mar 2007 19:37:58 +0000
O método de autenticação por query string não requer nenhum cabeçalho especial HTTP. Em vez disso, os elementos de autenticação exigidos são especificados como parâmetros de query string:
Nome de parâmetro de string de consulta | Valor de exemplo | Descrição |
---|---|---|
AWSAccessKeyId |
AKIAIOSFODNN7EXAMPLE |
Seu ID de chave de acesso da AWS. Especifica a chave de acesso secreta da AWS usada para assinar a solicitação e, indiretamente, a identidade do desenvolvedor que fez a solicitação. |
Expires |
1141889120 |
O tempo quando a assinatura vai expirar, especificado como o número de segundos desde o epoch (00:00:00 UTC em 1º de janeiro de 1970). Uma requisição recebida depois desse tempo (de acordo com o servidor) será rejeitada. |
Signature |
vjbyPxybdZaNmGa%2ByT272YEAiv4%3D |
A codificação do URL da codificação Base64 do HMAC-SHA1 de StringToSign. |
O método de autenticação de solicitação por query string difere ligeiramente do método comum, mas somente no formato do parâmetro da solicitação Signature
e no elemento StringToSign
. A seguir está a pseudogramática que ilustra o método de autenticação de solicitação por query string.
Signature = URL-Encode( Base64( HMAC-SHA1( YourSecretAccessKey, UTF-8-Encoding-Of( StringToSign ) ) ) ); StringToSign = HTTP-VERB + "\n" + Content-MD5 + "\n" + Content-Type + "\n" + Expires + "\n" + CanonicalizedAmzHeaders + CanonicalizedResource;
YourSecretAccessKey
é o ID da chave de acesso secreta da AWS que a Amazon atribui a você ao se cadastrar para ser um desenvolvedor da Amazon Web Services. Observe como o Signature
é codificado por URL para ser apropriado para a colocação na query string. Observe também que no StringToSign
, o elemento posicional HTTP Date
foi substituído por Expires
. O CanonicalizedAmzHeaders
e o CanonicalizedResource
são os mesmos.
nota
No método de autenticação por query string, você não utiliza o cabeçalho Date
nem o x-amz-date request
para calcular o string para assinar.
Autenticação de solicitação por string de consulta
Solicitação | StringToSign |
---|---|
|
|
Supomos que quando um navegador faz a solicitação GET, ele não fornece um cabeçalho Content-MD5 ou Content-Type, nem define os cabeçalhos x-amz- e assim essas partes de StringToSign
são deixadas em branco.
Usar codificação Base64
As assinaturas de solicitação HMAC devem ser codificadas em Base64. A codificação Base64 converte a assinatura em uma string simples ASCII que pode ser anexada à solicitação. Os caracteres que poderiam aparecer na string da assinatura como mais (+), barra (/) e igual (=) devem ser codificados se forem usados em uma URI. Por exemplo, se o código de autenticação inclui um sinal de mais (+), codifique-o como %2B na solicitação. Codifique uma barra como %2F e o sinal de igual como %3D.
Para obter exemplos de codificação Base64, consulte Exemplos de autenticação do Amazon S3.