DEV Community

Discussion on: AWS Serverless: 3 aspectos importantes ao projetar uma API Serverless

Collapse
 
oieduardorabelo profile image
Eduardo Rabelo • Edited

obrigado o tempo investido no comentário Bruno,

vou quebrar em pequenos trechos o que você falou e tentar abordar isoladamente cada um deles,

Eu fiquei com uma dúvida. Nos dois exemplos de integração com as lambdas, elas parecem que estão respondendo requests do frontend

vou assumir que você esteja falando da sessão 2.1 e 2.2, realmente temos a imagem tem um computador com tela no lado esquerdo, então faz sentido assumir "frontend", mas ao pensarmos em "cliente", a solicitação pode estar vindo de qualquer consumidor (e.g. mobile app, outra api, um iot device, um frontend etc)

a diferença principal é o objeto de evento que a lambda recebe, como descrito nas imagens 2.1 e 2.2

então a autenticação/autorização pelo bearer é do usuário, é isso mesmo?

como mencionado na sessão 3, os usos mais comuns de autenticação no API Gateway são Lambda Authorizers e Amazon Cognito User Pools como Authorizers.

Como Lambda Authorizers podem executar qualquer tipo de lógica que você quiser, as opções são inúmeras aqui. E sim, utilizar autenticação baseadas em tokens, como OAuth 2.0, é uma opção.

Já para Amazon Cognito User Pools, a única opção é um request assinado e validado com as credenciais do Cognito, bibliotecas como amazon-cognito-identity-js ou amplify-js cuidam disso para gente no ecosistema JavaScript.

...imagine que uma lambda X quisesse chamar outra lambda Y (por exemplo, todas a mini-lambdas do segundo exemplo chamassem uma lambda de log depois de cada execução),

vou trabalhar esse exemplo, mas vou comentar que ter uma lambda para log, como descrito, é desnecessário, pois a integração com CloudWatch no AWS Lambda é nativa.

o que me chama atenção aqui é o "...depois de cada execução", não há como "chamar uma lambda após a execução" aqui,

como estamos trabalhando com execuções síncronas do API Gateway, você terá que usar o aws-sdk para lambda e executar um .invoke ou invokeAsync ainda dentro do handler da sua função ou executar uma chamada HTTP no endereço completo da API Gateway da segunda lambda, seja com http/https ou alguma lib com suporte node.js como superagent ou axios,

...ela também passaria pela mesma autenticação? Lambda X consegue chamar a lambda Y sem autenticação (pois estão no mesmo domínio ou algo do tipo), ou não, elas são completamente independentes?

a resposta curta é: ela não passa pela mesma autenticação, Lambda X consegue sim chamar Lambda Y sem autenticação e não é porque estão no mesmo domínio, e sim elas são completamente independentes,

meio confuso? vou expandir a resposta abaixo,

a resposta longa é:

  • como você vai executar essa segunda lambda?

se você utilisar o aws-sdk, a Lambda X precisa de IAM Policies para invocar Lambdas (e.g. lambda:InvokeFunction), ou seja, você passa/bypass todas as features do API Gateway (e.g. Lambda e Cognito Authorizers) e executa a função diretamente.

caso você use uma chamada HTTP, você estará realizando uma chamada do começo da jornada, entrando pelo API Gateway, então tudo que o API Gateway precisar para aceitar o request, você precisar providenciar. Nesse caso, se você estiver utilizando um Lambda Authorizer, o que for necessário para o seu código de autenticação e no caso de Amazon Cognito, um request assinado e validado como mencionado acima,

  • como a autenticação dessa lambda funciona?

caso sua autenticação aconteça DENTRO da sua Lambda, em código dentro do handler, então seja com aws-sdk ou HTTP request, você precisará fornecer as credenciais necessárias

caso sua autenticação seja feita no API Gateway (e.g. Lambda e Cognito Authorizers), o cenário descrito acima se aplica, aws-sdk bypass, e os dois casos de HTTP,

No caso de ter que passar um token de autenticação, qual token passaria, um long lived que autentica a lambda X ou o mesmo token que ela recebeu?

como mostrado acima, temos vários cenários, vou me focar e assumir o seguinte cenário:

  • Autenticação e Autorização usando OAuth 2.0 Token no Headers de um request utilizando 'Authorization: Token ...'
  • A decodificação e lógico para validar o token acontece DENTRO da sua Lambda, ou seja, código dentro do Handler, como jwt.verify etc
  • Lambda X está exposta um endpoint em "/get-x"
  • Lambda Y está exposta um endpoint em "/get-y"
  • Lambda Z não está exposta, e seu nome é "internal-z"

assumindo o cenário acima, teremos o seguinte flow:

  • a Lambda X recebe o request, decodifica o token e valida o usuário
  • na lógica da Lambda X, executamos uma chamada HTTP para Lambda Y passando o token de autorização recebido, Lambda X fica no aguardo da resposta HTTP
  • a Lambda Y recebe o request, decodifica o token e valida o usuário
  • na lógica da Lambda Y, chamamos o aws-sdk e invocamos assíncronamente Lambda Z passando um payload necessário
  • como a Lambda Y não precisa aguardar a resposta da Lambda Z, o retorno da chamada HTTP é 200 OK
  • Lambda X recebe a resposta HTTP, faz a transformação necessária e responde 200 OK para o cliente
  • a execução da Lambda Z pode terminar a qualquer momento sem interromper o fluxo

fatos a considerar:

  • Lambda X e Lambda Y são expostas como endpoint, ou seja, um consumidor pode chamar Lambda Y diretamente
  • Lambda Y tem IAM Policies para invocar a Lambda Z
  • Não estamos usando Lambda Authorizers ou Amazon Cognito, pois AuthN/AuthZ acontece DENTRO das Lambdas, você pode compartilhar a lógica usando uma função/módulo

ficou claro agora? qualquer coisa só mandar a pergunta! :D


e pensando no seguinte caso:

  • eu quero expor Lambda Y como endpoint mas quero restringir acesso a ela

nesse caso, podemos usar uma das opções descritas na sessão 3, no contexto do exemplo, eu recomendaria Lambda Authorizers ou IAM Policies.

com Lambda Authorizers: você pode procurar algum secret no headers que não seja público e você coloca esse secret apenas quando o request for executado de outra Lambda etc

com IAM Policies: ao usar authorizationType: AWS_IAM você precisará ter um request assinado e validado e as credenciais, baseado no nosso exemplo acima, serão das permissões da IAM Role da Lambda X. Ou seja, teremos: Lambda Y exposta como endpoint e sua autorização no API Gateway é AWS_IAM, se alguém tentar chamar esse endpoint, precisará que sele seja assinado/validado, na execução da Lambda X, assinamos um request com aws4 que irá assumir as credenciais da Lambda X e adicionar os headers necessários, permitindo chamar o endpoint da Lambda Y.

ufa, acabou, qualquer coisa estamos aí! 🤙🤙🤙