You're viewing documentation for Anthos Config Management 1.4. This version has reached end of life and is no longer supported. View the latest documentation.

Using Policy Controller in a CI pipeline

This page describes how to integrate Policy Controller with Cloud Build by creating a Continuous Integration (CI) pipeline that checks policy validations synchronized with a Git repository.

If you are a developer and want to validate your app against company policies, read Validating your app against company policies in a continuous integration pipeline instead.


Creating a CI pipeline with Policy Controller allows you to:

  • Enforce defined policy configurations and provide feedback to developers as soon as possible. Policies allow platform admins to lock down access. Development teams must then comply with those policies rather than removing or circumventing them.

  • Set default fields on your Kubernetes Objects that should always be present. For example, you can automatically add labels for owners or cost center.

This document focuses on a Cloud Build CI pipeline using a GitHub config repository. You can use the same pattern to set up other CI tools or version control systems supported by Anthos Config Management.

This pipeline is built with KPT functions. KPT functions enable you to develop client-side container images to validate, transform, or generate Kubernetes configurations.

This topic uses pre-built KPT functions from the KPT Functions Catalog. A subset of the functions in the Catalog has been mirrored to a Google-supported Container Registry and is available to all projects.

Before you begin

  • You must have an Anthos entitlement to install Policy Controller using Anthos Config Management.

  • You need a cluster with Config Sync already installed.

  • Set up Policy Controller.

  • Have permission on your Google Cloud project, and have permission on the Cloud Build API. These permissions are required to enable the Cloud Build service account, see more details at Enabling APIs.

  • Enable Cloud Build in your project. This can be done through the Google Cloud Console.

Using an unstructured repo

This tutorial includes the option to use an unstructured repo. Unstructured repos do not require the default Anthos Config Management directory structure.

Configuring Cloud Build

You must grant the "Kubernetes Engine Developer" role to the Cloud Build service account in each Project where you configure the pipeline.

  1. Open the Cloud Build Settings page

    The Service account permissions page appears.

  2. Find the row that contains Kubernetes Engine and set the Status to Enabled.

For more information, see Setting service account permissions.

Setting up your environment

To configure Policy Controller to work with Cloud Build, see the example Git repo.

Clone the repo with git.

git clone

If you are using a hierarchical repo, you must edit configuration files in this repo after setting up Cloud Build.

Directory structure

In the repo csp-config-management, there are two directories that contain configs for a hierarchical repo (ci-pipeline/) and an unstructured repo (ci-pipeline-unstructured/). Choose the appropriate directory for your cluster type.

The ci-pipeline/ and ci-pipeline-unstructured/ directories in the repo use the following hierarchy:

  • config-root/ is the root of the repo and contains all of the configs for this example.

  • config-root/.../*-constraint.yaml and *-template.yaml define Policy Controller constraints and templates which all configs in config-root/ must pass.

    For example:

    • The file ci-pipeline/config-root/cluster/required-labels-constraint.yaml requires that each namespace must have a cost-center label.

    • The file ci-pipeline-unstructured/config-root/constraints/banned-key-constraint.yaml enforces that no ConfigMap Objects contain a field named private-key.

    For more information, see Creating constraints.

  • cloudbuild.yaml is the Cloud Build configuration file that defines build steps. These build steps are triggered by a commit to the repo.

    Using a hierarchical repo, the pipeline builds the contents of your repo with nomos hydrate, concatenates them, and validates them with Policy Controller.

    In an unstructured repo, Policy Controller builds your configuration without using nomos or connecting to your cluster.

    For more information on the contents of a configuration file, see Creating a basic configuration.

Configuring Cloud Build

In this section, you connect Cloud Build to your source repository so that Cloud Build can build the code in that repository.

Creating a build trigger

Cloud Build executes build triggers when a commit is pushed to the branch. To configure a build trigger in Google Cloud Console, perform the following steps.

  1. Open the Triggers page in the Google Cloud Console.

    Open the Triggers page

  2. Select your project from the project selector drop-down menu at the top of the page.

  3. Click Open.

  4. Click Create trigger.

  5. Create a Name for your trigger.

  6. For Event, select Push to a branch.

  7. Select your Repository. If you have not connected your repository, complete the following steps:

    1. Click Connect Repository.

    2. Select the repository where you've stored your source code.

      If you select GitHub (mirrored) or Bitbucket (mirrored) as your source repository, Cloud Build mirrors your repository in Cloud Source Repositories and uses the mirrored repository.

    3. Click Continue.

    4. Authenticate to your source repository with your username and password.

    5. From the list of available repositories, select the desired repository, then click Connect repository.

  8. From the list of available repositories, select the repository csp-config-management.

  9. Select your Branch, master.

  10. Under Build Configuration, set your Cloud Build Configuration File as ci-pipeline/cloudbuild.yaml or ci-pipeline-unstructured/cloudbuild.yaml.

  11. Click Create to save your build trigger.

You can also create build triggers with gcloud. For more information, see Creating and managing build triggers.

Configuring your repo

After Cloud Build is configured to connect to your repo, complete your configuration for Anthos Config Management.

  1. Edit the file csp-config-management/CODEOWNERS and replace @OWNER with your GitHub username or the email alias of the platform admin team. To learn more about the CODEOWNERS syntax, see About codeowners.

Select if you are using a hierarchical (default) or unstructured repo below.

  1. Edit the configuration file


    Edit the file csp-config-management/ci-pipeline/cloudbuild.yaml.

    Replace CLUSTER_NAME and ZONE with the cluster name and zone of a GKE cluster with Anthos Config Management and Policy Controller installed.


    No configuration change is necessary with an unstructured repo in this example. Anthos Config Management and Policy Controller validate your repo without connecting to your cluster.

  2. Add and commit your changes to the repo.


    cd ci-pipeline
    git add .
    git commit -m "[COMMIT_MESSAGE]"


    cd ci-pipeline-unstructured
    git add .
    git commit -m "[COMMIT_MESSAGE]"

    After the commit, Cloud Build runs a policy validation on the repo.

  3. Open your Cloud Build history and click the most recent Build.

    The Build Details page appears.

  4. The sample in the csp-config-management repo contains an error.

    Select the most recent build from the top of the list, that includes the icon.

  5. The last step that Cloud Build runs terminates with an error. The error follows.


    Error: Found 1 violations:
    [1] All namespaces must have a cost-center label that points to your division
    name: "shipping-prod"
    path: namespace_shipping-prod.yaml


    Step #2: Error: Found 1 violations:
    [1] The following banned keys are being used in the config map: {"private_key"}
    name: "super-secret"
    path: configmap.yaml

  6. Next, fix the error by editing a file in your repo.


    Edit the file /ci-pipeline/config-root/namespaces/online/shipping-app-backend/shipping-prod/namespace.yaml and set a value for metadata.labels.cost-center. Your namespace.yaml should look like the following:

    apiVersion: v1
    kind: Namespace
      name: shipping-prod
        env: prod
        cost-center: ""
        audit: "true"


    Edit the file /ci-pipeline-unstructured/config-root/configmap.yaml. Change the field named data.private_key to data.public_key. Your edited YAML looks like the following.

    apiVersion: v1
    kind: ConfigMap
      name: super-secret
      namespace: default
      public_key: no secrets here

    Next, commit and push your changes.

    git add .
    git commit -m "[COMMIT_MESSAGE]"
    git push origin [BRANCH]
  7. Open your Cloud Build history and click the most recent Build.

    The Build Details page appears.

  8. Your new build should be Successful.


Problem: My Cloud Build build fails and the history includes the following error.

  [1] KNV1021: No CustomResourceDefinition is defined for the type "" in the cluster.
  Resource types that are not native Kubernetes objects must have a CustomResourceDefinition.

Solution: Confirm your installation of Policy Controller.

What's next