Como criar uma API segura com gRPC
Vitalis Ogbonna
25 de agosto de 2022
0 minutos de leituraUma chamada de procedimento remoto do Google (gRPC) é a versão de código aberto do Google do framework de chamada de procedimento remoto (RPC). Trata-se de um protocolo de comunicação que utiliza HTTP/2 e a tecnologia Protocol Buffers (protobuf). O gRPC permite que um cliente ou servidor remoto se comunique com outro servidor simplesmente chamando uma função do servidor de destino como se ela fosse local. Isso facilita muito a comunicação e a transferência de grandes conjuntos de dados entre cliente e servidor em sistemas distribuídos.
Assim como outros sistemas RPC, o gRPC define um serviço. Ele especifica seus métodos e tipos de retorno usando protobuf — um protocolo do Google para serialização e desserialização —, o que facilita a definição de serviços e a geração automática de bibliotecas de cliente. O gRPC usa esse protocolo, atualmente na versão 3, como linguagem de definição de interface e conjunto de ferramentas de serialização.
Para a maioria das aplicações modernas, o gRPC é uma excelente opção por oferecer suporte excepcional a todos os tipos de dados. Ele é mais indicado para grandes volumes de dados, como os transmitidos por streaming, e pode ser excessivo para aplicações simples nas quais a transferência de grandes volumes não é uma preocupação.
Este artigo demonstra como usar gRPC para estabelecer uma comunicação entre cliente e servidor em duas aplicações Node.js. Também destacamos algumas medidas de segurança ao usar gRPC como mecanismo de comunicação nos seus serviços.
Pré-requisitos do tutorial
Para acompanhar este tutorial, você precisa ter o OpenSSL e o Node.js (versão 4.0 ou posterior) instalados no seu computador. É essencial ter conhecimentos básicos de Node.js e JavaScript. Você também precisa garantir que seu ambiente de trabalho tenha privilégios administrativos.
Configurando o projeto Node.js
Para começar, crie uma pasta chamada event-app-node-grpc para definir a estrutura de diretórios da aplicação e inicialize um projeto Node.js com npm executando os seguintes comandos:
Depois de inicializar a aplicação, crie a seguinte estrutura de diretórios. Você pode acessar no GitHub o código completo usado neste tutorial:
Instalando os pacotes
No terminal, acesse o diretório raiz da aplicação. Instale os pacotes a seguir usando o comando npm install, conforme mostrado no trecho de código:
Veja o que fazem os pacotes instalados no trecho de código acima:
Expressé o servidor HTTP da sua aplicação.@grpc/grpc-jsé uma biblioteca gRPC para Node.js. Ela permite criar um serviço gRPC no ambiente de execução Node.js.@grpc/proto-loaderé um pacote necessário para carregar arquivos protobuf e usá-los com gRPC. Ele usa o pacote versão 3 doprotobuf.js.
Depois de instalar os pacotes acima, abra o arquivo package.json e adicione as configurações extras a seguir às tags scripts, como mostrado no trecho de código:
As configurações adicionais mostradas no trecho de código acima definem o ambiente de execução da aplicação e a geração do certificado SSL. Depois de adicioná-las, seu arquivo package.json atualizado ficará parecido com o trecho de código abaixo:
O trecho de código acima mostra o arquivo package.json atualizado, com os comandos de configuração do ambiente de execução da aplicação e de geração do certificado SSL adicionados à tag scripts.
Definindo o Protocol Buffer
Este tutorial mostra como usar gRPC em uma aplicação simples de rastreamento de eventos. A aplicação de demonstração recebe detalhes de eventos e os salva em um banco de dados em memória, permitindo atualizar, buscar e excluir os dados dos eventos.
Em aplicações gRPC, a interface do serviço e os payloads necessários ficam em um arquivo protobuf para permitir a comunicação entre diferentes aplicações. Os arquivos protobuf têm a extensão .proto, como mostra o esquema de configuração do nosso projeto.
Agora, crie um arquivo events.proto no diretório raiz da aplicação e adicione o código a seguir. Para consultar a estrutura do projeto, use como referência o esquema que definimos anteriormente.
Nos trechos de código acima, que definem o proto, primeiro especificamos a versão do Protocol Buffer com a declaração syntax = "proto3" e, em seguida, definimos o serviço do protocolo.
Em seguida, na descrição do serviço de eventos do protocolo, criamos um serviço chamado EventService. Depois, criamos funções rpc nesse serviço, com os parâmetros necessários e os valores de retorno esperados. Você pode definir quantos serviços sua aplicação precisar, mas, para simplificar, vamos definir apenas um.
Também definimos os tipos de dados da função rpc na definição de EventService e os valores de retorno usando o sistema exclusivo de numeração de campos do gRPC. Ele especifica o número de bytes usados durante a codificação. Saiba mais na documentação oficial do protobuf.
Criando o servidor gRPC
Seguindo a estrutura de diretórios acima, crie uma pasta server no diretório raiz da aplicação e, dentro dela, crie um arquivo index.js. Cole o trecho de código a seguir no arquivo recém-criado server/index.js:
No trecho de código acima, importamos o arquivo events.proto, definido anteriormente, para a variável PROTO_PATH e o carregamos usando o método loadSync da biblioteca protoLoader. Em seguida, salvamos as definições do proto na variável eventsProto, que armazena todas elas.
Em seguida, adicione o trecho de código a seguir logo depois da variável eventsProto no arquivo server/index.js definido anteriormente.
No trecho de código acima, importamos o pacote node:crypto e sua função randomUUID, usada para gerar strings exclusivas aleatórias para os IDs dos eventos. Como usamos um banco de dados em memória neste tutorial, vamos defini-lo como um array para armazenar a lista de eventos e, em seguida, configurar a instância do servidor chamando um novo método grpc.Server.
Em seguida, vamos registrar os serviços da aplicação. Para isso, adicione o trecho de código a seguir logo depois da variável server no trecho de código acima:
No trecho de código acima, chamamos o método addService na instância do servidor gRPC para registrar os serviços da aplicação, que basicamente realizam operações de criação, leitura e atualização dos eventos.
Para iniciar o servidor da aplicação, cole o trecho de código a seguir logo depois do método addService mostrado no trecho de código acima.
Criando o cliente gRPC
Seguindo a estrutura de diretórios acima, crie uma pasta client no diretório raiz da aplicação e, dentro dela, crie dois arquivos: index.js e app.js. Cole o trecho de código a seguir no arquivo client/app.js.
No trecho de código acima, importamos as definições do proto criadas anteriormente, carregamos o arquivo com protoLoader, conectamos o cliente grpc ao endereço IP da aplicação do servidor e exportamos o serviço de eventos com o nome de variável client. Também associamos um certificado SSL ao cliente para autenticar e criptografar as comunicações entre cliente e servidor.
Em seguida, cole o trecho de código a seguir no arquivo client/index.js:
No trecho de código acima, importamos event-service do arquivo client/app.js. Depois, configuramos um servidor Express com endpoints simples para gerenciar a creation, a update, a fetch e a delete de eventos, chamando remotamente a aplicação do servidor com gRPC.
Testando as aplicações do servidor e do cliente
Agora podemos testar o que fizemos para confirmar que está tudo certo.
O servidor
No terminal, acesse o diretório raiz do projeto e execute os seguintes comandos:
O servidor da aplicação deverá estar disponível em http://localhost:50051:
O cliente
Abra uma nova janela do terminal, acesse a pasta client a partir do diretório raiz da aplicação e execute os seguintes comandos:
A aplicação deverá estar disponível em http://localhost:50050:
Para testar, acesse localhost:50050 no navegador ou use uma ferramenta de teste de API, como o Postman. Você deverá ver o evento padrão que adicionamos inicialmente ao array de eventos. A resposta deverá ser igual à captura de tela abaixo:

Autenticando e protegendo a API gRPC
O protocolo gRPC oferece suporte a vários mecanismos de autenticação, o que facilita sua adaptação a sistemas novos e existentes. Podemos implementar a autenticação nas comunicações entre cliente e servidor gRPC usando mecanismos recomendados, como SSL e TLS, com ou sem autenticação baseada em tokens do Google. Também podemos criar uma autenticação personalizada estendendo a função de autenticação integrada ao gRPC.
Por padrão, o gRPC inclui os seguintes mecanismos de autenticação:
SSL e TLS para autenticar o servidor e criptografar os dados trocados entre cliente e servidor
ALTS (um protocolo mútuo de transporte e autenticação desenvolvido pelo Google) para proteger as comunicações RPC de aplicações executadas na Google Cloud Platform (GCP)
Mecanismo genérico de autenticação baseada em tokens para incluir credenciais baseadas em metadados nas solicitações e respostas
Como mencionamos na introdução do tutorial, vamos implementar a autenticação usando SSL e, em seguida, modificar os arquivos client/app.js e server/index.js para incorporar essa mudança.
Gerando um certificado SSL com OpenSSL
Primeiro, vamos gerar um certificado SSL usando o OpenSSL. Para isso, você precisa ter o OpenSSL instalado e permissão para executar scripts bash. Esses requisitos são essenciais para evitar erros de permissão.
Na estrutura de diretórios do projeto, crie uma pasta scripts e, dentro dela, um arquivo chamado generate-certs.sh. Cole o trecho de código a seguir nesse arquivo:
O código acima gera os certificados SSL necessários para estabelecer uma conexão segura e criptografada entre as aplicações do servidor e do cliente. Quando executado, ele cria uma pasta certs, gera os certificados SSL do servidor e do cliente com o OpenSSL e os salva na pasta certs. Para saber mais sobre essas configurações e sua finalidade, acesse o site do OpenSSL.
Gerando um certificado SSL para a aplicação com npm
Agora, use o script para gerar um certificado SSL para a aplicação. No terminal, acesse o diretório raiz da aplicação e execute os seguintes comandos.
Isso cria uma pasta certs com os certificados SSL gerados.
Atenção: são necessários alguns privilégios administrativos. Se ocorrer um erro de permissões ao executar o script, use os comandos a seguir para conceder permissão de execução e tente novamente.
O terminal deverá exibir a seguinte saída:
Atualizando os arquivos client/app.js e server/index.js
Até agora, geramos os certificados SSL necessários para autenticar nossas APIs gRPC. Agora, vamos modificar os arquivos client/index.js e server/index.js para usar os certificados gerados.
No arquivo client/app.js atualizado, mostrado abaixo, adicionamos o módulo fs para ler os certificados gerados e usamos esses certificados para criar credenciais SSL do gRPC. Por fim, aplicamos essas credenciais ao serviço gRPC.
Também adicionamos o módulo fs ao arquivo server/index.js atualizado, mostrado abaixo, para ler os certificados gerados. Em seguida, usamos esses certificados para criar credenciais SSL do gRPC e aplicá-las ao servidor.
Executando as aplicações do servidor e do cliente
Implementamos com sucesso uma solução de gerenciamento de eventos usando as especificações gRPC. Para testar os endpoints, inicie a aplicação pelo terminal seguindo as etapas abaixo.
O servidor
No terminal, acesse o diretório raiz do projeto e execute os seguintes comandos:
Depois de executar os comandos, o servidor deverá estar disponível em http://0.0.0.0:50051:
O cliente
Abra uma nova janela do terminal, acesse a pasta do cliente a partir do diretório raiz da aplicação e execute os seguintes comandos:
Depois de executar os comandos, a aplicação cliente deverá estar disponível em http://localhost:50050:
Para testar a aplicação, acesse localhost:50050 no navegador ou use uma ferramenta de teste de API, como o Postman. Você verá o evento padrão que adicionamos inicialmente ao nosso array de eventos. A resposta deverá ser igual à captura de tela abaixo:

Você pode testar outros endpoints adicionados à aplicação para garantir que tudo funcione como esperado.
Você criou uma API segura com gRPC!
Neste tutorial, criamos uma API simples com gRPC usando Node.js e apresentamos seus conceitos de funcionamento e suas diversas vantagens, como o uso de HTTP/2 e SSL/TLS para autenticação e criptografia de ponta a ponta, que aumentam a segurança da API.
Apesar dessas vantagens, o gRPC também tem pontos fracos, como o suporte limitado nos navegadores, o formato de dados não legível por humanos, a curva de aprendizado íngreme e o suporte precário ao cache na borda. Ainda assim, o gRPC é a melhor opção para a comunicação entre microsserviços internos, graças ao desempenho incomparável e ao suporte a várias linguagens. O protocolo gRPC é impressionante e, desde seu lançamento, em agosto de 2016, vem sendo amplamente adotado no setor. Essa adoção deve continuar crescendo.
Há muitas outras possibilidades com o gRPC. O exemplo deste tutorial é apenas a ponta do iceberg. Consulte a documentação para aprofundar seus conhecimentos sobre gRPC, aprimorar os processos de comunicação da sua aplicação e conhecer estratégias para manter a segurança do gRPC.
