De volta aos microserviços com Istio. Parte 3

De volta aos microserviços com Istio. Parte 3

Nota do tradutor.: Primeira parte deste ciclo foi dedicada a conhecer as funcionalidades do Istio e suas demonstrações em ação, segundo — roteamento finamente ajustado e gerenciamento de tráfego de rede. Agora, falaremos sobre segurança: para demonstrar suas funções básicas, o autor utiliza o serviço de identidade Auth0, mas outros provedores podem ser configurados de maneira semelhante.

Configuramos um cluster Kubernetes, no qual implantamos o Istio e um exemplo de aplicativo de microserviço de Análise de Sentimentos, demonstrando assim as capacidades do Istio.

Com o Istio, conseguimos manter um pequeno tamanho dos serviços, uma vez que eles não precisam implementar camadas como tentativas de reconexão (Retries), timeouts, disjuntores (Circuit Breakers), rastreamento (Tracing) e monitoramento (Monitoring). Além disso, utilizamos técnicas de teste e implantação avançadas: testes A/B, espelhamento e liberações canário.

De volta aos microserviços com Istio. Parte 3

No novo material, vamos explorar as camadas finais em direção ao valor de negócio: autenticação e autorização — e no Istio isso é um verdadeiro prazer!

Autenticação e autorização no Istio

Nunca pensei que me inspiraria em autenticação e autorização. O que, do ponto de vista tecnológico, o Istio pode oferecer para tornar esses tópicos fascinantes e, mais ainda, para inspirar você também?

A resposta é simples: o Istio transfere a responsabilidade por essas funcionalidades de seus serviços para o proxy Envoy. Quando as solicitações chegam aos serviços, elas já estão autenticadas e autorizadas, então você só precisa escrever código útil para os negócios.

Soa bem? Vamos explorar!

Autenticação com Auth0

Usaremos o Auth0 como servidor para gerenciar identificação e acesso, que possui uma versão de teste, é intuitivo de usar e simplesmente me agrada. No entanto, os mesmos princípios podem ser aplicados a qualquer outra implementação de OpenID Connect: KeyCloak, IdentityServer e muitos outros.

Para começar, acesse o Portal Auth0 com sua conta, crie um tenant (tenant — unidade lógica de isolamento, detalhes em documentação — nota do tradutor.) e acesse Aplicações > Aplicativo Padrão, selecionando Domínio, como mostrado na captura de tela abaixo:

De volta aos microserviços com Istio. Parte 3

Especifique esse domínio no arquivo resource-manifests/istio/security/auth-policy.yaml (origem):

apiVersion: authentication.istio.io/v1alpha1
kind: Policy
metadata:
  name: auth-policy
spec:
  targets:
  - name: sa-web-app
  - name: sa-feedback
  origins:
  - jwt:
      issuer: "https://{YOUR_DOMAIN}/"
      jwksUri: "https://{YOUR_DOMAIN}/.well-known/jwks.json"
  principalBinding: USE_ORIGIN

Com este recurso, o Pilot (um dos três componentes básicos do Control Plane no Istio — nota do tradutor) configura os Envoys para autenticar as requisições antes de redirecioná-las para os serviços: sa-web-app e sa-feedback. Ao mesmo tempo, a configuração não é aplicada aos Envoys do serviço sa-frontend, permitindo que deixemos o frontend não autenticado. Para aplicar a política (Policy), execute o comando:

$ kubectl apply -f resource-manifests/istio/security/auth-policy.yaml
policy.authentication.istio.io “auth-policy” created

Volte à página e faça uma requisição — você verá que ela terminará com o status 401 Unauthorized. Agora, vamos redirecionar os usuários do frontend para a autenticação com o Auth0.

Autenticação de requisições com Auth0

Para autenticar as requisições do usuário final, é necessário criar uma API no Auth0 que represente os serviços autenticados (reviews, detalhes e ratings). Para criar a API, acesse Auth0 Portal > APIs > Create API e preencha o formulário:

De volta aos microserviços com Istio. Parte 3

Uma informação importante aqui é Identifier, que usaremos mais tarde no script. Anote assim:

  • Audience: {YOUR_AUDIENCE}

Os outros detalhes necessários estão no Auth0 Portal na seção Applications — selecione Test Application (criado automaticamente junto com a API).

Aqui vamos anotar:

  • Domínio: {YOUR_DOMAIN}
  • Client Id: {YOUR_CLIENT_ID}

Role para o campo de texto Test Application Allowed Callback URLs (URLs permitidas para callback), onde vamos especificar o URL para onde a chamada deve ser enviada após a autenticação ser concluída. No nosso caso, é: http://{EXTERNAL_IP}/callback

E para

Allowed Logout URLs (URLs permitidas para logout) adicione: http://{EXTERNAL_IP}/logout

Vamos para o frontend.

Atualização do frontend

Mude para o branch

auth0 do repositório [istio-mastery] . Neste branch, o código do frontend foi alterado para redirecionar os usuários para o Auth0 para autenticação e usar o token JWT nas requisições para os outros serviços. Isso foi implementado da seguinte forma (analyzeSentence() { fetch('/sentiment', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${auth.getAccessToken()}` // Access Token }, body: JSON.stringify({ sentence: this.textField.getValue() }) }) .then(response => response.json()) .then(data => this.setState(data)); }App.js):

}

Para traduzir o frontend para usar os dados do tenant no Auth0, abra sa-frontend/src/services/Auth.js e substitua os valores que anotamos acima (Auth.js):

const Config = {
    clientID: '{YOUR_CLIENT_ID}',
    domain:'{YOUR_DOMAIN}',
    audience: '{YOUR_AUDIENCE}',
    ingressIP: '{EXTERNAL_IP}' // Usado para redirecionamento após autenticação
}

O aplicativo está pronto. Insira seu ID do Docker nos comandos abaixo ao construir e implantar as alterações feitas:

$ docker build -f sa-frontend/Dockerfile 
 -t $DOCKER_USER_ID/sentiment-analysis-frontend:istio-auth0 
 sa-frontend

$ docker push $DOCKER_USER_ID/sentiment-analysis-frontend:istio-auth0

$ kubectl set image deployment/sa-frontend 
 sa-frontend=$DOCKER_USER_ID/sentiment-analysis-frontend:istio-auth0

Experimente o aplicativo! Você será redirecionado para o Auth0, onde precisará fazer login (ou se registrar), após o que será enviado de volta para a página na qual serão feitas as solicitações já autenticadas. Se você tentar os comandos mencionados nas primeiras partes do artigo com curl — receberá o código 401 Status Code, indicando que a solicitação não está autorizada.

Vamos dar o próximo passo — vamos autorizar as solicitações.

Autorização com Auth0

A autenticação nos permite entender quem é o usuário, mas para saber a que ele tem acesso, é necessária a autorização. Istio também oferece ferramentas para isso.

Como exemplo, criaremos dois grupos de usuários (veja no diagrama abaixo):

  • Usuários (users) — com acesso apenas aos serviços SA-WebApp e SA-Frontend;
  • Moderadores (moderators) — com acesso a todos os três serviços.

De volta aos microserviços com Istio. Parte 3
Conceito de autorização

Para criar esses grupos, usaremos a extensão Auth0 Authorization e, com a ajuda do Istio, forneceremos a eles diferentes níveis de acesso.

Instalação e configuração do Auth0 Authorization

No portal Auth0, vá para extensões (Extensions) e instale Auth0 Authorization.Após a instalação, vá para Authorization Extension, e então — para a configuração do tenant clicando no canto superior direito e escolhendo a opção correspondente do menu (Configuration).Ative os grupos (Groups) e clique no botão de publicar regra (Publish rule)..

De volta aos microserviços com Istio. Parte 3

Criação de grupos

Na Authorization Extension, vá para Groups e crie o grupo Moderadores.Como iremos considerar todos os usuários autenticados como comuns, não há necessidade de criar um grupo adicional para eles.

Selecione o grupo Moderadores., clique em Add Members, adicione sua conta principal. Deixe alguns usuários sem nenhum grupo para garantir que o acesso a eles seja negado. (Novos usuários podem ser criados manualmente através de Auth0 Portal > Usuários > Criar Usuário.)

Adicione Group Claim ao Access Token

Os usuários foram adicionados a grupos, no entanto, essa informação também deve estar refletida nos tokens de acesso. Para estar em conformidade com OpenID Connect e ao mesmo tempo retornar os grupos que precisamos, o token precisará adicionar seu custom claim. Isso é implementado através de regras Auth0.

Para criar uma regra, vá até o Auth0 Portal em Regras, clique em Criar Regra e selecione uma regra em branco a partir dos templates.

De volta aos microserviços com Istio. Parte 3

Copie o código abaixo e salve-o como uma nova regra Adicionar Group Claim (namespacedGroup.js):

function (user, context, callback) {
    context.accessToken['https://sa.io/group'] = user.groups[0];
    return callback(null, user, context);
}

Nota: este código pega o primeiro grupo do usuário, definido na Expansão de Autorização, e o adiciona ao access token como um custom claim (sob seu namespace, como requerido pelo Auth0).

Volte à página Regras e verifique se você tem duas regras escritas na seguinte ordem:

  • auth0-authorization-extension
  • Adicionar Group Claim

A ordem é importante, pois o campo de grupo recebe a regra de forma assíncrona auth0-authorization-extension e depois é adicionado como claim pela segunda regra. O resultado é um access token como este:

{
 "https://sa.io/group": "Moderators",
 "iss": "https://sentiment-analysis.eu.auth0.com/",
 "sub": "google-oauth2|196405271625531691872"
 // [abreviado para clareza]
}

Agora é necessário configurar o proxy Envoy para verificar o acesso do usuário, para o qual o grupo será retirado do claim (https://sa.io/group) no access token retornado. Este é o tema da próxima seção do artigo.

Configuração de autorização no Istio

Para que a autorização funcione, é necessário habilitar o RBAC para o Istio. Para isso, usaremos a seguinte configuração:

apiVersion: "rbac.istio.io/v1alpha1"
kind: RbacConfig
metadata:
  name: default
spec:
  mode: 'ON_WITH_INCLUSION'                     # 1
  inclusion:
    services:                                   # 2
    - "sa-frontend.default.svc.cluster.local"
    - "sa-web-app.default.svc.cluster.local"
    - "sa-feedback.default.svc.cluster.local" 

Notas:

  • 1 — habilitamos RBAC apenas para os serviços e namespaces listados no campo Inclusion;
  • 2 — listamos nossos serviços.

Aplicaremos a configuração com o seguinte comando:

$ kubectl apply -f resource-manifests/istio/security/enable-rbac.yaml
rbacconfig.rbac.istio.io/default criado

Agora todos os serviços precisam de controle de acesso baseado em roles (Role-Based Access Control). Em outras palavras, o acesso a todos os serviços é negado e resultará na resposta RBAC: acesso negado. Agora vamos permitir o acesso a usuários autenticados.

Configuração de acesso para usuários comuns

Todos os usuários devem ter acesso aos serviços SA-Frontend e SA-WebApp. Isso é realizado através dos seguintes recursos do Istio:

  • ServiceRole — define os direitos que o usuário possui;
  • ServiceRoleBinding — define a quem essa ServiceRole se aplica.

Para usuários comuns, vamos permitir acesso a serviços específicos (servicerole.yaml):

apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRole
metadata:
  name: regular-user
  namespace: default
spec:
  rules:
  - services: 
    - "sa-frontend.default.svc.cluster.local" 
    - "sa-web-app.default.svc.cluster.local"
    paths: ["*"]
    methods: ["*"]

E através de regular-user-binding aplicaremos a ServiceRole a todos os visitantes da página (regular-user-service-role-binding.yaml):

apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRoleBinding
metadata:
  name: regular-user-binding
  namespace: default
spec:
  subjects:
  - user: "*"
  roleRef:
    kind: ServiceRole
    name: "regular-user"

Significa que "todos os usuários" implica que usuários não autenticados também terão acesso ao SA WebApp? Não, a política verificará a validade do token JWT.

Aplicaremos as configurações:

$ kubectl apply -f resource-manifests/istio/security/user-role.yaml
servicerole.rbac.istio.io/regular-user criado
servicerolebinding.rbac.istio.io/regular-user-binding criado

Configuração de acesso para moderadores

Para moderadores, queremos permitir o acesso a todos os serviços (mod-service-role.yaml):

apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRole
metadata:
  name: mod-user
  namespace: default
spec:
  rules:
  - services: ["*"]
    paths: ["*"]
    methods: ["*"]

Mas queremos esses direitos apenas para aqueles usuários cujo access-token contém o claim https://sa.io/group com o valor Moderadores. (mod-service-role-binding.yaml):

apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRoleBinding
metadata:
  name: mod-user-binding
  namespace: default
spec:
  subjects:
  - properties:
      request.auth.claims[https://sa.io/group]: "Moderators"
  roleRef:
    kind: ServiceRole
name: "mod-user" 

Aplicaremos as configurações:

$ kubectl apply -f resource-manifests/istio/security/mod-role.yaml
servicerole.rbac.istio.io/mod-user criado
servicerolebinding.rbac.istio.io/mod-user-binding criado

Devido ao cache nos envoy, pode levar alguns minutos para que as regras de autorização tenham efeito. Após isso, você poderá verificar que os usuários e moderadores têm níveis de acesso diferentes.

Conclusão sobre esta parte

Sério, você já viu uma abordagem mais simples, escalável e segura para autenticação e autorização?

Somente três recursos do Istio (RbacConfig, ServiceRole e ServiceRoleBinding) foram necessários para alcançar um controle refinado sobre a autenticação e autorização de acesso de usuários finais aos serviços.

Além disso, removemos a preocupação com esses problemas dos nossos serviços em envoy, conseguindo:

  • reduzir a quantidade de código padrão, onde podem ocorrer problemas de segurança e bugs;
  • diminuir as situações absurdas em que um endpoint ficou acessível externamente e esqueceu de notificar sobre isso;
  • eliminar a necessidade de atualizar todos os serviços sempre que um novo papel ou direito é adicionado;
  • garantir que novos serviços permaneçam simples, seguros e rápidos.

Saída

O Istio permite que as equipes se concentrem em tarefas importantes para os negócios, sem adicionar sobrecarga aos serviços, retornando-os ao status de 'micro'.

O artigo (em três partes) forneceu conhecimentos básicos e um guia prático pronto para começar a trabalhar com Istio em projetos reais.

P.S. do tradutor

Confira também em nosso blog:

Fonte: habr.com

Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS 🔥 Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS | ProHoster