En este post vamos a profundizar un poco más en el uso de Api GateWay Http y vamos a ver cómo agregar un método de autorización de acceso a los métodos de nuestro Api.
Vamos a partir del ejemplo realizado en el siguiente post:
Api Gateway Http en donde creamos un Api que hace referencia a servicios externos. Este Api no tiene ningún control de acceso por lo que cualquier persona puede consumirlo sin ninguna restricción. en esta ocasión para tener acceso al Api vamos a tener que enviar una cabecera de autorización para tener acceso a sus métodos.
Pasos a realizar:
1.Creación función Lambda para rotar el secreto.
2.Creación de Secreto.
3.Crear función lamba de autorización.
4.Creación de autorizar en Api Gateway.
5.Asociar autorizador.
Vamos a comenzar creando la función Lambda que va a ser la encargada de rotar nuestro secreto.
Una vez creada nuestra función vamos a la pestaña de código y copiamos lo siguiente:
import json
import uuid
import boto3
client = boto3.client('secretsmanager')
def lambda_handler(event, context):
# TODO implement
secret = { "secret_header":str(uuid.uuid4())}
id = 'reemplazar por arn del secreto'
client.update_secret(SecretId = id,SecretString=json.dumps(secret))
Después de tener nuestro código damos click en Deploy para que nuestros cambios queden guardados.
Hasta el momento hemos creado la función Lambda que va a ser la encargada de rotar el valor del secreto que va servir para la autorización a nuestra api. Sin embargo para que Secrets Manager pueda invocar la función debemos asignarle al Rol de la función la Política que le permita realizar esta acción.
Para este vamos a la pestaña de configuración y damos click en el nombre del Rol.
Ya en la pantalla del ROl vamos a Add Permissions - Attach Policies.
En la barra de búsqueda colocamos Secrests ,seleccionamos SecretsManagerReadWritey damos click en Attach policies
Ya que la función Lambda tiene el rol adecuado para modificar nuestro secreto cuando la ejecutemos, el siguiente paso es agregar una politica a la función Lambda para que pueda ser llamada desde Secrets Manager. Para esto debemos ejecutar el siguiente comando en la terminal reemplazando ARN_of_lambda_function por el ARN de la función Lambda que acabamos de crear.
aws lambda add-permission --function-name ARN_of_lambda_function --principal secretsmanager.amazonaws.com --action lambda:InvokeFunction --statement-id SecretsManagerAccess
Terminada la configuración anterior, nuestra función Lambda ya puede realizar modificaciones a nuestro secreto.
El siguiente paso es definir el secreto que vamos a utilizar para autorizar el acceso a nuestro Api. Para esto buscamos en la barra de búsqueda de servicios: *Secrets Manager * y en la pantalla principal damos click en Store a new Secret
Empezamos por definir el tipo de secreto y el nombre y valor por defecto que vamos a establecer a nuestro secreto.
Definimos un nombre para el secreto: secret-header-api.
Ahora definimos cada cuando queremos que nuestro secreto cambie (1 día) y qué función Lambda (la que creamos con anterioridad) va a ser la encargada de realizar la rotación.
La siguiente pantalla nos va a mostrar el resumen de la configuración de nuestro secret, damos click en Store.
En la pantalla del listado de secretos damos click en el secreto que acabamos de crear.
En la pantalla debemos copiar el ARN del secreto para reemplazarlo en la variable id de la función Lambda que creamos. Con el objetivo que cuando ejecutemos la función Lambda modifique el valor de nuestro secreto.
Adicional podemos ver el valor del secreto dando click en Retrive secret value.
En la parte inferior de la pantalla vamos a encontrar el código fuente para obtener el secreto utilizando el lenguaje de programación de nuestra preferencia, que para nuestro caso es Python.
Hasta el momento hemos creado un secreto con un tiempo definido para su rotación y una función Lambda que es la encargada de cambiar el valor de nuestro secreto.
El siguiente paso es crear la función Lambda que va autorizar el acceso a nuestro Api.
El siguiente código es el que debe tener nuestra función:
import json
import boto3
import base64
from botocore.exceptions import ClientError
# Use this code snippet in your app.
# If you need more information about configurations or implementing the sample code, visit the AWS docs:
# https://aws.amazon.com/developers/getting-started/python/
secret_name = "arn:aws:secretsmanager:us-east-1:385033107168:secret:secret-header-api4-Yt9jGg"
region_name = "us-east-1"
# Create a Secrets Manager client
session = boto3.session.Session()
client = session.client(service_name='secretsmanager',region_name=region_name)
def get_secret():
secret =""
# In this sample we only handle the specific exceptions for the 'GetSecretValue' API.
# See https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html
# We rethrow the exception by default.
try:
get_secret_value_response = client.get_secret_value(
SecretId=secret_name
)
except ClientError as e:
if e.response['Error']['Code'] == 'DecryptionFailureException':
# Secrets Manager can't decrypt the protected secret text using the provided KMS key.
# Deal with the exception here, and/or rethrow at your discretion.
raise e
elif e.response['Error']['Code'] == 'InternalServiceErrorException':
# An error occurred on the server side.
# Deal with the exception here, and/or rethrow at your discretion.
raise e
elif e.response['Error']['Code'] == 'InvalidParameterException':
# You provided an invalid value for a parameter.
# Deal with the exception here, and/or rethrow at your discretion.
raise e
elif e.response['Error']['Code'] == 'InvalidRequestException':
# You provided a parameter value that is not valid for the current state of the resource.
# Deal with the exception here, and/or rethrow at your discretion.
raise e
elif e.response['Error']['Code'] == 'ResourceNotFoundException':
# We can't find the resource that you asked for.
# Deal with the exception here, and/or rethrow at your discretion.
raise e
else:
# Decrypts secret using the associated KMS key.
# Depending on whether the secret is a string or binary, one of these fields will be populated.
if 'SecretString' in get_secret_value_response:
secret = get_secret_value_response['SecretString']
else:
secret = base64.b64decode(get_secret_value_response['SecretBinary'])
# Your code goes here.
return json.loads(secret)["secret_header"]
def lambda_handler(event, context):
secret = get_secret()
# TODO implement
if event["headers"]["authorization"] == secret:
return {
"isAuthorized": True
}
else:
return {
"isAuthorized": False
}
Básicamente el código es muy parecido al que nos muestra Secrets Manager para obtener nuestro secreto, solamente se le hicieron algunas modificaciones.
Debemos modificar el Rol de la función Lambda para que nos permita obtener el secreto.Debemos seguir los mismos pasos que realizamos con la función Lambda definida anteriormente.
Para finalizar debemos crear nuestro autorizador y asociarlo a los métodos que creamos convenientes.
Vamos a API Gateway y buscamos nuestro API y damos click.
Ya en la pagina principal de nuestro API, vamos al menu: Authorization, buscamos la opción Manage authorizers y damos click en el botón Create.
En la configuración de nuestro Autorizar realizamos lo siguiente:
Lo que hicimos fue definir, que nuestro autorizador va a ser la función Lambda que creamos, que el tipo de respuesta es simple (json con un valor True o False) ,que nuestra respuesta no va estar en cache y le dimos autorización a API Gateway para que pueda hacer llamados a nuestra función Lambda.
El siguiente paso es asociar nuestro autorizador a las rutas que necesitemos. Vamos al tab Attach authorizers to routes, seleccionamos la ruta a la cual queremos asociarle el autorizardor, seleccionamos el autorizar y damos click en el boton Attach authorizer.
Ahora podemos ver al lado del tipo de método que nuestra ruta cuenta con un autorizador.
Con esto finalizamos la configuración de agregar un método de autorización para las rutas o métodos de nuestro API.Vamos a realizar las pruebas utilizando PostMan.Agregamos el header Authorization y colocamos el valor del secreto para realizar la prueba.
Como siguiente paso pueden realizar un llamado al Api con su lenguaje de programación favorito para validar su funcionamiento.
Una función Lambda en Python seria:
import json
import requests
def lambda_handler(event, context):
r=requests.get("https://d95ca2fimh.execute-api.us-east-1.amazonaws.com/api/timezone", headers={"Authorization":"6a7acb2b-5c79-4951-b051-503dca83225c"})
# TODO implement
print(r.json())
return {
'statusCode': 200,
'body': r.json()
}
Me pueden encontrar en
Top comments (0)