RKE2 Image security Admission Controller

Page content

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.

Parts of the K8S Security Lab series

Container Runetime Security
Advanced Kernel Security
Network Security
Secure Kubernetes Install
User Security
Image Security
  • Part1: Image security Admission Controller
  • Part2: Image security Admission Controller V2
  • Part3: Image security Admission Controller V3
  • Part4: Continuous Image security
  • Part5: trivy-operator 1.0
  • Part6: trivy-operator 2.1: Trivy-operator is now an Admisssion controller too!!!
  • Part7: trivy-operator 2.2: Patch release for Admisssion controller
  • Part8: trivy-operator 2.3: Patch release for Admisssion controller
  • Part8: trivy-operator 2.4: Patch release for Admisssion controller
  • Part8: trivy-operator 2.5: Patch release for Admisssion controller
  • Part9_ Image Signature Verification with Connaisseur
  • Part10: Image Signature Verification with Connaisseur 2.0
  • Part11: Image Signature Verification with Kyverno
  • Part12: How to use imagePullSecrets cluster-wide??
  • Part13: Automatically change registry in pod definition
  • Part14: ArgoCD auto image updater
    Pod Security
    Secret Security
    Monitoring and Observability
    Backup

    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.

    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 easier to deploy. Sadly anchore-image-validator run as root so we need to use my predifinde PSP to allow this.

    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
        createPolicies: true    
    

    During deploying this chart, it’s creating predefined policy bundles and activates AllowAll by default if createPolicies flag is set.

    Bundle Name Description
    Allow all and warn bundle Allow all images and warn if vulnerabilities are found
    Reject critical bundle Reject deploying images that contain critical vulnerabiliy
    Reject high bundle Reject deploying images that contain high vulnerabiliy
    Block root bundle Block deploying images that using root as effective user
    Deny all images Deny all imagest to deploy

    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]
    

    You can find the config files in my github repo: https://github.com/devopstales/k8s_sec_lab