From c2900400a42085a0b43fda498348e9a8451812e4 Mon Sep 17 00:00:00 2001 From: Will Anderson Date: Tue, 5 May 2026 04:07:35 -0500 Subject: [PATCH] ci: switch runner git clones from HTTPS+CF Access to SSH deploy key --- servers/legion/k8s/gitea-runner/Dockerfile | 20 +++----- .../legion/k8s/gitea-runner/deployment.yaml | 18 ++++--- .../k8s/gitea-runner/external-secrets.yaml | 43 +++++++---------- .../legion/k8s/gitea-runner/git-ssh-init.sh | 48 +++++++++++++++++++ 4 files changed, 78 insertions(+), 51 deletions(-) create mode 100644 servers/legion/k8s/gitea-runner/git-ssh-init.sh diff --git a/servers/legion/k8s/gitea-runner/Dockerfile b/servers/legion/k8s/gitea-runner/Dockerfile index 59f8d1d..361f71e 100644 --- a/servers/legion/k8s/gitea-runner/Dockerfile +++ b/servers/legion/k8s/gitea-runner/Dockerfile @@ -96,17 +96,9 @@ RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \ # build containers with its own entrypoint to keep them alive between # steps, and overriding it breaks job execution. -# In-cluster git redirect — GKE runners resolve the internal Gitea service -# directly, bypassing Cloudflare Access. This insteadOf rule rewrites any -# clone/fetch of the public URL to the in-cluster service URL so CI jobs work -# without CF Access headers inside the GKE cluster. -# -# On Legion runners this is overridden at runtime by git-cf-access-init.sh -# (which sets the reverse redirect + CF Access headers). The system-level rule -# here is a safe baseline; the init script wins because it runs after. -RUN git config --system \ - url."http://gitea.gitea.svc.cluster.local:3000/".insteadOf \ - "https://git.neuralplatform.ai/" - -COPY git-cf-access-init.sh /usr/local/bin/git-cf-access-init.sh -RUN chmod +x /usr/local/bin/git-cf-access-init.sh +# SSH-based git clone init script. +# Sourced before every CI step via BASH_ENV (set in deployment.yaml). +# Writes GITEA_SSH_PRIVATE_KEY to ~/.ssh/gitea_key and rewrites HTTPS +# Gitea URLs to SSH so actions/checkout and git clone both use SSH auth. +COPY git-ssh-init.sh /usr/local/bin/git-ssh-init.sh +RUN chmod +x /usr/local/bin/git-ssh-init.sh diff --git a/servers/legion/k8s/gitea-runner/deployment.yaml b/servers/legion/k8s/gitea-runner/deployment.yaml index 970d2d0..615ee58 100644 --- a/servers/legion/k8s/gitea-runner/deployment.yaml +++ b/servers/legion/k8s/gitea-runner/deployment.yaml @@ -8,7 +8,7 @@ metadata: labels: app: gitea-runner annotations: - config-version: "2026-05-05-gke-gitea-url" + config-version: "2026-05-05-ssh-clone" spec: replicas: 1 selector: @@ -19,7 +19,7 @@ spec: labels: app: gitea-runner annotations: - config-version: "2026-05-05-gke-gitea-url" + config-version: "2026-05-05-ssh-clone" spec: securityContext: runAsNonRoot: false @@ -52,9 +52,8 @@ spec: # /usr/local/bin/git-cf-access-init.sh before every step, # which sets up the redirect + headers. env: - CF_ACCESS_CLIENT_ID: "${CF_ACCESS_CLIENT_ID}" - CF_ACCESS_CLIENT_SECRET: "${CF_ACCESS_CLIENT_SECRET}" - BASH_ENV: "/usr/local/bin/git-cf-access-init.sh" + GITEA_SSH_PRIVATE_KEY: "${GITEA_SSH_PRIVATE_KEY}" + BASH_ENV: "/usr/local/bin/git-ssh-init.sh" extra_hosts: [] EOF envFrom: @@ -101,7 +100,7 @@ metadata: labels: app: neuron-technologies-runner annotations: - config-version: "2026-05-05-gke-gitea-url" + config-version: "2026-05-05-ssh-clone" spec: replicas: 2 selector: @@ -112,7 +111,7 @@ spec: labels: app: neuron-technologies-runner annotations: - config-version: "2026-05-05-gke-gitea-url" + config-version: "2026-05-05-ssh-clone" spec: securityContext: runAsNonRoot: false @@ -145,9 +144,8 @@ spec: # /usr/local/bin/git-cf-access-init.sh before every step, # which sets up the redirect + headers. env: - CF_ACCESS_CLIENT_ID: "${CF_ACCESS_CLIENT_ID}" - CF_ACCESS_CLIENT_SECRET: "${CF_ACCESS_CLIENT_SECRET}" - BASH_ENV: "/usr/local/bin/git-cf-access-init.sh" + GITEA_SSH_PRIVATE_KEY: "${GITEA_SSH_PRIVATE_KEY}" + BASH_ENV: "/usr/local/bin/git-ssh-init.sh" extra_hosts: [] EOF envFrom: diff --git a/servers/legion/k8s/gitea-runner/external-secrets.yaml b/servers/legion/k8s/gitea-runner/external-secrets.yaml index 14fe47d..553295e 100644 --- a/servers/legion/k8s/gitea-runner/external-secrets.yaml +++ b/servers/legion/k8s/gitea-runner/external-secrets.yaml @@ -1,20 +1,19 @@ --- # gitea-runner-secret — neural-platform org runner token # -# GITEA_INSTANCE_URL stays as the in-cluster URL — the act_runner daemon -# polls it constantly and we don't want every poll to hit Cloudflare Access. -# Build containers, however, need the public URL because they run with -# network: host and can't resolve gitea.git.svc.cluster.local. The -# git-cf-access-init.sh entrypoint in the ci-base image rewrites the -# in-cluster URL to https://git.neuralplatform.ai with the CF Access -# headers from CF_ACCESS_CLIENT_ID / CF_ACCESS_CLIENT_SECRET below. +# GITEA_INSTANCE_URL: act_runner daemon polls git.neuralplatform.ai via HTTPS. +# GITEA_SSH_PRIVATE_KEY: ED25519 deploy key for SSH-based git clones inside +# build containers. git-ssh-init.sh (sourced via BASH_ENV) writes this key +# to ~/.ssh/gitea_key and rewrites HTTPS Gitea URLs to SSH so that +# actions/checkout and plain `git clone` both use SSH auth without any +# HTTPS credential or CF Access token. apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: gitea-runner-secret namespace: ci annotations: - force-sync: "2026-05-05-gke-gitea-url" + force-sync: "2026-05-05-ssh-clone" spec: refreshInterval: 1h secretStoreRef: @@ -27,21 +26,16 @@ spec: data: GITEA_INSTANCE_URL: "https://git.neuralplatform.ai" GITEA_RUNNER_REGISTRATION_TOKEN: "{{ .runner_token }}" - CF_ACCESS_CLIENT_ID: "{{ .cf_access_client_id }}" - CF_ACCESS_CLIENT_SECRET: "{{ .cf_access_client_secret }}" + GITEA_SSH_PRIVATE_KEY: "{{ .ci_ssh_private_key }}" data: - secretKey: runner_token remoteRef: key: secret/data/gitea property: runner_token - - secretKey: cf_access_client_id + - secretKey: ci_ssh_private_key remoteRef: - key: secret/data/gitea-runner-cf-access - property: client_id - - secretKey: cf_access_client_secret - remoteRef: - key: secret/data/gitea-runner-cf-access - property: client_secret + key: secret/data/gitea + property: ci_ssh_private_key --- # neuron-technologies-runner-secret — neuron-technologies org runner token apiVersion: external-secrets.io/v1beta1 @@ -50,7 +44,7 @@ metadata: name: neuron-technologies-runner-secret namespace: ci annotations: - force-sync: "2026-05-05-gke-gitea-url" + force-sync: "2026-05-05-ssh-clone" spec: refreshInterval: 1h secretStoreRef: @@ -63,18 +57,13 @@ spec: data: GITEA_INSTANCE_URL: "https://git.neuralplatform.ai" GITEA_RUNNER_REGISTRATION_TOKEN: "{{ .runner_token }}" - CF_ACCESS_CLIENT_ID: "{{ .cf_access_client_id }}" - CF_ACCESS_CLIENT_SECRET: "{{ .cf_access_client_secret }}" + GITEA_SSH_PRIVATE_KEY: "{{ .ci_ssh_private_key }}" data: - secretKey: runner_token remoteRef: key: secret/data/gitea property: neuron_technologies_runner_token - - secretKey: cf_access_client_id + - secretKey: ci_ssh_private_key remoteRef: - key: secret/data/gitea-runner-cf-access - property: client_id - - secretKey: cf_access_client_secret - remoteRef: - key: secret/data/gitea-runner-cf-access - property: client_secret + key: secret/data/gitea + property: ci_ssh_private_key diff --git a/servers/legion/k8s/gitea-runner/git-ssh-init.sh b/servers/legion/k8s/gitea-runner/git-ssh-init.sh new file mode 100644 index 0000000..2018dbe --- /dev/null +++ b/servers/legion/k8s/gitea-runner/git-ssh-init.sh @@ -0,0 +1,48 @@ +#!/bin/sh +# git-ssh-init.sh +# +# Sets up SSH authentication for git operations inside CI build containers. +# +# How this gets invoked: +# act_runner runs each step via a non-interactive bash invocation. +# Setting BASH_ENV=/usr/local/bin/git-ssh-init.sh in act_runner's +# container.env causes bash to source this before any step's commands. +# (See servers/legion/k8s/gitea-runner/deployment.yaml.) +# +# What it does: +# 1. Writes GITEA_SSH_PRIVATE_KEY (from the runner secret) to ~/.ssh/gitea_key +# 2. Creates an ~/.ssh/config entry so git uses that key for git.neuralplatform.ai +# 3. Sets a git insteadOf rule to rewrite HTTPS Gitea URLs to SSH, +# so `actions/checkout` and any direct `git clone https://...` also use SSH +# +# Idempotent — safe to re-run on every step. + +if [ -n "${GITEA_SSH_PRIVATE_KEY:-}" ]; then + mkdir -p ~/.ssh + chmod 700 ~/.ssh + + # Write the private key + printf '%s\n' "${GITEA_SSH_PRIVATE_KEY}" > ~/.ssh/gitea_key + chmod 600 ~/.ssh/gitea_key + + # SSH config — use this key for git.neuralplatform.ai, skip host key checking + # (build containers are ephemeral; we don't persist a known_hosts file) + cat > ~/.ssh/gitea_config << 'EOF' +Host git.neuralplatform.ai + HostName git.neuralplatform.ai + User git + IdentityFile ~/.ssh/gitea_key + StrictHostKeyChecking no + UserKnownHostsFile /dev/null +EOF + chmod 600 ~/.ssh/gitea_config + + # Point SSH at our per-job config (merge with any existing config if present) + export GIT_SSH_COMMAND="ssh -F ~/.ssh/gitea_config" + + # Rewrite HTTPS Gitea URLs → SSH so `actions/checkout` and plain `git clone` + # both go through SSH without any HTTPS credential or CF Access token needed + git config --global \ + url."git@git.neuralplatform.ai:".insteadOf \ + "https://git.neuralplatform.ai/" 2>/dev/null || true +fi