Modulo 4: lavorare con altri servizi AWS
MODULO DI APPRENDIMENTO
Esistono diversi modi per lavorare con altri servizi AWS.
Se il servizio a cui accedi è un database RDS AWS, come SQL Server o Postgres, utilizzi le stesse librerie che useresti se ospitassi i database sul tuo computer o data center. È necessaria una stringa di connessione con nome utente e password o un'altra forma di autenticazione a scelta. Non c'è niente di diverso dall'utilizzo quotidiano del database. Non sono necessarie autorizzazioni aggiuntive per accedere al server del database. L'unica avvertenza è che se il database non è accessibile al pubblico, è necessario connettere Lambda al VPC (tale processo richiede autorizzazioni aggiuntive).
Se la tua funzione Lambda utilizza S3, DynamoDB, Kinesis, ecc., utilizzi gli SDK AWS per interagire con tali servizi. Il ruolo di esecuzione della funzione Lambda richiede autorizzazioni appropriate per interagire con ciascun servizio. Ad esempio, se desideri aggiungere un elemento a un bucket S3, il ruolo avrà bisogno dell'autorizzazione per scrivere in quel bucket. Se desideri ottenere elementi da una tabella DynamoDB, il ruolo avrà bisogno delle autorizzazioni per leggere da quella tabella.
Il terzo scenario è quello in cui desideri che un altro servizio attivi la funzione Lambda in risposta a un evento. Ad esempio, potresti voler attivare la funzione Lambda quando un nuovo elemento viene aggiunto a un determinato bucket S3 o quando gli eventi arrivano in un flusso Kinesis. Per fare ciò, la funzione Lambda deve utilizzare una "policy basata sulle risorse". Questa policy autorizza altri servizi a richiamare la funzione Lambda.
Tempo richiesto per il completamento
30 minuti
Accesso ai server di database RDS da una funzione Lambda
Il bello dell'utilizzo di servizi familiari come SQL Server, Postgres e MySQL è che, dal punto di vista del codice, non è necessario fare nulla di diverso quando li si chiama da una funzione Lambda. Entity Framework/ADO/NpgSql e altri funzionano altrettanto bene con un database ospitato su AWS come con un database locale/montato su rack. Lo chiami allo stesso modo, non hai bisogno di una libreria SDK AWS, però devi aggiungere i pacchetti NuGet pertinenti al tuo progetto. Ma per il resto è tutto uguale.
Accesso ai servizi AWS da una funzione Lambda
2. Come policy autonoma che puoi allegare a qualsiasi ruolo. In AWS, quest'ultima è chiamata policy gestita dal cliente.
È sempre buona norma concedere al ruolo il minor numero di autorizzazioni possibile. Nell'esempio seguente, in cui leggerai dalla tabella DynamoDB, devi concedere al ruolo Lambda due autorizzazioni: dynamodb:GetItem e dynamodb:DescribeTable. E limiterai tali autorizzazioni alla tabella specifica che ti interessa.
Innanzitutto, crea una nuova tabella DynamoDB denominata People. I seguenti comandi funzioneranno con PowerShell, se si utilizza il prompt dei comandi di Windows, altrimenti la shell (interprete di comandi) di Linux richiederà un escape diverso per le stringhe.
Esegui quanto segue-
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
Aggiungi alcuni elementi alla tabella:
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"}}'
Quindi, crea una funzione Lambda usando:
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
Distribuisci la funzione Lambda su AWS Lambda utilizzando:
dotnet lambda deploy-function LambdaFunctionDynamoDB
Successivamente ti verrà chiesto "Select IAM Role that to provide AWS credentials to your code:" (Seleziona il ruolo IAM per fornire le credenziali AWS al tuo codice), ti potrebbe essere presentato un elenco di ruoli che hai creato in precedenza, ma in fondo all'elenco ci sarà l'opzione "*** Create new IAM Role ***" (Crea un nuovo ruolo IAM); digita quel numero accanto all'opzione.
Ti verrà chiesto "Enter name of the new IAM Role:"(Inserisci il nome del nuovo ruolo IAM). Digita "LambdaFunctionDynamoDBRole".
Ti verrà quindi chiesto "Select IAM Policy to attach to the new role and grant permissions" (Seleziona la policy IAM da allegare al nuovo ruolo e concedi le autorizzazioni) e verrà presentato un elenco di policy. Seleziona AWSLambdaBasicExecutionRole, è la numero 6 sulla lista. So che esiste una policy chiamata AWSLambdaDynamoDBExecutionRole, ma l'obiettivo di questo modulo è mostrarti come aggiungere tu stesso le autorizzazioni necessarie.
Prova a richiamare la funzione Lambda usando:
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"
Questo indica che il ruolo di esecuzione della funzione Lambda non dispone dell'autorizzazione dynamodb:DescribeTable richiesta.
Per risolvere il problema, devi aggiungere una policy che conceda al ruolo l'autorizzazione dynamodb:DescribeTable. Come accennato in precedenza, puoi aggiungere una policy inline (solo per questo ruolo) o una policy autonoma (disponibile per tutti i ruoli).
Crea un file chiamato DynamoDBAccessPolicy.json nella cartella LambdaFunctionDynamoDB /src/LambdaFunctionDynamoDB.
Modifica DynamoDBAccessPolicy, ma utilizza il tuo numero di account nella risorsa:
{
"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
Questa volta il messaggio è:
"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",
Aggiorna il file DynamoDBAccessPolicy.json con quanto segue:
{
"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"
Un'altra possibilità è quella di passare il mouse sul metodo SDK in uso; i metadati possono contenere informazioni utili sulle autorizzazioni. Non tutti i metadati del metodo conterranno informazioni sulle autorizzazioni.
Ora sai come scoprire di quali autorizzazioni ha bisogno la tua funzione e come concedere le autorizzazioni corrette al ruolo di esecuzione delle funzioni Lambda.
Consentire ad altri servizi di richiamare funzioni Lambda
Nella sezione precedente hai appreso come concedere le autorizzazioni alla funzione Lambda per eseguire azioni su altri servizi. In questa sezione vedrai come concedere ad altri servizi le autorizzazioni per richiamare la funzione Lambda.
Se utilizzi i modelli serverless.*, probabilmente stai già concedendo a un gateway API l'autorizzazione necessaria per richiamare la funzione Lambda. Se hai distribuito una funzione di questo tipo, vai alla scheda Configuration (Configurazione), poi seleziona Permissions (Autorizzazioni) a sinistra e scorri fino alla sezione Resource-based policy (Policy basate sulle risorse). Vedrai le policy che consentono al gateway API di richiamare la funzione Lambda. Questa policy è stata aggiunta dal comando dotnet lambda deploy-serverless e da serverless.template nel tuo progetto.
Nell'immagine seguente puoi vedere due istruzioni di policy che consentono a un gateway API di richiamare la funzione Lambda.
Crea il bucket S3
Se vuoi creare il bucket nella Regione us-east-1, puoi usare il seguente 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
Crea la funzione Lambda
Dalla linea di comando esegui:
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}");
}
}
}
Se l'evento S3 è in risposta all'eliminazione di un oggetto, la funzione registrerà i nomi del bucket/della chiave su CloudWatch.
Distribuisci la funzione Lambda
dotnet lambda deploy-function S3EventHandler
Successivamente ti verrà chiesto "Select IAM Role that to provide AWS credentials to your code:" (Seleziona il ruolo IAM per fornire le credenziali AWS al tuo codice), ti potrebbe essere presentato un elenco di ruoli che hai creato in precedenza, ma in fondo all'elenco ci sarà l'opzione "*** Create new IAM Role ***" (Crea un nuovo ruolo IAM); digita quel numero accanto all'opzione.
Ti verrà chiesto "Enter name of the new IAM Role:"(Inserisci il nome del nuovo ruolo IAM). Digita "S3EventHandlerRole".
Ti verrà quindi chiesto "Select IAM Policy to attach to the new role and grant permissions" (Seleziona la policy IAM da allegare al nuovo ruolo e concedi le autorizzazioni) e verrà presentato un elenco di policy. Seleziona AWSLambdaBasicExecutionRole, è la numero 6 sulla lista. Dovrai aggiungere una policy per concedere l'accesso al bucket S3 affinché la chiamata GetObjectMetadataAsync(..) funzioni.
Concedi alla funzione Lambda le autorizzazioni per ottenere i metadati dell'oggetto
Vedrai come farlo in un paio di modi.
La policy sarà simile a questa, ma con il nome del bucket nella risorsa. Nota il simbolo /* alla fine, questo significa che s3:GetObject si applica a tutti gli oggetti nel 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
Quindi allega la policy al ruolo che hai creato in precedenza. Esegui quanto segue:
aws iam attach-role-policy --role-name S3EventHandlerRole --policy-arn arn:aws:iam::694977046108:policy/S3AccessPolicyForCourseBucket
Fai clic sulla scheda Configuration (Configurazione), poi su Permissions (Autorizzazioni) a sinistra e fai clic sul nome del ruolo.
Fai clic su Add permissions (Aggiungi autorizzazioni) e Attach policies (Allega policy).
Fai clic su Create policy (Crea policy)
Nella sezione Actions (Azioni), digita getobject e seleziona GetObject dall'elenco.
Nella sezione Resources (Risorse), scegli Specific (Specifico) e fai clic su Add ARN (Aggiungi ARN).
Torna alla scheda in cui hai fatto clic su Create policy (Crea policy). Segui questi passaggi:
1. Ricarica l'elenco delle policy
2. Digita S3AccessPolicyForCourseBucket nel filtro
3. Spunta la casella accanto alla policy
4. Fai clic su Attach policies (Allega policy)
A questo punto, hai un bucket S3, la funzione Lambda e le autorizzazioni necessarie per ottenere i metadati dell'oggetto dal bucket S3.
Ora è il momento di collegare il bucket S3 alla funzione Lambda, in modo che venga attivata dagli eventi di creazione ed eliminazione.
Attiva la funzione Lambda dal bucket S3
Apri l'elenco dei bucket in S3 https://s3.console.aws.amazon.com/s3/buckets.
Fai clic su quello che hai creato.
Scorri verso il basso fino alla sezione Event notifications (Notifiche eventi).
Fai clic su Create event notification (Crea notifica evento).
Inserisci un nome per la notifica di evento.
Seleziona le prime due caselle di controllo a sinistra: All object create events (Tutti gli eventi di creazione di oggetti) e All object removal events (Tutti gli eventi di rimozione di oggetti).
Scorri fino alla sezione Destination (Destinazione) in basso.
Scegli la funzione Lambda come destinazione.
Nell'elenco a discesa, digita il nome della funzione Lambda creata in precedenza.
Fai clic su Save changes (Salva modifiche).
Nella console AWS, accedi alla funzione Lambda che hai creato in precedenza.
Nota che S3 è ora elencato come trigger per la funzione Lambda.
Fai clic sulla scheda Configuration (Configurazione) e poi su Permissions (Autorizzazioni) a sinistra.
Verrà visualizzata un'istruzione di policy che consente a S3 di richiamare la funzione Lambda.
Test della funzione
Invece, la funzione Lambda registra su CloudWatch, quindi è lì che devi andare per vedere la tua funzione operare.
Crea un file di testo sul tuo computer da caricare su S3.
Dalla linea di comando, esegui:
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
Ora vai alla tua funzione Lambda nella console AWS e controlla i log.
Fai clic sulla scheda Monitor e seleziona View logs in CloudWatch (Visualizza i log in CloudWatch).
Il processo è simile per tutti e tre: apri l'estensione AWS, fai clic sui log di CloudWatch e trova il flusso/gruppo di log per /aws/lambda/S3EventHandler. Quindi apri il flusso più recente.
Il processo è simile per tutti e tre: apri l'estensione AWS, fai clic sui log di CloudWatch e trova il flusso/gruppo di log per /aws/lambda/S3EventHandler. Quindi apri il flusso più recente.
Conclusioni
Il punto chiave è che se desideri che la tua funzione Lambda interagisca con altri servizi AWS, devi concederle le autorizzazioni per agire su tali servizi.
Se desideri che altri servizi richiamino la tua funzione, devi utilizzare policy basate sulle risorse per consentire a tali servizi di accedere alla funzione.
Verifica delle conoscenze
1. Quando vuoi che un altro servizio richiami una funzione Lambda cosa devi fare? (seleziona una risposta)
b. Creare un documento di policy basato sulle risorse che conceda ai servizi chiamanti l'autorizzazione a richiamare la funzione Lambda
c. Niente, Lambda si fida di tutti gli altri servizi AWS
d. Aggiungere le autorizzazioni corrette al ruolo di esecuzione della funzione Lambda
2. Cosa devi aggiungere a un ruolo per concedergli le autorizzazioni per accedere ai servizi AWS? (seleziona una risposta)
b. Una policy basata sulle risorse
c. Una policy con le autorizzazioni necessarie
d. Un documento della lista di controllo degli accessi
3. Quali sono i due modi per creare una policy gestita dal cliente da utilizzare con il ruolo di esecuzione della funzione Lambda? (seleziona due risposte)
a. Tramite la linea di comando
b. Includerla nel codice sorgente della funzione
c. Tramite la console AWS
d. Aggiungerla al payload durante l'esecuzione della funzione
Risposte: 1-b, 2-c, 3-a e c
Conclusioni
Il punto chiave è che se desideri che la tua funzione Lambda interagisca con altri servizi AWS, devi concederle le autorizzazioni per agire su tali servizi.
Se desideri che altri servizi richiamino la tua funzione, devi utilizzare policy basate sulle risorse per consentire a tali servizi di accedere alla funzione.