Untuk memperkuat security di cluster Kubernetes yang anda kelola, ada baiknya untuk membatasi Docker Registry atau kadang disebut juga sebagai Docker Repository. Untuk menerapkan pembatasan ini di Kubernetes, gunakan OPA Gatekeeper. Gatekeeper ini sangat mudah di customize, karena kita bisa membuat template sendiri dengan menggunakan rego
. Rego sendiri adalah bahasa yang digunakan di OPA untuk menuliskan policy, atau aturan yang dibuat.
Untuk mendeploy OPA Gatekeeper, kita membutuhkan akses admin. Pastikan anda menggunakan user yang memiliki privileges tersebut.
Deploy Gatekeeper
Untuk men-deploy gatekeeper gunakan kubectl
.
wget https://raw.githubusercontent.com/open-policy-agent/gatekeeper/v3.17.1/deploy/gatekeeper.yaml kubectl apply -f gatekeeper.yaml
Buat Constraint Templates
Sebelum membuat rule, kita harus membuat template yang berisi aturan yang kita inginkan, contoh disini kita akan membuat filter Docker Registry yang diijinkan untuk digunakan di cluster Kubernetes yang kita miliki.
Buat whitelisted_repo_constraint_template.yaml
// constraint_template.yaml apiVersion: templates.gatekeeper.sh/v1 kind: ConstraintTemplate metadata: name: k8sallowedrepos annotations: metadata.gatekeeper.sh/title: "Allowed Repositories" metadata.gatekeeper.sh/version: 1.0.1 description: >- Requires container images to begin with a string from the specified list. spec: crd: spec: names: kind: K8sAllowedRepos validation: # Schema for the `parameters` field openAPIV3Schema: type: object properties: repos: description: The list of prefixes a container image is allowed to have. type: array items: type: string targets: - target: admission.k8s.gatekeeper.sh rego: | package k8sallowedrepos violation[{"msg": msg}] { container := input.review.object.spec.containers[_] not strings.any_prefix_match(container.image, input.parameters.repos) msg := sprintf("container <%v> has an invalid image repo <%v>, allowed repos are %v", [container.name, container.image, input.parameters.repos]) } violation[{"msg": msg}] { container := input.review.object.spec.initContainers[_] not strings.any_prefix_match(container.image, input.parameters.repos) msg := sprintf("initContainer <%v> has an invalid image repo <%v>, allowed repos are %v", [container.name, container.image, input.parameters.repos]) } violation[{"msg": msg}] { container := input.review.object.spec.ephemeralContainers[_] not strings.any_prefix_match(container.image, input.parameters.repos) msg := sprintf("ephemeralContainer <%v> has an invalid image repo <%v>, allowed repos are %v", [container.name, container.image, input.parameters.repos]) }
pada contoh diatas ada 3 jenis container yang akan mengaplikasikan rule/aturan ini, yaitu containers, init container dan ephemeral container. Untuk merubah pesan yang ditampilkan, ubah bagian msg
Daftar Whitelist Docker Registry
buat file constrain dengan nama whitelist-docker-registry.yaml
yang berisi
apiVersion: constraints.gatekeeper.sh/v1beta1 kind: K8sAllowedRepos metadata: name: whitelist-docker-registry spec: match: kinds: - apiGroups: [""] kinds: ["Pod"] parameters: repos: - "ghcr.io"
pada contoh disini kita hanya akan mengijinkan docker image yang menggunakan ghcr.io, atau pada perusahaan biasanya menggunakan private docker registry, contoh jfrog.jaranguda.com
Deploy Ke Kubernetes
Deploy Constraint dan Constraint Templates ke cluster
kubectl apply -f whitelisted_repo_constraint_template.yaml kubectl apply -f whitelist-docker-registry.yaml
Contoh Deployment
Untuk mencoba policy ini, mari kuta buat satu deployment yang menggunakan docker.io sebagai registry. Buat file dengan nama deploy-nginx.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 1 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.26.2 ports: - containerPort: 80
deploy object tersebut
kubectl apply -f deploy-nginx.yaml --namespace app # output deployment.apps/nginx-deployment created
setelah di deploy, coba cek pod nginx tersebut
$ kubectl get pods --namespace app No resources found in app namespace.
kita tidak akan menemukan pod tersebut, untuk mendapatkan error yang lebih detail cek event Kubernetes
$ kubectl get events --namespace app -w LAST SEEN TYPE REASON OBJECT MESSAGE 77s Warning FailedCreate replicaset/nginx-deployment-7f8746677b Error creating: admission webhook "validation.gatekeeper.sh" denied the request: [whitelist-docker-registry] container <nginx> has an invalid image repo <nginx:1.26.2>, allowed repos are ["ghcr.io"] 2m39s Normal ScalingReplicaSet deployment/nginx-deployment Scaled up replica set nginx-deployment-7f8746677b to 1
ganti nginx:1.26.2
dengan ghcr.io/linuxserver/nginx:1.26.2
diff --git a/deploy-nginx.yaml b/deploy-nginx.yaml index ba24fa5..45724be 100644 --- a/deploy-nginx.yaml +++ b/deploy-nginx.yaml @@ -16,6 +16,6 @@ spec: spec: containers: - name: nginx - image: nginx:1.27.2 + image: ghcr.io/linuxserver/nginx:1.26.2 ports: - containerPort: 80
lalu deploy
$ kubectl apply -f deploy-nginx.yaml --namespace app # outpout deployment.apps/nginx-deployment configured
sekarang cek kembali event, anda tidak akan menemukan pesan error. Lalu jalankan get pods
$ kubectl get pods --namespace app NAME READY STATUS RESTARTS AGE nginx-deployment-d8b77dbbd-d2pb6 1/1 Running 0 28s