jsPolicy Documentation

repository·main·Indexed 19 days ago

https://github.com/loft-sh/jspolicy

A high-performance Kubernetes policy engine that allows users to write validating, mutating, and controller-based policies using JavaScript or TypeScript. It leverages the V8 engine for fast execution and provides built-in cluster access functions for interacting with the Kubernetes state.

Tokens
20.6K
Snippets
60
Records
100
Agent score
65%

What's inside jsPolicy

  1. How Controller policies behave in jsPolicy

    main

    When a jsPolicy is configured with type: Controller, it behaves like a standard Kubernetes controller.

    Key behaviors include:

    • Reconciliation: The policy logic is called during each reconcile cycle.
    • Watch Events: The controller receives watch events directly from Kubernetes, allowing it to react immediately to cluster changes or enforce policies on existing objects.
    • Concurrency: jsPolicy ensures only one instance of a specific policy runs at a time to prevent race conditions.
    • Event Lifecycle:
      • On startup, a controller receives a CREATE event for every existing resource that matches its selectors.
      • On subsequent changes, it receives CREATE events for new or modified objects and DELETE events for deleted objects.
      • During informer re-syncs, CREATE events are re-emitted for all existing resources.
    • Selectors: Controller policies support objectSelector and namespaceSelector to limit the scope of the controller.
    apiVersion: policy.jspolicy.com/v1beta1
    kind: JsPolicy
    metadata:
      name: "state.resource.example"
    spec:
      type: Controller
      objectSelector:
        matchLabels:
          create-rq: "true"
      javascript: |
        // Policy logic goes here
  2. Use Mutating policies to modify Kubernetes objects

    main

    Mutating policies are executed during kubectl requests immediately after authentication and authorization (RBAC). They are used to modify the payload (Kubernetes object) of a request before it is persisted.

    Common use cases include:

    • Adding mandatory labels or annotations to metadata.
    • Auto-completing fields (e.g., adding a nodeSelector to a Pod).
    • Replacing placeholders in strings (e.g., replacing #BASE_HOSTNAME# with a specific domain).

    Because mutating policies change the object, Kubernetes executes them sequentially to prevent interference.

    Reinvocation Policy

    You can specify a reinvocationPolicy to control how the jsPolicy admission plugin observes changes made by other admission plugins. This defaults to Never.

    • Never: The policy webhook is called at most once per admission evaluation.
    • IfNeeded: The policy webhook may be called again if the object is modified by other admission plugins after the initial call.
  3. How jsPolicy architecture works

    main

    jsPolicy is a Kubernetes policy engine that allows you to write policies using JavaScript or TypeScript. While it runs within a single container, it is logically composed of three interacting components:

    1. Webhook Manager: Manages the registration and lifecycle of admission webhooks with the Kubernetes API server. It ensures that requests to the API server trigger the mutating and validating webhooks defined in your JsPolicy objects.
    2. V8 JavaScript Sandbox Pool: A performance-optimizing component that maintains a pool of pre-heated V8 sandboxes. This allows the engine to execute policy logic rapidly without the overhead of starting a new JavaScript environment for every request.
    3. Policy Compiler: A controller that automates the transformation of raw JavaScript into executable bundles. It monitors JsPolicy resources and manages JsPolicyBundle objects.
  4. Understand the jsPolicy Custom Resource Definitions (CRDs)

    main

    jsPolicy operates using three primary Kubernetes Custom Resource Definitions (CRDs) to manage policy lifecycle, code distribution, and violation reporting:

    1. JsPolicy: Defines the actual policy logic. You can provide code either as a raw string in spec.javascript or by referencing a bundle.
    2. JsPolicyBundle: Used to distribute policy code. It contains a base64 encoded and gzip compressed version of your JavaScript code in the spec.bundle field. A JsPolicyBundle must have the same name as its corresponding JsPolicy object.
    3. JsPolicyViolations: Automatically generated by the engine to record denied requests or errors encountered during policy execution. These can be queried via kubectl or the Kubernetes API for monitoring and alerting.
  5. Understand the three types of jsPolicy policies

    main

    jsPolicy supports three distinct policy models depending on your use case:

    1. Validating Policies: Used for request validation. You can control the outcome using three primary functions:
      • allow(): Explicitly permits the request.
      • deny("reason"): Rejects the request with a specific error message.
      • warn("message"): Allows the request but emits a warning (e.g., for deprecation notices).
    2. Mutating Policies: Used to modify the incoming kubectl request payload. You apply changes by calling mutate(modifiedObj) with the updated object.
    3. Controller Policies: Reactive policies that respond to Events in your cluster rather than being part of a synchronous Kubernetes API server request (webhooks). These are used for building resource sync mechanisms, namespace enforcement, garbage collectors, or custom CRD controllers.
  6. Understand jsPolicy policy types: Mutating, Validating, and Controller

    main

    jsPolicy supports three distinct policy types, each with different triggers, execution models, and expected outcomes:

    1. Mutating Policies

    • Trigger: Requests to the Kubernetes API server.
    • Execution Order: Sequential.
    • Expected Result: A modified mutate() request object.
    • Lifecycle: Runs after Kubernetes authentication and authorization (RBAC).

    2. Validating Policies

    • Trigger: Requests to the Kubernetes API server.
    • Execution Order: Parallel.
    • Expected Result: An allow() or deny() decision.
    • Lifecycle: Runs after Mutating policies. If any Validating policy calls deny(), the request is aborted and not persisted in etcd.

    3. Controller Policies

    • Trigger: Asynchronous Kubernetes Events (triggered by any CRUD operation on Kubernetes objects).
    • Execution Order: Queued.
    • Expected Result: Any action (e.g., performing other CRUD operations in the cluster).
    • Lifecycle: These are not part of the Kubernetes API server request lifecycle; they react to changes that have already occurred.
    |         `type:` | [`Mutating`](../using-policies/policy-types.mdx#mutating)                  | [`Validating`](../using-policies/policy-types.mdx#validating)                  | [`Controller`](../using-policies/policy-types.mdx#controller)                   |
    |----------------:|:---------------------------:|:-----------------------------:|:------------------------------:|
    | Trigger         | Requests to k8s API server  |   Requests to k8s API server  | Changes to k8s object (Events) |
    | Execution Order |          sequential         |            parallel           |             queued             |
    | Expected Result |  `mutate()` request object  | `allow()` or `deny()` request |            anything            |
  7. Configure JsPolicy resource settings

    main

    Writing a jsPolicy involves defining two components: Policy Settings (the JsPolicy custom resource) and Policy Logic (the actual code).

    Policy settings are stored in the JsPolicy resource and are categorized into three types:

    1. Policy Type: Determines the role of the policy (Validating, Mutating, or Controller).
    2. Policy Trigger: Defines which Kubernetes operations and objects trigger the policy.
    3. Runtime Settings: Parameters that control how the policy executes and handles errors/violations.

    To implement a policy, you define these settings in the spec of a JsPolicy object and provide the logic via spec.javascript or a JsPolicyBundle.

    apiVersion: policy.jspolicy.com/v1beta1
    kind: JsPolicy
    metadata:
      name: "policy-name.company.tld"
    spec:
      type: Validating
      # ... other settings ...
      # javascript: if ...
  8. Configure Policy Types

    main

    The type field in the JsPolicy spec determines the role of the policy within Kubernetes:

    • Mutating: Acts as a mutating admission control webhook to modify the object/payload of a request.
    • Validating: Acts as a validating admission control webhook to validate requests.
    • Controller: Acts as a reconciliation function of a Kubernetes controller, reacting to Kubernetes Events after an object has changed.
  9. Access Kubernetes cluster state in jsPolicy

    main

    jsPolicy provides built-in functions to interact with the Kubernetes cluster state directly within your policy logic. This allows you to read, create, or modify resources as part of your policy execution.

    Commonly used functions include:

    • get(kind, apiVersion, name): Retrieve a specific object (e.g., get("Pod", "v1", "my-namespace/my-pod")).
    • list(kind, apiVersion): List objects of a specific type (e.g., list("Namespace", "v1")).
    • create(object): Create a new resource.
    • update(object): Update an existing resource.
    • remove(object): Delete a resource.