Cette page explique comment utiliser le contrôleur d'admission Gatekeeper pour appliquer des contrôles de sécurité au niveau des pods à vos clusters Google Kubernetes Engine (GKE).
Présentation
Gatekeeper est un contrôleur d'admission qui valide les demandes de création et de mise à jour de pods sur les clusters Kubernetes à l'aide d'OPA (Open Policy Agent).
L'utilisation de Gatekeeper permet aux administrateurs de définir des stratégies avec une contrainte, un ensemble de conditions qui autorisent ou refusent les comportements de déploiement dans Kubernetes. Vous pouvez ensuite appliquer ces stratégies sur un cluster à l'aide d'un ConstraintTemplate
. Ce document fournit des exemples permettant de restreindre les capacités de sécurité des charges de travail pour appliquer, tester et auditer des stratégies de sécurité à l'aide de Gatekeeper.
Gatekeeper peut également :
- Déployer des stratégies : appliquer des stratégies de manière progressive pour limiter le risque de perturbation des charges de travail.
- Simuler des changements de stratégie : fournir des mécanismes permettant de tester l'impact des stratégies et la plage avant leur application.
- Auditer les stratégies existantes : vérifier l'application des contrôles de sécurité aux charges de travail nouvelles et existantes (contrôles d'audit).
Concepts
Gatekeeper propose deux concepts permettant aux administrateurs de disposer d'un moyen efficace et flexible de contrôler leur cluster : les contraintes et les modèles de contraintes, qui sont tous deux des concepts hérités d'OPA Constraint Framework.
Les contraintes représentent votre stratégie de sécurité. Elles définissent les exigences et la plage d'application de la stratégie. Les modèles de contraintes sont des instructions réutilisables (écrites dans Rego) qui permettent d'appliquer une logique afin d'évaluer des champs spécifiques dans des objets Kubernetes, en fonction des exigences définies dans les contraintes.
Par exemple, vous pouvez avoir une contrainte qui déclare des profils seccomp autorisés pouvant être appliqués aux pods dans un espace de noms spécifique, et un modèle de contrainte comparable qui fournit la logique d'extraction de ces valeurs et de traitement de leur application.
Le modèle de contrainte suivant, à partir du dépôt Gatekeeper, vérifie l'existence de securityContext.privileged
dans une spécification de pod :
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: k8spspprivilegedcontainer
spec:
crd:
spec:
names:
kind: K8sPSPPrivilegedContainer
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8spspprivileged
violation[{"msg": msg, "details": {}}] {
c := input_containers[_]
c.securityContext.privileged
msg := sprintf("Privileged container is not allowed: %v, securityContext: %v", [c.name, c.securityContext])
}
input_containers[c] {
c := input.review.object.spec.containers[_]
}
input_containers[c] {
c := input.review.object.spec.initContainers[_]
}
Pour étendre le modèle de contrainte ci-dessus, la contrainte suivante définit le champ d'application (kinds
) pour l'application spécifique de ce modèle de contrainte dans un mode dryrun
:
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPPrivilegedContainer
metadata:
name: psp-privileged-container
spec:
enforcementAction: dryrun
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
Avec Gatekeeper, vous pouvez créer vos propres contraintes et modèles de contraintes pour répondre à vos besoins spécifiques. Vous pouvez également utiliser un ensemble standard de contraintes et de modèles de contraintes dans le dépôt Gatekeeper, qui a été défini pour permettre l'adoption rapide et l'application de mesures de sécurité. Chaque contrainte est également accompagnée d'exemples de configurations de pod.
Google Cloud fournit une version gérée et officiellement compatible de Gatekeeper Open Source, nommé Policy Controller. Google n'accepte pas officiellement le projet Open Source Gatekeeper.
Avant de commencer
Avant de commencer, effectuez les tâches suivantes :
- Activez l'API Google Kubernetes Engine. Activer l'API Google Kubernetes Engine
- Si vous souhaitez utiliser Google Cloud CLI pour cette tâche, installez puis initialisez gcloud CLI. Si vous avez déjà installé gcloud CLI, assurez-vous de disposer de la dernière version en exécutant la commande
gcloud components update
.
Activer le contrôleur d’accès sur un cluster avec Policy Controller
Policy Controller est un moteur de règles basé sur le projet Open Source Gatekeeper. Google recommande l'utilisation de Policy Controller, car il inclut des fonctionnalités supplémentaires pour faciliter l'application des règles à grande échelle, telles que la stratégie en tant que code, la compatibilité multicluster, l'intégration à Cloud Logging et la capacité à afficher l'état des règles dans la console Google Cloud. Policy Controller est disponible avec une licence Google Kubernetes Engine (GKE) Enterprise, mais vous pouvez installer Gatekeeper sur votre cluster à la place.
Pour activer Policy Controller sur un cluster, suivez le guide d'installation de Policy Controller.
Activer des contraintes et des modèles de contraintes
Gatekeeper et ses modèles de contraintes peuvent être installés et activés sans affecter les charges de travail existantes ou nouvelles. Pour cette raison, il est recommandé d'appliquer tous les modèles de contraintes de sécurité des pods applicables au cluster.
En outre, les contraintes Gatekeeper peuvent être mises en œuvre pour appliquer des contrôles à des objets spécifiques, tels que des espaces de noms et des pods.
Examinez l'exemple ci-dessous qui limite le champ d'application aux pods situés dans l'espace de noms production en les définissant dans l'instruction de correspondance de contrainte :
...
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
namespaces:
- "production"
Pour en savoir plus sur les options disponibles pour les objets Constraint
et ConstraintTemplate
, consultez la page Comment utiliser Gatekeeper.
Stratégies de test
L'introduction de nouvelles stratégies dans les clusters existants peut avoir des effets négatifs, par exemple en limitant les charges de travail existantes. L'un des avantages de Gatekeeper pour la sécurité des pods est sa capacité à tester l'efficacité et l'impact d'une stratégie sans apporter de modifications réelles grâce à un mode de simulation. Cela permet de tester la configuration d'une stratégie avec des clusters en cours d'exécution sans l'appliquer. Les cas de non-respect des règles sont enregistrés et identifiés, sans interférence.
Les étapes suivantes expliquent comment un développeur, un opérateur ou un administrateur peut appliquer des modèles de contraintes et des contraintes pour déterminer leur efficacité ou leur impact potentiel :
Appliquez la configuration Gatekeeper afin de répliquer les données pour les fonctionnalités d'audit et de simulation :
kubectl create -f- <<EOF apiVersion: config.gatekeeper.sh/v1alpha1 kind: Config metadata: name: config namespace: "gatekeeper-system" spec: sync: syncOnly: - group: "" version: "v1" kind: "Namespace" - group: "" version: "v1" kind: "Pod" EOF
Sans contrainte appliquée, exécutez une charge de travail avec des privilèges élevés :
kubectl create -f- <<EOF apiVersion: v1 kind: Pod metadata: name: nginx labels: app: nginx spec: containers: - name: nginx image: nginx securityContext: privileged: true EOF
Chargez le modèle de contrainte
k8spspprivilegedcontainer
mentionné ci-dessus :kubectl create -f- <<EOF apiVersion: templates.gatekeeper.sh/v1beta1 kind: ConstraintTemplate metadata: name: k8spspprivilegedcontainer spec: crd: spec: names: kind: K8sPSPPrivilegedContainer targets: - target: admission.k8s.gatekeeper.sh rego: | package k8spspprivileged violation[{"msg": msg, "details": {}}] { c := input_containers[_] c.securityContext.privileged msg := sprintf("Privileged container is not allowed: %v, securityContext: %v", [c.name, c.securityContext]) } input_containers[c] { c := input.review.object.spec.containers[_] } input_containers[c] { c := input.review.object.spec.initContainers[_] } EOF
À présent, créez une contrainte pour étendre ce modèle de contrainte. Pour le moment, nous allons définir
enforcementAction
surdryrun
:kubectl create -f- <<EOF apiVersion: constraints.gatekeeper.sh/v1beta1 kind: K8sPSPPrivilegedContainer metadata: name: psp-privileged-container spec: enforcementAction: dryrun match: kinds: - apiGroups: [""] kinds: ["Pod"] EOF
Grâce à Gatekeeper qui synchronise les données d'objet en cours d'exécution et vérifie les violations de manière passive, nous pouvons vérifier si des violations ont été détectées en examinant la valeur
status
de la contrainte :kubectl get k8spspprivilegedcontainer.constraints.gatekeeper.sh/psp-privileged-container -o yaml
apiVersion: constraints.gatekeeper.sh/v1beta1 kind: K8sPSPPrivilegedContainer metadata: ... name: psp-privileged-container ... spec: enforcementAction: dryrun match: kinds: - apiGroups: - "" kinds: - Pod status: auditTimestamp: "2019-12-15T22:19:54Z" byPod: - enforced: true id: gatekeeper-controller-manager-0 violations: - enforcementAction: dryrun kind: Pod message: 'Privileged container is not allowed: nginx, securityContext: {"privileged": true}' name: nginx namespace: default
Exécutez un autre pod privilégié pour vérifier que la stratégie n'interfère pas avec les déploiements :
kubectl create -f- <<EOF apiVersion: v1 kind: Pod metadata: name: privpod labels: app: privpod spec: containers: - name: nginx image: nginx securityContext: privileged: true EOF
Ce nouveau pod sera déployé avec succès.
Pour nettoyer les ressources créées dans cette section, exécutez les commandes suivantes :
kubectl delete k8spspprivilegedcontainer.constraints.gatekeeper.sh/psp-privileged-container kubectl delete constrainttemplate k8spspprivilegedcontainer kubectl delete pod/nginx kubectl delete pod/privpod
Appliquer des règles
Maintenant qu'il est possible de confirmer la validité et l'impact d'une stratégie sans affecter les charges de travail existantes ou nouvelles, passons à la mise en œuvre d'une stratégie avec son application complète.
En fonction des exemples utilisés pour valider la stratégie ci-dessus, la procédure suivante montre comment un développeur, un opérateur ou un administrateur peut appliquer des modèles de contraintes et des contraintes à une stratégie :
Chargez le modèle de contrainte
k8spspprivilegedcontainer
mentionné précédemment :kubectl create -f- <<EOF apiVersion: templates.gatekeeper.sh/v1beta1 kind: ConstraintTemplate metadata: name: k8spspprivilegedcontainer spec: crd: spec: names: kind: K8sPSPPrivilegedContainer targets: - target: admission.k8s.gatekeeper.sh rego: | package k8spspprivileged violation[{"msg": msg, "details": {}}] { c := input_containers[_] c.securityContext.privileged msg := sprintf("Privileged container is not allowed: %v, securityContext: %v", [c.name, c.securityContext]) } input_containers[c] { c := input.review.object.spec.containers[_] } input_containers[c] { c := input.review.object.spec.initContainers[_] } EOF
À présent, créez une contrainte pour étendre ce modèle de contrainte. Pour le moment, nous n'allons pas définir la clé
enforcementAction
. Par défaut, la cléenforcementAction
est définie surdeny
.kubectl create -f- <<EOF apiVersion: constraints.gatekeeper.sh/v1beta1 kind: K8sPSPPrivilegedContainer metadata: name: psp-privileged-container spec: match: kinds: - apiGroups: [""] kinds: ["Pod"] EOF
Tentative de déploiement d'un conteneur qui déclare des autorisations privilégiées :
kubectl create -f- <<EOF apiVersion: v1 kind: Pod metadata: name: nginx labels: app: nginx spec: containers: - name: nginx image: nginx securityContext: privileged: true EOF
Le message d'erreur suivant doit s'afficher :
Error from server ([denied by psp-privileged-container] Privileged container is not allowed: nginx, securityContext: {"privileged": true}): error when creating "STDIN": admission webhook "validation.gatekeeper.sh" denied the request: [denied by psp-privileged-container] Privileged container is not allowed: nginx, securityContext: {"privileged": true}
Pour effectuer un nettoyage, exécutez les commandes suivantes :
kubectl delete k8spspprivilegedcontainer.constraints.gatekeeper.sh/psp-privileged-container kubectl delete constrainttemplate k8spspprivilegedcontainer
Alternatives à Gatekeeper
Gatekeeper vous permet de déclarer et d'appliquer des règles de sécurité personnalisées au niveau des pods. Vous pouvez également utiliser le contrôleur d'admission PodSecurity
intégré à Kubernetes pour appliquer des stratégies de sécurité prédéfinies au niveau du pod. Ces règles prédéfinies sont conformes aux niveaux définis par les normes de sécurité des pods.
Étape suivante
Gatekeeper fournit un moyen incroyablement efficace pour appliquer et valider la sécurité sur des clusters GKE à l'aide de stratégies déclaratives. Toutefois, l'utilisation de Gatekeeper s'étend au-delà de la sécurité, et peut servir dans d'autres domaines administratifs et opérationnels.