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
- Part1: Best Practices to keeping Kubernetes Clusters Secure
- Part2: RKE2 The Secure Kubernetes Engine
- Part3: RKE2 Pod Security Policy
- Part4: Kubernetes Network Policy
- Part5: Kubernetes Cluster Policy
- Part6: Using Admission Controllers
- Part7: Image security Admission Controller
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]