Creación de una solicitud de API de AWS firmada - AWS Identity and Access Management

Creación de una solicitud de API de AWS firmada

importante

Si utiliza un SDK de AWS (consulte Bibliotecas y código de muestra) o la herramienta de AWS Command Line Interface (AWS CLI) para enviar solicitudes de API a AWS, puede omitir esta sección porque los clientes del SDK y la CLI autentican sus solicitudes mediante las claves de acceso que les proporciona. A menos que tenga una razón específica para no hacerlo, le recomendamos que utilice siempre un SDK o la CLI.

En las regiones en las que se admiten varias versiones de firma, las solicitudes de firma manual significan que debe especificar qué versión de firma se utiliza. Cuando envía solicitudes a puntos de acceso de varias regiones, los SDK y la CLI cambian de forma automática a Signature Version 4A sin configuración adicional.

Puede utilizar el protocolo de firma de AWS SigV4 a fin de crear una solicitud firmada para las solicitudes de API de AWS.

  1. Crear una solicitud canónica en función de los detalles de la solicitud.

  2. Calcular una firma con sus credenciales de AWS.

  3. Agregar esta firma a la solicitud como encabezado de autorización.

Luego, AWS replica este proceso y verifica la firma, concediendo o denegando el acceso en consecuencia.

Para conocer cómo puede utilizar AWS SigV4 para firmar solicitudes de API, consulte Ejemplos de firmas de solicitudes.

En el siguiente diagrama se ilustra el proceso de firma de SigV4, incluidos los distintos componentes de la cadena que se crea para la firma.

Una imagen de las partes de una solicitud canónica, cadena para firmar, clave de firma y firma.

En la siguiente tabla, se describen las funciones que se muestran en el diagrama. Debe implementar código para estas funciones. Para obtener más información, consulte ejemplos de código en los SDK de AWS.

Función Descripción

Lowercase()

Convierta la cadena de caracteres en minúsculas.

Hex()

Codificación en minúsculas en base 16.

SHA256Hash()

Función de hash criptográfico del algoritmo de hash seguro (SHA).

HMAC-SHA256()

Calcula el HMAC mediante el algoritmo SHA256 con la clave de firma proporcionada. Esta es la firma final.

Trim()

Elimine cualquier espacio en blanco inicial o final.

UriEncode()

El URI codifica cada byte. UriEncode() debe aplicar las siguientes reglas:

  • El URI codifica todos los bytes excepto los caracteres no reservados: “A”-“Z”, “a”-“z”, “0”-“9”, “-”, “.”, “_” y “~”.

  • El carácter de espacio es un carácter reservado y debe codificarse como “%20” (y no como “+”).

  • Cada byte codificado en URI se encuentra formado por un “%” y el valor hexadecimal de dos dígitos del byte.

  • Las letras del valor hexadecimal deben estar en mayúsculas, por ejemplo, “%1A”.

  • Codifique el carácter de barra diagonal, “/”, en todas partes excepto en el nombre de la clave del objeto. Por ejemplo, si el nombre de la clave del objeto es photos/Jan/sample.jpg, la barra diagonal del nombre de la clave no se encuentra codificada.

importante

Es posible que las funciones estándar de UriEncode que proporciona su plataforma de desarrollo no funcionen debido a las diferencias en la implementación y a la ambigüedad relacionada en las RFC subyacentes. Le recomendamos que escriba su propia función UriEncode personalizada para asegurarse de que la codificación funcione.

Para ver un ejemplo de una función UriEncode en Java, consulte Utilidades de Java en el sitio web de GitHub.

nota

Al firmar sus solicitudes, puede utilizar cualquiera de las siguientes opciones: AWS Signature Version 4 o AWS Signature Version 4A. La diferencia clave entre las dos se determina por la forma en que se calcula la firma. Con AWS Signature Version 4A, la firma no incluye información específica de la región y se calcula mediante el algoritmo AWS4-ECDSA-P256-SHA256.

Solicitudes de firma con credenciales de seguridad temporales

En lugar de utilizar credenciales de larga duración para firmar una solicitud, puede utilizar las credenciales de seguridad temporales proporcionadas por AWS Security Token Service (AWS STS).

Cuando utilice credenciales de seguridad temporales, debe agregar X-Amz-Security-Token al encabezado de autorización o incluirlo a la cadena de consulta para contener el token de sesión. Algunos servicios requieren que agregue X-Amz-Security-Token a la solicitud canónica. Otros servicios requieren que solo agregue X-Amz-Security-Token al final, después de calcular la firma. Consulte la documentación de cada servicio de AWS para conocer los requisitos específicos.

Resumen de pasos de firma

Cree una solicitud canónica:

Organice el contenido de la solicitud (host, acción, encabezados, etc.) en un formato canónico estándar. La solicitud canónica es uno de los datos de entrada utilizados con el fin de crear la cadena para firmar. Para obtener detalles sobre cómo crear la solicitud canónica, consulte Elementos de una firma de solicitud a la API de AWS.

Crear un hash de la solicitud canónica

Cree un hash de la solicitud canónica con el mismo algoritmo que utilizó para crear el hash de la carga. El hash de la solicitud canónica es una cadena de caracteres hexadecimales en minúsculas.

Crear una cadena para firmar

Cree una cadena para firmar con la solicitud canónica e información adicional, como el algoritmo, la fecha de la solicitud, el ámbito de la credencial y el hash de la solicitud canónica.

Generar una clave de firma

Lleve a cabo una sucesión de operaciones hash con clave (HMAC) en la fecha de la solicitud, la región y el servicio, con su clave de acceso secreta de AWS como clave de la operación hash inicial.

Calcular la firma

Lleve a cabo una operación hash con clave (HMAC) en la cadena para firmar con la clave de firma generada como clave de hash.

Agregar la firma a la solicitud

Agregue la firma calculada a un encabezado HTTP o a la cadena de consulta de la solicitud.

Crear una solicitud canónica

Para crear una solicitud canónica, concatene las siguientes cadenas, separadas por caracteres de nueva línea. Esto ayuda a garantizar que la firma que calcula pueda coincidir con la firma que calcula AWS.

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

  • CanonicalUri: la versión codificada en URI del componente de ruta absoluta, que comienza con la / que sigue al nombre de dominio y continúa hasta el final de la cadena o del signo de interrogación (?) si tiene parámetros de cadena de consulta. Si la ruta absoluta está vacía, utilice un carácter de barra diagonal (/). El URI del siguiente ejemplo, /examplebucket/myphoto.jpg, es la ruta absoluta y no se codifica la / en la ruta absoluta:

    http://s3.amazonaws.com/examplebucket/myphoto.jpg
  • CanonicalQueryString: los parámetros de la cadena de consulta codificados en URI. Codifique en URI cada nombre y valor de forma individual. También debe ordenar los parámetros de la cadena de consulta canónica alfabéticamente por nombre de clave. La clasificación se produce después de la codificación. La cadena de consulta del siguiente ejemplo de URI es:

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

    La cadena de consulta canónica es la siguiente (se agregan saltos de línea a este ejemplo para facilitar la lectura):

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

    Cuando una solicitud se dirige a un subrecurso, el valor del parámetro de consulta correspondiente será una cadena vacía (""). Por ejemplo, el siguiente URI identifica el subrecurso ACL en el bucket examplebucket:

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

    En este caso, la cadena CanonicalQueryString sería:

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

    Si el URI no incluye un ?, no hay ninguna cadena de consulta en la solicitud y establece la cadena de consulta canónica en una cadena vacía (""). Aún tendrá que incluir el carácter de nueva línea ("\n").

  • CanonicalHeaders: una lista de los encabezados de las solicitudes con sus valores. Los pares individuales de nombre y valor del encabezado se encuentran separados por el carácter de nueva línea ("\n"). El siguiente es un ejemplo de un CanonicalHeader:

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

    La lista CanonicalHeaders debe incluir lo siguiente:

    • Encabezado de host HTTP.

    • Si el encabezado Content-Type se encuentra en la solicitud, debe agregarlo a la lista CanonicalHeaders.

    • También debe agregar cualquier encabezado x-amz-* que planea incluir en su solicitud. Por ejemplo, si utiliza credenciales de seguridad temporales, debe incluir x-amz-security-token en su solicitud. Debe agregar este encabezado a la lista de CanonicalHeaders.

    nota

    El encabezado x-amz-content-sha256 es obligatorio para las solicitudes de AWS de Amazon S3. Proporciona un hash de la carga de solicitud. Si no hay ninguna carga, debe proporcionar el hash de una cadena vacía.

    Cada nombre de encabezado debe:

    • tener caracteres en minúsculas;

    • aparecer en orden alfabético;

    • ir seguido de dos puntos (:).

    En el caso de los valores, debe:

    • recortar los espacios iniciales o finales;

    • convertir espacios secuenciales en un solo espacio;

    • separar los valores de un encabezado con varios valores mediante comas.

    • Debe incluir el encabezado de host (HTTP/1.1) o el encabezado :authority (HTTP/2) y cualquier encabezado x-amz-* de la firma. Si lo desea, puede incluir otros encabezados estándar en la firma, como content-type.

    Las funciones Lowercase() y Trim() que se utilizan en este ejemplo se describen en la sección anterior.

    La siguiente es una cadena de CanonicalHeaders de ejemplo. Los nombres de encabezado se encuentran en minúsculas y ordenados.

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

    nota

    Para calcular una firma de autorización, solo se requieren el host y cualquier encabezado x-amz-*; sin embargo, a fin de evitar la manipulación de datos, debería considerar la posibilidad de incluir todos los encabezados en el cálculo de la firma.

  • SignedHeaders: una lista ordenada alfabéticamente y separada por punto y coma de nombres de encabezados de solicitudes en minúsculas. Los encabezados de las solicitudes de la lista son los mismos que incluyó en la cadena de CanonicalHeaders. En el caso anterior, el valor de SignedHeaders sería el siguiente:

    host;x-amz-content-sha256;x-amz-date
  • HashedPayload: una cadena creada con la carga del cuerpo de la solicitud HTTP como entrada para una función de hash. Esta cadena utiliza caracteres hexadecimales en minúscula.

    Hex(SHA256Hash(<payload>>))

    Si no hay ninguna carga en la solicitud, se calcula un hash de la cadena vacía, por ejemplo, cuando se recupera un objeto mediante una solicitud GET, no hay nada en la carga.

    Hex(SHA256Hash(""))
    nota

    En el caso de Amazon S3, incluya la cadena literal UNSIGNED-PAYLOAD al crear una solicitud canónica y establezca el mismo valor que el valor del encabezado x-amz-content-sha256 al enviar la solicitud.

    Hex(SHA256Hash("UNSIGNED-PAYLOAD"))

Crear un hash de la solicitud canónica

Cree un hash (resumen) de la solicitud canónica con el mismo algoritmo que utilizó para crear el hash de la carga. El hash de la solicitud canónica es una cadena de caracteres hexadecimales en minúsculas.

Crear una cadena para firmar

A fin de crear una cadena para firmar, concatene las siguientes cadenas, separadas por caracteres de nueva línea. No termine esta cadena con un carácter de nueva línea.

Algorithm \n RequestDateTime \n CredentialScope \n HashedCanonicalRequest
  • Algorithm: el algoritmo utilizado para crear el hash de la solicitud canónica. Para SHA-256, el algoritmo es AWS4-HMAC-SHA256.

  • RequestDateTime: la fecha y la hora utilizadas en el alcance de la credencial. Este valor es la hora UTC actual en formato ISO 8601 (por ejemplo, 20130524T000000Z).

  • CredentialScope: el ámbito de la credencial, que restringe la firma resultante a la región y el servicio especificados. La cadena tiene el siguiente formato:YYYYMMDD/region/service/aws4_request.

  • HashedCanonicalRequest: el hash de la solicitud canónica, calculado en el paso anterior.

La siguiente es una cadena de ejemplo para firmar.

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

Generar una clave de firma

Para generar una clave de firma, lleve a cabo una sucesión de operaciones hash con clave (HMAC) en la fecha de la solicitud, la región y el servicio, con su clave de acceso secreta de AWS como clave de la operación hash inicial.

Para cada paso, llame a la función de hash con la clave y los datos necesarios. El resultado de cada llamada a la función de hash se convierte en la entrada de la siguiente llamada a la función de hash.

En el siguiente ejemplo, se muestra cómo se genera la SigningKey que se utiliza en la siguiente sección de este procedimiento y se muestra el orden en el que se concatena y se codifica la entrada. HMAC-SHA256 es la función hash que se utiliza para codificar los datos, tal como se muestra.

DateKey = HMAC-SHA256("AWS4"+"<SecretAccessKey>", "<YYYYMMDD>") DateRegionKey = HMAC-SHA256(<DateKey>, "<aws-region>") DateRegionServiceKey = HMAC-SHA256(<DateRegionKey>, "<aws-service>") SigningKey = HMAC-SHA256(<DateRegionServiceKey>, "aws4_request")
Datos de ingreso obligatorios
  • Key, una cadena que contiene su clave de acceso secreta.

  • Date, una cadena que contiene la fecha utilizada en el alcance de la credencial con el formato AAAAMMDD.

  • Region, una cadena que contiene el código de región (por ejemplo, us-east-1).

    Para obtener una lista de cadenas de región, consulte Puntos de conexión regionales en la Referencia general de AWS.

  • Service, una cadena que contiene el código de servicio (por ejemplo, ec2).

  • La cadena para firmar que creó en el paso anterior.

Para generar una clave de firma
  1. Concatene "AWS4" y la clave de acceso secreta. Llame a la función de hash con la cadena concatenada como clave y la cadena de fecha como datos.

    DateKey = hash("AWS4" + Key, Date)
  2. Llame a la función de hash con el resultado de la llamada anterior como clave y la cadena de región como datos.

    DateRegionKey = hash(kDate, Region)
  3. Llame a la función de hash con el resultado de la llamada anterior como clave y la cadena de servicio como datos.

    El servicio define el código de servicio. Puede utilizar get-products en la CLI de precios de AWS para devolver el código de servicio de un servicio.

    DateRegionServiceKey = hash(kRegion, Service)
  4. Llame a la función de hash con el resultado de la llamada anterior como clave y “aws4_request” como datos.

    SigningKey = hash(kService, "aws4_request")

Calcular la firma

Una vez que se ha generado la clave de firma, se calcula la firma al llevar a cabo una operación hash con clave en la cadena para firmar. Utilice la clave de firma generada como clave hash para esta operación.

Para calcular una firma
  1. Llame a la función de hash con el resultado de la llamada anterior como clave y la cadena para firmar como datos. El resultado es la firma como valor binario.

    signature = hash(SigningKey, string-to-sign)
  2. Convierta la firma de representación binaria a hexadecimal, en caracteres en minúsculas.

Agregar la firma a la solicitud

Agregue la firma calculada a su solicitud.

ejemplo Ejemplo: encabezado de autorización

En el ejemplo siguiente se muestra un encabezado Authorization para la acción DescribeInstances. Para facilitar la lectura, este ejemplo está formateado con saltos de línea. En su código, debe ser una cadena continua. No hay ninguna coma entre el algoritmo y Credential. Sin embargo, los demás elementos deben ir separados por comas.

Authorization: AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20220830/us-east-1/ec2/aws4_request, SignedHeaders=host;x-amz-date, Signature=calculated-signature
ejemplo Ejemplo: solicitud con parámetros de autenticación en la cadena de consulta

En el siguiente ejemplo, se muestra una consulta para la acción DescribeInstances que incluye la información de autenticación. Para facilitar la lectura, este ejemplo está formateado con saltos de línea y no está codificado en URL. En el código, la cadena de consulta debe ser una cadena continua codificada 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