Skip to content

feat(providers): support Kubernetes Secret credential sources for provider credentials #1882

@rohancmr

Description

@rohancmr

Problem Statement

In multi-tenant Kubernetes deployments, platform teams commonly use External Secrets Operator to sync approved credentials from HashiCorp Vault, OpenBao, or another enterprise secret manager into Kubernetes Secrets.

In that model, the enterprise secret manager remains the source of truth. The Kubernetes Secret is the in-cluster handoff object that lets Kubernetes workloads consume approved credential material.

OpenShell providers currently store concrete credential values in OpenShell provider records. That works for local and simple deployments, but it creates friction for Kubernetes platforms because credentials must be copied into OpenShell instead of being resolved from the platform’s existing secret workflow.

OpenShell should support provider credentials backed by Kubernetes Secrets while preserving the current controlled supervisor/provider credential injection model.

Proposed Design

Add Kubernetes Secret as a provider credential source.

OpenShell should support two modes.

1. Explicit Secret key mapping

A provider credential can map one OpenShell credential key to one Kubernetes Secret key.

Example:

provider:
  name: nvbugs-gitlab
  type: gitlab
  credentials:
    GITLAB_TOKEN:
      source:
        type: kubernetesSecret
        namespace: tenant-nvbugs-prod
        name: nvbugs-provider-credentials
        key: gitlab-token

2. Secret extraction

A provider can reference a Kubernetes Secret and let OpenShell load multiple credential values from it.

Example:

provider:
  name: nvbugs-agent-secrets
  type: custom
  credentialsFrom:
    - source:
        type: kubernetesSecret
        namespace: tenant-nvbugs-prod
        name: nvbugs-provider-credentials
      mode: providerProfileKeys

providerProfileKeys imports Secret keys that match credentials declared by the provider profile.

A broader mode can allow importing all keys from the Secret:

credentialsFrom:
  - source:
      type: kubernetesSecret
      namespace: tenant-nvbugs-prod
      name: nvbugs-provider-credentials
    mode: allKeys

allKeys imports every key from the referenced Secret into the provider environment.

Runtime Behavior

Preferred flow:

  1. Platform syncs approved credentials from Vault/OpenBao/etc. into a Kubernetes Secret using ESO.
  2. Platform creates or references an OpenShell provider that points to the Kubernetes Secret.
  3. OpenShell Gateway validates that the caller is allowed to use that Secret reference.
  4. When a sandbox starts or refreshes provider environment, OpenShell resolves the Secret value.
  5. The supervisor receives provider credential material through the existing provider environment flow.
  6. The child agent receives placeholders, and OpenShell supervisor/proxy performs credential injection or rewrite according to provider policy.

A secondary implementation option is mounting the Kubernetes Secret into a supervisor-only path and letting the supervisor resolve provider credentials from that mounted Secret. This should only be used if OpenShell can guarantee the child agent process cannot read the mounted Secret directly. If supervisor and child agent share the same container filesystem/user boundary, gateway-side Secret resolution is safer.

Security Requirements

  • Kubernetes Secret references must be authorized before use.
  • Secret namespace, name, and key access must be scoped by caller identity or OpenShell policy.
  • Cross-tenant Secret reads must be denied by default.
  • Secret values must not appear in provider get/list output, logs, events, or audit records.
  • Audit records should include provider name, credential key, Secret reference, sandbox identity, and caller identity, but not the Secret value.
  • Missing, unauthorized, or unreadable Secrets should fail closed.
  • credentialsFrom extraction should support provider-profile-declared keys and full Secret extraction.

Alternatives Considered

Store credentials directly in OpenShell provider records

This works for simple deployments but does not fit Kubernetes platforms that already manage credential ownership, sync, rotation, and audit through Vault/OpenBao plus ESO.

Mount arbitrary Kubernetes Secrets directly into sandbox pods

This is Kubernetes-native but risky if the child agent can read the Secret file or env var directly. Provider credentials should continue to flow through OpenShell’s controlled supervisor/provider model.

Support only Vault/OpenBao directly

Vault/OpenBao should be a possible future backend, but many Kubernetes platforms already standardize on ESO as the bridge. Supporting Kubernetes Secret as a backend lets OpenShell integrate with multiple external secret managers through the Kubernetes-native handoff object.

Agent Investigation

I inspected the current provider and sandbox credential flow:

  • docs/sandboxes/providers-v2.mdx says Providers v2 combines provider credentials with provider-owned policy and that credential delivery still uses placeholder environment variables plus proxy rewrite.
  • proto/datamodel.proto defines Provider.credentials as map<string, string>, so provider records currently carry concrete credential values.
  • proto/openshell.proto has SandboxSpec.providers, and GetSandboxProviderEnvironment returns provider environment variables to the sandbox supervisor.
  • crates/openshell-sandbox/src/lib.rs fetches provider environment from the gateway during sandbox startup and refresh.
  • crates/openshell-sandbox/src/secrets.rs builds placeholder-based secret resolution from provider environment values.
  • crates/openshell-server/src/grpc/provider.rs resolves provider environment from stored provider records.
  • I did not find a dedicated Kubernetes Secret provider credential backend issue. The closest broader issue is Support platform-managed Kubernetes sandboxes with namespace, Secret, and SandboxClaim controls #1678.

Checklist

  • I've reviewed existing issues and the architecture docs
  • This is a design proposal, not a "please build this" request

Metadata

Metadata

Assignees

No one assigned

    Labels

    state:triage-neededOpened without agent diagnostics and needs triage

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions