DEV Community

Cover image for Kubernetes policy management: IV - jsPolicy
Ashok Nagaraj
Ashok Nagaraj

Posted on • Edited on

Kubernetes policy management: IV - jsPolicy

This is the final post of the series.

Other parts:
I - Introduction
II - OPA Gatekeeper
III - Kyverno


jsPolicy offers a simple alternative to OPA. You can use it to write policy logic in JavaScript or TypeScript, and it offers Turing completeness, easy cluster access, and a huge ecosystem of libraries. Other features include validating, mutating, or changing policies, and defining controller policies. It uses Chrome V8 engine underneath, so performance and stability are battle tested

Installation

❯ helm install jspolicy jspolicy -n jspolicy --create-namespace --repo https://charts.loft.sh NAME: jspolicy LAST DEPLOYED: Tue Mar 8 20:46:34 2022 NAMESPACE: jspolicy STATUS: deployed ... ❯ kubectl get crds | grep jspolicy jspolicies.policy.jspolicy.com 2022-03-08T15:16:28Z jspolicybundles.policy.jspolicy.com 2022-03-08T15:16:28Z jspolicyviolations.policy.jspolicy.com 2022-03-08T15:16:28Z 
Enter fullscreen mode Exit fullscreen mode

Architecture
jsPolicy architecture from loft labs

Creating and instantiating policies
Validating policy to disallow workload creation under namespaces default and restricted

❯ cat /tmp/policy.yaml # policy.yaml apiVersion: policy.jspolicy.com/v1beta1 kind: JsPolicy metadata: name: "deny-default-namespace.example.com" spec: operations: ["CREATE"] resources: ["*"] scope: Namespaced javascript: | var namespacesToDeny = ["default", "restricted"]; if (namespacesToDeny.includes(request.namespace)) { deny("Creation of resources is not allowed in the following namespaces: " + namespacesToDeny.toString()); } ❯ kubectl create -f /tmp/policy.yaml jspolicy.policy.jspolicy.com/deny-default-namespace created 
Enter fullscreen mode Exit fullscreen mode

Mutating policy to add a foo=bar label to pods

❯ cat /tmp/mutate.yaml apiVersion: policy.jspolicy.com/v1beta1 kind: JsPolicy metadata: name: "create-foo-bar-label.example.com" spec: type: Mutating operations: ["CREATE", "UPDATE"] resources: ["pods"] javascript: | if (request.object.metadata.labels?.["foo"] !== "bar") { request.object.metadata.labels = {...request.object.metadata.labels, 'foo': 'bar'}; // tell jspolicy to calc the patch and exit mutate(request.object); } ❯ kubectl create -f /tmp/mutate.yaml jspolicy.policy.jspolicy.com/create-foo-bar-label.example.com created ❯ kubectl run test-pod --image=nginx -n test-ns pod/test-pod created ❯ kubectl get pod -n test-ns --show-labels NAME READY STATUS RESTARTS AGE LABELS test-pod 1/1 Running 0 14s foo=bar,run=test-pod 
Enter fullscreen mode Exit fullscreen mode

Testing

❯ kubectl run test-pod --image=nginx --restart=Never Error from server (Forbidden): admission webhook "deny-default-namespace.example.com" denied the request: Creation of resources is not allowed in the following namespaces: default,restricted 
Enter fullscreen mode Exit fullscreen mode

Extra tools
Policies created for jsPolicy are regular javascript files =>

  • You can develop policies with your favorite editor
  • You can test(unit, functional, scale) with any javascript test frameworks like Jest, Mocha ..
  • You can write policies as external JavaScript files and load them as a dependency This is a programming library so it can be scaled, evolved and maintained with relative ease over time.

More info
jsPolicy configuration
jsPolicy custom javascript functions
Comparison with OPA


I love the rationale(improve understandability) behind JSPolicy

Top comments (0)