Skip to content

Track the ClusterIssuer instead of gitignoring it - #63

Open
3uzbcqje wants to merge 1 commit into
mainfrom
feat/clusterissuer-in-git
Open

3uzbcqje wants to merge 1 commit into
mainfrom
feat/clusterissuer-in-git

Conversation

@3uzbcqje

@3uzbcqje 3uzbcqje commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator

clusterissuer.yaml has been gitignored since 2024-04-14, which left the root of every TLS certificate on this cluster with no history, no review and no drift detection. If it were edited or deleted, nothing would notice or restore it.

The gitignore wasn't protecting anything

Git history tells the story plainly — it was tracked for a week first:

2024-04-07  ea73fb3  adds clusterissuer.template.txt AND clusterissuer.yaml
2024-04-14  6d575ac  "Prod clusterissuer" — flips staging→prod,
                     deletes clusterissuer.yaml, adds the .gitignore entry

The version deleted in 6d575ac contained the same subscription ID, client ID and email address the ignore now appears to guard, in plaintext. This reads as an ordinary "don't commit generated output" instinct, applied in the commit that turned the file into a template — not a security decision.

None of the values are sensitive by this repo's own convention

Value Already tracked?
subscription ID 86f3145a-… yes — applications/external-dns/values.yaml
resource group equalvote yes — 9 files
prod.equal.vote yes — 9 files
gmail@evanstucker.com yes — 3 files
client ID ebafbf2e-… no — the only absent value

But external-dns's identity (747dcea4-…) and loki's (098d7377-…) are both committed in plaintext. A managed-identity client ID is an identifier, not a credential — the repo already treats them that way.

No hidden variance

I rendered the template with the live values and diffed against the cluster: identical apart from the comment header. The manifest added here is byte-identical to what's deployed, so this changes nothing at sync time.

Why secrets/

It's the only directory an auto-syncing app applies raw manifests from — secrets/kustomization.yaml already carries namespaces.yaml exactly this way, and bootstrap-secrets runs with selfHeal: true and prune: true.

The directory name is a poor fit for a ClusterIssuer, and I'd rather say so than pretend otherwise. Moving it later means changing bootstrap-secrets' path in application.yaml, which needs a manual kubectl apply — the thing #57 moved away from. Happy to do that separately if you'd prefer a cluster-resources/ directory.

It can't live with cert-manager: that app is a Helm chart from the ApplicationSet and can't carry extra manifests.

One subtle fix

The .gitignore entry is now anchored to /clusterissuer.yaml. Unanchored, the pattern matches at any depth — it was already silently ignoring secrets/clusterissuer.yaml before I anchored it, which would have made this PR quietly do nothing.

The root-level render stays ignored, so the envsubst workflow still works locally.

Template kept

utils/clusterissuer.template.txt remains as the record of where the five values come from, with a note that rendering it no longer deploys anything — copy the result into secrets/clusterissuer.yaml and push instead.

After merge

kubectl -n argocd get app bootstrap-secrets -o jsonpath='{.status.sync.status}'
kubectl get clusterissuer letsencrypt-prod -o jsonpath='{.status.conditions[*].type}'   # want Ready
kubectl get certificate -A    # unchanged

The manifest matches live, so ArgoCD should adopt it with an empty diff.

🤖 Generated with Claude Code

https://claude.ai/code/session_01XTsEHfxxGsxGkKWfyQCYmr

clusterissuer.yaml has been gitignored since 2024-04-14, so the root of every TLS
certificate on this cluster had no history, no review and no drift detection. If
it were edited or deleted, nothing would notice or restore it.

The gitignore was not protecting anything. Git history shows the file was
committed for a week first -- ea73fb3 added it on 2024-04-07, and 6d575ac
"Prod clusterissuer" deleted it on 2024-04-14 in the same commit that turned it
into a template. The deleted version contained the same subscription ID, client ID
and email address the ignore now appears to guard, in plaintext.

None of those values are sensitive by this repo's own convention:

  subscription ID 86f3145a-...  already in applications/external-dns/values.yaml
  resource group equalvote      9 tracked files
  prod.equal.vote               9 tracked files
  gmail@evanstucker.com         3 tracked files
  client ID ebafbf2e-...        the only one absent -- but external-dns's
                                747dcea4-... and loki's 098d7377-... are both
                                committed in plaintext

A managed-identity client ID is an identifier, not a credential.

Rendering the template with the live values reproduces the running ClusterIssuer
exactly, so there is no hidden per-environment variance to preserve. The tracked
manifest is byte-identical to what is deployed.

It lives in secrets/ because that is the only directory an auto-syncing app
applies raw manifests from -- secrets/kustomization.yaml already carries
namespaces.yaml the same way. The name is a poor fit for a ClusterIssuer; moving
it later would mean changing bootstrap-secrets' path in application.yaml, which
needs a manual kubectl apply.

The .gitignore entry is now anchored to /clusterissuer.yaml. Unanchored it matched
at any depth, which would have silently ignored secrets/clusterissuer.yaml too.

utils/clusterissuer.template.txt is kept as the record of where the five values
come from, with a note that rendering it no longer deploys anything.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XTsEHfxxGsxGkKWfyQCYmr
@3uzbcqje
3uzbcqje requested a review from arterro as a code owner September 9, 2026 18:10
@coderabbitai

coderabbitai Bot commented Sep 9, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: ed17843a-437b-40ba-bd2e-49e0c0e76f0b


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@jacksonloper

Copy link
Copy Markdown
Collaborator

Along the same lines as #73, I vaguely think we want

metadata:
  annotations:
    argocd.argoproj.io/sync-options: Delete=false

here so it would survive an application delete.

spec:
acme:
server: "https://acme-v02.api.letsencrypt.org/directory"
email: "gmail@evanstucker.com"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we change this to elections@equal.vote ?

I'd like to add you add the other dev leads to that email group anyway, so that way the work any certificate issues can be shared

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants