Manage contexts with config policies
On This Page
- Introduction
- Prerequisites
- Define the contexts allowed for a project
- 1. Create your policy
- 2. Update policy with your details
- 3. Push up your policy bundle
- Conclusion
- Use sets and variables
- Define the contexts blocked for a project
- 1. Create your policy
- 2. Update policy with your details
- 3. Push up your policy bundle
- Conclusion
- Define the contexts reserved by a project
- 1. Create your policy
- 2. Update policy with your details
- 3. Push up your policy bundle
- Conclusion
- Define the contexts reserved by a branch
- 1. Create your policy
- 2. Update policy with your details
- 3. Push up your policy bundle
- Conclusion
- Next steps
The config policies feature is available on the Scale Plan and from CircleCI server v4.2. |
Follow this how-to guide to create config policies for managing the use of contexts in your organization. For more information about config policies, see the Config policies overview.
Using server? When using the |
Introduction
Config policies use a decision engine leveraging OPA ( Open Policy Agent) to allow you to specify policies, and return a decision about whether a pipeline’s config complies with those policies. In the strictest case, if a pipeline configuration does not comply with the organisation’s policies, that pipeline will be blocked from triggering until it does comply.
Well-designed secrets management is a delicate balancing act between security and usability. To help with this balance, you can lock down contexts at different levels using config policies.
This how-to guide presents a selection of helpers (CircleCI-specific rego functions) that are likely to be useful for you when writing policies around the use of contexts in your organization.
The contexts helpers covered are as follows:
In the examples on this page, project IDs, branch names, and context names can be supplied using the following types:
-
String
-
Set of strings
-
Array of strings
Prerequisites
-
A CircleCI account connected to a supported VCS.
-
Install/update the CircleCI CLI, and ensure you have authenticated with a token before attempting to use the CLI with config policies. See the Installing the Local CLI page for more information.
-
Ensure you have enabled config policy evaluation for your organization so that project configurations will be evaluated against your organization’s policies when pipelines are triggered:
circleci policy settings --enabled=true --owner-id <your-organization-ID>
Example output:
{ "enabled": true }
To find your organization/user ID, select Organization Settings in the CircleCI web app side bar.
-
It is recommended to run through the Create a policy and Manage policies with your VCS guides first. Best practice is to use a repository within your organization to store and develop your policies. The Manage policies with your VCS guide walks through setting this up and setting up a pipeline for policy development.
-
To use the examples set out on this page, you will need to be using contexts to store secrets. For more information, see the Using contexts page.
Define the contexts allowed for a project
You may want to allow specific projects the use of only certain contexts. For example, you might want to only allow contexts that have EKS-related deployment keys to projects architected to be deployed on EKS using those keys.
To achieve this, use the contexts_allowed_by_project_ids
helper to create a policy to apply this restriction. This helper function accepts project IDs and context names, and prevents the usage of contexts that are not in the allow-list for all specified projects.
1. Create your policy
-
If you have not already done so, create an empty directory to store your policies. For example:
mkdir ./config-policies
-
Create a new file in this directory for your new policy. Name the file
allow_contexts.rego
. -
Copy the following snippet into the
allow_contexts.rego
file you just made:# All policies start with the org package definition package org # import CircleCI specific helper functions import data.circleci.config # Declare a policy name policy_name["contexts_allowed_by_project"] # Declare a rule rule_contexts_allowed_by_project_ids = config.contexts_allowed_by_project_ids( ["<project-ID>"], ["<context-1>","<context-2>"] ) # Enable the rule and choose the hard_fail enforcement level enable_hard["rule_contexts_allowed_by_project_ids"]
Notice the contexts_allowed_by_project_ids
helper is accessed using theconfig
keyword.In the following steps you will replace
<project-ID>
and<context-1>
(and<context-2>
if you choose to use more than one) with your projects and contexts. Theallow_contexts.rego
policy, once uploaded, will restrict your specified project to only have access to the context(s) in your allow-list.
2. Update policy with your details
-
Replace
<project-ID>
with the ID for the project you want to restrict:-
In the CircleCI web app, select Projects from the sidebar, and click the ellipsis (
…
) next to your project, and select Project Settings to locate the Project ID.
-
-
Replace
<context-1>
with the name of the context you want to allow the use of. You can add multiple contexts as an array, or stick with one for now.-
To find a list of your contexts, select Organization settings from the sidebar in the CircleCI web app and then select Contexts from the menu.
-
3. Push up your policy bundle
You can now push your new policy to your organization for it to take effect. You have two options:
-
Push the policy manually using the CLI from your local environment
-
Push your changes to your config policy repository if you are managing policies via your VCS as shown in the Manage policies with your VCS guide.
Conclusion
Once you have pushed your new allow_contexts.rego
policy, if an attempt to trigger a pipeline is made, in which the specified project has access to contexts in the block-list configured in your policy, the pipeline will fail to trigger. Developers will be notified on the dashboard as shown below.
Use sets and variables
In this example, you have hard coded your project IDs and context names into your policy. This hard coding is not ideal as it makes the policies hard to read and understand. A better way is to use sets and variables defined in separate .rego
files. To use this method, follow these steps:
-
Create three files for your contexts and IDs:
project_ids.rego
,project_groups.rego
andcontext_groups.rego
so you end up with the following file structure:├── config-policies/ │ ├── allow_contexts.rego │ ├── project_ids.rego │ ├── project_groups.rego │ ├── context_groups.rego
-
Add the following to your new
.rego
files, and replace IDs and context names shown between< >
with your data as shown in the previous section:-
project_id.rego
# Single application project IDs. Can be automated. my_project_id := “<project-ID>”
-
project_groups.rego
# sets can be used to group variables Front_end_applications := {my_project_id}
-
context_groups.rego
# sets can be used to group variables Front_end_application_contexts := {"<context-1>","<context-2>"}
-
-
You can now rewrite your
allow_policy.rego
policy as follows:# All policies start with the org package definition package org # import CircleCI specific helper functions import data.circleci.config # Declare a policy name policy_name["contexts_allowed_by_sample_project"] # Declare a rule rule_contexts_allowed_by_project_ids = config.contexts_allowed_by_project_ids( Front_end_applications, Front_end_application_contexts ) # Enable the rule and choose the hard_fail enforcement level enable_hard["rule_contexts_allowed_by_project_ids"]
Define the contexts blocked for a project
To add an extra layer of security to secrets management, you may wish to block access to certain contexts for projects that should not have access to their secrets for security or compliance reasons.
Use the contexts_blocked_by_project_ids
helper to create a policy to apply this restriction. This helper function accepts project IDs and context names, and prevents the usage of any contexts in the block-list for all specified projects.
1. Create your policy
-
If you have not already done so, create an empty directory to store your policies. For example:
mkdir ./config-policies
-
Create a new file in this directory for your new policy. Name the file
block_contexts.rego
. -
Copy the following snippet into the
block_contexts.rego
file you just made:# All policies start with the org package definition package org # import CircleCI specific helper functions import data.circleci.config # Declare a policy name policy_name["contexts_blocked_by_sample_project"] # Declare a rule rule_contexts_blocked_by_project_ids = config.contexts_blocked_by_project_ids( ["<project-ID>"], ["<context-1>","<context-2>"] ) # Enable the rule and choose the hard_fail enforcement level enable_hard["rule_contexts_blocked_by_project_ids"]
Notice the contexts_blocked_by_project_ids
helper is accessed using theconfig
keyword.In the following steps you will replace
<project-ID>
and<context-1>
(and<context-2>
if you choose to use more than one) with your projects and contexts. Theblock_contexts.rego
policy, once uploaded, will restrict your specified project so that it will not have access to the context(s) in your block-list.
2. Update policy with your details
-
Replace
<project-ID>
with the ID for the project you want to restrict:-
In the CircleCI web app, select Projects from the sidebar, and click the elipsis (
…
) next to your project. Select Project Settings to locate the Project ID.
-
-
Replace
<context-1>
with the name of the context you want to block the use of. You can add multiple contexts as an array, or stick with one for now.-
To find a list of your contexts, select Organization settings from the sidebar in the CircleCI web app and then select Contexts from the menu.
-
3. Push up your policy bundle
You can now push your new policy to your organization for it to take effect. You have two options:
-
Push the policy manually using the CLI from your local environment, or;
-
Push your changes to your config policy repository if you are managing policies via your VCS as shown in the Manage policies with your VCS guide.
Conclusion
Once you have pushed your new block_contexts.rego
policy, if an attempt to trigger a pipeline is made, in which the specified project has access to contexts in the block-list configured in your policy, the pipeline will fail to trigger. Developers will be notified on the dashboard as shown below.
Define the contexts reserved by a project
You may want to reserve contexts for use by a defined list of projects, blocking the use of those contexts by any project not in the allow-list. One possible use case for this would be locking contexts containing deployment keys to only those applications (projects) that need it. Any app that does not need this access will not be able to access those contexts. Developers will receive a hard fail, and pipelines will fail to trigger.
Use the contexts_reserved_by_project_ids
helper to create a policy to apply this restriction. This helper function accepts project IDs and context names. It prevents the usage of any reserved contexts for projects that are not in the allow-list.
1. Create your policy
-
If you have not already done so, create an empty directory to store your policies. For example:
mkdir ./config-policies
-
Create a new file in this directory for your new policy. Name the file
reserve_contexts.rego
. -
Copy the following snippet into the
reserve_contexts.rego
file you just made:# All policies start with the org package definition package org # import CircleCI specific helper functions import data.circleci.config # Declare a policy name policy_name["reserved_contexts"] # Declare a rule rule_reserve_contexts = config.contexts_reserved_by_project_ids( ["<project-ID-1>","<project-ID-1>"], ["<context-1>","<context-2>"] ) # Enable the rule and choose the hard_fail enforcement level enable_hard["rule_reserve_contexts"]
Notice the contexts_reserved_by_project_ids
helper is accessed using theconfig
keyword.In the following steps you will replace
<project-ID-1>
and<context-1>
(and<project-ID-2>
and<context-2>
if you choose to use more than one) with your projects and contexts. Thereserve_contexts.rego
policy, once uploaded, will restrict your specified context(s) so that they can only be used by the project(s) you have added to the allow-list.
2. Update policy with your details
-
Replace
<project-ID-1>
with the ID for the first project you want to add to the allow-list. You can add multiple project IDs as an array, or stick with one for now:-
In the CircleCI web app, select Projects from the sidebar, and click the elipsis (
…
) next to your project, and select Project Settings to locate the Project ID.
-
-
Replace
<context-1>
with the name of the first context you want to restrict the use of. You can add multiple contexts as an array, or stick with one for now.-
To find a list of your contexts, select Organization settings from the sidebar in the CircleCI web app and then select Contexts from the menu.
-
3. Push up your policy bundle
You can now push your new policy to your organization for it to take effect. You have two options:
-
Push the policy manually using the CLI from your local environment, or;
-
Push your changes to your config policy repository if you are managing policies via your VCS as shown in the Manage policies with your VCS guide.
Conclusion
Once you have pushed your new reserve_contexts.rego
policy, if an attempt to trigger a pipeline is made for a project outside your allow-list, in which the project tries to access contexts in the reserved-list configured in your policy, the pipeline will fail to trigger. Developers will be notified on the dashboard as shown below.
Define the contexts reserved by a branch
You may want to restrict which contexts (and therefore secrets) are available depending on which branch is being built. Using branch-based restrictions, you can manage your application environment in one repository, and lock down the use of secrets to individual branches. For example, you could split up production secrets and development secrets. This allows you to ensure that production secrets cannot be accessed by a build on a development branch.
Use the contexts_reserved_by_branches
helper to define a policy for this use case. This helper function accepts branch names and context names. Only pipelines running on specified branches are allowed access to contexts in the allow-list.
1. Create your policy
-
If you have not already done so, create an empty directory to store your policies. For example:
mkdir ./config-policies
-
Create a new file in this directory for your new policy. Name the file
context_protection.rego
. -
Copy the following snippet into the
context_protection.rego
file you just made:# All policies start with the org package definition package org # import CircleCI specific helper functions import data.circleci.config # Declare a policy name policy_name["prod_context_protection"] # Declare a rule use_prod_context_on_main = config.contexts_reserved_by_branches(["main"], ["<context-1>","<context-2>"] ) # This rule will apply to all projects subscribed in project_groups.rego under policy_restrict_context_access enable_rule["use_prod_context_on_main"]{ policy_restrict_context_access[data.meta.project_id] } hard_fail["use_prod_context_on_main"]
Notice the contexts_reserved_by_branches
helper is accessed using theconfig
keyword. -
Create a second rego file, names
project_groups.rego
to specify an additional restriction on which projects are affected by this rule. Replace<project-ID>
with one of your project IDsproject_groups.rego
# sets can be used to group variables policy_restrict_context_access := <project-ID>
In the following steps you will replace <context-1>
(and <context-2>
if you choose to use more than one) with your context name. The context_protection.rego
policy, once uploaded, will restrict use of your specified context(s) to builds on the main
branch, for projects specified in project_groups.rego
.
2. Update policy with your details
-
Replace
<context-1>
with the name of the context you want to allow the use of. You can add multiple contexts as an array, or stick with one for now.-
To find a list of your contexts, select Organization settings from the sidebar in the CircleCI web app and then select Contexts from the menu.
-
3. Push up your policy bundle
You can now push your new policy to your organization for it to take effect. You have two options:
-
Push the policy manually using the CLI from your local environment, or;
-
Push your changes to your config policy repository if you are managing policies via your VCS as shown in the Manage policies with your VCS guide.
Conclusion
Once you have pushed your new context_protection.rego
policy, if an attempt to trigger a pipeline on a branch other than main
is made, in which production contexts are used, the pipeline will fail to trigger. Developers will also be notified on the dashboard.