
Tudo certo, após o lançamento 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 (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 , 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.

Diagrama 1: Visão geral oficial do método de autorização do Consul
Vamos dar uma olhada na .
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.

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:
- 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.
- 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).
- Nosso cliente Consul, então, encaminhará essa requisição para o nosso servidor Consul.
- 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).
- 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).
- 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.

Esquema 3: A mágica revelada!
- 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.
- 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.
- 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).
- 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.
- 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).

- 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 [].
- 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.

- 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. .
- Crie o arquivo /etc/consul.d/agent.json da seguinte forma []:
### /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'.

- 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- helm chart:
- Use o seguinte arquivo de valores (note que a maioria eu desativei):
### 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.

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

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 []
- 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- Agora vamos vincular nosso novo papel à instância do método auth. Observe que a flag “selector” determina se nosso pedido de entrada receberá este papel. Confira aqui outras opções de seletor:
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 :
###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.yamlConexão com o Consul Client
- Como mencionado , existem várias opções para se conectar ao daemonset, mas vamos seguir para a próxima solução simples:
- Aplique o seguinte arquivo [].
### 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 []. 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}')"]}
EOFTeste 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.

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 [].
- 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 [].
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:
Expiration Time (Tempo de expiração) — o momento em que este token será revogado. (Opcional; adicionado no Consul 1.5.0)- Só existe para criação/atualização manual
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
