CircleCI Field Guide
GitHub Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage
Edit page

Restrict Environment Access

Restrict Environment Access with CircleCI Policy Manager

CircleCI Contexts can be designated for use by environments, and protected in CPM based on the branch.

CircleCI UI showing the reasons the build failed policy and was not executed
CircleCI UI showing the reasons the build failed policy and was not executed

Sample CircleCI Configuration

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
version: 2.1

orbs:
  python: circleci/python@2.1.1

workflows:
  main:
    jobs:
      - python/test
      - deploy:
          name: Deploy Dev
          requires: [ python/test ]
          context: [ cera-boa-dev ] #Feature and Dev work use a dev context available to any branch
      - deploy:
          name: Deploy Production
          requires: [ Deploy Dev ]
          context: [ cera-boa-prod ] #Prod releases use a dedicated context
          filters:
            branches:
              only: [ main, dev123 ] #  Tat should only ever be used on main branch, this is a violation!


#
# Jobs included for valid config, replace with your own.
#

jobs:
  deploy:
    executor: python/default
    steps:
     - run: echo "Hello Governance!"

Sample CircleCI Policy in rego

Apply policy with our CLI.
circleci policy push ./directory --owner-id << ORGANIZATION_UUID >>

You can visit our Policy Playground to test various policy changes.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package org

import future.keywords

# Each file is a single policy
policy_name["prod_context_protection"]

# May activate 1 to many rules
enable_rule["use_prod_context_on_main"] 

# Rules default to SOFT_FAIL/WARNING, but can be a hard_fail/BLOCK
hard_fail["use_prod_context_on_main"]

# Custom rule is a rego function that iterates config.yml object to compare branch with context use.
use_prod_context_on_main[reason] {
  some wfName, workflow in input.workflows
  some job in workflow.jobs 
  some jobName, jobInfo in job
  some context in to_array(jobInfo.context)
 
  # If the job is using any 'prod' contexts
  regex.match("prod",context)
 
  # but is not exclusive to main branch
  not job_is_only_main(jobInfo)
 
  # display this failure reason to user.
  reason := sprintf("You may not use production context: %s outside of main branch. Offending workflow.job: `%s.%s` %s",[context, wfName, job_name(jobName, jobInfo), reason_contact_footer])
}

# Helper functions

# Convert value to aray if it isn't one
to_array(value) := [value] if { not is_array(value) } else := value

# Use `name` if provided, otherwise use key name
job_name(jobName, jobInfo) := jobInfo.name if { jobInfo.name } else := jobName

# returns true if job only has branch.only and it is main
job_is_only_main(job) := true { 
  only := to_array(job.filters.branches.only)
  count(only) == 1
  only[0] == "main"
} else := false

Advanced: Apply Policy as Pipeline

We highly recommend all policy live in a protected repository applied through a strongly managed lifecycle including approvals and automated testing and promotion.

See Policy as Pipeline for guideance.