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 SDK da AWS (consulte Código de exemplo e bibliotecas) ou a ferramenta AWS Command Line Interface (AWS CLI) para enviar solicitações de API à AWS, você pode pular esta seção, pois os clientes do SDK e CLI autenticam as 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 compatíveis com várias versões de assinatura, assinar as solicitações manualmente 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.

Você pode usar o protocolo de assinatura SigV4 da AWS para criar uma solicitação assinada para solicitações de API da AWS.

  1. A criação de uma solicitação canônica com base nos detalhes da solicitação.

  2. O cálculo uma assinatura usando suas credenciais da AWS.

  3. Adicionar essa assinatura à solicitação como um cabeçalho de autorização.

A AWS, em seguida, replica esse processo e verifica a assinatura, concedendo ou negando o acesso adequadamente.

Para ver como você pode usar o SigV4 da AWS para assinar solicitações de API, consulte Exemplos de assinatura de solicitação

O diagrama a seguir ilustra o processo de assinatura do SigV4, 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.

Solicitação de assinatura com 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 o código X-Amz-Security-Token ao cabeçalho de autorização ou incluí-lo na 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 requisitos específicos.

Resumo das etapas de assinatura

Crie 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 a string para assinar. Para obter detalhes sobre a criação da solicitação canônica, consulte Elementos de uma assinatura de solicitação de API da AWS.

Criar um hash para a solicitação canônica

Faça o hash 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.

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, escopo de credencial e o hash da solicitação canônica.

Derivar uma chave de assinatura

Realize uma sequência de operações de hash com chave (HMAC) na data da solicitação, região e serviço, usando sua chave de acesso secreta da AWS como a chave para a operação inicial de hashing.

Calcular a assinatura

Realize uma operação de hash com chave (HMAC) na string para assinar usando a chave de assinatura derivada como a chave de hash.

Adicionar a assinatura à solicitação

Adicione a assinatura calculada a um cabeçalho de HTTP ou à string de consulta da solicitação.

Criar uma solicitação canônica

Para criar uma solicitação canônica, concatene as strings a seguir separadas por caracteres de linha nova. Isso ajuda a garantir que a assinatura que você calcula possa corresponder à assinatura que a AWS calcula.

<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 em URI do componente de caminho absoluto do URI, começando com o código / que segue o nome do domínio e indo até o final da string ou até o caractere de ponto de interrogação (?) se você tiver parâmetros de string de consulta. Se o caminho absoluto estiver vazio, use um caractere de barra inclinada (/). O URI no exemplo a seguir, /amzn-s3-demo-bucket/myphoto.jpg, é o caminho absoluto, e você não codifica o / no caminho absoluto:

    http://s3.amazonaws.com/amzn-s3-demo-bucket/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/amzn-s3-demo-bucket?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 amzn-s3-demo-bucket:

    http://s3.amazonaws.com/amzn-s3-demo-bucket?acl

    Nesse caso, a CanonicalQueryString seria:

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

    Caso o URI não contenha 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 caractere de linha nova ("\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 linha nova ("\n"). Veja a seguir um exemplo de um 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. 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. Por exemplo, ao recuperar um objeto usando uma solicitação GET, não haverá nada na carga útil.

    Hex(SHA256Hash(""))
    nota

    Para o Amazon S3, inclua a string literal UNSIGNED-PAYLOAD ao construir uma solicitação canônica e defina o mesmo valor como o cabeçalho x-amz-content-sha256 ao enviar a solicitação.

    Hex(SHA256Hash("UNSIGNED-PAYLOAD"))

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.

Criar uma string para assinar

Para criar uma string para assinar, concatene 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 de credencial, que 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, calculada na etapa anterior.

Veja a seguir um exemplo de string para assinar.

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

Derivar uma chave de assinatura

Para derivar uma chave de assinatura, realize uma sequência de operações de hash com chave (HMAC) na data da solicitação, região e serviço, usando sua chave de acesso secreta da AWS como a chave para a operação inicial de hashing.

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.

O exemplo a seguir mostra como você deriva a SigningKey usada na próxima seção desse procedimento, mostrando a ordem na qual sua entrada é concatenada e transformada em hash. O código HMAC-SHA256 é a função de hash usada para fazer o hash dos dados, conforme mostrado.

DateKey = HMAC-SHA256("AWS4"+"<SecretAccessKey>", "<YYYYMMDD>") DateRegionKey = HMAC-SHA256(<DateKey>, "<aws-region>") DateRegionServiceKey = HMAC-SHA256(<DateRegionKey>, "<aws-service>") SigningKey = HMAC-SHA256(<DateRegionServiceKey>, "aws4_request")
Entrada obrigatória
  • Key, uma string que contém sua chave de acesso secreta.

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

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

    Para obter uma lista de regiões de strings, consulte Regional endpoints, na Referência geral da AWS.

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

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

Para derivar uma chave de 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.

    DateKey = 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.

    DateRegionKey = 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.

    O código do serviço é definido pelo serviço. Você pode usar get-products na AWS Pricing CLI para retornar o código de serviço de um serviço.

    DateRegionServiceKey = 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.

    SigningKey = hash(kService, "aws4_request")

Calcular a assinatura

Depois de derivar a chave de assinatura, calcule-a realizando 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.

Para calcular uma assinatura
  1. 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(SigningKey, string-to-sign)
  2. Converta a assinatura da representação binária em hexadecimal, em caracteres minúsculos.

Adicionar a assinatura à solicitação

Adicione a assinatura calculada à sua 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