Security
What exists, who holds it, and what is overdue. Several of these are personal credentials doing organisational work, which is the single largest concentration of risk on this page.
Each of these is known to be exposed, shared, or past the point where it should have been replaced. Listed with the reason, because a rotation list without reasons gets deferred indefinitely.
| Credential | Why | Blast radius if abused |
|---|---|---|
itadmin host password | Typed into a shell on prod-k8s-master-01 on 7 October and recorded in history and transcripts | SSH to all six nodes |
| GitHub PAT used for the initial push | Exposed in working transcripts during September | Repository write |
| Postgres superuser | Exposed in working transcripts; should be disabled outright with enableSuperuserAccess: false once nothing needs it | Every production database |
dbadmin role | Exposed in working transcripts | Create role, create database |
Rotating a password that is still sitting in ~/.bash_history on a
production node only solves half the problem. Check for it, delete the entry,
and write the file back — on every node where it may have been typed.
This is the pattern most worth fixing, because it does not fail until someone leaves — and then it fails everywhere at once.
| Credential | Used by | What breaks when it goes |
|---|---|---|
GHCR token on tman-dcbar | Around 39 Image Updater entries | Image updates stop estate-wide, silently |
GHCR token on timramlogandcbar | HelpDesk image pulls | HelpDesk pods cannot pull images |
Per-namespace ghcr-pull-secret | Every application namespace | That application cannot pull |
The deployment generator reinforces this: its setup commands say
--docker-username=<your-gh-username>, so every person who
follows the documented process adds another personal dependency. Replacing
those with an organisation-owned machine account, and changing the generator’s
placeholder, fixes the cause rather than the instances.
A token that expires does not alert. The first symptom is a deployment that does not roll, or a pod that cannot start after an unrelated restart, days or weeks later. There is nothing currently watching for it.
Things that will expire on a known date, whether or not anyone is watching. These feed the renewal reminders in the Vendors section.
| Item | Expires | Effect |
|---|---|---|
*.dcbar.org wildcard certificate | 27 November 2026 | TLS fails on every production hostname |
app-kv-reader service principal secret | Two years from creation — date not recorded | Pods cannot mount secrets and will not start |
| GHCR personal access tokens | Not recorded | Image pulls and updates fail |
| SendGrid API key | Not recorded | All alerting stops, silently |
Three of those four have no recorded date. That is the actual finding: the estate has at least four credentials with hard expiries and knows the date of one of them.
From the app-db cluster on 8 October 2026. Application roles follow
<database>_user and own their own database; the rest are
platform roles.
| Role | Attributes | Purpose |
|---|---|---|
postgres | Superuser, replication, bypass RLS | Platform. Candidate for disabling. |
dbadmin | Create role, create DB | Administration |
streaming_replica | Replication | CloudNativePG replication |
cnpg_pooler_pgbouncer | — | PgBouncer authentication |
cnpg_metrics_exporter | — | Metrics |
watchdog | — | Database monitoring CronJobs |
appuser | — | Owns appdb and crm-production |
Seven *_user roles | Create role, create DB | One per application database |
Most *_user roles carry Create role and Create DB.
An application compromised through SQL injection could then create roles and
databases rather than only reading its own. Nothing here requires those
attributes at runtime; they are an artefact of how the roles were created.
Until the personal credentials above are replaced, an IT leaver is an infrastructure event. The list to work through:
ghcr-pull-secret and every Image Updater
pull-secret reference for their username.itadmin shared account password, since they knew it.The shape of that list is itself the argument for the fix: with organisational credentials, most of these lines disappear.