From 643e628aa0fc88b14bfba6a531be17fb5e68e95e Mon Sep 17 00:00:00 2001 From: michaeljguarino Date: Sat, 29 Aug 2026 12:03:43 -0400 Subject: [PATCH] Add policy management documentation Adds documentation for the current support for policy management in stacks + workbenches. Heavily relies on the policy-examples repo but also adds useful additional context. --- .github/workflows/codeql.yml | 6 +- .github/workflows/trivy.yaml | 2 +- generated/routes.json | 76 +++++---- package.json | 2 + pages/_app.tsx | 1 + .../plural-ai/ai-agent/configure-agent.md | 13 ++ .../policy-management/common-use-cases.md | 94 +++++++++++ .../policy-management/index.md | 66 ++++++++ .../policy-management/simulating-policies.md | 139 ++++++++++++++++ .../policy-management/stack-policies.md | 149 ++++++++++++++++++ .../policy-management/workbench-policies.md | 105 ++++++++++++ .../policy-management/policy-simulator.png | Bin 0 -> 79207 bytes src/components/GlobalStyles.tsx | 7 + src/highlight.ts | 6 + src/routing/docs-structure.ts | 13 ++ yarn.lock | 9 ++ 16 files changed, 656 insertions(+), 32 deletions(-) create mode 100644 pages/plural-features/policy-management/common-use-cases.md create mode 100644 pages/plural-features/policy-management/index.md create mode 100644 pages/plural-features/policy-management/simulating-policies.md create mode 100644 pages/plural-features/policy-management/stack-policies.md create mode 100644 pages/plural-features/policy-management/workbench-policies.md create mode 100644 public/assets/policy-management/policy-simulator.png create mode 100644 src/highlight.ts diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index e21e1338..239f0d28 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -22,8 +22,8 @@ jobs: - uses: actions/checkout@v3 with: fetch-depth: 0 - - uses: github/codeql-action/init@v2 + - uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} - - uses: github/codeql-action/autobuild@v2 - - uses: github/codeql-action/analyze@v2 + - uses: github/codeql-action/autobuild@v3 + - uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/trivy.yaml b/.github/workflows/trivy.yaml index ece804bf..d8e2a763 100644 --- a/.github/workflows/trivy.yaml +++ b/.github/workflows/trivy.yaml @@ -26,6 +26,6 @@ jobs: ignore-unfixed: true #severity: 'CRITICAL,HIGH' - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@v2 + uses: github/codeql-action/upload-sarif@v3 with: sarif_file: 'trivy-results.sarif' diff --git a/generated/routes.json b/generated/routes.json index 23824478..f0d685ed 100644 --- a/generated/routes.json +++ b/generated/routes.json @@ -85,7 +85,7 @@ }, "/getting-started/advanced-config/sandboxing": { "relPath": "/getting-started/advanced-config/sandboxing.md", - "lastmod": "2026-06-26T10:42:27.000Z" + "lastmod": "2026-08-06T14:42:58.000Z" }, "/getting-started/advanced-config/network-configuration": { "relPath": "/getting-started/advanced-config/network-configuration.md", @@ -105,11 +105,11 @@ }, "/api-reference/kubernetes/management-api-reference": { "relPath": "/api-reference/kubernetes/management-api-reference.md", - "lastmod": "2026-06-10T12:45:04.000Z" + "lastmod": "2026-08-13T15:31:21.000Z" }, "/api-reference/kubernetes/agent-api-reference": { "relPath": "/api-reference/kubernetes/agent-api-reference.md", - "lastmod": "2026-06-10T12:45:04.000Z" + "lastmod": "2026-08-11T20:00:52.000Z" }, "/api-reference/graphql": { "relPath": "/api-reference/graphql.md", @@ -121,11 +121,11 @@ }, "/api-reference/terraform": { "relPath": "/api-reference/terraform/index.md", - "lastmod": "2026-08-04T13:27:26.025Z" + "lastmod": "2026-08-04T15:01:58.000Z" }, "/api-reference/terraform/pulumi": { "relPath": "/api-reference/terraform/pulumi.md", - "lastmod": "2026-08-04T13:27:26.046Z" + "lastmod": "2026-08-04T15:01:58.000Z" }, "/plural-features": { "relPath": "/plural-features/index.md", @@ -137,23 +137,23 @@ }, "/plural-features/continuous-deployment/management-controller": { "relPath": "/plural-features/continuous-deployment/management-controller/index.md", - "lastmod": "2026-06-26T10:42:27.000Z" + "lastmod": "2026-08-06T14:42:58.000Z" }, "/plural-features/continuous-deployment/management-controller/deployment-settings": { "relPath": "/plural-features/continuous-deployment/management-controller/deployment-settings.md", - "lastmod": "2026-06-26T10:42:27.000Z" + "lastmod": "2026-08-06T14:42:58.000Z" }, "/plural-features/continuous-deployment/deployment-operator": { "relPath": "/plural-features/continuous-deployment/deployment-operator/index.md", - "lastmod": "2026-06-26T10:42:27.000Z" + "lastmod": "2026-08-06T14:42:58.000Z" }, "/plural-features/continuous-deployment/deployment-operator/agent-configuration": { "relPath": "/plural-features/continuous-deployment/deployment-operator/agent-configuration.md", - "lastmod": "2026-06-26T10:42:27.000Z" + "lastmod": "2026-08-06T14:42:58.000Z" }, "/plural-features/continuous-deployment/deployment-operator/custom-health": { "relPath": "/plural-features/continuous-deployment/deployment-operator/custom-health.md", - "lastmod": "2026-08-13T15:06:28.330Z" + "lastmod": "2026-08-13T15:30:45.000Z" }, "/plural-features/continuous-deployment/git-service": { "relPath": "/plural-features/continuous-deployment/git-service.md", @@ -173,11 +173,11 @@ }, "/plural-features/continuous-deployment/service-templating": { "relPath": "/plural-features/continuous-deployment/service-templating/index.md", - "lastmod": "2026-08-04T13:27:26.172Z" + "lastmod": "2026-08-29T16:19:38.379Z" }, "/plural-features/continuous-deployment/service-templating/supporting-liquid-filters": { "relPath": "/plural-features/continuous-deployment/service-templating/supporting-liquid-filters.md", - "lastmod": "2026-08-04T13:27:26.192Z" + "lastmod": "2026-08-29T16:19:38.402Z" }, "/plural-features/continuous-deployment/lua": { "relPath": "/plural-features/continuous-deployment/lua.md", @@ -221,7 +221,7 @@ }, "/plural-features/stacks-iac-management": { "relPath": "/plural-features/stacks-iac-management/index.md", - "lastmod": "2026-07-15T09:31:13.000Z" + "lastmod": "2026-08-04T15:01:58.000Z" }, "/plural-features/stacks-iac-management/customize-runners": { "relPath": "/plural-features/stacks-iac-management/customize-runners.md", @@ -229,7 +229,7 @@ }, "/plural-features/stacks-iac-management/pulumi": { "relPath": "/plural-features/stacks-iac-management/pulumi.md", - "lastmod": "2026-07-15T09:31:13.000Z" + "lastmod": "2026-08-04T15:01:58.000Z" }, "/plural-features/stacks-iac-management/pr-workflow": { "relPath": "/plural-features/stacks-iac-management/pr-workflow.md", @@ -293,7 +293,7 @@ }, "/plural-features/plural-ai/ai-agent/configure-agent": { "relPath": "/plural-features/plural-ai/ai-agent/configure-agent.md", - "lastmod": "2026-03-04T02:33:39.000Z" + "lastmod": "2026-08-29T16:16:14.000Z" }, "/plural-features/plural-ai/ai-agent/remote-browser": { "relPath": "/plural-features/plural-ai/ai-agent/remote-browser.md", @@ -345,11 +345,11 @@ }, "/plural-features/workbenches": { "relPath": "/plural-features/workbenches/index.md", - "lastmod": "2026-07-31T10:05:04.000Z" + "lastmod": "2026-08-06T15:20:26.000Z" }, "/plural-features/workbenches/configuration": { "relPath": "/plural-features/workbenches/configuration.md", - "lastmod": "2026-07-31T10:05:04.000Z" + "lastmod": "2026-08-06T15:20:26.000Z" }, "/plural-features/workbenches/coding-agent": { "relPath": "/plural-features/workbenches/coding-agent.md", @@ -357,28 +357,48 @@ }, "/plural-features/workbenches/tools": { "relPath": "/plural-features/workbenches/tools.md", - "lastmod": "2026-07-31T10:05:04.000Z" + "lastmod": "2026-08-06T15:20:26.000Z" }, "/plural-features/workbenches/tools/datadog": { "relPath": "/plural-features/workbenches/tools/datadog.md", - "lastmod": "2026-07-31T10:05:04.000Z" + "lastmod": "2026-08-06T15:20:26.000Z" }, "/plural-features/workbenches/running-jobs": { "relPath": "/plural-features/workbenches/running-jobs.md", - "lastmod": "2026-07-31T10:05:04.000Z" + "lastmod": "2026-08-06T15:20:26.000Z" }, "/plural-features/workbenches/automation": { "relPath": "/plural-features/workbenches/automation.md", - "lastmod": "2026-07-30T14:01:51.000Z" + "lastmod": "2026-08-06T15:20:26.000Z" }, "/plural-features/workbenches/follow-up-automation": { "relPath": "/plural-features/workbenches/follow-up-automation.md", - "lastmod": "2026-07-30T15:19:23.000Z" + "lastmod": "2026-08-06T15:20:26.000Z" }, "/plural-features/workbenches/use-cases": { "relPath": "/plural-features/workbenches/use-cases.md", "lastmod": "2026-05-27T21:33:58.000Z" }, + "/plural-features/policy-management": { + "relPath": "/plural-features/policy-management/index.md", + "lastmod": "2026-08-29T16:16:14.000Z" + }, + "/plural-features/policy-management/stack-policies": { + "relPath": "/plural-features/policy-management/stack-policies.md", + "lastmod": "2026-08-29T16:16:14.000Z" + }, + "/plural-features/policy-management/workbench-policies": { + "relPath": "/plural-features/policy-management/workbench-policies.md", + "lastmod": "2026-08-29T16:16:14.000Z" + }, + "/plural-features/policy-management/simulating-policies": { + "relPath": "/plural-features/policy-management/simulating-policies.md", + "lastmod": "2026-08-29T16:16:14.000Z" + }, + "/plural-features/policy-management/common-use-cases": { + "relPath": "/plural-features/policy-management/common-use-cases.md", + "lastmod": "2026-08-29T16:16:14.000Z" + }, "/plural-features/observability": { "relPath": "/plural-features/observability/index.md", "lastmod": "2025-05-10T04:27:39.000Z" @@ -557,7 +577,7 @@ }, "/deployments/sandboxing": { "relPath": "/getting-started/advanced-config/sandboxing.md", - "lastmod": "2026-06-26T10:42:27.000Z" + "lastmod": "2026-08-06T14:42:58.000Z" }, "/deployments/network-configuration": { "relPath": "/getting-started/advanced-config/network-configuration.md", @@ -569,11 +589,11 @@ }, "/deployments/operator/architecture": { "relPath": "/plural-features/continuous-deployment/deployment-operator/index.md", - "lastmod": "2026-06-26T10:42:27.000Z" + "lastmod": "2026-08-06T14:42:58.000Z" }, "/plural-features/continuous-deployment/deployment-operator/deployment-settings": { "relPath": "/plural-features/continuous-deployment/management-controller/deployment-settings.md", - "lastmod": "2026-06-26T10:42:27.000Z" + "lastmod": "2026-08-06T14:42:58.000Z" }, "/deployments/operator/git-service": { "relPath": "/plural-features/continuous-deployment/git-service.md", @@ -625,7 +645,7 @@ }, "/deployments/stacks": { "relPath": "/plural-features/stacks-iac-management/index.md", - "lastmod": "2026-07-15T09:31:13.000Z" + "lastmod": "2026-08-04T15:01:58.000Z" }, "/service-catalog/creation": { "relPath": "/plural-features/service-catalog/creation.md", @@ -697,10 +717,10 @@ }, "/management-api-reference": { "relPath": "/api-reference/kubernetes/management-api-reference.md", - "lastmod": "2026-06-10T12:45:04.000Z" + "lastmod": "2026-08-13T15:31:21.000Z" }, "/agent-api-reference": { "relPath": "/api-reference/kubernetes/agent-api-reference.md", - "lastmod": "2026-06-10T12:45:04.000Z" + "lastmod": "2026-08-11T20:00:52.000Z" } } \ No newline at end of file diff --git a/package.json b/package.json index 7fb3d47d..2c929f05 100644 --- a/package.json +++ b/package.json @@ -42,12 +42,14 @@ "@react-stately/list": "3.8.1", "@react-stately/select": "3.5.1", "@react-stately/selection": "3.19.0", + "@styra/highlightjs-rego": "^0.1.2", "chroma-js": "2.4.2", "classnames": "2.3.2", "deep-freeze": "0.0.1", "fuse.js": "6.6.2", "graphql": "16.6.0", "gray-matter": "4.0.3", + "highlight.js": "11.9.0", "honorable": "0.194.0", "honorable-theme-default": "0.77.0", "htmlparser2": "9.1.0", diff --git a/pages/_app.tsx b/pages/_app.tsx index 9a3dd732..484d63b1 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -25,6 +25,7 @@ import { useRouter } from 'next/router' import { until } from '@open-draft/until' import { MarkdocContextProvider } from '@pluralsh/design-system/dist/markdoc' import { SSRProvider } from '@react-aria/ssr' +import '@src/highlight' import '@src/styles/globals.css' import styled, { ThemeProvider as StyledThemeProvider } from 'styled-components' import { SWRConfig } from 'swr' diff --git a/pages/plural-features/plural-ai/ai-agent/configure-agent.md b/pages/plural-features/plural-ai/ai-agent/configure-agent.md index 90e3131d..8bd1b3f6 100644 --- a/pages/plural-features/plural-ai/ai-agent/configure-agent.md +++ b/pages/plural-features/plural-ai/ai-agent/configure-agent.md @@ -34,6 +34,19 @@ spec: Supported runtime types are `CLAUDE`, `OPENCODE`, and `GEMINI`. +## Optional: Enable codebase memory persistence + +Agent runtimes include the `codebase-memory-mcp` server for graph-backed code search. By default, its indexes are stored only in the agent pod cache and generated `.codebase-memory/` artifacts are excluded from commits. + +Set `spec.memory: true` to enable team-shared memory persistence by default: + +```yaml +spec: + memory: true +``` + +When enabled, agents index repositories with persistent artifact export enabled, allowing `.codebase-memory/graph.db.zst` and the related `.gitattributes` update to be committed so future runs can bootstrap from the shared graph. Leave this unset or `false` if you want every run to keep its codebase-memory index local to the runtime cache. + ## Tune runtime resources `AgentRuntime` accepts a pod template so you can set CPU/memory requests and limits for the agent container. Use the `default` container name to target the main agent container. diff --git a/pages/plural-features/policy-management/common-use-cases.md b/pages/plural-features/policy-management/common-use-cases.md new file mode 100644 index 00000000..cf045505 --- /dev/null +++ b/pages/plural-features/policy-management/common-use-cases.md @@ -0,0 +1,94 @@ +--- +title: Common policy use cases +description: Patterns for governing workbench tools and infrastructure stack approvals +--- + +Policies are most useful when they encode a narrow, explainable rule around a high-impact operation. Start with guardrails that can be evaluated from explicit input fields, then expand coverage as you observe real evaluations in the simulator. + +## Workbench policies + +### Extend authorization for external tools + +Many external systems have coarse authorization models: a credential may allow access to an entire observability account, log index, or API even when a user only needs a subset. Workbench policies can add request-level controls without issuing a separate credential for every user and use case. + +Examples include: + +- Restricting production log searches to an incident-response group +- Denying queries against sensitive audit or customer-data indices +- Limiting observability queries to approved accounts, services, or time ranges +- Preventing write operations through an external API while permitting reads + +Policy input includes both the actor and tool arguments, allowing the decision to account for who is requesting the action and exactly what the agent plans to send. + +### Increase autonomy with safe-action allowlists + +Agents are most useful when routine, reversible actions can proceed without waiting for a human. Add `approve` rules for a well-defined set of safe operations while leaving everything else on the normal approval path. + +Examples include: + +- Approving restarts of stateless workloads outside protected namespaces +- Approving read-only diagnostic or observability calls +- Allowing an SRE group to update non-production resources +- Automatically posting summaries to a designated incident channel + +Prefer explicit conditions on tool name and arguments over broad actor-only approvals. A narrow allowlist keeps autonomy predictable as new tools and operations are added. + +### Guarantee operational best practices + +Workbench policies apply the same safeguards to every matching workbench, regardless of its prompt or the model running it. + +Examples include: + +- Blocking Kubernetes deletes in system namespaces +- Requiring production mutations to originate from an approved group +- Denying changes that omit required ownership, ticket, or incident metadata +- Preventing access to regulated datasets from general-purpose workbenches + +Use binding policies to attach these guardrails automatically based on workbench naming or metadata conventions. + +## Stack policies + +### Enforce change-management requirements + +Inspect the actor, stack, commit, run type, and plan to require the evidence your organization expects before infrastructure changes proceed. + +Examples include: + +- Rejecting production applies without an approved change reference +- Restricting destroy runs to a designated operations group +- Requiring sensitive stacks to follow a specific repository or branch workflow +- Blocking changes during a freeze window when the required context is present in policy input + +### Streamline approval of known-safe plans + +Stack policies can automatically approve plans that fit a constrained risk profile and leave all other plans to a human or AI reviewer. + +Examples include: + +- Approving tag-only updates +- Approving additive changes to an allowed set of resource types +- Approving non-production plans below a defined size +- Approving EKS plans only when they do not destroy clusters or node groups and do not update the control-plane version + +Model the safe case explicitly. If a plan does not satisfy every condition, return no approval and let the configured approval workflow handle it. + +### Enforce compliance at scale + +Evaluate every matching Terraform plan against controls derived from internal standards or regulatory frameworks. + +Examples include: + +- Requiring encryption and approved key-management configuration +- Denying public network exposure for protected workloads +- Enforcing required tags, retention settings, and backup policies +- Restricting resource types, providers, regions, or machine classes + +Combine reusable stack policies with binding policies to apply controls across projects and stack families. Include a clear denial message that identifies the failed requirement and the expected remediation. + +## Design recommendations + +- Keep each rule focused on one decision and provide a specific reason. +- Use `deny` for requirements that must never be bypassed. +- Use `approve` only for operations whose complete safe boundary can be expressed from the available input. +- Leave uncertain cases undecided so existing human or AI approval remains in control. +- Test boundary conditions in Rego and replay representative live inputs in the [policy simulator](/plural-features/policy-management/simulating-policies). diff --git a/pages/plural-features/policy-management/index.md b/pages/plural-features/policy-management/index.md new file mode 100644 index 00000000..b50a8ff6 --- /dev/null +++ b/pages/plural-features/policy-management/index.md @@ -0,0 +1,66 @@ +--- +title: Policy enforcement +description: Extend Plural authorization and approval workflows with policy as code +--- + +Plural policies let platform and security teams encode enterprise guardrails in [Rego](https://www.openpolicyagent.org/docs/policy-language). Policies are evaluated alongside Plural's built-in RBAC and approval controls, adding organization-specific authorization without replacing the permissions you already configured. + +Use policy enforcement to: + +- Allow or deny workbench tool calls based on the actor, tool, and arguments +- Automatically approve known-safe workbench operations +- Approve or reject stack runs from the contents of an infrastructure plan +- Apply policies consistently to matching workbenches or stacks +- Test proposed policy changes against inputs captured from live evaluations + +{% callout severity="info" %} +Policies only add constraints or automate an existing approval step. They do not grant access that the actor or workbench does not already have through Plural RBAC and tool permissions. +{% /callout %} + +## Policy types + +| Type | Rego package | Purpose | +|---|---|---| +| Workbench | `plrl.wb.admission` | Deny tool calls or automatically approve operations that require approval | +| Stack | `plrl.stack` | Approve or reject stack runs from plan, stack, commit, and actor data | +| Binding | `plrl.binding` | Select which workbenches or stacks receive another policy | + +Workbench and stack policies return decisions. Binding policies return a `bind` decision and connect those enforcement policies to matching resources. This separation lets you reuse one guardrail across many workbenches or stacks without attaching it to each resource manually. + +## Decision model + +Workbench and stack policies can add objects to the `deny` and `approve` sets: + +```rego +deny[{"msg": "explain why the operation is blocked"}] if { + # conditions +} + +approve[{"reason": "explain why the operation is safe"}] if { + # conditions +} +``` + +A denial takes precedence over an approval. When no rule produces a decision: + +- A workbench tool call continues through its normal authorization and approval path. +- A stack run continues to its configured human or AI approval path. + + +## Managing policies + +Open **Security → Policies** in the Plural Console to create and edit policies, inspect attachments, review evaluations, and run simulations. Policies are project-scoped, allowing each project to apply guardrails appropriate to its resources and teams. + +For a GitOps workflow, store policies and tests in Git and publish them with the [Plural Terraform provider](https://registry.terraform.io/providers/pluralsh/plural/latest/docs). The [Plural policy examples repository](https://github.com/pluralsh/policy-examples) demonstrates the complete workflow, including: + +- Workbench, stack, and binding policies +- Rego unit tests and CI +- Terraform resources that publish and bind policies +- A Plural `InfrastructureStack` that deploys the configuration + +## Next steps + +- [Stack policies](/plural-features/policy-management/stack-policies) +- [Workbench policies](/plural-features/policy-management/workbench-policies) +- [Simulating and testing policies](/plural-features/policy-management/simulating-policies) +- [Common use cases](/plural-features/policy-management/common-use-cases) diff --git a/pages/plural-features/policy-management/simulating-policies.md b/pages/plural-features/policy-management/simulating-policies.md new file mode 100644 index 00000000..d86285b9 --- /dev/null +++ b/pages/plural-features/policy-management/simulating-policies.md @@ -0,0 +1,139 @@ +--- +title: Simulating and testing policies +description: Validate Rego policies with live evaluation data and automated tests +--- + +Test policies at two levels: + +- Use the Plural policy simulator to evaluate an editor draft against representative or previously observed input. +- Keep Rego unit tests beside each policy in Git and run them in CI before publishing changes. + +## Simulate a policy in Plural + +Open **Security → Policies**, select a policy, and open its **Definition** tab. The simulator appears next to the Rego editor. + +![](/assets/policy-management/policy-simulator.png) + +To run a simulation: + +1. Select an item from **Past evals** to load input captured from a live policy evaluation. +2. Review or edit the JSON under **Input**. +3. Update the Rego in the editor if you want to test a proposed change. +4. Click **Run simulation** and inspect the decision and JSON under **Output**. + +Simulations run against the current editor buffer, even when it has not been saved. This lets you validate a change before replacing the active policy. + +{% callout severity="info" %} +Past evaluations are sampled for debugging and auditability, so the list is not a complete record of every policy evaluation. +{% /callout %} + +The output depends on the policy type: + +| Type | Relevant output | +|---|---| +| Workbench | `deny` and `approve` decision arrays | +| Stack | `deny`, `approve`, and `defer` | +| Binding | Boolean `bind` decision | + +For stack policies, inspect the raw output when testing automatic approval. An output without a denial is allowed by the simulator, while an `approve` entry is what causes the stack runtime to automatically approve a run. + +## Test Rego in a repository + +The [policy examples repository](https://github.com/pluralsh/policy-examples) uses this layout: + +```text +. +├── .github/workflows/test.yaml +├── policies/ +│ ├── binding/ +│ ├── stack/ +│ └── workbench/ +└── terraform/ + ├── main.tf + ├── stack.tf + ├── workbench.tf + └── policies -> ../policies +``` + +Place tests next to their policy and name them `*_test.rego`. Use the same package as the policy and evaluate its rules with a supplied input: + +```rego +package plrl.wb.admission + +test_non_sre_cannot_delete_from_kube_system if { + deny[{"msg": "deleting resources in the kube-system namespace is not allowed"}] with input as { + "actor": {"groups": ["developers"]}, + "tool_name": "delete_k8s_resource", + "tool": {"namespace": "kube-system"}, + } +} + +test_sre_update_is_approved if { + approve[{"reason": "SREs may update resources outside the kube-system namespace"}] with input as { + "actor": {"groups": ["sre"]}, + "tool_name": "update_k8s_resource", + "tool": {"namespace": "production"}, + } +} +``` + +Run formatting and tests locally with the [OPA CLI](https://www.openpolicyagent.org/docs/latest/cli/): + +```shell +opa fmt --fail policies +opa test --verbose policies +``` + +Run the same checks in CI: + +```yaml +name: Test policies + +on: + pull_request: + push: + branches: + - main + +jobs: + rego: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: open-policy-agent/setup-opa@v2 + with: + version: latest + - run: opa fmt --fail policies + - run: opa test --verbose policies +``` + +Include positive, negative, and undecided cases. For stack policies, cover destructive and replacement actions as well as missing `before` or `after` objects. For workbench policies, test relevant actor groups, tool names, and argument boundaries. + +## Publish through a Plural stack + +Manage policies as code by declaring `plural_policy` and `plural_binding_policy` resources in Terraform, then deploying that directory with an `InfrastructureStack`: + +```yaml +apiVersion: deployments.plural.sh/v1alpha1 +kind: InfrastructureStack +metadata: + name: policy-management + namespace: infra +spec: + name: policy-management + type: TERRAFORM + approval: true + manageState: true + actor: console@plural.sh + clusterRef: + name: mgmt + namespace: infra + repositoryRef: + name: policy-management + namespace: infra + git: + ref: main + folder: terraform +``` + +When the stack checks out only the configured Git folder, keep policy files inside that folder or symlink them into it as shown in the example repository. diff --git a/pages/plural-features/policy-management/stack-policies.md b/pages/plural-features/policy-management/stack-policies.md new file mode 100644 index 00000000..572f4005 --- /dev/null +++ b/pages/plural-features/policy-management/stack-policies.md @@ -0,0 +1,149 @@ +--- +title: Stack policies +description: Enforce and automate infrastructure stack approvals with Rego +--- + +Stack policies evaluate infrastructure plans before an approval-gated stack run proceeds. They can reject a run that violates a guardrail, automatically approve a known-safe plan, or leave the run undecided so it continues to the configured human or AI approval flow. + +Stack policies use the `plrl.stack` Rego package. + +## Supported input + +Plural evaluates a stack policy with the following top-level input: + +| Field | Description | +|---|---| +| `input.plan` | A reduced Terraform plan containing `terraform_version` and `resource_changes` | +| `input.run_type` | The run operation: `plan`, `apply`, or `destroy` | +| `input.stack` | Stack metadata, including its name, project, and Git configuration | +| `input.commit` | Metadata for the commit associated with the run | +| `input.actor` | The initiating user, including `id`, `name`, `email`, and `groups` when available | + +Each entry in `input.plan.resource_changes` contains: + +| Field | Description | +|---|---| +| `address` | Full Terraform resource address | +| `type` | Terraform resource type, such as `aws_eks_cluster` | +| `name` | Resource name | +| `provider` | Short provider name | +| `change.actions` | Planned actions, such as `create`, `update`, `delete`, or `replace` | +| `change.before` | Resource state before the run | +| `change.after` | Expected resource state after the run | + +## Decisions + +A stack policy can produce: + +- `deny[{"msg": "..."}]`: reject the stack run +- `approve[{"reason": "..."}]`: approve the stack run +- `defer`: leave the decision to the next configured approval step + +If a policy produces neither a denial nor an approval, Plural also continues to the configured approval flow. This is useful for policies that only auto-approve a narrowly defined set of safe plans. + +## Full example + +The following policy denies destructive EKS changes and control-plane upgrades that skip more than one Kubernetes minor version. Plans without destructive changes or any version update are automatically approved, while single-minor upgrades continue to review: + +```rego +package plrl.stack + +eks_types := {"aws_eks_cluster", "aws_eks_node_group"} + +destructive_actions := {"delete", "replace"} + +destructive_eks_change if { + some rc in input.plan.resource_changes + eks_types[rc.type] + some action in rc.change.actions + destructive_actions[action] +} + +cluster_version_update if { + some rc in input.plan.resource_changes + rc.type == "aws_eks_cluster" + is_object(rc.change.before) + is_object(rc.change.after) + rc.change.before.version != rc.change.after.version +} + +version_number(version) := numeric_version if { + parts := split(version, ".") + major := to_number(parts[0]) + minor := to_number(parts[1]) + numeric_version := major * 1000 + minor +} + +cluster_version_skips_minor if { + some rc in input.plan.resource_changes + rc.type == "aws_eks_cluster" + is_object(rc.change.before) + is_object(rc.change.after) + before_version := version_number(rc.change.before.version) + after_version := version_number(rc.change.after.version) + after_version > before_version + 1 +} + +deny[{"msg": "destroying or replacing EKS clusters and node groups is not allowed"}] if { + destructive_eks_change +} + +deny[{"msg": "EKS control-plane upgrades cannot skip Kubernetes minor versions"}] if { + cluster_version_skips_minor +} + +approve[{"reason": "no destructive EKS cluster or node group changes and no cluster version update"}] if { + not destructive_eks_change + not cluster_version_update +} +``` + +The `deny` rules reject prohibited plans and record a specific explanation. A one-minor control-plane upgrade is not denied, but it also does not match the approval rule, so it continues to human or AI review. Plans without an EKS version change or destructive EKS action receive an explicit approval. + +## Attach a policy to stacks + +You can attach a stack policy in either of two ways: + +1. Open **Security → Policies**, select the stack policy, and use the **Attachments** tab to attach it to a stack. +2. Create a binding policy that selects stacks dynamically, then connect the binding policy to the stack policy. + +A binding policy uses `plrl.binding` and returns `bind`: + +```rego +package plrl.binding + +bind if { + startswith(input.stack.name, "cluster-") +} +``` + +Plural evaluates binding policies when matching resources change and on their configured interval. A `true` result attaches the enforcement policy; a `false` result removes an attachment previously managed by that binding. + +The same configuration can be managed with Terraform: + +```hcl +resource "plural_policy" "eks_guardrails" { + name = "eks-guardrails" + type = "STACK" + description = "Reject unsafe EKS changes and auto-approve plans without destructive or version changes." + project_id = data.plural_project.project.id + policy = file("${path.module}/policies/stack/eks_guardrails.rego") +} + +resource "plural_policy" "cluster_stacks" { + name = "cluster-stacks" + type = "BINDING" + description = "Select stacks whose names begin with cluster-." + project_id = data.plural_project.project.id + policy = file("${path.module}/policies/binding/cluster_stacks.rego") +} + +resource "plural_binding_policy" "eks_guardrails_for_clusters" { + policy_id = plural_policy.eks_guardrails.id + bind_policy_id = plural_policy.cluster_stacks.id + type = "STACK" + interval = "6h" +} +``` + +See the [complete stack example](https://github.com/pluralsh/policy-examples/tree/main/policies/stack) for its tests and deployment configuration. diff --git a/pages/plural-features/policy-management/workbench-policies.md b/pages/plural-features/policy-management/workbench-policies.md new file mode 100644 index 00000000..6b3e4360 --- /dev/null +++ b/pages/plural-features/policy-management/workbench-policies.md @@ -0,0 +1,105 @@ +--- +title: Workbench policies +description: Control and approve workbench tool calls with Rego guardrails +--- + +Workbench policies evaluate each matching tool call made by a workbench agent. They extend Plural RBAC and tool permissions with authorization rules that understand the current actor, the requested tool, and its arguments. + +Workbench policies use the `plrl.wb.admission` Rego package. + +{% callout severity="info" %} +A policy cannot make an unavailable tool accessible or grant permissions the actor does not already have. It adds guardrails to the existing workbench authorization model. +{% /callout %} + +## Supported input + +| Field | Description | +|---|---| +| `input.tool_name` | Name of the tool being called | +| `input.tool` | Arguments supplied to the tool, represented as an object | +| `input.actor` | Current user, including `id`, `name`, `email`, and a `groups` array when available | + +The shape of `input.tool` depends on the tool. For example, a Kubernetes operation can include a `namespace`, while a logging tool can include an index and query. Select a past evaluation in the [policy simulator](/plural-features/policy-management/simulating-policies) to inspect the real input for a tool before writing rules against it. + +## Decisions + +A workbench policy can produce: + +- `deny[{"msg": "..."}]`: block the tool call and return the denial message +- `approve[{"reason": "..."}]`: automatically approve a tool that supports approval and record the reason + +A denial takes precedence when multiple rules or attached policies produce decisions. If no rule produces a decision, the tool continues through its normal authorization and approval path. + +## Full example + +This policy blocks non-SRE users from deleting resources in `kube-system` and automatically approves SRE updates outside that namespace: + +```rego +package plrl.wb.admission + +actor_is_sre if { + input.actor.groups[_] == "sre" +} + +deny[{"msg": "deleting resources in the kube-system namespace is not allowed"}] if { + input.tool_name == "delete_k8s_resource" + input.tool.namespace == "kube-system" + not actor_is_sre +} + +approve[{"reason": "SREs may update resources outside the kube-system namespace"}] if { + input.tool_name == "update_k8s_resource" + input.tool.namespace != "kube-system" + actor_is_sre +} +``` + +Use exact tool names and validate the argument shape from a real evaluation. Different integrations can model similar operations with different fields. + +## Attach a policy to workbenches + +You can attach a workbench policy in either of two ways: + +1. Open **Security → Policies**, select the workbench policy, and use the **Attachments** tab to attach it to a workbench. Configure tool matches on the attachment when the policy should only evaluate selected tool names. +2. Use a binding policy to attach it automatically to workbenches matching a naming or metadata convention. + +For example, this binding policy selects workbenches whose names start with `demo-`: + +```rego +package plrl.binding + +bind if { + startswith(input.workbench.name, "demo-") +} +``` + +Plural evaluates binding policies when workbenches change and on their configured interval. A `true` result attaches the enforcement policy; a `false` result removes an attachment previously managed by that binding. + +The policy and binding can be managed with Terraform: + +```hcl +resource "plural_policy" "kubernetes_guardrails" { + name = "kubernetes-guardrails" + type = "WORKBENCH" + description = "Guard Kubernetes deletes and approve safe SRE updates." + project_id = data.plural_project.project.id + policy = file("${path.module}/policies/workbench/kubernetes_guardrails.rego") +} + +resource "plural_policy" "demo_workbenches" { + name = "demo-workbenches" + type = "BINDING" + description = "Select workbenches whose names begin with demo-." + project_id = data.plural_project.project.id + policy = file("${path.module}/policies/binding/demo_workbenches.rego") +} + +resource "plural_binding_policy" "kubernetes_guardrails_for_demos" { + policy_id = plural_policy.kubernetes_guardrails.id + bind_policy_id = plural_policy.demo_workbenches.id + type = "WORKBENCH" + interval = "6h" +} +``` + +See the [complete workbench example](https://github.com/pluralsh/policy-examples/tree/main/policies/workbench) for its tests and deployment configuration. diff --git a/public/assets/policy-management/policy-simulator.png b/public/assets/policy-management/policy-simulator.png new file mode 100644 index 0000000000000000000000000000000000000000..f05df9aa1d46a0981410cd6ec5a70c414a12c354 GIT binary patch literal 79207 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 literal 0 HcmV?d00001 diff --git a/src/components/GlobalStyles.tsx b/src/components/GlobalStyles.tsx index c6e06c9e..2f7704bf 100644 --- a/src/components/GlobalStyles.tsx +++ b/src/components/GlobalStyles.tsx @@ -27,6 +27,13 @@ const GlobalStyles = createGlobalStyle(({ theme }) => ({ color: 'unset', textDecoration: 'unset', }, + '.primary-content table td': { + flexDirection: 'row', + flexWrap: 'wrap', + alignContent: 'center', + alignItems: 'center', + justifyContent: 'flex-start', + }, html: { ...fillAvailable('height'), }, diff --git a/src/highlight.ts b/src/highlight.ts new file mode 100644 index 00000000..2e57495d --- /dev/null +++ b/src/highlight.ts @@ -0,0 +1,6 @@ +import rego from '@styra/highlightjs-rego' +import hljs from 'highlight.js/lib/core' + +if (!hljs.getLanguage('rego')) { + hljs.registerLanguage('rego', rego) +} diff --git a/src/routing/docs-structure.ts b/src/routing/docs-structure.ts index fb3a196f..f7708e28 100644 --- a/src/routing/docs-structure.ts +++ b/src/routing/docs-structure.ts @@ -279,6 +279,19 @@ export const docsStructure: DocSection[] = [ { path: 'use-cases', title: 'Common use cases' }, ], }, + { + path: 'policy-management', + title: 'Policy management', + sections: [ + { path: 'stack-policies', title: 'Stack policies' }, + { path: 'workbench-policies', title: 'Workbench policies' }, + { + path: 'simulating-policies', + title: 'Simulating and testing policies', + }, + { path: 'common-use-cases', title: 'Common use cases' }, + ], + }, { path: 'observability', title: 'Observability Integration', diff --git a/yarn.lock b/yarn.lock index 45c09277..47b7625e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5490,6 +5490,13 @@ __metadata: languageName: node linkType: hard +"@styra/highlightjs-rego@npm:^0.1.2": + version: 0.1.2 + resolution: "@styra/highlightjs-rego@npm:0.1.2" + checksum: f6a47f85f12a523a8104e281d26e9e44bd7d07d4886528812d4cd67991cc02a0ef00278cf717d35e12d63552014577aac7454389968f285e283416b181742646 + languageName: node + linkType: hard + "@swc/counter@npm:^0.1.3": version: 0.1.3 resolution: "@swc/counter@npm:0.1.3" @@ -14834,6 +14841,7 @@ __metadata: "@react-stately/list": 3.8.1 "@react-stately/select": 3.5.1 "@react-stately/selection": 3.19.0 + "@styra/highlightjs-rego": ^0.1.2 "@types/glob": 8.1.0 "@types/node": 20.4.2 "@types/react": 18.3.3 @@ -14859,6 +14867,7 @@ __metadata: fuse.js: 6.6.2 graphql: 16.6.0 gray-matter: 4.0.3 + highlight.js: 11.9.0 honorable: 0.194.0 honorable-theme-default: 0.77.0 htmlparser2: 9.1.0