Creare una richiesta AWS API firmata - AWS Identity and Access Management

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Creare una richiesta AWS API firmata

Importante

Se utilizzi uno strumento AWS SDK (vedi Codice di esempio e librerie) o a riga di AWS comando (CLI) a cui inviare richieste AWS API, puoi saltare questa sezione perché i client SDK e CLI autenticano le tue richieste utilizzando le chiavi di accesso che fornisci. A meno che tu non abbia una buona ragione per non farlo, ti consigliamo di utilizzare sempre un SDK o una CLI.

Nelle regioni che supportano più versioni di firma, per le richieste di firma manuale è necessario specificare quale versione della firma viene utilizzata. Quando utilizzi punti di accesso multi-regione, gli SDK e le CLI vengono commutate automaticamente per utilizzare Signature Version 4A senza ulteriori configurazioni.

Di seguito è riportata una panoramica del processo per creare una richiesta firmata. Per calcolare una firma, occorre una stringa da firmare. Quindi calcoli un hash HMAC-SHA256 della stringa da firmare utilizzando una chiave di firma. Il diagramma seguente illustra il processo, inclusi i vari componenti della stringa che hai creato per la firma.

Un'immagine delle parti di una richiesta canonica, inclusa la stringa da firmare, la chiave di firma e la firma.

La tabella seguente descrive le funzioni mostrate nel diagramma. Per queste funzioni devi implementare il codice. Per ulteriori informazioni, consulta gli esempi di codice negli SDK. AWS

Funzione Descrizione

Lowercase()

Converte la stringa in minuscolo.

Hex()

Codifica in base 16 minuscola.

SHA256Hash()

Funzione hash crittografica Secure Hash Algorithm (SHA).

HMAC-SHA256()

Calcola HMAC utilizzando l'algoritmo SHA256 con la chiave di firma fornita. Questa è la firma definitiva.

Trim()

Rimuove eventuali spazi bianchi all’inizio o alla fine della stringa.

UriEncode()

L'URI codifica ogni byte. UriEncode() deve applicare le seguenti regole:

  • L'URI codifica ogni byte tranne i caratteri senza riserve: 'A'-'Z', 'a'-'z', '0'-'9', '-', ' . ','_' e '~'.

  • Il carattere di spazio è un carattere riservato e deve essere codificato come "%20" (e non come "+").

  • Ogni byte codificato in URI è formato da una '%' e dal valore esadecimale a due cifre del byte.

  • Le lettere nel valore esadecimale devono essere maiuscole, ad esempio "%1A".

  • Codifica la barra, '/', ovunque tranne nel nome della chiave dell'oggetto. Ad esempio, se il nome della chiave dell'oggetto è photos/Jan/sample.jpg, la barra nel nome della chiave non è codificata.

Importante

Le UriEncode funzioni standard fornite dalla piattaforma di sviluppo potrebbero non funzionare a causa delle differenze di implementazione e della relativa ambiguità nelle RFC sottostanti. Ti consigliamo di scrivere una UriEncode funzione personalizzata per assicurarti che la codifica funzioni.

Per vedere un esempio di UriEncode funzione in Java, consulta Java Utilities sul GitHub sito Web.

Nota

Quando firmi le tue richieste, puoi utilizzare AWS Signature Version 4 o AWS Signature Version 4A. La differenza fondamentale tra le due versioni è determinata dalla modalità di calcolo della firma. Con AWS Signature Version 4A, la firma non include informazioni specifiche della regione e viene calcolata utilizzando l'algoritmo. AWS 4-ECDSA-P256-SHA256

Credenziali di sicurezza temporanee

Invece di utilizzare credenziali a lungo termine per firmare una richiesta, è possibile utilizzare credenziali di sicurezza temporanee fornite da (). AWS Security Token Service AWS STS

Quando si utilizzano credenziali di sicurezza temporanee, è necessario aggiunge X-Amz-Security-Token all'intestazione di autorizzazione o alla stringa di query per contenere il token di sessione. Alcuni servizi richiedono l'aggiunta di X-Amz-Security-Token alla richiesta canonica. Per gli altri servizi, aggiungi il parametro X-Amz-Security-Token alla fine, dopo aver calcolato la firma. Per i dettagli, consulta la documentazione relativa a ciascuna Servizio AWS di esse.

Riepilogo delle fasi di firma

Fase 1: creazione di una richiesta canonica

Disponi i contenuti della tua richiesta (host, operazione, intestazioni, ecc.) in un formato standard (canonico). La richiesta canonica è uno degli input utilizzati per creare una stringa di firma. Per informazioni dettagliate, vedi Elementi della firma di una richiesta AWS API.

Fase 2: creazione di un hash della richiesta canonica

Ricava una chiave di firma eseguendo una serie di operazioni hash con chiave (operazioni HMAC) nella data, nella regione e nel servizio della richiesta, utilizzando la chiave di accesso AWS segreta come chiave per l'operazione di hashing iniziale.

Fase 3: creazione di una stringa da firmare

Crea una stringa di firma con la richiesta canonica e informazioni aggiuntive, ad esempio l'algoritmo, la data della richiesta, l'ambito delle credenziali e il digest (hash) della richiesta canonica.

Fase 4: calcolo della firma

Dopo avere ottenuto la chiave di firma, puoi calcolare la firma eseguendo un'operazione hash con chiave sulla stringa di firma. Usa la chiave di firma derivata come chiave hash per questa operazione.

Fase 5: aggiunta della firma alla richiesta.

Dopo aver calcolato la firma, aggiungila a un'intestazione HTTP o alla stringa di query della richiesta.

Fase 1: creazione di una richiesta canonica

Crea una richiesta canonica concatenando le seguenti stringhe, separate da caratteri di nuova riga. Questo aiuta a garantire che la firma calcolata e la firma calcolata possano corrispondere. AWS

<HTTPMethod>\n <CanonicalURI>\n <CanonicalQueryString>\n <CanonicalHeaders>\n <SignedHeaders>\n <HashedPayload>
  • HTTPMethod - I metodi HTTP, come GET, PUT, HEAD, e DELETE.

  • CanonicalUri— La versione con codifica URI dell'URI del componente del percorso assoluto, che inizia con «/» che segue il nome di dominio e fino alla fine della stringa o fino al punto interrogativo ('?') se disponi di parametri della stringa di query. Se il percorso assoluto è vuoto, usa una barra (/). L'URI nell'esempio seguente, /examplebucket/myphoto.jpg, è il percorso assoluto e non devi codificare "/" nel percorso assoluto:

    http://s3.amazonaws.com/examplebucket/myphoto.jpg
  • CanonicalQueryString— I parametri della stringa di query con codifica URI. Ogni nome e ogni valore vengono codificati singolarmente tramite URI. È inoltre necessario ordinare i parametri nella stringa di query canonica in ordine alfabetico in base al nome della chiave. L'ordinamento avviene dopo la codifica. La stringa di query nell'esempio di URI seguente è:

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

    La stringa di query canonica è la seguente (le interruzioni di riga vengono aggiunte a questo esempio a fini di leggibilità):

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

    Quando una richiesta ha come target una sottorisorsa, il valore del parametro di query corrispondente sarà una stringa vuota (""). Ad esempio, il seguente URI identifica la sottorisorsa ACL sul bucket examplebucket:

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

    CanonicalQueryString In questo caso è il seguente:

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

    Se l'URI non include un '?', la richiesta non contiene una stringa di query e occorre impostare la stringa di query canonica su una stringa vuota (""). Dovrai comunque includere "\n".

  • CanonicalHeaders— Un elenco di intestazioni di richiesta con i relativi valori. Le singole coppie di nome e valore dell'intestazione sono separate dal carattere di nuova riga ("\n"). Di seguito è riportato un esempio di canonicalheader:

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

    CanonicalHeaders l'elenco deve includere quanto segue:

    • Intestazione host HTTP.

    • Se l'Content-Typeintestazione è presente nella richiesta, è necessario aggiungerla all'CanonicalHeaderselenco.

    • Devi aggiungere anche qualsiasi intestazione x-amz-* che desideri includere nella richiesta. Ad esempio, se utilizzi credenziali di sicurezza temporanee, nella tua richiesta devi includere x-amz-security-token. È necessario aggiungere questa intestazione nell'elenco di. CanonicalHeaders

    Nota

    L'x-amz-content-sha256intestazione è necessaria per le richieste Amazon AWS S3. Fornisce un hash del payload di richiesta. Se non è presente alcun payload, devi indicare l'hash di una stringa vuota.

    Il nome di ogni intestazione deve:

    • usare caratteri minuscoli.

    • in ordine alfabetico.

    • seguiti da due punti (:).

    Per i valori, devi:

    • eliminare eventuali spazi all’inizio o alla fine.

    • convertire gli spazi sequenziali in uno spazio singolo.

    • separare i valori per un'intestazione multivalore con virgole.

    • Nella firma devi includere l'intestazione dell’host  (HTTP/1.1) o l'intestazione :authority  (HTTP/2) e tutte le intestazioni x-amz-*. Facoltativamente puoi includere altre intestazioni standard nella firma, ad esempio content-type.

    Le funzioni Lowercase() e Trim() utilizzate in questo esempio sono descritte nella sezione precedente.

    Di seguito è riportata una stringa CanonicalHeaders di esempio. I nomi di intestazione sono in caratteri minuscoli e in ordine alfabetico.

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

    Nota

    Ai fini del calcolo di una firma di autorizzazione, sono richiesti solo l'host e qualsiasi altra intestazione x-amz-*; tuttavia, per evitare la manomissione dei dati, nel calcolo della firma è consigliabile includere tutte le intestazioni.

  • SignedHeaders— Un elenco in ordine alfabetico e separati da punto e virgola di nomi di intestazioni di richiesta in lettere minuscole. Le intestazioni della richiesta nell'elenco sono le stesse che hai incluso nella stringa CanonicalHeaders. Ad esempio, per l'esempio precedente, il valore di sarebbe il seguente: SignedHeaders

    host;x-amz-content-sha256;x-amz-date
  • HashedPayload— Una stringa creata utilizzando il payload nel corpo della richiesta HTTP come input per una funzione hash. Questa stringa utilizza caratteri esadecimali minuscoli.

    Hex(SHA256Hash(<payload>)

    Se non è presente alcun payload nella richiesta, calcola un hash della stringa vuota come segue:

    Hex(SHA256Hash(""))

    L’hash restituisce i seguenti valori:

    e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

    Ad esempio, quando carichi un oggetto utilizzando una richiesta PUT, fornisci i dati dell'oggetto nel corpo. Quando recuperi un oggetto utilizzando una richiesta GET, calcoli l'hash della stringa vuota.

Fase 2: creazione di un hash della richiesta canonica

Crea un hash (digest) della richiesta canonica con lo stesso algoritmo utilizzato per creare l'hash del payload. L'hash della richiesta canonica è una stringa di caratteri esadecimali minuscoli.

Fase 3: creazione di una stringa da firmare

Crea una richiesta concatenando le seguenti stringhe, separate da caratteri di nuova riga. Non terminare questa stringa con un carattere di nuova riga.

Algorithm \n RequestDateTime \n CredentialScope \n HashedCanonicalRequest
  • Algorithm: l'algoritmo utilizzato per creare l'hash della richiesta canonica. Per SHA-256, l'algoritmo è AWS4-HMAC-SHA256.

  • RequestDateTime— La data e l'ora utilizzate nell'ambito delle credenziali. Questo valore è l'ora UTC corrente in formato ISO 8601 (ad esempio,20130524T000000Z).

  • CredentialScope— L'ambito delle credenziali. Ciò limita la firma risultante alla regione e al servizio specificati. La stringa ha il seguente formato: AAAAMMGG/regione/servizio/aws4_request.

  • HashedCanonicalRequest— L'hash della richiesta canonica. Questo valore viene calcolato nella fase 2.

Di seguito è riportata una stringa di esempio da firmare.

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

Fase 4: calcolo della firma

Nella versione 4 di AWS Signature, invece di utilizzare le chiavi di AWS accesso per firmare una richiesta, crei una chiave di firma valida per una regione e un servizio specifici come informazioni di autenticazione da aggiungere alla richiesta.

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

Per un elenco dei codici delle regioni, consulta la pagina Endpoint regionali nei AWS Riferimenti generali .

Per ogni passaggio, richiama la funzione hash con la chiave e i dati richiesti. Il risultato di ogni chiamata alla funzione hash diventa l'input per la chiamata successiva alla funzione.

Input richiesto
  • Una stringa, Key, che contiene la tua chiave di accesso segreta

  • Una stringa, Date, che contiene la data utilizzata nell'ambito delle credenziali, nel formato AAAAMMGG

  • Una stringa, Region, che contiene il codice della regione (ad esempio, us-east-1)

  • Una stringa, Service, che contiene il codice del servizio (ad esempio, ec2)

  • La stringa da firmare creata nel passaggio precedente.

Calcolo della firma
  1. Concatena "AWS4" e la chiave di accesso segreta. Chiama la funzione hash con la stringa concatenata come stringa di chiave e data come dati.

    kDate = hash("AWS4" + Key, Date)
  2. Chiama la funzione hash con il risultato della chiamata precedente come stringa di chiave e regione come dati.

    kRegion = hash(kDate, Region)
  3. Chiama la funzione hash con il risultato della chiamata precedente come stringa di chiave e servizio come dati.

    kService = hash(kRegion, Service)
  4. Chiama la funzione hash con il risultato della chiamata precedente come chiave e "aws4_request" come dati.

    kSigning = hash(kService, "aws4_request")
  5. Chiama la funzione hash con il risultato della chiamata precedente come chiave e stringa da firmare come dati. Il risultato è la firma come valore binario.

    signature = hash(kSigning, string-to-sign)
  6. Converti la firma da rappresentazione binaria a esadecimale, in caratteri minuscoli.

Fase 5: aggiunta della firma alla richiesta.

Esempio: intestazione di autorizzazione

Nell'esempio seguente viene mostrata una intestazione Authorization per l'operazione DescribeInstances. Per motivi di leggibilità, questo esempio è formattato con interruzioni di riga. Nel tuo codice, deve essere una stringa continua. Non vi è alcun virgola tra l'algoritmo e Credential. Tuttavia, gli altri elementi devono essere separati da virgole.

Authorization: AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20220830/us-east-1/ec2/aws4_request, SignedHeaders=host;x-amz-date, Signature=calculated-signature
Esempio: richiesta con parametri di autenticazione nella stringa di query

L'esempio seguente mostra una query per l'operazione DescribeInstances che include le informazioni di autenticazione. Per motivi di leggibilità, questo esempio è formattato con interruzioni di riga e non è codificato con l'URL. Nel codice, la stringa di query deve essere una stringa continua con codifica 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

Codice sorgente negli SDK AWS

Gli AWS SDK includono il codice sorgente GitHub per la firma delle richieste AWS API. Per alcuni esempi di codice, consulta Progetti di esempio nell'archivio di AWS esempi