Stay organized with collections Save and categorize content based on your preferences.

Use CIS Kubernetes Benchmark policy constraints

Policy Controller comes with a default library of constraint templates that can be used with the CIS bundle to audit the compliance of your cluster against the CIS Kubernetes Benchmark. This benchmark is a set of recommendations for configuring Kubernetes to support a strong security posture.

This bundle of constraints addresses and enforces policies in the following domains:

  • RBAC and service accounts
  • Pod Security Policies
  • Network policies and CNI
  • Secrets management
  • General policies

These have not yet been certified by CIS.

The bundle includes these constraints to satisfy corresponding controls in the CIS benchmark:

Constraint Control ID Control description Referential
psp-privileged-container 5.2.1 Minimize the admission of privileged containers No
psp-host-namespace 5.2.2 Minimize the admission of containers wanting to share the host process ID namespace No
5.2.3 Minimize the admission of containers wanting to share the host IPC namespace No
psp-host-network-ports 5.2.4 Minimize the admission of containers wanting to share the host network namespace No
psp-allow-privilege-escalation-container 5.2.5 Minimize the admission of containers with allowPrivilegeEscalation No
psp-pods-must-run-as-nonroot 5.2.6 Minimize the admission of root containers No
psp-capabilities 5.2.7 Minimize the admission of containers with the NET_RAW capability No
5.2.8 Minimize the admission of containers with added capabilities No
5.2.9 Minimize the admission of containers with capabilities assigned No
require-namespace-network-policies 5.3.2 Ensure that all namespaces have Network Policies defined Yes
no-secrets-as-env-vars 5.4.1 Prefer using Secrets as files over Secrets as environment variables No
psp-seccomp-default 5.7.2 Ensure that the seccomp profile is set to docker/default in your Pod definitions No
pods-require-security-context 5.7.3 Apply Security Context to your Pods and containers No

Before you begin

  1. Install and initialize the Google Cloud CLI, which provides the gcloud and kubectl commands used in these instructions. If you use Cloud Shell, Google Cloud CLI comes pre-installed.
  2. Install Policy Controller on your cluster with the default library of constraint templates. You must also enable support for referential constraints, as this bundle contains referential constraints, which are listed in the overview table.

Configure Policy Controller for referential constraints

  1. Save the following YAML manifest to a file as policycontroller-config.yaml. The manifest configures Policy Controller to watch specific kinds of objects.

    apiVersion: config.gatekeeper.sh/v1alpha1
    kind: Config
    metadata:
      name: config
      namespace: "gatekeeper-system"
    spec:
      sync:
        syncOnly:
          - group: ""
            version: "v1"
            kind: "Namespace"
          - group: "networking.k8s.io"
            version: "v1"
            kind: "NetworkPolicy"
    
  2. Apply the policycontroller-config.yaml manifest:

    kubectl apply -f policycontroller-config.yaml
    

Audit CIS policies with Policy Controller

Policy Controller lets you enforce policies for your Kubernetes cluster. To help test your workloads and their compliance with regard to the CIS policies outlined in the preceding table, you can deploy these constraints in "audit" mode to reveal violations and more importantly give yourself a chance to fix them before enforcing on your Kubernetes cluster.

You can apply these policies with spec.enforcementAction set to dryrun using kubectl, kpt, or Config Sync.

kubectl

  1. (Optional) Preview the policy constraints with kubectl:

    kubectl kustomize https://github.com/GoogleCloudPlatform/acm-policy-controller-library.git/bundles/cis-k8s-v1.5.1
    
  2. Apply the policy constraints with kubectl:

    kubectl apply -k https://github.com/GoogleCloudPlatform/acm-policy-controller-library.git/bundles/cis-k8s-v1.5.1
    

    The output is the following:

    k8snoenvvarsecrets.constraints.gatekeeper.sh/cis-k8s-v1.5.1-no-secrets-as-env-vars created
    k8spspallowprivilegeescalationcontainer.constraints.gatekeeper.sh/cis-k8s-v1.5.1-psp-allow-privilege-escalation created
    k8spspallowedusers.constraints.gatekeeper.sh/cis-k8s-v1.5.1-psp-pods-must-run-as-nonroot created
    k8spspcapabilities.constraints.gatekeeper.sh/cis-k8s-v1.5.1-psp-capabilities created
    k8spsphostnamespace.constraints.gatekeeper.sh/cis-k8s-v1.5.1-psp-host-namespace created
    k8spsphostnetworkingports.constraints.gatekeeper.sh/cis-k8s-v1.5.1-psp-host-network-ports created
    k8spspprivilegedcontainer.constraints.gatekeeper.sh/cis-k8s-v1.5.1-psp-privileged-container created
    k8spspseccomp.constraints.gatekeeper.sh/cis-k8s-v1.5.1-psp-seccomp-default created
    k8spodsrequiresecuritycontext.constraints.gatekeeper.sh/cis-k8s-v1.5.1-pods-require-security-context created
    k8sprohibitrolewildcardaccess.constraints.gatekeeper.sh/cis-k8s-v1.5.1-prohibit-role-wildcard-access created
    k8srequirenamespacenetworkpolicies.constraints.gatekeeper.sh/cis-k8s-v1.5.1-require-namespace-network-policies created
    k8srestrictrolebindings.constraints.gatekeeper.sh/cis-k8s-v1.5.1-restrict-clusteradmin-rolebindings created
    
  3. Verify that policy constraints have been installed and check if violations exist across the cluster:

    kubectl get -k https://github.com/GoogleCloudPlatform/acm-policy-controller-library.git/bundles/cis-k8s-v1.5.1
    

    The output is similar to the following:

    NAME                                                                                 ENFORCEMENT-ACTION   TOTAL-VIOLATIONS
    k8snoenvvarsecrets.constraints.gatekeeper.sh/cis-k8s-v1.5.1-no-secrets-as-env-vars   dryrun               0
    
    NAME                                                                                                              ENFORCEMENT-ACTION   TOTAL-VIOLATIONS
    k8spspallowprivilegeescalationcontainer.constraints.gatekeeper.sh/cis-k8s-v1.5.1-psp-allow-privilege-escalation   dryrun               0
    
    NAME                                                                                       ENFORCEMENT-ACTION   TOTAL-VIOLATIONS
    k8spspallowedusers.constraints.gatekeeper.sh/cis-k8s-v1.5.1-psp-pods-must-run-as-nonroot   dryrun               0
    
    NAME                                                                           ENFORCEMENT-ACTION   TOTAL-VIOLATIONS
    k8spspcapabilities.constraints.gatekeeper.sh/cis-k8s-v1.5.1-psp-capabilities   dryrun               0
    
    NAME                                                                              ENFORCEMENT-ACTION   TOTAL-VIOLATIONS
    k8spsphostnamespace.constraints.gatekeeper.sh/cis-k8s-v1.5.1-psp-host-namespace   dryrun               0
    
    NAME                                                                                        ENFORCEMENT-ACTION   TOTAL-VIOLATIONS
    k8spsphostnetworkingports.constraints.gatekeeper.sh/cis-k8s-v1.5.1-psp-host-network-ports   dryrun               0
    
    NAME                                                                                          ENFORCEMENT-ACTION   TOTAL-VIOLATIONS
    k8spspprivilegedcontainer.constraints.gatekeeper.sh/cis-k8s-v1.5.1-psp-privileged-container   dryrun               0
    
    NAME                                                                         ENFORCEMENT-ACTION   TOTAL-VIOLATIONS
    k8spspseccomp.constraints.gatekeeper.sh/cis-k8s-v1.5.1-psp-seccomp-default   dryrun               0
    
    NAME                                                                                                   ENFORCEMENT-ACTION   TOTAL-VIOLATIONS
    k8spodsrequiresecuritycontext.constraints.gatekeeper.sh/cis-k8s-v1.5.1-pods-require-security-context   dryrun               0
    
    NAME                                                                                                   ENFORCEMENT-ACTION   TOTAL-VIOLATIONS
    k8sprohibitrolewildcardaccess.constraints.gatekeeper.sh/cis-k8s-v1.5.1-prohibit-role-wildcard-access   dryrun               0
    
    NAME                                                                                                             ENFORCEMENT-ACTION   TOTAL-VIOLATIONS
    k8srequirenamespacenetworkpolicies.constraints.gatekeeper.sh/cis-k8s-v1.5.1-require-namespace-network-policies   dryrun               0
    
    NAME                                                                                                  ENFORCEMENT-ACTION   TOTAL-VIOLATIONS
    k8srestrictrolebindings.constraints.gatekeeper.sh/cis-k8s-v1.5.1-restrict-clusteradmin-rolebindings   dryrun               0
    

kpt

  1. Install and setup kpt. kpt is used in these instructions to customize and deploy Kubernetes resources.

  2. Download the CIS policy bundle from GitHub using kpt:

    kpt pkg get https://github.com/GoogleCloudPlatform/acm-policy-controller-library.git/bundles/cis-k8s-v1.5.1
    
  3. Run the set-enforcement-action kpt function to set the policies' enforcement action to dryrun:

    kpt fn eval cis-k8s-v1.5.1 -i gcr.io/kpt-fn/set-enforcement-action:v0.1 \
      -- enforcementAction=dryrun
    
  4. Initialize the working directory with kpt, which creates a resource to track changes:

    cd cis-k8s-v1.5.1
    kpt live init
    
  5. Apply the policy constraints with kpt:

    kpt live apply
    

    The output is the following:

    k8spspseccomp.constraints.gatekeeper.sh/psp-seccomp-docker-default created
    k8spodsrequiresecuritycontext.constraints.gatekeeper.sh/pods-require-security-context created
    k8sprohibitrolewildcardaccess.constraints.gatekeeper.sh/prohibit-role-wildcard-access created
    k8srequirenamespacenetworkpolicies.constraints.gatekeeper.sh/require-namespace-network-policies created
    k8snoenvvarsecrets.constraints.gatekeeper.sh/no-secrets-as-env-vars created
    k8spspallowprivilegeescalationcontainer.constraints.gatekeeper.sh/psp-allow-privilege-escalation-container created
    k8spspallowedusers.constraints.gatekeeper.sh/psp-pods-must-run-as-nonroot created
    k8spsphostnetworkingports.constraints.gatekeeper.sh/psp-host-network-ports created
    k8srestrictrolebindings.constraints.gatekeeper.sh/restrict-clusteradmin-rolebindings created
    k8spspcapabilities.constraints.gatekeeper.sh/psp-capabilities created
    k8spsphostnamespace.constraints.gatekeeper.sh/psp-host-namespace created
    k8spspprivilegedcontainer.constraints.gatekeeper.sh/psp-privileged-container created
    13 resource(s) applied. 13 created, 0 unchanged, 0 configured, 0 failed
    
  6. Verify that policy constraints have been installed and check if violations exist across the cluster:

    kpt live status --output table --poll-until current
    

    A status of CURRENT confirms successful installation of the constraints.

Config Sync

  1. Install and setup kpt. kpt is used in these instructions to customize and deploy Kubernetes resources.

  2. If you are using Anthos Config Management for the first time, enable Anthos Config Management.

Operators using Config Sync to deploy policies to their clusters can use the following instructions:

  1. Change into the sync directory for Config Sync:

    cd SYNC_ROOT_DIR
    
  2. Create a dedicated policies directory:

    mkdir -p policies
    
  3. Download the CIS policy bundle from GitHub using kpt:

    kpt pkg get https://github.com/GoogleCloudPlatform/acm-policy-controller-library.git/bundles/cis-k8s-v1.5.1 policies/cis-k8s-v1.5.1
    
  4. Run the set-enforcement-action kpt function to set the policies' enforcement action to dryrun:

    kpt fn eval policies/cis-k8s-v1.5.1 -i gcr.io/kpt-fn/set-enforcement-action:v0.1 -- enforcementAction=dryrun
    
  5. (Optional) Preview the policy constraints that will be created:

    kpt live init policies/cis-k8s-v1.5.1
    kpt live apply --dry-run policies/cis-k8s-v1.5.1
    

    The output is the following:

    Dry-run strategy: client
    inventory update started
    inventory update finished
    apply phase started
    k8snoenvvarsecrets.constraints.gatekeeper.sh/cis-k8s-v1.5.1-no-secrets-as-env-vars apply successful
    k8spspallowprivilegeescalationcontainer.constraints.gatekeeper.sh/cis-k8s-v1.5.1-psp-allow-privilege-escalation apply successful
    k8spspallowedusers.constraints.gatekeeper.sh/cis-k8s-v1.5.1-psp-pods-must-run-as-nonroot apply successful
    k8spspcapabilities.constraints.gatekeeper.sh/cis-k8s-v1.5.1-psp-capabilities apply successful
    k8spsphostnamespace.constraints.gatekeeper.sh/cis-k8s-v1.5.1-psp-host-namespace apply successful
    k8spsphostnetworkingports.constraints.gatekeeper.sh/cis-k8s-v1.5.1-psp-host-network-ports apply successful
    k8spspprivilegedcontainer.constraints.gatekeeper.sh/cis-k8s-v1.5.1-psp-privileged-container apply successful
    k8spspseccomp.constraints.gatekeeper.sh/cis-k8s-v1.5.1-psp-seccomp-default apply successful
    k8spodsrequiresecuritycontext.constraints.gatekeeper.sh/cis-k8s-v1.5.1-pods-require-security-context apply successful
    k8sprohibitrolewildcardaccess.constraints.gatekeeper.sh/cis-k8s-v1.5.1-prohibit-role-wildcard-access apply successful
    k8srequirenamespacenetworkpolicies.constraints.gatekeeper.sh/cis-k8s-v1.5.1-require-namespace-network-policies apply successful
    k8srestrictrolebindings.constraints.gatekeeper.sh/cis-k8s-v1.5.1-restrict-clusteradmin-rolebindings apply successful
    apply phase finished
    inventory update started
    inventory update finished
    apply result: 12 attempted, 12 successful, 0 skipped, 0 failed
    
  6. If your sync directory for Config Sync uses Kustomize, add policies/cis-k8s-v1.5.1 to your root kustomization.yaml. Otherwise remove the policies/cis-k8s-v1.5.1/kustomization.yaml file:

    rm SYNC_ROOT_DIR/policies/cis-k8s-v1.5.1/kustomization.yaml
    
  7. Push changes to the Config Sync repo:

    git add SYNC_ROOT_DIR/policies/cis-k8s-v1.5.1
    git commit -m 'Adding CIS policy audit enforcement'
    git push
    
  8. Verify the status of the installation:

    watch gcloud beta container fleet config-management status --project PROJECT_ID
    

    A status of SYNCED confirms the installation of the policies.

View policy violations

Once the policy constraints are installed in audit mode, violations on the cluster can be viewed in the UI using the Policy Controller Dashboard.

You can also use kubectl to view violations on the cluster using the following command:

kubectl get constraint -l policycontroller.gke.io/bundleName=cis-k8s-v1.5.1 -o json | jq -cC '.items[]| [.metadata.name,.status.totalViolations]'

If violations are present, a listing of the violation messages per constraint can be viewed with:

kubectl get constraint -l policycontroller.gke.io/bundleName=cis-k8s-v1.5.1 -o json | jq -C '.items[]| select(.status.totalViolations>0)| [.metadata.name,.status.violations[]?]'

Enforce CIS policies

Once you've reviewed policy violations on your cluster, the next step is to enforce these policies so that the Admission Controller blocks any non-compliant resource from getting applied to the cluster.

kubectl

  1. Use kubectl to set the policies' enforcement action to deny:

    kubectl get constraint -l policycontroller.gke.io/bundleName=cis-k8s-v1.5.1 -o json | jq '.items[].spec.enforcementAction="deny"' | kubectl apply -f -
    
  2. Verify that policy constraints enforcement action have been updated:

    kubectl get -k https://github.com/GoogleCloudPlatform/acm-policy-controller-library.git/bundles/cis-k8s-v1.5.1
    

kpt

  1. Run the set-enforcement-action kpt function to set the policies' enforcement action to deny:

    kpt fn eval -i gcr.io/kpt-fn/set-enforcement-action:v0.1 -- enforcementAction=deny
    
  2. Apply the policy constraints:

    kpt live apply
    

Config Sync

Operators using Config Sync to deploy policies to their clusters can use the following instructions:

  1. Change into the sync directory for Config Sync:

    cd SYNC_ROOT_DIR
    
  2. Run the set-enforcement-action kpt function to set the policies' enforcement action to deny:

    kpt fn eval policies/cis-k8s-v1.5.1 -i gcr.io/kpt-fn/set-enforcement-action:v0.1 -- enforcementAction=deny
    
  3. Push changes to the Config Sync repo:

    git add SYNC_ROOT_DIR/policies/cis-k8s-v1.5.1
    git commit -m 'Enforcing CIS policies for GKE'
    git push
    
  4. Verify the status of the installation:

    gcloud alpha anthos config sync repo list --project PROJECT_ID
    

    Your repo showing up in the SYNCED column confirms the installation of the policies.

Test policy enforcement

Perform a quick test to confirm the policy enforcement and blocking of non-compliant resources on the cluster.

Create a non-compliant resource on the cluster using the following command:

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  namespace: default
  name: wp-non-compliant
  labels:
    app: wordpress
spec:
  containers:
    - image: wordpress
      name: wordpress
      ports:
      - containerPort: 80
        name: wordpress
EOF

The admission controller should produce an error listing out the policy violations that this resource violates. For example:

Error from server (Forbidden): error when creating "STDIN": admission webhook "validation.gatekeeper.sh" denied the request:
[cis-k8s-v1.5.1-psp-pods-must-run-as-nonroot] Container wordpress is attempting to run without a required securityContext/runAsNonRoot or securityContext/runAsUser != 0
[cis-k8s-v1.5.1-psp-allow-privilege-escalation] Privilege escalation container is not allowed: wordpress
[cis-k8s-v1.5.1-psp-seccomp-default] Seccomp profile 'not configured' is not allowed for container 'wordpress'. Found at: no explicit profile found. Allowed profiles: {"RuntimeDefault", "docker/default", "runtime/default"}
[cis-k8s-v1.5.1-psp-capabilities] container  is not dropping all required capabilities. Container must drop all of ["NET_RAW"] or "ALL"
[cis-k8s-v1.5.1-pods-require-security-context] securityContext must be defined for all Pod containers