Policy as code
Create a policy as code
You can create a new policy as code in three ways:
- Via the Cloudsmith web app
- Via the Cloudsmith API
- Via the Cloudsmith Terraform provider
Create a policy via the Cloudsmith web app
-
From the overview page in the Cloudsmith web app, go to the Policies tab and click Policy as code.
-
Click + Create new policy.
-
Select Create blank policy or Start from a template.
-
Create blank policy:
- Enter a policy name.
- Set the policy precedence.
- Specify whether the policy should be terminal.
- Click +Create blank policy.
-
Start from a template:
- Select the template that you want to use. Cloudsmith displays a preview of the template's Rego logic.
- Click Use template.
-
-
The policy opens in the edit view. You can edit the policy name, description, precedence, and terminal setting by clicking the pencil icon next to the policy name.
-
Review and edit the policy logic as needed, and configure actions to apply when the policy conditions are met.
-
Click Save policy.
Cloudsmith will prompt you to enable the policy. Before enabling a policy, test it using the Workspaces Policies Simulate List endpoint. The simulate endpoint evaluates your policy against all packages in the workspace and returns a decision log for each evaluation, without applying any actions. This lets you confirm whether the policy behaves as expected before enabling it. To use this endpoint, you will need the policy's unique identifier (
slug_perm), which you can retrieve via the Workspace Policies List endpoint.
Create a policy via the Cloudsmith API
You can create and manage policies as code by using the Cloudsmith REST API. For the full list of available endpoints, see the Workspaces Policies API documentation.
1. Write your policy logic
Create your policy logic in Rego and save it as a .rego file. For guidance on writing Rego matching logic, see Rego recipes.
package cloudsmith
default match := false
match if count(malicious_packages) > 0
malicious_packages := [vulnerability.id |
some vulnerability in input.v0.osv
startswith(vulnerability.id, "MAL-")
]2. Validate your policy logic
By validating your policy logic, you can catch syntax and type errors before submitting it to the create or update endpoints, which apply the same check. The submitted Rego is not stored.
Use the Workspaces Policies Validate endpoint to check that your policy compiles successfully. The request body has one field, rego, which contains the policy source:
curl -X POST "https://api.cloudsmith.io/v2/workspaces/$CLOUDSMITH_WORKSPACE/policies/validate/" \
-H "Content-Type: application/json" \
-H "X-Api-Key: $CLOUDSMITH_API_KEY" \
-d "$(jq -Rs '{rego: .}' < policy.rego)"Requests return:
is_valid:truewhenfindingscontains no entries with aseverityoferror.findings: a list that describes each problem withseverity,code, andmessagefields and, when known, alinenumber.raw: contains the full output from the Rego compiler and is empty when the policy is valid.
A policy that compiles returns no findings:
{
"is_valid": true,
"findings": [],
"raw": ""
}If the policy doesn't compile, the response lists each problem. For example, if line 5 of the policy refers to malicious_package instead of malicious_packages, the response is:
{
"is_valid": false,
"findings": [
{
"severity": "error",
"code": "rego_unsafe_var_error",
"message": "var malicious_package is unsafe",
"line": 5
}
],
"raw": "1 error occurred: policy.rego:5: rego_unsafe_var_error: var malicious_package is unsafe"
}3. Convert the Rego file to a request payload
Use jq to escape the Rego file contents and build a payload.json request body. Set enabled to false so you can test the policy before enabling it:
escaped_policy=$(jq -Rs . < policy.rego)
cat <<EOF > payload.json
{
"name": "malware policy",
"description": "Detect packages flagged as malicious",
"rego": $escaped_policy,
"enabled": false,
"is_terminal": false,
"precedence": 1
}
EOFA successful request will return an HTTP 201 response, indicating that the policy was created.
4. Retrieve the policy's unique identifier
When a policy is created via the API, the unique identifier for the policy will be provided in the slug_perm field of the response body. This identifier will be required, for example, if you need to update the policy or add actions to it. This identifier can be retrieved by directly extracting it from the policy creation response:
POLICY_SLUG=$(curl ... | jq -r '.slug_perm')Alternatively, you can retrieve the policy identifier via the Workspace Policies List endpoint.
5. Add actions for the policy
After you create a policy, you can assign actions to it with the Workspaces Policies Actions Create endpoint.
In this example, two actions are added to the policy:
- An action to quarantine a package matched by the matching logic.
- An action to tag a package matched by the matching logic.
To create an action to quarantine a package, use the following curl command. This example request specifies the required action_type, sets the quarantined package state via the package_state field, and provides an action precedence value of 1:
curl -X POST "https://api.cloudsmith.io/v2/workspaces/$CLOUDSMITH_WORKSPACE/policies/{POLICY_SLUG}/actions/" \
-H "Content-Type: application/json" \
-H "X-Api-Key: $CLOUDSMITH_API_KEY" \
-d '{ "action_type": "SetPackageState", "precedence": 1, "package_state": "QUARANTINED" }'A successful request will return an HTTP 201 response, with the unique identifier of the action returned in the slug_perm field.
To create an action to tag a matched package, use the following curl command. This request specifies the required action_type, the relevant tag in the tags array, and a precedence value of 32767:
curl -X POST "https://api.cloudsmith.io/v2/workspaces/$CLOUDSMITH_WORKSPACE/policies/{POLICY_SLUG}/actions/" \
-H "Content-Type: application/json" \
-H "X-Api-Key: $CLOUDSMITH_API_KEY" \
-d '{ "action_type": "AddPackageTags", "precedence": 32767, "tags": ["policy-violated"] }'6. Test the policy
Before enabling a policy, test it with the Workspaces Policies Simulate List endpoint.
The endpoint evaluates your policy against all packages in the workspace and returns a decision log for each evaluation, without applying any actions. This lets you confirm whether the policy behaves as expected before enabling it. To use the simulator, you will need the policy's unique identifier.
7. Enable the policy
Once you confirm the policy works as expected, you can enable it by setting enabled to true via the Workspaces Policies Partial Update endpoint.
Enabling the policy means it will run matching logic against packages and apply any associated actions (in this example, quarantining and tagging) to packages that are matched.
curl -X PATCH "https://api.cloudsmith.io/v2/workspaces/$CLOUDSMITH_WORKSPACE/policies/{POLICY_SLUG}/" \
-H "Content-Type: application/json" \
-H "X-Api-Key: $CLOUDSMITH_API_KEY" \
-d '{"enabled": true}'Create a policy via the Cloudsmith Terraform provider
You can manage policies as code by using the cloudsmith_policy and cloudsmith_policy_action resources, and the cloudsmith_policy and cloudsmith_policy_list data sources in the Cloudsmith Terraform provider.