Skip to content

ENG-1632: Add org key custody backend (client-hosted HTTPS key service)#3814

Merged
mitchell-as merged 2 commits into
version/0-48-1-RC2from
mitchell/eng-1632
Jun 23, 2026
Merged

ENG-1632: Add org key custody backend (client-hosted HTTPS key service)#3814
mitchell-as merged 2 commits into
version/0-48-1-RC2from
mitchell/eng-1632

Conversation

@mitchell-as

@mitchell-as mitchell-as commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

ENG-1632: Add org key custody backend: client-hosted HTTPS key service

The next piece of the private ingredient work (ENG-1563). It lets the State Tool fetch an organization's single encryption key from the customer's own HTTPS key service, verify it's the right key, and reuse it for the run. The key is read only from the customer's service and never reaches ActiveState.

This adds the key provider, its configuration (settable via state config), and the seams the publish and consume flows will use. The actual wiring into publish and pull lands with ENG-1634 and ENG-1635.

Base branch: this targets mitchell/eng-1631 (in review as #3813) so the diff shows only this change. Once that merges, GitHub will retarget this PR to version/0-48-1-RC2.

Covered by tests for the fetch paths, TLS enforcement, key validation, caching, and the env scrub.

🤖 Generated with Claude Code

Add the key-custody backend for private ingredients: a provider that fetches
the organization's single AES-256 key from the customer-hosted HTTPS key
service, validates it, and caches it for the run.

- internal/runbits/orgkey: the Provider, the v1 org-key contract validation
  (schema/org/algorithm/encoding, base64 decode, fingerprint match via
  artifactcrypto), and the HTTPS backend (https-only, TLS 1.2+ with a configured
  CA or pinned cert, optional mTLS, bearer token from an env var or file, bounded
  timeout, no redirects). The key is held in memory for the run with an opt-in
  0600 on-disk cache for headless/offline/CI.
- Config options for the URL, CA, mTLS cert/key, bearer-token source, and the
  on-disk cache opt-in, registered in the package's init() and settable via
  state config.
- subshell scrubs the configured bearer-token env var from child process
  environments.
- pkg/runtime gains a WithDecryptionKey option as the consume-side injection
  seam, and orgkey exposes a header pre-flight key check.

The custody backend lives caller-side and is not imported by pkg/runtime, which
stays CGO-free. Wiring into the publish and consume flows lands with ENG-1634
and ENG-1635.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mitchell-as mitchell-as requested a review from MDrakos June 22, 2026 18:59
Base automatically changed from mitchell/eng-1631 to version/0-48-1-RC2 June 22, 2026 20:36
@mitchell-as mitchell-as requested a review from Copilot June 23, 2026 18:09

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds a new “org key custody” backend that can fetch an organization’s AES-256 key from a customer-hosted HTTPS service, validate it against a contract, and cache it for the duration of a run (optionally on disk), providing seams for future publish/pull wiring.

Changes:

  • Introduces internal/runbits/orgkey with HTTPS fetch, TLS/mTLS enforcement, contract validation, optional on-disk caching, and a preflight key check.
  • Adds runtime option plumbing to pass an org decryption key (OrgKey/OrgKeyID) into runtime setup.
  • Scrubs configured bearer-token environment variables from subshell child environments.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
pkg/runtime/setup.go Extends runtime setup options to carry org decryption key material.
pkg/runtime/options.go Adds WithDecryptionKey runtime option setter for org key + key id.
internal/subshell/subshell.go Scrubs org-key bearer token env var before propagating env to subshell.
internal/runbits/orgkey/orgkey.go Defines org key provider interface, config registration, and contract validation.
internal/runbits/orgkey/https.go Implements HTTPS key fetch with TLS policy, auth, and in-run caching.
internal/runbits/orgkey/cache.go Implements optional on-disk cache read/write and permission checks.
internal/runbits/orgkey/cache_lin_mac.go Enforces cache file permission constraints on non-Windows.
internal/runbits/orgkey/cache_win.go No-op cache permission checks on Windows.
internal/runbits/orgkey/env.go Removes configured bearer-token env var from child process env.
internal/runbits/orgkey/preflight.go Adds a header-only preflight check for key/artifact mismatch.
internal/runbits/orgkey/helpers_test.go Test helpers for contracts, TLS CA setup, and mTLS cert generation.
internal/runbits/orgkey/https_test.go Tests HTTPS fetch paths, TLS/mTLS enforcement, caching behavior, and timeouts.
internal/runbits/orgkey/validate_test.go Tests contract validation, preflight key behavior, and env scrubbing.
internal/constants/constants.go Adds config keys for key service URL/CA/mTLS/token sources and caching toggle.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pkg/runtime/options.go
Comment thread internal/runbits/orgkey/cache.go
Comment thread internal/runbits/orgkey/https.go
Warn on unexpected on-disk cache stat errors (permission denied, bad path)
instead of silently treating them as a cache miss; a genuinely missing file
stays a normal silent miss. This matches the behavior the doc comment already
describes.

Set Proxy: http.ProxyFromEnvironment on the key service HTTP transport. A
hand-built http.Transport does not inherit the default proxy behavior, so
HTTPS_PROXY/NO_PROXY were ignored and a customer-hosted key service behind a
corporate proxy could be unreachable.

ENG-1632

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mitchell-as mitchell-as merged commit ab9ef79 into version/0-48-1-RC2 Jun 23, 2026
17 of 20 checks passed
@mitchell-as mitchell-as deleted the mitchell/eng-1632 branch June 23, 2026 21:12
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