Skip to content

feat(provider): add Kubernetes - #387

Open
giancarlopernudisegura wants to merge 10 commits into
cachix:mainfrom
giancarlopernudisegura:feat/kubernetes-provider
Open

feat(provider): add Kubernetes#387
giancarlopernudisegura wants to merge 10 commits into
cachix:mainfrom
giancarlopernudisegura:feat/kubernetes-provider

Conversation

@giancarlopernudisegura

@giancarlopernudisegura giancarlopernudisegura commented Aug 19, 2026

Copy link
Copy Markdown

Summary

  • add Kubernetes provider support with refs, writes (including refs)
  • can use either Kubernetes ConfigMaps or Secrets
  • reference Kubernetes object in specific namespace or omit for default cluster namespace
  • document 0.20+ configuration

Scenario coverage

  • Secret value is stored in Kubernetes because it was generated by a helm provider
  • Secret value is stored in Kubernetes and gets updated via cronjob so only accurate real-time value exists there
  • User may lack permission to write to the Kubernetes ConfigMap or Secret
  • User may want to reference a specific key in the Kubernetes ConfigMap/Secret via ref

Validation

  • cargo test --all
  • devenv shell -- prek run -a
  • npm --prefix docs run build
  • Manually tested that getting and setting values worked for both ConfigMaps and Secrets, with or without explicit namespace, and with or without refs using an AKS cluster.

Fixes #316

}),
Err(_) => runtime().block_on(future),
}
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Just to be upfront, this snippet is essentially a copy/paste from vault_common.rs. I don't know if it should be extracted to some common function or if just mentioning in a comment that it's essentially a duplicate is fine. Initially I just used super::block_on but that caused panics when trying to set a secret value.

@domenkozar domenkozar 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.

Six actionable inline findings on the Kubernetes provider implementation.

Comment thread secretspec/src/provider/kubernetes.rs Outdated
resource_attributes: Some(ResourceAttributes {
namespace: Some(namespace.into()),
verb: Some("patch".to_string()),
resource: Some(self.config.kind.to_string()),

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.

[P1] Use plural resource names in access reviews

Kubernetes RBAC checks use plural API resource names. Display yields secret or configmap here, so ordinary roles granting resources: ["secrets"] or resources: ["configmaps"] will not match this SelfSubjectAccessReview, and authorized writes will be rejected. Map each kind to its plural API resource name for this field.

config: KubernetesConfig,
name: "kubernetes",
description: "Kubernetes",
schemes: ["k8s+configmap", "k8s+secret"],

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.

[P1] Keep the bare name out of provider selection

The global provider picker persists info.name, so this registration offers kubernetes even though the registry only accepts the two configured URI schemes. Selecting it produces a provider value that later construction—and config global init --provider kubernetes itself—rejects. Please either exclude this provider from bare-name selection or make the flow collect a concrete Kubernetes URI.

description: "Kubernetes",
schemes: ["k8s+configmap", "k8s+secret"],
examples: ["k8s+secret://db-config", "k8s+configmap://db-config@default"],
deletes: true,

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.

[P2] Stop advertising deletion until it is implemented

This advertises static delete support, but KubernetesProvider implements neither delete nor supports_delete, so it inherits the unsupported-operation behavior. That admits cache invalidation and import --delete-source planning only for instance deletion to fail. Remove this flag until deletion is implemented, or implement the capability consistently.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Implemented deletion in 75d67f6

Comment thread secretspec/src/provider/kubernetes.rs Outdated
Comment on lines +351 to +352
fn check_writable(&self, _addr: Address<'_>) -> Result<()> {
let can_i_patch = block_on(self.can_i_patch())?;

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.

[P2] Resolve the address during write preflight

_addr is ignored, so check_writable can succeed for a native address containing an unsupported coordinate such as field; set then reaches resolve_coords and rejects it only after the CLI may have prompted for a value. Resolve the address here before the permission review so preflight rejects everything set will reject.

Comment thread secretspec/src/provider/kubernetes.rs Outdated
}

fn format_secret_name(project: &str, profile: &str, key: &str) -> Result<String> {
let secret_name = format!("secretspec-{}-{}-{}", project, profile, key);

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.

[P2] Encode convention components without collisions

Hyphen concatenation is not injective: (project="a-b", profile="c", key="KEY") and (project="a", profile="b-c", key="KEY") both become secretspec-a-b-c-KEY. Projects sharing the Kubernetes object can therefore read or overwrite one another. Use an injective component encoding or a reserved delimiter so the profile-aware path remains isolated.

Comment thread secretspec/src/provider/kubernetes.rs Outdated
struct: KubernetesProvider,
config: KubernetesConfig,
name: "kubernetes",
description: "Kubernetes",

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.

[P2] Add the release version to the CLI description

This description feeds the config init selector, so it currently renders kubernetes: Kubernetes without the release marker. Because this provider targets the unreleased 0.20 release, label the registration description Kubernetes (0.20+), matching the version required at every selector entry.

**Prerequisites**: A Kubernetes configuration in `$KUBECONFIG` or
`$HOME/.kube/config`; build with `--features kubernetes` (0.20+)
**Authentication**: Configured in Kubernetes configuration
**Storage**: `secretspec-{project}-{profile}-{key}` key under `.data` in the

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.

Kubernetes Secret and ConfigMap .data fields are flat key/value maps rather than folder hierarchies, and / is not valid in a data key. The implementation reserves -- to separate the SecretSpec coordinates, so this should match it: secretspec--{project}--{profile}--{key}.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support kubernetes secrets as provider

3 participants