3. Create & Test Policies
To write a policy with JsPolicy, we need to do two things:
- Configure the Policy Settings via the
JsPolicyresource - Add Policy Logic either via embedding vanilla JavaScript code to
spec.javascriptinside theJsPolicyresource or by creating a separateJsPolicyBundlefrom compiled JavaScript or TypeScript code
Configure Policy Settings#
All relevant settings for policies are stored inside the JsPolicy custom resource and there are three types of options:
- Policy Type:
Validating,Mutating, orController - Policy Trigger: defines for which kind of operations and objects the policy should be exectued
- Runtime Settings: define additional parameters that matter during the execution of the policy logic.
An example of a JsPolicy object with these settings could look like this:
Policy Type#
The type of the policy tells jsPolicy what the policy is supposed to do:
type: Mutating: mutate the object/payload of a request to the Kubernetes API server (mutating admission control webhook)type: Validating: validate requests to the Kubernetes API server (validating admission control webhook)type: Controller: react to Kubernetes Events after an object in your cluster has changed (reconciliation function of a Kubernetes controller)
Learn more about the different Policy Types
Policy Trigger#
Since you do not want all your policies to be executed every time for all interactions with all the objects in your Kubernetes cluster, you can limit for which objects a particular policy should trigger.
The following options may be configured to specify when a particular policy should be triggered:
operations: An array of strings containing Kubernetes CRUD operations, i.e. any combination ofCREATE,UPDATE,DELETEresources: An array of strings stating Kubernetes resources, e.g.pods,deployments,servicesetc.scope: A string stating if the operation isNamespacedorCluster-wide (default value:*(meansNamespaced||Cluster))namespaceSelector: A Kubernetes namespace selector which defines that a policy should only trigger for operations in namespaces with specific attributes (e.g. only namespaces with certain labels)objectSelector: A Kubernetes object selector which defines that a policy should only trigger for objects with specific attributes (e.g. only objects with certain labels)matchPolicy: A string stating the Kubernetes match policy which tells Kubernetes how fuzzy theobjectSelectorshall be applied (eitherExactorEquivalent(default))apiGroups: An array of strings stating Kubernetes API groups (default:*matching any API group)apiVersions: An array of strings stating Kubernetes API versions (default:*matching any API version)
Runtime Settings#
Within the spec of a JsPolicy object, you can also define certain settings that are relevant during the execution of a policy:
violationPolicy:deny(default) orwarn(for testing) when the policy logic calls thedeny()functionfailurePolicy:Fail(default) orIgnorewhen jsPolicy fails to execute the policy or it aborts with a runtime errorreinvocationPolicy: Reinvocation Policy defines whether JSPolicy is called again as part of the admission evaluation if the object being admitted is modified by other admission plugins after the initial webhook call (IfNeeded) or not (Never, default)auditPolicy:Log(default) orSkiplogging any policy violations (requests that lead todeny()) in the status of this policyauditLogSize: Maximum number of violations that should be stored in the status of this policy (default:10violations)timeoutSeconds: Maximum number of seconds that the execution of the policy logic may take before jsPolicy aborts the policy execution (default:10seconds, maximum is30)
Write Policy Logic#
There are different ways to write policy logic for JsPolicy. The following table compares three common workflows:
Embedded spec.javascript | Separate JavaScript | TypeScript | |
|---|---|---|---|
| Language | JavaScript | JavaScript | TypeScript (modern) |
| Type Safety | no | no | yes |
| IDE Support | bad (JavaScript in YAML) | good | great (auto-completion, warnings, types) |
| Testing | only end-to-end via test kubectl requests | unit, functional and end-to-end tests | unit, functional and end-to-end tests |
| Publishing | only via JsPolicy YAML files | via npm packages | via npm packages |
| JsBundle Generation | automatic by jsPolicy | manual or via dev tools (SDK) | manual or via dev tools (SDK) |
| SDK | - | jsPolicy SDK | jsPolicy SDK |
Inline JavaScript Policies#
Use the spec.javascript option of the JsPolicy CRD to write policy code inline as embedded JavaScript ES5 (vanilla JS):
Dependencies For Embedded JavaScript Policies#
Use the spec.dependencies option to define dependencies that you want to load for this policy. You can specify any CommonJS package from the npm registry here or import your own packages.
Separate JavaScript or TypeScript#
You can use a separate JavaScript project to build, test and deploy your policies. Any language that can get cross-compiled to Javascript is supported. Please take a look at our Policy SDK or TypeScript example on how to write policies and compile them to JsPolicy and JsPolicyBundle objects.
Test Policies#
Of course, you can simply apply your policies via kubectl apply to any cluster and then run kubectl command to end-to-end test your policies. However, since your policy logic will be entirely written in JavaScript (or TypeScript which compiles to JavaScript), you can use any JavaScript testing framework to create and run test suits, including unit tests, functional tests, integration tests and end-to-end tests.
See the example tests in the jsPolicy SDK project on GitHub for a reference implementation using the test framework Jest developed by Facebook.