Introduction à l'autorisation Kubernetes du consul Hashicorp

Introduction à l'autorisation Kubernetes du consul Hashicorp

C'est vrai, après la sortie Consul Hashicorp 1.5.0 début mai 2019, dans Consul, vous pourrez autoriser les applications et services exécutés nativement dans Kubernetes.

Dans ce tutoriel, nous allons créer étape par étape POC (Preuve de concept, PoC) démontrant cette nouvelle fonctionnalité. Vous devez avoir des connaissances de base de Kubernetes et de Consul de Hashicorp. Bien que vous puissiez utiliser n'importe quelle plate-forme cloud ou environnement sur site, dans ce didacticiel, nous utiliserons la plate-forme cloud de Google.

vue d'ensemble

Si nous allons à Documentation du consul sur sa méthode d'autorisation, nous aurons un aperçu rapide de son objectif et de son cas d'utilisation, ainsi que quelques détails techniques et un aperçu général de la logique. Je recommande fortement de le lire au moins une fois avant de continuer, car je vais maintenant tout expliquer et mâcher tout cela.

Introduction à l'autorisation Kubernetes du consul Hashicorp

Schéma 1 : Aperçu officiel du mode d'autorisation Consul

Regardons dedans documentation pour une méthode d'autorisation Kubernetes spécifique.

Bien sûr, vous y trouverez des informations utiles, mais il n’existe aucun guide sur la manière de les utiliser réellement. Ainsi, comme toute personne sensée, vous parcourez Internet pour obtenir des conseils. Et puis... Vous échouez. Ça arrive. Réparons ça.

Avant de passer à la création de notre POC, revenons sur l'aperçu des méthodes d'autorisation de Consul (Schéma 1) et affinons-le dans le contexte de Kubernetes.

Architecture

Dans ce tutoriel, nous allons créer un serveur Consul sur une machine distincte qui communiquera avec un cluster Kubernetes sur lequel le client Consul est installé. Nous créerons ensuite notre application factice dans le pod et utiliserons notre méthode d'autorisation configurée pour lire à partir de notre magasin de clés/valeurs Consul.

Le schéma ci-dessous détaille l'architecture que nous créons dans ce tutoriel, ainsi que la logique derrière la méthode d'autorisation, qui sera expliquée plus tard.

Introduction à l'autorisation Kubernetes du consul Hashicorp

Diagramme 2 : Présentation de la méthode d'autorisation Kubernetes

Un petit mot : le serveur Consul n'a pas besoin de vivre en dehors du cluster Kubernetes pour que cela fonctionne. Mais oui, il peut le faire de telle ou telle façon.

Ainsi, en prenant le diagramme de présentation Consul (Diagramme 1) et en y appliquant Kubernetes, nous obtenons le diagramme ci-dessus (Diagramme 2), et la logique ici est la suivante :

  1. Chaque pod sera associé à un compte de service contenant un jeton JWT généré et connu par Kubernetes. Ce jeton est également inséré dans le pod par défaut.
  2. Notre application ou service à l'intérieur du pod initie une commande de connexion à notre client Consul. La demande de connexion inclura également notre jeton et notre nom spécialement créé méthode d’autorisation (type Kubernetes). Cette étape n°2 correspond à l'étape 1 du diagramme Consul (Schéma 1).
  3. Notre client Consul transmettra ensuite cette demande à notre serveur Consul.
  4. LA MAGIE! C'est ici que le serveur Consul vérifie l'authenticité de la demande, collecte des informations sur l'identité de la demande et la compare avec les règles prédéfinies associées. Vous trouverez ci-dessous un autre diagramme pour illustrer cela. Cette étape correspond aux étapes 3, 4 et 5 du schéma de synthèse Consul (Schéma 1).
  5. Notre serveur Consul génère un jeton Consul avec des autorisations selon nos règles de méthode d'autorisation spécifiées (que nous avons définies) concernant l'identité du demandeur. Il renverra ensuite ce jeton. Cela correspond à l'étape 6 du diagramme Consul (Schéma 1).
  6. Notre client Consul transmet le jeton à l’application ou au service demandeur.

Notre application ou service peut désormais utiliser ce jeton Consul pour communiquer avec nos données Consul, comme déterminé par les privilèges du jeton.

La magie est révélée !

Pour ceux d'entre vous qui ne sont pas satisfaits d'un simple lapin sorti d'un chapeau et qui veulent savoir comment cela fonctionne... laissez-moi vous montrer à quel point trou de lapin».

Comme mentionné précédemment, notre étape « magique » (Figure 2 : Étape 4) est celle où le serveur Consul authentifie la demande, collecte des informations sur la demande et la compare à toutes les règles prédéfinies associées. Cette étape correspond aux étapes 3, 4 et 5 du schéma de synthèse Consul (Schéma 1). Ci-dessous se trouve un schéma (Schéma 3) dont le but est de montrer clairement ce qui se passe réellement sous la capuche méthode d’autorisation spécifique à Kubernetes.

Introduction à l'autorisation Kubernetes du consul Hashicorp

Schéma 3 : La magie est révélée !

  1. Pour commencer, notre client Consul transmet la demande de connexion à notre serveur Consul avec le jeton de compte Kubernetes et le nom d'instance spécifique de la méthode d'autorisation créée précédemment. Cette étape correspond à l'étape 3 de l'explication du circuit précédente.
  2. Le serveur Consul (ou leader) doit maintenant vérifier l'authenticité du jeton reçu. Il consultera donc le cluster Kubernetes (via le client Consul) et, avec les autorisations appropriées, nous saurons si le token est authentique et à qui il appartient.
  3. La demande validée est ensuite renvoyée au leader Consul, et le serveur Consul recherche l'instance de méthode d'autorisation avec le nom spécifié à partir de la demande de connexion (et le type Kubernetes).
  4. Le chef du consul identifie l'instance de méthode d'autorisation spécifiée (si elle est trouvée) et lit l'ensemble des règles contraignantes qui y sont attachées. Il lit ensuite ces règles et les compare aux attributs d'identité vérifiés.
  5. Et voilà! Passons à l'étape 5 de l'explication précédente du circuit.

Exécutez Consul-server sur une machine virtuelle standard

À partir de maintenant, je donnerai principalement des instructions sur la façon de créer ce POC, souvent sous forme de puces, sans explications en phrases complètes. De plus, comme indiqué précédemment, j'utiliserai GCP pour créer toute l'infrastructure, mais vous pouvez créer la même infrastructure n'importe où ailleurs.

  • Démarrez la machine virtuelle (instance/serveur).

Introduction à l'autorisation Kubernetes du consul Hashicorp

  • Créez une règle pour le pare-feu (groupe de sécurité dans AWS) :
  • J'aime attribuer le même nom de machine à la règle et à la balise réseau, dans ce cas "skywiz-consul-server-poc".
  • Recherchez l'adresse IP de votre ordinateur local et ajoutez-la à la liste des adresses IP sources afin que nous puissions accéder à l'interface utilisateur (UI).
  • Ouvrez le port 8500 pour l'interface utilisateur. Cliquez sur Créer. Nous allons bientôt changer à nouveau ce pare-feu [lien].
  • Ajoutez une règle de pare-feu à l'instance. Revenez au tableau de bord de la VM sur Consul Server et ajoutez « skywiz-consul-server-poc » au champ des balises réseau. Cliquez sur Enregistrer.

Introduction à l'autorisation Kubernetes du consul Hashicorp

  • Installez Consul sur une machine virtuelle, vérifiez ici. N'oubliez pas que vous avez besoin de la version Consul ≥ 1.5 [lien]
  • Créons un seul nœud Consul - la configuration est la suivante.

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

  • Pour un guide plus détaillé sur l'installation de Consul et la configuration d'un cluster de 3 nœuds, voir ici.
  • Créez un fichier /etc/consul.d/agent.json comme suit [lien]:

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

  • Démarrez notre serveur Consul :

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

  • Vous devriez voir un tas de résultats et vous retrouver avec « … mise à jour bloquée par les ACL ».
  • Recherchez l'adresse IP externe du serveur Consul et ouvrez un navigateur avec cette adresse IP sur le port 8500. Assurez-vous que l'interface utilisateur s'ouvre.
  • Essayez d'ajouter une paire clé/valeur. Il y a sûrement une erreur. En effet, nous avons chargé le serveur Consul avec une ACL et désactivé toutes les règles.
  • Revenez à votre shell sur le serveur Consul et démarrez le processus en arrière-plan ou par un autre moyen pour le faire fonctionner et entrez ce qui suit :

consul acl bootstrap

  • Recherchez la valeur « SecretID » et revenez à l'interface utilisateur. Dans l'onglet ACL, saisissez l'ID secret du jeton que vous venez de copier. Copiez SecretID ailleurs, nous en aurons besoin plus tard.
  • Ajoutez maintenant une paire clé/valeur. Pour ce POC, ajoutez ce qui suit : clé : "custom-ns/test_key", valeur : "Je suis dans le dossier custom-ns !"

Lancement d'un cluster Kubernetes pour notre application avec le client Consul comme Daemonet

  • Créez un cluster K8s (Kubernetes). Nous allons le créer dans la même zone que le serveur pour un accès plus rapide, et ainsi pouvoir utiliser le même sous-réseau pour nous connecter facilement aux adresses IP internes. Nous l'appellerons "skywiz-app-with-consul-client-poc".

Introduction à l'autorisation Kubernetes du consul Hashicorp

  • En remarque, voici un bon tutoriel que j'ai découvert lors de la configuration d'un cluster POC Consul avec Consul Connect.
  • Nous utiliserons également le graphique de barre Hashicorp avec un fichier de valeurs étendu.
  • Installez et configurez Helm. Étapes de configuration :

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

  • Appliquer le tableau de barre :

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

  • Lorsqu'il essaiera de s'exécuter, il aura besoin d'autorisations pour le serveur Consul, ajoutons-les donc.
  • Notez la « Plage d'adresses du pod » située sur le tableau de bord du cluster et reportez-vous à notre règle de pare-feu « skywiz-consul-server-poc ».
  • Ajoutez la plage d'adresses du pod à la liste des adresses IP et ouvrez les ports 8301 et 8300.

Introduction à l'autorisation Kubernetes du consul Hashicorp

  • Accédez à l'interface utilisateur de Consul et après quelques minutes, vous verrez notre cluster apparaître dans l'onglet nœuds.

Introduction à l'autorisation Kubernetes du consul Hashicorp

Configuration d'une méthode d'autorisation en intégrant Consul à Kubernetes

  • Revenez au shell du serveur Consul et exportez le jeton que vous avez enregistré précédemment :

export CONSUL_HTTP_TOKEN=<SecretID>

  • Nous aurons besoin des informations de notre cluster Kubernetes pour créer une instance de la méthode auth :
  • hôte kubernetes

kubectl get endpoints | grep kubernetes

  • compte-de-service-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:

  • Le jeton est codé en base64, alors déchiffrez-le à l'aide de votre outil préféré [lien]
  • kubernetes-ca-cert

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

  • Prenez le certificat « ca.crt » (après décodage en base64) et écrivez-le dans le fichier « ca.crt ».
  • Instanciez maintenant la méthode auth, en remplaçant les espaces réservés par les valeurs que vous venez de recevoir.

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

  • Ensuite, nous devons créer une règle et l'attacher au nouveau rôle. Pour cette partie, vous pouvez utiliser Consul UI, mais nous utiliserons la ligne de commande.
  • Écrivez une règle

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

  • Appliquer la règle

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

  • Recherchez l'ID de la règle que vous venez de créer à partir de la sortie.
  • Créez un rôle avec une nouvelle règle.

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

Enfin les configurations

Droits d'accès

  • Créez des droits d'accès. Nous devons autoriser Consul à vérifier et identifier l'identité du jeton du compte de service K8s.
  • Écrivez ce qui suit dans le fichier [lien]:

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

  • Créons des droits d'accès

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

Connexion au client Consul

  • Comme indiqué iciIl existe plusieurs options pour se connecter au démonset, mais nous allons passer à la solution simple suivante :
  • Appliquez le fichier suivant [lien].

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

  • Utilisez ensuite la commande intégrée suivante pour créer un configmap [lien]. Attention, nous faisons référence au nom de notre service, remplacez-le si nécessaire.

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

Tester la méthode d'authentification

Voyons maintenant la magie en action !

  • Créez plusieurs dossiers de clés supplémentaires avec la même clé de niveau supérieur (c'est-à-dire /sample_key) et une valeur de votre choix. Créez des politiques et des rôles appropriés pour les nouveaux chemins clés. Nous ferons les liaisons plus tard.

Introduction à l'autorisation Kubernetes du consul Hashicorp

Test d'espace de noms personnalisé :

  • Créons notre propre espace de noms :

kubectl create namespace custom-ns

  • Créons un pod dans notre nouvel espace de noms. Écrivez la configuration du 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

  • Créer sous :

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

  • Une fois le conteneur exécuté, allez-y et installez curl.

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

  • Nous allons maintenant envoyer une demande de connexion à Consul en utilisant la méthode d'autorisation que nous avons créée précédemment [lien].
  • Pour afficher le jeton saisi depuis votre compte de service :

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

  • Écrivez ce qui suit dans un fichier à l'intérieur du conteneur :

### payload.json
{
 "AuthMethod": "auth-method-test",
 "BearerToken": "<jwt_token>"
}

  • S'identifier!

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

  • Pour effectuer les étapes ci-dessus sur une seule ligne (puisque nous exécuterons plusieurs tests), vous pouvez procéder comme suit :

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

  • Travaux! Au moins, cela devrait être le cas. Prenez maintenant le SecretID et essayez d'accéder à la clé/valeur à laquelle nous devrions avoir accès.

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

  • Vous pouvez décoder en base64 "Valeur" et voir qu'elle correspond à la valeur dans custom-ns/test_key dans l'interface utilisateur. Si vous avez utilisé la même valeur ci-dessus dans ce didacticiel, votre valeur codée serait IkknbSBpbiB0aGUgY3VzdG9tLW5zIGZvbGRlciEi.

Test du compte de service utilisateur :

  • Créez un ServiceAccount personnalisé à l'aide de la commande suivante [lien].

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

  • Créez un nouveau fichier de configuration pour le pod. Veuillez noter que j'ai inclus l'installation de curl pour économiser du travail :)

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

  • Après cela, exécutez un shell à l’intérieur du conteneur.

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

  • S'identifier!

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

  • Permission refusée. Oh, nous avons oublié d'ajouter une nouvelle liaison de règles avec les autorisations appropriées, faisons-le maintenant.

Répétez les étapes précédentes ci-dessus :
a) Créez une politique identique pour le préfixe « custom-sa/ ».
b) Créez un rôle, appelez-le « custom-sa-role »
c) Attachez la politique au rôle.

  • Créez une liaison de règle (possible uniquement à partir de cli/api). Notez la signification différente du drapeau de sélection.

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

  • Connectez-vous à nouveau depuis le conteneur "poc-ubuntu-custom-sa". Succès!
  • Consultez notre accès au chemin custom-sa/key.

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

  • Vous pouvez également vous assurer que ce jeton n'accorde pas l'accès à kv dans "custom-ns/". Répétez simplement la commande ci-dessus après avoir remplacé « custom-sa » par le préfixe « custom-ns ».
    Permission refusée.

Exemple de superposition :

  • Il convient de noter que tous les mappages de liaison de règles seront ajoutés au jeton avec ces droits.
  • Notre conteneur "poc-ubuntu-custom-sa" se trouve dans l'espace de noms par défaut - utilisons-le donc pour une liaison de règles différente.
  • Répétez les étapes précédentes :
    a) Créez une stratégie identique pour le préfixe de clé « default/ ».
    b) Créez un rôle, nommez-le « default-ns-role »
    c) Attachez la politique au rôle.
  • Créer une liaison de règle (uniquement possible à 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"'

  • Revenez à notre conteneur "poc-ubuntu-custom-sa" et essayez d'accéder au chemin kv "default/".
  • Permission refusée.
    Vous pouvez afficher les informations d'identification spécifiées pour chaque jeton dans l'interface utilisateur sous ACL > Jetons. Comme vous pouvez le voir, notre jeton actuel n’est associé qu’à un seul « rôle-sa-personnalisé ». Le jeton que nous utilisons actuellement a été généré lorsque nous nous sommes connectés et il n'y avait alors qu'une seule liaison de règle qui correspondait. Nous devons nous reconnecter et utiliser le nouveau jeton.
  • Assurez-vous que vous pouvez lire à la fois les chemins kv « custom-sa/ » et « default/ ».
    Succès!
    En effet, notre « poc-ubuntu-custom-sa » correspond aux liaisons de règles « custom-sa » et « default-ns ».

Conclusion

Gestion des jetons TTL ?

Au moment d'écrire ces lignes, il n'existe aucun moyen intégré pour déterminer la durée de vie des jetons générés par cette méthode d'autorisation. Ce serait une opportunité fantastique de fournir une automatisation sécurisée de l’autorisation consulaire.

Il existe une option pour créer manuellement un jeton avec TTL :

Espérons que dans un avenir proche, nous serons en mesure de contrôler la façon dont les jetons sont générés (par règle ou méthode d'autorisation) et d'ajouter du TTL.

En attendant, il est suggéré d'utiliser un point de terminaison de déconnexion dans votre logique.

Lisez également d'autres articles sur notre blog:

Source: habr.com

Ajouter un commentaire