RKE2 Image security Admission Controller

In a previous post we talked about Admission Controllers. In this post I will show you how to use an Admission Controller to test image vulnerabilities.

Parst of the K8S Security series

There is multiple tools to scan vulnerabilities, but less Admission Controller to use them. I found multiple solution for Anchore Engine so the first step is to deploy with its helm chart. In RKE2 I will use Rancher’s Helm controller what is preinstalled. Sadly anchore-enginn run as root so we need to use my predifinde PSP to allow this.

Then we can Deploy an Admission Controller to us this tool to automaticle scann any image deploy in the cluster and reject if is vulnerable. As I sad before there is multiple solution for this one is Anchore’s own Admission Controller but I will use Banzaicloud’s solution because this is more flexible.

nano /var/lib/rancher/rke2/server/manifests/10_image-security.yaml
---
apiVersion: v1
kind: Namespace
metadata:
  name: securty-system
---
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
  name: anchore-enginn
  namespace: kube-system
spec:
  repo: "https://charts.anchore.io"
  chart: anchore-engine
  targetNamespace: securty-system
  valuesContent: |-
     postgresql:
       postgresPassword: Password1
       persistence:
         size: 10Gi
     anchoreGlobal:
       defaultAdminPassword: Password1
       defaultAdminEmail: devopstales@mydomain.intra
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: psp-rolebinding-securty-system
  namespace: securty-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system-unrestricted-psp-role
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: system:serviceaccounts
---
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
  name: anchore-policy-validator
  namespace: kube-system
spec:
  repo: "https://kubernetes-charts.banzaicloud.com"
  chart: anchore-policy-validator
  targetNamespace: securty-system
  valuesContent: |-
    externalAnchore:
      anchoreHost: "http://anchore-enginn-anchore-engine-api:8228/v1/"
      anchoreUser: admin
      anchorePass: Password1
    rbac:
      psp:
        enabled: true

Test the Admission Controller

kubectl run --image=busybox -- sleep 3600
Error from server: admission webhook "pods.anchore-policy-validator.admission.banzaicloud.com" denied the request: Image failed policy check: busybox
kubectl describe audits busybox1
Name:         busybox1
Namespace:    
Labels:       fakerelease=true
Annotations:  <none>
API Version:  security.banzaicloud.com/v1alpha1
Kind:         Audit
Metadata:
  Creation Timestamp:  2020-11-29T10:20:41Z
  Generation:          1
  Managed Fields:
    API Version:  security.banzaicloud.com/v1alpha1
    Fields Type:  FieldsV1
    fieldsV1:
      f:metadata:
        f:labels:
          .:
          f:fakerelease:
      f:spec:
        .:
        f:action:
        f:image:
        f:releaseName:
        f:resource:
        f:result:
      f:status:
        .:
        f:state:
    Manager:         anchore-image-validator
    Operation:       Update
    Time:            2020-11-29T10:20:41Z
  Resource Version:  39174
  Self Link:         /apis/security.banzaicloud.com/v1alpha1/audits/busybox1
  UID:               1e90c8b0-fffa-45f6-a986-d9fd269f0a83
Spec:
  Action:  reject
  Image:
    Image Digest:  
    Image Name:    
    Image Tag:     
    Last Updated:  
  Release Name:    busybox1
  Resource:        Pod
  Result:
    Image failed policy check: busybox
Status:
  State:  
Events:   <none>

The default policy is deny All Image theat failed on policy check but we can white list a specific image or set createPolicies to true in Banzaicloud’s Helm chart to create default AllowAll Policy.

kubectl apply -f - << EOF
apiVersion: security.banzaicloud.com/v1alpha1
kind:  WhiteListItem
metadata:
  name: busybox1
spec:
  reason: testing
  creator: devopstales-sa
EOF
kubectl run busybox1 --image=busybox -- sleep 3600
pod/busybox1 created
kubectl get whitelistitems -o wide -o=custom-columns=NAME:.metadata.name,CREATOR:.spec.creator,REASON:.spec.reason
NAME       CREATOR          REASON
busybox1   devopstales-sa   testing

kubectl get audits -o wide -o=custom-columns=NAME:.metadata.name,RELEASE:.spec.releaseName,IMAGES:.spec.image,RESULT:.spec.result
NAME       RELEASE    IMAGES                                                  RESULT
busybox1   busybox1   [map[imageDigest: imageName: imageTag: lastUpdated:]]   [Image failed policy check: busybox]