Módulo 4: Trabajar con otros servicios de AWS
MÓDULO DE APRENDIZAJE
Hay varias formas de trabajar con otros servicios de AWS.
Si el servicio al que está accediendo es una base de datos de AWS RDS, como SQL Server o Postgres, utilizará las mismas bibliotecas que utilizaría si alojara las bases de datos en su propia computadora o centro de datos. Necesita una cadena de conexión con nombre de usuario y contraseña, u otra forma de autenticación de su elección. No hay nada diferente del uso diario de la base de datos. No necesita ningún permiso adicional para acceder al servidor de la base de datos. La única advertencia al respecto es que si la base de datos no es de acceso público, tendrá que conectar la Lambda a la VPC (ese proceso requiere permisos adicionales).
Si su función de Lambda utiliza S3, DynamoDB, Kinesis, etc., utilice los SDK de AWS para interactuar con esos servicios. El rol en el que se ejecuta su función de Lambda necesita los permisos adecuados para interactuar con cada servicio. Por ejemplo, si desea añadir un elemento a un bucket de S3, el rol necesitará permiso para escribir en ese bucket. Si desea obtener elementos de una tabla de DynamoDB, el rol necesitará permisos para leer de esa tabla.
El tercer escenario es en el que desea que otro servicio active su función de Lambda en respuesta a algún evento. Por ejemplo, es posible que desee activar la función de Lambda cuando se agrega un elemento nuevo a un bucket de S3 determinado o cuando los eventos llegan a una secuencia de Kinesis. Para ello, la función de Lambda debe utilizar una “política basada en recursos”. Esta política otorga a otros servicios el permiso para invocar su función de Lambda.
Tiempo de realización
30 minutos
Acceso a los servidores de bases de datos de RDS desde una función de Lambda
Lo mejor de usar servicios conocidos como SQL Server, Postgres o MySQL es que, desde la perspectiva del código, no es necesario hacer nada diferente al llamarlos desde una función de Lambda. Entity Framework/ADO/Npgsql, etc., funcionan igual de bien con una base de datos alojada en AWS que con una base de datos local o en bastidor. Lo llama de la misma manera, no necesita una biblioteca de SDK de AWS, pero, desde luego, aún necesita agregar los paquetes NuGet relevantes a su proyecto. Por lo demás, todo es lo mismo.
Acceso a los servicios de AWS desde una función de Lambda
2. Como una política independiente que puede adjuntar a cualquier rol. En AWS, esta última se denomina política administrada por el cliente.
Siempre es una buena práctica asignar la menor cantidad de permisos posible al rol. En el siguiente ejemplo, en el que leerá la tabla de DynamoDB, tendrá que conceder al rol de Lambda dos permisos: dynamodb:GetItem y dynamodb:DescribeTable. Además, limitará esos permisos a la tabla específica que le interese.
Primero, cree una nueva tabla de DynamoDB llamada People. Los siguientes comandos funcionarán con PowerShell, si usa la línea de comandos de Windows o el shell de Linux necesitará un escape diferente para las cadenas.
Ejecute lo siguiente:
aws dynamodb create-table --table-name People --attribute-definitions AttributeName=PersonId,AttributeType=N --key-schema AttributeName=PersonId,KeyType=HASH --provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1
Añada algunos elementos a la tabla:
aws dynamodb put-item --table-name People --item '{"PersonId":{"N":"1"},"State":{"S":"MA"}, "FirstName": {"S":"Alice"}, "LastName": {"S":"Andrews"}}'
aws dynamodb put-item --table-name People --item '{"PersonId":{"N":"2"},"State":{"S":"MA"}, "FirstName": {"S":"Ben"}, "LastName": {"S":"Bradley"}}'
aws dynamodb put-item --table-name People --item '{"PersonId":{"N":"3"},"State":{"S":"MA"}, "FirstName": {"S":"Claire"}, "LastName": {"S":"Connor"}}'
A continuación, cree una función de Lambda con:
dotnet new lambda.EmptyFunction -n LambdaFunctionDynamoDB
cd LambdaFunctionDynamoDB /src/LambdaFunctionDynamoDB
dotnet add package AWSSDK.DynamoDBv2
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;
using Amazon.Lambda.Core;
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
namespace LambdaFunctionDynamoDB ;
public class Function
{
public async Task<string> FunctionHandler(ILambdaContext lambdaContext)
{
AmazonDynamoDBConfig clientConfig = new AmazonDynamoDBConfig();
AmazonDynamoDBClient client = new AmazonDynamoDBClient(clientConfig);
DynamoDBContext dynamoDbContext = new DynamoDBContext(client);
Person person = await dynamoDbContext.LoadAsync<Person>(1);
return $"{person.FirstName} {person.LastName} lives in {person.State}";
}
}
[DynamoDBTable("People")]
public class Person
{
[DynamoDBHashKey]
public int PersonId {get; set;}
public string State {get; set;}
public string FirstName {get; set;}
public string LastName {get; set;}
}
dotnet lambda deploy-function LambdaFunctionDynamoDB
Despliegue la función de Lambda en AWS Lambda mediante:
dotnet lambda deploy-function LambdaFunctionDynamoDB
A continuación, se le preguntará “Seleccione el rol de IAM para proporcionar las credenciales de AWS a su código”. Es posible que se le presente una lista de los roles que creó anteriormente, pero al final de la lista aparecerá la opción “*** Crear un nuevo rol de IAM ***”, escriba ese número junto a esa opción.
Se le pedirá que “Introduzca el nombre del nuevo rol de IAM:”. Escriba “LambdaFunctionDynamoDBRole”.
A continuación, se le pedirá que “Seleccione la política de IAM para adjuntarla a la nueva función y conceder permisos” y se mostrará una lista de políticas. Seleccione AWSLambdaBasicExecutionRole, es el número 6 de mi lista. (Sé que hay una política llamada AWSLambdaDynamoDBExecutionRole, pero el objetivo de este módulo es mostrarle cómo agregar usted mismo los permisos necesarios).
Intente invocar la función de Lambda mediante:
dotnet lambda invoke-function LambdaFunctionDynamoDB
"errorMessage": "User: arn:aws:sts::YOUR_ACCOUNT_NUMBER:assumed-role/LambdaFunctionDynamoDB Role/LambdaFunctionDynamoDB is not authorized to perform: dynamodb:DescribeTable on resource: arn:aws:dynamodb:us-east-1:YOUR_ACCOUNT_NUMBER:table/People because no identity-based policy allows the dynamodb:DescribeTable action"
Esto indica que el rol en el que se ejecuta la función de Lambda no tiene el permiso dynamodb:DescribeTable requerido.
Para solucionarlo, debe añadir una política que conceda el permiso dynamodb:DescribeTable al rol. Como se mencionó anteriormente, puede agregar una política en línea (solo para este rol) o una política independiente (disponible para todos los roles).
Cree un archivo denominado DynamoDBAccessPolicy.json en la carpeta LambdaFunctionDynamoDB /src/LambdaFunctionDynamoDB.
Edite DynamoDBAccessPolicy, pero utilice su número de cuenta en el recurso:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"dynamodb:DescribeTable"
],
"Resource": "arn:aws:dynamodb:us-east-1:YOUR_ACCOUNT_NUMBER:table/People"
}
]
}
aws iam put-role-policy --role-name LambdaFunctionDynamoDBRole --policy-name LambdaFunctionDynamoDBAccess --policy-document file://DynamoDBAccessPolicy.json
dotnet lambda deploy-function LambdaFunctionDynamoDB
dotnet lambda invoke-function LambdaFunctionDynamoDB
Esta vez el mensaje es:
"errorMessage": "User: arn:aws:sts::YOUR_ACCOUNT_NUMBER:assumed-role/LambdaFunctionDynamoDB Role/LambdaFunctionDynamoDB is not authorized to perform: dynamodb:GetItem on resource: arn:aws:dynamodb:us-east-1:YOUR_ACCOUNT_NUMBER:table/People because no identity-based policy allows the dynamodb:GetItem action",
Actualice el archivo DynamoDBAccessPolicy.json con lo siguiente:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"dynamodb:DescribeTable",
"dynamodb:GetItem"
],
"Resource": "arn:aws:dynamodb:us-east-1:YOUR_ACCOUNT_NUMBER:table/People"
}
]
}
dotnet lambda deploy-function LambdaFunctionDynamoDB
dotnet lambda invoke-function LambdaFunctionDynamoDB
Amazon Lambda Tools for .NET Core applications (5.4.2)
Project Home: https://github.com/aws/aws-extensions-for-dotnet-cli, https://github.com/aws/aws-lambda-dotnet
Payload:
"Alice Andrews lives in MA"
Otra opción es colocar el cursor sobre el método del SDK que esté utilizando; los metadatos pueden contener información útil sobre los permisos. No todos los metadatos del método contendrán información de permisos.
Ahora sabe cómo averiguar qué permisos necesita su función y cómo conceder los permisos correctos al rol en el que se ejecutan sus funciones de Lambda.
Permitir que otros servicios invoquen funciones de Lambda
En la sección anterior, aprendió a conceder permisos a la función de Lambda para realizar acciones en otros servicios. En esta sección, verá cómo conceder permisos a otros servicios para invocar su función de Lambda.
Si utiliza las plantillas sin servidor.*, probablemente ya esté concediendo a una API Gateway el permiso necesario para invocar su función de Lambda. Si ha desplegado una función de este tipo, vaya a la pestaña Configuración, seleccione Permisos a la izquierda y desplácese hasta la sección Política basada en recursos. Verá políticas que permiten a la API Gateway invocar su función de Lambda. Esta política se agregó mediante el comando dotnet lambda deploy-serverless y el archivo serverless.template de su proyecto.
En la imagen siguiente, puede ver dos declaraciones de política que permiten a una API Gateway invocar la función de Lambda.
Cree el bucket S3
Si desea que su bucket esté en us-east-1, puede utilizar el siguiente comando:
aws s3api create-bucket --bucket my-unique-bucket-name-lambda-course
aws s3api create-bucket --bucket my-unique-bucket-name-lambda-course --create-bucket-configuration LocationConstraint=REGION
Cree la función de Lambda
Desde la línea de comandos, ejecute:
dotnet new lambda.S3 -n S3EventHandler
cd S3EventHandler/src/S3EventHandler
public async Task FunctionHandler(S3Event evnt, ILambdaContext context)
{
context.Logger.LogInformation($"A S3 event has been received, it contains {evnt.Records.Count} records.");
foreach (var s3Event in evnt.Records)
{
context.Logger.LogInformation($"Action: {s3Event.EventName}, Bucket: {s3Event.S3.Bucket.Name}, Key: {s3Event.S3.Object.Key}");
if (!s3Event.EventName.Contains("Delete"))
{
try
{
var response = await this.S3Client.GetObjectMetadataAsync(s3Event.S3.Bucket.Name, s3Event.S3.Object.Key);
context.Logger.LogInformation( $"The file type is {response.Headers.ContentType}");
}
catch (Exception e)
{
context.Logger.LogError(e.Message);
context.Logger.LogError($"An exception occurred while retrieving {s3Event.S3.Bucket.Name}/{s3Event.S3.Object.Key}. Exception - ({e.Message})");
}
}
else
{
context.Logger.LogInformation($"You deleted {s3Event.S3.Bucket.Name}/{s3Event.S3.Object.Key}");
}
}
}
Si el evento de S3 responde a la eliminación de un objeto, la función registrará los nombres de los buckets o las claves en CloudWatch.
Desplegar la función de Lambda
dotnet lambda deploy-function S3EventHandler
A continuación, se le preguntará “Seleccione el rol de IAM para proporcionar las credenciales de AWS a su código”. Es posible que se le presente una lista de los roles que creó anteriormente, pero al final de la lista aparecerá la opción “*** Crear un nuevo rol de IAM ***”, escriba ese número junto a esa opción.
Se le pedirá que “Introduzca el nombre del nuevo rol de IAM:”. Escriba “S3EventHandlerRole”.
A continuación, se le pedirá que “Seleccione la política de IAM para adjuntarla a la nueva función y conceder permisos” y se mostrará una lista de políticas. Seleccione AWSLambdaBasicExecutionRole, es el número 6 de mi lista. Tendrá que añadir una política para otorgar acceso al bucket de S3 para que funcione la llamada GetObjectMetadataAsync(..).
Otorgue permisos a la función de Lambda para obtener los metadatos del objeto
Verá un par de maneras para hacerlo.
La política tendrá este aspecto, pero con el nombre del bucket en el recurso. Tenga en cuenta el /* al final; esto significa que s3:GetObject se aplica a todos los objetos del bucket:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::my-unique-bucket-name-lambda-course/*"
}
]
}
aws iam create-policy --policy-name S3AccessPolicyForCourseBucket --policy-document file://S3AccessPolicyForCourseBucket.json
A continuación, adjunte la política al rol que creó anteriormente. Ejecute lo siguiente:
aws iam attach-role-policy --role-name S3EventHandlerRole --policy-arn arn:aws:iam::694977046108:policy/S3AccessPolicyForCourseBucket
Haga clic en la pestaña Configuración, luego en Permisos a la izquierda y haga clic en el nombre del rol.
Haga clic en Agregar permisos y Adjuntar políticas.
Haga clic en Crear política
En la sección Acciones, escriba getobject y seleccione GetObject en la lista.
En la sección de recursos, elija Específico y haga clic en Agregar ARN.
Vuelva a la pestaña en la que hizo clic en Crear política. Siga estos pasos:
1. Recargue la lista de políticas
2. Escriba s3AccessPolicyForCourseBucket en el filtro
3. Marque la casilla situada junto a la política
4. Haga clic en Adjuntar políticas
En este punto, tiene un bucket de S3, la función de Lambda y los permisos necesarios para obtener los metadatos del objeto del bucket de S3.
Ahora es el momento de conectar el bucket de S3 a la función de Lambda para que los eventos de creación y eliminación activen la función de Lambda.
Active la función de Lambda desde el bucket de S3
Abra la lista de buckets en S3 https://s3.console.aws.amazon.com/s3/buckets.
Haga clic en el que creó.
Desplácese hacia abajo hasta la sección Notificaciones de eventos.
Haga clic en Crear notificación de evento.
Introduzca un nombre para la notificación del evento.
Seleccione las dos primeras casillas de la izquierda: Todos los eventos de creación de objetos y Todos los eventos de eliminación de objetos.
Desplácese hasta la sección Destino en la parte inferior.
Elija la función de Lambda como destino.
En la lista desplegable, escriba el nombre de la función de Lambda que creó anteriormente.
Haga clic en Guardar los cambios.
En la Consola de AWS, vaya a la función de Lambda que creó anteriormente.
Tenga en cuenta que S3 ahora aparece como activador de la función de Lambda.
Haga clic en la pestaña Configuración y, a continuación, en Permisos a la izquierda.
Verá una declaración de política que permite a S3 invocar la función de Lambda.
Realice pruebas
En su lugar, la función de Lambda se registra en CloudWatch, por lo que tiene que ir allí para ver su función en acción.
Cree un archivo de texto en su computadora para subirlo a S3.
Desde la línea de comandos, ejecute:
aws s3api put-object --bucket my-unique-bucket-name-lambda-course --key Hello.txt --body Hello.txt --content-type "text/plain"
aws s3api delete-object --bucket my-unique-bucket-name-lambda-course --key Hello.txt
Ahora vaya a su función de Lambda en la Consola de AWS y compruebe los registros.
Haga clic en la pestaña Supervisar y, a continuación, en Ver registros en CloudWatch.
El proceso es similar para los tres: abra la extensión de AWS, haga clic en los registros de CloudWatch y busque el grupo o secuencia de registros de /aws/lambda/S3EventHandler. A continuación, abra la secuencia más reciente.
El proceso es similar para los tres: abra la extensión de AWS, haga clic en los registros de CloudWatch y busque el grupo o secuencia de registros de /aws/lambda/S3EventHandler. A continuación, abra la secuencia más reciente.
Conclusión
Este es el punto clave: si desea que su función de Lambda interactúe con otros servicios de AWS, debe otorgar permisos a su función para que actúe en ese otro servicio.
Si desea que otros servicios invoquen su función, debe utilizar políticas basadas en recursos para dar a esos servicios acceso a su función.
Pruebas de conocimientos
1. Cuando desea que otro servicio invoque una función de Lambda, ¿qué debe hacer? (seleccione una opción)
b. Crear un documento de política basada en recursos que dé permiso a los servicios de llamada para invocar la función de Lambda
c. Nada, Lambda confía en todos los demás servicios de AWS
d. Agregar los permisos correctos al rol en el que se ejecuta la función de Lambda1
2. ¿Qué necesita añadir a un rol para concederle permisos de acceso a los servicios de AWS? (seleccione uno)
b. Una política basada en los recursos
c. Una política con los permisos necesarios
d. Un documento de lista de control de acceso
3. ¿Cuáles son las dos formas de crear una política administrada por el cliente para utilizarla con el rol que desempeña una función de Lambda? (seleccione dos)
a. Mediante la línea de comandos
b. Incluirla en el código fuente de la función
c. Mediante esa Consola de AWS
d. Añadirla a la carga útil al ejecutar la función
Respuestas: 1-b, 2-c, 3-ac
Conclusión
Este es el punto clave: si desea que su función de Lambda interactúe con otros servicios de AWS, debe otorgar permisos a su función para que actúe en ese otro servicio.
Si desea que otros servicios invoquen su función, debe utilizar políticas basadas en recursos para dar a esos servicios acceso a su función.