
É isso mesmo, após o lançamento do Hashicorp Consul 1.5.0 no início de maio de 2019 no Consul, você pode autorizar aplicativos e serviços em execução no Kubernetes nativamente.
Neste tutorial, criaremos passo a passo um POC (Prova de conceito, PoC - prova de conceito) - demonstrando esse novo recurso. O conhecimento básico do Kubernetes e do Cônsul de Hashicorp é esperado de você. você pode usar qualquer plataforma em nuvem ou ambiente local; neste guia, usaremos a plataforma em nuvem do Google.
Revisão
Se recorrermos à documentação do Consul sobre seu método de autorização , obteremos uma breve visão geral de sua finalidade e caso de uso, além de alguns detalhes técnicos e uma visão geral da lógica. Eu recomendo a leitura pelo menos uma vez antes de continuar, pois vou explicar e mastigar tudo agora.

Figura 1: Visão geral do método de autorização do cônsul oficial
Vamos dar uma olhada na documentação para o método de autorização específico do Kubernetes .
Obviamente, há informações úteis, mas não há um guia sobre como realmente usar tudo isso. Portanto, como qualquer pessoa sã, você vasculha a Internet em busca de orientação. E então ... Seja derrotado. Isso acontece Vamos consertar.
Antes de prosseguirmos com a criação do nosso POC, vamos voltar à visão geral dos métodos de autorização do Consul (Figura 1) e refiná-lo no contexto do Kubernetes.
Arquitetura
Neste guia, criaremos um servidor Consul em uma máquina separada que irá interagir com o cluster Kubernetes com o cliente Consul instalado. Em seguida, criaremos nosso aplicativo fictício na lareira e usaremos nosso método de autorização personalizado para ler em nosso repositório de chaves / valores Consul.
O diagrama abaixo mostra em detalhes a arquitetura que criamos neste guia, bem como a lógica do método de autorização, que será explicada mais adiante.

Figura 2: Visão geral do método de autorização no Kubernetes
Uma observação rápida: o servidor consul não precisa viver fora do cluster Kubernetes para que isso funcione. Mas sim, ele pode fazer isso e aquilo.
Portanto, pegando o diagrama de visão geral do Consul (Esquema 1) e aplicando o Kubernetes, obtemos o diagrama acima (Esquema 2), e aqui a lógica será a seguinte:
- Cada pod terá uma conta de serviço anexada contendo um token JWT gerado e conhecido pelo Kubernetes. Esse token também é inserido no sub por padrão.
- Nosso aplicativo ou serviço dentro da lareira inicia um comando para entrar no nosso cliente Consul. A solicitação de login também indicará nosso token e o nome de um método de autorização criado especialmente (como o Kubernetes). Esta etapa nº 2 corresponde à etapa 1 do esquema Consul (esquema 1).
- Nosso cliente Cônsul encaminhará essa solicitação ao nosso servidor Cônsul.
- MÁGICA! É aqui que o servidor Consul consulta a autenticidade da solicitação, coleta informações sobre a identidade da solicitação e a compara com as 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 (Esquema 1).
- Nosso servidor Consul Consul gera um token Consul com permissões de acordo com as regras do método de autorização que especificamos (que determinamos) em relação à identidade do solicitante. Então ele enviará esse token de volta. Isso corresponde à etapa 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 esse token Consul para se comunicar com os dados do Consul, conforme determinado pelos privilégios do token.
A mágica é revelada!
Para aqueles de vocês que não estão felizes apenas com o coelho do chapéu e querem saber como ele funciona ... deixe-me "mostrar o quão profunda é a toca do coelho ".
Como mencionado anteriormente, nossa etapa "mágica" (Esquema 2: Etapa 4) é que o servidor Consul verifique a autenticidade da solicitação, colete informações sobre a solicitação e a compare com as regras predefinidas associadas. Esta etapa corresponde às etapas 3, 4 e 5 do diagrama de visão geral do Consul (Esquema 1). Abaixo está um diagrama (Esquema 3), cujo objetivo é mostrar claramente o que realmente acontece sob o capô de um método de autorização específico do Kubernetes.

Esquema 3: A mágica é revelada!
- Como ponto de partida, nosso cliente Consul redireciona a solicitação de logon para o servidor Consul com o token da conta Kubernetes e o nome da instância específica do método de autorização criado anteriormente. Este passo corresponde ao passo 3 na explicação anterior do circuito.
- Agora, o servidor Consul (ou líder) precisa verificar a autenticidade do token recebido. Portanto, ele consultará o cluster Kubernetes (por meio do cliente Consul) e, com as permissões apropriadas, descobriremos se o token é genuíno e a quem pertence.
- Em seguida, a solicitação verificada retorna ao líder do Consul e o servidor Consul procura uma instância do método de autorização com o nome especificado na solicitação de login (e digite Kubernetes).
- O líder do cônsul determina a instância especificada do método de autorização (se houver) e lê o conjunto de regras vinculativas anexadas a ele. Ele então lê essas regras e as compara com os atributos de identidade verificados.
- Tada! Vá para o passo 5 na explicação anterior do circuito.
Execute o Consul-server em uma máquina virtual comum
A partir de agora, darei principalmente instruções para a criação deste POC, geralmente em pontos, sem frases completas explicativas. Além disso, como 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).

- Crie uma regra para firewall (grupo de segurança na AWS):
- Eu 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.
- Abra a porta 8500 para a interface do usuário. Clique em Create. Mudaremos esse firewall [ link ] novamente em breve.
- Adicione a regra do firewall à instância. Retorne ao painel da VM no servidor Consul e adicione "skywiz-consul-server-poc" ao campo de tag de rede. Clique em Save.

- Instale o Consul em uma máquina virtual, confira aqui. Lembre-se de que você precisa da versão do Consul ≥ 1.5 [link]
- Crie 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
- Para um guia mais detalhado sobre a instalação do Consul e a configuração de um cluster de 3 nós, consulte aqui .
- Crie o arquivo /etc/consul.d/agent.json da seguinte maneira [ 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 vários resultados e terminar com "... atualização bloqueada por ACLs".
- Localize o endereço IP externo do servidor Consul e abra um navegador com esse endereço IP na porta 8500. Verifique se a interface do usuário é aberta.
- Tente adicionar um par de chave / valor. Deve haver um erro. Isso ocorre porque carregamos o servidor Consul usando a ACL e negamos todas as regras.
- Volte para o seu shell no servidor Consul e inicie o processo em segundo plano ou de alguma outra maneira para que ele funcione e digite o seguinte:
consul acl bootstrap
- Encontre o valor "SecretID" e volte para a interface do usuário. Na guia ACL, insira o identificador secreto do token que você acabou de copiar. Copie o SecretID em outro lugar, precisaremos mais tarde.
- Agora adicione um par de chave / valor. Para este POC, adicione o seguinte: key: “custom-ns / test_key”, valor: “Estou na pasta custom-ns!”
Inicie o Kubernetes Cluster para nosso aplicativo com o Consul Client como Daemonset
- Crie um cluster K8s (Kubernetes). Vamos criá-lo na mesma zona do servidor para acesso mais rápido e, portanto, podemos usar a mesma sub-rede para facilitar a conexão com endereços IP internos. Vamos chamá-lo de skywiz-app-with-consul-client-poc.

- Como observação, aqui está um bom guia que encontrei ao configurar um cluster do Consul POC com o Consul Connect.
- Também usaremos o gráfico de leme Hashicorp com um arquivo de valores estendidos.
- 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
- Aplique o gráfico de leme:
./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 ao "intervalo de endereços do pod" localizado no painel do cluster e retorne à nossa regra para o firewall skywiz-consul-server-poc.
- Inclua o intervalo de endereços para o IPA na lista de endereços IP e abra as portas 8301 e 8300.

- Vá para a interface do usuário do cônsul e em alguns minutos você verá que nosso cluster aparecerá na guia nó.

Configure o 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>
- Precisamos de 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 <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 decodifique-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 decodificar com base64) e grave-o no arquivo “ca.crt”.
- Agora crie uma instância do 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>" \ -kubernetes-ca-cert=@ca.crt \ -kubernetes-service-account- jwt="<decoded_token_retrieved_earlier>"
- Em seguida, precisamos criar uma regra e anexá-la à nova função. Você pode usar a UI do Consul para esta parte, mas usaremos a linha de comando.
- Escreva uma regra
### kv-custom-ns-policy.hcl key_prefix "custom-ns/" { policy = "write" }
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 identificador da regra que você acabou de criar a partir da 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"'
Últimas configurações
Direitos de acesso
- Crie permissões. Precisamos dar à Consul permissão para verificar e identificar a identidade do token da conta de serviço K8s.
- Escreva o seguinte [link] 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
kubectl create -f skywiz-poc-consul-server_rbac.yaml
Conecte-se ao Consul Client
- Conforme observado aqui , existem várias opções para conectar-se ao daemonset, mas passaremos à 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 o 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 mágica em ação!
- Crie mais algumas pastas de chaves com a mesma chave de nível superior (ou seja, <nova_pasta> / amostra_chave) e o valor de sua escolha. Crie políticas e funções apropriadas para novos caminhos-chave. Faremos as ligações mais tarde.

Teste de namespace personalizado:
- Crie nosso próprio espaço para nome:
kubectl create namespace custom-ns
- Crie abaixo em nosso novo espaço para nome. Escreva a configuração para a lareira.
###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
kubectl create -f poc-ubuntu-custom-ns.yaml
- Quando o contêiner iniciar, 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 para entrar no Consul usando o método de autorização que criamos anteriormente [ link ].
- Para visualizar 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>" }
curl \ --request POST \ --data @payload.json \ consul-ds-client.default.svc.cluster.local/v1/acl/login
- Para concluir as etapas acima em uma única linha (como 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
- Isso funciona! Deve pelo menos. 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 o "Value" base64 e verificar se ele corresponde ao valor em custom-ns / test_key na interface do usuário. Se você usou o mesmo valor acima neste manual, seu valor codificado seria IkknbSBpbiB0aGUgY3VzdG9tLW5zIGZvbGRlciEi.
Teste da conta de serviço do usuário:
- 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 a lareira. Observe que eu ativei 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 o shell dentro do contêiner.
kubectl exec -it poc-ubuntu-custom-sa /bin/bash
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 ligação de regra com as permissões apropriadas, vamos fazê-lo agora.
Repita as etapas anteriores acima:
a) Crie uma política idêntica para o prefixo "custom-sa /".
b) Crie uma função, nomeie-a "custom-sa-role"
c) Anexe a política à função.
- Crie uma vinculação de regras (possível apenas a partir de cli / api). Observe o valor 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"'
- Efetue login novamente no contêiner poc-ubuntu-custom-sa. Sucesso!
- Verifique 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 forneça acesso ao kv em "custom-ns /". Apenas repita o comando acima depois de substituir "custom-sa" pelo prefixo "custom-ns".
Permissão negada.
Exemplo de sobreposição:
- Vale ressaltar que todos os mapeamentos de ligação de regra 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 outra ligação de regra.
- Repita as etapas anteriores:
a) Crie uma política idêntica para o prefixo da chave “padrão /”.
b) Crie uma função, nomeie-a como "default-ns-role"
c) Anexe a política à função. - Criar vinculação de regras (possível apenas a partir de 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 / kv padrão.
- Permissão negada.
Você pode visualizar as credenciais especificadas para cada token na interface do usuário em ACL> Tokens. Como você pode ver, apenas uma "custom-sa-role" está anexada ao nosso token atual. O token que estamos usando no momento foi gerado quando efetuamos login e havia apenas uma ligação de regra, que então correspondia. Precisamos fazer login novamente e usar o novo token. - Certifique-se de ler os caminhos “custom-sa /” e “default /” kv.
Sucesso!
Isso ocorre porque o nosso poc-ubuntu-custom-sa corresponde às ligações das regras custom-sa e default-ns.
Conclusão
Token TTL mgmt?
No momento da redação deste documento, não havia uma maneira integrada de determinar o TTL para tokens gerados por este método de autorização. Seria uma oportunidade fantástica para fornecer automação segura da autorização do Consul.
É possível criar manualmente um token com TTL:
Espero que, em um futuro próximo, possamos controlar como os tokens são gerados (para cada regra ou método de autorização) e adicionar TTL.
Até então, propõe-se usar em sua lógica o ponto final da saída do sistema.
Leia também outros artigos em nosso blog: