Workloads do .NET no AWS Lambda

MÓDULO 4

Módulo 4: Trabalhar com outros serviços da AWS

 MÓDULO DE APRENDIZAGEM

Observe que você pode seguir os exemplos apresentados aqui, mas isso não é necessário.

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

Para acessar a maioria dos serviços da AWS, você precisa dar permissão à função do Lambda para interagir com esse serviço. Faça isso adicionando uma política ao perfil sob a qual a função do Lambda estiver sendo executada. A política precisará conceder permissão à função do Lambda para interagir com o serviço. Você pode criar a política de duas maneiras:
1. como uma política em linha na qual você a usa somente com esse perfil.

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
Memorize o TableArn, você o usará daqui a pouco. Ele estará próximo à parte inferior do resultado.

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"}}'
Agora você tem uma tabela com três itens.

Crie agora uma função do Lambda usando:
dotnet new lambda.EmptyFunction -n LambdaFunctionDynamoDB 
Mude para o diretório LambdaFunctionDynamoDB /src/LambdaFunctionDynamoDB e adicione o pacote NuGet AWSSDK.DynamoDBv2:
cd LambdaFunctionDynamoDB /src/LambdaFunctionDynamoDB 
dotnet add package AWSSDK.DynamoDBv2
Em seguida, abra o Function.cs e substitua o código pelo seguinte:
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;}
}
Implante a função do Lambda no AWS Lambda usando:
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 
Você receberá uma mensagem de erro longa, mas na parte de cima verá algo como -
 "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"
Observe a mensagem: “...nenhuma política baseada em identidade permite a ação dynamodb:DescribeTable”.

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"
        }
    ]
}
Execute o seguinte:
aws iam put-role-policy --role-name LambdaFunctionDynamoDBRole --policy-name LambdaFunctionDynamoDBAccess --policy-document file://DynamoDBAccessPolicy.json
A política pode demorar um pouco para entrar em vigor. Você pode esperar alguns minutos ou implantar a função do Lambda novamente. Se você quiser reimplantar a função, execute:
dotnet lambda deploy-function LambdaFunctionDynamoDB 
Depois que a função do Lambda for implantada, você poderá invocá-la novamente usando:
dotnet lambda invoke-function LambdaFunctionDynamoDB
Outro erro!

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",
Você precisa adicionar “dynamodb:GetItem” às várias permissões na política.

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"
    }
  ]
}
Implemente a função do Lambda novamente:
dotnet lambda deploy-function LambdaFunctionDynamoDB
Invoque novamente:
dotnet lambda invoke-function LambdaFunctionDynamoDB 
Sucesso!
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"
As mensagens de erro do Lambda serão muito úteis para tentar dar o mínimo de permissões possível a um perfil, mas, como você viu, talvez seja necessário repetir esse processo algumas vezes.

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.
Consulte também a documentação do serviço da AWS para obter informações sobre as permissões necessárias.

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

Você terá muitos cenários em que precisará de outro serviço para invocar uma função do Lambda para você. Alguns cenários comuns incluem a chegada de uma mensagem em uma fila, a chegada de um evento em um fluxo do Kinesis, uma alteração em um objeto/bucket no S3, uma solicitação que chega a um API Gateway. Em cada um desses casos, a função do Lambda será invocada por outro serviço da AWS.

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.
Mas o exemplo em que você trabalhará permite que um bucket do S3 invoque a função do Lambda sempre que você criar ou excluir um arquivo nesse bucket.

Crie o bucket do S3

A primeira etapa é criar um 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
Se você quiser o bucket em uma região diferente, use o seguinte comando -
aws s3api create-bucket --bucket my-unique-bucket-name-lambda-course --create-bucket-configuration LocationConstraint=REGION
Para obter uma lista das regiões válidas para o LocationConstraint, consulte o link a seguir - https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3api/create-bucket.html.

Observe que o nome do bucket deve ser exclusivo. Veja aqui para saber mais

Criar a função do Lambda

Há um modelo de função do Lambda que ajudará você a lidar com os eventos do S3. Ele tem os pacotes NuGet do SDK necessários já adicionados. Você ainda precisa adicionar a permissão necessária do perfil e criar a política baseada em recursos para permitir que o S3 invoque a função.

Na linha de comando, execute:
dotnet new lambda.S3 -n S3EventHandler
Mude para o diretório S3EventHandler/src/S3EventHandler:
cd S3EventHandler/src/S3EventHandler
Abra o arquivo Function.cs, substitua o método FunctionHandler pelo seguinte:
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}");
        }
    }
}
Quando a função do Lambda recebe um evento do S3, ela registra os detalhes do evento no CloudWatch. Se o evento do S3 for em resposta à criação de um objeto, a função usará o SDK da AWS para fazer uma chamada ao S3 para obter o tipo de arquivo e, em seguida, registrar os detalhes.

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

Na linha de comando, execute:
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

No exemplo anterior, você criou uma política em linha que se aplicava somente ao perfil que você estava usando. Desta vez, você criará uma política que qualquer perfil poderá usar.

Você verá como fazer isso de formas diferentes.
Linha de comando
 
Crie um arquivo chamado S3AccessPolicyForCourseBucket.json na pasta S3EventHandler/src/S3EventHandler.

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/*"
        }
    ]
}
Execute o seguinte:
aws iam create-policy --policy-name S3AccessPolicyForCourseBucket --policy-document file://S3AccessPolicyForCourseBucket.json
Anote o ARN da política.

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
Console da AWS
 
Acesse a função do Lambda no Console da AWS.

Clique na guia Configuração, depois em Permissões à esquerda e clique no nome do perfil.
Isso abre uma nova página com detalhes do perfil.

Clique em Adicionar permissões e em Anexar políticas.

Clique em Criar política.

Na seção de serviço, digite s3 na caixa de texto destacada e selecione S3.

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.

Digite o nome do bucket e selecione Qualquer para o nome do objeto.
Digite um nome para a política e clique em Criar política

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

Como você viu, é importante poder usar as ferramentas de linha de comando da AWS e o console de interface do usuário. Na a próxima etapa, você usará o console de IU, porque é mais fácil e claro para essa etapa.

Abra a lista de buckets no S3 https://s3.console.aws.amazon.com/s3/buckets.

Clique no que você criou.
Selecione a guia Propriedades.

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.

Quando terminar, você verá essa nova notificação de evento listada na seção Notificações de eventos.

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.

Role para baixo até a seção de política baseada em recursos

Você verá uma declaração de política permitindo que o S3 invoque a função do Lambda.
Clique na ID da declaração para revisar a declaração de política.

Teste

Essa função do Lambda não retorna nada para o chamador, neste caso, o S3.

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.

Você receberá uma lista de fluxos de log, escolha o mais recente.
Você verá entradas de log que mostram os eventos do S3 e o texto que você registrou no CloudWatch.
Outra forma de verificar os logs é usar a extensão da AWS para Visual Studio, Visual Studio Code e Rider.

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.
Outra forma de verificar os logs é usar a extensão da AWS para Visual Studio, Visual Studio Code e Rider.

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

Neste módulo relativamente curto, você aprendeu bastante. Alguns diriam que entender os perfis e as políticas é um dos aprendizados mais importantes na AWS. Espero que isso tenha proporcionado a você uma boa base em relação às funções do Lambda.

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

Agora você concluiu o Módulo 4, Trabalhar com outros serviços da AWS. O teste a seguir verificará o que você aprendeu até agora.

1. Quando você quiser que outro serviço invoque uma função do Lambda, o que precisará fazer? (selecione um)

a. Criar um documento de ACL dando ao perfil o outro serviço executado como permissão para invocar a função 5 do Lambda

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)

a. Nada, todos os perfis podem acessar outros serviços da AWS.

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

Neste módulo relativamente curto, você aprendeu bastante. Alguns diriam que entender os perfis e as políticas é um dos aprendizados mais importantes na AWS. Espero que isso tenha proporcionado a você uma boa base em relação às funções do Lambda.

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.

Essa página foi útil?

TESTE DE UNIDADE E DEPURAÇÃO