Introdução à Autorização do Kubernetes do Hashicorp Consul

Introdução à Autorização do Kubernetes do Hashicorp Consul

Tudo certo, após o lançamento Hashicorp Consul 1.5.0 no início de maio de 2019, no Consul é possível realizar a autorização de aplicativos e serviços executados no Kubernetes de forma nativa.

Neste guia, criaremos passo a passo POC (Prova de conceito (Proof of concept, PoC) — demonstração da viabilidade da ideia — nota do tradutor), mostrando essa nova funcionalidade. Espera-se que você tenha conhecimentos básicos sobre Kubernetes e o Consul da Hashicorp. E embora você possa usar qualquer plataforma em nuvem ou um ambiente local, neste guia utilizaremos a Google Cloud Platform.

Visão geral

Se formos para a documentação do Consul sobre seu método de autorização, teremos uma visão geral de seu propósito e caso de uso, além de alguns detalhes técnicos e uma visão geral da lógica. Recomendo fortemente que você a leia pelo menos uma vez antes de continuar, pois agora eu explicarei isso tudo com detalhes.

Introdução à Autorização do Kubernetes do Hashicorp Consul

Diagrama 1: Visão geral oficial do método de autorização do Consul

Vamos dar uma olhada na documentação para o método de autorização específico do Kubernetes.

Claro, lá há informações úteis, mas não existe um guia sobre como realmente usar tudo isso. Então, como qualquer pessoa sensata, você vasculha a Internet em busca de um guia. E então... você acaba frustrado. Isso acontece. Vamos corrigir isso.

Antes de irmos para a criação do nosso POC, vamos voltar à visão geral dos métodos de autorização do Consul (Diagrama 1) e esclarecer isso no contexto do Kubernetes.

Arquitetura

Neste guia, estaremos criando um servidor Consul em uma máquina separada que interagirá com o cluster Kubernetes com um cliente Consul instalado. Em seguida, criaremos nosso aplicativo fictício em um pod e usaremos nosso método de autorização configurado para ler do nosso armazenamento key/value do Consul.

O diagrama abaixo detalha a arquitetura que estamos criando neste guia, bem como a lógica do método de autorização, que será explicada posteriormente.

Introdução à Autorização do Kubernetes do Hashicorp Consul

Diagrama 2: Visão geral do método de autorização no Kubernetes

Uma pequena observação: o servidor Consul não precisa estar fora do cluster Kubernetes para que isso funcione. Mas sim, ele pode ficar tanto dentro quanto fora.

Assim, pegando o diagrama de visão geral do Consul (Diagrama 1) e aplicando ao Kubernetes, obtemos o diagrama acima (Diagrama 2), e aqui a lógica será a seguinte:

  1. A cada pod será anexada uma conta de serviço, contendo um token JWT, gerado e conhecido pelo Kubernetes. Este token também é inserido no pod por padrão.
  2. Nosso aplicativo ou serviço dentro do pod inicia um comando de login no nosso cliente Consul. A requisição de login também incluirá nosso token e um nome especificamente criado método de autenticação (tipo Kubernetes). Este passo nº 2 corresponde ao passo 1 do esquema Consul (Esquema 1).
  3. Nosso cliente Consul, então, encaminhará essa requisição para o nosso servidor Consul.
  4. MÁGICA! É aqui que o servidor Consul verifica a autenticidade da requisição, coleta informações sobre a identidade da requisição e as compara com quaisquer regras predefinidas associadas. Abaixo haverá outro esquema para ilustrar isso. Este passo corresponde aos passos 3, 4 e 5 do esquema geral do Consul (Esquema 1).
  5. Nosso servidor Consul gera um token Consul com permissões de acordo com as regras que definimos para o método de autenticação (que definimos) em relação à identidade do solicitante. Em seguida, ele enviará este token de volta. Isso corresponde ao passo 6 do esquema Consul (Esquema 1).
  6. Nosso cliente Consul redireciona o token para o aplicativo ou serviço solicitante.

Nosso aplicativo ou serviço agora pode usar este token Consul para se comunicar com nossos dados Consul, conforme definido pelas permissões do token.

A mágica revelada!

Para aqueles de vocês que não estão satisfeitos apenas com um coelho saindo da cartola e querem saber como isso funciona… deixe-me "mostrar o quão fundo a toca do coelho».

Como mencionado anteriormente, nosso passo "mágico" (Esquema 2: Passo 4) é que o servidor Consul verifica a autenticidade da requisição, coleta informações da requisição e as compara com quaisquer regras predefinidas associadas. Este passo corresponde aos passos 3, 4 e 5 do esquema geral do Consul (Esquema 1). Abaixo está um esquema (Esquema 3) cujo objetivo é mostrar claramente o que realmente acontece por trás dos panos do método de autenticação Kubernetes específico.

Introdução à Autorização do Kubernetes do Hashicorp Consul

Esquema 3: A mágica revelada!

  1. Como ponto de partida, nosso cliente Consul redireciona a requisição de login para nosso servidor Consul com o token da conta Kubernetes e o nome específico da instância do método de autenticação, que foi criado anteriormente. Este passo corresponde ao passo 3 na explicação anterior do esquema.
  2. Agora o servidor Consul (ou líder) precisa verificar a autenticidade do token recebido. Portanto, ele consultará o cluster Kubernetes (através do cliente Consul) e, se as permissões adequadas forem concedidas, determinaremos se o token é legítimo e a quem pertence.
  3. Em seguida, a solicitação verificada é retornada ao líder do Consul, e no servidor Consul, uma busca é realizada para encontrar a instância do método de autorização com o nome indicado na solicitação de login (e do tipo Kubernetes).
  4. O líder do Consul identifica a instância do método de autorização especificada (se encontrada) e lê o conjunto de regras de vinculação que estão anexadas a ela. Em seguida, ele lê essas regras e as compara com os atributos de identidade verificados.
  5. Eureka! Passamos para o passo 5 da explicação anterior do esquema.

Inicie o servidor Consul em uma máquina virtual comum.

A partir deste ponto, principalmente fornecerei instruções para criar este POC, frequentemente em itens, sem frases explicativas completas. Como mencionado anteriormente, usarei o GCP para criar toda a infraestrutura, mas você pode criar uma infraestrutura semelhante em qualquer outro lugar.

  • Inicie a máquina virtual (instância / servidor).

Introdução à Autorização do Kubernetes do Hashicorp Consul

  • Crie uma regra para o firewall (grupo de segurança na AWS):
  • Gosto de atribuir o mesmo nome da máquina à regra e à tag de rede, neste caso é "skywiz-consul-server-poc".
  • Encontre o endereço IP do seu computador local e adicione-o à lista de IPs de origem, para que possamos acessar a interface do usuário (UI).
  • Abra a porta 8500 para a UI. Clique em Criar. Em breve, alteraremos este firewall novamente [link].
  • Adicione uma regra para o firewall à instância. Volte ao painel de controle da VM no servidor Consul e adicione "skywiz-consul-server-poc" no campo de tags de rede. Clique em Salvar.

Introdução à Autorização do Kubernetes do Hashicorp Consul

  • Instale o Consul na máquina virtual, verifique aqui. Lembre-se de que você precisa da versão Consul ≥ 1.5 [link]
  • Vamos criar um Consul de nó único — a configuração é a seguinte.

groupadd --system consul
useradd -s /sbin/nologin --system -g consul consul
mkdir -p /var/lib/consul
chown -R consul:consul /var/lib/consul
chmod -R 775 /var/lib/consul
mkdir /etc/consul.d
chown -R consul:consul /etc/consul.d

  • Um guia mais detalhado sobre como instalar o Consul e configurar um cluster de 3 nós pode ser encontrado aqui. aqui.
  • Crie o arquivo /etc/consul.d/agent.json da seguinte forma [link]:

### /etc/consul.d/agent.json
{
 "acl" : {
 "enabled": true,
 "default_policy": "deny",
 "enable_token_persistence": true
 }
}

  • Inicie nosso servidor Consul:

consul agent 
-server 
-ui 
-client 0.0.0.0 
-data-dir=/var/lib/consul 
-bootstrap-expect=1 
-config-dir=/etc/consul.d

  • Você deve ver uma tonelada de saídas e, no final, '… update blocked by ACLs'.
  • Encontre o endereço IP externo do servidor Consul e abra um navegador com esse IP na porta 8500. Certifique-se de que a interface do usuário seja exibida.
  • Tente adicionar um par chave/valor. Deve haver um erro. Isso ocorre porque carregamos o servidor Consul com ACL e bloqueamos todas as regras.
  • Volte para seu shell no servidor Consul e inicie o processo em segundo plano ou de outra forma, para que ele continue rodando, e digite o seguinte:

consul acl bootstrap

  • Encontre o valor 'SecretID' e volte para a interface do usuário. Na aba 'ACL', insira o identificador secreto do token que você acabou de copiar. Copie o SecretID para outro lugar, ele será necessário mais tarde.
  • Agora adicione um par chave/valor. Para este POC, vamos adicionar o seguinte: chave: 'custom-ns/test_key', valor: 'Estou na pasta custom-ns!'

Executando um cluster Kubernetes para nosso aplicativo com o cliente Consul como Daemonset

  • Crie um cluster K8s (Kubernetes). Vamos criá-lo na mesma zona que o servidor, para acesso mais rápido, e assim podemos usar a mesma sub-rede para fácil conexão com endereços IP internos. Vamos chamá-lo de 'skywiz-app-with-consul-client-poc'.

Introdução à Autorização do Kubernetes do Hashicorp Consul

  • Como nota, aqui está um bom guia que encontrei ao configurar o POC do cluster Consul com o Consul Connect.
  • Usaremos também o gráfico helm da Hashicorp com um arquivo de valores expandido.
  • Instale e configure o Helm. Passos de configuração:

kubectl create serviceaccount tiller --namespace kube-system
kubectl create clusterrolebinding tiller-admin-binding 
   --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
./helm init --service-account=tiller
./helm update

### poc-helm-consul-values.yaml
global:
 enabled: false
 image: "consul:latest"
# Expose the Consul UI through this LoadBalancer
ui:
 enabled: false
# Allow Consul to inject the Connect proxy into Kubernetes containers
connectInject:
 enabled: false
# Configure a Consul client on Kubernetes nodes. GRPC listener is required for Connect.
client:
 enabled: true
 join: ["<PRIVATE_IP_CONSUL_SERVER>"]
 extraConfig: |
{
  "acl" : {
 "enabled": true,   
 "default_policy": "deny",   
 "enable_token_persistence": true 
  }
}
# Minimal Consul configuration. Not suitable for production.
server:
 enabled: false
# Sync Kubernetes and Consul services
syncCatalog:
 enabled: false

  • Aplique o gráfico helm:

./helm install -f poc-helm-consul-values.yaml ./consul-helm --name skywiz-app-with-consul-client-poc

  • Ao tentar iniciar, ele precisará de permissões para o servidor Consul, então vamos adicioná-las.
  • Preste atenção no 'intervalo de endereços Pod' localizado no painel do cluster e volte para nossa regra do firewall 'skywiz-consul-server-poc'.
  • Adicione o intervalo de endereços para o pod à lista de endereços IP e abra as portas 8301 e 8300.

Introdução à Autorização do Kubernetes do Hashicorp Consul

  • Vá para a interface do usuário do Consul e, após alguns minutos, você verá nosso cluster aparecer na aba de nós.

Introdução à Autorização do Kubernetes do Hashicorp Consul

Configurando o método de autorização integrando o Consul com o Kubernetes

  • Volte para o shell do servidor Consul e exporte o token que você salvou anteriormente:

export CONSUL_HTTP_TOKEN=

  • Precisamos das informações do nosso cluster Kubernetes para criar uma instância do método auth:
  • kubernetes-host

kubectl get endpoints | grep kubernetes

  • kubernetes-service-account-jwt

kubectl get sa -consul-client -o yaml | grep "- name:"
kubectl get secret  -o yaml | grep token:

  • O token está codificado em base64, então decodifique-o usando sua ferramenta favorita [link]
  • kubernetes-ca-cert

kubectl get secret  -o yaml | grep ca.crt:

  • Pegue o certificado “ca.crt” (após a decodificação com base64) e coloque-o no arquivo “ca.crt”.
  • Agora crie uma instância do método auth, substituindo os placeholders pelos valores que você acabou de obter.

consul acl auth-method create 
-type "kubernetes" 
-name "auth-method-skywiz-consul-poc" 
-description "Este é um método de autenticação usando kubernetes para o cluster skywiz-app-with-consul-client-poc" 
-kubernetes-host "" 
-kubernetes-ca-cert=@ca.crt 
-kubernetes-service-account-
jwt=""

  • Em seguida, precisamos criar uma regra e vinculá-la a um novo papel. Para esta parte, você pode usar a interface do usuário do Consul, mas usaremos a linha de comando.
  • Escreva a regra

### kv-custom-ns-policy.hcl
key_prefix "custom-ns/" {
 policy = "write"
}

  • Aplique a regra

consul acl policy create 
-name kv-custom-ns-policy 
-description "Esta é uma política de exemplo para kv em custom-ns/" 
-rules @kv-custom-ns-policy.hcl

  • Encontre o identificador da regra que você acabou de criar nos resultados.
  • Crie um papel com a nova regra.

consul acl role create 
-name "custom-ns-role" 
-description "Este é um papel de exemplo para o namespace custom-ns" 
-policy-id

consul acl binding-rule create 
-method=auth-method-skywiz-consul-poc 
-bind-type=role 
-bind-name='custom-ns-role' 
-selector='serviceaccount.namespace=="custom-ns"'

Configurações finais

Direitos de acesso

  • Crie permissões de acesso. Precisamos dar ao Consul a permissão para verificar e identificar a credencial do token da conta de serviço K8s.
  • Escreva o seguinte no arquivo [link]:

###skywiz-poc-consul-server_rbac.yaml
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
 name: review-tokens
 namespace: default
subjects:
- kind: ServiceAccount
 name: skywiz-app-with-consul-client-poc-consul-client
 namespace: default
roleRef:
 kind: ClusterRole
 name: system:auth-delegator
 apiGroup: rbac.authorization.k8s.io
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
 name: service-account-getter
 namespace: default
rules:
- apiGroups: [""]
 resources: ["serviceaccounts"]
 verbs: ["get"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
 name: get-service-accounts
 namespace: default
subjects:
- kind: ServiceAccount
 name: skywiz-app-with-consul-client-poc-consul-client
 namespace: default
roleRef:
 kind: ClusterRole
 name: service-account-getter
 apiGroup: rbac.authorization.k8s.io

  • Vamos criar permissões de acesso

kubectl create -f skywiz-poc-consul-server_rbac.yaml

Conexão com o Consul Client

  • Como mencionado aqui, existem várias opções para se conectar ao daemonset, mas vamos seguir para a próxima solução simples:
  • Aplique o seguinte arquivo [link].

### poc-consul-client-ds-svc.yaml
apiVersion: v1
kind: Service
metadata:
 name: consul-ds-client
spec:
 selector:
   app: consul
   chart: consul-helm
   component: client
   hasDNS: "true"
   release: skywiz-app-with-consul-client-poc
 ports:
 - protocol: TCP
   port: 80
   targetPort: 8500

  • Em seguida, aplique o seguinte comando embutido para criar o configmap [link]. Observe que estamos nos referindo ao nome do nosso serviço, substitua-o conforme necessário.

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
 labels:
   addonmanager.kubernetes.io/mode: EnsureExists
 name: kube-dns
 namespace: kube-system
data:
 stubDomains: |
   {"consul": ["$(kubectl get svc consul-ds-client -o jsonpath='{.spec.clusterIP}')"]}
EOF

Teste do método de autenticação

Agora vamos ver a mágica em ação!

  • Crie mais algumas chaves principais com a mesma chave de nível superior (ou seja, /sample_key) e um valor à sua escolha. Crie políticas e funções correspondentes para os novos caminhos de chave. Faremos as associações mais tarde.

Introdução à Autorização do Kubernetes do Hashicorp Consul

Teste do usuário do namespace:

  • Vamos criar nosso próprio namespace:

kubectl create namespace custom-ns

  • Vamos criar um pod em nosso novo namespace. Escreva a configuração para o pod.

###poc-ubuntu-custom-ns.yaml
apiVersion: v1
kind: Pod
metadata:
 name: poc-ubuntu-custom-ns
 namespace: custom-ns
spec:
 containers:
 - name: poc-ubuntu-custom-ns
   image: ubuntu
   command: ["/bin/bash", "-ec", "sleep infinity"]
 restartPolicy: Never

  • Crie um pod:

kubectl create -f poc-ubuntu-custom-ns.yaml

  • Assim que o contêiner iniciar, entre nele e instale o curl.

kubectl exec poc-ubuntu-custom-ns -n custom-ns -it /bin/bash
apt-get update && apt-get install curl -y

  • Agora vamos enviar uma solicitação de login para o Consul, usando o método de autenticação que criamos anteriormente [link].
  • Para ver o token inserido da sua conta de serviço:

cat /run/secrets/kubernetes.io/serviceaccount/token

  • Escreva o seguinte em um arquivo dentro do contêiner:

### payload.json
{
 "AuthMethod": "auth-method-test",
 "BearerToken": "<jwt_token>"
}

  • Login!

curl 
--request POST 
--data @payload.json 
consul-ds-client.default.svc.cluster.local/v1/acl/login

  • Para executar os passos acima em uma linha (já que vamos realizar vários testes), você pode fazer o seguinte:

echo "{ 
"AuthMethod": "auth-method-skywiz-consul-poc", 
"BearerToken": "$(cat /run/secrets/kubernetes.io/serviceaccount/token)" 
}" 
| curl 
--request POST 
--data @- 
consul-ds-client.default.svc.cluster.local/v1/acl/login

  • Funciona! Deve funcionar, pelo menos. Agora pegue o SecretID e tente acessar a chave/valor que devemos ter acesso.

curl 
consul-ds-client.default.svc.cluster.local/v1/kv/custom-ns/test_key --header “X-Consul-Token: ”

  • Você pode decodificar o 'Value' em base64 e ver que ele corresponde ao valor em custom-ns/test_key na interface. Se você usou o mesmo valor mencionado acima neste guia, seu valor codificado será IkknbSBpbiB0aGUgY3VzdG9tLW5zIGZvbGRlciEi.

Teste da conta de serviço personalizada:

  • Crie uma ServiceAccount personalizada com o seguinte comando [link].

kubectl apply -f - <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
 name: custom-sa
EOF

  • Crie um novo arquivo de configuração para o pod. Observe que incluí a instalação do curl para economizar trabalho 🙂

###poc-ubuntu-custom-sa.yaml
apiVersion: v1
kind: Pod
metadata:
 name: poc-ubuntu-custom-sa
 namespace: default
spec:
 serviceAccountName: custom-sa
 containers:
 - name: poc-ubuntu-custom-sa
   image: ubuntu
   command: ["/bin/bash","-ec"]
   args: ["apt-get update && apt-get install curl -y; sleep infinity"]
 restartPolicy: Never

  • Depois disso, inicie um shell dentro do contêiner.

kubectl exec -it poc-ubuntu-custom-sa /bin/bash

  • Login!

echo "{ 
"AuthMethod": "auth-method-skywiz-consul-poc", 
"BearerToken": "$(cat /run/secrets/kubernetes.io/serviceaccount/token)" 
}" 
| curl 
--request POST 
--data @- 
consul-ds-client.default.svc.cluster.local/v1/acl/login

  • Permissão negada. Oh, esquecemos de adicionar um novo vínculo de regra com as permissões adequadas, vamos fazer isso agora.

Repita os passos anteriores acima:
a) Crie uma Política idêntica para o prefixo "custom-sa/".
b) Crie uma Role, nomeie-a "custom-sa-role"
c) Anexe a Política à Role.

  • Crie um Rule-Binding (apenas possível via cli / api). Observe outro valor para o flag do seletor.

consul acl binding-rule create 
-method=auth-method-skywiz-consul-poc 
-bind-type=role 
-bind-name='custom-sa-role' 
-selector='serviceaccount.name=="custom-sa"'

  • Repita o login do contêiner "poc-ubuntu-custom-sa". Sucesso!
  • Verifique nosso acesso ao caminho chave custom-sa/.

curl 
consul-ds-client.default.svc.cluster.local/v1/kv/custom-sa/test_key --header "X-Consul-Token: "

  • Você também pode verificar se esse token não oferece acesso ao kv em "custom-ns/". Basta repetir o comando acima, substituindo "custom-sa" pelo prefixo "custom-ns".
    Permissão negada.

Exemplo de sobreposição:

  • Vale ressaltar que todos os mapeamentos do rule-binding serão adicionados ao token com esses direitos.
  • Nosso contêiner "poc-ubuntu-custom-sa" está no espaço de nomes padrão - então vamos usá-lo para outro rule-binding.
  • Repita os passos anteriores:
    a) Crie uma Política idêntica para o prefixo da chave "default/".
    b) Crie uma Role, nomeie-a "default-ns-role"
    c) Anexe a Política à Role.
  • Crie um Rule-Binding (apenas possível via cli / api)

consul acl binding-rule create 
-method=auth-method-skywiz-consul-poc 
-bind-type=role 
-bind-name='default-ns-role' 
-selector='serviceaccount.namespace=="default"'

  • Volte ao nosso contêiner "poc-ubuntu-custom-sa" e tente acessar o caminho "default/" kv.
  • Permissão negada.
    Você pode visualizar as credenciais especificadas para cada token na interface do usuário na seção ACL > Tokens. Como você pode ver, ao nosso token atual está anexada apenas uma "custom-sa-role". O token que estamos usando atualmente foi gerado quando fizemos login, e na época havia apenas um rule-binding correspondente. Precisamos fazer login novamente e usar um novo token.
  • Certifique-se de que pode ler tanto dos caminhos "custom-sa/" quanto "default/" kv.
    Sucesso!
    Isso se deve ao fato de que nosso "poc-ubuntu-custom-sa" corresponde aos vínculos de regra "custom-sa" e "default-ns".

Conclusão

Gerenciamento de token TTL?

No momento da redação deste artigo, não existe uma maneira integrada de determinar o TTL para tokens gerados por esse método de autorização. Seria uma oportunidade fantástica - garantir uma automação segura da autorização do Consul.

É possível criar um token manualmente com TTL:

Espero que em breve possamos controlar como os tokens são gerados (para cada regra ou método de autorização) e adicionar TTL.

Até lá, recomenda-se usar um ponto de saída lógico.

Leia também outros artigos 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