Padrões de segurança para arquiteturas de microsserviço
Se você participar de muitas conferências de ecossistema java, você vai pensar que todo mundo usa microsserviços. É um tópico da moda, e desenvolvedores em todos os lugares estão interessados em aprender sobre eles. Por uma boa razão também! Arquiteturas de microsserviço são uma técnica para fornecer código mais rapidamente.
Chris Richardson é um amigo e especialista em microserviços. Ele sugere uma diretriz útil em um post recente no blog:
Por que microsserviços?
IF
you are developing a large/complex application
AND
you need to deliver it rapidly, frequently and reliably
over a long period of time
THEN
the Microservice Architecture is often a good choice
Chris Richardson também dirige microservices.io, que lista inúmeros padrões de microsserviço na parte inferior. Notei que “Token de acesso” é o único item sob segurança.
Na mesma linha da lista de Chris, nem todos precisam dos padrões neste post. Por exemplo, se eu disser para usar tokens PASETO em vez de JWT quando possível, isso vai ser difícil para desenvolvedores que usam Okta ou outros IdPs que não oferecem PASETO.
Abaixo estão 11 padrões que recomendo para proteger arquiteturas de microsserviço.
Table of Contents
- 1. Seja seguro por design
- 2. Digitalizar dependências
- 3. Use HTTPS Em todos os lugares
- 4. Use tokens de acesso e identidade
- 5. Criptografar e proteger segredos
- 6. Verifique a segurança com os dutos de entrega
- 7. Retardar atacantes
- 8. Use o modo Sem Raiz Docker
- 9. Use a segurança baseada no tempo
- 10. Digitalizar a configuração de Docker e Kubernetes para vulnerabilidades
- 11. Conheça sua segurança em nuvem e cluster
- Saiba mais sobre microsserviços e segurança da Web
1. Seja seguro por design
Código seguro é o melhor código. Seguro por design significa que você assa segurança em seu design de software desde o início. Se você tiver entrada de usuário, higienize os dados e remova caracteres maliciosos.
Perguntei ao meu amigo Rob Winch o que ele achava de remover personagens maliciosos. Rob é o líder do projeto de Segurança da Primavera, e amplamente considerado um especialista em segurança.
Acho que faz sentido projetar seu código para estar seguro desde o início. No entanto, remover caracteres maliciosos é complicado na melhor das hipóteses. O que é um personagem malicioso realmente depende do contexto em que ele é usado. Você pode garantir que não há caracteres maliciosos em um contexto HTML apenas para descobrir que existem outros ataques de injeção (ou seja, JavaScript, SQL, etc). É importante notar que mesmo a codificação de documentos HTML é baseada contextualmente.
Além disso, nem sempre é prático limitar os personagens. Em muitos contextos um ‘ é um personagem malicioso, mas este é um personagem perfeitamente válido em nome de alguém. O que deve ser feito então?
Acho melhor garantir que os caracteres sejam devidamente codificados no contexto em que estão sendo usados em vez de tentar limitar os caracteres.
— Rob Winch
Como engenheiros, somos ensinados desde cedo sobre a importância de criar softwares e arquiteturas bem projetados. Você estuda e se orgulha disso. Design é uma parte natural do software de construção.
Ameaças de segurança bem conhecidas devem impulsionar decisões de design em arquiteturas de segurança. Técnicas e padrões reutilizáveis fornecem soluções para aplicar a autenticação, autorização, confidencialidade, integridade de dados, privacidade, responsabilidade e disponibilidade, mesmo quando o sistema está sob ataque.
O Top 10 da OWASP realmente não mudou muito nos últimos dez anos. Por exemplo, apesar de ser a abordagem número um usada para educar engenheiros defensivos sobre como proteger seus aplicativos, a injeção SQL ainda é o ataque mais comum. Continuamos repetindo os mesmos erros que expuseram sistemas há uma década.
— Johnny Natal
É por isso que as precauções de segurança precisam ser cozidas em sua arquitetura.
Gosto do exemplo do livro Secure by Design, de Dan Bergh Johnsson, Daniel Deogun e Daniel Sawano. Eles mostram como você pode desenvolver um objeto básico que exibe um nome de usuário em uma página.User
public class User {
private final Long id;
private final String username;
public User(final Long id, final String username) {
this.id = id;
this.username = username;
}
// ...
}
Se você aceitar qualquer valor de string para o nome de usuário, alguém pode usar o nome de usuário para executar ataques XSS. Você pode corrigir isso com validação de entrada, como o seguinte.
import static com.example.xss.ValidationUtils.validateForXSS;
import static org.apache.commons.lang3.Validate.notNull;
public class User {
private final Long id;
private final String username;
public User(final Long id, final String username) {
notNull(id);
notNull(username);
this.id = notNull(id);
this.username = validateForXSS(username);
}
}
No entanto, este código ainda é problemático.
-
Os desenvolvedores precisam pensar em vulnerabilidades de segurança
-
Desenvolvedores têm que ser especialistas em segurança e saber usar
validateForXSS()
-
Ele assume que a pessoa que escreve o código pode pensar em cada fraqueza potencial que pode ocorrer agora ou no futuro
Um projeto melhor é criar uma classe que encapsula todas as preocupações de segurança.Username
import static org.apache.commons.lang3.Validate.*;
public class Username {
private static final int MINIMUM_LENGTH = 4;
private static final int MAXIMUM_LENGTH = 40;
private static final String VALID_CHARACTERS = "[A-Za-z0-9_-]+";
private final String value;
public Username(final String value) {
notBlank(value);
final String trimmed = value.trim();
inclusiveBetween(MINIMUM_LENGTH,
MAXIMUM_LENGTH,
trimmed.length());
matchesPattern(trimmed,
VALID_CHARACTERS,
"Allowed characters are: %s", VALID_CHARACTERS);
this.value = trimmed;
}
public String value() {
return value;
}
}
public class User {
private final Long id;
private final Username username;
public User(final Long id, final Username username) {
this.id = notNull(id);
this.username = notNull(username);
}
}
Dessa forma, seu design torna mais fácil para os desenvolvedores escrever código seguro.
Escrever e enviar código seguro vai se tornar cada vez mais importante à medida que colocamos mais software em robôs e dispositivos incorporados.
2. Digitalizar dependências
As dependências de terceiros compõem 80% do código que você implanta na produção. Muitas das bibliotecas que usamos para desenvolver software dependem de outras bibliotecas. Dependências transitivas levam a uma (às vezes) grande cadeia de dependências, algumas das quais podem ter vulnerabilidades de segurança.
Você pode usar um programa de digitalização em seu repositório de código-fonte para identificar dependências vulneráveis. Você deve procurar vulnerabilidades em seu pipeline de implantação, em sua linha principal de código, em versões de código lançadas e em novas contribuições de código.
Pesquisa Snyk: 25% dos projetos não relatam problemas de segurança; A maioria só adiciona nota de liberação; Apenas 10% relatam CVE;
Em suma, use ferramentas para priorizar, mas SEMPRE atualize dependências!
— Rob Winch
Se você é um usuário do GitHub, você pode usar o dependabot para fornecer atualizações automatizadas através de solicitações de pull. O GitHub também fornece alertas de segurança que você pode ativar em seu repositório.
Você também pode usar soluções mais completas, como Snyk e JFrog Xray.
3. Use HTTPS Em todos os lugares
Você deve usar HTTPS em todos os lugares, mesmo para sites estáticos. Se você tiver uma conexão HTTP, mude-a para uma HTTPS. Certifique-se de que todos os aspectos do seu fluxo de trabalho — desde repositórios do Maven até XSDs — consulte URIs HTTPS.
HTTPS tem um nome oficial: Transport Layer Security (também conhecido como TLS). Ele foi projetado para garantir privacidade e integridade de dados entre aplicativos de computador. Como o HTTPS Works é um excelente site para aprender mais sobre HTTPS.
Para usar HTTPS, você precisa de um certificado. É uma espécie de carteira de motorista e serve duas funções. Ele concede permissões para usar comunicação criptografada via Public Key Infrastructure (PKI), e também autentica a identidade do titular do certificado.
Vamos criptografar oferece certificados gratuitos, e você pode usar sua API para automatizar a renovação deles. De um artigo recente do InfoQ de Sergio De Simone:
Let’s Encrypt foi lançado em 12 de abril de 2016 e de alguma forma transformou a Internet fazendo um processo caro e demorado, como o uso de HTTPS através de um certificado X.509, em um serviço simples, gratuito e amplamente disponível. Recentemente, a organização anunciou que emitiu um bilhão de certificados no geral desde sua fundação e estima-se que o Let’s Encrypt dobrou a porcentagem de sites seguros da Internet.
Vamos criptografar recomenda que você use Certbot para obter e renovar seus certificados. O Certbot é uma ferramenta de software gratuita de código aberto para usar automaticamente certificados Let’s Encrypt em sites administrados manualmente para ativar HTTPS. A Electronic Frontier Foundation (EFF) criou e mantém a Certbot.
Para usar um certificado com Spring Boot, basta ter alguma configuração.
src/main/resources/application.yml
server:
ssl:
key-store: classpath:keystore.p12
key-store-password: password
key-store-type: pkcs12
key-alias: tomcat
key-password: password
port: 8443
Armazenar senhas e segredos em arquivos de configuração é uma má ideia. Vou te mostrar como criptografar chaves como esta abaixo.
Você também pode querer forçar HTTPS. Você pode ver como fazer isso no meu post anterior do blog 10 excelentes maneiras de garantir seu aplicativo de inicialização de mola. Muitas vezes, forçar https usa um cabeçalho de resposta HTTP Strict-Transport-Security (abreviado as ) para dizer aos navegadores que eles só devem acessar um site usando HTTPS.HSTS
Você pode perguntar “Por que precisamos de HTTPS dentro de nossa rede?”
Essa é uma excelente pergunta! É bom proteger os dados que você transmite porque pode haver ameaças de dentro da sua rede.
Johnny Xmas descreve como um ataque na web normalmente acontece em um recente InfoQ Podcast. Phishing e adivinhação as credenciais das pessoas são técnicas incrivelmente eficazes. Em ambos os casos, o invasor pode ter acesso a uma máquina em rede (com direitos administrativos) e causar estragos.
APIs de graphql seguras
O GraphQL usa HTTP, para que você não precise fazer nenhuma lógica extra de uma perspectiva de segurança. A maior coisa que você precisa fazer é manter sua implementação do GraphQL atualizada. O GraphQL depende de fazer pedidos POST para tudo. O servidor que você usa será responsável pela higienização de entrada.
Apollo é uma plataforma para a construção de um gráfico de dados, e o Apollo Client tem implementações para React e Angular, entre outros. |
const clientParam = { uri: '/graphql' };
const myAuth = this.props && this.props.auth;
if (myAuth) {
clientParam.request = async (operation) => {
const token = await myAuth.getAccessToken();
operation.setContext({ headers: { authorization: token ? `Bearer ${token}` : '' } });
}
}
const client = new ApolloClient(clientParam);
export function createApollo(httpLink: HttpLink, oktaAuth: OktaAuthService) {
const http = httpLink.create({ uri });
const auth = setContext((_, { headers }) => {
return oktaAuth.getAccessToken().then(token => {
return token ? { headers: { Authorization: `Bearer ${token}` } } : {};
});
});
return {
link: auth.concat(http),
cache: new InMemoryCache()
};
}
No servidor, você pode usar o que usar para proteger seus pontos finais de API REST para proteger o GraphQL.
Pontos finais do RSocket seguros
O RSocket é um protocolo de comunicação de aplicativos de última geração, reativo e de camada 5 para a construção dos modernos aplicativos de microsserviço e nativos em nuvem atuais.
O que tudo isso significa? Isso significa que o RSocket tem semântica reativa incorporada, para que possa comunicar a pressão de volta aos clientes e fornecer comunicações mais confiáveis. O site da RSocket diz que as implementações estão disponíveis para Java, JavaScript, Go, .NET, C++e Kotlin.
4. Use tokens de acesso e identidade
A OAuth 2.0 fornece autorização delegada desde 2012. O OpenID Connect adicionou identidade federada em cima do OAuth 2.0 em 2014. Juntos, eles oferecem uma especificação padrão que você pode escrever código contra e têm confiança de que ele funcionará em IdPs (Provedores de Identidade).
A especificação também permite que você procure a identidade do usuário enviando um token de acesso para o ponto final. Você pode procurar o URI para este ponto final usando a descoberta do OIDC, que fornece uma maneira padrão de obter a identidade de um usuário./userinfo
Se você estiver se comunicando entre microsserviços, você pode usar o fluxo de credenciais de cliente do OAuth 2.0 para implementar uma comunicação segura entre servidores e servidores. No diagrama abaixo, o é um servidor, e o outro.API Client
API Server
Se você estiver usando o OAuth 2.0 para proteger seu serviço, você está usando um servidor de autorização. A configuração típica é um relacionamento de muitos para um, onde você tem muitos microsserviços conversando com um servidor de autorização.
Os prós desta abordagem:
-
Os serviços podem usar tokens de acesso para conversar com quaisquer outros serviços internos (uma vez que todos foram cunhados pelo mesmo servidor de autorização)
-
Único lugar para procurar todas as definições de escopo e permissão
-
Mais fácil de gerenciar para desenvolvedores e pessoas de segurança
-
Mais rápido (menos tagarela)
Os contras:
-
Abre-o para a possibilidade de serviços desonestos causando problemas com seus tokens
-
Se o token de um serviço estiver comprometido, todos os serviços estarão em risco
-
Limites vagos de segurança
A outra alternativa, mais segura, é uma abordagem um-para-um onde cada microsserviço é vinculado ao seu próprio servidor de autorização. Se eles precisam falar uns com os outros, eles precisam se registrar antes de confiar.
Esta arquitetura permite que você tenha limites de segurança claramente definidos. No entanto, é mais lento porque é mais tagarela, e é mais difícil de gerenciar.
Minha recomendação: use um relacionamento de muitos para um até que você tenha um plano e documentação para apoiar um relacionamento um-para-um.
Use tokens PASETO sobre JWT
JSON Web Tokens (JWT) tornaram-se muito populares nos últimos anos, mas eles também foram incendiados. Principalmente porque muitos desenvolvedores tentam usar o JWT para evitar o armazenamento do lado do servidor para sessões. Veja por que os JWTs suck como Session Tokens para saber por que isso não é recomendado.
PASETO significa platform-a gnóstico security parakens. Paseto é tudo o que você ama sobre JOSE (JWT, JWE, JWS) sem nenhum dos muitos déficits de design que assolam os padrões JOSE.
Meus colegas Randall Degges e Brian Demers escreveram alguns posts informativos no PASETO.
Longa história, curta: usar tokens PASETO não é tão fácil quanto parece. Se você quer escrever sua própria segurança, é possível. Mas se você vai usar um provedor de nuvem bem conhecido, é provável que ele não suporte o padrão PASETO (ainda).
5. Criptografar e proteger segredos
Quando você desenvolve microsserviços que conversam com servidores de autorização e outros serviços, os microsserviços provavelmente têm segredos que eles usam para comunicação. Esses segredos podem ser uma chave de API, ou um segredo do cliente, ou credenciais para autenticação básica.
A regra número 1 para segredos é não checá-los no controle de origem. Mesmo se você desenvolver código em um repositório privado, é um hábito desagradável, e se você está trabalhando em código de produção, é provável que cause problemas.
O primeiro passo para ser mais seguro com segredos é armazená-los em variáveis ambientais. Mas isso é só o começo. Você deve fazer o seu melhor para criptografar seus segredos.
Em suma, a maneira como funciona é:
-
Você gera uma chave mestre usando KMS
-
Cada vez que você quiser criptografar dados, você pede ao AWS para gerar uma nova chave de dados para você. Uma chave de dados é uma chave de criptografia única que a AWS gera para cada pedaço de dados que você precisa criptografar.
-
Em seguida, criptografe seus dados usando a chave de dados
-
A Amazon então criptografará sua chave de dados usando a chave mestre
-
Em seguida, você mesclará a chave de dados criptografadas com os dados criptografados para criar uma mensagem criptografada. A mensagem criptografada é a sua saída final, que é o que você armazenaria como um arquivo ou em um banco de dados.
A razão pela qual isso é tão conveniente é que você nunca precisa se preocupar em proteger chaves — as chaves que alguém precisaria para descriptografar qualquer dado são sempre únicas e seguras.
Você também pode usar o Azure KeyVault para guardar seus segredos.
6. Verifique a segurança com os dutos de entrega
A dependência e a varredura de contêineres devem fazer parte do seu sistema de monitoramento de controle de origem, mas você também deve realizar testes ao executar seus dutos de CI (integração contínua) e CD (entrega contínua).
DevSecOps é o termo que muitos recomendam em vez de DevOps para enfatizar a necessidade de construir segurança nas iniciativas do DevOps. Só queria que rolasse fora da língua um pouco mais fácil. 😉 |
O post da Atlassian recomenda o uso de testes de unidade de segurança, teste de segurança de análise estática (SAST) e teste de segurança de análise dinâmica (DAST).
Seu pipeline de entrega de código pode automatizar essas verificações de segurança, mas provavelmente levará algum tempo para configurar.
-
Crie uma lista branca de imagens básicas do Docker para verificar contra no tempo de compilação
-
Certifique-se de que você está puxando imagens base criptograficamente assinadas
-
Assine os metadados de uma imagem empurrada criptograficamente para que você possa verificar mais tarde
-
Em seus contêineres, use apenas distribuições Linux que verifiquem a integridade do pacote usando os recursos de segurança do gerenciador de pacotes
-
Ao puxar as dependências de terceiros manualmente, apenas permita HTTPS e garanta que você valide checksums
-
Não permita que o programa construa imagens cujo especifica um caminho sensível do host como uma montagem de volume
Dockerfile
Mas e o código? Zach e Austin usam automação para analisá-lo, também:
-
Execute a análise de código estático na base de código para vulnerabilidades de segurança conhecidas em nível de código
-
Execute verificadores automatizados de dependência para ter certeza de que você está usando a última versão mais segura de suas dependências
-
Gire seu serviço, aponte bots de penetração automatizados nos contêineres em execução e veja o que acontece
7. Retardar atacantes
Se alguém tentar atacar suas APIs com centenas de gigas de combinações de nome de usuário/senha, pode levar um tempo para que elas se autenticam com sucesso. Se você puder detectar este ataque e retardar seu serviço, é provável que o atacante vá embora. Simplesmente não vale o tempo deles.
Você pode implementar a limitação de taxas em seu código (muitas vezes com uma biblioteca de código aberto) ou no Gateway de API. Tenho certeza que há outras opções, mas estas provavelmente serão as mais simples de implementar.
8. Use o modo Sem Raiz Docker
O Docker 19.03 introduziu um modo sem raízes. Os desenvolvedores projetaram esse recurso para reduzir a pegada de segurança do daemon Docker e expor os recursos do Docker a sistemas onde os usuários não podem obter privilégios raiz.
Se você está executando Docker daemons na produção, isso é definitivamente algo que você deve olhar. No entanto, se você está deixando Kubernetes executar seus contêineres Docker, você precisará configurar o em seu .runAsUser
PodSecurityPolicy
9. Use a segurança baseada no tempo
Outra dica que recebi de Johnny Xmas no podcast InfoQ foi usar segurança baseada no tempo. Winn Schwartau escreveu um conhecido livro de segurança baseada no tempo que é um grande recurso para quem quer dar um mergulho mais profundo.
A ideia por trás da segurança baseada no tempo é que seu sistema nunca está totalmente seguro — alguém vai invadir. Prevenir intrusos é apenas uma parte da proteção de um sistema; detecção e reação são essenciais, também.
Use autenticação multifatorial para diminuir a velocidade dos invasores, mas também para ajudar a detectar quando alguém com privilégio elevado autentica em um servidor crítico (o que não deve acontecer com frequência). Se você tiver algo como um controlador de domínio que controla o tráfego de rede, envie um alerta para sua equipe de administrador de rede sempre que houver um login bem-sucedido.
Este é apenas um exemplo de tentar detectar anomalias e reagir a elas rapidamente.
10. Digitalizar a configuração de Docker e Kubernetes para vulnerabilidades
Os contêineres Docker são muito populares em arquiteturas de microsserviço. Nossos amigos da Snyk publicaram 10 Práticas Recomendadas de Segurança de Imagem Docker. Ele repete algumas das coisas que eu já mencionei, mas eu vou resumir aqui de qualquer maneira.
-
Prefira imagens básicas mínimas
-
Use a diretiva para garantir que o menos privilegiado seja usado
USER
-
Assine e verifique imagens para mitigar ataques do MITM
-
Encontre, corrija e monitore para vulnerabilidades de código aberto (o Snyk oferece uma maneira de digitalizar e monitorar suas imagens do Docker também)
-
Não vaze informações confidenciais para imagens do Docker
-
Use etiquetas fixas para imutabilidade
-
Use em vez de
COPY
ADD
-
Use etiquetas de metadados como e
maintainer
securitytxt
-
Use compilações multi-estágio para imagens pequenas e seguras
-
Use um linter como hadolint
Você também deve digitalizar sua configuração Kubernetes para vulnerabilidades, mas há muito mais do que isso, então eu vou cobrir a segurança K8s na próxima seção.
11. Conheça sua segurança em nuvem e cluster
Cada um dos 4C’s depende da segurança das praças em que se encaixam. É quase impossível proteger contra padrões de segurança ruins em nuvem, contêineres e código, apenas abordando a segurança no nível de código. No entanto, quando você lida com essas áreas adequadamente, em seguida, adicionar segurança ao seu código aumenta uma base já forte.
O blog Kubernetes tem um post detalhado de Andrew Martin intitulado 11 Maneiras (Não) para Ser Hackeado. Andrew oferece essas dicas para endurecer seus clusters e aumentar sua resiliência se um hacker os comprometer.
-
Use TLS em todos os lugares
-
Habilite o RBAC com o menos privilege, desabilite o ABAC e use o Registro de Auditoria
-
Use um provedor Auth de terceiros (como Google, GitHub - ou Okta!)
-
Separe e Firewall seu cluster etcd
-
Gire chaves de criptografia
-
Use recursos de segurança linux e um
PodSecurityPolicy
restrito -
Análise estaticamente yaml
-
Executar contêineres como um usuário não raiz
-
Use políticas de rede (para limitar o tráfego entre pods)
-
Digitalizar imagens e executar IDS (Sistema de Detecção de Intrusões)
-
Executar uma malha de serviço
Este post é de julho de 2018, mas nada mudou. Eu acho que tem havido uma boa quantidade de hype em torno de malhas de serviço desde 2018, mas isso não fez uma grande diferença.
Executar uma malha de serviço como istio pode permitir que você descarregue sua segurança para um “conjunto compartilhado e testado em batalha de bibliotecas”. Ainda assim, não acho que seja “simplificada a implantação da próxima geração de segurança de rede” como o post do blog diz que poderia.
Saiba mais sobre microsserviços e segurança da Web
Espero que esses padrões de segurança tenham ajudado você a se tornar um desenvolvedor mais consciente da segurança. É interessante para mim que apenas metade da minha lista diz respeito a desenvolvedores que escrevem código no dia-a-dia.
-
Seja seguro por design
-
Dependências de varredura
-
Use HTTPS Em todos os lugares
-
Use tokens de acesso e identidade
-
Criptografar e proteger segredos
O resto deles parecem se aplicar às pessoas de DevOps, ou melhor, DevSecOps.
-
Verifique a segurança com os dutos de entrega
-
Retardar atacantes
-
Use o modo sem raízes Docker
-
Use a segurança baseada no tempo
-
Digitalizar configuração de Docker e Kubernetes para vulnerabilidades
-
Conheça sua segurança em nuvem e cluster
Uma vez que todos esses padrões são considerações importantes, você deve ter certeza de manter um relacionamento próximo entre suas equipes de desenvolvedor e DevSecOps. Na verdade, se você está fazendo microsserviços direito, essas pessoas não estão em equipes separadas! Eles estão na mesma equipe de produtos que possui o microsserviço do conceito à produção.
Procurando por mais? Temos alguns blogs focados em microsserviço e segurança, acho que você vai gostar:
-
Microserviços Java com Inicialização da Mola e Nuvem de Mola
-
Construir microserviços seguros com AWS Lambda e ASP.NET Core
Nós também escrevemos um livro! A API Security é um guia para construir e proteger APIs da equipe de desenvolvedores da Okta.
Se você gostou deste post e quer notificações quando postarmos outras, siga @oktadev no Twitter. Também temos um canal no YouTube que você pode gostar. Como sempre, deixe um comentário abaixo se você tiver alguma dúvida.
Um grande agradecimento a Chris Richardson e Rob Winch por suas críticas completas e feedback detalhado.
Matt Raible é uma figura bem conhecida na comunidade Java e vem construindo aplicações web durante a maior parte de sua vida adulta. Por mais de 20 anos, ele ajudou os desenvolvedores a aprender e adotar estruturas de código aberto e usá-las efetivamente. Ele é um desenvolvedor web, Java Champion, e Advogado de Desenvolvedores na Okta. Matt foi palestrante em muitas conferências em todo o mundo, incluindo Devnexus, Devoxx Belgium, Devoxx France, Jfokus e JavaOne. Ele é autor de The Angular Mini-Book, The JHipster Mini-Book, Spring Live, e contribuiu para Pro JSP. Ele é colaborador frequente do código aberto e membro da equipe de desenvolvimento da JHipster. Você pode encontrá-lo online @mraible e raibledesigns.com.