Introdução à autorização Kubernetes do cônsul Hashicorp


É 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:


  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 sub por padrão.
  2. 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).
  3. Nosso cliente Cônsul encaminhará essa solicitação ao nosso servidor Cônsul.
  4. 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).
  5. 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).
  6. 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!


  1. 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.
  2. 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.
  3. 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).
  4. 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.
  5. 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" } 

  • Aplique 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 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 

  • Criar direitos de acesso

 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 

  • Criar em:

 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>" } 

  • Entrar!

 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 

  • 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 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:


Source: https://habr.com/ru/post/pt473014/


All Articles