From a3f25456e429b49e1fcc6770d93e6b19d81cf1d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zo=C3=AB?= Date: Sat, 30 May 2026 14:46:01 -0700 Subject: [PATCH] feat: CI pipeline, ArgoCD app, ExternalSecrets, and Woodpecker config - .woodpecker.yaml: build+push agent and dispatcher images to Harbor on mainline/tag - k8s/argocd-app.yaml: ArgoCD Application syncing k8s/ from mainline - k8s/externalsecrets/: ExternalSecret manifests for all 19 agent AppRole creds + dispatcher - ArgoCD app applied to cluster, Woodpecker repo enabled with harbor secrets --- .woodpecker.yaml | 75 +++ k8s/argocd-app.yaml | 27 ++ k8s/externalsecrets/agent-approles.yaml | 512 ++++++++++++++++++++ k8s/externalsecrets/dispatcher-approle.yaml | 24 + 4 files changed, 638 insertions(+) create mode 100644 .woodpecker.yaml create mode 100644 k8s/argocd-app.yaml create mode 100644 k8s/externalsecrets/agent-approles.yaml create mode 100644 k8s/externalsecrets/dispatcher-approle.yaml diff --git a/.woodpecker.yaml b/.woodpecker.yaml new file mode 100644 index 0000000..5f681a8 --- /dev/null +++ b/.woodpecker.yaml @@ -0,0 +1,75 @@ +--- +# AutoJanet CI Pipeline +# Builds and pushes two images to Harbor: +# - registry.ctz.fyi/autojanet/agent:latest (+ git SHA tag) +# - registry.ctz.fyi/autojanet/dispatcher:latest (+ git SHA tag) +# Triggered on push to mainline or semver tags. + +when: + - event: push + branch: mainline + - event: tag + ref: refs/tags/v* + +steps: + # ── Agent image ───────────────────────────────────────────────────────────── + - name: build-agent + image: woodpeckerci/plugin-docker-buildx + settings: + registry: registry.ctz.fyi + repo: registry.ctz.fyi/autojanet/agent + dockerfile: container/Dockerfile + context: . + username: + from_secret: harbor_user + password: + from_secret: harbor_password + tags: + - latest + - "${CI_COMMIT_SHA:0:12}" + cache_from: registry.ctz.fyi/autojanet/agent:latest + platforms: linux/amd64 + when: + - event: push + branch: mainline + - event: tag + + # ── Dispatcher image ───────────────────────────────────────────────────────── + - name: build-dispatcher + image: woodpeckerci/plugin-docker-buildx + settings: + registry: registry.ctz.fyi + repo: registry.ctz.fyi/autojanet/dispatcher + dockerfile: container/Dockerfile.dispatcher + context: . + username: + from_secret: harbor_user + password: + from_secret: harbor_password + tags: + - latest + - "${CI_COMMIT_SHA:0:12}" + cache_from: registry.ctz.fyi/autojanet/dispatcher:latest + platforms: linux/amd64 + when: + - event: push + branch: mainline + - event: tag + + # ── Trivy scan agent image ─────────────────────────────────────────────────── + - name: trivy-agent + image: aquasec/trivy:latest + commands: + - trivy image --exit-code 1 --severity HIGH,CRITICAL + --ignore-unfixed + registry.ctz.fyi/autojanet/agent:${CI_COMMIT_SHA:0:12} + environment: + TRIVY_USERNAME: + from_secret: harbor_user + TRIVY_PASSWORD: + from_secret: harbor_password + when: + - event: push + branch: mainline + - event: tag + failure: ignore # warn only — don't block on upstream CVEs in base image diff --git a/k8s/argocd-app.yaml b/k8s/argocd-app.yaml new file mode 100644 index 0000000..07b75d9 --- /dev/null +++ b/k8s/argocd-app.yaml @@ -0,0 +1,27 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: autojanet + namespace: argocd +spec: + project: default + source: + repoURL: https://git.ctz.fyi/zoe/autojanet.git + targetRevision: mainline + path: k8s + destination: + server: https://kubernetes.default.svc + namespace: autojanet + syncPolicy: + automated: + prune: true + selfHeal: true + syncOptions: + - CreateNamespace=true + - ServerSideApply=true + retry: + limit: 5 + backoff: + duration: 30s + maxDuration: 5m + factor: 2 diff --git a/k8s/externalsecrets/agent-approles.yaml b/k8s/externalsecrets/agent-approles.yaml new file mode 100644 index 0000000..752632a --- /dev/null +++ b/k8s/externalsecrets/agent-approles.yaml @@ -0,0 +1,512 @@ +--- +# ExternalSecret: agent-pm +# Pulls AppRole credentials from OpenBao into a k8s Secret +# so the Job can authenticate and fetch runtime secrets. +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: agent-pm-approle + namespace: autojanet +spec: + refreshInterval: 1h + secretStoreRef: + name: openbao + kind: ClusterSecretStore + target: + name: agent-pm-approle + creationPolicy: Owner + data: + - secretKey: role_id + remoteRef: + key: autojanet/pm/approle + property: role_id + - secretKey: secret_id + remoteRef: + key: autojanet/pm/approle + property: secret_id +--- +--- +# ExternalSecret: agent-coder +# Pulls AppRole credentials from OpenBao into a k8s Secret +# so the Job can authenticate and fetch runtime secrets. +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: agent-coder-approle + namespace: autojanet +spec: + refreshInterval: 1h + secretStoreRef: + name: openbao + kind: ClusterSecretStore + target: + name: agent-coder-approle + creationPolicy: Owner + data: + - secretKey: role_id + remoteRef: + key: autojanet/coder/approle + property: role_id + - secretKey: secret_id + remoteRef: + key: autojanet/coder/approle + property: secret_id +--- +--- +# ExternalSecret: agent-code-reviewer +# Pulls AppRole credentials from OpenBao into a k8s Secret +# so the Job can authenticate and fetch runtime secrets. +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: agent-code-reviewer-approle + namespace: autojanet +spec: + refreshInterval: 1h + secretStoreRef: + name: openbao + kind: ClusterSecretStore + target: + name: agent-code-reviewer-approle + creationPolicy: Owner + data: + - secretKey: role_id + remoteRef: + key: autojanet/code-reviewer/approle + property: role_id + - secretKey: secret_id + remoteRef: + key: autojanet/code-reviewer/approle + property: secret_id +--- +--- +# ExternalSecret: agent-test-engineer +# Pulls AppRole credentials from OpenBao into a k8s Secret +# so the Job can authenticate and fetch runtime secrets. +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: agent-test-engineer-approle + namespace: autojanet +spec: + refreshInterval: 1h + secretStoreRef: + name: openbao + kind: ClusterSecretStore + target: + name: agent-test-engineer-approle + creationPolicy: Owner + data: + - secretKey: role_id + remoteRef: + key: autojanet/test-engineer/approle + property: role_id + - secretKey: secret_id + remoteRef: + key: autojanet/test-engineer/approle + property: secret_id +--- +--- +# ExternalSecret: agent-devsecops +# Pulls AppRole credentials from OpenBao into a k8s Secret +# so the Job can authenticate and fetch runtime secrets. +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: agent-devsecops-approle + namespace: autojanet +spec: + refreshInterval: 1h + secretStoreRef: + name: openbao + kind: ClusterSecretStore + target: + name: agent-devsecops-approle + creationPolicy: Owner + data: + - secretKey: role_id + remoteRef: + key: autojanet/devsecops/approle + property: role_id + - secretKey: secret_id + remoteRef: + key: autojanet/devsecops/approle + property: secret_id +--- +--- +# ExternalSecret: agent-secops +# Pulls AppRole credentials from OpenBao into a k8s Secret +# so the Job can authenticate and fetch runtime secrets. +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: agent-secops-approle + namespace: autojanet +spec: + refreshInterval: 1h + secretStoreRef: + name: openbao + kind: ClusterSecretStore + target: + name: agent-secops-approle + creationPolicy: Owner + data: + - secretKey: role_id + remoteRef: + key: autojanet/secops/approle + property: role_id + - secretKey: secret_id + remoteRef: + key: autojanet/secops/approle + property: secret_id +--- +--- +# ExternalSecret: agent-sre +# Pulls AppRole credentials from OpenBao into a k8s Secret +# so the Job can authenticate and fetch runtime secrets. +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: agent-sre-approle + namespace: autojanet +spec: + refreshInterval: 1h + secretStoreRef: + name: openbao + kind: ClusterSecretStore + target: + name: agent-sre-approle + creationPolicy: Owner + data: + - secretKey: role_id + remoteRef: + key: autojanet/sre/approle + property: role_id + - secretKey: secret_id + remoteRef: + key: autojanet/sre/approle + property: secret_id +--- +--- +# ExternalSecret: agent-kubernetes-pilot +# Pulls AppRole credentials from OpenBao into a k8s Secret +# so the Job can authenticate and fetch runtime secrets. +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: agent-kubernetes-pilot-approle + namespace: autojanet +spec: + refreshInterval: 1h + secretStoreRef: + name: openbao + kind: ClusterSecretStore + target: + name: agent-kubernetes-pilot-approle + creationPolicy: Owner + data: + - secretKey: role_id + remoteRef: + key: autojanet/kubernetes-pilot/approle + property: role_id + - secretKey: secret_id + remoteRef: + key: autojanet/kubernetes-pilot/approle + property: secret_id +--- +--- +# ExternalSecret: agent-linux-admin +# Pulls AppRole credentials from OpenBao into a k8s Secret +# so the Job can authenticate and fetch runtime secrets. +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: agent-linux-admin-approle + namespace: autojanet +spec: + refreshInterval: 1h + secretStoreRef: + name: openbao + kind: ClusterSecretStore + target: + name: agent-linux-admin-approle + creationPolicy: Owner + data: + - secretKey: role_id + remoteRef: + key: autojanet/linux-admin/approle + property: role_id + - secretKey: secret_id + remoteRef: + key: autojanet/linux-admin/approle + property: secret_id +--- +--- +# ExternalSecret: agent-systems-engineer +# Pulls AppRole credentials from OpenBao into a k8s Secret +# so the Job can authenticate and fetch runtime secrets. +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: agent-systems-engineer-approle + namespace: autojanet +spec: + refreshInterval: 1h + secretStoreRef: + name: openbao + kind: ClusterSecretStore + target: + name: agent-systems-engineer-approle + creationPolicy: Owner + data: + - secretKey: role_id + remoteRef: + key: autojanet/systems-engineer/approle + property: role_id + - secretKey: secret_id + remoteRef: + key: autojanet/systems-engineer/approle + property: secret_id +--- +--- +# ExternalSecret: agent-networking +# Pulls AppRole credentials from OpenBao into a k8s Secret +# so the Job can authenticate and fetch runtime secrets. +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: agent-networking-approle + namespace: autojanet +spec: + refreshInterval: 1h + secretStoreRef: + name: openbao + kind: ClusterSecretStore + target: + name: agent-networking-approle + creationPolicy: Owner + data: + - secretKey: role_id + remoteRef: + key: autojanet/networking/approle + property: role_id + - secretKey: secret_id + remoteRef: + key: autojanet/networking/approle + property: secret_id +--- +--- +# ExternalSecret: agent-dba +# Pulls AppRole credentials from OpenBao into a k8s Secret +# so the Job can authenticate and fetch runtime secrets. +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: agent-dba-approle + namespace: autojanet +spec: + refreshInterval: 1h + secretStoreRef: + name: openbao + kind: ClusterSecretStore + target: + name: agent-dba-approle + creationPolicy: Owner + data: + - secretKey: role_id + remoteRef: + key: autojanet/dba/approle + property: role_id + - secretKey: secret_id + remoteRef: + key: autojanet/dba/approle + property: secret_id +--- +--- +# ExternalSecret: agent-prometheus-expert +# Pulls AppRole credentials from OpenBao into a k8s Secret +# so the Job can authenticate and fetch runtime secrets. +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: agent-prometheus-expert-approle + namespace: autojanet +spec: + refreshInterval: 1h + secretStoreRef: + name: openbao + kind: ClusterSecretStore + target: + name: agent-prometheus-expert-approle + creationPolicy: Owner + data: + - secretKey: role_id + remoteRef: + key: autojanet/prometheus-expert/approle + property: role_id + - secretKey: secret_id + remoteRef: + key: autojanet/prometheus-expert/approle + property: secret_id +--- +--- +# ExternalSecret: agent-tofu-engineer +# Pulls AppRole credentials from OpenBao into a k8s Secret +# so the Job can authenticate and fetch runtime secrets. +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: agent-tofu-engineer-approle + namespace: autojanet +spec: + refreshInterval: 1h + secretStoreRef: + name: openbao + kind: ClusterSecretStore + target: + name: agent-tofu-engineer-approle + creationPolicy: Owner + data: + - secretKey: role_id + remoteRef: + key: autojanet/tofu-engineer/approle + property: role_id + - secretKey: secret_id + remoteRef: + key: autojanet/tofu-engineer/approle + property: secret_id +--- +--- +# ExternalSecret: agent-release-manager +# Pulls AppRole credentials from OpenBao into a k8s Secret +# so the Job can authenticate and fetch runtime secrets. +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: agent-release-manager-approle + namespace: autojanet +spec: + refreshInterval: 1h + secretStoreRef: + name: openbao + kind: ClusterSecretStore + target: + name: agent-release-manager-approle + creationPolicy: Owner + data: + - secretKey: role_id + remoteRef: + key: autojanet/release-manager/approle + property: role_id + - secretKey: secret_id + remoteRef: + key: autojanet/release-manager/approle + property: secret_id +--- +--- +# ExternalSecret: agent-doc-updater +# Pulls AppRole credentials from OpenBao into a k8s Secret +# so the Job can authenticate and fetch runtime secrets. +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: agent-doc-updater-approle + namespace: autojanet +spec: + refreshInterval: 1h + secretStoreRef: + name: openbao + kind: ClusterSecretStore + target: + name: agent-doc-updater-approle + creationPolicy: Owner + data: + - secretKey: role_id + remoteRef: + key: autojanet/doc-updater/approle + property: role_id + - secretKey: secret_id + remoteRef: + key: autojanet/doc-updater/approle + property: secret_id +--- +--- +# ExternalSecret: agent-doc-writer +# Pulls AppRole credentials from OpenBao into a k8s Secret +# so the Job can authenticate and fetch runtime secrets. +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: agent-doc-writer-approle + namespace: autojanet +spec: + refreshInterval: 1h + secretStoreRef: + name: openbao + kind: ClusterSecretStore + target: + name: agent-doc-writer-approle + creationPolicy: Owner + data: + - secretKey: role_id + remoteRef: + key: autojanet/doc-writer/approle + property: role_id + - secretKey: secret_id + remoteRef: + key: autojanet/doc-writer/approle + property: secret_id +--- +--- +# ExternalSecret: agent-technical-writer +# Pulls AppRole credentials from OpenBao into a k8s Secret +# so the Job can authenticate and fetch runtime secrets. +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: agent-technical-writer-approle + namespace: autojanet +spec: + refreshInterval: 1h + secretStoreRef: + name: openbao + kind: ClusterSecretStore + target: + name: agent-technical-writer-approle + creationPolicy: Owner + data: + - secretKey: role_id + remoteRef: + key: autojanet/technical-writer/approle + property: role_id + - secretKey: secret_id + remoteRef: + key: autojanet/technical-writer/approle + property: secret_id +--- +--- +# ExternalSecret: agent-cost-optimizer +# Pulls AppRole credentials from OpenBao into a k8s Secret +# so the Job can authenticate and fetch runtime secrets. +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: agent-cost-optimizer-approle + namespace: autojanet +spec: + refreshInterval: 1h + secretStoreRef: + name: openbao + kind: ClusterSecretStore + target: + name: agent-cost-optimizer-approle + creationPolicy: Owner + data: + - secretKey: role_id + remoteRef: + key: autojanet/cost-optimizer/approle + property: role_id + - secretKey: secret_id + remoteRef: + key: autojanet/cost-optimizer/approle + property: secret_id \ No newline at end of file diff --git a/k8s/externalsecrets/dispatcher-approle.yaml b/k8s/externalsecrets/dispatcher-approle.yaml new file mode 100644 index 0000000..1cca628 --- /dev/null +++ b/k8s/externalsecrets/dispatcher-approle.yaml @@ -0,0 +1,24 @@ +--- +# ExternalSecret: dispatcher approle +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: dispatcher-approle + namespace: autojanet +spec: + refreshInterval: 1h + secretStoreRef: + name: openbao + kind: ClusterSecretStore + target: + name: dispatcher-approle + creationPolicy: Owner + data: + - secretKey: role_id + remoteRef: + key: autojanet/pm/approle + property: role_id + - secretKey: secret_id + remoteRef: + key: autojanet/pm/approle + property: secret_id \ No newline at end of file