From c0c83f52feae43856afaba792aa3d2dcb8f685e1 Mon Sep 17 00:00:00 2001 From: Erich Blume Date: Sat, 28 Mar 2026 21:12:12 -0700 Subject: [PATCH] Add Kingfisher secret scanner CronJob Weekly scan of all Forgejo repos (Sunday 4am) using MongoDB's Kingfisher tool. Produces HTML and JSON reports on sifaka NFS. Uses official container image with Forgejo API token via ExternalSecret from 1Password. Co-Authored-By: Claude Opus 4.6 (1M context) --- argocd/apps/kingfisher.yaml | 17 +++++ argocd/manifests/kingfisher/cronjob.yaml | 66 +++++++++++++++++++ .../manifests/kingfisher/external-secret.yaml | 22 +++++++ .../manifests/kingfisher/kustomization.yaml | 15 +++++ argocd/manifests/kingfisher/pv-nfs.yaml | 17 +++++ argocd/manifests/kingfisher/pvc.yaml | 13 ++++ .../feature-kingfisher-cronjob.feature.md | 1 + 7 files changed, 151 insertions(+) create mode 100644 argocd/apps/kingfisher.yaml create mode 100644 argocd/manifests/kingfisher/cronjob.yaml create mode 100644 argocd/manifests/kingfisher/external-secret.yaml create mode 100644 argocd/manifests/kingfisher/kustomization.yaml create mode 100644 argocd/manifests/kingfisher/pv-nfs.yaml create mode 100644 argocd/manifests/kingfisher/pvc.yaml create mode 100644 docs/changelog.d/feature-kingfisher-cronjob.feature.md diff --git a/argocd/apps/kingfisher.yaml b/argocd/apps/kingfisher.yaml new file mode 100644 index 0000000..27d24a5 --- /dev/null +++ b/argocd/apps/kingfisher.yaml @@ -0,0 +1,17 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: kingfisher + namespace: argocd +spec: + project: default + source: + repoURL: ssh://forgejo@forge.ops.eblu.me:2222/eblume/blumeops.git + targetRevision: main + path: argocd/manifests/kingfisher + destination: + server: https://kubernetes.default.svc + namespace: kingfisher + syncPolicy: + syncOptions: + - CreateNamespace=true diff --git a/argocd/manifests/kingfisher/cronjob.yaml b/argocd/manifests/kingfisher/cronjob.yaml new file mode 100644 index 0000000..9fce418 --- /dev/null +++ b/argocd/manifests/kingfisher/cronjob.yaml @@ -0,0 +1,66 @@ +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: kingfisher + namespace: kingfisher +spec: + schedule: "0 4 * * 0" # Sunday 4am (after Prowler k8s scan at 3am) + concurrencyPolicy: Forbid + jobTemplate: + spec: + ttlSecondsAfterFinished: 604800 # Auto-delete after 7 days + template: + spec: + securityContext: + seccompProfile: + type: RuntimeDefault + containers: + - name: kingfisher + image: ghcr.io/mongodb/kingfisher:kustomized + command: ["/bin/sh", "-c"] + args: + - | + set -e + STAMP=$(date +%Y%m%d-%H%M%S) + OUTDIR=/reports/kingfisher + mkdir -p "$OUTDIR" + + COMMON_ARGS="scan gitea \ + --api-url https://forge.ops.eblu.me/api/v1/ \ + --all-organizations \ + --user eblume \ + --repo-type all \ + --no-update-check \ + --tls-mode lax \ + --allow-internal-ips" + + # HTML report for human review + kingfisher $COMMON_ARGS \ + --format html \ + --output "$OUTDIR/scan-${STAMP}.html" || true + + # JSON report for machine parsing + kingfisher $COMMON_ARGS \ + --format json \ + --output "$OUTDIR/scan-${STAMP}.json" + env: + - name: KF_GITEA_TOKEN + valueFrom: + secretKeyRef: + name: kingfisher-forgejo-token + key: KF_GITEA_TOKEN + volumeMounts: + - name: reports + mountPath: /reports + resources: + requests: + memory: 256Mi + cpu: 100m + limits: + memory: 1Gi + restartPolicy: OnFailure + volumes: + - name: reports + persistentVolumeClaim: + claimName: kingfisher-reports diff --git a/argocd/manifests/kingfisher/external-secret.yaml b/argocd/manifests/kingfisher/external-secret.yaml new file mode 100644 index 0000000..6f6a5f2 --- /dev/null +++ b/argocd/manifests/kingfisher/external-secret.yaml @@ -0,0 +1,22 @@ +# ExternalSecret for Forgejo API token used by Kingfisher to enumerate repos +# +# 1Password item: "Forgejo Secrets" in blumeops vault +# Field: api-token +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: kingfisher-forgejo-token + namespace: kingfisher +spec: + refreshInterval: 1h + secretStoreRef: + kind: ClusterSecretStore + name: onepassword-blumeops + target: + name: kingfisher-forgejo-token + creationPolicy: Owner + data: + - secretKey: KF_GITEA_TOKEN + remoteRef: + key: Forgejo Secrets + property: api-token diff --git a/argocd/manifests/kingfisher/kustomization.yaml b/argocd/manifests/kingfisher/kustomization.yaml new file mode 100644 index 0000000..97d951c --- /dev/null +++ b/argocd/manifests/kingfisher/kustomization.yaml @@ -0,0 +1,15 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +namespace: kingfisher + +resources: + - pv-nfs.yaml + - pvc.yaml + - external-secret.yaml + - cronjob.yaml + +images: + - name: ghcr.io/mongodb/kingfisher + newTag: "1.91.0" diff --git a/argocd/manifests/kingfisher/pv-nfs.yaml b/argocd/manifests/kingfisher/pv-nfs.yaml new file mode 100644 index 0000000..ddff3b1 --- /dev/null +++ b/argocd/manifests/kingfisher/pv-nfs.yaml @@ -0,0 +1,17 @@ +# NFS PersistentVolume for Kingfisher secret scan reports +# Reuses the same sifaka:/volume1/reports share as Prowler +# NFS rules already configured for indri +apiVersion: v1 +kind: PersistentVolume +metadata: + name: kingfisher-reports-nfs-pv +spec: + capacity: + storage: 1Gi + accessModes: + - ReadWriteMany + persistentVolumeReclaimPolicy: Retain + storageClassName: "" + nfs: + server: sifaka + path: /volume1/reports diff --git a/argocd/manifests/kingfisher/pvc.yaml b/argocd/manifests/kingfisher/pvc.yaml new file mode 100644 index 0000000..f48da95 --- /dev/null +++ b/argocd/manifests/kingfisher/pvc.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: kingfisher-reports + namespace: kingfisher +spec: + accessModes: + - ReadWriteMany + storageClassName: "" + volumeName: kingfisher-reports-nfs-pv + resources: + requests: + storage: 1Gi diff --git a/docs/changelog.d/feature-kingfisher-cronjob.feature.md b/docs/changelog.d/feature-kingfisher-cronjob.feature.md new file mode 100644 index 0000000..871c9d8 --- /dev/null +++ b/docs/changelog.d/feature-kingfisher-cronjob.feature.md @@ -0,0 +1 @@ +Add Kingfisher secret scanner as a weekly CronJob scanning all Forgejo repos, with HTML and JSON reports written to sifaka NFS.