commit 40eb3b842c0c2746609e4baa91a4a020fad74749 Author: nick-gorse Date: Sun Apr 19 23:36:09 2026 +0100 feat: initial ArgoCD GitOps self-management setup - Base references upstream ArgoCD v3.3.6 install.yaml - Production overlay applies all cluster customizations: - KSOPS CMP sidecar on argocd-repo-server - Custom ConfigMaps (argocd-cm, argocd-cmd-params-cm, argocd-rbac-cm, argocd-notifications-cm) - Redis migrated to shared-redis.data:6379 - Traefik IngressRoute for argocd.olb42.com - SOPS-encrypted secrets (age key, redis auth, gitea tokens, repo-creds) - Bootstrap Application with prune:false for safe self-management diff --git a/.gitea/workflows/validate.yaml b/.gitea/workflows/validate.yaml new file mode 100644 index 0000000..f196f73 --- /dev/null +++ b/.gitea/workflows/validate.yaml @@ -0,0 +1,117 @@ +name: Validate manifests + +on: + push: + pull_request: + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install tools + run: | + curl -sL https://github.com/yannh/kubeconform/releases/latest/download/kubeconform-linux-amd64.tar.gz \ + | tar xz -C /usr/local/bin + + # Traefik IngressRoute is a CRD, so kubeconform needs an extra schema source. + mkdir -p .ci-schemas/traefik.io + curl -fsSL https://raw.githubusercontent.com/datreeio/CRDs-catalog/main/traefik.io/ingressroute_v1alpha1.json \ + -o .ci-schemas/traefik.io/ingressroute_v1alpha1.json + cp .ci-schemas/traefik.io/ingressroute_v1alpha1.json .ci-schemas/traefik.io/IngressRoute_v1alpha1.json + cp .ci-schemas/traefik.io/ingressroute_v1alpha1.json .ci-schemas/traefik.io/IngressRoute.json + cp .ci-schemas/traefik.io/ingressroute_v1alpha1.json .ci-schemas/traefik.io/ingressroute.json + + # ArgoCD Application is also a CRD. + mkdir -p .ci-schemas/argoproj.io + curl -fsSL https://raw.githubusercontent.com/datreeio/CRDs-catalog/main/argoproj.io/application_v1alpha1.json \ + -o .ci-schemas/argoproj.io/application_v1alpha1.json + cp .ci-schemas/argoproj.io/application_v1alpha1.json .ci-schemas/argoproj.io/Application_v1alpha1.json + cp .ci-schemas/argoproj.io/application_v1alpha1.json .ci-schemas/argoproj.io/Application.json + cp .ci-schemas/argoproj.io/application_v1alpha1.json .ci-schemas/argoproj.io/application.json + + - name: kubeconform - raw YAML + run: | + bootstrap_enabled=false + if [ -f bootstrap/config.yaml ] && grep -Eq '^[[:space:]]*enabled:[[:space:]]*true[[:space:]]*$' bootstrap/config.yaml; then + bootstrap_enabled=true + fi + + mapfile -t manifests < <( + find . -type f -name '*.yaml' \ + ! -path './.gitea/*' \ + ! -name '.sops.yaml' \ + ! -name '*.secret.yaml' \ + ! -name 'kustomization.yaml' \ + ! \( -name 'secret*.yaml' \) \ + ! \( -path '*/config/*' -prune \) \ + ! -path './bootstrap/config.yaml' \ + | sort + ) + + if [ "$bootstrap_enabled" != "true" ]; then + filtered=() + for manifest in "${manifests[@]}"; do + [ "$manifest" = "./bootstrap/application.yaml" ] && continue + filtered+=("$manifest") + done + manifests=("${filtered[@]}") + fi + + if [ "${#manifests[@]}" -eq 0 ]; then + echo "No manifests found" + exit 0 + fi + + printf '%s\n' "${manifests[@]}" \ + | xargs kubeconform \ + -strict \ + -kubernetes-version 1.35.0 \ + -schema-location default \ + -schema-location '.ci-schemas/{{.Group}}/{{.ResourceKind}}{{.KindSuffix}}.json' \ + -schema-location '.ci-schemas/{{.Group}}/{{.ResourceKind}}_{{.ResourceAPIVersion}}.json' \ + -summary + + - name: SOPS - check no secret files committed unencrypted + run: | + fail=0 + + while IFS= read -r file; do + if ! grep -q 'sops:' "$file"; then + echo "ERROR: $file appears to be unencrypted" + fail=1 + fi + done < <( + find . -type f \( -name '*.secret.yaml' -o -name '*.enc.yaml' \) | sort + ) + + exit "$fail" + + - name: Apply bootstrap Application + env: + KUBECONFIG_B64: ${{ secrets.KUBECONFIG_B64 }} + run: | + if [ "${GITHUB_EVENT_NAME:-}" != "push" ] || [ "${GITHUB_REF:-}" != "refs/heads/main" ]; then + echo "Skipping bootstrap apply: only push events on main may apply" + exit 0 + fi + + if [ ! -f bootstrap/config.yaml ] || ! grep -Eq '^[[:space:]]*enabled:[[:space:]]*true[[:space:]]*$' bootstrap/config.yaml; then + echo "Skipping bootstrap apply: bootstrap/config.yaml is not enabled" + exit 0 + fi + + if [ -z "${KUBECONFIG_B64:-}" ]; then + echo "Warning: KUBECONFIG_B64 secret not set — skipping bootstrap apply" + exit 0 + fi + + curl -fsSL https://dl.k8s.io/release/$(curl -fsSL https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl \ + -o /usr/local/bin/kubectl + chmod +x /usr/local/bin/kubectl + + mkdir -p "${HOME}/.kube" + printf '%s' "$KUBECONFIG_B64" | base64 -d > "${HOME}/.kube/config" + + kubectl apply -f bootstrap/application.yaml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..26ee1c2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +.DS_Store +.idea/ +.vscode/ +*.swp +*.swo + +# Local plaintext twins for sync-managed secrets. Keep these untracked. +manifest/overlays/**/secret.yaml +manifest/components/**/secret.yaml diff --git a/.sops.yaml b/.sops.yaml new file mode 100644 index 0000000..5d073cc --- /dev/null +++ b/.sops.yaml @@ -0,0 +1,5 @@ +creation_rules: + - path_regex: manifest/(overlays|components)/.*/.*\.enc\.yaml$ + age: age1s0gzgh8c00tgnkgxrqyz2nu0k56xvc9ev3jdenkmu90egux9xfmsxvvj43 + - path_regex: manifest/(overlays|components)/.*/secret\.secret\.yaml$ + age: age1s0gzgh8c00tgnkgxrqyz2nu0k56xvc9ev3jdenkmu90egux9xfmsxvvj43 diff --git a/bootstrap/application.yaml b/bootstrap/application.yaml new file mode 100644 index 0000000..ea95692 --- /dev/null +++ b/bootstrap/application.yaml @@ -0,0 +1,29 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: argocd-production + namespace: argocd + labels: + app.kubernetes.io/managed-by: argocd + app.kubernetes.io/name: argocd +spec: + project: default + source: + repoURL: http://gitea-ha-http.apps:3000/olb42/argocd.git + targetRevision: main + path: manifest/overlays/production + plugin: + name: ksops + destination: + server: https://kubernetes.default.svc + namespace: argocd + syncPolicy: + automated: + # prune: false — ArgoCD self-managing itself; never auto-prune to avoid + # accidentally removing ArgoCD components and losing cluster management. + prune: false + selfHeal: true + syncOptions: + - CreateNamespace=false + - ApplyOutOfSyncOnly=true + - ServerSideApply=true diff --git a/bootstrap/config.yaml b/bootstrap/config.yaml new file mode 100644 index 0000000..eb1a8f6 --- /dev/null +++ b/bootstrap/config.yaml @@ -0,0 +1,3 @@ +enabled: true +target_namespace: argocd +apply_from_branch: main diff --git a/manifest/base/kustomization.yaml b/manifest/base/kustomization.yaml new file mode 100644 index 0000000..3230b42 --- /dev/null +++ b/manifest/base/kustomization.yaml @@ -0,0 +1,7 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +namespace: argocd + +resources: + - https://raw.githubusercontent.com/argoproj/argo-cd/v3.3.6/manifests/install.yaml diff --git a/manifest/overlays/production/argocd-cm-patch.yaml b/manifest/overlays/production/argocd-cm-patch.yaml new file mode 100644 index 0000000..87c6814 --- /dev/null +++ b/manifest/overlays/production/argocd-cm-patch.yaml @@ -0,0 +1,95 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: argocd-cm + namespace: argocd +data: + accounts.homepage: apiKey + accounts.mcpserver: apiKey + exec.enabled: "true" + kustomize.buildOptions: --enable-helm + resource.customizations.ignoreResourceUpdates.ConfigMap: | + jqPathExpressions: + - '.metadata.annotations."cluster-autoscaler.kubernetes.io/last-updated"' + - '.metadata.annotations."control-plane.alpha.kubernetes.io/leader"' + resource.customizations.ignoreResourceUpdates.Endpoints: | + jsonPointers: + - /metadata + - /subsets + resource.customizations.ignoreResourceUpdates.all: | + jsonPointers: + - /status + resource.customizations.ignoreResourceUpdates.apps_ReplicaSet: | + jqPathExpressions: + - '.metadata.annotations."deployment.kubernetes.io/desired-replicas"' + - '.metadata.annotations."deployment.kubernetes.io/max-replicas"' + - '.metadata.annotations."rollout.argoproj.io/desired-replicas"' + resource.customizations.ignoreResourceUpdates.argoproj.io_Application: | + jqPathExpressions: + - '.metadata.annotations."notified.notifications.argoproj.io"' + - '.metadata.annotations."argocd.argoproj.io/refresh"' + - '.metadata.annotations."argocd.argoproj.io/hydrate"' + - '.operation' + resource.customizations.ignoreResourceUpdates.argoproj.io_Rollout: | + jqPathExpressions: + - '.metadata.annotations."notified.notifications.argoproj.io"' + resource.customizations.ignoreResourceUpdates.autoscaling_HorizontalPodAutoscaler: | + jqPathExpressions: + - '.metadata.annotations."autoscaling.alpha.kubernetes.io/behavior"' + - '.metadata.annotations."autoscaling.alpha.kubernetes.io/conditions"' + - '.metadata.annotations."autoscaling.alpha.kubernetes.io/metrics"' + - '.metadata.annotations."autoscaling.alpha.kubernetes.io/current-metrics"' + resource.customizations.ignoreResourceUpdates.discovery.k8s.io_EndpointSlice: | + jsonPointers: + - /metadata + - /endpoints + - /ports + resource.exclusions: | + - apiGroups: + - '' + - discovery.k8s.io + kinds: + - Endpoints + - EndpointSlice + - apiGroups: + - coordination.k8s.io + kinds: + - Lease + - apiGroups: + - authentication.k8s.io + - authorization.k8s.io + kinds: + - SelfSubjectReview + - TokenReview + - LocalSubjectAccessReview + - SelfSubjectAccessReview + - SelfSubjectRulesReview + - SubjectAccessReview + - apiGroups: + - certificates.k8s.io + kinds: + - CertificateSigningRequest + - apiGroups: + - cert-manager.io + kinds: + - CertificateRequest + - apiGroups: + - cilium.io + kinds: + - CiliumIdentity + - CiliumEndpoint + - CiliumEndpointSlice + - apiGroups: + - kyverno.io + - reports.kyverno.io + - wgpolicyk8s.io + kinds: + - PolicyReport + - ClusterPolicyReport + - EphemeralReport + - ClusterEphemeralReport + - AdmissionReport + - ClusterAdmissionReport + - BackgroundScanReport + - ClusterBackgroundScanReport + - UpdateRequest diff --git a/manifest/overlays/production/argocd-cmd-params-cm-patch.yaml b/manifest/overlays/production/argocd-cmd-params-cm-patch.yaml new file mode 100644 index 0000000..c307c59 --- /dev/null +++ b/manifest/overlays/production/argocd-cmd-params-cm-patch.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: argocd-cmd-params-cm + namespace: argocd +data: + redis.server: shared-redis.data:6379 + server.insecure: "true" diff --git a/manifest/overlays/production/argocd-cmp-cm.yaml b/manifest/overlays/production/argocd-cmp-cm.yaml new file mode 100644 index 0000000..35975ab --- /dev/null +++ b/manifest/overlays/production/argocd-cmp-cm.yaml @@ -0,0 +1,26 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: argocd-cmp-cm + namespace: argocd +data: + ksops.yaml: | + apiVersion: argoproj.io/v1alpha1 + kind: ConfigManagementPlugin + metadata: + name: ksops + spec: + generate: + command: ["sh", "-c"] + args: + - | + if [ -n "$ARGOCD_ENV_BRANCH_SLUG" ]; then + sed -i "s/BRANCH_SLUG_PLACEHOLDER/$ARGOCD_ENV_BRANCH_SLUG/g" kustomization.yaml + fi + if [ -n "$ARGOCD_ENV_IMAGE_TAG" ]; then + kustomize edit set image "ngorse/swarm-dns-watcher:$ARGOCD_ENV_IMAGE_TAG" + fi + kustomize build --enable-alpha-plugins --enable-exec . + discover: + find: + glob: "**/kustomization.yaml" diff --git a/manifest/overlays/production/argocd-notifications-cm-patch.yaml b/manifest/overlays/production/argocd-notifications-cm-patch.yaml new file mode 100644 index 0000000..1749f64 --- /dev/null +++ b/manifest/overlays/production/argocd-notifications-cm-patch.yaml @@ -0,0 +1,27 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: argocd-notifications-cm + namespace: argocd +data: + service.webhook.gitea: | + url: https://git.olb42.com + headers: + - name: Authorization + value: token $GITEA_TOKEN + - name: Content-Type + value: application/json + template.gitea-create-issue: | + webhook: + gitea: + method: POST + path: /api/v1/repos/olb42/k8s-manifests/issues + body: | + { + "title": "Deploy failed: {{.app.metadata.name}}", + "body": "## Deployment Failure\n\n**App:** `{{.app.metadata.name}}`\n**Namespace:** `{{.app.spec.destination.namespace}}`\n**Sync status:** `{{.app.status.sync.status}}`\n**Health:** `{{.app.status.health.status}}`\n\n### Conditions\n```\n{{range .app.status.conditions}}{{.message}}\n{{end}}```\n\n[View in ArgoCD](https://argocd.olb42.com/applications/{{.app.metadata.name}})", + "labels": [1] + } + trigger.on-deploy-failed: | + - when: app.status.health.status == 'Degraded' || app.status.sync.status == 'Unknown' + send: [gitea-create-issue] diff --git a/manifest/overlays/production/argocd-rbac-cm-patch.yaml b/manifest/overlays/production/argocd-rbac-cm-patch.yaml new file mode 100644 index 0000000..ea12d49 --- /dev/null +++ b/manifest/overlays/production/argocd-rbac-cm-patch.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: argocd-rbac-cm + namespace: argocd +data: + policy.csv: | + p, role:app-manager, applications, *, */*, allow + p, role:app-viewer, applications, get, */*, allow + g, mcpserver, role:app-manager + g, homepage, role:app-viewer + policy.default: role:readonly diff --git a/manifest/overlays/production/ingressroute.yaml b/manifest/overlays/production/ingressroute.yaml new file mode 100644 index 0000000..2029049 --- /dev/null +++ b/manifest/overlays/production/ingressroute.yaml @@ -0,0 +1,36 @@ +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: argocd-server + namespace: argocd + annotations: + gethomepage.dev/app: argocd-server + gethomepage.dev/description: CI Service + gethomepage.dev/enabled: "true" + gethomepage.dev/href: https://argocd.olb42.com + gethomepage.dev/icon: argo-cd + gethomepage.dev/name: Argo-CD + gethomepage.dev/namespace: argocd + gethomepage.dev/widget.key: '{{HOMEPAGE_VAR_ARGOCD_TOKEN}}' + gethomepage.dev/widget.type: argocd + gethomepage.dev/widget.url: http://argocd-server.argocd +spec: + entryPoints: + - websecure + routes: + - kind: Rule + match: Host(`argocd.olb42.com`) + priority: 10 + services: + - name: argocd-server + port: 80 + scheme: http + - kind: Rule + match: Host(`argocd.olb42.com`) && Header(`Content-Type`, `application/grpc`) + priority: 11 + services: + - name: argocd-server + port: 80 + scheme: h2c + tls: + secretName: olb42-com-tls diff --git a/manifest/overlays/production/ksops-cmp-config.yaml b/manifest/overlays/production/ksops-cmp-config.yaml new file mode 100644 index 0000000..a5e3d49 --- /dev/null +++ b/manifest/overlays/production/ksops-cmp-config.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: ksops-cmp-config + namespace: argocd +data: + plugin.yaml: | + apiVersion: argoproj.io/v1alpha1 + kind: ConfigManagementPlugin + metadata: + name: ksops + spec: + version: v1.0 + discover: + find: + glob: "**/ksops-generator.yaml" + generate: + command: + - kustomize + - build + - --enable-alpha-plugins + - --enable-exec + - . diff --git a/manifest/overlays/production/ksops-generator.yaml b/manifest/overlays/production/ksops-generator.yaml new file mode 100644 index 0000000..99caaae --- /dev/null +++ b/manifest/overlays/production/ksops-generator.yaml @@ -0,0 +1,10 @@ +apiVersion: viaduct.ai/v1 +kind: ksops +metadata: + name: argocd-secret-generator + annotations: + config.kubernetes.io/function: | + exec: + path: ksops +files: + - ./secret.enc.yaml diff --git a/manifest/overlays/production/kustomization.yaml b/manifest/overlays/production/kustomization.yaml new file mode 100644 index 0000000..d02083b --- /dev/null +++ b/manifest/overlays/production/kustomization.yaml @@ -0,0 +1,22 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +namespace: argocd + +resources: + - ../../base + - argocd-cmp-cm.yaml + - ksops-cmp-config.yaml + - ingressroute.yaml + +patches: + - path: argocd-cm-patch.yaml + - path: argocd-cmd-params-cm-patch.yaml + - path: argocd-rbac-cm-patch.yaml + - path: argocd-notifications-cm-patch.yaml + - path: repo-server-patch.yaml + +# KSOPS decrypts secret.enc.yaml at render time. +# The presence of ksops-generator.yaml activates the KSOPS CMP plugin. +generators: + - ksops-generator.yaml diff --git a/manifest/overlays/production/repo-server-patch.yaml b/manifest/overlays/production/repo-server-patch.yaml new file mode 100644 index 0000000..9eab332 --- /dev/null +++ b/manifest/overlays/production/repo-server-patch.yaml @@ -0,0 +1,61 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: argocd-repo-server + namespace: argocd +spec: + template: + spec: + initContainers: + - name: copyutil + image: quay.io/argoproj/argocd:v3.3.6 + command: + - sh + - -c + args: + - /bin/cp --update=none /usr/local/bin/argocd /var/run/argocd/argocd && /bin/ln -s /var/run/argocd/argocd /var/run/argocd/argocd-cmp-server + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + volumeMounts: + - mountPath: /var/run/argocd + name: var-files + containers: + - name: ksops + image: viaductoss/ksops:v4.3.2 + command: + - /var/run/argocd/argocd-cmp-server + env: + - name: SOPS_AGE_KEY_FILE + value: /age/key.txt + securityContext: + runAsNonRoot: true + runAsUser: 999 + volumeMounts: + - mountPath: /var/run/argocd + name: var-files + - mountPath: /home/argocd/cmp-server/plugins + name: plugins + - mountPath: /home/argocd/cmp-server/config/plugin.yaml + name: argocd-cmp-cm + subPath: ksops.yaml + - mountPath: /age + name: age-key + readOnly: true + - mountPath: /tmp + name: cmp-tmp + volumes: + - name: argocd-cmp-cm + configMap: + name: argocd-cmp-cm + - name: age-key + secret: + secretName: argocd-age-key + - name: cmp-tmp + emptyDir: {} diff --git a/manifest/overlays/production/secret.enc.yaml b/manifest/overlays/production/secret.enc.yaml new file mode 100644 index 0000000..f426fa9 --- /dev/null +++ b/manifest/overlays/production/secret.enc.yaml @@ -0,0 +1,41 @@ +apiVersion: ENC[AES256_GCM,data:nAs=,iv:DjVwuYqCpa9e9TY59qPUqG2yjrGOykfDUI/bH00cYC8=,tag:AgFF0Bb3YXZeUKb2BmA9Pg==,type:str] +kind: ENC[AES256_GCM,data:oBkqTrVH,iv:/M+hMx4ioTgtqjySJ0SvIv2W7huDyH1jAFCRXfHl4MQ=,tag:Qmq8JHdpdbpTA1WRrt8kuA==,type:str] +metadata: + name: ENC[AES256_GCM,data:MhdiC/arAhFbp2yzt4o=,iv:8pmcBcIj+iiVymud92ZIbMgEt9XCN7EFEYnL1ocwkWQ=,tag:T7/Dr24TtqACE7J171U/Rg==,type:str] + namespace: ENC[AES256_GCM,data:60vOnJKT,iv:t9Fapbuu9Ya311uzqZ86YjwEAR76PpOjxMDdGgfbxpA=,tag:6ERx/f670/SNOMikO+q/4w==,type:str] +type: ENC[AES256_GCM,data:i+s8ejKv,iv:LOqBlClSNxZY/RA50V0LNWD8a2XsHOI7bZSastpQ2E8=,tag:hlJ3TVaK6c4j/GSAK4EbqA==,type:str] +stringData: + key.txt: ENC[AES256_GCM,data:BYd7VuC7Tpu+fBfT2f+UwdmbzQnxDbAcapvNyoQR4qmcV/t4y7gjiD5Og5Tcpw3WhLLA3JBTuea7R/FqLwsHxqM1ZFsO17dUSZw=,iv:rodtfLRQUTyyt9P+7bhP6i/BEgZe5fePPDSYC1VHlq0=,tag:WGNFEStQo6CInbvNFbhrVw==,type:str] +sops: + age: + - recipient: age1s0gzgh8c00tgnkgxrqyz2nu0k56xvc9ev3jdenkmu90egux9xfmsxvvj43 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBqTVFMS3hqVFpFYkJPYkdl + QTU5ZTNtL3NhbWhFRUt4N1ZmOHNUT2Z6SnhjCmFGYTdsVm9lWWJBMURQdExkQ3pD + eFZvYTdzaS9Eb0dURGNXaERVSm1jSUEKLS0tIGpJSjJqU2NDZXBNSmIxRWg5Nk1G + aFNPeGdCUUxuUHJPZWdkWU1QWW8yN2MKo5P8YpmEx1K6n2KmJ5ZinI8tHTt79U+x + QIPHIOsL0vyRRDwDrhxagd1MX4OEOZl590GvT6IiNY0lN4gCdjoNow== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-04-19T22:34:54Z" + mac: ENC[AES256_GCM,data:5Ya2agLt9jHqylYh72cN9SNWpinNkSnbfAoUYXtPI+lp69qxYIq3SelE8vulWcDoOZIDxEepttVpIo+pkyQbxKwMms/iHLyEC1EIFg9MVIaP5KIdrr93p/aExMkFyPcDLiqC0XcCMuBhNTaZvQ5IE+wDs3JthUIa5F1ZL+3eTt4=,iv:iQLvWgAegOMYas/nxD3k3lXZ7wOjMGXYq/fuiin1+zU=,tag:F/YLP8oDDlGMisz0XLCJDA==,type:str] + unencrypted_suffix: _unencrypted + version: 3.12.2 +--- +apiVersion: ENC[AES256_GCM,data:THQ=,iv:kX/yYct8NmlujHHZ2Ui29wcGsjHojnHvYzx24i6CGxA=,tag:XtQInMnByeiit852ZAom7Q==,type:str] +kind: ENC[AES256_GCM,data:4NDGjFRb,iv:ImM1RSLM7Sa0J/RNPOeSmBUdDbxg32yIImurjgAIocM=,tag:5HLeek7XNSHDZ9ZlZsbahQ==,type:str] +metadata: + name: ENC[AES256_GCM,data:EotC086GrXiwxc2a,iv:xC5j6+Wokph7O5few7Kkzxwg8PW9eCE56QynyJftdUE=,tag:MvHqWXnwj3cVoie3VbTf/Q==,type:str] + namespace: ENC[AES256_GCM,data:Vo+Jc74Q,iv:Xfl7xjj8obV62L5U7IcK9XhY81aOvjWpQVu4XveMU/E=,tag:FDL3yxeO9DtVvHJY6LpWGA==,type:str] +type: ENC[AES256_GCM,data:U6aSqKrG,iv:iDBCN4GNTF01+c1sURCRDMXyY+WZ8IYYEYCQx3AX2As=,tag:QzwWCRXZWzncLo668Ei9RQ==,type:str] +stringData: + auth: ENC[AES256_GCM,data:IoYCciqcZIahHzyqIfs9dPtOU9//DU8ISSf/w5R2Og==,iv:1xqmXww4P+C/auZ6IjTISChTfhDEC76fYPi7beNl7Pc=,tag:c5ze7wDGfCxp2xiACbRcQg==,type:str] +sops: + age: + - recipient: age1s0gzgh8c00tgnkgxrqyz2nu0k56xvc9ev3jdenkmu90egux9xfmsxvvj43 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBqTVFMS3hqVFpFYkJPYkdl + QTU5ZTNtL3NhbWhFRUt4N1ZmOHNUT2Z6SnhjCmFGYTdsVm9lWWJBMURQdExkQ3pD + eFZvYTdzaS9Eb0dURGNXaERVSm1jSUEKLS0tIGpJSjJqU2NDZXBNSmIxRWg5Nk1G +... (145 lines truncated)