Criando um Serverless .NET Core Web API com AWS Lambda
Para muitos que como eu estão se aventurando na AWS e estudando em como utilizar e implementar os serviços disponíveis na Amazon (que não sou poucos), resolvi compartilhar um pouco do meu aprendizado e mostrar o pouco que aprendi até agora.
Resolvi começar mostrando como criar uma pequena API em .Net Core com AWS Lambda. Para isso, precisaremos de:
- Visual Studio 2019
- AWS Toolkit para o Visual Studio (mostrarei como instalar)
- Ter uma conta na AWS
- Postman
Então vamos lá. Primeiramente vamos instalar o AWS Toolkit for Visual Studio.
Após efetuar o download, clique no instalador e a seguinte tela aparecerá:
Como possuo a versão 2017 e 2019 do Visual Studio, o instalador me dá a opção de instalação nos dois produtos. Apenas clique em Install e espere a instalação ser concluída.
Após a instalação, abra o Visual Studio e veja que novas opções de projetos estarão disponíveis. Clique em Create a New Project e escolha o template AWS Servless Application (.NET Core – C#) e clique em Next:
O nome do nosso projeto será AWSProductListWebAPI e o objetivo dele será inserir e excluir dados de uma lista de produtos que ficará em memória.
Clique em Create.
Escolha a opção AP.NET Core Web API e clique em Next.
Clique em Create e o seu projeto será criado.
Vamos apagar os dois Controllers criados no projeto, pois escreveremos o nosso próprio.
A API que criaremos fará a inclusão de produtos e suas respectivas quantidades em uma lista em memória. Algo bem simples.
Antes de continuarmos, entenda que não é objetivo desse artigo ensinar C#, portanto, descreverei a estrutura e disponibilizarei os fontes a seguir.
Estrutura de nossa API:
- Controllers
- Models
- Services
Controllers
using System.Linq;
using System.Threading.Tasks;
using AWSProductListWebAPI.Models;
using AWSProductListWebAPI.Services;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace AWSProductListWebAPI.Controllers
{
[Route("v1/productList")]
public class ProductListController : ControllerBase
{
private readonly IProductListService _productListService;
public ProductListController(IProductListService productListService)
{
_productListService = productListService;
}
[HttpGet]
public IActionResult GetProductList()
{
var result = _productListService.GetItemsFromProductList();
return Ok(result);
}
[HttpPost]
public IActionResult AddItemToProductList([FromBody] ProductListModel productList)
{
_productListService.AddItemToProductList(productList);
return Ok();
}
[HttpDelete]
public IActionResult DeleteItemsFromProductList([FromBody] ProductListModel productList)
{
_productListService.RemoveItem(productList.Name);
return Ok();
}
}
}
Aqui definimos a rota de chamada de nossa API (v1/productList) e os métodos HTTP get, delete e post.
Models
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace AWSProductListWebAPI.Models
{
public class ProductListModel
{
public string Name { get; set; }
public int Quantity { get; set; }
}
}
Aqui o modelo de nossa lista de produtos
Services
Primeiro a interface de nosso Serviço:
using System.Collections.Generic;
using AWSProductListWebAPI.Models;
namespace AWSProductListWebAPI.Services
{
public interface IProductListService
{
Dictionary GetItemsFromProductList();
void AddItemToProductList(ProductListModel productList);
void RemoveItem(string name);
}
}
E sua implementação:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace AWSProductListWebAPI.Services
{
public class ProductListService : IProductListService
{
private readonly Dictionary _productListStorage = new Dictionary();
public Dictionary GetItemsFromProductList()
{
return _productListStorage;
}
public void AddItemToProductList(Models.ProductListModel productList)
{
_productListStorage.Add(productList.Name, productList.Quantity);
}
public void RemoveItem(string productListName)
{
_productListStorage.Remove(productListName);
}
}
}
A estrutura ficará assim no Visual Studio:
Compile tudo (CTRL+SHIFT+B), e se nenhum erro se apresentar, o seu projeto está íntegro ! 🙂
Vamos fazer um teste. Clique em F5 para executar o projeto e levantar o IIS ( Internet Information Services). Vamos agora testar o nosso serviço utilizando o Postman. Se você não o tem instalado e nem sabe como utilizá-lo, veja o artigo abaixo:
Quando o IIS levantar, o navegador abrirá e mostrará o endereço localhost com a respectiva porta. Copie esse link para utilizarmos na chamada de nossa API.
Vamos fazer a nossa primeira chamada com GET:
Observe que o JSON retornou vazio, pois não inserimos nada em nossa lista de produtos.
Vamos fazer uma chamada com POST incluindo um produto e sua quantidade:
{
"Name": "mouse",
"Quantity": 1
}
Incluiremos outro produto agora:
{
"Name": "keyboard",
"Quantity": 1
}
Agora faremos uma nova chamada GET.
Veja que o retorno foi os dois produtos que enviamos para a lista. Mouse e teclado.
Vamos fazer uma chamada DELETE apagando um produto de nossa lista. Vamos retirar o keyboard de nossa lista.
{
"Name": "keyboard"
}
E um novo GET agora.
Observe que apenas o mouse permanece na lista. Isso mostra que a nossa API está 100% funcional ! 🙂
Agora vem o mais interessante. Vamos publicá-la na AWS ! Para isso, clique com o botão direito no nome da nossa API e escolha a opção Publish to AWS Lambda.
A seguinte tela se apresentará. Clique no botão para incluir o Account profile to use para preencher todos os dados da credencial.
Os principais campos a serem preenchidos são:
- Access Key Id – Chave de acesso do usuário AWS que deverá possuir permissões para fazer a criação do Bucket S3, do Lambda Function e API Gateway
- Secret Access Key – Chave de acesso secreta do usuário
- Account Number – Account Number de sua conta AWS
Criando um usuário na AWS
O usuário que utilizaremos não é o root (master) que acessa todos os serviços da AWS, e sim um que contenha apenas as roles necessárias para a publicação de nossa API.
Clique em Serviços > Identity and Access Managemente (IAM) e depois Adicionar usuario.
Criemos o usuário tester. No Tipo de acesso, habilite o Acesso programático para que tenhamos as chaves de acesso necessárias para publicarmos nossa API. Após isso clique no botão Próximo: Permissões.
Escolha a opção Anexar políticas existentes de forma direta e escolha as permissões abaixo:
Em uma implementação de produção real, nunca daríamos acesso full aos serviço, mas como o objetivo desse artigo não é o aprofundamento na criação de usuário na AWS, vamos prosseguir do jeito mais fácil.
Clique em Criar usuário.
Voltemos ao IAM. Clique no usuário tester que criamos e acesse a aba Credenciais de Segurança. Lá clique em Criar chave de acesso para obtermos o Access Key ID e o Secret Access Key.
Voltemos ao Visual Studio para preenchermos os dados faltantes e clicar em OK. A seguinte tela se apresentará:
Preencha os seguintes campos:
- Region: Região do datacenter onde você publicaremos a nossa API
- Configuration: Release
- Framework: netcoreapp2.1
- Stack Name: ProductListLambdaWebAPI
- S3 Bucket: Se não possuir um criado, clique em New e crie o seu bucket
Clique em Publish.
Se qualquer problema ocorrer, ele efetuará o ROLLBACK do deploy e apresentará a tela acima. Caso tudo funcione como esperamos, a tela abaixo aparecerá:
Onde está em vermelho, aparecerá o link para executarmos a nossa API. No Postman, substitua o localhost por esse link e faça os mesmos testes que efetuamos anteriormente. Se tudo funcionar, meus parabéns ! Você acabou de publicar sua primeira API na AWS !!
Dica: Após o término de seus testes, sugiro que bloqueie o seu bucket S3 para acesso público, pois ele estará exposto a ser chamado por qualquer um. Para isso, acesse sua conta na AWS, clique em Serviços e busque por Amazon S3. Clique na aba Permissões e depois em Editar.
Agora clique em Bloquear todo Acesso Público e depois em Salvar.
Digite confirmar e clique no botão Confirmar.
Pronto ! Seu bucket S3 não estará mais exposto a acesso público !
Assim chegamos ao fim de nosso artigo. Espero que ele seja útil e ajude um pouco a entender e a implementar APIs na AWS.
Fontes