Je tenais à prendre quelques minutes afin de vous remercier d’avoir été plus de 500 000 visiteurs à lire mon blog ces derniers mois. Nous avons vécu dans un contexte compliqué mais qui nous a permis également de nous ré-inventer technologiquement.
La ligne éditoriale de ce blog continuera d’évoluer sur les thématique liées à la sécurité Cloud (Azure Security Center, Azure Sentinel), la gouvernance (Azure Policy, OPA Gatekeeper, …) ainsi que sur les sujets liés à la sécurité des clusters Kubernetes.
Je vous souhaite à toutes et à tous mes meilleurs voeux pour cette année 2021!
Dans cet article, je vais vous présenter un autre « policy engine » pour Kubernetes. Dans un précédent article, j’avais pu vous présenter la solution OPA Gatekeeper. Dans cet article, nous porterons une attention particulière au projet Kyverno. Ce projet est supporté par la CNCF Foundation dans la catégorie « Sandbox ».
Les principaux avantages d’utiliser la solution Kyverno versus OPA Gatekeeper sont:
Ne pas ré-apprendre un nouveau langage, les policies Kyverno sont des resources Kubernetes. Comme pour OPA Gatekeeper, ces policies peuvent être déployées en mode « audit » ou « enforce ».
En plus de la validation, Kyverno supporte également la mutation et la génération de resources.
Dans cet exemple, je vous présente comment déployer la solution Kyverno ainsi que comment créer et déployer une policy qui a comme objectif de forcer l’application d’un label lors de la création d’un resource group. J’avais pu vous présenter un exemple similaire au sein de l’article: AKS | OPA
Déployer Kyverno:
max@Azure:~$ kubectl create -f https://raw.githubusercontent.com/kyverno/kyverno/main/definitions/release/install.yaml
namespace/kyverno created
customresourcedefinition.apiextensions.k8s.io/clusterpolicies.kyverno.io created
customresourcedefinition.apiextensions.k8s.io/clusterpolicyreports.wgpolicyk8s.io created
customresourcedefinition.apiextensions.k8s.io/clusterreportchangerequests.kyverno.io created
customresourcedefinition.apiextensions.k8s.io/generaterequests.kyverno.io created
customresourcedefinition.apiextensions.k8s.io/policies.kyverno.io created
customresourcedefinition.apiextensions.k8s.io/policyreports.wgpolicyk8s.io created
customresourcedefinition.apiextensions.k8s.io/reportchangerequests.kyverno.io created
serviceaccount/kyverno-service-account created
clusterrole.rbac.authorization.k8s.io/kyverno:admin-policies created
clusterrole.rbac.authorization.k8s.io/kyverno:admin-policyreport created
clusterrole.rbac.authorization.k8s.io/kyverno:admin-reportchangerequest created
clusterrole.rbac.authorization.k8s.io/kyverno:customresources created
clusterrole.rbac.authorization.k8s.io/kyverno:generatecontroller created
clusterrole.rbac.authorization.k8s.io/kyverno:policycontroller created
clusterrole.rbac.authorization.k8s.io/kyverno:userinfo created
clusterrole.rbac.authorization.k8s.io/kyverno:webhook created
clusterrolebinding.rbac.authorization.k8s.io/kyverno:customresources created
clusterrolebinding.rbac.authorization.k8s.io/kyverno:generatecontroller created
clusterrolebinding.rbac.authorization.k8s.io/kyverno:policycontroller created
clusterrolebinding.rbac.authorization.k8s.io/kyverno:userinfo created
clusterrolebinding.rbac.authorization.k8s.io/kyverno:webhook created
configmap/init-config created
service/kyverno-svc created
deployment.apps/kyverno created
max@Azure:~/clouddrive$ kubectl apply -f ns-label.yaml
clusterpolicy.kyverno.io/require-ns-labels created
Test:
max@Azure:~/clouddrive$ kubectl create namespace maxime
Error from server: admission webhook "validate.kyverno.svc" denied the request:
resource Namespace//maxime was blocked due to the following policies
require-ns-labels:
require-ns-labels: 'validation error: The label my-app is required. Rule require-ns-labels failed at path /metadata/labels/'
max@Azure:~/clouddrive$ kubectl apply -f namespace.yaml
namespace/maxime created
max@Azure:~/clouddrive$ kubectl get ns --show-labels
NAME STATUS AGE LABELS
default Active 31m
kube-node-lease Active 31m
kube-public Active 31m
kube-system Active 31m addonmanager.kubernetes.io/mode=Reconcile,control-plane=true,kubernetes.io/cluster-service=true
kyverno Active 20m
maxime Active 2m36s my-app=maxapp
En conclusion, nous pouvons constater que Kyverno est une solution très intéressante et simple d’utilisation. A noter qu’une fonctionnalité de reporting est en cours de développement. Je reviendrai vous présenter cette fonctionnalité dans un prochain article.
Dans cet exemple, nous allons créer une policy qui va nécessiter d’avoir le label gatekeeper lors de la création d’un nouveau namespace. Pour cela nous allons créer un template puis une contrainte. Nous verrons dans un second temps comment créer une contrainte en « audit » mode.
max@Azure:~/clouddrive$ kubectl create namespace maxime
Error from server ([denied by ns-must-have-gk] you must provide labels: {"gatekeeper"}): admission webhook "validation.gatekeeper.sh" denied the request: [denied by ns-must-have-gk] you must provide labels: {"gatekeeper"}
Lister les contraintes:
max_coquerel@Azure:~/clouddrive$ kubectl get constraint NAME AGE ns-must-have-gk 80s
Créer une contrainte en mode audit:
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
name: ns-must-have-gk
spec:
enforcementAction: dryrun
match:
kinds:
- apiGroups: [""]
kinds: ["Namespace"]
parameters:
labels: ["gatekeeper"]
max@Azure:~/clouddrive$ kubectl describe constraint ns-must-have-gk
Name: ns-must-have-gk
Namespace:
Labels:
Annotations:
API Version: constraints.gatekeeper.sh/v1beta1
Kind: K8sRequiredLabels
Status:
Audit Timestamp: 2020-12-30T16:09:13Z
By Pod:
Constraint UID: b245e684-174d-4b28-8be0-064722f2b4a3
Enforced: true
Id: gatekeeper-audit-576f6d6f8d-kx8p6
Observed Generation: 1
Operations:
audit
status
Constraint UID: b245e684-174d-4b28-8be0-064722f2b4a3
Enforced: true
Id: gatekeeper-controller-manager-85d8bf48c9-jqhq4
Observed Generation: 1
Operations:
webhook
Constraint UID: b245e684-174d-4b28-8be0-064722f2b4a3
Enforced: true
Id: gatekeeper-controller-manager-85d8bf48c9-mrj2w
Observed Generation: 1
Operations:
webhook
Constraint UID: b245e684-174d-4b28-8be0-064722f2b4a3
Enforced: true
Id: gatekeeper-controller-manager-85d8bf48c9-s2d86
Observed Generation: 1
Operations:
webhook
Total Violations: 6
Violations:
Enforcement Action: dryrun
Kind: Namespace
Message: you must provide labels: {"gatekeeper"}
Name: default
Enforcement Action: dryrun
Kind: Namespace
Message: you must provide labels: {"gatekeeper"}
Name: gatekeeper-system
Enforcement Action: dryrun
Kind: Namespace
Message: you must provide labels: {"gatekeeper"}
Name: kube-node-lease
Enforcement Action: dryrun
Kind: Namespace
Message: you must provide labels: {"gatekeeper"}
Name: kube-public
Enforcement Action: dryrun
Kind: Namespace
Message: you must provide labels: {"gatekeeper"}
Name: kube-system
Enforcement Action: dryrun
Kind: Namespace
Message: you must provide labels: {"gatekeeper"}
Name: maxime
Events:
In this article, we will create a new policy. The goal of this policy will to enforce a label at the namespace level. In the first we will create a template and a constraint. In the second part of this article we will see how we can create a constraint in audit mode.
max@Azure:~/clouddrive$ kubectl create namespace maxime Error from server ([denied by ns-must-have-gk] you must provide labels: {"gatekeeper"}): admission webhook "validation.gatekeeper.sh" denied the request: [denied by ns-must-have-gk] you must provide labels: {"gatekeeper"}
Constraints List:
max_coquerel@Azure:~/clouddrive$ kubectl get constraint NAME AGE ns-must-have-gk 80s