Introducerea în Autorizarea Kubernetes a Hashicorp Consul

Introducerea în Autorizarea Kubernetes a Hashicorp Consul

Totul este corect, după lansare Hashicorp Consul 1.5.0 la începutul lunii mai 2019, în Consul este posibil să se facă autorizarea aplicațiilor și serviciilor care rulează în Kubernetes, nativ.

În acest ghid, vom crea pas cu pas POC (Proba de concept (Proof of concept, PoC) — dovada [viabilității] conceptului — n.red.), demonstrând această nouă funcționalitate. Se așteaptă de la dumneavoastră cunoștințe de bază despre Kubernetes și Hashicorp’s Consul. Și, deși puteți utiliza orice platformă cloud sau un mediu local, în acest ghid ne vom folosi de Google’s Cloud Platform.

Prezentare generală

Dacă ne îndreptăm spre documentația Consul pentru metoda sa de autorizare, vom obține o prezentare generală a scopului și cazului de utilizare, precum și câteva detalii tehnice și o imagine de ansamblu asupra logicii. Vă recomand cu tărie să o citiți cel puțin o dată înainte de a continua, deoarece acum voi explica și detalia toate acestea.

Introducerea în Autorizarea Kubernetes a Hashicorp Consul

Schema 1: Prezentarea oficială a metodei de autorizare Consul

Să ne uităm în documentația pentru metoda specifică de autorizare Kubernetes.

Desigur, există informații utile acolo, dar nu există un ghid despre cum să folosiți efectiv toate acestea. Așa că, ca orice persoană cu bun simț, căutați pe internet un ghid. Și apoi... suferiți o înfrângere. Se mai întâmplă. Haideți să corectăm asta.

Înainte de a începe crearea POC-ului nostru, să ne întoarcem la prezentarea generală a metodelor de autorizare Consul (Schema 1) și să o detaliem în contextul Kubernetes.

Arhitectură

În acest ghid, vom crea un server Consul pe o mașină separată, care va interacționa cu clusterul Kubernetes cu clientul Consul instalat. Apoi, vom crea aplicația noastră fictivă în pod și vom folosi metoda noastră de autorizare configurată pentru a citi din stocarea Consul key/value.

Schema de mai jos ilustrează detaliile arhitecturii pe care o construim în acest ghid, precum și logica metodei de autorizare, care va fi explicată ulterior.

Introducerea în Autorizarea Kubernetes a Hashicorp Consul

Schema 2: Prezentarea metodei de autorizare în Kubernetes

O mică observație: serverul Consul nu trebuie să fie situat în afara clusterului Kubernetes pentru a funcționa. Dar da, poate fi și așa.

Așadar, luând schema de bază Consul (Schema 1) și aplicând-o la Kubernetes, obținem diagramă de mai sus (Schema 2), iar logica va fi următoarea:

  1. Fiecărei pod îi va fi atașat un cont de serviciu, care conține un token JWT, generat și cunoscut de Kubernetes. Acest token este, de asemenea, inserat în podul implicit.
  2. Aplicația sau serviciul nostru din interiorul podului inițiază un comutator de autentificare către clientul nostru Consul. În cererea de autentificare va fi inclus și tokenul nostru și va fi specificat numele creat special metodei de autorizare (tip Kubernetes). Acest pas nr. 2 corespunde pasului 1 din schema Consul (Schema 1).
  3. Clientul nostru Consul va direcționa apoi această cerere către serverul nostru Consul.
  4. MAGIE! Aici serverul Consul verifică autenticitatea cererii, adună informațiile despre identitatea cererii și le compară cu eventuale reguli predefinite asociate. Mai jos va fi o altă schemă pentru a ilustra acest lucru. Acest pas corespunde pașilor 3, 4 și 5 din schema de revizuire Consul (Schema 1).
  5. Serverul nostru Consul generează un token Consul cu permisiuni conforme cu regulile specificate de noi pentru metoda de autorizare (pe care le-am definit) în raport cu identitatea solicitantului. Apoi, acesta va trimite înapoi acest token. Acesta corespunde pasului 6 din schema Consul (Schema 1).
  6. Clientul nostru Consul redirecționează tokenul aplicației sau serviciului solicitant.

Aplicația sau serviciul nostru pot acum utiliza acest token Consul pentru a comunica cu datele noastre Consul, așa cum a fost definit în privilegiile tokenului.

Magia dezvăluită!

Pentru cei dintre voi care nu sunt mulțumiți doar cu un iepure din pălărie și vor să știe cum funcționează… permiteți-mi să vă „arăt cât de adâncă vopseaua de iepure».

După cum am menționat anterior, „magicul” nostru pas (Schema 2: Pasul 4) constă în faptul că serverul Consul verifică autenticitatea cererii, adună detalii despre cerere și le compară cu orice reguli predefinite asociate. Acest pas corespunde pașilor 3, 4 și 5 din schema de revizuire Consul (Schema 1). Mai jos este o schemă (Schema 3), al cărei scop este să arate vizibil ceea ce se întâmplă de fapt sub capotă metodei specifice de autorizare Kubernetes.

Introducerea în Autorizarea Kubernetes a Hashicorp Consul

Schema 3: Magia dezvăluită!

  1. Ca punct de plecare, clientul nostru Consul redirecționează cererea de autentificare către serverul nostru Consul cu tokenul contului Kubernetes și numele specific al instanței metodei de autorizare, care a fost creat anterior. Acest pas corespunde pasului 3 din explicația anterioară a schemei.
  2. Acum, serverul Consul (sau liderul) trebuie să verifice autenticitatea tokenului primit. De aceea, acesta va consulta clusterul Kubernetes (prin intermediul clientului Consul) și, în cazul în care are permisiunile necesare, vom determina dacă tokenul este autentic și cui aparține.
  3. Apoi, cererea verificată este returnată liderului Consul, iar pe serverul Consul se caută instanța metodei de autorizare cu numele specificat din cererea de autentificare (de tip Kubernetes).
  4. Liderul Consul identifică instanța specificată a metodei de autorizare (dacă este găsită) și citește setul de reguli de legătură care îi sunt atașate. Apoi, citește aceste reguli și le compară cu atributele identității verificate.
  5. Tada! Trecem la pasul 5 din explicația anterioară a schemei.

Rulați Consul-server pe o mașină virtuală obișnuită.

De acum înainte, voi oferi în principal instrucțiuni pentru crearea acestui POC, adesea sub formă de puncte, fără propoziții explicative întregi. De asemenea, după cum am menționat anterior, voi folosi GCP pentru a crea întreaga infrastructură, dar puteți crea o infrastructură similară în altă parte.

  • Rulați o mașină virtuală (instanță / server).

Introducerea în Autorizarea Kubernetes a Hashicorp Consul

  • Creează o regulă pentru firewall (grup de securitate în AWS):
  • Îmi place să atribui același nume mașinii regulii și etichetei de rețea, în acest caz este «skywiz-consul-server-poc».
  • Găsiți adresa IP a computerului local și adăugați-o în lista IP-urilor sursă, astfel încât să putem accesa interfața utilizatorului (UI).
  • Deschideți portul 8500 pentru UI. Faceți clic pe Create (Creează). Vom modifica din nou acest firewall în curând [linkul].
  • Adăugați regula pentru firewall instanței. Întoarceți-vă la tabloul de bord VM de pe serverul Consul și adăugați «skywiz-consul-server-poc» în câmpul etichetelor de rețea. Faceți clic pe Save (Salvează).

Introducerea în Autorizarea Kubernetes a Hashicorp Consul

  • Instalați Consul pe mașina virtuală, verificați aici. Amintiți-vă că aveți nevoie de versiunea Consul ≥ 1.5 [link]
  • Să creăm un Consul single node — configurația este următoarea.

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

  • Un ghid mai detaliat pentru instalarea Consul și configurarea unui cluster de 3 noduri poate fi găsit aici. aici.
  • Creează fișierul /etc/consul.d/agent.json astfel [linkul]:

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

  • Rulați serverul nostru Consul:

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

  • Ar trebui să vedeți o mulțime de ieșiri și, în final, „… actualizare blocată de ACL-uri”.
  • Găsiți adresa IP externă a serverului Consul și deschideți un browser cu această adresă IP pe portul 8500. Asigurați-vă că interfața utilizatorului se deschide.
  • Încercați să adăugați o pereche cheie/valoare. Ar trebui să fie o eroare. Acest lucru se datorează faptului că am încărcat serverul Consul cu ACL și am interzis toate regulile.
  • Întoarceți-vă la shell-ul de pe serverul Consul și rulați procesul în fundal sau în alt mod pentru a-l face să funcționeze, și introduceți următoarele:

consul acl bootstrap

  • Găsiți valoarea „SecretID” și întoarceți-vă la interfața utilizatorului. În tab-ul „ACL”, introduceți identificatorul secret al tokenului pe care tocmai l-ați copiat. Salvați SecretID undeva, ne va fi necesar mai târziu.
  • Acum adăugați o pereche cheie/valoare. Pentru acest POC, vom adăuga următoarele: cheie: „custom-ns/test_key”, valoare: „Sunt în folderul custom-ns!”

Lansare a clusterului Kubernetes pentru aplicația noastră cu clientul Consul ca Daemonset

  • Creați un cluster K8s (Kubernetes). Îl vom crea în aceeași zonă ca serverul, pentru un acces mai rapid, astfel încât putem folosi aceeași subrețea pentru o conexiune ușoară cu adrese IP interne. Îl vom numi „skywiz-app-with-consul-client-poc”.

Introducerea în Autorizarea Kubernetes a Hashicorp Consul

  • Ca o notă, iată un ghid bun cu care m-am întâlnit în timpul configurării POC-ului clusterului Consul cu Consul Connect.
  • De asemenea, vom folosi graficul helm Hashicorp cu un fișier de valori extins.
  • Instalați și configurați Helm. Etapele de configurare:

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

  • Aplicați graficul helm:

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

  • Când încercați să rulați, îi vor fi necesare permisiuni pentru serverul Consul, așa că haideți să le adăugăm.
  • Reveniți la „intervalul de adrese Pod” situat pe panoul de control al clusterului și întoarceți-vă la regula noastră pentru firewall-ul „skywiz-consul-server-poc”.
  • Adăugați intervalul de adrese pentru pod în lista de adrese IP și deschideți porturile 8301 și 8300.

Introducerea în Autorizarea Kubernetes a Hashicorp Consul

  • Accesați interfața utilizatorului Consul, iar în câteva minute veți vedea că clusterul nostru va apărea pe tab-ul noduri.

Introducerea în Autorizarea Kubernetes a Hashicorp Consul

Configurarea metodei de autorizare prin integrarea Consul cu Kubernetes

  • Întoarceți-vă la shell-ul serverului Consul și exportați tokenul pe care l-ați salvat anterior:

export CONSUL_HTTP_TOKEN=

  • Vom necesita informații din clusterul nostru Kubernetes pentru a crea o instanță a metodei 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:

  • Tokenul este codificat în base64, așa că decodificați-l cu instrumentul dumneavoastră preferat [linkul]
  • kubernetes-ca-cert

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

  • Luați certificatul "ca.crt" (după decodificare cu base64) și introduceți-l în fișierul "ca.crt".
  • Acum creați o instanță a metodei auth, înlocuind locurile rezervate cu valorile pe care tocmai le-ați obținut.

consul acl auth-method create -type "kubernetes" -name "auth-method-skywiz-consul-poc" -description "Aceasta este o metodă de autentificare folosind kubernetes pentru clusterul skywiz-app-with-consul-client-poc" -kubernetes-host "" -kubernetes-ca-cert=@ca.crt -kubernetes-service-account-jwt=""

  • În continuare, trebuie să creăm o regulă și să o atașăm unui nou rol. Pentru această parte, puteți folosi interfața utilizatorului Consul, dar vom folosi linia de comandă.
  • Scrieți regula

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

  • Aplicați regula

consul acl policy create -name kv-custom-ns-policy -description "Aceasta este o politică exemplu pentru kv la custom-ns/" -rules @kv-custom-ns-policy.hcl

  • Găsiți identificatorul regulii pe care tocmai ați creat-o din ieșirea datelor.
  • Creați un rol cu noua regulă.

consul acl role create -name "custom-ns-role" -description "Aceasta este un rol exemplu pentru spațiul de nume 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"'

Configurările de final

Permisiuni

  • Creați permisiunile. Trebuie să dăm Consul permisiunea de a verifica și identifica certificatul tokenului contului de serviciu K8s.
  • Scrieți în fișier următorul lucru [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

  • Să creăm permisiunile

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

Conectare la Consul Client

  • După cum s-a menționat aici, există câteva opțiuni pentru a se conecta la daemonset, dar vom trece la următoarea soluție simplă:
  • Aplicați următorul fișier [linkul].

### 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

  • Apoi, aplicați următoarea comandă încorporată pentru a crea configmap [linkul]. Rețineți că facem referire la numele serviciului nostru, înlocuiți-l dacă este necesar.

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

Testarea metodei de autentificare

Acum să vedem magia în acțiune!

  • Creează câteva alte foldere cheie cu aceeași cheie de nivel superior (adică /sample_key) și o valoare la alegerea ta. Creează politicile și rolurile corespunzătoare pentru noile căi de cheie. Vom face legăturile mai târziu.

Introducerea în Autorizarea Kubernetes a Hashicorp Consul

Testul utilizatorului pentru spațiul de nume:

  • Să creăm propriul nostru spațiu de nume:

kubectl create namespace custom-ns

  • Să creăm un pod în noul nostru spațiu de nume. Scrie configurația pentru 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

  • Creează un pod:

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

  • Odată ce containerul pornește, intră în el și instalează curl.

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

  • Acum vom trimite o cerere de autentificare către Consul, folosind metoda de autorizare pe care am creat-o anterior [linkul].
  • Pentru a vizualiza tokenul introdus din contul tău de serviciu:

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

  • Scrie următoarele în fișierul din interiorul containerului:

### 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

  • Pentru a executa pașii de mai sus într-o singură linie (deoarece vom face mai multe teste), poți face următoarele:

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

  • Merge! Ar trebui să funcționeze, cel puțin. Acum ia SecretID și încearcă să accesezi cheia/valoarea la care ar trebui să avem acces.

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

  • Poți decoda „Value” base64 și vezi că se potrivește cu valoarea din custom-ns/test_key în UI. Dacă ai folosit aceeași valoare menționată mai sus în acest ghid, valoarea ta codificată va fi IkknbSBpbiB0aGUgY3VzdG9tLW5zIGZvbGRlciEi.

Testul contului de serviciu personalizat:

  • Creează un ServiceAccount personalizat folosind următoarea comandă [linkul].

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

  • Creează un nou fișier de configurație pentru pod. Observă că am inclus instalarea curl pentru a economisi efort 🙂

###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

  • După aceea, lansează shell-ul în interiorul containerului.

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

  • Permisiune refuzată. Oh, am uitat să adăugăm un nou binding de reguli cu permisiunile corespunzătoare, să facem asta acum.

Repetă pașii anteriori de mai sus:
a) Creează o Politică identică pentru prefixul „custom-sa/”.
b) Creează un Rol, numește-l „custom-sa-role”
c) Atașează Politica la Rol.

  • Creează un Rule-Binding (posibil doar din cli / api). Acordă atenție unei alte valori a semnului selector.

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

  • Reîntrează-te în sistem din containerul „poc-ubuntu-custom-sa”. Succes!
  • Verifică accesul nostru la calea cheie custom-sa/.

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

  • De asemenea, poți verifica că acest token nu oferă acces la kv în „custom-ns/”. Pur și simplu repetă comanda de mai sus înlocuind „custom-sa” cu prefixul „custom-ns”.
    Permisiune refuzată.

Exemplu de overlay:

  • Merită menționat că toate asocierile de rule-binding vor fi adăugate la token cu aceste drepturi.
  • Containerul nostru „poc-ubuntu-custom-sa” se află în spațiul de nume implicit — așa că să-l folosim pentru un alt rule-binding.
  • Repetă pașii anteriori:
    a) Creează o Politică identică pentru prefixul cheii „default/”.
    b) Creează un Rol, numește-l „default-ns-role”
    c) Atașează Politica la Rol.
  • Creează un Rule-Binding (posibil doar din 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"'

  • Întoarce-te la containerul nostru „poc-ubuntu-custom-sa” și încearcă să accesezi calea „default/” kv.
  • Permisiune refuzată.
    Poți vizualiza acreditivele specificate pentru fiecare token în UI în secțiunea ACL > Tokens. Așa cum vezi, la tokenul nostru curent este atașată doar o „custom-sa-role”. Tokenul pe care îl folosit în prezent a fost generat când ne-am autentificat, și atunci a existat doar un singur rule-binding care corespundea. Trebuie să ne autentificăm din nou și să folosim un nou token.
  • Asigură-te că poți citi atât din căile „custom-sa/”, cât și din „default/” kv.
    Succes!
    Aceasta se datorează faptului că „poc-ubuntu-custom-sa” corespunde bindurilor de reguli „custom-sa” și „default-ns”.

Concluzie

Gestionarea token-ului TTL?

La momentul redactării acestui articol, nu există o modalitate integrată de a determina TTL pentru token-urile generate prin această metodă de autorizare. Aceasta ar fi o oportunitate fantastică - pentru a oferi automatizare sigură pentru autorizarea Consul.

Există posibilitatea de a crea manual un token cu TTL:

Sper că în curând vom putea controla modul în care sunt generate tokenurile (pentru fiecare regulă sau metodă de autorizare) și adăuga TTL.

Până atunci, se recomandă utilizarea în logica sa a endpoint-ului de deconectare.

Citiți și alte articole de pe blogul nostru:

Sursa: habr.com

Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS 🔥 Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS | ProHoster