From 7dc2a76e30882f0d2846a92c37ac99756c5f7880 Mon Sep 17 00:00:00 2001 From: Abhijeet Singh Date: Sun, 22 Dec 2024 13:06:31 +0530 Subject: [PATCH 01/13] Update SpringbootK8sDemoApplication.java Added home page on root path (/) so we do not have to change the uri path to /message all the time. --- .../k8s/SpringbootK8sDemoApplication.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/javatechie/k8s/SpringbootK8sDemoApplication.java b/src/main/java/com/javatechie/k8s/SpringbootK8sDemoApplication.java index 3b9023f..832e0d7 100644 --- a/src/main/java/com/javatechie/k8s/SpringbootK8sDemoApplication.java +++ b/src/main/java/com/javatechie/k8s/SpringbootK8sDemoApplication.java @@ -9,13 +9,17 @@ @RestController public class SpringbootK8sDemoApplication { - @GetMapping("/message") - public String welcome(){ - return "Congratulation you successfully deployed your application to kubernetes !!"; - } + public static void main(String[] args) { + SpringApplication.run(SpringbootK8sDemoApplication.class, args); + } - public static void main(String[] args) { - SpringApplication.run(SpringbootK8sDemoApplication.class, args); - } + @GetMapping("/message") + public String welcome() { + return "Congratulations! You have successfully deployed your application to Kubernetes!"; + } + @GetMapping("/") + public String home() { + return "Home! Congratulations! You have successfully deployed your application to Kubernetes!"; + } } From a1bad325f751288b2f3f41f1e292fb5d207a7ed3 Mon Sep 17 00:00:00 2001 From: Abhijeet Singh Date: Sun, 22 Dec 2024 13:12:26 +0530 Subject: [PATCH 02/13] Create job-eks.yaml Adding kube-bench for security checks. --- job-eks.yaml | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 job-eks.yaml diff --git a/job-eks.yaml b/job-eks.yaml new file mode 100644 index 0000000..90b1c3a --- /dev/null +++ b/job-eks.yaml @@ -0,0 +1,34 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: kube-bench + namespace: kube-system +spec: + template: + spec: + hostPID: true + containers: + - name: kube-bench + image: aquasec/kube-bench:latest + command: ["kube-bench", "node", "--benchmark", "eks-1.0"] + volumeMounts: + - name: var-lib-kubelet + mountPath: /var/lib/kubelet + readOnly: true + - name: etc-systemd + mountPath: /etc/systemd + readOnly: true + - name: etc-kubernetes + mountPath: /etc/kubernetes + readOnly: true + restartPolicy: Never + volumes: + - name: var-lib-kubelet + hostPath: + path: "/var/lib/kubelet" + - name: etc-systemd + hostPath: + path: "/etc/systemd" + - name: etc-kubernetes + hostPath: + path: "/etc/kubernetes" From b61288bfacae3526d8b1d605475bd15d23fa02fc Mon Sep 17 00:00:00 2001 From: Abhijeet Singh Date: Thu, 26 Dec 2024 12:24:11 +0530 Subject: [PATCH 03/13] Create kube-bench-job.yaml kube-bench with specific commands --- kube-bench/kube-bench-job.yaml | 42 ++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 kube-bench/kube-bench-job.yaml diff --git a/kube-bench/kube-bench-job.yaml b/kube-bench/kube-bench-job.yaml new file mode 100644 index 0000000..ac934ae --- /dev/null +++ b/kube-bench/kube-bench-job.yaml @@ -0,0 +1,42 @@ +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: kube-bench +spec: + template: + spec: + hostPID: true + containers: + - name: kube-bench + image: docker.io/aquasec/kube-bench:latest + command: + [ + "kube-bench", + "run", + "--targets", + "node", + "--benchmark", + "eks-1.2.0", + ] + volumeMounts: + - name: var-lib-kubelet + mountPath: /var/lib/kubelet + readOnly: true + - name: etc-systemd + mountPath: /etc/systemd + readOnly: true + - name: etc-kubernetes + mountPath: /etc/kubernetes + readOnly: true + restartPolicy: Never + volumes: + - name: var-lib-kubelet + hostPath: + path: "/var/lib/kubelet" + - name: etc-systemd + hostPath: + path: "/etc/systemd" + - name: etc-kubernetes + hostPath: + path: "/etc/kubernetes" From 63658a38c9d3277261397014201485566437b5bc Mon Sep 17 00:00:00 2001 From: Abhijeet Singh Date: Thu, 26 Dec 2024 12:26:51 +0530 Subject: [PATCH 04/13] Create kube-bench_job-minikube.yaml kube-bench for minikube --- kube-bench/kube-bench_job-minikube.yaml | 34 +++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 kube-bench/kube-bench_job-minikube.yaml diff --git a/kube-bench/kube-bench_job-minikube.yaml b/kube-bench/kube-bench_job-minikube.yaml new file mode 100644 index 0000000..be7b97e --- /dev/null +++ b/kube-bench/kube-bench_job-minikube.yaml @@ -0,0 +1,34 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: kube-bench + namespace: default +spec: + template: + spec: + hostPID: true + containers: + - name: kube-bench + image: aquasec/kube-bench:latest + command: ["kube-bench"] + volumeMounts: + - name: var-lib-kubelet + mountPath: /var/lib/kubelet + readOnly: true + - name: etc-systemd + mountPath: /etc/systemd + readOnly: true + - name: etc-kubernetes + mountPath: /etc/kubernetes + readOnly: true + restartPolicy: Never + volumes: + - name: var-lib-kubelet + hostPath: + path: "/var/lib/kubelet" + - name: etc-systemd + hostPath: + path: "/etc/systemd" + - name: etc-kubernetes + hostPath: + path: "/etc/kubernetes" From ca0965f6b25c696d8e84f93bb8e6bf93bdd1b856 Mon Sep 17 00:00:00 2001 From: Abhijeet Singh Date: Thu, 26 Dec 2024 12:27:49 +0530 Subject: [PATCH 05/13] Create kube-bench_cronjob-minikube.yaml kube-bench cronjob --- kube-bench/kube-bench_cronjob-minikube.yaml | 43 +++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 kube-bench/kube-bench_cronjob-minikube.yaml diff --git a/kube-bench/kube-bench_cronjob-minikube.yaml b/kube-bench/kube-bench_cronjob-minikube.yaml new file mode 100644 index 0000000..3b40145 --- /dev/null +++ b/kube-bench/kube-bench_cronjob-minikube.yaml @@ -0,0 +1,43 @@ +apiVersion: batch/v1 +kind: CronJob +metadata: + name: kube-bench-cron + namespace: default +spec: + schedule: "*/1 * * * *" # Runs every 1 minute + jobTemplate: + spec: + template: + spec: + hostPID: true + containers: + - name: kube-bench + image: aquasec/kube-bench:latest + command: ["sh", "-c", "apk add --no-cache curl && kube-bench | jq -R -s '{\"text\": .}' | curl -X POST -H 'Content-type: application/json' --data @- $(WEBHOOK_URL)"] + env: + - name: WEBHOOK_URL + valueFrom: + secretKeyRef: + name: slack-webhook-secret + key: webhook-url + volumeMounts: + - name: var-lib-kubelet + mountPath: /var/lib/kubelet + readOnly: true + - name: etc-systemd + mountPath: /etc/systemd + readOnly: true + - name: etc-kubernetes + mountPath: /etc/kubernetes + readOnly: true + restartPolicy: Never + volumes: + - name: var-lib-kubelet + hostPath: + path: "/var/lib/kubelet" + - name: etc-systemd + hostPath: + path: "/etc/systemd" + - name: etc-kubernetes + hostPath: + path: "/etc/kubernetes" From e0df9942644702641f07ae9e344f970248c31a63 Mon Sep 17 00:00:00 2001 From: Abhijeet Singh Date: Thu, 26 Dec 2024 12:31:44 +0530 Subject: [PATCH 06/13] Create README.md --- kube-bench/README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 kube-bench/README.md diff --git a/kube-bench/README.md b/kube-bench/README.md new file mode 100644 index 0000000..a610bbd --- /dev/null +++ b/kube-bench/README.md @@ -0,0 +1,10 @@ +These are the kube-bench jobs and cronjob yaml files to check for CIS benchmark of your k8 cluster. +To run the cronjob, you need to setup a slack webhook secret first. + +Use this command: + +`kubectl create secret generic slack-webhook-secret --from-literal=slack_webhook-url=https://hooks.slack.com/services/ -n default` + +then apply the cronjob in your cluster. + +`kubectl apply -f kube-bench_cronjob-minikube.yaml` From 4f2f6b3ff5f99bced4c35d3577b3b804185b091f Mon Sep 17 00:00:00 2001 From: Abhijeet Singh Date: Thu, 26 Dec 2024 12:36:33 +0530 Subject: [PATCH 07/13] Create trivy-rbac.yaml --- trivy/trivy-rbac.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 trivy/trivy-rbac.yaml diff --git a/trivy/trivy-rbac.yaml b/trivy/trivy-rbac.yaml new file mode 100644 index 0000000..2d91eb2 --- /dev/null +++ b/trivy/trivy-rbac.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: trivy-cluster-admin-binding +subjects: + - kind: ServiceAccount + name: trivy-sa + namespace: default +roleRef: + kind: ClusterRole + name: cluster-admin + apiGroup: rbac.authorization.k8s.io From 558d5e54d256b027d868843b58e610c137d2d5a0 Mon Sep 17 00:00:00 2001 From: Abhijeet Singh Date: Thu, 26 Dec 2024 12:36:50 +0530 Subject: [PATCH 08/13] Create trivy-serviceaccount.yaml --- trivy/trivy-serviceaccount.yaml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 trivy/trivy-serviceaccount.yaml diff --git a/trivy/trivy-serviceaccount.yaml b/trivy/trivy-serviceaccount.yaml new file mode 100644 index 0000000..fec9940 --- /dev/null +++ b/trivy/trivy-serviceaccount.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: trivy-sa + namespace: default From ec9060894ca9d447dd7a2f2bb1fcbd7c8f457320 Mon Sep 17 00:00:00 2001 From: Abhijeet Singh Date: Thu, 26 Dec 2024 12:38:21 +0530 Subject: [PATCH 09/13] Create cronjob-trivy.yaml --- trivy/cronjob-trivy.yaml | 72 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 trivy/cronjob-trivy.yaml diff --git a/trivy/cronjob-trivy.yaml b/trivy/cronjob-trivy.yaml new file mode 100644 index 0000000..f40d07d --- /dev/null +++ b/trivy/cronjob-trivy.yaml @@ -0,0 +1,72 @@ +apiVersion: batch/v1 +kind: CronJob +metadata: + name: trivy-k8s-scan + namespace: default +spec: + schedule: "37 20 * * *" + jobTemplate: + spec: + template: + spec: + serviceAccountName: trivy-sa + containers: + - name: trivy-k8s + image: aquasec/trivy:latest + command: + - /bin/sh + - -c + - | + apk add --no-cache curl && + curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" && + chmod +x kubectl && + mv kubectl /usr/local/bin/ && + echo "kubectl installed successfully" && + TOTAL_NS=$(kubectl get ns -o jsonpath='{.items[*].metadata.name}' | wc -w) && + curl -X POST https://slack.com/api/chat.postMessage \ + -H "Authorization: Bearer $(cat /var/secrets/SLACK-TOKEN)" \ + -H "Content-Type: application/json" \ + -d '{ + "channel": "#security-aws-eks", + "text": "Total number of namespaces are '"$TOTAL_NS"'. Running Trivy in each namespace" + }' && + for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do + DATE_TIME=$(date +%Y-%m-%d_%H-%M-%S) && + FILENAME="/tmp/trivy_${ns}_${DATE_TIME}.txt" && + RESOURCE_COUNT=$(kubectl get all -n $ns --no-headers 2>/dev/null | wc -l) && + if [ "$RESOURCE_COUNT" -eq 0 ]; then + curl -X POST https://slack.com/api/chat.postMessage \ + -H "Authorization: Bearer $(cat /var/secrets/SLACK-TOKEN)" \ + -H "Content-Type: application/json" \ + -d '{ + "channel": "#security-aws-eks", + "text": "There are no resources in namespace '"$ns"' to scan." + }'; + else + echo "Scanning namespace: $ns" && + trivy k8s --include-namespaces $ns --report all --severity CRITICAL --format table > $FILENAME && + if [ -f $FILENAME ]; then + curl -F file=@$FILENAME \ + -F "channels=#security-aws-eks" \ + -F "initial_comment=Trivy scan results for namespace: $ns" \ + -F "token=$(cat /var/secrets/SLACK-TOKEN)" \ + https://slack.com/api/files.upload; + else + curl -X POST https://slack.com/api/chat.postMessage \ + -H "Authorization: Bearer $(cat /var/secrets/SLACK-TOKEN)" \ + -H "Content-Type: application/json" \ + -d '{ + "channel": "#security-aws-eks", + "text": "Trivy scan failed for namespace '"$ns"'." + }'; + fi; + fi; + done; + volumeMounts: + - name: slack-secret + mountPath: /var/secrets + restartPolicy: OnFailure + volumes: + - name: slack-secret + secret: + secretName: slack-security-secret From 1491e204e3d72818702bea00c21e8e433d78dd8e Mon Sep 17 00:00:00 2001 From: Abhijeet Singh Date: Thu, 26 Dec 2024 12:40:04 +0530 Subject: [PATCH 10/13] Create trivy_job_eks_dev_single_ns.yaml --- trivy/trivy_job_eks_dev_single_ns.yaml | 41 ++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 trivy/trivy_job_eks_dev_single_ns.yaml diff --git a/trivy/trivy_job_eks_dev_single_ns.yaml b/trivy/trivy_job_eks_dev_single_ns.yaml new file mode 100644 index 0000000..507be87 --- /dev/null +++ b/trivy/trivy_job_eks_dev_single_ns.yaml @@ -0,0 +1,41 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: trivy-k8s-scan + namespace: default +spec: + # activeDeadlineSeconds: 3600 # Set timeout for the Job to 10 minutes + # backoffLimit: 1 # Optional: Retry once if the Job fails + template: + spec: + serviceAccountName: trivy-sa + containers: + - name: trivy-k8s + image: aquasec/trivy:latest + command: + - /bin/sh + - -c + - | + apk add --no-cache curl && + trivy k8s --include-namespaces default --report all --severity CRITICAL --format table --timeout 60m > /tmp/trivy_k8_scan.txt && + if [ -f /tmp/trivy_k8_scan.txt ]; then + curl -F file=@/tmp/trivy_k8_scan.txt \ + -F "channels=#my-automation" \ + -F "initial_comment=Trivy K8s Scan Results" \ + -F "token=$(cat /var/secrets/SLACK-TOKEN)" \ + https://slack.com/api/files.upload; + else + echo "Trivy scan failed or no results generated."; + fi + volumeMounts: + - name: tmp-dir + mountPath: /tmp + - name: slack-secret + mountPath: /var/secrets + restartPolicy: OnFailure + volumes: + - name: tmp-dir + emptyDir: {} + - name: slack-secret + secret: + secretName: slack-security-secret From 67435b5b8ca7743256db468cd552306b36db5bf2 Mon Sep 17 00:00:00 2001 From: Abhijeet Singh Date: Thu, 26 Dec 2024 12:41:54 +0530 Subject: [PATCH 11/13] Create trivy_job_eks_dev_all_ns.yaml --- trivy/trivy_job_eks_dev_all_ns.yaml | 69 +++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 trivy/trivy_job_eks_dev_all_ns.yaml diff --git a/trivy/trivy_job_eks_dev_all_ns.yaml b/trivy/trivy_job_eks_dev_all_ns.yaml new file mode 100644 index 0000000..a0e88f4 --- /dev/null +++ b/trivy/trivy_job_eks_dev_all_ns.yaml @@ -0,0 +1,69 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: trivy-k8s-scan + namespace: default +spec: + template: + spec: + serviceAccountName: trivy-sa + containers: + - name: trivy-k8s + image: aquasec/trivy:latest + command: + - /bin/sh + - -c + - | + apk add --no-cache curl && + curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" && + chmod +x kubectl && + mv kubectl /usr/local/bin/ && + echo "kubectl installed successfully" && + TOTAL_NS=$(kubectl get ns -o jsonpath='{.items[*].metadata.name}' | wc -w) && + curl -X POST https://slack.com/api/chat.postMessage \ + -H "Authorization: Bearer $(cat /var/secrets/SLACK-TOKEN)" \ + -H "Content-Type: application/json" \ + -d '{ + "channel": "#my-automation", + "text": "Total number of namespaces are '"$TOTAL_NS"'. Running Trivy in each namespace" + }' && + for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do + DATE_TIME=$(date +%Y-%m-%d_%H-%M-%S) && + FILENAME="/tmp/trivy_${ns}_${DATE_TIME}.txt" && + RESOURCE_COUNT=$(kubectl get all -n $ns --no-headers 2>/dev/null | wc -l) && + if [ "$RESOURCE_COUNT" -eq 0 ]; then + curl -X POST https://slack.com/api/chat.postMessage \ + -H "Authorization: Bearer $(cat /var/secrets/SLACK-TOKEN)" \ + -H "Content-Type: application/json" \ + -d '{ + "channel": "#my-automation", + "text": "There are no resources in namespace '"$ns"' to scan." + }'; + else + echo "Scanning namespace: $ns" && + trivy k8s --include-namespaces $ns --report all --severity CRITICAL --format table > $FILENAME && + if [ -f $FILENAME ]; then + curl -F file=@$FILENAME \ + -F "channels=#my-automation" \ + -F "initial_comment=Trivy scan results for namespace: $ns" \ + -F "token=$(cat /var/secrets/SLACK-TOKEN)" \ + https://slack.com/api/files.upload; + else + curl -X POST https://slack.com/api/chat.postMessage \ + -H "Authorization: Bearer $(cat /var/secrets/SLACK-TOKEN)" \ + -H "Content-Type: application/json" \ + -d '{ + "channel": "#my-automation", + "text": "Trivy scan failed for namespace '"$ns"'." + }'; + fi; + fi; + done; + volumeMounts: + - name: slack-secret + mountPath: /var/secrets + restartPolicy: OnFailure + volumes: + - name: slack-secret + secret: + secretName: slack-security-secret From ff7860d60268d62b0129ca22fbba030c077a8e1c Mon Sep 17 00:00:00 2001 From: Abhijeet Singh Date: Thu, 26 Dec 2024 12:43:22 +0530 Subject: [PATCH 12/13] Create trivy_job_minikube.yaml --- trivy/trivy_job_minikube.yaml | 45 +++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 trivy/trivy_job_minikube.yaml diff --git a/trivy/trivy_job_minikube.yaml b/trivy/trivy_job_minikube.yaml new file mode 100644 index 0000000..eeb2a9c --- /dev/null +++ b/trivy/trivy_job_minikube.yaml @@ -0,0 +1,45 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: trivy-k8s-scan + namespace: default +spec: + template: + spec: + serviceAccountName: trivy-sa + containers: + - name: trivy-k8s + image: aquasec/trivy:latest + command: ["/bin/sh", "-c"] + args: + - | + apk add --no-cache curl && \ + trivy k8s --report all --severity CRITICAL --format table > /tmp/trivy_k8_$(date +%Y-%m-%d_%H-%M-%S).txt && \ + FILENAME=$(ls /tmp/trivy_k8_*.txt) && \ + SLACK_TOKEN=$(cat /var/secrets/SLACK-TOKEN) && \ + curl -F file=@$FILENAME -F "channels=#my-automation" -F "initial_comment=trivy_k8_result" -F "token=$SLACK_TOKEN" https://slack.com/api/files.upload + env: + - name: KUBECONFIG + value: /root/.kube/config + volumeMounts: + - name: kubeconfig + mountPath: /root/.kube + - name: minikube-certs + mountPath: /root/.minikube + - name: tmp-dir + mountPath: /tmp + - name: slack-secret + mountPath: /var/secrets + restartPolicy: OnFailure + volumes: + - name: kubeconfig + hostPath: + path: /Users/abhijeetsingh/.kube + - name: minikube-certs + hostPath: + path: /Users/abhijeetsingh/.minikube + - name: tmp-dir + emptyDir: {} + - name: slack-secret + secret: + secretName: slack-security-secret From b24d75ed4e0a2e2af0b36dec21b6c1af07a4a981 Mon Sep 17 00:00:00 2001 From: Abhijeet Singh Date: Thu, 26 Dec 2024 12:46:41 +0530 Subject: [PATCH 13/13] Create README.md --- trivy/README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 trivy/README.md diff --git a/trivy/README.md b/trivy/README.md new file mode 100644 index 0000000..6df732c --- /dev/null +++ b/trivy/README.md @@ -0,0 +1,12 @@ +Create secret before running these jobs/cronjobs + +``` +kubectl create secret generic slack-webhook-secret --from-literal=slack_webhook-url=https://hooks.slack.com/services/ -n default +kubectl create secret generic slack-security-secret --from-literal=SLACK-TOKEN=xoxb- -n default +``` + +Make sure that your bot token have permission to upload file in your channel. And you must need to integrate your bot in your slack channel. + + +Then apply these jobs: +`kubectl apply -f .yaml`