From 484744b07f1ca1780859baab6ddd2c12ebc8206f Mon Sep 17 00:00:00 2001 From: Maidn Date: Tue, 8 Sep 2026 15:24:09 +0200 Subject: [PATCH] feat: isolate delivery task credentials --- catalog/maidn-node-static-image.yaml | 122 ++++++++++++++++++++------- catalog/test-node-static-image.sh | 32 +++++++ 2 files changed, 124 insertions(+), 30 deletions(-) create mode 100644 catalog/test-node-static-image.sh diff --git a/catalog/maidn-node-static-image.yaml b/catalog/maidn-node-static-image.yaml index b3027fb..18755d0 100644 --- a/catalog/maidn-node-static-image.yaml +++ b/catalog/maidn-node-static-image.yaml @@ -1,7 +1,7 @@ apiVersion: tekton.dev/v1 kind: Task metadata: - name: maidn-node-static-image + name: maidn-git-clone namespace: tekton-pipelines spec: stepTemplate: @@ -23,28 +23,8 @@ spec: type: string - name: revision type: string - - name: image - type: string - - name: output-directory - type: string - - name: build-configuration - type: string - default: ci - - name: base-image - type: string - default: nginx:1.27-alpine - - name: target-directory - type: string - default: /www/target workspaces: - name: source - volumes: - - name: registry-credentials - secret: - secretName: forgejo-registry-credentials - items: - - key: .dockerconfigjson - path: config.json steps: - name: clone image: alpine/git:2.47.2 @@ -67,14 +47,43 @@ spec: git clone "$REPOSITORY_URL" "$SOURCE_PATH" git config --global --add safe.directory "$SOURCE_PATH" git -C "$SOURCE_PATH" checkout "$REVISION" +--- +apiVersion: tekton.dev/v1 +kind: Task +metadata: + name: maidn-node-static-build + namespace: tekton-pipelines +spec: + stepTemplate: + env: + - name: HOME + value: /tekton/home + securityContext: + runAsNonRoot: true + runAsUser: 1000 + runAsGroup: 1000 + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + params: + - name: output-directory + type: string + - name: build-configuration + type: string + default: ci + - name: target-directory + type: string + default: /www/target + workspaces: + - name: source + steps: - name: build-layer image: node:22-alpine workingDir: $(workspaces.source.path) env: - - name: IMAGE - value: $(params.image) - - name: REVISION - value: $(params.revision) - name: OUTPUT_DIRECTORY value: $(params.output-directory) - name: TARGET_DIRECTORY @@ -84,15 +93,11 @@ spec: script: | #!/bin/sh set -eu - case "$IMAGE" in git.pingu.pw/*) ;; *) exit 1 ;; esac - image_path=${IMAGE#git.pingu.pw/} - case "$image_path" in ''|*[!A-Za-z0-9._/-]*|/*|*//*|*..*|*/) exit 1 ;; esac - case "$REVISION" in [A-Za-z0-9]*) ;; *) exit 1 ;; esac - case "$REVISION" in *[!A-Za-z0-9._/-]*|*..*|*//*|*/) exit 1 ;; esac case "$OUTPUT_DIRECTORY" in ''|/*|-*|*[!A-Za-z0-9._/-]*|*..*|*//*|*/) exit 1 ;; esac case "$TARGET_DIRECTORY" in /*) ;; *) exit 1 ;; esac target_path=${TARGET_DIRECTORY#/} case "$target_path" in ''|-*|*[!A-Za-z0-9._/-]*|*..*|*//*|*/) exit 1 ;; esac + case "$BUILD_CONFIGURATION" in ''|-*|*[!A-Za-z0-9._-]*) exit 1 ;; esac # ponytail: no lockfile; skip install scripts and use npm ci when package-lock.json is committed. npm install --ignore-scripts --no-audit --no-fund --package-lock=false npm run build -- --configuration "$BUILD_CONFIGURATION" @@ -102,6 +107,63 @@ spec: mkdir -p "$layer_dir/$target_path" cp -R "$OUTPUT_DIRECTORY"/. "$layer_dir/$target_path/" tar -C "$layer_dir" -cf layer.tar "$target_path" +--- +apiVersion: tekton.dev/v1 +kind: Task +metadata: + name: maidn-node-static-push + namespace: tekton-pipelines +spec: + stepTemplate: + env: + - name: HOME + value: /tekton/home + securityContext: + runAsNonRoot: true + runAsUser: 1000 + runAsGroup: 1000 + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + params: + - name: image + type: string + - name: revision + type: string + - name: base-image + type: string + default: nginx:1.27-alpine + workspaces: + - name: source + volumes: + - name: registry-credentials + secret: + secretName: forgejo-registry-credentials + items: + - key: .dockerconfigjson + path: config.json + steps: + - name: validate-inputs + image: alpine:3.21.3 + env: + - name: IMAGE + value: $(params.image) + - name: REVISION + value: $(params.revision) + - name: BASE_IMAGE + value: $(params.base-image) + script: | + #!/bin/sh + set -eu + case "$IMAGE" in git.pingu.pw/*) ;; *) exit 1 ;; esac + image_path=${IMAGE#git.pingu.pw/} + case "$image_path" in ''|*[!A-Za-z0-9._/-]*|/*|*//*|*..*|*/) exit 1 ;; esac + case "$REVISION" in [A-Za-z0-9]*) ;; *) exit 1 ;; esac + case "$REVISION" in *[!A-Za-z0-9._/-]*|*..*|*//*|*/) exit 1 ;; esac + case "$BASE_IMAGE" in ''|-*|*[!A-Za-z0-9._/@:-]*|/*|*//*|*..*) exit 1 ;; esac - name: push image: gcr.io/go-containerregistry/crane:v0.21.7 args: diff --git a/catalog/test-node-static-image.sh b/catalog/test-node-static-image.sh new file mode 100644 index 0000000..d16397c --- /dev/null +++ b/catalog/test-node-static-image.sh @@ -0,0 +1,32 @@ +#!/bin/sh +set -eu + +root=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd) +catalog="$root/catalog/maidn-node-static-image.yaml" +tmp=$(mktemp -d) +trap 'rm -rf "$tmp"' EXIT + +task() { + awk -v name="$1" ' + /^---$/ { if (found) exit } + $0 == " name: " name { found=1 } + found { print } + ' "$catalog" +} + +[ "$(grep -c '^apiVersion: tekton.dev/v1$' "$catalog")" -eq 3 ] +[ "$(grep -c '^kind: Task$' "$catalog")" -eq 3 ] +[ "$(grep -cF 'runAsNonRoot: true' "$catalog")" -eq 3 ] +[ "$(grep -cF 'forgejo-registry-credentials' "$catalog")" -eq 1 ] + +for name in maidn-git-clone maidn-node-static-build maidn-node-static-push; do + task "$name" > "$tmp/$name" + grep -qF " name: $name" "$tmp/$name" + grep -qF ' - name: source' "$tmp/$name" +done + +grep -qF 'git clone "$REPOSITORY_URL" "$SOURCE_PATH"' "$tmp/maidn-git-clone" +grep -qF 'tar -C "$layer_dir" -cf layer.tar "$target_path"' "$tmp/maidn-node-static-build" +grep -qF 'image: gcr.io/go-containerregistry/crane:v0.21.7' "$tmp/maidn-node-static-push" +grep -qF ' - append' "$tmp/maidn-node-static-push" +grep -qF 'mountPath: /tekton/home/.docker' "$tmp/maidn-node-static-push" -- 2.43.7