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

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

Isso mesmo, após o lançamento Cônsul Hashicorp 1.5.0 no início de maio de 2019, no Consul você pode autorizar aplicações e serviços rodando nativamente no Kubernetes.

Neste tutorial vamos criar passo a passo POC (Prova de conceito, PoC) demonstrando esse novo recurso. Espera-se que você tenha conhecimento básico de Kubernetes e do Consul da Hashicorp. Embora você possa usar qualquer plataforma de nuvem ou ambiente local, neste tutorial usaremos a plataforma de nuvem do Google.

visão global

Se formos para Documentação Consul sobre seu método de autorização, obteremos uma rápida visão geral de sua finalidade e caso de uso, bem como alguns detalhes técnicos e uma visão geral da lógica. Eu recomendo fortemente lê-lo pelo menos uma vez antes de prosseguir, pois agora irei explicar e refletir sobre tudo.

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

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

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

Claro, há informações úteis lá, mas não há nenhum guia sobre como realmente usar tudo isso. Então, como qualquer pessoa sã, você vasculha a Internet em busca de orientação. E então... Você falha. Acontece. Vamos consertar isso.

Antes de prosseguirmos com a criação de nosso POC, vamos voltar à visão geral dos métodos de autorização do Consul (Diagrama 1) e refiná-los no contexto do Kubernetes.

Arquitetura

Neste tutorial, criaremos um servidor Consul em uma máquina separada que se comunicará com um cluster Kubernetes com o cliente Consul instalado. Em seguida, criaremos nosso aplicativo fictício no pod e usaremos nosso método de autorização configurado para ler nosso armazenamento de chave/valor Consul.

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

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

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

Uma observação rápida: o servidor Consul não precisa residir fora do cluster Kubernetes para que isso funcione. Mas sim, ele pode fazer isso e aquilo.

Então, pegando o diagrama de visão geral do Consul (Diagrama 1) e aplicando o Kubernetes a ele, obtemos o diagrama acima (Diagrama 2), e a lógica aqui é a seguinte:

  1. Cada pod terá uma conta de serviço anexada contendo um token JWT gerado e conhecido pelo Kubernetes. Esse token também é inserido no pod por padrão.
  2. Nosso aplicativo ou serviço dentro do pod inicia um comando de login para nosso cliente Consul. A solicitação de login também incluirá nosso token e nome especialmente criado método de autorização (tipo Kubernetes). Esta etapa 2 corresponde à etapa 1 do diagrama Consul (Esquema 1).
  3. Nosso cliente Consul encaminhará essa solicitação ao nosso servidor Consul.
  4. MAGIA! É aqui que o servidor Consul verifica a autenticidade da solicitação, coleta informações sobre a identidade da solicitação e a compara com quaisquer regras predefinidas associadas. Abaixo está outro diagrama para ilustrar isso. Esta etapa corresponde às etapas 3, 4 e 5 do diagrama de visão geral do Consul (Diagrama 1).
  5. Nosso servidor Consul gera um token Consul com permissões de acordo com nossas regras de método de autorização especificadas (que definimos) em relação à identidade do solicitante. Em seguida, ele enviará esse token de volta. Isso corresponde à etapa 6 do diagrama Consul (Diagrama 1).
  6. Nosso cliente Consul encaminha o token para a aplicação ou serviço solicitante.

Nosso aplicativo ou serviço agora pode usar esse token Consul para se comunicar com nossos dados Consul, conforme determinado pelos privilégios do token.

A magia é revelada!

Para aqueles de vocês que não estão felizes com apenas um coelho tirado da cartola e querem saber como funciona... deixe-me "mostrar o quão profundo toca do Coelho".

Conforme mencionado anteriormente, nossa etapa “mágica” (Figura 2: Etapa 4) é onde o servidor Consul autentica a solicitação, coleta informações sobre a solicitação e a compara com quaisquer regras predefinidas associadas. Esta etapa corresponde às etapas 3, 4 e 5 do diagrama de visão geral do Consul (Diagrama 1). Abaixo está um diagrama (Diagrama 3), cujo objetivo é mostrar claramente o que realmente está acontecendo sob o capô método de autorização específico do Kubernetes.

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

Diagrama 3: A magia é revelada!

  1. Como ponto de partida, nosso cliente Consul encaminha a solicitação de login para nosso servidor Consul com o token da conta Kubernetes e o nome da instância específica do método de autorização que foi criado anteriormente. Esta etapa corresponde à etapa 3 da explicação do circuito anterior.
  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, com as devidas permissões, descobriremos se o token é genuíno e a quem pertence.
  3. A solicitação validada é então retornada ao líder Consul, e o servidor Consul procura a instância do método de autorização com o nome especificado na solicitação de login (e tipo Kubernetes).
  4. O líder cônsul identifica a instância do método de autorização especificada (se encontrada) e lê o conjunto de regras vinculativas anexadas a ela. Em seguida, ele lê essas regras e as compara com os atributos de identidade verificados.
  5. Surpresa! Vamos passar para a etapa 5 da explicação do circuito anterior.

Execute o Consul-server em uma máquina virtual normal

De agora em diante, darei principalmente instruções sobre como criar este POC, geralmente em marcadores, sem explicações de frases completas. Além disso, conforme observado anteriormente, usarei o GCP para criar toda a infraestrutura, mas você pode criar a mesma infraestrutura em qualquer outro lugar.

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

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

  • Crie uma regra para o firewall (grupo de segurança na AWS):
  • Gosto de atribuir o mesmo nome de 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 endereços IP de origem para que possamos acessar a interface do usuário (IU).
  • Abra a porta 8500 para UI. Clique em Criar. Alteraremos esse firewall novamente em breve [link].
  • Adicione uma regra de firewall à instância. Volte para o painel da VM no Consul Server e adicione “skywiz-consul-server-poc” ao campo de tags de rede. Clique em Salvar.

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

  • Instale o Consul em uma máquina virtual, confira aqui. Lembre-se que você precisa da versão Consul ≥ 1.5 [link]
  • Vamos criar um único nó Consul - 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

  • Para obter um guia mais detalhado sobre como instalar o Consul e configurar um cluster de 3 nós, consulte aqui.
  • Crie um 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ê deverá ver vários resultados e acabar com “... atualização bloqueada por ACLs”.
  • Encontre o endereço IP externo do servidor Consul e abra um navegador com este endereço IP na porta 8500. Certifique-se de que a IU seja aberta.
  • Tente adicionar um par chave/valor. Deve haver algum engano. Isso ocorre porque carregamos o servidor Consul com uma ACL e desabilitamos todas as regras.
  • Volte para o seu shell no servidor Consul e inicie o processo em segundo plano ou de alguma outra forma de executá-lo e digite o seguinte:

consul acl bootstrap

  • Encontre o valor "SecretID" e retorne à IU. Na guia ACL, insira o ID secreto do token que você acabou de copiar. Copie o SecretID para outro lugar, precisaremos dele mais tarde.
  • Agora adicione um par chave/valor. Para este POC, adicione o seguinte: key: “custom-ns/test_key”, valor: “Estou na pasta custom-ns!”

Lançando um cluster Kubernetes para nosso aplicativo com o cliente Consul como um Daemonset

  • Crie um cluster K8s (Kubernetes). Iremos criá-lo na mesma zona do servidor para um acesso mais rápido e para que possamos usar a mesma sub-rede para conectar-se facilmente com endereços IP internos. Chamaremos isso de "skywiz-app-with-consul-client-poc".

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

  • Como observação lateral, aqui está um bom tutorial que encontrei ao configurar um cluster POC Consul com Consul Connect.
  • Também usaremos o gráfico de leme da Hashicorp com um arquivo de valores estendido.
  • Instale e configure o Helm. Etapas 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

  • Aplicar gráfico do leme:

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

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

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

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

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

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

  • Retorne ao shell do servidor Consul e exporte o token que você salvou anteriormente:

export CONSUL_HTTP_TOKEN=<SecretID>

  • Precisaremos de informações do nosso cluster Kubernetes para criar uma instância do método de autenticação:
  • host kubernetes

kubectl get endpoints | grep kubernetes

  • conta de serviço kubernetes-jwt

kubectl get sa <helm_deployment_name>-consul-client -o yaml | grep "- name:"
kubectl get secret <secret_name_from_prev_command> -o yaml | grep token:

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

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

  • Pegue o certificado “ca.crt” (após a decodificação base64) e escreva-o no arquivo “ca.crt”.
  • Agora instancie o método auth, substituindo os espaços reservados pelos valores que você acabou de receber.

consul acl auth-method create 
-type "kubernetes" 
-name "auth-method-skywiz-consul-poc" 
-description "This is an auth method using kubernetes for the cluster skywiz-app-with-consul-client-poc" 
-kubernetes-host "<k8s_endpoint_retrieved earlier>" 
[email protected] 
-kubernetes-service-account-
jwt="<decoded_token_retrieved_earlier>"

  • Em seguida, precisamos criar uma regra e anexá-la à nova função. Para esta parte você pode usar o Consul UI, mas usaremos a linha de comando.
  • Escreva uma regra

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

  • Aplicar a regra

consul acl policy create 
-name kv-custom-ns-policy 
-description "This is an example policy for kv at custom-ns/" 
-rules @kv-custom-ns-policy.hcl

  • Encontre o ID da regra que você acabou de criar na saída.
  • Crie uma função com uma nova regra.

consul acl role create 
-name "custom-ns-role" 
-description "This is an example role for custom-ns namespace" 
-policy-id <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"'

Por último configurações

Permissões

  • Crie direitos de acesso. Precisamos dar permissão ao Consul para verificar e identificar a identidade 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 direitos de acesso

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

Conectando-se ao Cliente Consul

  • Como observado aquiExistem várias opções para conectar-se ao daemonset, mas passaremos para a seguinte 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, use o seguinte comando interno para criar um configmap [link]. Observe que nos referimos ao nome do nosso serviço, substitua-o se 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

Testando o método de autenticação

Agora vamos ver a magia em ação!

  • Crie várias outras pastas de chaves com a mesma chave de nível superior (ou seja, /sample_key) e um valor de sua escolha. Crie políticas e funções apropriadas para novos caminhos principais. Faremos as ligações mais tarde.

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

Teste de namespace personalizado:

  • Vamos criar nosso próprio namespace:

kubectl create namespace custom-ns

  • Vamos criar um pod em nosso novo namespace. Escreva a configuração do 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 em:

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

  • Assim que o contêiner estiver em execução, vá até lá 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 enviaremos uma solicitação de login ao Consul usando o método de autorização que criamos anteriormente [link].
  • Para visualizar o token inserido na 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>"
}

  • Entrar!

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

  • Para concluir as etapas acima em uma linha (já que executaremos 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! Pelo menos deveria. Agora pegue o SecretID e tente acessar a chave/valor ao qual devemos ter acesso.

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

  • Você pode decodificar "Valor" em base64 e ver se ele corresponde ao valor em custom-ns/test_key na interface do usuário. Se você usou o mesmo valor acima neste tutorial, seu valor codificado seria IkknbSBpbiB0aGUgY3VzdG9tLW5zIGZvbGRlciEi.

Teste de conta de serviço do usuário:

  • Crie uma ServiceAccount personalizada usando 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, execute um shell dentro do contêiner.

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

  • Entrar!

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. Ah, esquecemos de adicionar uma nova vinculação de regras com as permissões apropriadas, vamos fazer isso agora.

Repita as etapas anteriores acima:
a) Crie uma Política idêntica para o prefixo “custom-sa/”.
b) Crie uma função, chame-a de “função personalizada”
c) Anexe a Política à Função.

  • Crie uma ligação de regra (possível apenas em cli/api). Observe o significado diferente do sinalizador 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"'

  • Faça login novamente no contêiner "poc-ubuntu-custom-sa". Sucesso!
  • Confira nosso acesso ao caminho custom-sa/key.

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

  • Você também pode garantir que esse token não conceda acesso ao kv em "custom-ns/". Basta repetir o comando acima após substituir “custom-sa” pelo prefixo “custom-ns”.
    Permissão negada.

Exemplo de sobreposição:

  • Vale a pena notar que todos os mapeamentos de vinculação de regras serão adicionados ao token com esses direitos.
  • Nosso contêiner "poc-ubuntu-custom-sa" está no namespace padrão - então vamos usá-lo para uma vinculação de regras diferente.
  • Repita as etapas anteriores:
    a) Crie uma Política idêntica para o prefixo de chave “default/”.
    b) Crie uma função, nomeie-a como “default-ns-role”
    c) Anexe a Política à Função.
  • Crie uma vinculação de regras (possível apenas em 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 para o nosso contêiner "poc-ubuntu-custom-sa" e tente acessar o caminho kv "default/".
  • Permissão negada.
    Você pode visualizar as credenciais especificadas para cada token na UI em ACL > Tokens. Como você pode ver, nosso token atual possui apenas uma “função personalizada” anexada a ele. O token que estamos usando atualmente foi gerado quando efetuamos login e havia apenas uma vinculação de regra correspondente. Precisamos fazer login novamente e usar o novo token.
  • Certifique-se de poder ler os caminhos kv "custom-sa/" e "default/".
    Sucesso!
    Isso ocorre porque nosso “poc-ubuntu-custom-sa” corresponde às ligações de regras “custom-sa” e “default-ns”.

Conclusão

Gerenciamento de token TTL?

No momento em que este artigo foi escrito, não havia uma maneira integrada de determinar o TTL para tokens gerados por esse método de autorização. Seria uma oportunidade fantástica para fornecer automação segura da autorização Consul.

Existe uma opção para criar manualmente um token com TTL:

Esperamos que num futuro próximo seremos capazes de controlar como os tokens são gerados (por regra ou método de autorização) e adicionar TTL.

Até então, sugere-se que você use um endpoint de logout em sua lógica.

Leia também outros artigos em nosso blog:

Fonte: habr.com

Adicionar um comentário