Start Building for Free
CircleCI.comAcademyBlogCommunitySupport

Use the CLI and VCS for config policy management

2 weeks ago3 min read
Cloud
On This Page

Use the CircleCI CLI to manage your organization’s policies programmatically. The sub-commands to perform policy management are grouped under the policy command.

The following sub-commands are currently supported within the CLI for configuration policy management:

  • diff - shows the difference between local and remote policy bundles

  • fetch - fetches the policy bundle (or one policy, based on name) from remote

  • push - pushes the policy bundle (activate policy bundle)

    For example, running the following command activates a policy bundle stored at ./policy_bundle_dir_path:

    circleci policy push ./policy_bundle_dir_path --owner-id <your-organization-ID>
  • settings - used to modify config policy management settings as required.

    When the settings sub-command is called without any flags, current settings are fetched and printed on console.

    circleci-cli policy settings --owner-id <your-organization-ID>

    Example output:

    {
      "enabled": false
    }

Create and upload a policy

Follow these steps to create a policy that checks the version of CircleCI config files to ensure it is greater than or equal to 2.1.

  1. Enable config policy management for your organization

    circleci-cli policy settings --enabled=true --owner-id <your-organization-ID>

    Example output:

    {
      "enabled": true
    }
  2. Create a policy file in an empty directory. For example:

    mkdir ./config-policies
  3. Inside your new directory create a Rego file for our new policy, for example, version.rego.

  4. Add the following content to version.rego:

    # All policies start with the org package definition
    package org
    
    policy_name["example"]
    
    # signal to circleci that check_version is enabled and must be included when making a decision
    enable_rule["check_version"]
    
    # signal to circleci that check_version is a hard_failure condition and that builds should be
    # stopped if this rule is not satisfied.
    hard_fail["check_version"]
    
    # define check version
    check_version = reason {
        not input.version # check the case where version is not in the input
        reason := "version must be defined"
    } {
        not is_number(input.version) # check that version is number
        reason := "version must be a number"
    } {
        not input.version >= 2.1 # check that version is at least 2.1
        reason := sprintf("version must be at least 2.1 but got %s", [input.version])
    }
  5. Upload your policy to your organization:

    circleci-cli policy push ./config-policies --owner-id <your-organization-ID>

    Now, when a pipeline is triggered within your organization, the project’s .circleci/config.yml will be validated against this policy.

Update a policy

To illustrate making a change to an existing policy, suppose you made an error when creating the policy above. You realise that configs in your organization are using CircleCI config version 2.0 and you want your policy to reflect this.

  1. Change the rule definition in your version.rego file:

    {
        not input.version >= 2.0 # check that version is at least 2.0
        reason := sprintf("version must be at least 2.0 but got %s", [input.version])
    }
  2. Push the policy directory containing the updated policy file using the CLI (verify the diff, and choose yes when prompted):

    circleci-cli policy push ./config-policies --owner-id <your-organization-ID>

Enable or disable policy evaluation for an organization

Control whether policy evaluation is applied to pipeline configurations within your organization using the --enabled flag.

  • If --enabled is set to true, project configurations will be evaluated against your organization’s policies when pipelines are triggered.

  • If --enabled is set to false, project configurations will not be evaluated against your organization’s policies when pipelines are triggered.

circleci-cli policy settings --enabled=true --owner-id <your-organization-ID>

Example output:

{
  "enabled": true
}

Manage policies with your VCS

CircleCI policies are managed by pushing directories of policies to CircleCI via the CLI. The recommended method for managing your policy directory is by storing them in a repository in your VCS, within your organization. This is how policies are managed internally at CircleCI. Pushing policy bundles is done by triggering CircleCI pipelines.

We recommend creating a bot account for pushing policies, and using its associated CircleCI personal API token for authentication. For maximum security the token should be stored as an environment variable within a context, and that context should be restricted to groups that are responsible for managing policies. For more information, see the Using Contexts page.

Set up a config policy management CI pipeline

  1. Set up repository in your VCS to manage policies.

  2. Create a directory for your Rego policy files, for example:

    mkdir ./config-policies
  3. Create a .circleci/config.yml file for your policies repository, and copy and paste the config example below. This example pushes policies to CircleCI on commits to the main branch, and shows a diff of the policy bundle on commits to all other branches:

    version: 2.1
    
    orbs:
      circleci-cli: circleci/circleci-cli@0.1.9 # Use orb to make the `circleci-cli/default` executor available for running jobs
    
    workflows:
      main-workflow:
        jobs:
          - diff-policy-bundle:
              context: <my-context>
              filters:
                branches:
                  ignore: main # on all branches other than main
          - push-policy-bundle:
              context: <my-context>
              filters:
                branches:
                  only: main # only on the main branch
    
    jobs:
      diff-policy-bundle:
        executor: circleci-cli/default
        resource_class: small
        steps:
          - checkout
          - run:
              name: Diff policy bundle
              command: circleci policy diff ./config --owner-id $ORG_ID # show a diff of the policy bundle
    
      push-policy-bundle:
        executor: circleci-cli/default
        resource_class: small
        steps:
          - checkout
          - run:
              name: Push policy bundle
              command: circleci policy push ./config --no-prompt --owner-id $ORG_ID # push the policy bundle to CircleCI

Help make this document better

This guide, as well as the rest of our docs, are open source and available on GitHub. We welcome your contributions.

Need support?

Our support engineers are available to help with service issues, billing, or account related questions, and can help troubleshoot build configurations. Contact our support engineers by opening a ticket.

You can also visit our support site to find support articles, community forums, and training resources.