
TÎt ou tard, la question de la sécurité se pose lors de l'exploitation de tout systÚme : la mise en place de l'authentification, la répartition des droits, l'audit et d'autres tùches. Pour Kubernetes, plusieurs solutions ont déjà été créées Kubernetes dispose de deux types d'utilisateurs :
Authentification
Service Accounts
- â des comptes gĂ©rĂ©s par l'API Kubernetes ; â des utilisateurs « normaux », gĂ©rĂ©s par des services externes et indĂ©pendants.
- Utilisateurs La principale diffĂ©rence entre ces types rĂ©side dans le fait qu'il existe des objets spĂ©cifiques dans l'API Kubernetes pour les Service Accounts (appelĂ©s simplement â
ServiceAccounts ), qui sont liĂ©s Ă un namespace et Ă un ensemble de donnĂ©es d'autorisation stockĂ©es dans le cluster sous forme d'objets de type Secrets. Ces utilisateurs (Service Accounts) sont principalement destinĂ©s Ă gĂ©rer les droits d'accĂšs Ă l'API Kubernetes pour les processus s'exĂ©cutant dans le cluster Kubernetes.Les Users ordinaires, en revanche, n'ont pas d'enregistrements dans l'API Kubernetes : leur gestion doit ĂȘtre effectuĂ©e par des mĂ©canismes externes. Ils sont destinĂ©s aux personnes ou aux processus rĂ©sidant en dehors du cluster.
Chaque requĂȘte Ă l'API est associĂ©e soit Ă un Service Account, soit Ă un User, soit est considĂ©rĂ©e comme anonyme.
Les données d'authentification de l'utilisateur comprennent :
â le nom d'utilisateur (sensible Ă la casse !) ;
- Nom d'utilisateur UID
- â une chaĂźne d'identification machine lisible qui est « plus cohĂ©rente et unique que le nom d'utilisateur » ; â la liste des groupes auxquels appartient l'utilisateur ;
- Groupes Extra
- â des champs supplĂ©mentaires pouvant ĂȘtre utilisĂ©s par le mĂ©canisme d'autorisation. Kubernetes peut utiliser de nombreux mĂ©canismes d'authentification : certificats X509, jetons Bearer, proxy d'authentification, HTTP Basic Auth. GrĂące Ă ces mĂ©canismes, il est possible de mettre en Ćuvre une variĂ©tĂ© de schĂ©mas d'autorisation : d'un simple fichier avec des mots de passe Ă OpenID OAuth2.
De plus, l'utilisation de plusieurs schémas d'autorisation simultanément est autorisée. Par défaut, le cluster utilise :
des jetons de compte de service â pour les Service Accounts ;
- X509 â pour les Users.
- X509 â pour les utilisateurs.
La question de la gestion des ServiceAccounts dépasse le cadre de cet article, et je recommande à ceux qui souhaitent en savoir plus de commencer par . Nous allons examiner en détail la question des certificats X509.
Certificats pour les utilisateurs (X.509)
La méthode classique pour travailler avec les certificats implique :
- génération de la clé :
mkdir -p ~/mynewuser/.certs/ openssl genrsa -out ~/mynewuser.key 2048 - génération d'une demande de certificat :
openssl req -new -key ~/mynewuser.key -out ~/mynewuser.csr -subj "/CN=mynewuser/O=company" - traitement de la demande de certificat avec les clés CA du cluster Kubernetes, obtention du certificat utilisateur (pour obtenir le certificat, il est nécessaire d'utiliser un compte ayant accÚs à la clé de l'autorité de certification du cluster Kubernetes, qui se trouve par défaut dans
/etc/kubernetes/pki/ca.key):openssl x509 -req -in ~/mynewuser.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out ~/mynewuser.crt -days 500 - création du fichier de configuration :
- description du cluster (indiquez l'adresse et l'emplacement du fichier de certificat CA de l'installation spécifique du cluster) :
kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --server=https://192.168.100.200:6443 - ou â comme neoption recommandĂ©e â vous pouvez ne pas spĂ©cifier le certificat racine (dans ce cas, kubectl ne vĂ©rifiera pas la validitĂ© de l'api-server du cluster) :
kubectl config set-cluster kubernetes --insecure-skip-tls-verify=true --server=https://192.168.100.200:6443 - ajout d'un utilisateur dans le fichier de configuration :
kubectl config set-credentials mynewuser --client-certificate=.certs/mynewuser.crt --client-key=.certs/mynewuser.key - ajout du contexte :
kubectl config set-context mynewuser-context --cluster=kubernetes --namespace=target-namespace --user=mynewuser - définir le contexte par défaut :
kubectl config use-context mynewuser-context
- description du cluster (indiquez l'adresse et l'emplacement du fichier de certificat CA de l'installation spécifique du cluster) :
AprĂšs les manipulations ci-dessus, le fichier .kubeâconfig aura la configuration suivante :
apiVersion: v1
clusters:
- cluster:
certificate-authority: /etc/kubernetes/pki/ca.crt
server: https://192.168.100.200:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
namespace: target-namespace
user: mynewuser
name: mynewuser-context
current-context: mynewuser-context
kind: Config
preferences: {}
users:
- name: mynewuser
user:
client-certificate: /home/mynewuser/.certs/mynewuser.crt
client-key: /home/mynewuser/.certs/mynewuser.keyPour faciliter le transfert de la configuration entre les comptes et les serveurs, il est utile de modifier les valeurs des clés suivantes :
-
certificate-authority -
client-certificate -
client-key
Pour cela, vous pouvez encoder les fichiers mentionnés en utilisant base64 et les inscrire dans la configuration, en ajoutant le suffixe -data, c'est-à -dire obtenir certificate-authority-data etc.
Certificats avec kubeadm
Avec la version Travailler avec les certificats est devenu beaucoup plus facile grùce à la version alpha de son support dans . Par exemple, voici à quoi pourrait ressembler la génération du fichier de configuration avec les clés utilisateur :
kubeadm alpha kubeconfig user --client-name=mynewuser --apiserver-advertise-address 192.168.100.200 NB: Requis adresse publicitaire peut ĂȘtre consultĂ©e dans le fichier de configuration de l'api-server, qui est par dĂ©faut situĂ© dans /etc/kubernetes/manifests/kube-apiserver.yaml.
Le fichier de configuration rĂ©sultant sera affichĂ© dans stdout. Il doit ĂȘtre sauvegardĂ© dans ~/.kube/config le compte utilisateur ou dans un fichier spĂ©cifiĂ© par la variable d'environnement KUBECONFIG.
Approfondir
Pour ceux qui souhaitent approfondir les questions décrites :
- sur le travail avec les certificats dans la documentation officielle de Kubernetes ;
- , dans lequel la question des certificats est abordée d'un point de vue pratique.
- sur l'authentification dans Kubernetes.
Autorisation
Un compte autorisé par défaut n'a pas de droits d'action dans le cluster. Pour accorder des permissions, Kubernetes a mis en place un mécanisme d'autorisation.
Jusqu'Ă la version 1.6, un type d'autorisation appelĂ© ABAC (contrĂŽle d'accĂšs basĂ© sur les attributs) Ă©tait utilisĂ© dans Kubernetes. Les dĂ©tails peuvent ĂȘtre trouvĂ©s dans . Actuellement, cette approche est considĂ©rĂ©e comme obsolĂšte, cependant vous pouvez encore l'utiliser en parallĂšle avec d'autres types d'autorisation.
Le mode actuel (et plus flexible) de sĂ©paration des droits d'accĂšs au cluster s'appelle RBAC (). Il a Ă©tĂ© dĂ©clarĂ© stable depuis la version . RBAC met en Ćuvre un modĂšle de droits oĂč tout est interdit tant que cela n'est pas explicitement autorisĂ©.
Pour activer RBAC, vous devez démarrer le serveur api Kubernetes avec le paramÚtre --authorization-mode=RBAC. Les paramÚtres sont définis dans le manifeste de configuration de l'api-server, qui se trouve par défaut au chemin /etc/kubernetes/manifests/kube-apiserver.yaml, dans la section commande. Cependant, par défaut, RBAC est déjà activé, donc il ne devrait probablement pas y avoir lieu de s'inquiéter : vous pouvez vérifier cela par la valeur authorization-mode (dans le fichier déjà mentionné kube-apiserver.yaml). D'ailleurs, parmi ses valeurs, d'autres types d'autorisation peuvent également apparaßtre (node, webhook, always allow), mais nous laisserons leur examen en dehors de ce document.
D'ailleurs, nous avons déjà publié un récit assez détaillé sur les principes et les particularités du travail avec RBAC ; ainsi, je me limiterai à une brÚve énumération des bases et des exemples.
Pour gérer l'accÚs dans Kubernetes via RBAC, les entités API suivantes sont utilisées :
-
RĂŽleetClusterRoleâ rĂŽles qui servent Ă dĂ©crire les droits d'accĂšs : -
RÎlepermet de décrire les droits dans un espace de noms; -
ClusterRoleâ dans le cadre d'un cluster, y compris pour les objets spĂ©cifiques au cluster tels que les nĆuds, les urls non-ressources (c'est-Ă -dire non liĂ©s aux ressources Kubernetes â par exemple,/version,/logs,/api*); -
RoleBindingetClusterRoleBindingâ sert Ă lierRĂŽleetClusterRoleĂ un utilisateur, un groupe d'utilisateurs ou un ServiceAccount.
Les entitĂ©s Role et RoleBinding sont limitĂ©es Ă l'espace de noms, c'est-Ă -dire qu'elles doivent se trouver dans un mĂȘme espace de noms. Cependant, RoleBinding peut faire rĂ©fĂ©rence Ă ClusterRole, ce qui permet de crĂ©er un ensemble de permissions standard et de gĂ©rer l'accĂšs Ă l'aide de celles-ci.
Les rÎles décrivent les droits à l'aide d'ensembles de rÚgles, contenant :
- groupes API â voir pour apiGroups et sortie
kubectl api-resources; - ressources (resources:
pod,namespace,déploiementet autres); - verbes (verbs:
set,updateetc.). - noms de ressources (
resourceNames) â pour le cas oĂč il est nĂ©cessaire d'accorder l'accĂšs Ă une ressource spĂ©cifique, et non Ă toutes les ressources de ce type.
Une analyse plus dĂ©taillĂ©e de l'autorisation dans Kubernetes peut ĂȘtre trouvĂ©e sur la page . Au lieu de cela (ou plutĂŽt â en complĂ©ment de cela), je vais donner des exemples qui illustrent son fonctionnement.
Exemples d'entités RBAC
Simplicité RÎle, permettant d'obtenir la liste et le statut des pods et de les surveiller dans l'espace de noms target-namespace:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: target-namespace
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"] Exemple ClusterRole, ce qui permet d'obtenir la liste et le statut des pods et de les surveiller dans tout le cluster :
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
# la section "namespace" n'est pas présente, car ClusterRole couvre tout le cluster
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"] Exemple RoleBinding, ce qui permet à l'utilisateur mynewuser de « lire » les pods dans l'espace de noms my-namespace:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: target-namespace
subjects:
- kind: User
name: mynewuser # le nom d'utilisateur est sensible Ă la casse !
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role # cela doit ĂȘtre âRoleâ ou âClusterRoleâ
name: pod-reader # nom de Role, qui se trouve dans le mĂȘme namespace,
# ou le nom de ClusterRole, dont l'utilisation
# est autorisée à l'utilisateur
apiGroup: rbac.authorization.k8s.ioAudit des événements
De maniĂšre schĂ©matique, l'architecture de Kubernetes peut ĂȘtre prĂ©sentĂ©e comme suit :

Le composant clé de Kubernetes, responsable du traitement des demandes, est api-server. Toutes les opérations sur le cluster passent par lui. Pour en savoir plus sur ces mécanismes internes, vous pouvez lire l'article «».
L'audit systĂšme est une fonctionnalitĂ© intĂ©ressante dans Kubernetes qui est dĂ©sactivĂ©e par dĂ©faut. Elle permet de journaliser toutes les demandes adressĂ©es Ă l'API Kubernetes. Comme on peut s'en douter, c'est par cette API que toutes les actions liĂ©es au contrĂŽle et Ă la modification de l'Ă©tat du cluster sont effectuĂ©es. Une bonne description de ses capacitĂ©s peut ĂȘtre trouvĂ©e dans K8s. Je vais essayer d'expliquer le sujet de maniĂšre plus simple. K8s. Je vais maintenant essayer d'expliquer le sujet de maniĂšre plus simple.
Alors, Pour activer l'audit, nous devons fournir au conteneur dans le api-server trois paramÚtres obligatoires, dont je parlerai plus en détail ci-dessous :
-
--audit-policy-file=/etc/kubernetes/policies/audit-policy.yaml -
--audit-log-path=/var/log/kube-audit/audit.log -
--audit-log-format=json
En plus de ces trois paramÚtres nécessaires, il existe de nombreux paramÚtres supplémentaires concernant l'audit : de la rotation des journaux aux descriptions des webhooks. Exemple de paramÚtres de rotation des journaux :
-
--audit-log-maxbackup=10 -
--audit-log-maxsize=100 -
--audit-log-maxage=7
Mais nous ne nous attarderons pas plus en dĂ©tail lĂ -dessus â toutes les informations peuvent ĂȘtre trouvĂ©es dans .
Comme mentionné précédemment, tous les paramÚtres sont définis dans le manifeste de configuration du api-server (par défaut /etc/kubernetes/manifests/kube-apiserver.yaml), dans la section commande. Revenons aux 3 paramÚtres obligatoires et examinons-les :
-
audit-policy-fileâ le chemin vers le fichier YAML contenant la description de la politique d'audit. Nous y reviendrons, mais je souligne que le fichier doit ĂȘtre lisible par le processus du api-server. Il est donc nĂ©cessaire de le monter Ă l'intĂ©rieur du conteneur, ce qui peut ĂȘtre fait en ajoutant le code suivant dans les sections appropriĂ©es de la configuration :volumeMounts: - mountPath: /etc/kubernetes/policies name: policies readOnly: true volumes: - hostPath: path: /etc/kubernetes/policies type: DirectoryOrCreate name: policies -
audit-log-pathâ le chemin vers le fichier de journal. Ce chemin doit Ă©galement ĂȘtre accessible au processus du api-server, donc nous dĂ©crivons de la mĂȘme maniĂšre son montage :volumeMounts: - mountPath: /var/log/kube-audit name: logs readOnly: false volumes: - hostPath: path: /var/log/kube-audit type: DirectoryOrCreate name: logs -
audit-log-formatâ le format du journal d'audit. Par dĂ©faut, c'estjson, mais un format texte obsolĂšte est Ă©galement disponible (legacy).
Politique d'audit
Maintenant, concernant le fichier mentionnĂ© dĂ©crivant la politique de journalisation. La premiĂšre notion de politique d'audit, c'est le niveau, niveau de journalisation. Il peut ĂȘtre l'un des suivants :
-
TSSAAâ ne pas journaliser ; -
Metadataâ journaliser les mĂ©tadonnĂ©es de la demande : utilisateur, heure de la demande, ressource cible (pod, namespace, etc.), type d'action (verb), etc. ; -
Requestâ journaliser les mĂ©tadonnĂ©es et le corps de la demande ; -
RequestResponseâ journaliser les mĂ©tadonnĂ©es, le corps de la demande et le corps de la rĂ©ponse.
Les deux derniers niveaux (Request et RequestResponse) ne consignent pas les requĂȘtes qui n'ont pas accĂ©dĂ© aux ressources (les accĂšs aux URL dites non-ressources).
De plus, toutes les requĂȘtes passent par plusieurs Ă©tapes:
-
RequestReceivedâ Ă©tape oĂč la requĂȘte a Ă©tĂ© reçue par le gestionnaire et n'a pas encore Ă©tĂ© transmise Ă la chaĂźne de gestionnaires ; -
ResponseStartedâ les en-tĂȘtes de rĂ©ponse ont Ă©tĂ© envoyĂ©s, mais le corps de la rĂ©ponse n'a pas encore Ă©tĂ© envoyĂ©. Cela est gĂ©nĂ©rĂ© pour les requĂȘtes prolongĂ©es (par exemple,regarder); -
ResponseCompleteâ le corps de la rĂ©ponse a Ă©tĂ© envoyĂ©, aucune information supplĂ©mentaire ne sera envoyĂ©e ; -
Panicâ des Ă©vĂ©nements sont gĂ©nĂ©rĂ©s lorsqu'une situation anormale est dĂ©tectĂ©e.
Pour ignorer certaines étapes, vous pouvez utiliser omitStages.
Dans le fichier de politique, nous pouvons décrire plusieurs sections avec différents niveaux de journalisation. La premiÚre rÚgle appropriée trouvée dans la description de la politique sera appliquée.
Le dĂ©mon kubelet surveille les modifications du manifeste avec la configuration du serveur api et redĂ©marre le conteneur avec le serveur api lorsqu'il dĂ©tecte de telles modifications. Mais il y a un dĂ©tail important : les modifications dans le fichier de politique seront ignorĂ©es par lui. AprĂšs avoir effectuĂ© des modifications dans le fichier de politique, il faudra redĂ©marrer le serveur api manuellement. Ătant donnĂ© que le serveur api est lancĂ© comme , l'Ă©quipe kubectl delete ne saura pas le redĂ©marrer. Il faudra manuellement exĂ©cuter docker stop sur les kube-masters oĂč la politique d'audit a Ă©tĂ© modifiĂ©e :
docker stop $(docker ps | grep k8s_kube-apiserver | awk '{print $1}')Lors de l'activation de l'audit, il est important de se rappeler que la charge sur le kube-apiserver augmente. En particulier, la consommation de mĂ©moire pour stocker le contexte des requĂȘtes augmente. L'enregistrement dans le journal commence seulement aprĂšs l'envoi de l'en-tĂȘte de rĂ©ponse. La charge dĂ©pend Ă©galement de la configuration de la politique d'audit.
Exemples de politiques
Analysons la structure des fichiers de politique Ă travers des exemples.
Voici un fichier simple policy, pour enregistrer tout au niveau Metadata:
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata Dans la politique, vous pouvez spécifier une liste d'utilisateurs (Utilisateurs et ), qui sont liés à un namespace et à un ensemble de données d'autorisation stockées dans le cluster sous forme d'objets de type Secrets. Ces utilisateurs (Service Accounts) sont principalement destinés à gérer les droits d'accÚs à l'API Kubernetes pour les processus s'exécutant dans le cluster Kubernetes.) et de groupes d'utilisateurs. Par exemple, voici comment nous ignorerons les utilisateurs systÚme tout en enregistrant le reste au niveau Request:
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: None
userGroups:
- "system:serviceaccounts"
- "system:nodes"
users:
- "system:anonymous"
- "system:apiserver"
- "system:kube-controller-manager"
- "system:kube-scheduler"
- level: RequestIl est également possible de décrire des cibles :
- noms d'espaces (
namespaces); - verbes (verbs:
obtenir,update,supprimeret autres) ; - ressources (resources, Ă savoir :
pod,configmapset autres.) et groupes de ressources (apiGroups).
Attention! Les ressources et groupes de ressources (groupes API, c'est-Ă -dire apiGroups), ainsi que leurs versions installĂ©es dans le cluster, peuvent ĂȘtre obtenus Ă l'aide des commandes :
kubectl api-resources
kubectl api-versionsLa politique d'audit suivante est fournie à titre de démonstration des meilleures pratiques dans :
apiVersion: audit.k8s.io/v1beta1
kind: Policy
# Ne pas enregistrer l'étape RequestReceived
omitStages:
- "RequestReceived"
rules:
# Ne pas enregistrer les événements considérés comme mineurs et non dangereux :
- level: None
users: ["system:kube-proxy"]
verbs: ["watch"]
resources:
- group: "" # c'est le groupe api avec un nom vide, relatif aux
# ressources de base Kubernetes, appelĂ©es âcoreâ
resources: ["endpoints", "services"]
- level: None
users: ["system:unsecured"]
namespaces: ["kube-system"]
verbs: ["get"]
resources:
- group: "" # core
resources: ["configmaps"]
- level: None
users: ["kubelet"]
verbs: ["get"]
resources:
- group: "" # core
resources: ["nodes"]
- level: None
userGroups: ["system:nodes"]
verbs: ["get"]
resources:
- group: "" # core
resources: ["nodes"]
- level: None
users:
- system:kube-controller-manager
- system:kube-scheduler
- system:serviceaccount:kube-system:endpoint-controller
verbs: ["get", "update"]
namespaces: ["kube-system"]
resources:
- group: "" # core
resources: ["endpoints"]
- level: None
users: ["system:apiserver"]
verbs: ["get"]
resources:
- group: "" # core
resources: ["namespaces"]
# Ne pas enregistrer les accĂšs aux URL en lecture seule :
- level: None
nonResourceURLs:
- /healthz*
- /version
- /swagger*
# Ne pas enregistrer les messages relatifs au type de ressources âĂ©vĂ©nementsâ :
- level: None
resources:
- group: "" # core
resources: ["events"]
# Les ressources de type Secret, ConfigMap et TokenReview peuvent contenir des données sensibles,
# donc nous enregistrons uniquement les mĂ©tadonnĂ©es des requĂȘtes qui leur sont liĂ©es
- level: Metadata
resources:
- group: "" # core
resources: ["secrets", "configmaps"]
- group: authentication.k8s.io
resources: ["tokenreviews"]
# Les actions de type get, list et watch peuvent ĂȘtre gourmandes en ressources ; ne pas les enregistrer
- level: Request
verbs: ["get", "list", "watch"]
resources:
- group: "" # core
- group: "admissionregistration.k8s.io"
- group: "apps"
- group: "authentication.k8s.io"
- group: "authorization.k8s.io"
- group: "autoscaling"
- group: "batch"
- group: "certificates.k8s.io"
- group: "extensions"
- group: "networking.k8s.io"
- group: "policy"
- group: "rbac.authorization.k8s.io"
- group: "settings.k8s.io"
- group: "storage.k8s.io"
# Niveau de journalisation par défaut pour les ressources API standards
- level: RequestResponse
resources:
- group: "" # core
- group: "admissionregistration.k8s.io"
- group: "apps"
- group: "authentication.k8s.io"
- group: "authorization.k8s.io"
- group: "autoscaling"
- group: "batch"
- group: "certificates.k8s.io"
- group: "extensions"
- group: "networking.k8s.io"
- group: "policy"
- group: "rbac.authorization.k8s.io"
- group: "settings.k8s.io"
- group: "storage.k8s.io"
# Niveau de journalisation par dĂ©faut pour toutes les autres requĂȘtes
- level: MetadataUn autre bon exemple de politique d'audit â .
Pour une réponse rapide aux événements d'audit, il est possible de décrire un webhook. Cette question est abordée dans , je laisserai cela de cÎté dans cet article.
Résultats
Cet article offre un aperçu des mĂ©canismes de sĂ©curitĂ© de base dans les clusters Kubernetes, permettant de crĂ©er des comptes utilisateurs personnalisĂ©s, de sĂ©parer leurs droits et d'enregistrer leurs actions. J'espĂšre qu'il sera utile Ă ceux qui ont rencontrĂ© de telles questions, que ce soit en thĂ©orie ou en pratique. Je vous recommande Ă©galement de consulter la liste des autres ressources sur la sĂ©curitĂ© dans Kubernetes, mentionnĂ©e dans le 'P.S.', car vous y trouverez peut-ĂȘtre des dĂ©tails nĂ©cessaires sur les problĂšmes qui vous prĂ©occupent.
P.S.
Lisez aussi dans notre blog :
- «»;
- «»;
- «»;
- «»;
- «».
Source : habr.com
