others-prepare for cks exam with me 11: Open policy agent in Kubernetes

1. Purpose

In this post, I would continue to write about preparing for the CKS (Certified Kubernetes Security Specialist) exam. I would write my own notes about the exam, and you can refer to these articles to prepare your own.

List of the series of posts:

-prepare for cks exam with me 1: Linux user and group management

-prepare for cks exam with me 2: Linux ssh hardening

-prepare for cks exam with me 3: Linux remove obsolete packages and services

-prepare for cks exam with me 4: Linux kernal hardening

-prepare for cks exam with me 5: Linux UFW(Uncomplicated firewall)

-prepare for cks exam with me 6: Seccomp in Linux, Docker and Kubernetes

-prepare for cks exam with me 7: Apparmor in Linux, Docker and Kubernetes

-prepare for cks exam with me 8: Security context in Kubernetes

-prepare for cks exam with me 9: Admission controllers in Kubernetes

-prepare for cks exam with me 10: Pod security policy in Kubernetes

-prepare for cks exam with me 11: Open policy agent in Kubernetes

-prepare for cks exam with me 12: Secrets in Kubernetes

-prepare for cks exam with me 13: Container runtimes(gvisor/kata containers) in Kubernetes

-prepare for cks exam with me 14: Container Image security in Docker and Kubernetes

-prepare for cks exam with me 15: How to print docker images of all pods in kubernetes

2. Environment

  • CKS
  • Ubuntu System

3. Open policy agent in Kubernetes

3.1 What is open policy agent(OPA)?

OPA can be used for fine-grained authorization, for example, the container’s image must come from a certain mirror repository.

3.2 Some examples of OPA policy

A policy that checks request path and user.

package httpapi.authz

import input

default allow = false 
allow {
  input.path == "home"
  input.user == "Kedar"
 }

A policy that checks kubernetes pod, assure that the pod’s image must come from a specific repository:

package kubernetes.admission

deny[msg] {
  input.request.kind.kind == "Pod"
  image := input.request.object.spec.containers[_].image
  not startswith(image, "hooli.com/")
  msg := sprintf("image '%v' comes from untrusted registry", [image])
}

A policy that checks ingress, which should not conflict with other namespaces’ ingress.

package kubernetes.admission
import data.kubernetes.ingresses


deny[msg] {
    some other_ns, other_ingress
    input.request.kind.kind == "Ingress"
    input.request.operation == "CREATE"
    host := input.request.object.spec.rules[_].host
    ingress := ingresses[other_ns][other_ingress]
    other_ns != input.request.namespace
    ingress.spec.rules[_].host == host
    msg := sprintf("invalid ingress host %q (conflicts with %v/%v)", [host, other_ns, other_ingress])
}

3.3 Configure kubernetes to use OPA to validate api server’s requests

Let api-server send all create/update requests to OPA for authentication, create ValidatingWebhookConfiguration:

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
  name: opa-validating-webhook
webhooks:
- name: validating-webhook.openpolicyagent.org
  rules:
  - operations: ["CREATE", "UPDATE"]
    apiGroups: [‘*’]
    apiVersions: [“*"]
    resources: [“*”]
  clientConfig:
    url: "http://opa-address:8181"

3.4 Create configmap to use OPA in kubernetes

K8s-based kube-mgmt component (a sidecar deployed with the Opa k8s server, responsible for synchronizing K8s resources, loading opa strategies, etc.), it can be implemented using configmap to deploy Opa strategies.

Suppose there exists an OPA policy file named untrusted-registry.rego, then we can create the configmap as follows:

kubectl create configmap untrusted-registry --from-file=untrusted-registry.rego

Then we get this configmap:

apiVersion: v1

kind: ConfigMap
metadata:
  annotations:
    openpolicyagent.org/policy-status: '{"status":"ok"}'
  name: untrusted-registry
  namespace: opa
data:
  untrusted-registry.rego: |2
    package kubernetes.admission

    deny[msg] {
      input.request.kind.kind == "Pod"
      image := input.request.object.spec.containers[_].image
      not startswith(image, "hooli.com/")
      msg := sprintf("image '%v' comes from untrusted registry", [image])
    }

4. Summary

In this post, I write some examples about open policy agent in kubernetes.