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

Leave a comment

Your email address will not be published. Required fields are marked *