Uso de autorizadores Lambda de API Gateway - Amazon API Gateway

Uso de autorizadores Lambda de API Gateway

Un autorizador de Lambda (que anteriormente se denominaba autorizador personalizado) es una característica de API Gateway que utiliza una función de Lambda para controlar el acceso a su API.

Un autorizador de Lambda resulta útil si desea implementar un esquema de autorización personalizado que utiliza una estrategia de autenticación de token al portador como OAuth o SAML, o que utiliza los parámetros de la solicitud para determinar la identidad del intermediario.

Cuando un cliente realiza una solicitud a uno de los métodos de la API, API Gateway llama a su autorizador de Lambda, que toma la identidad del intermediario como entrada y devuelve una política de IAM como salida.

Hay dos tipos de autorizadores Lambda:

  • Un autorizador de Lambda basado en token (también llamado autorizador TOKEN) recibe la identidad del intermediario en un token al portador, como, por ejemplo, un JSON Web Token (JWT) o un token de OAuth. Para ver una aplicación de ejemplo, consulte Open Banking Brazil - Ejemplos de autorización en GitHub.

  • Un autorizador de Lambda basado en parámetros de solicitud (también denominado autorizador de REQUEST) recibe la identidad de la persona que llama en una combinación de encabezados, parámetros de cadenas de consulta, stageVariables y variables de $context.

    Para las API de WebSocket, solo se admiten los autorizadores basados en parámetros de la solicitud.

Se puede utilizar una función de AWS Lambda de una cuenta de AWS distinta a aquella en la creó su API. Para obtener más información, consulte Configuración de un autorizador de Lambda entre cuentas.

Para ver ejemplos de funciones Lambda, consulte aws-apigateway-lambda-authorizer-blueprints en GitHub.

Flujo de trabajo de autorización para autorizadores de Lambda

El siguiente diagrama ilustra el flujo de trabajo de autorización para autorizadores de Lambda.


        Flujo de trabajo de autorización de Lambda en API Gateway
Flujo de trabajo de autorización de Lambda en API Gateway
  1. El cliente llama a un método en un método de la API de API Gateway, pasando un token al portador o parámetros de solicitud.

  2. API Gateway comprueba si hay configurado un autorizador de Lambda para el método. Si es así, API Gateway llama a la función de Lambda.

  3. La función de Lambda autentica al intermediario mediante métodos como los siguientes:

    • Llamando a un proveedor de OAuth para obtener un token de acceso OAuth.

    • Llamando a un proveedor de SAML para obtener una aserción SAML.

    • Generando una política de IAM basada en los valores de los parámetros de la solicitud.

    • Recuperando credenciales de una base de datos.

  4. Si la llamada se realiza correctamente, la función de Lambda concede acceso devolviendo un objeto de salida que contiene al menos una política de IAM y un identificador principal.

  5. API Gateway evalúa la política.

    • Si se deniega el acceso, API Gateway devuelve un código de estado HTTP apropiado, como por ejemplo 403 ACCESS_DENIED.

    • Si se permite el acceso, API Gateway ejecuta el método. Si el almacenamiento en caché está habilitado en la configuración de autorizador, API Gateway también almacena en caché la política de modo que no es necesario volver a invocar la función del autorizador de Lambda.

Pasos para crear un autorizador de Lambda de API Gateway

Para crear un autorizador de Lambda, debe realizar las siguientes tareas:

  1. Cree la función del autorizador de Lambda en la consola de Lambda tal y como se describe en Crear una función del autorizador de Lambda de API Gateway en la consola de Lambda.. Puede utilizar uno de los ejemplos de proyecto como punto de partida y personalizar la entrada y salida como desee.

  2. Configure la función de Lambda como un autorizador de API Gateway y configurar un método de API para exigirlo tal y como se describe en Configuración de un autorizador de Lambda mediante la consola de API Gateway. Por otro lado, si necesita un autorizador de Lambda entre cuentas, consulte Configuración de un autorizador de Lambda entre cuentas.

    nota

    También puede configurar un autorizador con la AWS CLI o un AWS SDK.

  3. Pruebe el autorizador mediante Postman, tal y como se describe en Llamada a una API con autorizadores de Lambda de API Gateway.

Crear una función del autorizador de Lambda de API Gateway en la consola de Lambda.

Antes de configurar un autorizador de Lambda, en primer lugar debe crear la función de Lambda que implemente la lógica para autorizar y, si es necesario, autenticar al intermediario. La consola de Lambda ofrece un proyecto de Python, que se puede utilizar eligiendo Use a blueprint (Utilizar un proyecto) y eligiendo el proyecto api-gateway-authorizer-python. De lo contrario, deberá utilizar uno de los proyectos en el repositorio de GitHub awslabs como punto de partida.

Para las funciones del autorizador de Lambda de ejemplo en esta sección, que no llaman a otros servicios, puede utilizar el integrado AWSLambdaBasicExecutionRole. Al crear la función de Lambda para el autorizador de Lambda de API Gateway, tendrá que asignar un rol de ejecución de IAM para la función de Lambda si esta llama a otros servicios de AWS. Para crear el rol, siga las instrucciones de Rol de ejecución de AWS Lambda.

Para ver más ejemplos de funciones de Lambda, consulte aws-apigateway-lambda-authorizer-blueprints en GitHub. Para ver una aplicación de ejemplo, consulte Open Banking Brazil - Ejemplos de autorización en GitHub.

EJEMPLO: Crear una función de autorizador de Lambda basada en tokens

Para crear una función de autorizador de Lambda basada en tokens, ingrese el siguiente código Node.js para el tiempo de ejecución más reciente en la consola de Lambda. A continuación, pruebe el autorizador en la consola de API Gateway.

Para crear la función de un autorizador de Lambda basado en token
  1. En la consola de Lambda, elija Create function (Crear función).

  2. Elija Author from scratch.

  3. Escriba el nombre de la función.

  4. En Tiempo de ejecución, elija el último tiempo de ejecución de Node.js o Python compatible.

  5. Elija Create function (Crear función).

  6. Copie y pegue el siguiente código en el editor de códigos.

    Node.js
    // A simple token-based authorizer example to demonstrate how to use an authorization token // to allow or deny a request. In this example, the caller named 'user' is allowed to invoke // a request if the client-supplied token value is 'allow'. The caller is not allowed to invoke // the request if the token value is 'deny'. If the token value is 'unauthorized' or an empty // string, the authorizer function returns an HTTP 401 status code. For any other token value, // the authorizer returns an HTTP 500 status code. // Note that token values are case-sensitive. export const handler = function(event, context, callback) { var token = event.authorizationToken; switch (token) { case 'allow': callback(null, generatePolicy('user', 'Allow', event.methodArn)); break; case 'deny': callback(null, generatePolicy('user', 'Deny', event.methodArn)); break; case 'unauthorized': callback("Unauthorized"); // Return a 401 Unauthorized response break; default: callback("Error: Invalid token"); // Return a 500 Invalid token response } }; // Help function to generate an IAM policy var generatePolicy = function(principalId, effect, resource) { var authResponse = {}; authResponse.principalId = principalId; if (effect && resource) { var policyDocument = {}; policyDocument.Version = '2012-10-17'; policyDocument.Statement = []; var statementOne = {}; statementOne.Action = 'execute-api:Invoke'; statementOne.Effect = effect; statementOne.Resource = resource; policyDocument.Statement[0] = statementOne; authResponse.policyDocument = policyDocument; } // Optional output with custom properties of the String, Number or Boolean type. authResponse.context = { "stringKey": "stringval", "numberKey": 123, "booleanKey": true }; return authResponse; }
    Python
    # A simple token-based authorizer example to demonstrate how to use an authorization token # to allow or deny a request. In this example, the caller named 'user' is allowed to invoke # a request if the client-supplied token value is 'allow'. The caller is not allowed to invoke # the request if the token value is 'deny'. If the token value is 'unauthorized' or an empty # string, the authorizer function returns an HTTP 401 status code. For any other token value, # the authorizer returns an HTTP 500 status code. # Note that token values are case-sensitive. import json def lambda_handler(event, context): token = event['authorizationToken'] if token == 'allow': print('authorized') response = generatePolicy('user', 'Allow', event['methodArn']) elif token == 'deny': print('unauthorized') response = generatePolicy('user', 'Deny', event['methodArn']) elif token == 'unauthorized': print('unauthorized') raise Exception('Unauthorized') # Return a 401 Unauthorized response return 'unauthorized' try: return json.loads(response) except: print('unauthorized') return 'unauthorized' # Return a 500 response def generatePolicy(principalId, effect, resource): authResponse = {} authResponse['principalId'] = principalId if (effect and resource): policyDocument = {} policyDocument['Version'] = '2012-10-17' policyDocument['Statement'] = []; statementOne = {} statementOne['Action'] = 'execute-api:Invoke' statementOne['Effect'] = effect statementOne['Resource'] = resource policyDocument['Statement'] = [statementOne] authResponse['policyDocument'] = policyDocument authResponse['context'] = { "stringKey": "stringval", "numberKey": 123, "booleanKey": True } authResponse_JSON = json.dumps(authResponse) return authResponse_JSON
  7. Elija Deploy (Implementar).

Después de crear la función de Lambda, debe crear y probar un autorizador de Lambda basado en token en la consola de API Gateway.

Para crear un autorizador de Lambda basado en token
  1. En la consola de API Gateway, cree una API sencilla si todavía no tiene una.

  2. Elija la API de la lista de API.

  3. Elija Authorizers (Autorizadores).

  4. Elija Crear autorizador.

  5. En Nombre del autorizador, ingrese un nombre.

  6. En Tipo de autorizador, seleccione Lambda.

  7. En Función de Lambda, seleccione la Región de AWS en la que creó la función de autorizador de Lambda y, a continuación, ingrese el nombre de la función.

  8. Mantenga el Rol de invocación de Lambda en blanco.

  9. En Carga de evento de Lambda, seleccione Token.

  10. En Origen de token, escriba authorizationToken.

  11. Elija Crear autorizador.

Para probar el autorizador
  1. Seleccione el nombre del autorizador.

  2. En Probar el autorizador, para el valor authorizationToken, ingrese allow.

  3. Elija Probar el autorizador.

En este ejemplo, cuando la API recibe una solicitud de método, API Gateway pasa el token de origen a esta función de autorizador de Lambda en el atributo event.authorizationToken. La función del autorizador de Lambda lee el token y actúa como se indica a continuación:

  • Si el valor del token es 'allow', la prueba de la función del autorizador devuelve una respuesta HTTP 200 OK y una política de IAM que tiene un aspecto similar al siguiente, y la solicitud del método se lleva a cabo correctamente:

    { "Version": "2012-10-17", "Statement": [ { "Action": "execute-api:Invoke", "Effect": "Allow", "Resource": "arn:aws:execute-api:us-east-1:123456789012:ivdtdhp7b5/ESTestInvoke-stage/GET/" } ] }
  • Si el valor del token es 'deny', la prueba de la función del autorizador devolverá una respuesta HTTP 200 OK y una política Deny de IAM similar a la siguiente y se producirá un error en la solicitud del método:

    { "Version": "2012-10-17", "Statement": [ { "Action": "execute-api:Invoke", "Effect": "Deny", "Resource": "arn:aws:execute-api:us-east-1:123456789012:ivdtdhp7b5/ESTestInvoke-stage/GET/" } ] }
    nota

    Fuera del entorno de prueba, la función del autorizador devolverá una respuesta HTTP 403 Forbidden y la solicitud del método produce un error.

  • Si el valor del token es 'unauthorized' o una cadena vacía, la prueba de la función del autorizador devolverá una respuesta HTTP 401 Unauthorized y la llamada al método producirá un error.

  • Si el token es cualquier otra cosa, el cliente recibirá una respuesta 500 Invalid token y la llamada al método producirá un error.

nota

En el código de producción, es posible que necesite autenticar al usuario antes de conceder la autorización. En tal caso, también puede agregar la lógica de autenticación a la función de Lambda llamando a un proveedor de autenticación como se indica en la documentación de ese proveedor.

Además de devolver una política de IAM, la función del autorizador de Lambda también debe devolver el identificador principal del intermediario. También puede devolver un objeto context, que contiene información adicional que puede pasarse al backend de integración. Para obtener más información, consulte Salida de un autorizador de Lambda de Amazon API Gateway.

EJEMPLO: Crear una función de autorizador de Lambda basada en solicitudes

Para crear una función de autorizador de Lambda basada en solicitudes, ingrese el siguiente código Node.js para el tiempo de ejecución más reciente en la consola de Lambda. A continuación, pruebe el autorizador en la consola de API Gateway.

  1. En la consola de Lambda, elija Create function (Crear función).

  2. Elija Author from scratch.

  3. Escriba el nombre de la función.

  4. En Tiempo de ejecución, elija el último tiempo de ejecución de Node.js o Python compatible.

  5. Elija Create function (Crear función).

  6. Copie y pegue el siguiente código en el editor de códigos.

    Node.js
    // A simple request-based authorizer example to demonstrate how to use request // parameters to allow or deny a request. In this example, a request is // authorized if the client-supplied headerauth1 header, QueryString1 // query parameter, and stage variable of StageVar1 all match // specified values of 'headerValue1', 'queryValue1', and 'stageValue1', // respectively. export const handler = function(event, context, callback) { console.log('Received event:', JSON.stringify(event, null, 2)); // Retrieve request parameters from the Lambda function input: var headers = event.headers; var queryStringParameters = event.queryStringParameters; var pathParameters = event.pathParameters; var stageVariables = event.stageVariables; // Parse the input for the parameter values var tmp = event.methodArn.split(':'); var apiGatewayArnTmp = tmp[5].split('/'); var awsAccountId = tmp[4]; var region = tmp[3]; var restApiId = apiGatewayArnTmp[0]; var stage = apiGatewayArnTmp[1]; var method = apiGatewayArnTmp[2]; var resource = '/'; // root resource if (apiGatewayArnTmp[3]) { resource += apiGatewayArnTmp[3]; } // Perform authorization to return the Allow policy for correct parameters and // the 'Unauthorized' error, otherwise. var authResponse = {}; var condition = {}; condition.IpAddress = {}; if (headers.headerauth1 === "headerValue1" && queryStringParameters.QueryString1 === "queryValue1" && stageVariables.StageVar1 === "stageValue1") { callback(null, generateAllow('me', event.methodArn)); } else { callback("Unauthorized"); } } // Help function to generate an IAM policy var generatePolicy = function(principalId, effect, resource) { // Required output: var authResponse = {}; authResponse.principalId = principalId; if (effect && resource) { var policyDocument = {}; policyDocument.Version = '2012-10-17'; // default version policyDocument.Statement = []; var statementOne = {}; statementOne.Action = 'execute-api:Invoke'; // default action statementOne.Effect = effect; statementOne.Resource = resource; policyDocument.Statement[0] = statementOne; authResponse.policyDocument = policyDocument; } // Optional output with custom properties of the String, Number or Boolean type. authResponse.context = { "stringKey": "stringval", "numberKey": 123, "booleanKey": true }; return authResponse; } var generateAllow = function(principalId, resource) { return generatePolicy(principalId, 'Allow', resource); } var generateDeny = function(principalId, resource) { return generatePolicy(principalId, 'Deny', resource); }
    Python
    # A simple request-based authorizer example to demonstrate how to use request # parameters to allow or deny a request. In this example, a request is # authorized if the client-supplied headerauth1 header, QueryString1 # query parameter, and stage variable of StageVar1 all match # specified values of 'headerValue1', 'queryValue1', and 'stageValue1', # respectively. import json def lambda_handler(event, context): print(event) # Retrieve request parameters from the Lambda function input: headers = event['headers'] queryStringParameters = event['queryStringParameters'] pathParameters = event['pathParameters'] stageVariables = event['stageVariables'] # Parse the input for the parameter values tmp = event['methodArn'].split(':') apiGatewayArnTmp = tmp[5].split('/') awsAccountId = tmp[4] region = tmp[3] restApiId = apiGatewayArnTmp[0] stage = apiGatewayArnTmp[1] method = apiGatewayArnTmp[2] resource = '/' if (apiGatewayArnTmp[3]): resource += apiGatewayArnTmp[3] # Perform authorization to return the Allow policy for correct parameters and the 'Unauthorized' error, otherwise. authResponse = {} condition = {} condition['IpAddress'] = {} if (headers['headerauth1'] == "headerValue1" and queryStringParameters["QueryString1"] == "queryValue1" and stageVariables["StageVal1"] == "stageValue1"): response = generateAllow('me', event['methodArn']) print('authorized') return json.loads(response) else: print('unauthorized') return 'unauthorized' # Help function to generate IAM policy def generatePolicy(principalId, effect, resource): authResponse = {} authResponse['principalId'] = principalId if (effect and resource): policyDocument = {} policyDocument['Version'] = '2012-10-17' policyDocument['Statement'] = []; statementOne = {} statementOne['Action'] = 'execute-api:Invoke' statementOne['Effect'] = effect statementOne['Resource'] = resource policyDocument['Statement'] = [statementOne] authResponse['policyDocument'] = policyDocument authResponse['context'] = { "stringKey": "stringval", "numberKey": 123, "booleanKey": True } authResponse_JSON = json.dumps(authResponse) return authResponse_JSON def generateAllow(principalId, resource): return generatePolicy(principalId, 'Allow', resource) def generateDeny(principalId, resource): return generatePolicy(principalId, 'Deny', resource)
  7. Elija Deploy (Implementar).

Después de crear la función de Lambda, debe crear y probar un autorizador de Lambda basado en solicitudes en la consola de API Gateway.

Para crear un autorizador de Lambda basado en solicitudes
  1. En la consola de API Gateway, cree una API sencilla si todavía no tiene una.

  2. Elija la API de la lista de API.

  3. Elija Authorizers (Autorizadores).

  4. Elija Crear autorizador.

  5. En Nombre del autorizador, ingrese un nombre.

  6. En Tipo de autorizador, seleccione Lambda.

  7. En Función de Lambda, seleccione la Región de AWS en la que creó la función de autorizador de Lambda y, a continuación, ingrese el nombre de la función.

  8. Mantenga el Rol de invocación de Lambda en blanco.

  9. En Carga de evento de Lambda, seleccione Solicitud.

  10. En Tipo de origen de identidades, ingrese lo siguiente:

    1. Seleccione Encabezado e ingrese headerauth1 y, a continuación, elija Agregar parámetro.

    2. En Tipo de origen de identidades, seleccione Cadena de consulta e ingrese QueryString1 y, a continuación, elija Agregar parámetro.

    3. En Tipo de origen de identidades, seleccione Variable de etapa e ingrese StageVar1.

  11. Elija Crear autorizador.

Para probar el autorizador
  1. Seleccione el nombre del autorizador.

  2. En Probar el autorizador, ingrese lo siguiente:

    1. Seleccione Encabezado e ingrese headerValue1 y, a continuación, elija Agregar parámetro.

    2. En Tipo de origen de identidades, seleccione Cadena de consulta e ingrese queryValue1 y, a continuación, elija Agregar parámetro.

    3. En Tipo de origen de identidades, seleccione Variable de etapa e ingrese stageValue1.

  3. Elija Probar el autorizador.

En este ejemplo, la función del autorizador de Lambda comprueba los parámetros de entrada y actúa como se indica a continuación:

  • Si todos los valores de los parámetros necesarios coinciden con los valores previstos, la función del autorizador devuelve una respuesta HTTP 200 OK y una política de IAM que tiene un aspecto similar al siguiente, y la solicitud del método se lleva a cabo correctamente:

    { "Version": "2012-10-17", "Statement": [ { "Action": "execute-api:Invoke", "Effect": "Allow", "Resource": "arn:aws:execute-api:us-east-1:123456789012:ivdtdhp7b5/ESTestInvoke-stage/GET/" } ] }
  • De lo contrario, la función del autorizador devuelve una respuesta HTTP 401 Unauthorized y la llamada al método produce un error.

nota

En el código de producción, es posible que necesite autenticar al usuario antes de conceder la autorización. En tal caso, también puede agregar la lógica de autenticación a la función de Lambda llamando a un proveedor de autenticación como se indica en la documentación de ese proveedor.

Además de devolver una política de IAM, la función del autorizador de Lambda también debe devolver el identificador principal del intermediario. También puede devolver un objeto context, que contiene información adicional que puede pasarse al backend de integración. Para obtener más información, consulte Salida de un autorizador de Lambda de Amazon API Gateway.