Módulo 4: Trabalhar com outros serviços da AWS
MÓDULO DE APRENDIZAGEM
Existem algumas maneiras de trabalhar com outros serviços da AWS.
Se o serviço que você estiver acessando for um banco de dados do AWS RDS, como SQL Server ou o Postgres, você usa as mesmas bibliotecas que usaria se hospedasse os bancos de dados em seu próprio computador ou datacenter. Você precisa de uma cadeia de conexão com nome de usuário e senha, ou outra forma de autenticação de sua preferência. Não há nada diferente do uso diário do banco de dados. Você não precisa de nenhuma permissão adicional para acessar o servidor do banco de dados. A única ressalva é que, se o banco de dados não estiver acessível ao público, você precisará conectar o Lambda à VPC (esse processo requer permissões extras).
Se a função do Lambda estiver usando o S3, DynamoDB, Kinesis etc., você usará os SDKs da AWS para interagir com esses serviços. O perfil sob o qual a função do Lambda está sendo executada precisa de permissões apropriadas para interagir com cada serviço. Por exemplo, se você quiser adicionar um item a um bucket do S3, o perfil precisará de permissão para gravar nesse bucket. Se você quiser obter itens de uma tabela do DynamoDB, o perfil precisará de permissões para ler essa tabela.
O terceiro cenário é quando você quiser que outro serviço acione a função do Lambda em resposta a algum evento. Por exemplo, talvez você queira acionar a função do Lambda quando um novo item for adicionado a um determinado bucket do S3 ou quando os eventos chegarem em um fluxo do Kinesis. Para fazer isso, a função do Lambda deve usar uma “política baseada em recursos”. Essa política concede a outros serviços a permissão para invocar a função do Lambda.
Tempo para a conclusão
30 minutos
Acessar servidores de banco de dados RDS em uma função do Lambda
O melhor de usar serviços conhecidos, como SQL Server, Postgres e MySQL, é que, do ponto de vista do código, você não precisa fazer nada diferente ao chamá-los em uma função do Lambda. Entity Framework/ADO/NpgSql, etc., funcionam tão bem com um banco de dados hospedado na AWS quanto com um banco de dados local ou em rack. Você chama isso da mesma forma, não precisa de uma biblioteca do SDK da AWS. É claro que ainda precisará adicionar os pacotes NuGet relevantes ao seu projeto. Mas, caso contrário, é tudo a mesma coisa.
Acessar os serviços da AWS em uma função do Lambda
2. Como uma política independente que você pode associar a qualquer perfil. Na AWS, a última é chamada de política gerenciada pelo cliente.
É sempre uma boa prática dar ao perfil o mínimo de permissões possível. No exemplo a seguir, em que você lerá a tabela do DynamoDB, você precisa conceder duas permissões ao perfil do Lambda: dynamodb:GetItem e dynamodb:DescribeTable. E você limitará essas permissões à tabela específica na qual estiver interessado.
Primeiro, crie uma nova tabela do DynamoDB chamada Pessoal. Os comandos a seguir funcionarão com o PowerShell, se você estiver usando o prompt de comando do Windows, ou o shell do Linux precisará de um escape diferente para as cadeias de caracteres.
Execute a seguinte consulta:
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
Adicione alguns itens à tabela:
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"}}'
Crie agora uma função do 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
Implante a função do Lambda no AWS Lambda usando:
função de implantação dotnet lambda LambdaFunctionDynamoDB
Agora será necessário “Selecionar o perfil do IAM para fornecer credenciais da AWS ao seu código”. Será apresentada uma lista de perfis criados anteriormente, mas na parte inferior da lista estará a opção “*** Criar novo perfil do IAM ***”. Digite o número ao lado dessa opção.
Será necessário “Inserir o nome do novo perfil do IAM:”. Digite “LambdaFunctionDynamoDBRole”.
Em seguida, você deverá “Selecionar a política do IAM para anexar ao novo perfil e conceder permissões” e uma lista de políticas será apresentada. Selecione AWSLambdaBasicExecutionRole, o número 6 na minha lista. (Eu sei que existe uma política chamada AWSLambdaDynamoDBExecutionRole, mas o objetivo deste módulo é mostrar como você mesmo pode adicionar as permissões necessárias).
Tente invocar a função do 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"
Isso indica que o perfil em que a função do Lambda está sendo executada não tem a permissão necessária do dynamodb:DescribeTable.
Para corrigir isso, você precisa adicionar uma política que conceda ao perfil a permissão dynamoDB:DescribeTable. Conforme mencionamos acima, você pode adicionar uma política em linha (somente para esse perfil) ou uma política independente (disponível para todos os perfis).
Crie um arquivo chamado DynamoDBAccessPolicy.json na pasta LambdaFunctionDynamoDB /src/LambdaFunctionDynamoDB.
Edite o DynamoDBAccessPolicy, mas use o número da sua conta no 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
Desta vez, a mensagem é:
"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",
Atualize o arquivo DynamoDBAccessPolicy.json com o seguinte -
{
"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"
Outra opção é passar o mouse sobre o método SDK que você estiver usando. Os metadados podem conter informações úteis sobre as permissões. Nem todos os metadados do método conterão informações sobre as permissões.
Agora você sabe como descobrir quais permissões sua função precisa e como conceder as permissões corretas para o perfil nos quais as funções do Lambda estão sendo executadas.
Permitir que outros serviços invoquem as funções do Lambda
Na seção anterior, você aprendeu a conceder permissões à função do Lambda para realizar ações em outros serviços. Nesta seção, você verá como conceder a outros serviços permissões para invocar sua função do Lambda.
Se você estiver usando os modelos sem servidor.*, provavelmente já estará concedendo a um API Gateway a permissão necessária para invocar a função do Lambda. Se você implantou essa função, acesse a guia Configuração, selecione Permissões à esquerda e vá até a seção Política baseada em recursos. Você verá políticas que permitem que o API Gateway invoque a função do Lambda. Essa política foi adicionada pelo comando dotnet lambda deploy-serverless e pelo serverless.template em seu projeto.
Na imagem abaixo, você pode ver duas declarações de política que permitem que um API Gateway invoque a função do Lambda.
Crie o bucket do S3
Se você quiser o bucket na região us-east-1, use o seguinte 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
Criar a função do Lambda
Na linha de comando, execute:
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 o evento do S3 for em resposta à exclusão de um objeto, a função registrará os nomes dos buckets e das chaves no CloudWatch.
Excluir a função do Lambda
dotnet lambda deploy-function S3EventHandler
Agora será necessário “Selecionar o perfil do IAM para fornecer credenciais da AWS ao seu código”. Será apresentada uma lista de perfis criados anteriormente, mas na parte inferior da lista estará a opção “*** Criar novo perfil do IAM ***”. Digite o número ao lado dessa opção.
Será necessário “Inserir o nome do novo perfil do IAM:”. Digite “S3EventHandlerRole”.
Em seguida, você deverá “Selecionar a política do IAM para anexar ao novo perfil e conceder permissões” e uma lista de políticas será apresentada. Selecione AWSLambdaBasicExecutionRole, o número 6 na minha lista. Você precisará adicionar uma política para conceder acesso ao bucket do S3 para que a chamada GetObjectMetadataAsync(..) funcione.
Conceda permissões à função do Lambda para obter os metadados do objeto
Você verá como fazer isso de formas diferentes.
A política ficará assim, mas com o nome do bucket no recurso. Observe o /* no final. Isso significa que s3:GetObject se aplica a todos os objetos no 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
Em seguida, anexe a política ao perfil criado anteriormente. Execute o seguinte:
aws iam attach-role-policy --role-name S3EventHandlerRole --policy-arn arn:aws:iam::694977046108:policy/S3AccessPolicyForCourseBucket
Clique na guia Configuração, depois em Permissões à esquerda e clique no nome do perfil.
Clique em Adicionar permissões e em Anexar políticas.
Clique em Criar política.
Na seção Ações, digite getobject e selecione GetObject na lista.
Na seção de recursos, escolha Específico e clique em Adicionar ARN.
Volte para a guia na qual você clicou em Criar política. Siga estas etapas:
1. Recarregue a lista de políticas
2. Digite S3AccessPolicyForCourseBucket no filtro
3. Marque a caixa ao lado da política
4. Clique em Anexar políticas
Aqui você terá um bucket do S3, a função do Lambda e as permissões necessárias para obter os metadados do objeto no bucket do S3.
Agora é hora de conectar o bucket do S3 à função do Lambda, então os eventos de criação e exclusão acionam a função do Lambda.
Acione a função do Lambda no bucket do S3
Abra a lista de buckets no S3 https://s3.console.aws.amazon.com/s3/buckets.
Clique no que você criou.
Desça até a seção Notificações de eventos.
Clique em Criar notificação de evento.
Dê um nome para a notificação do evento.
Marque as duas primeiras caixas de seleção à esquerda - Todos os eventos de criação de objetos e Todos os eventos de remoção de objetos.
Vá até a seção Destino na parte inferior.
Escolha a função do Lambda como destino.
Na lista suspensa, digite o nome da função do Lambda que você criou anteriormente.
Clique em Salvar alterações.
No console da AWS, acesse a função do Lambda que você criou anteriormente.
Observe que o S3 agora está listado como um acionador para a função do Lambda.
Clique na guia Configuração e, em seguida, em Permissões à esquerda.
Você verá uma declaração de política permitindo que o S3 invoque a função do Lambda.
Teste
Em vez disso, a função do Lambda registra no CloudWatch, então é lá que você precisará ir para ver a função em ação.
Crie um arquivo de texto no seu computador para fazer o upload para o S3.
Na linha de comando, execute:
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
Agora, acesse a função do Lambda no console da AWS e verifique os logs.
Clique na guia Monitorar e, em seguida, em Exibir logs no CloudWatch.
O processo é semelhante para os três. Abra a extensão da AWS, clique nos registros do CloudWatch e encontre o fluxo ou grupo de logs para /aws/lambda/S3EventHandler. Em seguida, abra o fluxo mais recente.
O processo é semelhante para os três. Abra a extensão da AWS, clique nos registros do CloudWatch e encontre o fluxo ou grupo de logs para /aws/lambda/S3EventHandler. Em seguida, abra o fluxo mais recente.
Conclusão
Esta é a principal conclusão: se você quiser que a função do Lambda interaja com outros serviços da AWS, precisará conceder à função permissões para atuar nesse outro serviço.
Se você quiser que outros serviços invoquem a função, será necessário usar políticas baseadas em recursos para conceder a esses serviços acesso à sua função.
Verificação de conhecimento
1. Quando você quiser que outro serviço invoque uma função do Lambda, o que precisará fazer? (selecione um)
b. Criar um documento de política baseado em recursos que dê aos serviços de chamada permissão para invocar a função do Lambda
c. Nada, o Lambda confia em todos os outros serviços da AWS
d. Adicione as permissões corretas ao perfil que a função do Lambda executa como 1
2. O que você precisa adicionar a um perfil para conceder a ele permissões de acesso aos serviços da AWS? (selecione um)
b. Políticas baseadas em recursos
c. Uma política com as permissões necessárias
d. Um documento de lista de controle de acesso
3. Quais são as duas maneiras de criar uma política gerenciada pelo cliente para uso com um perfil que uma função do Lambda desempenha? (selecione dois)
a. Por meio da linha de comando
b. Incluir no código-fonte da função
c. Por meio desse console da AWS
d. Adicionando à carga útil quando executar a função
Respostas: 1-b, 2-c, 3-ac
Conclusão
Esta é a principal conclusão: se você quiser que a função do Lambda interaja com outros serviços da AWS, precisará conceder à função permissões para atuar nesse outro serviço.
Se você quiser que outros serviços invoquem a função, será necessário usar políticas baseadas em recursos para conceder a esses serviços acesso à sua função.