Functions: Validación de una clave de API con API Gateway

En este tutorial, utilizará Oracle Functions para validar una clave de API transferida desde Oracle API Gateway. Una clave de API es un método sencillo para proteger una API al solicitar al cliente que transfiera un token específico. El gateway puede utilizar el token como autorizador personalizado para validar solicitudes. Crea una función Python que valida el token y devuelve una respuesta JSON autenticada.

Las tareas clave incluyen cómo:

  • Recopilar la información necesaria.
  • Crear una aplicación para su función.
  • Crear una función "Hello World!".
  • Convertir su función para validar la clave de API.
  • Desplegar y probar la función.
  • Crear un API Gateway para su función
  • Llamar a su función desde Internet utilizando su instancia de API Gateway.
En las imágenes se muestran los componentes de OCI utilizados para ejecutar Oracle Functions.

Para obtener información adicional, consulte:

Antes de empezar

Para realizar correctamente este tutorial, debe tener lo siguiente:

Requisitos de la cuenta de OCI
Requisitos de software

CLI de Oracle

Oracle Cloud Shell

  • Si utiliza Cloud Shell, la lista anterior de software ya está instalada.

1. Recopilación de la información necesaria

Recopile toda la información necesaria para completar el tutorial. Copie la siguiente información en el bloc de notas.

Obtención de la información del compartimento

Para crear un compartimento, consulte Creación de un compartimento. Después de crear el compartimento, guarde el OCID y el nombre del compartimento.

Para obtener el OCID de compartimento de un compartimento existente:

  1. Abra el menú de navegación y haga clic en Identidad y seguridad. En Identidad, haga clic en Servicios.
  2. Seleccione el compartimento.
  3. Haga clic en el enlace Copiar del campo OCID.

Guarde el OCID y el nombre del compartimento.

Información recopilada

Asegúrese de escribir la siguiente información para el tutorial.

  • Nombre de compartimento: <your-compartment-name>

    Ejemplo: my-compartment

  • ID de compartimento: <your-compartment-OCID>

    Ejemplo: ocid1.compartment.oc1.aaaaaaa...

  • Nombre de VCN: <your-vcn-name>

    Ejemplo: my-vcn

    Abra el menú de navegación y haga clic en Red y, a continuación, haga clic en Red virtual en la nube.

  • Nombre de subred pública de VCN: <Public-Subnet-your-vcn-name>

    Ejemplo: Public-Subnet-my-vcn

    Abra el menú de navegación y haga clic en Red y, a continuación, haga clic en Red virtual en la nube. Haga clic en la VCN que ha creado.

2. Realización de la configuración necesaria

Realice toda la configuración que necesita para el tutorial.

Creación de la aplicación de Functions

Para crear una aplicación, siga estos pasos.

  1. Abra el menú de navegación y haga clic en Servicios para desarrolladores. En Funciones, haga clic en Aplicaciones.
  2. Seleccione el compartimento de la lista desplegable Compartimento.
  3. Haga clic en Crear aplicación.
  4. Rellene los datos del formulario.
    • Nombre: <your-app-name>
    • VCN: <your-vcn-name>
    • Subredes: <Public-Subnet-your-vcn-name>
  5. Haga clic en Crear.

Se crea la aplicación.

Configuración de la regla de entrada para HTTPS
  1. Abra el menú de navegación y haga clic en Red y, a continuación, haga clic en Red virtual en la nube.
  2. Haga clic en el nombre de la VCN utilizada para su aplicación de Oracle Functions.
  3. Con la nueva VCN mostrada, haga clic en el enlace de la subred pública.

    La información de subred pública se muestra con las listas de seguridad en la parte inferior de la página.

  4. Haga clic en el enlace Lista de seguridad por defecto o en el enlace de lista de seguridad adecuado.

    Se muestran las reglas de entrada por defecto para su VCN.

  5. Haga clic en Agregar reglas de entrada.

    Se muestra un cuadro de diálogo Agregar reglas de entrada.

  6. Rellene la regla de entrada con la siguiente información. Después de introducir todos los datos, haga clic en Agregar reglas de entrada

    Rellene la regla de entrada de la siguiente forma:

    • Sin estado: marcada
    • Tipo de origen: CIDR
    • CIDR de origen: 0.0.0.0/0
    • Protocolo IP: TCP
    • Rango de puertos de origen: (déjelo en blanco)
    • Rango de puertos de destino: 443
    • Descripción: VCN para aplicaciones

    Después de hacer clic en Agregar regla de entrada, se permiten conexiones HTTPS a su subred pública.

Política de configuración para acceso de API Gateway a Functions

A continuación, configure una política que permita a API Gateway llamar a Functions.

En primer lugar, cree un grupo dinámico para API Gateway.

  1. Abra el menú de navegación y haga clic en Identidad y seguridad. En Identidad, haga clic en Grupos dinámicos.
  2. Haga clic en Crear grupo dinámico.
  3. Rellene la siguiente información para definir el grupo dinámico.
    • Nombre: <name-for-your-dynamic-group>
    • En Reglas de coincidencia, utilice Regla 1: <the-rule-text>

    Aquí se muestra el nombre de ejemplo y la regla que debe rellenar.

    • Nombre: grupo-dinámico-de-funciones-de-funciones
    • En Reglas de coincidencia, utilice Regla 1: ALL {resource.type = 'ApiGateway', resource.compartment.id = 'ocid1.compartment.<your-compartment-OCID>'}
  4. Haga clic en Crear.

Ahora cree la política para API Gateway.

  1. Abra el menú de navegación y haga clic en Identidad y seguridad. En Identidad, haga clic en Políticas.
  2. Haga clic en Crear política.
  3. Para definir la política, rellene la siguiente información.
    • Nombre: <name-for-your-policy>
    • Descripción: <description-for policy>
    • Compartimento: <name-of-functions-compartment>

    En la sección Creador de política:

    • Haga clic en Mostrar editor manual.
    • Introduzca la política en el cuadro de texto, por ejemplo:
      Allow dynamic-group  api-gtw-func-dynamic-group to use functions-family in compartment <your-compartment-name>
      Nota

      El último parámetro es el nombre del compartimento, no el OCID del compartimento.
  4. Haga clic en Crear.

Ha creado una política para permitir que API Gateway utilice Functions.

Creación de la función "Hello World" de Python
  1. Abra un terminal.
  2. Cree un directorio para almacenar sus funciones y cambie a ese directorio.
    mkdir my-dir-name
    cd my-dir-name                        
                         
  3. Cree una función "Hello World" de Python con Fn.
    fn init --runtime python my-func-name

    Con este comando se crea un directorio denominado my-func-name con los archivos de función y configuración incluidos en él.

  4. Cambie al directorio.
  5. Despliegue la función.
    fn -v deploy --app your-app-name

    Se muestran varios mensajes a medida que se crean las imágenes de Docker, se transfieren a OCIR y, finalmente, se despliegan en Oracle Functions.

  6. Llame a la función.
    fn invoke your-app-name my-func-name

    Devuelve: {"message": "Hello World"}

  7. Llame a la función con un parámetro.
    echo -n '{"name":"Bob"}' | fn invoke your-app-name my-func-name

    Devuelve: {"message": "Hello Bob"}

3. Creación de una instancia de API Gateway

Para llamar a su función, cree una instancia de API Gateway.

Creación de la instancia de API Gateway

Para crear una instancia de API Gateway:

  1. Abra el menú de navegación y haga clic en Servicios para desarrolladores. En Gestión de API, haga clic en Gateways.
  2. Seleccione el compartimento de la lista desplegable Compartimento.
  3. Haga clic en Crear gateway.
  4. Rellene la siguiente información para definir su instancia de API Gateway.
    • Nombre: <your-gateway-name>
    • Tipo: <Public>
    • Compartimento: <your-compartment-name>
    • Red virtual en la nube en <su-vcn-name>: <select-your-vcn>
    • Subnet en <nombre-su-compartimento: <your-public-subnet-name>
  5. Haga clic en Crear. Espere unos minutos hasta que la instancia de API Gateway se cree.
Creación de un despliegue de API para su gateway

A continuación, cree un despliegue para su instancia de API Gateway.

  1. Haga clic en Despliegues en la sección Recursos de la parte izquierda de la pantalla.
  2. Haga clic en Crear despliegue.
  3. Asegúrese de que la opción De cero esté seleccionada para el tipo de despliegue.
  4. Para definir el despliegue, rellene la sección Información básica.
    • Nombre: <your-deployment-name>
    • Path Prefix (ejemplo): /tokens
    • Compartimento: <your-compartment-name>
    • Políticas de solicitud de API: acepte los valores por defecto
    • Políticas de registro de API: acepte el valor por defecto Información
  5. Haga clic en Siguiente. Aparece el cuadro de diálogo Rutas con la opción Ruta 1 seleccionada.
  6. Para definir la ruta, rellene la sección Ruta 1.
    • Ruta: <your-route-path>

      Ejemplo: /val-token

    • Métodos: GET POST
    • Tipo: Oracle Functions
    • Aplicación en <nombre de compartimento>: seleccione la aplicación de Functions que ha creado.
    • Nombre de función: seleccione la función que ha creado en la sección de configuración.
  7. Haga clic en Siguiente. Se muestra el cuadro de diálogo Revisar, donde se resumen las opciones que ha realizado.
  8. Haga clic en Crear. Se crea el despliegue.
  9. Haga clic en el enlace Despliegues del gateway. Copie el punto final base del despliegue que ha creado.

    Por ejemplo: https://aaaaa.apigateway.us-ashburn-X.oci.customer-oic.com/tokens

Prueba de la instancia de API Gateway

Con su instancia de API Gateway y el despliegue creados, ahora puede probar la instalación. Cree un script simple para el comando curl. Para crear la URL para curl, agregue la ruta de despliegue al punto final.

  1. Cree el archivo de script: touch gtw01.sh && chmod 755 gtw01.sh
  2. Agregue el comando curl al archivo de script:
    #!/bin/bash
    curl <your-api-gateway-endpoint>/val-token
  3. El comando devuelve: {"message":"Hello World"}

Ha conectado la instancia de API Gateway a una función de Python de texto fijo. A continuación, actualizará la función Python para mostrar la información transferida en una solicitud HTTP.

4. Actualización de la función para validar la clave de API

A continuación, modifique la función Python de texto fijo para validar una clave de API.

Revisión del código de Python inicial

Si observa la función de texto fijo, la función de Python tiene un aspecto similar al siguiente.

import io
import json
import logging

from fdk import response


def handler(ctx, data: io.BytesIO = None):
    name = "World"
    try:
        body = json.loads(data.getvalue())
        name = body.get("name")
    except (Exception, ValueError) as ex:
        logging.getLogger().info('error parsing json payload: ' + str(ex))
    
    logging.getLogger().info("Inside Python Hello World function")
    return response.Response(
       ctx, response_data=json.dumps(
           {"message": "Hello {0}".format(name)}),
       headers={"Content-Type": "application/json"}
    )

Mediante este código como punto de partida, las secciones que siguen convierten la función en una función de Python que valida una clave de API y devuelve un token.

Creación de una variable de configuración de Functions

Oracle Functions permite almacenar datos de configuración en el contexto que está disponible en la solicitud. Los datos de configuración se pueden almacenar en una aplicación o en una función. Con el siguiente comando se almacena la clave de API en la configuración de la aplicación.

  • fn config app <your-app-name> FN_API_KEY ABCD

La cadena "ABCD" es un valor de clave de ejemplo.

Para obtener más información sobre la configuración de valores de configuración de funciones, consulte el tutorial de Fn Project sobre contexto de tiempo de ejecución.

Actualización de paquetes y la función de manejador necesarios

En primer lugar, actualice func.py para los paquetes necesarios.

  1. Actualice las sentencias import en func.py para la validación de paquetes necesaria:
    import io
    import json
    import logging
    import datetime
    
    from datetime import timedelta
    from fdk import response
                    

    El paquete datetime se utiliza para definir un tiempo de caducidad para el token devuelto.

  2. A continuación, elimine el cuerpo principal de la función. El método response y el código relacionado se vuelven a agregar a medida que avanzamos.
    import io
    import json
    import logging
    import datetime
    
    from datetime import timedelta
    from fdk import response
                            
    
    def handler(ctx, data: io.BytesIO = None):                
    

Ahora está listo para actualizar la función con el código de validación.

Adición de código de validación a la función

A continuación, agregue código para validar la clave de API y devolver un token en la respuesta. Este es el código con comentarios a continuación.

import io
import json
import logging
import datetime

from datetime import timedelta
from fdk import response

def handler(ctx, data: io.BytesIO = None):
    auth_token = "invalid"
    token = "invalid"
    apiKey = "invalid"
    expiresAt = (datetime.datetime.utcnow() + timedelta(seconds=60)).replace(tzinfo=datetime.timezone.utc).astimezone().replace(microsecond=0).isoformat()
    
    try:
        auth_token = json.loads(data.getvalue())
        token = auth_token.get("token")
        
        app_context = dict(ctx.Config())
        apiKey = app_context['FN_API_KEY']
        
        if token == apiKey:
            return response.Response(
                ctx, 
                status_code=200, 
                response_data=json.dumps({"active": True, "principal": "foo", "scope": "bar", "clientId": "1234", "expiresAt": expiresAt, "context": {"username": "wally"}})
            )
    
    except (Exception, ValueError) as ex:
        logging.getLogger().info('error parsing json payload: ' + str(ex))
        pass
    
    return response.Response(
        ctx, 
        status_code=401, 
        response_data=json.dumps({"active": False, "wwwAuthenticate": "API-key"})
    )
  • La función handler recibe información del sistema sobre la solicitud actual a través de los parámetros ctx y data.
  • La función asume que FN_API_KEY está definido en la configuración de la aplicación. A continuación, la función compara el valor de configuración con el valor de token enviado desde la solicitud POST curl: -d '{"token":"ABCD"}'.
  • Si los valores coinciden, se devuelve un mensaje de JSON de validación. Si no coinciden, se devuelve un código 401 con datos de error de JSON.

El código de función está completo. Ya está listo para probar la función.

Prueba de la función
  1. Vuelva a desplegar la función actualizada.
  2. Llame a la función para asegurarse de que la función es correcta.
  3. Actualice el script gtw01.sh para transferir los datos POST al script.
    /bin/bash
    curl -X POST -d '{"token":"ABCD"}' https://aaaaa.apigateway.us-ashburn-X.oci.customer-oic.com/tokens/val-token
  4. Ejecute el script: gtw01.sh | jq
  5. Si coinciden las claves de API, la salida del script es similar a:
    {
        "active": true,
        "principal": "foo",
        "scope": "bar",
        "clientId": "1234",
        "expiresAt": "2020-12-16T22:48:50+00:00",
        "context": {
        "username": "wally"
        }
    }

    Si las claves de API no coinciden, se devuelve un mensaje de error.

    {
        "active": false,
        "wwwAuthenticate": "API-key"
    }                        
                        

    Puede descargar el código fuente completo para la función desde el sitio oracle-functions-samples aquí.

Enhorabuena, ha convertido la función de Python de texto fijo en una nueva función que valida una clave de API. La función muestra cómo se pueden transferir los datos a API Gateway y procesarlos en una función.