From 0e3f99745805157f91db27019c8099cb31378b34 Mon Sep 17 00:00:00 2001 From: Michael Fornaro <20387402+xUnholy@users.noreply.github.com> Date: Wed, 10 Jan 2024 18:45:51 +1100 Subject: [PATCH] fix: escaped chars and workflows Signed-off-by: Michael Fornaro <20387402+xUnholy@users.noreply.github.com> --- .github/workflows/build-docker.yaml | 47 +++++++++++++++++++++++++++ kubernetes/static/deployment.yaml | 9 +++-- kubernetes/static/kustomization.yaml | 11 +++++++ kubernetes/static/serviceaccount.yaml | 6 ++++ main.go | 47 +++++++++++++++++++++++---- 5 files changed, 112 insertions(+), 8 deletions(-) create mode 100644 .github/workflows/build-docker.yaml create mode 100644 kubernetes/static/kustomization.yaml create mode 100644 kubernetes/static/serviceaccount.yaml diff --git a/.github/workflows/build-docker.yaml b/.github/workflows/build-docker.yaml new file mode 100644 index 0000000..61c8de3 --- /dev/null +++ b/.github/workflows/build-docker.yaml @@ -0,0 +1,47 @@ +name: Build and Push Docker Images + +on: + workflow_dispatch: {} + push: + branches: + - main + paths: + - .github/workflows/build-docker.yaml + - Dockerfile + +jobs: + build-and-push: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3 + with: + platforms: all + + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3 + with: + install: true + version: latest + + - name: Login to GHCR + uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and Push + if: github.ref != 'refs/heads/master' + uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5 + with: + context: . + file: Dockerfile + platforms: linux/amd64 + push: true + tags: | + ghcr.io/xunholy/images/kustomize-mutating-webhook:latest diff --git a/kubernetes/static/deployment.yaml b/kubernetes/static/deployment.yaml index 828fbff..a5ee1b8 100644 --- a/kubernetes/static/deployment.yaml +++ b/kubernetes/static/deployment.yaml @@ -7,14 +7,17 @@ metadata: labels: app: *name spec: - replicas: 1 + replicas: 3 selector: matchLabels: &labels app: *name template: metadata: - labels: *labels + labels: + <<: *labels spec: + serviceAccountName: kustomize-mutating-webhook + automountServiceAccountToken: true securityContext: runAsNonRoot: true seccompProfile: @@ -22,6 +25,7 @@ spec: containers: - name: webhook image: ghcr.io/xunholy/images/kustomize-mutating-webhook:latest + imagePullPolicy: Always env: - name: LOG_LEVEL value: info @@ -31,6 +35,7 @@ spec: allowPrivilegeEscalation: false readOnlyRootFilesystem: true runAsUser: 1000 + runAsGroup: 1000 capabilities: drop: - ALL diff --git a/kubernetes/static/kustomization.yaml b/kubernetes/static/kustomization.yaml new file mode 100644 index 0000000..9f07b2e --- /dev/null +++ b/kubernetes/static/kustomization.yaml @@ -0,0 +1,11 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - certificate.yaml + - deployment.yaml + - issuer.yaml + - mutating-webhook-configuration.yaml + - network-policy.yaml + - service.yaml + - serviceaccount.yaml diff --git a/kubernetes/static/serviceaccount.yaml b/kubernetes/static/serviceaccount.yaml new file mode 100644 index 0000000..5d920ff --- /dev/null +++ b/kubernetes/static/serviceaccount.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: kustomize-mutating-webhook + namespace: flux-system +automountServiceAccountToken: false diff --git a/main.go b/main.go index e46fc8a..4042236 100644 --- a/main.go +++ b/main.go @@ -30,7 +30,8 @@ func init() { // Determine log level from environment variable if logLevel, ok := os.LookupEnv("LOG_LEVEL"); ok { - level, err := zerolog.ParseLevel(logLevel) + var err error + level, err = zerolog.ParseLevel(logLevel) if err != nil { log.Warn().Msgf("Invalid log level '%s'. Falling back to '%s'", logLevel, level) } @@ -101,7 +102,8 @@ func handleMutate(w http.ResponseWriter, r *http.Request) { Allowed: true, }, } - // Send the response to avoid locking deletcion + + // Send the response to avoid locking deletion respondWithAdmissionReview(w, admissionResponse) return } @@ -117,13 +119,33 @@ func handleMutate(w http.ResponseWriter, r *http.Request) { // Process the AdmissionReview request and create a patch var patch []map[string]interface{} + + // Ensure /spec/postBuild exists + if _, found, _ := unstructured.NestedMap(obj.Object, "spec", "postBuild"); !found { + patch = append(patch, map[string]interface{}{ + "op": "add", + "path": "/spec/postBuild", + "value": map[string]interface{}{}, + }) + } + + // Ensure /spec/postBuild/substitute exists + if _, found, _ := unstructured.NestedMap(obj.Object, "spec", "postBuild", "substitute"); !found { + patch = append(patch, map[string]interface{}{ + "op": "add", + "path": "/spec/postBuild/substitute", + "value": map[string]interface{}{}, + }) + } + + // Add key-value pairs from appConfig to /spec/postBuild/substitute for key, value := range appConfig { - patchOperation := map[string]interface{}{ + escapedKey := escapeJsonPointer(key) + patch = append(patch, map[string]interface{}{ "op": "add", - "path": "/spec/postBuild/substitute/" + key, + "path": "/spec/postBuild/substitute/" + escapedKey, "value": value, - } - patch = append(patch, patchOperation) + }) } patchBytes, _ := json.Marshal(patch) @@ -162,6 +184,13 @@ func respondWithAdmissionReview(w http.ResponseWriter, admissionResponse v1.Admi } } +// escapeJsonPointer escapes special characters in JSON pointer +func escapeJsonPointer(value string) string { + value = strings.ReplaceAll(value, "~", "~0") + value = strings.ReplaceAll(value, "/", "~1") + return value +} + func main() { // Log the starting of the server log.Info().Msg("Starting the webhook server on port 8443") @@ -170,9 +199,15 @@ func main() { configMapPath := "/etc/config" appConfig = readConfigMap(configMapPath) + log.Debug().Msg("Loaded appConfig:") + for key, value := range appConfig { + log.Debug().Msgf("Config - Key: %s, Value: %s", key, value) + } + // Set up HTTP handler and server http.HandleFunc("/mutate", handleMutate) if err := http.ListenAndServeTLS(":8443", "/etc/webhook/certs/tls.crt", "/etc/webhook/certs/tls.key", nil); err != nil { log.Fatal().Err(err).Msg("Failed to start server") + os.Exit(1) } }