From 92da24699d68b69d2a5e94c0807e0796419cedde Mon Sep 17 00:00:00 2001 From: Roy Hadad Date: Thu, 13 Jul 2023 13:45:26 +0300 Subject: [PATCH 1/8] mounted and shared perssitentvolume to webhook deployment --- .../templates/deployment.yaml | 17 +++++++++++++++++ internal/fixtures/values.dev.yaml | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/charts/datree-admission-webhook/templates/deployment.yaml b/charts/datree-admission-webhook/templates/deployment.yaml index a0460d7b..64f2fe4e 100644 --- a/charts/datree-admission-webhook/templates/deployment.yaml +++ b/charts/datree-admission-webhook/templates/deployment.yaml @@ -106,6 +106,8 @@ spec: - containerPort: 5555 name: debug volumeMounts: + - mountPath: /app/folder + name: volume - name: webhook-tls-certs mountPath: /run/secrets/tls readOnly: true @@ -113,6 +115,9 @@ spec: mountPath: /config readOnly: true volumes: + - name: volume + persistentVolumeClaim: + claimName: volume-claim - name: webhook-tls-certs secret: secretName: webhook-server-tls @@ -125,3 +130,15 @@ spec: - configMap: name: webhook-scanning-filters optional: true +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: volume-claim + namespace: datree +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 2Gi diff --git a/internal/fixtures/values.dev.yaml b/internal/fixtures/values.dev.yaml index 6633043f..da14a7ae 100644 --- a/internal/fixtures/values.dev.yaml +++ b/internal/fixtures/values.dev.yaml @@ -6,7 +6,7 @@ # The name of the namespace all resources will be created in, if not specified in the release. namespace: "" # The number of Datree webhook-server replicas to deploy for the webhook. -replicaCount: 1 +replicaCount: 2 # Additional labels to add to all resources. customLabels: { } # Additional annotations to add to all resources. From 79637ec0dec46ad2f5ee448f1464331cbe287b0b Mon Sep 17 00:00:00 2001 From: Roy Hadad Date: Thu, 13 Jul 2023 15:55:05 +0300 Subject: [PATCH 2/8] first draft, generating the certificate if it is missing and activating the validatingwebhookconfiguration --- .../wait-server-ready-post-install.yaml | 41 ------------ .../templates/webhook-with-cert-secrets.yaml | 35 +--------- go.mod | 3 +- go.sum | 2 + internal/startup/startup.go | 17 ++++- pkg/k8sClient2/k8sClient2.go | 66 +++++++++++++++++++ 6 files changed, 85 insertions(+), 79 deletions(-) delete mode 100644 charts/datree-admission-webhook/templates/wait-server-ready-post-install.yaml create mode 100644 pkg/k8sClient2/k8sClient2.go diff --git a/charts/datree-admission-webhook/templates/wait-server-ready-post-install.yaml b/charts/datree-admission-webhook/templates/wait-server-ready-post-install.yaml deleted file mode 100644 index 02cd97ed..00000000 --- a/charts/datree-admission-webhook/templates/wait-server-ready-post-install.yaml +++ /dev/null @@ -1,41 +0,0 @@ -apiVersion: batch/v1 -kind: Job -metadata: - name: datree-wait-server-ready-hook-post-install - namespace: {{template "datree.namespace" .}} - labels: {{ include "datree.labels" . | nindent 4 }} - annotations: - argocd.argoproj.io/hook: PostSync - argocd.argoproj.io/hook-delete-policy: BeforeHookCreation - "helm.sh/hook": post-install, post-upgrade - "helm.sh/hook-weight": "-5" - "helm.sh/hook-delete-policy": before-hook-creation, hook-succeeded, hook-failed - {{- with .Values.customAnnotations }} - {{ toYaml . }} - {{- end }} -spec: - ttlSecondsAfterFinished: {{.Values.hooks.ttlSecondsAfterFinished | default "1" }} - template: - metadata: - name: datree-wait-server-ready-hook-post-install - labels: {{ include "datree.labels" . | nindent 8 }} - {{- with .Values.customAnnotations }} - annotations: {{ toYaml . | nindent 8 }} - {{- end }} - spec: - serviceAccountName: datree-wait-server-ready-hook-post-install - restartPolicy: Never - {{- if .Values.imageCredentials.enabled }} - imagePullSecrets: - - name: datree-repo-credentials - {{- end }} - containers: - - name: kubectl-client - image: "{{ .Values.hooks.image.repository }}:{{ .Values.hooks.image.tag }}" - imagePullPolicy: {{.Values.hooks.image.pullPolicy}} - securityContext: {{- toYaml .Values.securityContext | nindent 12 }} - command: - - sh - - "-c" - - >- - kubectl wait --for=condition=ready pod -l app=datree-webhook-server --timeout="{{ default "180s" .Values.hooks.timeoutTime }}" diff --git a/charts/datree-admission-webhook/templates/webhook-with-cert-secrets.yaml b/charts/datree-admission-webhook/templates/webhook-with-cert-secrets.yaml index 47ada79e..c2ef60fa 100644 --- a/charts/datree-admission-webhook/templates/webhook-with-cert-secrets.yaml +++ b/charts/datree-admission-webhook/templates/webhook-with-cert-secrets.yaml @@ -1,37 +1,4 @@ -{{- $ca := genCA "/CN=Admission Controller Webhook Demo CA" 1827 -}} {{- $svcHost := printf "datree-webhook-server.%s.svc" ( include "datree.namespace" . ) -}} -{{- $altNames := list ( $svcHost ) -}} -{{- $cert := genSignedCert (printf "/CN=%s" $svcHost) nil $altNames 1827 $ca -}} -apiVersion: v1 -kind: Secret -metadata: - name: datree-ca-tls - labels: {{ include "datree.labels" . | nindent 4 }} - namespace: {{ template "datree.namespace" . }} - {{- with .Values.customAnnotations }} - annotations: {{ toYaml . | nindent 4 }} - {{- end }} -type: kubernetes.io/tls -data: - tls.key: {{ $ca.Key | b64enc }} - tls.crt: {{ $ca.Cert | b64enc }} ---- -apiVersion: v1 -kind: Secret -metadata: - name: webhook-server-tls - labels: {{ include "datree.labels" . | nindent 4 }} - namespace: {{ template "datree.namespace" . }} - annotations: - self-signed-cert: "true" - {{- with .Values.customAnnotations }} - {{ toYaml . }} - {{- end }} -type: kubernetes.io/tls -data: - tls.key: {{ $cert.Key | b64enc }} - tls.crt: {{ $cert.Cert | b64enc }} ---- apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: @@ -59,7 +26,7 @@ webhooks: name: datree-webhook-server namespace: {{ template "datree.namespace" . }} path: "/validate" - caBundle: {{ $ca.Cert | b64enc }} + caBundle: {{ "PLACEHOLDER" | b64enc }} namespaceSelector: matchExpressions: - key: admission.datree/validate diff --git a/go.mod b/go.mod index b1c2bc40..43ddcd24 100644 --- a/go.mod +++ b/go.mod @@ -7,8 +7,10 @@ require ( github.com/ghodss/yaml v1.0.0 github.com/google/go-cmp v0.5.9 github.com/lithammer/shortuuid v3.0.0+incompatible + github.com/openshift/api v0.0.0-20230705144233-e28cd4dd28a8 github.com/openshift/client-go v0.0.0-20230705133330-7f808ad59404 github.com/patrickmn/go-cache v2.1.0+incompatible + github.com/sirupsen/logrus v1.9.0 github.com/stretchr/testify v1.8.1 go.uber.org/zap v1.10.0 k8s.io/api v0.27.2 @@ -33,7 +35,6 @@ require ( github.com/jinzhu/copier v0.3.5 // indirect github.com/mikefarah/yq/v4 v4.27.3 // indirect github.com/open-policy-agent/opa v0.49.2 // indirect - github.com/openshift/api v0.0.0-20230705144233-e28cd4dd28a8 // indirect github.com/owenrumney/go-sarif/v2 v2.1.2 // indirect github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect github.com/stretchr/objx v0.5.0 // indirect diff --git a/go.sum b/go.sum index fc66718a..f2df72ea 100644 --- a/go.sum +++ b/go.sum @@ -226,6 +226,7 @@ github.com/santhosh-tekuri/jsonschema/v5 v5.0.0/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H github.com/shirou/gopsutil/v3 v3.22.5 h1:atX36I/IXgFiB81687vSiBI5zrMsxcIBkP9cQMJQoJA= github.com/shirou/gopsutil/v3 v3.22.5/go.mod h1:so9G9VzeHt/hsd0YwqprnjHnfARAUktauykSbr+y2gA= github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= @@ -327,6 +328,7 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/internal/startup/startup.go b/internal/startup/startup.go index 7fcf14bc..53f43650 100644 --- a/internal/startup/startup.go +++ b/internal/startup/startup.go @@ -3,6 +3,8 @@ package startup import ( "errors" "fmt" + cert_manager "github.com/datreeio/admission-webhook-datree/pkg/cert-manager" + "github.com/datreeio/admission-webhook-datree/pkg/k8sClient2" "github.com/datreeio/admission-webhook-datree/pkg/openshiftService" "net/http" @@ -87,9 +89,18 @@ func Start() { if err != nil { fmt.Printf("Failed init skip list: %s \n", err.Error()) } - certPath, keyPath, err := server.ValidateCertificate() + + err = cert_manager.GenerateCertificatesIfTheyAreMissing() + if err != nil { + fmt.Printf("Failed to generate certificates: %s \n", err.Error()) + } + k8sClient2Instance, err := k8sClient2.NewK8sClient() + if err != nil { + fmt.Printf("Failed to create k8s client: %s \n", err.Error()) + } + err = k8sClient2Instance.ActivateValidatingWebhookConfiguration(cert_manager.CaCertPath) if err != nil { - panic(err) + fmt.Printf("Failed to activate validating webhook configuration: %s \n", err.Error()) } validationController := controllers.NewValidationController(basicCliClient, state, errorReporter, k8sMetadataUtilInstance, &internalLogger, openshiftServiceInstance) @@ -105,7 +116,7 @@ func Start() { internalLogger.LogInfo(fmt.Sprintf("server starting in webhook-version: %s", config.WebhookVersion)) // start server - if err := http.ListenAndServeTLS(":"+port, certPath, keyPath, nil); err != nil { + if err := http.ListenAndServeTLS(":"+port, cert_manager.CertPath, cert_manager.KeyPath, nil); err != nil { err = http.ListenAndServe(":"+port, nil) if err != nil { fmt.Println("Failed to start http server", err.Error()) diff --git a/pkg/k8sClient2/k8sClient2.go b/pkg/k8sClient2/k8sClient2.go new file mode 100644 index 00000000..d9e041cd --- /dev/null +++ b/pkg/k8sClient2/k8sClient2.go @@ -0,0 +1,66 @@ +package k8sClient2 + +import ( + "context" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" +) + +type k8sClientInterface interface { + doesValidatingWebhookConfigurationExist() (any, error) + applyValidatingWebhookConfiguration() (any, error) +} + +type k8sClient struct { + clientset *kubernetes.Clientset +} + +func NewK8sClient() (*k8sClient, error) { + // creates the in-cluster config + config, err := rest.InClusterConfig() + if err != nil { + return nil, err + } + // creates the clientset + clientsetInstance, err := kubernetes.NewForConfig(config) + if err != nil { + return nil, err + } + + return &k8sClient{ + clientset: clientsetInstance, + }, nil +} + +func (kc *k8sClient) ActivateValidatingWebhookConfiguration(certPath string) error { + //certificateContent, readFileError := os.ReadFile(certPath) + //if readFileError != nil { + // return readFileError + //} + + result, err := kc.clientset.AdmissionregistrationV1().ValidatingWebhookConfigurations().Get(context.TODO(), "datree-webhook", metav1.GetOptions{}) + if err != nil { + return err + } + + // update the CABundle from PLACEHOLDER to the actual certificate from cert-manager + //result.Webhooks[0].ClientConfig.CABundle = certificateContent + + // remove the match expression at index 1, which is responsible for disabling the webhook + matchExpressions := result.Webhooks[0].NamespaceSelector.MatchExpressions + if len(matchExpressions) > 1 { + result.Webhooks[0].NamespaceSelector.MatchExpressions = append(matchExpressions[:1], matchExpressions[2:]...) + } + + _, err = kc.clientset.AdmissionregistrationV1().ValidatingWebhookConfigurations().Update(context.TODO(), result, metav1.UpdateOptions{}) + if err != nil { + return err + } + + return nil +} + +func (kc *k8sClient) applyValidatingWebhookConfiguration() error { + return nil +} From 2df7c90e512be6063c31ca5480ed5edae1add1c8 Mon Sep 17 00:00:00 2001 From: Roy Hadad Date: Thu, 13 Jul 2023 15:58:36 +0300 Subject: [PATCH 3/8] add the validatingWEbhookConfiguration disabler and permissions --- charts/datree-admission-webhook/templates/clusterrole.yaml | 7 +++++++ .../templates/webhook-with-cert-secrets.yaml | 2 ++ 2 files changed, 9 insertions(+) diff --git a/charts/datree-admission-webhook/templates/clusterrole.yaml b/charts/datree-admission-webhook/templates/clusterrole.yaml index b8818799..a35c9b3e 100644 --- a/charts/datree-admission-webhook/templates/clusterrole.yaml +++ b/charts/datree-admission-webhook/templates/clusterrole.yaml @@ -8,6 +8,13 @@ metadata: annotations: {{ toYaml . | nindent 4 }} {{- end }} rules: + - apiGroups: + - "admissionregistration.k8s.io" + resources: + - "validatingwebhookconfigurations" + verbs: + - "get" + - "update" - apiGroups: - "user.openshift.io" resources: diff --git a/charts/datree-admission-webhook/templates/webhook-with-cert-secrets.yaml b/charts/datree-admission-webhook/templates/webhook-with-cert-secrets.yaml index c2ef60fa..2fbbc0fb 100644 --- a/charts/datree-admission-webhook/templates/webhook-with-cert-secrets.yaml +++ b/charts/datree-admission-webhook/templates/webhook-with-cert-secrets.yaml @@ -31,6 +31,8 @@ webhooks: matchExpressions: - key: admission.datree/validate operator: DoesNotExist + - key: admission.datree/validate + operator: Exists # the label can't exist AND not exist simultaneously, therefore the webhook will never be invoked until we delete this expression rules: - operations: ["CREATE", "UPDATE"] apiGroups: ["*"] From 7eb545c0f3753747e774c92ccbca46b668982d74 Mon Sep 17 00:00:00 2001 From: Roy Hadad Date: Thu, 13 Jul 2023 16:38:28 +0300 Subject: [PATCH 4/8] wip --- .../templates/deployment.yaml | 2 +- internal/startup/startup.go | 2 +- pkg/cert-manager/cert-manager.go | 18 +++++------- pkg/k8sClient2/k8sClient2.go | 28 +++++++++++-------- 4 files changed, 26 insertions(+), 24 deletions(-) diff --git a/charts/datree-admission-webhook/templates/deployment.yaml b/charts/datree-admission-webhook/templates/deployment.yaml index 64f2fe4e..978cee89 100644 --- a/charts/datree-admission-webhook/templates/deployment.yaml +++ b/charts/datree-admission-webhook/templates/deployment.yaml @@ -106,7 +106,7 @@ spec: - containerPort: 5555 name: debug volumeMounts: - - mountPath: /app/folder + - mountPath: /etc/webhook-certs name: volume - name: webhook-tls-certs mountPath: /run/secrets/tls diff --git a/internal/startup/startup.go b/internal/startup/startup.go index 53f43650..d4bed2b5 100644 --- a/internal/startup/startup.go +++ b/internal/startup/startup.go @@ -116,7 +116,7 @@ func Start() { internalLogger.LogInfo(fmt.Sprintf("server starting in webhook-version: %s", config.WebhookVersion)) // start server - if err := http.ListenAndServeTLS(":"+port, cert_manager.CertPath, cert_manager.KeyPath, nil); err != nil { + if err := http.ListenAndServeTLS(":"+port, cert_manager.TlsCertPath, cert_manager.TlsKeyPath, nil); err != nil { err = http.ListenAndServe(":"+port, nil) if err != nil { fmt.Println("Failed to start http server", err.Error()) diff --git a/pkg/cert-manager/cert-manager.go b/pkg/cert-manager/cert-manager.go index bad6bb7d..00022ff3 100644 --- a/pkg/cert-manager/cert-manager.go +++ b/pkg/cert-manager/cert-manager.go @@ -15,9 +15,9 @@ import ( "time" ) -const certsFolder = "/app/folder/certs" -const CertPath = certsFolder + "/tls.crt" -const KeyPath = certsFolder + "/tls.key" +const certsFolder = "/etc/webhook-certs" +const TlsCertPath = certsFolder + "/tls.crt" +const TlsKeyPath = certsFolder + "/tls.key" const CaCertPath = certsFolder + "/ca.crt" const CaKeyPath = certsFolder + "/ca.key" @@ -43,7 +43,7 @@ func doCertificatesExist() bool { return true } - return doesFileExist(CertPath) && doesFileExist(KeyPath) && doesFileExist(CaCertPath) && doesFileExist(CaKeyPath) + return doesFileExist(TlsCertPath) && doesFileExist(TlsKeyPath) && doesFileExist(CaCertPath) && doesFileExist(CaKeyPath) } func generateCertificates() { @@ -124,17 +124,13 @@ func generateCertificates() { Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(serverPrivKey), }) - - err = os.MkdirAll("/app/folder/certs/", 0666) - if err != nil { - log.Panic(err) - } - err = writeFile("/app/folder/certs/tls.crt", serverCertPEM) + + err = writeFile(TlsCertPath, serverCertPEM) if err != nil { log.Panic(err) } - err = writeFile("/app/folder/certs/tls.key", serverPrivKeyPEM) + err = writeFile(TlsKeyPath, serverPrivKeyPEM) if err != nil { log.Panic(err) } diff --git a/pkg/k8sClient2/k8sClient2.go b/pkg/k8sClient2/k8sClient2.go index d9e041cd..4485079c 100644 --- a/pkg/k8sClient2/k8sClient2.go +++ b/pkg/k8sClient2/k8sClient2.go @@ -2,9 +2,11 @@ package k8sClient2 import ( "context" + "fmt" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" + "os" ) type k8sClientInterface interface { @@ -33,27 +35,31 @@ func NewK8sClient() (*k8sClient, error) { }, nil } -func (kc *k8sClient) ActivateValidatingWebhookConfiguration(certPath string) error { - //certificateContent, readFileError := os.ReadFile(certPath) - //if readFileError != nil { - // return readFileError - //} +func (kc *k8sClient) ActivateValidatingWebhookConfiguration(caCertPath string) error { + certificateContent, readFileError := os.ReadFile(caCertPath) + if readFileError != nil { + return readFileError + } + + fmt.Println("@@@@@@@@@@@@@@@@@") + fmt.Println(string(certificateContent)) + fmt.Println("@@@@@@@@@@@@@@@@@") - result, err := kc.clientset.AdmissionregistrationV1().ValidatingWebhookConfigurations().Get(context.TODO(), "datree-webhook", metav1.GetOptions{}) + existingValidatingWebhookConfiguration, err := kc.clientset.AdmissionregistrationV1().ValidatingWebhookConfigurations().Get(context.TODO(), "datree-webhook", metav1.GetOptions{}) if err != nil { return err } - // update the CABundle from PLACEHOLDER to the actual certificate from cert-manager - //result.Webhooks[0].ClientConfig.CABundle = certificateContent + // update the CABundle from PLACEHOLDER to the actual certificate from persistent volume + existingValidatingWebhookConfiguration.Webhooks[0].ClientConfig.CABundle = certificateContent // remove the match expression at index 1, which is responsible for disabling the webhook - matchExpressions := result.Webhooks[0].NamespaceSelector.MatchExpressions + matchExpressions := existingValidatingWebhookConfiguration.Webhooks[0].NamespaceSelector.MatchExpressions if len(matchExpressions) > 1 { - result.Webhooks[0].NamespaceSelector.MatchExpressions = append(matchExpressions[:1], matchExpressions[2:]...) + existingValidatingWebhookConfiguration.Webhooks[0].NamespaceSelector.MatchExpressions = append(matchExpressions[:1], matchExpressions[2:]...) } - _, err = kc.clientset.AdmissionregistrationV1().ValidatingWebhookConfigurations().Update(context.TODO(), result, metav1.UpdateOptions{}) + _, err = kc.clientset.AdmissionregistrationV1().ValidatingWebhookConfigurations().Update(context.TODO(), existingValidatingWebhookConfiguration, metav1.UpdateOptions{}) if err != nil { return err } From ef5643ac8ae449ca4a72c9ed4fcc836b5c5d5f13 Mon Sep 17 00:00:00 2001 From: Roy Hadad Date: Thu, 13 Jul 2023 20:02:22 +0300 Subject: [PATCH 5/8] works --- .../templates/deployment.yaml | 6 ----- internal/startup/startup.go | 2 +- pkg/cert-manager/cert-manager.go | 22 ++++++++-------- pkg/k8sClient2/k8sClient2.go | 25 +++++-------------- pkg/server/server.go | 23 ----------------- 5 files changed, 19 insertions(+), 59 deletions(-) diff --git a/charts/datree-admission-webhook/templates/deployment.yaml b/charts/datree-admission-webhook/templates/deployment.yaml index 978cee89..a4fdc3d6 100644 --- a/charts/datree-admission-webhook/templates/deployment.yaml +++ b/charts/datree-admission-webhook/templates/deployment.yaml @@ -108,9 +108,6 @@ spec: volumeMounts: - mountPath: /etc/webhook-certs name: volume - - name: webhook-tls-certs - mountPath: /run/secrets/tls - readOnly: true - name: webhook-config mountPath: /config readOnly: true @@ -118,9 +115,6 @@ spec: - name: volume persistentVolumeClaim: claimName: volume-claim - - name: webhook-tls-certs - secret: - secretName: webhook-server-tls - name: webhook-config projected: sources: diff --git a/internal/startup/startup.go b/internal/startup/startup.go index d4bed2b5..3249345f 100644 --- a/internal/startup/startup.go +++ b/internal/startup/startup.go @@ -98,7 +98,7 @@ func Start() { if err != nil { fmt.Printf("Failed to create k8s client: %s \n", err.Error()) } - err = k8sClient2Instance.ActivateValidatingWebhookConfiguration(cert_manager.CaCertPath) + err = k8sClient2Instance.ActivateValidatingWebhookConfiguration() if err != nil { fmt.Printf("Failed to activate validating webhook configuration: %s \n", err.Error()) } diff --git a/pkg/cert-manager/cert-manager.go b/pkg/cert-manager/cert-manager.go index 00022ff3..6fdc8ceb 100644 --- a/pkg/cert-manager/cert-manager.go +++ b/pkg/cert-manager/cert-manager.go @@ -19,7 +19,6 @@ const certsFolder = "/etc/webhook-certs" const TlsCertPath = certsFolder + "/tls.crt" const TlsKeyPath = certsFolder + "/tls.key" const CaCertPath = certsFolder + "/ca.crt" -const CaKeyPath = certsFolder + "/ca.key" type AllCertificates struct { Cert []byte @@ -43,7 +42,7 @@ func doCertificatesExist() bool { return true } - return doesFileExist(TlsCertPath) && doesFileExist(TlsKeyPath) && doesFileExist(CaCertPath) && doesFileExist(CaKeyPath) + return doesFileExist(TlsCertPath) && doesFileExist(TlsKeyPath) && doesFileExist(CaCertPath) } func generateCertificates() { @@ -81,20 +80,18 @@ func generateCertificates() { Bytes: caBytes, }) - dnsNames := []string{"webhook-service", - "webhook-service.default", "webhook-service.default.svc"} - commonName := "datree-webhook-server.datree.svc" // TODO use namespace from config + webhookDNS := "datree-webhook-server.datree.svc" // TODO use namespace from config // server cert config cert := &x509.Certificate{ - DNSNames: dnsNames, + DNSNames: []string{webhookDNS}, SerialNumber: big.NewInt(1658), Subject: pkix.Name{ - CommonName: commonName, - Organization: []string{"velotio.com"}, + CommonName: fmt.Sprintf("/CN=%v", webhookDNS), + Organization: []string{"/CN=Datree Admission Controller Webhook CA"}, }, NotBefore: time.Now(), - NotAfter: time.Now().AddDate(1, 0, 0), + NotAfter: time.Now().AddDate(5, 0, 0), SubjectKeyId: []byte{1, 2, 3, 4, 6}, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, KeyUsage: x509.KeyUsageDigitalSignature, @@ -124,7 +121,12 @@ func generateCertificates() { Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(serverPrivKey), }) - + + err = writeFile(CaCertPath, caPEM) + if err != nil { + log.Panic(err) + } + err = writeFile(TlsCertPath, serverCertPEM) if err != nil { log.Panic(err) diff --git a/pkg/k8sClient2/k8sClient2.go b/pkg/k8sClient2/k8sClient2.go index 4485079c..f0616750 100644 --- a/pkg/k8sClient2/k8sClient2.go +++ b/pkg/k8sClient2/k8sClient2.go @@ -2,23 +2,18 @@ package k8sClient2 import ( "context" - "fmt" + cert_manager "github.com/datreeio/admission-webhook-datree/pkg/cert-manager" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" "os" ) -type k8sClientInterface interface { - doesValidatingWebhookConfigurationExist() (any, error) - applyValidatingWebhookConfiguration() (any, error) -} - -type k8sClient struct { +type K8sClient struct { clientset *kubernetes.Clientset } -func NewK8sClient() (*k8sClient, error) { +func NewK8sClient() (*K8sClient, error) { // creates the in-cluster config config, err := rest.InClusterConfig() if err != nil { @@ -30,21 +25,17 @@ func NewK8sClient() (*k8sClient, error) { return nil, err } - return &k8sClient{ + return &K8sClient{ clientset: clientsetInstance, }, nil } -func (kc *k8sClient) ActivateValidatingWebhookConfiguration(caCertPath string) error { - certificateContent, readFileError := os.ReadFile(caCertPath) +func (kc *K8sClient) ActivateValidatingWebhookConfiguration() error { + certificateContent, readFileError := os.ReadFile(cert_manager.CaCertPath) if readFileError != nil { return readFileError } - fmt.Println("@@@@@@@@@@@@@@@@@") - fmt.Println(string(certificateContent)) - fmt.Println("@@@@@@@@@@@@@@@@@") - existingValidatingWebhookConfiguration, err := kc.clientset.AdmissionregistrationV1().ValidatingWebhookConfigurations().Get(context.TODO(), "datree-webhook", metav1.GetOptions{}) if err != nil { return err @@ -66,7 +57,3 @@ func (kc *k8sClient) ActivateValidatingWebhookConfiguration(caCertPath string) e return nil } - -func (kc *k8sClient) applyValidatingWebhookConfiguration() error { - return nil -} diff --git a/pkg/server/server.go b/pkg/server/server.go index 8baa1ef6..de9fa561 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -2,12 +2,10 @@ package server import ( "errors" - "fmt" servicestate "github.com/datreeio/admission-webhook-datree/pkg/serviceState" "os" "path/filepath" - "github.com/datreeio/admission-webhook-datree/pkg/deploymentConfig" "gopkg.in/yaml.v2" ) @@ -71,24 +69,3 @@ func readConfigScanningFilters() (skipList []string, err error) { } return skipLists, nil } - -func ValidateCertificate() (certPath string, keyPath string, err error) { - tlsDir := `/run/secrets/tls` - tlsCertFile := `tls.crt` - tlsKeyFile := `tls.key` - - certPath = filepath.Join(tlsDir, tlsCertFile) - keyPath = filepath.Join(tlsDir, tlsKeyFile) - - if deploymentConfig.ShouldValidateCertificate { - if _, err := os.Stat(certPath); errors.Is(err, os.ErrNotExist) { - return "", "", fmt.Errorf("cert file doesn't exist") - } - - if _, err := os.Stat(keyPath); errors.Is(err, os.ErrNotExist) { - return "", "", fmt.Errorf("key file doesn't exist") - } - } - - return certPath, keyPath, nil -} From 8d7481c6980e3ca2f4301d29c5aec95212fd0981 Mon Sep 17 00:00:00 2001 From: Roy Hadad Date: Thu, 13 Jul 2023 20:09:01 +0300 Subject: [PATCH 6/8] refactor: extract some variables --- .../templates/deployment.yaml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/charts/datree-admission-webhook/templates/deployment.yaml b/charts/datree-admission-webhook/templates/deployment.yaml index a4fdc3d6..e45afaa7 100644 --- a/charts/datree-admission-webhook/templates/deployment.yaml +++ b/charts/datree-admission-webhook/templates/deployment.yaml @@ -1,5 +1,7 @@ {{- $emptyTokenMessage := "\n\t❌ The installation failed since the token that was provided is invalid.\n\t💡 To fix this issue:\n\t\t1. Get your token at: https://app.datree.io/settings/token-management\n\t\t2. Reinstall Datree and set your token using helm:\n\n\t\thelm install -n datree datree-webhook datree-webhook/datree-admission-webhook --create-namespace --set datree.token=\n" -}} {{- $uuidv4RegexPattern := "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$" -}} +{{- $webhookCertsVolumeName := "webhook-certs-volume" -}} +{{- $webhookCertsVolumeClaimName := "webhook-certs-volume-claim" -}} apiVersion: apps/v1 kind: Deployment metadata: @@ -107,14 +109,14 @@ spec: name: debug volumeMounts: - mountPath: /etc/webhook-certs - name: volume + name: {{ $webhookCertsVolumeName }} - name: webhook-config mountPath: /config readOnly: true volumes: - - name: volume + - name: {{ $webhookCertsVolumeName }} persistentVolumeClaim: - claimName: volume-claim + claimName: {{ $webhookCertsVolumeClaimName }} - name: webhook-config projected: sources: @@ -128,11 +130,11 @@ spec: apiVersion: v1 kind: PersistentVolumeClaim metadata: - name: volume-claim - namespace: datree + name: {{ $webhookCertsVolumeClaimName }} + namespace: {{ template "datree.namespace" . }} spec: accessModes: - ReadWriteMany resources: requests: - storage: 2Gi + storage: 1Gi From cdd567c3d6dfdf2632729dfa51f9d808db1298bc Mon Sep 17 00:00:00 2001 From: Roy Hadad Date: Sun, 16 Jul 2023 14:01:16 +0300 Subject: [PATCH 7/8] fix: update CA organization --- pkg/cert-manager/cert-manager.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cert-manager/cert-manager.go b/pkg/cert-manager/cert-manager.go index 6fdc8ceb..16b4c7fe 100644 --- a/pkg/cert-manager/cert-manager.go +++ b/pkg/cert-manager/cert-manager.go @@ -51,7 +51,7 @@ func generateCertificates() { ca := &x509.Certificate{ SerialNumber: big.NewInt(2020), Subject: pkix.Name{ - Organization: []string{"velotio.com"}, + Organization: []string{"/CN=Datree Admission Controller Webhook CA"}, }, NotBefore: time.Now(), NotAfter: time.Now().AddDate(1, 0, 0), From 7d91169d6bd70f362c940a055c743f0a2df963bd Mon Sep 17 00:00:00 2001 From: Roy Hadad Date: Sun, 16 Jul 2023 14:02:06 +0300 Subject: [PATCH 8/8] fix: duration --- pkg/cert-manager/cert-manager.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cert-manager/cert-manager.go b/pkg/cert-manager/cert-manager.go index 16b4c7fe..c3f4d6ad 100644 --- a/pkg/cert-manager/cert-manager.go +++ b/pkg/cert-manager/cert-manager.go @@ -54,7 +54,7 @@ func generateCertificates() { Organization: []string{"/CN=Datree Admission Controller Webhook CA"}, }, NotBefore: time.Now(), - NotAfter: time.Now().AddDate(1, 0, 0), + NotAfter: time.Now().AddDate(5, 0, 0), IsCA: true, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,