Crie uma solicitação assinada de API da AWS - AWS Identity and Access Management

Crie uma solicitação assinada de API da AWS

Importante

Caso use um AWS SDK (consulte Código de exemplo e Bibliotecas) ou a ferramenta AWS Command Line Interface (CLI) para enviar solicitações de API para a AWS, você pode pular esta seção, pois os clientes de SDK e CLI autenticam suas solicitações usando as chaves de acesso fornecidas por você. A menos que haja um bom motivo para não usar, é recomendável usar sempre um SDK ou a CLI.

Em regiões que oferecem suporte a várias versões de assinatura, assinar manualmente as solicitações significa que é necessário especificar qual versão de assinatura está sendo usada. Quando você fornece solicitações para pontos de acesso multirregionais, os SDKs e a CLI automaticamente alternam para o uso do Signature Version 4A, sem configuração adicional.

Veja abaixo uma visão geral do processo para criar uma solicitação assinada. Para calcular uma assinatura, primeiro é necessário usar uma string para assinar. Em seguida, calcule um hash HMAC-SHA256 da string a ser assinada usando uma chave de assinatura. O diagrama a seguir ilustra o processo, incluindo os vários componentes da string criada para assinatura.

Uma imagem das partes de uma solicitação canônica, string para assinar, chave de assinatura e assinatura.

A tabela a seguir descreve as funções exibidas no diagrama. É necessário implementar o código para essas funções. Para obter mais informações, consulte os exemplos de código nos AWS SDKs.

Função Descrição

Lowercase()

Converta a string em letras minúsculas.

Hex()

Codificação de base 16 em letras minúsculas.

SHA256Hash()

Função de hash criptográfico do Secure Hash Algorithm (SHA).

HMAC-SHA256()

Calcula o HMAC usando o algoritmo SHA256 com a chave de assinatura fornecida. Essa é a assinatura final.

Trim()

Remova qualquer espaço em branco inicial e final.

UriEncode()

O URI codifica cada byte. O UriEncode() deve aplicar as seguintes regras:

  • O URI codifica cada byte, exceto os caracteres não reservados: “A”-“Z”, “a”-“z”, “0”-“9”, “-”, “.”, “_” e “~”.

  • O caractere de espaço é um caractere reservado e deve ser codificado como “%20” (e não como “+”).

  • Cada byte codificado por URI é formado por um “%” e o valor hexadecimal de dois dígitos do byte.

  • As letras no valor hexadecimal devem estar em maiúsculas; por exemplo, “%1A”.

  • Codifique o caractere de barra, “/”, em todos os lugares, exceto no nome da chave do objeto. Por exemplo, se o nome da chave do objeto for photos/Jan/sample.jpg, a barra no nome da chave não está codificada.

Importante

As funções UriEncode padrão fornecidas por sua plataforma de desenvolvimento podem não funcionar devido às diferenças na implementação e à ambiguidade relacionada nos RFCs subjacentes. É recomendável escrever sua própria função UriEncode personalizada para garantir que a codificação funcione.

Para ver um exemplo de uma função UriEncode em Java, consulte Java Utilities no site do GitHub.

nota

Ao assinar suas solicitações, você pode usar o AWS Signature Version 4 ou o AWS Signature Version 4A. A principal diferença entre os dois está na forma como a assinatura é calculada. Com o AWS Signature Version 4A, a assinatura não inclui informações específicas da região e é calculada usando o algoritmo AWS4-ECDSA-P256-SHA256.

Credenciais de segurança temporárias

Em vez de usar credenciais de longo prazo para assinar uma solicitação, é possível usar credenciais de segurança temporárias fornecidas pelo AWS Security Token Service (AWS STS).

Ao usar credenciais de segurança temporárias, é necessário adicionar X-Amz-Security-Token ao cabeçalho de autorização ou à string de consulta para manter o token da sessão. Alguns serviços exigem que você adicione X-Amz-Security-Token à solicitação canônica. Outros serviços exigem apenas que você adicione X-Amz-Security-Token no final, depois de calcular a assinatura. Verifique a documentação de cada AWS service (Serviço da AWS) para obter detalhes.

Resumo das etapas de assinatura

Etapa 1: criar uma solicitação canônica

Organize o conteúdo da solicitação (host, ação, cabeçalhos etc.) em um formato padrão canônico. A solicitação canônica é um recurso usado para criar uma string para assinar. Para obter detalhes, consulte Elementos de uma assinatura de solicitação de API da AWS.

Etapa 2: criar um hash para a solicitação canônica

Derive uma chave de assinatura executando uma série de operações de hash com chave (operações HMAC) na data, na região e no serviço da solicitação com sua chave de acesso secreta da AWS como a chave para a operação de hash inicial.

Etapa 3: criar uma string para assinar

Crie uma string para assinar com a solicitação canônica e informações adicionais, como o algoritmo, data de solicitação, gama de credenciais e o resumo (hash) da solicitação canônica.

Etapa 4: calcular a assinatura

Depois de derivar a chave de assinatura, calcule esta executando uma operação de hash de chave na string a ser assinada. Use a chave de assinatura derivada como a chave de hash para esta operação.

Etapa 5: adicionar a assinatura à solicitação

Depois de calcular a assinatura, adicione-a a um cabeçalho de HTTP ou à string de consulta da solicitação.

Etapa 1: criar uma solicitação canônica

Crie uma solicitação canônica concatenando as strings a seguir, separadas por caracteres de linha nova. Isso ajuda a garantir que a assinatura que você calcular e a assinatura que a AWS calcular sejam correspondentes.

<HTTPMethod>\n <CanonicalURI>\n <CanonicalQueryString>\n <CanonicalHeaders>\n <SignedHeaders>\n <HashedPayload>
  • HTTPMethod: o método HTTP, como GET, PUT, HEAD e DELETE.

  • CanonicalUri: a versão codificada por URI do URI do componente de caminho absoluto, começando pelo “/” após o nome do domínio e seguindo até o final da string ou até o caractere de ponto de interrogação (“?”), se houver parâmetros de string de consulta. Se o caminho absoluto estiver vazio, use um caractere de barra inclinada (/). O URI no seguinte exemplo, /examplebucket/myphoto.jpg, é o caminho absoluto, e você não codifica o “/” no caminho absoluto:

    http://s3.amazonaws.com/examplebucket/myphoto.jpg
  • CanonicalQueryString: os parâmetros da string de consulta codificados por URI. Codifique por URI cada nome e valor individualmente. Também é necessário classificar os parâmetros na string de consulta canônica em ordem alfabética pelo nome da chave. A classificação ocorre após a codificação. A string de consulta no seguinte exemplo de URI é:

    http://s3.amazonaws.com/examplebucket?prefix=somePrefix&marker=someMarker&max-keys=2

    A string de consulta canônica é como este exemplo (quebras de linha foram adicionadas ao exemplo para facilitar a leitura):

    UriEncode("marker")+"="+UriEncode("someMarker")+"&"+ UriEncode("max-keys")+"="+UriEncode("20") + "&" + UriEncode("prefix")+"="+UriEncode("somePrefix")

    Quando uma solicitação se destina a um sub-recurso, o valor do parâmetro de consulta correspondente é uma string vazia (“”). Por exemplo, o URI a seguir identifica o sub-recurso ACL no bucket examplebucket:

    http://s3.amazonaws.com/examplebucket?acl

    A CanonicalQueryString nesse caso é a seguinte:

    UriEncode("acl") + "=" + ""

    Se o URI não contém um “?”, não há strings de consulta na solicitação, e você define a string de consulta canônica como uma string vazia (“”). Você ainda precisará incluir o “\n”.

  • CanonicalHeaders: uma lista de cabeçalhos de solicitação com os respectivos valores. Os pares individuais de nome e valor do cabeçalho são separados pelo caractere de nova linha (“\n”). Veja a seguir um exemplo de CanonicalHeader:

    Lowercase(<HeaderName1>)+":"+Trim(<value>)+"\n" Lowercase(<HeaderName2>)+":"+Trim(<value>)+"\n" ... Lowercase(<HeaderNameN>)+":"+Trim(<value>)+"\n"

    A lista CanonicalHeaders deve conter:

    • Cabeçalho HTTP host

    • Se o cabeçalho Content-Type estiver presente na solicitação, você deverá adicioná-lo à lista CanonicalHeaders.

    • Também deverão ser adicionados todos os cabeçalhos x-amz-* que você pretende incluir na solicitação. Por exemplo, se você estiver usando credenciais de segurança temporárias, precisará incluir o x-amz-security-token na solicitação. É necessário adicionar esse cabeçalho à lista de CanonicalHeaders.

    nota

    O cabeçalho x-amz-content-sha256 é obrigatório para solicitações da AWS do Amazon S3. Ele fornece um hash da carga da solicitação. Se não houver carga útil, será necessário fornecer o hash de uma string vazia.

    Todo nome de cabeçalho deve:

    • usar caracteres minúsculos.

    • ser exibido em ordem alfabética.

    • ser seguido por dois pontos (:).

    Para valores, é necessário:

    • remover todos os espaços à esquerda ou à direita.

    • converter espaços sequenciais em um espaço único.

    • separar os valores de um cabeçalho de múltiplos valores usando vírgulas.

    • É necessário incluir na assinatura o cabeçalho host (HTTP/1.1) ou o cabeçalho :authority (HTTP/2) e quaisquer cabeçalhos x-amz-*. Opcionalmente, você pode incluir outros cabeçalhos padrão na assinatura, como content-type.

    As funções Lowercase() e Trim() usadas neste exemplo estão descritas na seção anterior.

    Veja a seguir um exemplo de string CanonicalHeaders. O nomes dos cabeçalhos estão em letras minúsculas e são classificados.

    host:s3.amazonaws.com x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 x-amz-date:20130708T220855Z

    nota

    Para fins de cálculo de uma assinatura de autorização, somente o host e cabeçalhos x-amz-* são obrigatórios; no entanto, para evitar a adulteração de dados, convém incluir todos os cabeçalhos no cálculo da assinatura.

  • SignedHeaders: uma lista ordenada alfabeticamente, separada por ponto e vírgula, de nomes de cabeçalhos de solicitação em letras minúsculas. Os cabeçalhos de solicitação da lista são os mesmos cabeçalhos que você incluiu na string CanonicalHeaders. Por exemplo, para o exemplo anterior, o valor de SignedHeaders seria:

    host;x-amz-content-sha256;x-amz-date
  • HashedPayload: uma string criada usando a carga útil no corpo da solicitação HTTP como entrada para uma função de hash. Esta string usa caracteres hexadecimais minúsculos.

    Hex(SHA256Hash(<payload>)

    Se não houver carga útil na solicitação, calcule um hash da string vazia da seguinte forma:

    Hex(SHA256Hash(""))

    O hash retorna o seguinte valor:

    e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

    Por exemplo, ao carregar um objeto usando uma solicitação PUT, forneça dados do objeto no corpo. Ao recuperar um objeto usando um solicitação GET, calcule o hash da string vazia.

Etapa 2: criar um hash para a solicitação canônica

Crie um hash (resumo) da solicitação canônica usando o mesmo algoritmo que você usou para criar o hash da carga útil. O hash da solicitação canônica é uma string de caracteres hexadecimais em minúsculas.

Etapa 3: criar uma string para assinar

Crie uma string concatenando as strings a seguir, separadas por caracteres de linha nova. Não termine esta string com um caractere de linha nova.

Algorithm \n RequestDateTime \n CredentialScope \n HashedCanonicalRequest
  • Algorithm: o algoritmo usado para criar o hash da solicitação canônica. Para SHA-256, o algoritmo é AWS4-HMAC-SHA256.

  • RequestDateTime: a data e a hora usadas no escopo da credencial. Esse valor é a hora UTC atual no formato ISO 8601 (por exemplo, 20130524T000000Z).

  • CredentialScope: o escopo da credencial. Isso restringe a assinatura resultante à região e ao serviço especificados. A string tem o seguinte formato: AAAAMMDD/região/serviço/aws4_request.

  • HashedCanonicalRequest: o hash da solicitação canônica. Esse valor é calculado na Etapa 2.

Veja a seguir um exemplo de string para assinar.

"AWS4-HMAC-SHA256" + "\n" + timeStampISO8601Format + "\n" + <Scope> + "\n" + Hex(SHA256Hash(<CanonicalRequest>))

Etapa 4: calcular a assinatura

No AWS Signature Version 4, em vez de usar suas chaves de acesso da AWS para assinar uma solicitação, crie uma chave de assinatura que tenha como escopo uma região e um serviço específicos como as informações de autenticação que você adicionará à solicitação.

DateKey = HMAC-SHA256("AWS4"+"<SecretAccessKey>", "<YYYYMMDD>") DateRegionKey = HMAC-SHA256(<DateKey>, "<aws-region>") DateRegionServiceKey = HMAC-SHA256(<DateRegionKey>, "<aws-service>") SigningKey = HMAC-SHA256(<DateRegionServiceKey>, "aws4_request")

Para obter uma lista de strings regionais, consulte Regional Endpoints na Referência geral da AWS.

Para cada etapa, chame a função de hash com a chave e os dados necessários. O resultado de cada chamada para a função de hash torna-se a entrada para a próxima chamada para a função de hash.

Entrada obrigatória
  • Uma string, Key, que contém sua chave de acesso secreta

  • Uma string, Date, que contém a data usada no escopo da credencial, no formato AAAAMMDD

  • Uma string, Region, que contém o código da região (por exemplo, us-east-1)

  • Uma string, Service, que contém o código do serviço (por exemplo, ec2)

  • A string para assinar que você criou na etapa anterior.

Para calcular a assinatura
  1. Concatene “AWS4" e a chave de acesso secreta. Chame a função de hash com a string concatenada como chave e a string de data como os dados.

    kDate = hash("AWS4" + Key, Date)
  2. Chame a função de hash com o resultado da chamada anterior como chave e a string de região como os dados.

    kRegion = hash(kDate, Region)
  3. Chame a função de hash com o resultado da chamada anterior como a chave e a string de serviço como os dados.

    kService = hash(kRegion, Service)
  4. Chame a função de hash com o resultado da chamada anterior como a chave e “aws4_request” como os dados.

    kSigning = hash(kService, "aws4_request")
  5. Chame a função de hash com o resultado da chamada anterior como a chave e a string para assinar como os dados. O resultado é a assinatura como valor binário.

    signature = hash(kSigning, string-to-sign)
  6. Converta a assinatura da representação binária em hexadecimal, em caracteres minúsculos.

Etapa 5: adicionar a assinatura à solicitação

exemplo Exemplo: cabeçalho de autorização

O exemplo a seguir mostra um cabeçalho Authorization para a ação DescribeInstances. Para facilitar a leitura, este exemplo está formatado com quebras de linha. Em seu código, deve ser uma string contínua. Não há vírgula entre o algoritmo e Credential. Porém, os outros elementos devem ser separados por vírgulas.

Authorization: AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20220830/us-east-1/ec2/aws4_request, SignedHeaders=host;x-amz-date, Signature=calculated-signature
exemplo Exemplo: solicitação com parâmetros de autenticação na string de consulta

O exemplo a seguir mostra uma consulta para a ação DescribeInstances que contém as informações de autenticação. Para facilitar a leitura, esse exemplo está formatado com quebras de linha e não codificado de URL. Em seu código, a string de consulta deve ser uma string contínua codificada de URL.

https://ec2.amazonaws.com/? Action=DescribeInstances& Version=2016-11-15& X-Amz-Algorithm=AWS4-HMAC-SHA256& X-Amz-Credential=AKIAIOSFODNN7EXAMPLE/20220830/us-east-1/ec2/aws4_request& X-Amz-Date=20220830T123600Z& X-Amz-SignedHeaders=host;x-amz-date& X-Amz-Signature=calculated-signature

Código-fonte nos AWS SDKs

Os AWS SDKs incluem código-fonte no GitHub para assinar solicitações de API da AWS. Para obter exemplos de código, consulte Projetos de exemplo em repositório de amostras da AWS