Skip to content

Secrets — 1Password Connect

FieldValue
TypeAgent Reference
Source~/.copilot/agents/_refs/platform-sre-kubernetes/secrets-1password.md
DescriptionNot specified

Source Content

Secrets — 1Password Connect

1Password Connect is the only sanctioned secret source. No hand-authored Secret values. No environment-injection from CI variables for runtime config. Everything is declared in 1Password, materialised in-cluster by the 1Password Connect Operator.

Non-negotiable rules

  • Vault: platform-three.
  • Item naming: p3-<service>-<purpose> — e.g. p3-billing-postgres, p3-webhooks-stripe-signing.
  • One item = one logical credential bundle. Don’t pile every secret a service needs into a single item.
  • Field names match the env-var name the workload consumes (DATABASE_URL, STRIPE_API_KEY).
  • Rotation cadence is recorded on the item’s notes field. SREs are paged when an item exceeds its rotation window.

Materialising into the cluster

.p3/helm/templates/secrets/onepassword-item.yaml
apiVersion: onepassword.com/v1
kind: OnePasswordItem
metadata:
name: {{ include "<chart>.fullname" . }}-postgres
spec:
itemPath: "vaults/platform-three/items/p3-{{ .Values.service.name }}-postgres"

The operator reconciles a Secret of the same name with each item field as a key. The Deployment references it with envFrom.secretRef or valueFrom.secretKeyRef.

Secret-doc contract (docs/secrets/1password-requirements.md)

Every service ships this file. A reviewer must be able to provision a fresh environment from it without asking questions.

# <service> — secret requirements
## Items in vault `platform-three`
### `p3-<service>-postgres`
| Field | Env var | Owner | Rotation |
|---------------|------------------|-------------|----------|
| host | DB_HOST | DBA team | n/a |
| port | DB_PORT | DBA team | n/a |
| database | DB_NAME | DBA team | n/a |
| username | DB_USER | DBA team | 90d |
| password | DB_PASSWORD | DBA team | 90d |
### `p3-<service>-stripe`
| Field | Env var | Owner | Rotation |
|-----------------|--------------------|-----------|----------|
| api_key | STRIPE_API_KEY | Payments | 180d |
| webhook_secret | STRIPE_WEBHOOK_SIG | Payments | on event |
## Troubleshooting
- `OnePasswordItem` stuck in `Pending`: check the `onepassword-connect-operator` pod logs and that the item path matches exactly (vault names are case-sensitive).
- Rotated value not picked up: the operator polls every 600s by default; force with `kubectl annotate onepassworditem <name> operator.1password.io/last-updated- --overwrite`.

Anti-patterns

  • Pulling secrets into CI via op read and writing them to the cluster from a job — defeats GitOps and audit.
  • Sharing one item across services to “save effort” — blast radius of rotation grows linearly.
  • Storing non-secret config (feature flags, hostnames) in 1Password — those go in values.yaml.
  • Naming items by environment (p3-billing-postgres-prod) — environments are namespaces in the vault, not item suffixes. Use separate vaults if you need strong env isolation.