Skip to content

feat(k8s): add Kubernetes KMS plugin and operator#999

Open
p0wline wants to merge 6 commits into
developfrom
feat/k8s-kms-plugin
Open

feat(k8s): add Kubernetes KMS plugin and operator#999
p0wline wants to merge 6 commits into
developfrom
feat/k8s-kms-plugin

Conversation

@p0wline

@p0wline p0wline commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Scope

This PR introduces two new crates under crate/clients/:

1. k8s_plugin — Kubernetes KMS Provider Plugin (v2)

A Unix-domain gRPC server implementing the Kubernetes KMS v2 provider API.
kube-apiserver calls it to encrypt/decrypt Data Encryption Keys (DEKs) stored in etcd.
The plugin delegates all crypto to the Cosmian KMS server.

Key files: src/main.rs, src/service.rs, src/config.rs, proto/v2.proto

2. k8s_operator — Kubernetes Operator (CRD controller + mutating admission webhook)

A full Kubernetes operator that:

  • Defines a KMSSecret CRD — declarative KMS-backed secrets with auto-refresh
  • Runs a reconciling controller (kube-runtime) that fetches secret bytes from the Cosmian KMS and stores them in Kubernetes Secrets
  • Runs a mutating admission webhook that rewrites Pod specs to inject an init-container that mounts KMS-fetched secrets into the pod filesystem at startup

This component is security-sensitive: it mutates Pod specs, injects init-containers, and manages long-lived KMS credentials on behalf of workloads.

Key files: src/webhook.rs, src/controller.rs, src/crd.rs, src/config.rs

Security notes

  • The KMS API token is injected into Pods via valueFrom.secretKeyRef (not as a literal value)
  • The Unix socket for the KMS plugin is created in a 0700 directory before bind to eliminate the TOCTOU window
  • The webhook TLS certificate is either loaded from disk or auto-generated (self-signed) at startup

@p0wline
p0wline force-pushed the feat/k8s-kms-plugin branch 2 times, most recently from c5e3675 to 2317356 Compare June 15, 2026 13:03
@p0wline

p0wline commented Jun 16, 2026

Copy link
Copy Markdown
Contributor Author

@copilot resolve the merge conflicts in this pull request

Copilot AI commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

Done — merged main (5.23.0) into this branch. The merge was clean with no conflicts. Merge commit: b634f5a.

@p0wline
p0wline force-pushed the feat/k8s-kms-plugin branch 2 times, most recently from 10eef1b to dc6f4ba Compare June 16, 2026 08:59
@p0wline
p0wline requested a review from Manuthor June 16, 2026 12:03
@Cosmian Cosmian deleted a comment from Copilot AI Jun 16, 2026
@p0wline p0wline closed this Jun 16, 2026
@Cosmian Cosmian deleted a comment from Copilot AI Jun 16, 2026
@p0wline p0wline reopened this Jun 16, 2026
@p0wline
p0wline requested a review from Copilot June 16, 2026 13:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 Kubernetes KMS v2 provider plugin binary (cosmian-kms-plugin) to let kube-apiserver delegate Encrypt/Decrypt operations to Cosmian KMS (via KMIP), along with documentation, test vectors, and Nix vendor-hash updates.

Changes:

  • Introduces cosmian_kms_k8s_plugin crate (gRPC service, YAML config, build-time proto generation).
  • Adds integration docs + MkDocs navigation entry for the Kubernetes plugin.
  • Adds a KMS test vector runner entry for the plugin flow and updates Nix expected vendor hashes / Cargo.lock.

Reviewed changes

Copilot reviewed 18 out of 19 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
nix/expected-hashes/ui.vendor.non-fips.sha256 Updates UI vendor hash for Nix builds.
nix/expected-hashes/ui.vendor.fips.sha256 Updates UI vendor hash for Nix builds.
nix/expected-hashes/server.vendor.static.sha256 Updates server vendor hash for Nix builds.
nix/expected-hashes/cli.vendor.linux.sha256 Updates CLI vendor hash for Nix builds.
documentation/mkdocs.yml Adds the Kubernetes plugin page to site navigation.
documentation/docs/integrations/kubernetes_kms_plugin.md New integration documentation for the Kubernetes KMS v2 plugin.
crate/test_kms_server/src/vector_runner.rs Registers a new test vector for the plugin wrap/unwrap flow.
crate/clients/k8s_plugin/src/service.rs Implements the KMS v2 gRPC service delegating to KmsClient KMIP Encrypt/Decrypt.
crate/clients/k8s_plugin/src/main.rs Adds CLI entrypoint: loads config, binds Unix socket, serves tonic gRPC.
crate/clients/k8s_plugin/src/kmsv2.proto Adds the Kubernetes KMS v2 proto definition (Apache 2.0 source).
crate/clients/k8s_plugin/src/integration_tests.rs New end-to-end test: spins up test KMS + plugin and checks Status/Encrypt/Decrypt.
crate/clients/k8s_plugin/src/error.rs Introduces plugin error type and maps it to tonic::Status.
crate/clients/k8s_plugin/src/config.rs Adds YAML config schema + loader for the plugin.
crate/clients/k8s_plugin/Cargo.toml New crate manifest (deps: tonic/prost/protox, serde_yaml, etc.).
crate/clients/k8s_plugin/build.rs Generates tonic bindings from the proto at build time (protox-based).
Cargo.toml Adds the new crate to the workspace members list.
Cargo.lock Locks new dependencies pulled in by the plugin (tonic-build/protox/etc.).

Comment thread crate/clients/k8s/plugin/src/config.rs
Comment thread crate/clients/k8s/plugin/build.rs Outdated
Comment thread crate/clients/k8s_plugin/src/main.rs Outdated
Comment thread crate/clients/k8s_plugin/src/main.rs Outdated
Comment thread documentation/docs/integrations/kubernetes_kms_plugin.md Outdated
Comment thread crate/clients/k8s_plugin/src/integration_tests.rs Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 22 out of 23 changed files in this pull request and generated 12 comments.

Comment thread crate/clients/k8s_plugin/src/service.rs Outdated
Comment thread crate/clients/k8s_plugin/src/service.rs Outdated
Comment thread crate/clients/k8s/plugin/src/config.rs
Comment thread crate/clients/k8s_plugin/src/main.rs Outdated
Comment thread documentation/docs/integrations/kubernetes/index.md
Comment thread crate/clients/k8s_operator/src/main.rs Outdated
Comment thread crate/clients/k8s_operator/src/config.rs Outdated
Comment thread crate/clients/k8s_plugin/Cargo.toml
Comment thread crate/clients/k8s_operator/Cargo.toml Outdated
Comment thread crate/test_kms_server/src/vector_runner.rs

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 22 out of 23 changed files in this pull request and generated 21 comments.

Comment thread crate/clients/k8s_operator/Cargo.toml Outdated
Comment thread crate/clients/k8s_operator/src/controller.rs
Comment thread crate/clients/k8s_operator/src/controller.rs Outdated
Comment thread crate/clients/k8s_operator/src/controller.rs
Comment thread crate/clients/k8s_operator/src/controller.rs
Comment thread crate/clients/k8s_plugin/src/integration_tests.rs Outdated
Comment thread crate/clients/k8s/plugin/build.rs Outdated
Comment thread crate/clients/k8s/operator/src/webhook.rs
Comment thread documentation/docs/integrations/kubernetes/index.md
Comment thread crate/clients/k8s/plugin/src/config.rs

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 24 out of 25 changed files in this pull request and generated 5 comments.

Comment thread crate/clients/k8s_plugin/src/integration_tests.rs Outdated
Comment thread crate/clients/k8s_operator/src/controller.rs Outdated
Comment thread crate/clients/k8s_plugin/src/main.rs Outdated
Comment thread documentation/docs/integrations/kubernetes_kms_plugin.md Outdated
Comment thread crate/clients/k8s_operator/src/crd.rs Outdated
@p0wline
p0wline requested a review from Copilot June 25, 2026 13:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

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

Comment thread crate/clients/k8s_plugin/src/lib.rs Outdated
Comment thread crate/clients/k8s_operator/src/lib.rs Outdated
Comment thread crate/clients/k8s_operator/src/webhook.rs Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

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

Comment thread crate/clients/k8s_plugin/src/main.rs Outdated
Comment thread crate/clients/k8s_operator/src/config.rs Outdated
Comment thread crate/clients/k8s/operator/src/lib.rs

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 25 out of 26 changed files in this pull request and generated 5 comments.

Comment thread Cargo.toml Outdated
Comment thread crate/clients/k8s_operator/src/webhook.rs Outdated
Comment thread crate/clients/k8s/operator/Cargo.toml
Comment thread crate/clients/k8s/operator/src/webhook.rs
Comment thread crate/clients/k8s/plugin/src/main.rs Outdated
@p0wline p0wline changed the title Feat/k8s kms plugin feat(k8s): add Kubernetes KMS plugin and operator Jun 26, 2026
@chokoblitz

Copy link
Copy Markdown
Contributor

Suggestion: extract the E2E job + reuse the new Helm chart

Nice work on the KMS plugin + operator — the etcd encryption E2E test is thorough. Two suggestions, both non-blocking:

1. Extract k8s-plugin-e2e into its own workflow file

The job added to test_all.yml is ~310 lines inline. The repo already has a pattern for this — test_windows.yml is a standalone workflow_call file, invoked from test_all.yml with a 4-line uses: block. Suggest doing the same here:

  • Move the whole k8s-plugin-e2e job body into .github/workflows/k8s_plugin_e2e.yml with:

    on:
      workflow_call:
        inputs:
          toolchain:
            required: true
            type: string
  • Replace the inline block in test_all.yml with:

    k8s-plugin-e2e:
      name: KMS plugin E2E (Minikube)
      if: >-
        github.event_name == 'workflow_dispatch' ||
        github.event_name == 'push' ||
        (github.event_name == 'pull_request' &&
          github.event.pull_request.head.repo.full_name == github.repository)
      uses: ./.github/workflows/k8s_plugin_e2e.yml
      with:
        toolchain: ${{ inputs.toolchain }}

Keeps test_all.yml scannable and makes the job runnable/reviewable standalone.

2. Consider deploying the KMS server via the new charts/cosmian-kms Helm chart instead of docker run

Right now the KMS server for this test runs as a plain Docker container on the runner host, then gets bridged into the Minikube network (docker network connect + IP inspection) so the plugin can reach it. A Helm chart for deploying cosmian-kms on Kubernetes just landed (charts/cosmian-kms, see #886). Deploying KMS inside the same cluster via:

helm install my-kms charts/cosmian-kms \
  --set kms.database.type=sqlite \
  -n kms-plugin-e2e --wait

would let the plugin config reference the in-cluster Service DNS name directly (http://my-kms-cosmian-kms.kms-plugin-e2e.svc.cluster.local:9998), removing the docker network connect + IP-lookup steps. helm test my-kms then becomes a meaningful post-install sanity check on top of the existing KMS-reachability curl check.

Implements a gRPC KMS v2 plugin (cosmian-kms-plugin) that enables
kube-apiserver to use Cosmian KMS as the encryption provider for
Kubernetes Secrets stored in etcd.

- Add crate/clients/k8s/plugin: tonic 0.12 gRPC server on Unix socket
  implementing the KMS v2 Status/Encrypt/Decrypt service
- Add Helm chart (charts/cosmian-kms) for deploying KMS inside a cluster
- Add dedicated CI workflow (.github/workflows/k8s_plugin_e2e.yml)
  with full Minikube E2E test: deploy KMS via Helm, install plugin via
  systemd, configure etcd encryption, verify secret encrypted at rest,
  verify decrypt via kubectl
- Use kubernetes-version v1.32.0 (adds grpc.WithAuthority(localhost)
  fixing RST_STREAM PROTOCOL_ERROR from h2 URI authority validation)
@p0wline
p0wline force-pushed the feat/k8s-kms-plugin branch from 1443ba2 to 90453a8 Compare July 15, 2026 15:34
@chokoblitz

Copy link
Copy Markdown
Contributor

Follow-up: pin the KMS image tag in the Helm install step

Small addition to the Helm-based deployment — the helm install call doesn't override image.tag:

helm install my-kms charts/cosmian-kms --namespace kms-plugin-e2e \
  --set kms.database.type=sqlite --wait --timeout 120s

Without it, the chart falls back to Chart.yaml's appVersion (currently pinned to 5.24.0). Before the switch to Helm, this job explicitly pulled ghcr.io/cosmian/kms:latest, so the test tracked develop's current image. Now it silently deploys whatever version string happens to be in the chart, which:

  • no longer tracks the bleeding-edge image on develop
  • will quietly go stale if Chart.yaml's appVersion isn't bumped in lockstep with every KMS release

Not a functional blocker today (the plugin only needs standard KMIP Get/Encrypt/Decrypt, so any recent server version works), but worth pinning explicitly to keep the test meaningful over time:

helm install my-kms charts/cosmian-kms --namespace kms-plugin-e2e \
  --set kms.database.type=sqlite \
  --set image.tag=latest \
  --wait --timeout 120s

(or whichever tag corresponds to the image this job is meant to validate against).

p0wline added 5 commits July 17, 2026 10:55
…bited' state

IRIS can return <HALTED> with 'Access to database inhibited' during the
KMIP server setup if the write-behind cache has not fully flushed when
the session starts. Wrap the KMIP_OUTPUT assignment in a retry loop (up
to 3 attempts, 15 s apart) that only retries on this specific transient
condition; all other errors still fail immediately.
- Add helm lint step to validate chart syntax before cluster tests
- Build cosmian_kms_k8s_operator and cosmian_kms_csi_provider in CI
- Run unit tests for all 3 k8s crates (plugin, operator, csi_provider)
- Add operator inject E2E: fetch KEK from KMS, verify file written to disk
- Add CSI provider E2E: install CSI driver, deploy SecretProviderClass + pod,
  verify secret file mounted inside container
- Extend debug section with CSI provider logs and socket state
- Increase timeout 45min → 90min for the additional E2E phases
- Remove unused test_kms_server dev-dep from csi_provider Cargo.toml
- Fix machete false-positive: prost is used, remove ignored annotation
bash printf interprets leading '-' in format string as an option flag,
causing 'printf: - : invalid option' (exit code 2) in the Create
SecretProviderClass step.
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.

4 participants