Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 62 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"bytes"
"context"
"encoding/json"
"fmt"
"log"
Expand All @@ -15,6 +16,7 @@ import (
"github.com/manzil-infinity180/k8s-custom-controller/controller"
admissionv1 "k8s.io/api/admission/v1"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/informers"
Expand Down Expand Up @@ -61,6 +63,10 @@ func getKubeConfig() (*api.Config, error) {
return config, nil
}

type validator struct {
clientset kubernetes.Interface
}

// GetClientSetWithContext retrieves a Kubernetes clientset and dynamic client for a specified context
func GetClientSetWithContext(contextName string) (*kubernetes.Clientset, dynamic.Interface, error) {
var (
Expand Down Expand Up @@ -133,10 +139,13 @@ func main() {
fmt.Println()
log.Printf("Error: %s", err.Error())
}
v := &validator{
clientset: clientset,
}

// Start the webhook server in a goroutine
go func() {
http.HandleFunc("/validate", ValidateDeployment)
http.HandleFunc("/validate", v.ValidateDeployment)
log.Println("Starting webhook server on :8000...")
certPaths := []struct {
cert string
Expand Down Expand Up @@ -213,6 +222,7 @@ func scanImageWithTrivy(image string) (bool, string, error) {
"trivy",
"image",
"--scanners", "vuln",
"--severity", "CRITICAL", // only critical CVEs
"--server", "http://trivy-server-service.default.svc:8080", // [service_name].[namespace].svc:[port] (if not port 80)
"--format", "json",
image,
Expand All @@ -235,7 +245,8 @@ func scanImageWithTrivy(image string) (bool, string, error) {
for _, v := range vlist {
vmap := v.(map[string]interface{})
severity := vmap["Severity"].(string)
if severity == "HIGH" || severity == "CRITICAL" {
// skipping for High CVE > Checking only for CRITICAL
if severity == "CRITICAL" {
msg := fmt.Sprintf(" - 🔥 %s\n", vmap["VulnerabilityID"].(string))
//vulns = append(vulns, vmap["VulnerabilityID"].(string))
vulns = append(vulns, msg)
Expand All @@ -249,7 +260,7 @@ func scanImageWithTrivy(image string) (bool, string, error) {
}
return true, "", nil
}
func ValidateDeployment(w http.ResponseWriter, r *http.Request) {
func (v *validator) ValidateDeployment(w http.ResponseWriter, r *http.Request) {
log.Println("Received /validate request")
in, err := parseRequest(r)
if err != nil {
Expand Down Expand Up @@ -304,6 +315,54 @@ func ValidateDeployment(w http.ResponseWriter, r *http.Request) {
denied = true
reasons = append(reasons, fmt.Sprintf("%s (CVE: %s)", image, vulns))
}

// TODO: Need to restruct the codebase :(
if BYPASS_CVE_DENIED {
// generate SBOM for it and attach to configmap

cmd := exec.Command(
"trivy",
"image",
"--format", "spdx-json",
image,
)
out, err := cmd.Output()
if err != nil {
//
}
var result map[string]interface{}
if err := json.Unmarshal(out, &result); err != nil {
//
}

name := result["name"].(string)
creationInfo := result["creationInfo"].(map[string]interface{})
creationDate := creationInfo["created"].(string)

configmap_name := name + creationDate

sbomConfig := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
// Name: fmt.Sprintf("%s-sbom", deploymentName),
Name: fmt.Sprintf("%s-sbom", configmap_name),
// Namespace: deployment.Namespace,
Namespace: "default",
Labels: map[string]string{
"app": configmap_name,
// "app": deploymentName,
},
},
Data: map[string]string{
"sbom.json": string(out),
},
}
ctx := context.Background()
_, err = v.clientset.CoreV1().ConfigMaps("default").Create(ctx, sbomConfig, metav1.CreateOptions{})
if err != nil {
fmt.Errorf("failed to create SBOM ConfigMap: %w", err)
}

}
}
message := "Images allowed"
if denied {
Expand Down
8 changes: 7 additions & 1 deletion manifest/webhook-example/ZeroInitCVE.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,10 @@ spec:
- name: BYPASS_CVE_DENIED
value: "yes" # yes or true (lowercase)
- name: NO_AUTO_CREATION
value: "yes" # yes or true (lowercase)
value: "yes" # yes or true (lowercase)


# spec:
# sbomPolicy: enforce # block workloads with no SBOM
# sbomPolicy: warn # allow but log warning
# sbomPolicy: async # allow + controller generates SBOM later