Skip to content

Latest commit

 

History

History
216 lines (193 loc) · 8.94 KB

test-kyverno-policies.md

File metadata and controls

216 lines (193 loc) · 8.94 KB

Test Kyverno policies

This repository defines the following cluster-level policies with Kyverno:

  • Disallow host namespaces (except for calico-system namespace).
  • Disallow hostPath volumes (except for calico-system, tigera-operator and monitoring namespaces).
  • Disallow hostPort(except for calico-system and monitoring namespaces).
  • Disallow privileged containers (except for calico namespace).
  • Disallow usage of the latest image tag.
  • Restrict the image registries images can be pulled from to corporate / defined list of repositories. To modify this list, go to config/base/policies/restrict-image-registries.yaml.
  • Automatically create a NetworkPolicy for new namespaces that denies all ingress traffic by default (this example repository creates network policies necessary or the components that are deployed).

Please visit Kyverno documentation for details on how it works and how policies are defined. Kyverno provides a large set of sample security policies here, including the implementation of Kubernetes Pod Security Standards definitions.

You can execute kubectl get policyreport -A to see a per namespace report of policy status:

kubectl get policyreport -A
NAMESPACE         NAME                      PASS   FAIL   WARN   ERROR   SKIP   AGE
calico-system     polr-ns-calico-system     9      0      0      0       0      5m39s
default           polr-ns-default           0      0      0      0       0      99s
flagger-system    polr-ns-flagger-system    14     0      0      0       0      5m41s
flux-system       polr-ns-flux-system       28     0      0      0       0      5m42s
ingress-nginx     polr-ns-ingress-nginx     7      0      0      0       0      5m42s
monitoring        polr-ns-monitoring        24     0      0      0       0      5m39s
podinfo           polr-ns-podinfo           14     0      0      0       0      5m12s
tigera-operator   polr-ns-tigera-operator   5      0      0      0       0      5m40s

This repository uses Kustomize overlays defined for TEST and PRODUCTION clusters. ClusterPolicies are applied in audit mode for TEST clusters and enforce mode for PRODUCTION clusters.

Example config/production/patch_validation_failure_action.yaml

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: patch-validation-failure-action
spec:
  validationFailureAction: enforce
  background: true

While on audit mode, you can identify resources violating defined policies describing policy reports. To see an example in action, let's create a privileged nginx pod using the latest tag:

   kubectl run test --image=nginx --privileged=true         
   pod/test created

Now, let's describe the policy report for the default namespace. We will see a violation for the disallow-latest-tag policy as well as the privileged-containers policy:

   kubectl describe policyreport polr-ns-default
   Name:         polr-ns-default
   Namespace:    default
   Labels:       <none>
   Annotations:  <none>
   API Version:  wgpolicyk8s.io/v1alpha1
   Kind:         PolicyReport
   [...]
   Results:
     Category:  Best Practices
     Message:   validation error: An image tag is required. Rule require-image-tag failed at path /spec/containers/0/image/
     Policy:    disallow-latest-tag
     Resources:
       API Version:  v1
       Kind:         Pod
       Name:         test
       Namespace:    default
       UID:          abcf96f5-6695-4ae1-bcbe-b98e4f127157
     Rule:           require-image-tag
     Scored:         true
     Severity:       medium
     Status:         fail
     Category:       Best Practices
     Message:        validation rule 'validate-image-tag' passed.
     Policy:         disallow-latest-tag
     Resources:
       API Version:  v1
       Kind:         Pod
       Name:         test
       Namespace:    default
       UID:          abcf96f5-6695-4ae1-bcbe-b98e4f127157
     Rule:           validate-image-tag
     Scored:         true
     Severity:       medium
     Status:         pass
     Category:       Pod Security Standards (Baseline)
     Message:        validation rule 'host-path' passed.
     Policy:         disallow-host-path
     Resources:
       API Version:  v1
       Kind:         Pod
       Name:         test
       Namespace:    default
       UID:          abcf96f5-6695-4ae1-bcbe-b98e4f127157
     Rule:           host-path
     Scored:         true
     Severity:       medium
     Status:         pass
     Category:       Pod Security Standards (Baseline)
     Message:        validation rule 'host-namespaces' passed.
     Policy:         disallow-host-namespaces
     Resources:
       API Version:  v1
       Kind:         Pod
       Name:         test
       Namespace:    default
       UID:          abcf96f5-6695-4ae1-bcbe-b98e4f127157
     Rule:           host-namespaces
     Scored:         true
     Severity:       medium
     Status:         pass
     Category:       Pod Security Standards (Baseline)
     Message:        validation error: Privileged mode is disallowed. The fields spec.containers[*].securityContext.privileged and spec.initContainers[*].securityContext.privileged must not be set    to true.          . Rule priviledged-containers failed at path /spec/containers/0/securityContext/privileged/
     Policy:         disallow-privileged-containers
     Resources:
       API Version:  v1
       Kind:         Pod
       Name:         test
       Namespace:    default
       UID:          abcf96f5-6695-4ae1-bcbe-b98e4f127157
     Rule:           priviledged-containers
     Scored:         true
     Severity:       medium
     Status:         fail
     Category:       Best Practices
     Message:        validation error: Unknown image registry. Rule validate-registries failed at path /spec/containers/0/image/
     Policy:         restrict-image-registries
     Resources:
       API Version:  v1
       Kind:         Pod
       Name:         test
       Namespace:    default
       UID:          abcf96f5-6695-4ae1-bcbe-b98e4f127157
     Rule:           validate-registries
     Scored:         true
     Severity:       medium
     Status:         fail
     [...]
  Summary:
    Error:  0
    Fail:   3
    Pass:   4
    Skip:   0
    Warn:   0
  Events:   <none>

If your cluster is sync'ing the PRODUCTION configuration, Kyverno has been configured to enforce the policies, so you'll get an error when trying to create the pod. You can see an example below:

  kubectl run test --image=nginx --privileged=true 
  Error from server: admission webhook "validate.kyverno.svc" denied the request: 
  
  resource Pod/nginx/test was blocked due to the following policies
  
  disallow-latest-tag:
    require-image-tag: 'validation error: An image tag is required. Rule require-image-tag
      failed at path /spec/containers/0/image/'
  disallow-privileged-containers:
    priviledged-containers: 'validation error: Privileged mode is disallowed. The fields
      spec.containers[*].securityContext.privileged and spec.initContainers[*].securityContext.privileged
      must not be set to true.          . Rule priviledged-containers failed at path
      /spec/containers/0/securityContext/privileged/'
  restrict-image-registries:
    validate-registries: 'validation error: Unknown image registry. Rule validate-registries
      failed at path /spec/containers/0/image/'

There's also a mutate policy configured to create a Network Policy blocking ingress traffic to all the namespaces created. To test it, run the following command to create a namespace:

kubectl create namespace test

Now, run the following command to see the Network policies on the namespace:

kubectl get networkpolicy -n test

You'll see a similar output to the following:

apiVersion: v1
items:
- apiVersion: networking.k8s.io/v1
  kind: NetworkPolicy
  metadata:
    creationTimestamp: "2021-11-17T14:25:30Z"
    generation: 1
    labels:
      app.kubernetes.io/managed-by: kyverno
      kyverno.io/generated-by-kind: Namespace
      kyverno.io/generated-by-name: test
      kyverno.io/generated-by-namespace: ""
      policy.kyverno.io/gr-name: gr-qz7d6
      policy.kyverno.io/policy-name: add-networkpolicy-deny-ingress
      policy.kyverno.io/synchronize: enable
    name: default-deny
    namespace: test
    resourceVersion: "68689"
    uid: c27b5426-5e55-4a02-9f0f-a2aa30d53e45
  spec:
    podSelector: {}
    policyTypes:
    - Ingress
kind: List
metadata:
  resourceVersion: ""
  selfLink: ""

Explore the Kyverno documentation to learn more about how it works. Alternatively, go to Flagger Canary deployments to learn about hoe flagger enables progressive deployments in this sample.