Création d’une requête d’API AWS signée - AWS Identity and Access Management

Création d’une requête d’API AWS signée

Important

Si vous utilisez un AWS SDK (voir Exemples de code et bibliothèques) ou un outil AWS Command Line Interface (AWS CLI) pour envoyer des demandes d’API à AWS, vous pouvez ignorer cette section, car les clients de kit SDK et de l’interface de ligne de commande authentifient vos demandes à l’aide des clés d’accès que vous fournissez. À moins que vous n'ayez une bonne raison de ne pas le faire, nous vous recommandons de toujours utiliser un kit SDK ou la CLI.

Dans les régions qui prennent en charge plusieurs versions de signature, les demandes de signature manuelle impliquent que vous devez spécifier la version de signature utilisée. Lorsque vous fournissez des demandes à des points d'accès multi-régions, les kits SDK et la CLI utiliseront automatiquement Signature version 4A sans configuration supplémentaire.

Vous pouvez utiliser le protocole de signature SigV4 AWS pour créer une requête signée pour les demandes d’API AWS.

  1. Création d’une requête canonique basée sur les détails de la requête.

  2. Calcul d’une signature à l’aide de vos informations d’identification AWS.

  3. Ajout de cette signature à la requête en tant qu’en-tête Autorisation.

AWS réplique ensuite ce processus et vérifie la signature, accordant ou refusant l’accès en conséquence.

Pour découvrir comment utiliser SigV4 AWS pour Signer des demandes d’API, consultez Demander des exemples de signature.

Le tableau suivant décrit les fonctions utilisées dans le processus de création d’une demande signée. Vous devez implémenter du code pour ces fonctions. Pour plus d'informations, consultez les exemples de code dans les SDK AWS.

Fonction Description

Lowercase()

Convertit la chaîne en minuscules.

Hex()

Encodage en minuscules en base 16.

SHA256Hash()

Fonction de hachage cryptographique Secure Hash Algorithm (SHA, algorithme de hachage sécurisé).

HMAC-SHA256()

Calcule HMAC à l'aide de l'algorithme SHA256 avec la clé de signature fournie. Il s’agit de la Signature finale lorsque vous Signez avec Sigv4.

ECDSA-Sign

Signature ECDSA (Elliptic Curve Digital Signature Algorithm) calculée à l’aide de signatures asymétriques basées sur le chiffrement à clé publique-privée.

KDF(K, Label, Context, L)

Un KDF NIST SP800-108 en mode compteur utilisant la fonction PRF HMAC-SHA256 telle que définie dans la norme NIST SP 800-108r1.

Oct2Int(byte[ ])

Une fonction octet vers entier telle que décrite dans la norme ANSI X9.62.

Trim()

Supprimez tous les espaces blancs de début ou de fin.

UriEncode()

L'URI code chaque octet. UriEncode() doit appliquer les règles suivantes :

  • L'URI encode tous les octets sauf les caractères non réservés : A-Z, a-z, 0-9, -, ., _ et ~.

  • Le caractère d'espace est un caractère réservé qui doit être codé sous la forme « %20 » (et non sous la forme « + »).

  • Chaque octet encodé par URI est formé par un « % » et la valeur hexadécimale à deux chiffres de l'octet.

  • Les lettres de la valeur hexadécimale doivent être en majuscules, par exemple « %1A ».

  • Encodez la barre oblique « / » partout sauf dans le nom de la clé de l'objet. Par exemple, si le nom de clé de l'objet est photos/Jan/sample.jpg, la barre oblique du nom de la clé n'est pas encodée.

Important

Les fonctions UriEncode standard fournies par votre plateforme de développement peuvent ne pas fonctionner en raison de différences d'implémentation et de l'ambiguïté associée dans les RFC sous-jacentes. Nous vous recommandons d'écrire votre propre fonction UriEncode personnalisée pour garantir le bon fonctionnement de votre encodage.

Pour voir un exemple de fonction UriEncode en Java, veuillez consulter la rubrique Utilitaires Java (langue française non garantie) sur le site Web de GitHub.

Note

Lorsque vous Signez vos demandes, vous pouvez utiliser AWS SigV4 ou AWS SigV4a. La principale différence entre les deux est déterminée par la façon dont la signature est calculée. Avec SigV4a, l’ensemble de régions est inclus dans la chaîne à Signer, mais ne fait pas partie de l’étape de dérivation des informations d’identification.

Requêtes de signature avec des informations d’identification de sécurité temporaires

Au lieu d'utiliser des informations d'identification à long terme pour signer une requête, vous pouvez utiliser des informations d'identification de sécurité temporaires fournies par AWS Security Token Service (AWS STS).

Lorsque vous utilisez des informations d’identification de sécurité temporaires, vous devez ajouter X-Amz-Security-Token à l’en-tête Autorisation ou l’inclure à la chaîne de requête pour contenir le jeton de session. Certains services nécessitent que vous ajoutiez X-Amz-Security-Token à la requête canonique. Pour les autres services, vous n’avez qu’à ajouter X-Amz-Security-Token à la fin, une fois que vous avez calculé la signature. Consultez la documentation de chaque Service AWS pour connaître les exigences spécifiques.

Récapitulatif des étapes de signature

Création d’une requête canonique

Organisez le contenu de votre demande (hôte, action, en-têtes, etc.) dans un format standard canonique. La requête canonique est l’une des entrées utilisées pour créer la chaîne de connexion. Pour plus de détails sur la création de la requête canonique, consultez Éléments d'une signature de requête d'API AWS.

Création d’un hachage de la requête canonique

Hashez la requête canonique avec le même algorithme que celui que vous avez utilisé pour créer le hachage des données utiles. Le hachage de la requête canonique est une chaîne de caractères hexadécimaux en minuscules.

Création d’une chaîne à signer

Créez une chaîne de connexion avec la requête canonique et des informations supplémentaires telles que l’algorithme, la date de la requête, la portée des informations d’identification et le hachage de la requête canonique.

Dérivation d’une clé de signature

Utilisez la clé d’accès secrète pour dériver la clé utilisée pour signer la demande.

Calcul de la signature

Effectuez une opération de hachage à clé sur la chaîne à signer en utilisant la clé de signature dérivée comme clé de hachage.

Ajout d’une signature à la requête

Ajouter la signature calculée à un en-tête HTTP ou à la chaîne de requête de la requête.

Création d’une requête canonique

Pour créer une requête canonique, concaténez les chaînes suivantes, séparées par des caractères de saut de ligne. Cela permet de garantir la correspondance entre la signature que vous calculez et la signature calculée par AWS.

<HTTPMethod>\n <CanonicalURI>\n <CanonicalQueryString>\n <CanonicalHeaders>\n <SignedHeaders>\n <HashedPayload>
  • HTTPMethod : la méthode HTTP, telle que GET, PUT, HEAD et DELETE.

  • CanonicalUri : version encodée par URI de l’URI du composant du chemin absolu, commençant par la / qui suit le nom de domaine et jusqu’à la fin de la chaîne ou jusqu’au point d’interrogation (?) si vous avez des paramètres de chaîne de requête. Si le chemin d’accès absolu est vide, utilisez un caractère barre oblique (/). L’URI de l’exemple suivant, /amzn-s3-demo-bucket/myphoto.jpg, est le chemin absolu et vous n’encodez pas la / dans le chemin absolu :

    http://s3.amazonaws.com/amzn-s3-demo-bucket/myphoto.jpg
  • CanonicalQueryString : paramètres de la chaîne de requête encodée par URI. Vous encodez individuellement chaque nom et chaque valeur par URI. Vous devez également trier les paramètres de la chaîne de requête canonique par ordre alphabétique par nom de clé. Le tri s'effectue après l'encodage. La chaîne de requête dans l'exemple d'URI suivant est la suivante :

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

    La chaîne de requête canonique est la suivante (des sauts de ligne sont ajoutés à cet exemple pour faciliter la lecture) :

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

    Lorsqu’une requête cible une sous-ressource, la valeur du paramètre de requête correspondant est une chaîne vide (""). Par exemple, l'URI suivant identifie la sous-ressource ACL sur le compartiment amzn-s3-demo-bucket :

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

    Dans ce cas, la CanonicalQueryString serait :

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

    Si l’URI ne contient pas de ?, la requête ne contient aucune chaîne de requête et vous définissez la chaîne de requête canonique sur une chaîne vide (""). Vous devrez tout de même inclure le caractère de saut de ligne ("\n").

  • CanonicalHeaders : une liste des en-têtes de requête avec leurs valeurs. Les paires de nom et de valeur d’en-tête individuelles sont séparées par le caractère de saut de ligne ("\n"). Voici un exemple de CanonicalHeader :

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

    La liste des CanonicalHeaders doit inclure les éléments suivants :

    • En-tête host HTTP.

    • Si l'en-tête Content-Type est présent dans la demande, vous devez l'ajouter à la liste CanonicalHeaders.

    • Les en-têtes x-amz-* que vous prévoyez d'inclure dans votre demande doivent également être ajoutés. Par exemple, si vous utilisez des informations d'identification de sécurité temporaires, vous devez inclure x-amz-security-token dans votre demande. Vous devez ajouter cet en-tête dans la liste des CanonicalHeaders.

    • Pour SigV4a, vous devez inclure un en-tête de jeu de régions qui spécifie l’ensemble des régions dans lesquelles la demande sera valide. L’en-tête X-Amz-Region-Set est spécifié sous forme de liste de valeurs séparées par des virgules. L’exemple suivant montre un en-tête de région qui permet d’effectuer une demande dans les régions us-east-1 et us-west-1.

      X-Amz-Region-Set=us-east-1,us-west-1

      Vous pouvez utiliser des caractères génériques (*) dans les régions pour spécifier plusieurs régions. Dans l’exemple suivant, l’en-tête permet de faire une demande à la fois dans les régions us-west-1 et us-west-2.

      X-Amz-Region-Set=us-west-*

    Note

    L’en-tête x-amz-content-sha256 est obligatoire pour les requêtes AWS Amazon S3. Il fournit un hachage de la charge utile de la requête. S'il n'y a pas de charge utile, vous devez fournir le hachage d'une chaîne vide.

    Chaque nom d'en-tête doit :

    • utiliser des caractères minuscules ;

    • apparaître par ordre alphabétique ;

    • être suivi de deux points (:).

    Pour les valeurs, vous devez :

    • supprimer toutes les espaces de début ou de fin ;

    • convertir des espaces séquentielles en une espace unique ;

    • séparez les valeurs d'un en-tête à valeurs multiples par des virgules.

    • Vous devez inclure l'en-tête hôte (HTTP/1.1) ou l'en-tête :authority (HTTP/2), ainsi que tout en-tête x-amz-* dans la signature. Vous pouvez éventuellement inclure d'autres en-têtes standard dans la signature, tels que content-type.

    Les fonctions Lowercase() et Trim() utilisées dans cet exemple sont décrites dans la section précédente.

    L'exemple suivant est une chaîne CanonicalHeaders. Les noms d'en-tête sont en minuscules et sont triés.

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

    Note

    Aux fins du calcul d’une signature d’autorisation, seuls l’hôte et les en-têtes x-amz-* sont obligatoires. Toutefois, afin d’éviter toute altération des données, vous devez envisager d’inclure les en-têtes supplémentaires dans le calcul de la signature.

    N’incluez pas les en-têtes tronçon qui sont fréquemment modifiés lors du transit à travers un système complexe. Cela inclut tous les en-têtes de transport volatils qui sont modifiés par les proxys, les équilibreurs de charge et les nœuds d’un système distribué, y compris connection, x-amzn-trace-id, user-agent, keep-alive, transfer-encoding, TE, trailer, upgrade, proxy-authorization, et proxy-authenticate.

  • SignedHeaders : une liste triée par ordre alphabétique et séparée par des points-virgules de noms d'en-tête de demande en minuscules. Les en-têtes de demande de la liste sont les mêmes que ceux que vous avez inclus dans la chaîne CanonicalHeaders. Pour l’exemple précédent, la valeur de SignedHeaders serait :

    host;x-amz-content-sha256;x-amz-date
  • HashedPayload : chaîne créée en utilisant la charge utile contenue dans le corps de la requête HTTP comme entrée dans une fonction de hachage. Cette chaîne utilise des caractères hexadécimaux minuscules.

    Hex(SHA256Hash(<payload>>))

    Si la requête ne contient pas de données utiles, vous calculez un hachage de la chaîne vide, comme lorsque vous récupérez un objet à l’aide d’une requête GET, il n’y a rien dans les données utiles.

    Hex(SHA256Hash(""))
    Note

    Pour Amazon S3, incluez la chaîne littérale UNSIGNED-PAYLOAD lors de la création d’une requête canonique, et définissez la même valeur que celle de l’en-tête x-amz-content-sha256 lors de l’envoi de la requête.

    Hex(SHA256Hash("UNSIGNED-PAYLOAD"))

Création d’un hachage de la requête canonique

Créez un hachage (digest) de la requête canonique avec le même algorithme que celui que vous avez utilisé pour créer le hachage de la charge utile. Le hachage de la requête canonique est une chaîne de caractères hexadécimaux en minuscules.

Création d’une chaîne à signer

Pour créer une chaîne, concaténez les chaînes suivantes, séparées par des sauts de ligne. Ne terminez pas cette chaîne par un caractère de saut de ligne.

Algorithm \n RequestDateTime \n CredentialScope \n HashedCanonicalRequest
  • Algorithme : algorithme utilisé pour créer le hachage de la requête canonique.

    • SigV4 : utilisez AWS4-HMAC-SHA256 pour spécifier l’algorithme de hachage HMAC-SHA256.

    • SigV4a : utilisez AWS4-ECDSA-P256-SHA256 pour spécifier l’algorithme de hachage ECDSA-P256-SHA-256.

  • RequestDateTime :date et heure utilisées dans l’étendue des informations d'identification. Cette valeur est l'heure UTC actuelle au format ISO 8601 (par exemple, 20130524T000000Z).

  • CredentialScope : la portée des informations d’identification, qui limite la signature obtenue à la région et au service spécifiés.

    • SigV4 : les informations d’identification comprennent votre clé d’accès, la date au format YYYYMMDD, le code de région, le code de service et la chaîne de terminaison aws4_request, séparés par des barres obliques (/). Le code Région, le code de service et la chaîne de terminaison doivent utiliser des caractères minuscules. La chaîne a le format suivant : YYYYMMDD/region/service/aws4_request.

    • SigV4a : les informations d’identification comprennent la date au format YYYYMMDD, le nom du service et la chaîne de terminaison aws4_request, séparés par des barres obliques (/). Notez que la portée des informations d’identification n’inclut pas la région, car celle-ci est couverte dans un en-tête X-Amz-Region-Set distinct. La chaîne a le format suivant : YYYYMMDD/service/aws4_request.

  • HashedCanonicalRequest : hachage de la requête canonique, calculé à l’étape précédente.

L'exemple suivant est une chaîne de connexion.

"<Algorithm>" + "\n" + timeStampISO8601Format + "\n" + <Scope> + "\n" + Hex(<Algorithm>(<CanonicalRequest>))

Dérivation d’une clé de signature

Pour dériver une clé de Signature, choisissez l’un des processus suivants afin de calculer une clé de Signature pour SigV4 ou SigV4a.

Dérivation d’une clé de Signature pour SigV4

Pour dériver une clé de Signature pour SigV4, exécutez une série d’opérations de hachage à clé (HMAC) sur la date, la région et le service de la demande, avec votre clé d’accès secrète AWS comme la clé d’opération de hachage initiale.

Pour chaque étape, appelez la fonction de hachage avec la clé et les données requises. Le résultat de chaque appel à la fonction de hachage devient l'entrée du prochain appel à la fonction de hachage.

L’exemple suivant montre comment vous obtenez la SigningKey utilisée dans la section suivante de cette procédure, en indiquant l’ordre dans lequel vos données sont concaténées et hachées. HMAC-SHA256 est la fonction de hachage utilisée pour hacher les données comme indiqué.

DateKey = HMAC-SHA256("AWS4"+"<SecretAccessKey>", "<YYYYMMDD>") DateRegionKey = HMAC-SHA256(<DateKey>, "<aws-region>") DateRegionServiceKey = HMAC-SHA256(<DateRegionKey>, "<aws-service>") SigningKey = HMAC-SHA256(<DateRegionServiceKey>, "aws4_request")
Entrée obligatoire
  • Key : une chaîne contenant votre clé d’accès secrète.

  • Date : une chaîne contenant la date utilisée dans l’étendue des informations d’identification, au format AAAAMMJJ

  • Region : une chaîne contenant le code Région (par exemple, us-east-1).

    Pour obtenir la liste des chaînes régionales, consultez la section Points de terminaison régionaux dans les Références générales AWS.

  • Service : une chaîne contenant le code de service (par exemple, ec2).

  • Chaîne de connexion que vous avez créée à l'étape précédente.

Pour dériver une clé de Signature pour SigV4
  1. Concaténez "AWS4" et la clé d’accès secrète. Appelez la fonction de hachage avec la chaîne concaténée en tant que clé et la chaîne de date en tant que données.

    DateKey = hash("AWS4" + Key, Date)
  2. Appelez la fonction de hachage en utilisant le résultat de l'appel précédent en tant que clé et la chaîne Région en tant que données.

    DateRegionKey = hash(kDate, Region)
  3. Appelez la fonction de hachage en utilisant le résultat de l'appel précédent en tant que clé et la chaîne de service en tant que données.

    Le code de service est défini par le service. Vous pouvez utiliser get-products dans l’interface de ligne de commande de tarification AWS pour renvoyer le code de service d’un service.

    DateRegionServiceKey = hash(kRegion, Service)
  4. Appelez la fonction de hachage en utilisant le résultat de l'appel précédent en tant que clé et « aws4_request » en tant que données.

    SigningKey = hash(kService, "aws4_request")

Dérivation d’une clé de Signature pour SigV4a

Pour créer une clé de Signature pour SigV4a, utilisez le processus suivant afin de dériver une paire de clés à partir de la clé d’accès secrète. Pour un exemple d’implémentation de cette dérivation, consultez l’implémentation de la bibliothèque C99 pour l’authentification côté client AWS.

n = [NIST P-256 elliptic curve group order] G = [NIST P-256 elliptic curve base point] label = "AWS4-ECDSA-P256-SHA256" akid = [AWS access key ID as a UTF8 string] sk = [AWS secret access Key as a UTF8 Base64 string] input_key = "AWS4A" || sk count = 1 while (counter != 255) { context = akid || counter // note: counter is one byte key = KDF(input_key, label, context, 256) c = Oct2Int(key) if (c > n - 2) { counter++ } else { k = c + 1 // private key Q = k * G // public key } } if (c < 255) { return [k, Q] } else { return FAILURE }

Calcul de la signature

Une fois la clé de signature dérivée, calculez la signature à ajouter à votre demande. Cette procédure varie en fonction de la version de signature que vous utilisez.

Pour calculer une Signature SigV4
  1. Appelez la fonction de hachage en utilisant le résultat de l’appel précédent en tant que clé et la chaîne de signature en tant que données. Utilisez la clé de signature dérivée comme la clé de hachage pour cette opération. Le résultat est la signature sous forme de valeur binaire.

    signature = hash(SigningKey, string-to-sign)
  2. Convertissez la signature de la représentation binaire à la représentation hexadécimale, en caractères minuscules.

Pour calculer une Signature SigV4a
  1. À l’aide de l’algorithme de signature numérique (ECDSA P-256), signez la chaîne de signature que vous avez créée à l’étape précédente. La clé utilisée pour cette signature est la clé asymétrique privée dérivée de la clé d’accès secrète telle que décrite ci-dessus.

    signature = base16(ECDSA-Sign(k, string-to-sign))
  2. Convertissez la signature de la représentation binaire à la représentation hexadécimale, en caractères minuscules.

Ajout d’une signature à la requête

Ajoutez la signature calculée à votre demande.

Exemple : en-tête d'autorisation
SigV4

L’exemple suivant montre un en-tête Authorization pour l’action DescribeInstances en utilisant AWS SigV4. Pour des raisons de lisibilité, cet exemple est formaté avec des sauts de ligne. Dans votre code, il doit s'agir d'une chaîne continue. Il n'y a pas de virgule entre l'algorithme et Credential. Toutefois, les autres éléments doivent être séparés par des virgules.

Authorization: AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20220830/us-east-1/ec2/aws4_request, SignedHeaders=host;x-amz-date, Signature=calculated-signature
SigV4a

L’exemple suivant montre un en-tête Autorisation pour l’action CreateBucket à l’aide d’AWS SigV4. Pour des raisons de lisibilité, cet exemple est formaté avec des sauts de ligne. Dans votre code, il doit s'agir d'une chaîne continue. Il n’y a pas de virgule entre l’algorithme et Informations d’identification. Toutefois, les autres éléments doivent être séparés par des virgules.

Authorization: AWS4-ECDSA-P256-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20220830/s3/aws4_request, SignedHeaders=host;x-amz-date;x-amz-region-set, Signature=calculated-signature
Exemple : requête avec des paramètres d'authentification dans la chaîne de requête
SigV4

L’exemple suivant présente une requête pour l’action DescribeInstances en utilisant AWS SigV4 qui inclut les informations d’authentification. Pour des raisons de lisibilité, cet exemple est formaté avec des sauts de ligne et n’est pas code en URL. Dans votre code, la chaîne de requête doit être une chaîne continue codée en 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
SigV4a

L’exemple suivant présente une requête pour l’action CreateBucket en utilisant AWS SigV4a qui inclut les informations d’authentification. Pour des raisons de lisibilité, cet exemple est formaté avec des sauts de ligne et n’est pas code en URL. Dans votre code, la chaîne de requête doit être une chaîne continue codée en URL.

https://ec2.amazonaws.com/? Action=CreateBucket& Version=2016-11-15& X-Amz-Algorithm=AWS4-ECDSA-P256-SHA256& X-Amz-Credential=AKIAIOSFODNN7EXAMPLE/20220830/s3/aws4_request& X-Amz-Region-Set=us-west-1& X-Amz-Date=20220830T123600Z& X-Amz-SignedHeaders=host;x-amz-date;x-amz-region-set& X-Amz-Signature=calculated-signature