Aller au contenu principal
Sommaire de la formation

RBAC : Role-based access control

coolibra473 vues

RBAC, ou Role-Based Access Control, est une méthode de gestion des autorisations dans Kubernetes. Il permet de définir qui peut faire quoi dans un cluster Kubernetes en attribuant des rôles et des règles à des utilisateurs ou à des groupes d'utilisateurs.

Composants clés de RBAC Kubernetes :

  1. Roles (rôles avec une porté namespace) : Les rôles définissent les autorisations (par exemple, la lecture, la création, la mise à jour ou la suppression) sur un ou plusieurs types de ressources (par exemple, pods, services, configmaps) dans un namespace spécifique.

  2. ClusterRoles (rôles avec une portée cluster) : Les rôles avec portée cluster sont similaires aux rôles, mais ils s'appliquent à l'ensemble du cluster, indépendamment de l'espace de noms.

  3. RoleBindings (liaisons de rôles) : Association des rôles à des utilisateurs ou à des groupes d'utilisateurs spécifiques dans un namespace donné.

  4. ClusterRoleBindings (liaisons avec une portée cluster) : Les liaisons de rôles au niveau du cluster associent des rôles au niveau du cluster à des utilisateurs ou à des groupes d'utilisateurs spécifiques dans l'ensemble du cluster.

  5. Service Account : Fournit une identité pour les processus qui s'exécutent dans un pod et est mappé à un objet Role/ClusterRole. Lorsque vous vous authentifiez auprès du serveur API, vous vous identifiez en tant qu'utilisateur particulier. Kubernetes reconnaît le concept d'utilisateur, cependant, Kubernetes lui-même ne dispose pas d'API utilisateur

 

Attention!

  1. Dans tous les namesapces, un serviceAcount default est créé et donne accès à l'api server. Il faut donc créer un autre service account pour cahque workload en désactivant son token: automountServiceAccountToken = false
  2. Les workloads metier generalement n'ont pas besoin d'acceder à l'api server. IL faut donc toujours mettre automountServiceAccountToken = false sur leur serviceAcount car il est true par defaut.
apiVersion: v1
kind: ServiceAccount
metadata:
  name: build-robot
automountServiceAccountToken: false  # desactive l'accès à l'api server

 

  • Création d'un Role et RoleBinding :
    • Création d'une idententité pour un pod :

Créez un utilisateur (dans le cadre de l'authentification Kubernetes, cela peut être un ServiceAccount) et liez-le au rôle que vous avez créé. Voici comment créer un utilisateur et une liaison de rôles (RoleBinding) :

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: role-get-pods
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["list"]

---

apiVersion: v1
kind: ServiceAccount
metadata:
  name: stagiaire-serviceaccount
  namespace: default

---

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: rolebinding-list-pods
  namespace: default
subjects:
- kind: ServiceAccount
  name: stagiaire-serviceaccount
roleRef:
  kind: Role
  name: role-get-pods
  apiGroup: rbac.authorization.k8s.io

---

apiVersion: v1
kind: Pod
metadata:
  name: kubectl-pod
spec:
  serviceAccountName: stagiaire-serviceaccount
  containers:
  - name: kubectl-container
    image: bitnami/kubectl:latest  # Utilisez l'image kubectl de Bitnami
    command: ["sleep"]  # Utilisez une commande qui attend pour maintenir le pod en vie
    args: ["3600"]       # Par exemple, faire dormir le pod pendant 1 heure (3600 secondes)

 

    • Le Role role-get-pods limite les doirts aux ressources pods ou un stagiaire et avec uniquement la possibilité de les lister(get).
    • Le service account statgiaire-serviceaccount est un compte que sera utilisé par le pod ou utilisateur pour s'autentifier aux près de l'api kube.
    • Le RoleBinding rolebinding-list-pods est utilisé pour faire correspondre le le role et le service account.
    • Les objets workloads ou utlisateurs qui vont utiliser ce service account seront limités aux droits listés dans le role et uniquement pour le namespace default.
    • On peut créer un kubeconfig avec ce service account et le donner à un stagiaire pour limiter ses droits

Mettre l'exemple dans un fichier pods-sa.yaml et l'executer.

kubectl apply -f pods-sa.yaml
kubectl get po,role,rolebinding,sa

 

 

On ouvre un shell dans le pode et faire des tests.

 

kubectl exec -it pods/kubectl-pod -- bash
kubectl get po  # marche
kubectl get role # ne marche pas
kubectl get po -n kube-system # ne marche pas car il s'agit d'un role limité au namespace default et non un cluster role

 

 

  • Création d'un ClusterRole et ClusterRoleBinding :
    • Création d'une idententité pour un pod :

Il s'agit du meme exemple mais avec une porté cluster. Ici on augmente les droits pour le manager de l'équipe par exemple. 

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cr-manager
rules:
- apiGroups: ["*"]
  resources: ["*"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

---

apiVersion: v1
kind: ServiceAccount
metadata:
  name: manager-sa
  namespace: default

---

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: manager-cr-binding
subjects:
- kind: ServiceAccount
  name: manager-sa
  namespace: default
roleRef:
  kind: ClusterRole
  name: cr-manager
  apiGroup: rbac.authorization.k8s.io

---
apiVersion: v1
kind: Pod
metadata:
  name: kubectl-pod-manager
  namespace: default
spec:
  serviceAccountName: manager-sa
  containers:
  - name: kubectl-container
    image: bitnami/kubectl:latest  # Utilisez l'image kubectl de Bitnami
    command: ["sleep"]  # Utilisez une commande qui attend pour maintenir le pod en vie
    args: ["3600"]       # Par exemple, faire dormir le pod pendant 1 heure (3600 secondes)

 

  • Le ClusterRole cr-manager limite les doirts à toutes les ressources et avec la possibilité d'executer ses verbes: "get", "list", "watch", "create", "update", "patch", "delete".
  • Le service account manager-sa est un compte que sera utilisé par le pod/chef d'équipe pour s'autentifier aux près de l'api kube.
  • Le ClusterRoleBinding manager-cr-binding est utilisé pour faire correspondre le cluster role et le service account.
  • Les objets workloads ou utilisateurs qui vont utiliser ce service account seront limités aux droits listés dans le cluster role et pour les namespaces du cluster.
  • On peut créer un kubeconfig avec ce service account et le donner à au manager pour limiter ses droits

 

Mettre l'exemple dans un fichier pods-cr-sa.yaml et l'executer.

kubectl apply -f pods-cr-sa.yaml
kubectl get po

 

On ouvre un shell dans le pode et faire des tests.

 

kubectl exec -it pods/kubectl-pod-manager -- bash
kubectl get po  # marche
kubectl get role # ne marche pas
kubectl get po -n kube-system # ne marche pas car il s'agit d'un role limité au namespace default et non un cluster role

 

 

Pour plus de restrictions:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: aggregate-cron-tabs-edit
  labels:
    # Add these permissions to the "admin" and "edit" default roles.
    rbac.authorization.k8s.io/aggregate-to-admin: "true"
    rbac.authorization.k8s.io/aggregate-to-edit: "true"
rules:
- apiGroups: ["stable.example.com"]
  resources: ["crontabs"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: stagiaire-serviceaccount
  namespace: default
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: aggregate-cron-tabs-view
  labels:
    # Add these permissions to the "view" default role.
    rbac.authorization.k8s.io/aggregate-to-view: "true"
rules:
- apiGroups: ["stable.example.com"]
  resources: ["crontabs"]
  verbs: ["get", "list", "watch"]
---
apiVersion: v1
kind: Pod
metadata:
  name: kubectl-pod
spec:
  serviceAccountName: stagiaire-serviceaccount
  containers:
  - name: kubectl-container
    image: bitnami/kubectl:latest  # Utilisez l'image kubectl de Bitnami
    command: ["sleep"]  # Utilisez une commande qui attend pour maintenir le pod en vie
    args: ["3600"]       # Par exemple, faire dormir le pod pendant 1 heure (3600 secondes)

 

ServiceAccount / context / kubeconfig

Comme le user va acceder à l'api server, on met automountServiceAccountToken = true ou on enlève tout simplement car activé par defaut.

#!/bin/sh

# Variables de configuration
clustername="test-k8s-kubeadm"
name="manager-sa"
ns="default"
server="https://192.168.1.200:6443"
crb=true  # mettre à true si cluster role binding et mettre rb = false
crb_name="manager-cr-binding"
rb=false # mettre à true si role binding et mettre crb = false
rb_name="manager-rolebinding"

# Vérification et création du ServiceAccount
if ! kubectl get sa "$name" -n "$ns" > /dev/null 2>&1; then
    kubectl create serviceaccount "$name" -n "$ns"
    echo "ServiceAccount $name créé dans le namespace $ns."
else
    echo "ServiceAccount $name existe déjà dans le namespace $ns."
fi

# Récupération du nom et UID du ServiceAccount
sa_name=$(kubectl get sa "$name" -n "$ns" -o jsonpath='{.metadata.name}')
sa_uid=$(kubectl get sa "$name" -n "$ns" -o jsonpath='{.metadata.uid}')

# Vérification et création du secret
secret_name="${sa_name}-token-${sa_uid}"
if ! kubectl get secret "$secret_name" -n "$ns" > /dev/null 2>&1; then
    kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
type: kubernetes.io/service-account-token
metadata:
  name: $secret_name
  namespace: $ns
  annotations:
    kubernetes.io/service-account.name: $sa_name
EOF
    echo "Secret $secret_name créé pour le ServiceAccount $sa_name."
else
    echo "Secret $secret_name existe déjà pour le ServiceAccount $sa_name."
fi

# Gestion des bindings (ClusterRoleBinding ou RoleBinding)
if [ "$crb" = true ] && [ "$rb" = true ]; then
    echo "Erreur : Vous ne pouvez pas activer à la fois 'crb' et 'rb'."
    exit 1
fi

if [ "$crb" = true ]; then
    if kubectl get clusterrolebinding "$crb_name" > /dev/null 2>&1; then
        kubectl patch clusterrolebinding "$crb_name" --type='json' -p="[{\"op\": \"add\", \"path\": \"/subjects/-\", \"value\": {\"kind\": \"ServiceAccount\", \"name\": \"$sa_name\", \"namespace\": \"$ns\"}}]"
        echo "ClusterRoleBinding $crb_name mis à jour avec le ServiceAccount $sa_name."
    else
        echo "Erreur : ClusterRoleBinding $crb_name n'existe pas."
        exit 1
    fi
elif [ "$rb" = true ]; then
    if kubectl get rolebinding "$rb_name" -n "$ns" > /dev/null 2>&1; then
        kubectl patch rolebinding "$rb_name" -n "$ns" --type='json' -p="[{\"op\": \"add\", \"path\": \"/subjects/-\", \"value\": {\"kind\": \"ServiceAccount\", \"name\": \"$sa_name\", \"namespace\": \"$ns\"}}]"
        echo "RoleBinding $rb_name mis à jour avec le ServiceAccount $sa_name dans le namespace $ns."
    else
        echo "Erreur : RoleBinding $rb_name n'existe pas dans le namespace $ns."
        exit 1
    fi
fi

# Génération du fichier kubeconfig
ca=$(kubectl get secret "$secret_name" -n "$ns" -o jsonpath='{.data.ca\.crt}')
token=$(kubectl get secret "$secret_name" -n "$ns" -o jsonpath='{.data.token}' | base64 --decode)

kubeconfig_content=$(cat <<EOF
apiVersion: v1
kind: Config
clusters:
- name: ${clustername}
  cluster:
    certificate-authority-data: ${ca}
    server: ${server}
contexts:
- name: ${sa_name}@${clustername}
  context:
    cluster: ${clustername}
    namespace: ${ns}
    user: ${sa_name}
users:
- name: ${sa_name}
  user:
    token: ${token}
current-context: ${sa_name}@${clustername}
EOF
)

config_file="${sa_name}@${clustername}"
echo "$kubeconfig_content" | tee "$config_file"
echo "Fichier kubeconfig généré : $config_file"

 

ServiceAccount / Cronjob

Comme le pod va acceder à l'api server, on met automountServiceAccountToken = true ou on enlève tout simplement car activé par defaut.

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: alertmanager-role
  namespace: cattle-monitoring-system # Should be namespace you are granting access to
rules:
- apiGroups: ["*"]
  resources: ["*"]
  verbs: ["scale", "get", "list", "watch", "create", "update", "patch"]

---

apiVersion: v1
kind: ServiceAccount
metadata:
  name: alertmanager-sa
  namespace: cattle-monitoring-system

---

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: alertmanager-rolebinding
  namespace: cattle-monitoring-system # Should be namespace you are granting access to
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: alertmanager-role # Should match name of Role
subjects:
- namespace: cattle-monitoring-system # Should match namespace where SA lives
  kind: ServiceAccount
  name: alertmanager-sa # Should match service account name, above

---

apiVersion: batch/v1
kind: CronJob
metadata:
  name: alertmanager-scaler-down
  namespace: cattle-monitoring-system
spec:
  schedule: "*/1 * * * *"  # À 09h00 tous les jours
  successfulJobsHistoryLimit: 0
  jobTemplate:
    spec:
      template:
        spec:
          serviceAccountName: alertmanager-sa
          containers:
          - name: scale-down
            image: bitnami/kubectl:latest  # Remplacez par votre image personnalisée pour le scaling
            command:
              - "bash"
              - "-c"
              - |
                kubectl patch statefulset alertmanager-rancher-monitoring-alertmanager -n cattle-monitoring-system --type json -p '[{"op": "remove", "path": "/metadata/labels/app.kubernetes.io~1managed-by"}]'
                kubectl scale --replicas=0 statefulset/alertmanager-rancher-monitoring-alertmanager -n cattle-monitoring-system
           restartPolicy: OnFailure

---

apiVersion: batch/v1
kind: CronJob
metadata:
  name: alertmanager-scaler-up
  namespace: cattle-monitoring-system
spec:
  schedule: "*/2 * * * *"  # À 18h00 tous les jours
  successfulJobsHistoryLimit: 0
  jobTemplate:
    spec:
      template:
        spec:
          serviceAccountName: alertmanager-sa
          containers:
          - name: scale-up
            image: bitnami/kubectl:latest  # Remplacez par votre image personnalisée pour le scaling
            command:
              - "bash"
              - "-c"
              - |
                kubectl scale --replicas=1 statefulset/alertmanager-rancher-monitoring-alertmanager -n cattle-monitoring-system
                kubectl patch statefulset alertmanager-rancher-monitoring-alertmanager -n cattle-monitoring-system --type merge -p '{"metadata": {"labels": {"app.kubernetes.io/managed-by": "Helm"}}}'
          restartPolicy: OnFailure

 

💡 Bonnes pratiques :

✅ Toujours appliquer le principe du moindre privilège.

✅ Toujours utiliser un serviceAccount différent du Default sa pour chaque workload. Le default sa à un accès par defaut à lapi server.

✅ Désactiver le automountServiceAccountToken pour tous les serviceAccount sauf si le l'utilisateur doit acceder à l'api server

✅ Privilégier les ClusterRoles pour des accès globaux et les Roles pour des accès spécifiques.

Commentaires

Connectez-vous pour rejoindre la discussion.

Aucun commentaire pour le moment.