Policy management

Policy as code

With policy as code (previously known as Enterprise Policy Manager or EPM), you can define, version, and enforce package governance rules for a workspace. Policy as code is built on Open Policy Agent (OPA), a general-purpose policy evaluation engine. OPA uses a declarative language called Rego to express policy logic as code.

Policies are written in Rego, evaluated continuously against packages in your repositories, and actioned automatically when a match is found.

How it works

At a high level, the evaluation workflow is:

  1. An event in Cloudsmith triggers a policy evaluation (for example, a package is uploaded into Cloudsmith).
  2. Package metadata and your Rego policy are passed to the policy evaluation engine.
  3. The engine determines whether the policy matches the package based on the logic in your policy.
  4. If the policy matches, any actions associated with the policy are applied to the package.

Key concepts

Policies

Policies are written in Rego, a declarative language used to define OPA policies. A policy evaluates packages against a set of criteria, such as package metadata, workspace, repository, and security information.

Cloudsmith provides the following templated Rego policies:

Evaluation point

Policies differ in where Cloudsmith evaluates them. The evaluation point determines what data the policy can act on, what outcome it can produce, and whether the package needs to exist in Cloudsmith at all.

  • Index-applicable policies

    Index-applicable policies are evaluated against the repository index. The index includes both packages already cached in your workspace and package versions available from an upstream source that Cloudsmith has not seen before. When an index-applicable policy matches a package version, that version is hidden from the index. Package managers cannot resolve it. Versions that are not already cached are not downloaded, so no package record is created.

    Cooldown policy is currently the only index-applicable policy.

  • Package-applicable policies

    Package-applicable policies require the package to exist in Cloudsmith. Cloudsmith evaluates them in response to a policy trigger, such as a new threat intelligence record being received or a policy being edited, and applies policy actions to the package when the policy matches.

    All policy as code policies other than a cooldown policy are package-applicable.

Policy triggers

The events that cause a policy to be evaluated depend on the evaluation point.

Cloudsmith evaluates package-applicable policies when:

  • A package is added to a repository and goes through package synchronization

  • A package is resynchronized

  • A package is copied from one repository to another

  • A policy or policy action is created, edited, or deleted

  • Cloudsmith receives updated threat intelligence that matches packages in your workspace.

    For more details, see Vulnerability detection and Malicious package detection.

    Note

    Not every threat intelligence update triggers an immediate evaluation. Changes to descriptive fields, such as an advisory's description, credits, references, published date, modified timestamp, or schema version, do not trigger an evaluation on their own. These changes are picked up at the next scheduled evaluation.
  • A fallback scheduled evaluation runs every 24 hours. Any package that has not been evaluated within the last 24 hours is automatically included, closing the gap for packages missed by event-driven triggers or those that rely on a time-based value in their policy logic.

Index-applicable policies are not triggered by events. Cloudsmith evaluates them when it receives a request to download a package.

Policy matching

Policy matching occurs when the policy evaluation engine evaluates a policy against a package to determine whether the package meets the policy's criteria. The evaluation result is returned in the policy output as a boolean: true (matched) or false (unmatched).

Policy actions

Actions are assigned to policies and applied to packages after a match is confirmed. Multiple actions can be associated with a single policy. The following actions are supported:

  • set_state: Controls the state of the package, for example whether to quarantine or delete it. Potential state values are AVAILABLE, DELETED, QUARANTINED, and HIDDEN:

    • AVAILABLE: The package is available for download.
    • DELETED: The package is deleted.
    • QUARANTINED: The package is quarantined.
    • HIDDEN: The package is hidden.

      Note

      The HIDDEN status is applied by Cloudsmith to packages that violate your cooldown policy and are already cached in your workspace.
  • add_package_tags: Adds one or more tags to the matched package.

  • remove_package_tags: Removes one or more tags from the matched package.

Note

If the action is set to quarantine, any request for the affected package returns a 403 Forbidden response.

Policy evaluation behavior

Cloudsmith evaluates all policies that apply to a package in a single evaluation task, so the outcome of that task applies to every policy within it. If the task fails, all policies for that package fail together.

Cloudsmith retries a failed evaluation task up to three times, then stops and records the failure in the policy decision logs.

Policy evaluation currently fails open. A package is not blocked, quarantined, or hidden because an evaluation task failed, and it remains available until it is evaluated successfully.

A package with a failed evaluation task is re-evaluated at the next scheduled fallback evaluation, or in response to another policy trigger, whichever happens first.

Policy precedence

Policy precedence determines the order in which policies are evaluated, from highest to lowest precedence value. All policies are evaluated in a single transaction. Package state and tags are only updated at the end of the transaction, once all policies have been evaluated. If multiple policies match, all of their actions are applied. For conflicting state changes, the last matched policy to execute wins.

Important

Policy precedence applies only to policies as code. Precedence does not apply to standard policies (vulnerability, license, and package deny), which evaluate independently of policy as code.

Terminal policies

When a policy is marked as a terminal policy and that policy matches, no further policies are evaluated. The Terminal setting has no effect on standard policies.

Policy decision logs

Every policy evaluation and its outcome are captured in a decision log. Policy decision logs record the result of each evaluation, including the reason for the decision and any actions taken. Decision logs are created for all evaluations, regardless of whether the package matched.

Policy exemptions

Policy enforcement can create friction with legitimate business needs, such as maintaining legacy applications that depend on packages with known vulnerabilities, or when no patched version of a non-compliant package is available. Policy exemptions allow you to exclude specific packages from policy evaluation.

Policy scope and connected repositories

Policies cannot be scoped to individual connections within a connected repository configuration. What this means depends on the evaluation point.

  • Package-applicable policies

    Packages are cached in the connected repositories, and a policy acts on the package record in the repository where the package resides. That record holds one state, so the policy produces one outcome for every repository that resolves the version through a connection. A package version cannot be quarantined for consumers of one repository and available for consumers of another, even where the policies configured on those repositories differ.

  • Index-applicable policies

    Cloudsmith generates the blended index at the primary repository level rather than by combining per-repository indexes. Within that index, the upstream source of a package version is not available to the policy engine, so enforcement is all or nothing across the configuration. For example, a primary repository with one connection holding packages from public upstreams and one holding internal packages from private upstreams cannot have a cooldown policy applied to the public connection alone.

    included_repositories and excluded_repositories operate on repository slugs, not on connections or the upstream source of a version.