Skip to content

1Password secret references for local Kubernetes secret manifests - #101

Merged
smebberson merged 9 commits into
masterfrom
op-secret-templates
Sep 16, 2026
Merged

smebberson merged 9 commits into
masterfrom
op-secret-templates

Conversation

@smebberson

@smebberson smebberson commented Sep 15, 2026 •

Copy link
Copy Markdown
Member

Adds support for 1Password secret references (op://) within Kubernetes manifest templates, so projects can keep secret manifests in git without plaintext secrets, resolving them to real values only at compile time.

Related PRs

  • idearium/ras-rsc#449 - adopts this in ras-rsc's local environment (pins this package's beta).

Notes

  • Any .yaml.tmpl containing op:// references has them resolved with op inject (file mode) before the template is rendered, so template placeholders never interfere with references. Templates without references never invoke op.
  • type: secret services can use stringData (plaintext, one value per line), which is base64 encoded into data within the compiled manifest, just as Kubernetes expects.
  • Before resolving references, the cli authenticates with op whoami (only when references are present) and halts with a friendly eval $(op signin) message otherwise.
  • Compiled secret manifests are written 0600 and removed after they've been applied (c kc start, c kc apply), or when c skaffold dev exits (new c kc secrets-clean command, quiet via -q). This only applies to the local environment; beta and production are unaffected (they will move to Google Secret Manager).
  • c skaffold dev now halts when manifest compilation fails, rather than continuing into skaffold with stale compiled manifests.
  • README and CHANGELOG updated with the template format, its constraints (single-line, unquoted values), and the compiled secrets lifecycle.

Verification and testing

Verification

  • Before this change, a project's local secret manifest (e.g. ras-rsc's manifests/local/site.secret.yaml) held base64 (i.e. plaintext) secret values committed to git: base64 -d on any value reveals it.

Testing

  • With eval $(op signin) in the shell, c kc manifests compiles secret templates into .compiled with values identical to the originals (verified 18/18 fields against the previous committed secrets, both in .compiled and applied to the minikube cluster).
  • Compiled secret files are 0600; other compiled manifests remain 0644.
  • After c kc start / c kc apply, compiled secret manifests are removed; other manifests remain.
  • c skaffold dev keeps them for the session and removes them on exit (including Ctrl+C), via the c kc secrets-clean -q trap.
  • Without an authenticated op session, c kc manifests and c skaffold dev halt with a friendly signin message (and skaffold never starts).
  • Non-secret templates (.yaml.tmpl without references) render exactly as before; plain .yaml secrets are still copied verbatim (beta/production/devspace unaffected).

Deployment

  • v6.1.0-beta.1 is published to npm (dist-tag beta) so ras-rsc#449 can pin it while this PR is reviewed. Note: this PR was previously merged prematurely as 1Password secret references for local Kubernetes secret manifests #99 and reset from master; the npm version remains valid (the git tag was removed with the reset).
  • Promoted to v6.1.0: released from this branch (changelog heading, npm version minor, tag v6.1.0 pushed) and published to npm as latest.

@smebberson smebberson mentioned this pull request Sep 15, 2026
3 tasks
@smebberson
smebberson requested review from allanchau and a lite review from Copilot and removed request for Copilot September 15, 2026 05:02

@allanchau allanchau left a comment

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.

@smebberson Question for you here

Comment thread bin/lib/c-kc.js Outdated
Mustache.render(content, service.locals),
'utf8'
);
// Secret references are resolved before the template is rendered, so

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.

@smebberson Don't you want to render the template first? what if you had a password with curly braces in it?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@allanchau, it is a bit of a catch-22 because the default advice from 1Password actually uses {{op://}}. I decided to roll with bare op:// references (i.e. not wrapped in {{}}) and it does still work - so the ordering you've suggested is the right approach. That's been updated.

@allanchau allanchau left a comment

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.

@smebberson Not sure if you want to tackle these too, it doesn't seem likely to ever happen

  • Severity: Low
  • Confidence: High
  • Location: bin/lib/c-kc.js:100-104
  • Issue: encodeSecretStringData flips inStringData = false for any line that doesn't match the field regex /^(\s+)([^:\s]+):\s*(.*)$/ — including blank lines and indented comments inside the stringData block. A blank line or # comment between entries silently stops encoding; all subsequent keys are written under data: as plaintext. kubectl apply then fails with an "error decoding from base64" style error at apply time, and the compiled secret is still deleted afterwards by removeCompiledSecrets — confusing and leaves the cluster with a stale secret.
  • Fix: Capture the stringData key's indentation and only treat lines indented deeper as fields; only reset inStringData on a line indented less than or equal to it (or at column 0). Alternatively parse the YAML properly instead of line-by-line regex.
  • Severity: Low
  • Confidence: High
  • Location: bin/lib/c-kc.js:85-90
  • Issue: If a secret template contains both data: and stringData: (valid in Kubernetes), the output contains two data: keys, producing an invalid/duplicate-key manifest. The README doesn't call this out.
  • Fix: Reject templates containing both blocks with a clear error, or merge stringData into the existing data block.

Comment thread bin/lib/c-kc.js Outdated
Comment thread bin/lib/c-kc.js Outdated
} catch (e) {
// Do nothing.
// It just means we don't have a templ file to render.
// It just means there was no compiled secret to remove.

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.

Do we need to rethrow other errors?

EACCES/EPERM/EROFS would silently leave plaintext secret files on disk while c kc secrets-clean reports success.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@allanchau, this has been resolved now.

@smebberson

Copy link
Copy Markdown
Member Author

@allanchau, I've resolved these now.

@allanchau allanchau left a comment

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.

looks good

@smebberson
smebberson merged commit 0c2f050 into master Sep 16, 2026
1 of 2 checks passed
@smebberson
smebberson deleted the op-secret-templates branch September 16, 2026 06:18

This branch is waiting to be deployed

1 waiting deployment
Publish — ca2e5a88 Waiting Sep 16, 2026 by smebberson via Publish #5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants