-
Notifications
You must be signed in to change notification settings - Fork 99
Update policies documentation for clarity and accuracy #3093
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
octo-ryanhall
wants to merge
6
commits into
main
Choose a base branch
from
policies-documentation-uplift
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
2917cba
Update policies documentation for clarity and accuracy
hcrhall 0602df0
Fix linting for markdown
hcrhall 1596320
Fix formatting inconsistencies in policies documentation
hcrhall 8e1e041
Add missing hints and warnings for policy rules in documentation
hcrhall 80a357b
Refine schema documentation for policies: update titles, subtitles, a…
hcrhall 73a4028
Refactor policies documentation for clarity: update terminology, fix …
hcrhall File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,75 +2,160 @@ | |
| layout: src/layouts/Default.astro | ||
| pubDate: 2025-09-11 | ||
| modDate: 2025-09-25 | ||
| title: Policies best practices | ||
| subtitle: Best practices for creating policies within Platform Hub | ||
| title: Policy best practices | ||
| subtitle: Guidance on naming, rollout, and writing reliable policies | ||
| icon: fa-solid fa-lock | ||
| navTitle: Best Practices | ||
| navTitle: Best practices | ||
| navSection: Policies | ||
| description: Best practices for creating policies within Platform Hub | ||
| description: Best practices for creating and managing policies in Platform Hub. | ||
| navOrder: 165 | ||
| --- | ||
|
|
||
| ## Policies administration | ||
| This page covers the practices that will save you time and prevent problems as you build and roll out policies across your organization. If you're writing your first policy, start with the [getting started guide](/docs/platform-hub/policies) first. | ||
|
|
||
| ### Establish a naming standard | ||
| ## Naming your policies | ||
|
|
||
| Use a [ Prefix ] - [ Policy Name ] that is easy for everyone to understand the policy's purpose. The [ Prefix ] should reflect when the policy will run. | ||
| A consistent naming standard makes it easy for everyone to understand what a policy does and when it runs, without having to open it. | ||
|
|
||
| For example: | ||
| Use the format **[Scope] - [Policy name]**, where the scope prefix reflects what type of execution the policy applies to: | ||
|
|
||
| - Deployments - [ Policy Name ] for policies designed to run during deployments only. | ||
| - Runbook Runs - [ Policy Name ] for policies designed to run during runbooks runs only. | ||
| - Deployments and Runbook Runs - [ Policy Name ] for policies for designed to run for deployments or runbooks runs. | ||
| | Scope prefix | Use when | | ||
| | --- | --- | | ||
| | Deploy | The policy only applies to deployments | | ||
| | Run | The policy only applies to runbook runs | | ||
| | Global | The policy applies to both | | ||
|
|
||
| ### Turn on SIEM audit log streaming | ||
| For example: `Deploy - Manual intervention required` or `Run - Main branch only`. | ||
|
|
||
| All policy evaluations are logged to the audit log. Ensure [audit log streaming](/docs/security/users-and-teams/auditing/audit-stream) is enabled to log those evaluations to Splunk, SumoLogic, or an OpenTelemetry collector. SIEM tools can provide alerting and visualizations that you can customize to your requirements. | ||
| ## Use warn before block | ||
|
|
||
| ## Creating and Updating Policies | ||
| Every new policy should start with `"action": "warn"` in the default result. A warning lets the execution proceed but records the violation in the task log, dashboard, and audit log. This gives you a chance to verify the policy is evaluating the right executions before it starts blocking anyone. | ||
|
|
||
| ### Start restrictive, then make generic | ||
| Once you've confirmed the policy is working as expected, switch to `"action": "block"`. | ||
|
|
||
| Consider a policy that will block the execution of deployments and runbook runs. By default, that policy applies to all deployments and runbook runs. | ||
| ```rego | ||
| # Start here while testing | ||
| default result := {"allowed": false, "action": "warn"} | ||
|
|
||
| When creating a new policy, be as restrictive as possible by limiting it to: | ||
| # Switch to this once confirmed | ||
| default result := {"allowed": false, "action": "block"} | ||
| ``` | ||
|
|
||
| - A specific hook - such a deployment or a runbook run (not both) | ||
| - A specific project | ||
| You can also use the `action` field in individual rules to block in production while warning elsewhere. See the [block in production, warn elsewhere](/docs/platform-hub/policies/examples#block-in-production-warn-elsewhere) example. | ||
|
|
||
| That will limit a policy's "blast radius." Once you are confident the policy is working as intended, extend the policy to cover more projects or tenants. When acceptable, switch the policy to project groups or spaces. | ||
| ## Start narrow, then broaden | ||
|
|
||
| ### Provide a verbose failure reason | ||
| When you create a new policy, limit its scope as tightly as possible: | ||
|
|
||
| A policy violation will be the first experience for must users with policies within Octopus Deploy. For example, when a policy blocks a deployment or runbook run. Provide a verbose failure reason to help the user self-service the solution. | ||
| 1. **Start with a single project and execution type.** For example, scope to one project and deployments only. This limits the blast radius if the policy behaves unexpectedly. | ||
| 2. **Extend to more projects or tenants** once you're confident the policy is correct. | ||
| 3. **Extend to project groups or spaces** once you're satisfied with behaviour across multiple projects. | ||
|
|
||
| This progression also gives teams time to fix violations before the policy scope reaches them, rather than discovering a blocked deployment with no warning. | ||
|
|
||
| ## Write a clear violation reason | ||
|
|
||
| A policy violation is often the first time a user encounters the policies feature. The violation reason is the message they see when a deployment or runbook run fails. Make it specific enough for them to understand what's wrong and what to do about it. | ||
|
|
||
| Avoid generic messages like "Policy violation" or "Deployment blocked". Instead, explain what was expected: | ||
|
|
||
| :::figure | ||
|  | ||
|  | ||
| ::: | ||
|
|
||
| ### Check for both the existence of steps and if they’ve been skipped | ||
| You can set a default violation reason in the policy UI, and override it per rule using the `reason` property in your conditions Rego: | ||
|
|
||
| ```rego | ||
| result := {"allowed": false, "reason": "A manual intervention step is required and cannot be skipped in this environment"} if { | ||
| manual_intervention_skipped | ||
| } | ||
| ``` | ||
|
|
||
| Policies can be written to check for the existence of specific steps within a deployment or runbook process. It's important to remember that in many cases those deployments and runbook processes have existed for years. Octopus Deploy has the capability to require a step and prevent it from being skipped. But it is unlikely that _all_ of those required steps in _all_ of your deployment and runbook processes have been configured to prevent them from being skipped. | ||
| ## Check for both existence and skipping | ||
|
|
||
| It is not enough for a policy to simply check for the existence of a specific step. The policy must also ensure users don't elect to skip the required step (for whatever reason). | ||
| It's not enough to check that a required step exists in the process. Users can skip steps when scheduling a deployment or runbook run, even if the step is present. | ||
|
|
||
| :::figure | ||
|  | ||
|  | ||
| ::: | ||
|
|
||
| The resulting policy will have two conditions. | ||
| Your policy conditions should check both that the step is present and that it hasn't been skipped: | ||
|
|
||
| ```rego | ||
| result := {"allowed": true} if { | ||
| some step in input.Steps | ||
| step.Source.SlugOrId == "<step-slug>" | ||
| not step.Id in input.SkippedSteps | ||
| step.Enabled == true | ||
| } | ||
| ``` | ||
|
|
||
| :::figure | ||
|  | ||
|  | ||
| ::: | ||
|
|
||
| ### Check for parallel execution | ||
| See the [steps and skipping examples](/docs/platform-hub/policies/examples#ensure-required-steps-are-present) for complete patterns. | ||
|
|
||
| ## Guard against conditional fields | ||
|
|
||
| Three input fields are not always present in the input object: `Tenant`, `Release`, and `Runbook`. Referencing them without checking for their existence first will cause a policy evaluation error. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should add a link to the schema here so we don't have to keep updating this with optional properties. Something like changing the below might be better. |
||
|
|
||
| | Field | When it's present | | ||
| | --- | --- | | ||
| | Tenant | Tenanted deployments only | | ||
| | Release | Deployments only | | ||
| | Runbook | Runbook runs only | | ||
|
|
||
| Always guard against their absence in your scope or conditions: | ||
|
|
||
| ```rego | ||
| # Safe: check Runbook exists before accessing its properties | ||
| evaluate if { | ||
| input.Runbook | ||
| input.Runbook.Id == "<runbook-id>" | ||
| } | ||
|
|
||
| # Unsafe: will error if Runbook is absent | ||
| evaluate if { | ||
| input.Runbook.Id == "<runbook-id>" | ||
| } | ||
| ``` | ||
|
|
||
| The simplest way to avoid this is to scope your policy to deployments only or runbook runs only when the policy is specific to one type. See the [scoping examples](/docs/platform-hub/policies/examples#scoping-examples). | ||
|
|
||
| ## Check for parallel execution | ||
|
|
||
| Steps can be configured to run in parallel or sequentially. If your organization requires sequential execution for compliance or audit purposes, add a policy to enforce it. | ||
|
|
||
| Each item in the `Execution` input field has a `StartTrigger` property with one of two values: | ||
|
|
||
| - `StartAfterPrevious`: the step runs after the previous step completes | ||
| - `StartWithPrevious`: the step runs at the same time as the previous step | ||
|
|
||
| To enforce sequential execution: | ||
|
|
||
| ```rego | ||
| result := {"allowed": true} if { | ||
| every execution in input.Execution { | ||
| execution.StartTrigger != "StartWithPrevious" | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| See the [prevent parallel execution](/docs/platform-hub/policies/examples#prevent-parallel-execution) example for the complete policy. | ||
|
|
||
| ## Stream evaluations to your SIEM | ||
|
|
||
| All policy evaluations are recorded in the Octopus audit log. If your organization uses a SIEM tool such as Splunk, Sumo Logic, or an OpenTelemetry collector, set up [audit log streaming](/docs/security/users-and-teams/auditing/audit-stream) to forward those records automatically. | ||
|
|
||
| This gives your security team visibility into policy violations across your entire Octopus instance, and lets you build dashboards and alerts that match your compliance requirements. | ||
|
|
||
| Steps can be configured to run in parallel or sequentially. If your organization requires sequential execution for compliance or troubleshooting purposes, create a policy to check the `Execution` array in the input schema. | ||
| ## Testing your policy | ||
|
|
||
| Each execution phase has a `StartTrigger` property that indicates when it should run: | ||
| Before extending a policy's scope or switching from warn to block, verify it's evaluating correctly: | ||
|
|
||
| - `StartAfterPrevious` - Steps run sequentially | ||
| - `StartWithPrevious` - Steps run in parallel | ||
| 1. Run a deployment or runbook run that should fail the policy. Confirm the violation appears in the task log and project dashboard. | ||
| 2. Run a deployment or runbook run that should pass the policy. Confirm it proceeds without a violation. | ||
| 3. Check the audit log under **Configuration** > **Audit**, filtered by **Compliance Policy Evaluated**, to see the full evaluation history. | ||
|
|
||
| To enforce sequential execution, check that no execution phases have `StartTrigger` set to `StartWithPrevious`. See the [examples page](/docs/platform-hub/policies/examples) for a sample policy. | ||
| To see the exact input object that was passed to the policy engine for a specific execution, turn on the verbose option in the task log. This is useful when a policy isn't evaluating as expected. See [Troubleshooting policies](/docs/platform-hub/policies/troubleshooting) for more detail. | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we use ruby as the language from memory as we don't have sytanx highlighting for rego