refer: https://medium.com/nerd-for-tech/policies-as-code-in-kubernetes-using-jspolicy-8d358d064bfd
DevSecops in Kubernetes using jsPolicy
Kubernetes clusters are now everywhere. To run an ML Model you need a Kubernetes cluster, you want to run Data analytics you need a Kubernetes cluster, to deploy your frontend application, backend application, or any type of application you’d need a Kubernetes cluster. But is your cluster secured? Did you ever worry about the security of the cluster? Assume you are trying to run some automation scripts and it accidentally deleted all the namespaces in Production. Boom, it is going to be the longest day in the life of a DevOps Engineer. Even thinking about this might be giving chills to the DevOps engineers reading this. Is there a way to avoid this? Is there a way to effectively control such disasters? jsPolicy to the rescue. jsPolicy is a policy engine for Kubernetes that allows you to write policies in JavaScript or TypeScript.
Advantages of jsPolicy
a) Lightning Fast & Secure Policy Execution: jsPolicy runs policies with Google’s super-fast V8 JavaScript engine in a pool of pre-heated sandbox environments. Most policies do not even take a single millisecond to execute.
b) Great Language For Policies: JavaScript is made for handling and manipulating JSON objects (short for “JavaScript Object Notation” (!)) and Kubernetes uses JSON by converting your YAML to JSON during every API request.
What is the entire story all about? (TLDR)
- Securing your K8s cluster using jsPolicy.
- Creating secure policies in JavaScript using jsPolicy.
Prerequisites
- A Kubernetes Cluster ( EKS, AKS, Kind, etc ).
Story Resources
- GitHub Link: https://github.com/pavan-kumar-99/medium-manifests
- GitHub Branch: jsPolicy
jsPolicy Installation and Architecture
Components
Although jsPolicy runs all of its components in a single container (not considering replicas when you scale up the replica number for high availability), jsPolicy logically consists of three main components:
Webhook Manager
The webhook manager is responsible for registering and managing admission webhooks with the Kubernetes API server so that API server requests will apply the mutating and validating webhooks that are defined as JsPolicy
objects.
V8 JavaScript Sandbox Pool
For faster execution of policy code, jsPolicy maintains a pool of pre-heated V8 JavaScript sandboxes that can be used to run JavaScript code containing policy logic.
Policy Compiler
The policy compiler is a controller that monitors JsPolicy
resources and that creates and updates JsPolicyBundle
objects for all JsPolicy
objects that define the spec.javascript
field. The compilation process looks about like this:
- Retrieve all required
npm
packages specified inspec.dependencies
(similar tonpm install
downloading thedependencies
specified in apackage.json
file of a regular JavaScript project) - Run
webpack
to create a highly optimized bundle of JavaScript code that contains the code fromspec.javascript
and all dependencies while only bundling the functions that are needed for the execution of the code. - Compress the bundle using
gzip
. - Encode the bundle using
base64
. - Store the bundle in
spec.bundle
within the respectiveJsPolicyBundle
object.
Install jsPolicy
The jsPolicy runs all of its components in a single container. This can be easily installed using the helm chart.
$ helm install jspolicy jspolicy -n jspolicy --create-namespace --repo https://charts.loft.sh
Time to see jsPolicy in Action
The Policies are of three types
a) Mutating: Mutating policies are executed as part of kubectl
requests right after the API server performs authentication and authorization (RBAC). The objective of mutating policies is to change the payload (Kubernetes object) provided in a request, e.g. automatically add a sidecar container when the pod is created.
b) Validating: Validating policies are executed as part of kubectl
requests after the execution of mutating policies. The objective of validating policies is to inspect the request and then to either deny or allow it. e.g. deny the creation of a pod if the namespace is default or deny the creation of the pod if the image is from a public repository.
c) Controller: Unlike mutating and validating policies, controller policies are not part of the lifecycle of a request to the Kubernetes API server. Controller policies are triggered by the Events
that Kubernetes creates for each change of the cluster state in etcd.e.g. Automatically creating certain resources in every newly created namespace (e.g. LimitRange
, NetworkPolicy
etc.)
Let us see all the 3 of them in Action.
Mutate Policy:
This jsPolicy says that it is of type Mutating( Line 6 ) and it is applicable while creating pods ( Line 7,8 ) and the policy says that if the pods that are being created have the annotation “inject-agent”: “true” ( Line 10 ) then the pod should be mutated by an extra sidecar container ( Line 16 ). Let us now create the policy and the pod to test this.
$ git clone https://github.com/pavan-kumar-99/medium-manifests.git \
-b jsPolicy$ cd medium-manifests$ kubectl apply -f mutate-policy.yaml$ kubectl apply -f pod.yaml
The pod has the required annotations, and the pod should now be created with 2 containers ( And the sidecar being automatically mutated ).
Validation Policy:
Let us delete the pod that we created earlier and then apply the validation Policy.
https://medium.com/media/519a9731f159798770385db4fe075ea6Default Deny
The validation policy says to Deny the creation of any resources in the default namespace.
$ git clone https://github.com/pavan-kumar-99/medium-manifests.git \
-b jsPolicy$ cd medium-manifests## Delete the Pod created earlier$ kubectl delete -f pod.yaml## Apply the validation webhook$ kubectl apply -f default-ns-deny.yaml
Let us now try to create the same pod again.
$ kubectl apply -f pod.yaml
Error from server (Forbidden): error when creating “pod. yaml”: admission webhook “deny-default-namespace.devsecops.com” denied the request: Creation of resources within the default namespace is not allowed!
This is what you’d see when you try to create any resource in the default namespace.
Controller Policy:
In this example, we will try to create a resource quota automatically whenever the namespace is created. Provided the namespace should have the labels “create-rq”: “true”.
$ git clone https://github.com/pavan-kumar-99/medium-manifests.git \
-b jsPolicy$ cd medium-manifests$ kubectl apply -f controller-policy.yaml## Let us now create the namespace with the required labels$ kubectl apply -f namespace.yaml
Once the namespace is created, you can find the ResourceQouta also gets automatically created.
Well, that is how you utilize jsPolicy to write various types of policies in JavaScript and in TypeScript using jsPolicy. Please feel free to share your experience while working on these policies in the comment section.
Until next time…..