Skip to content

feat: use velero SA and add bound-sa-token volume for KDM controller - #2349

Merged
openshift-merge-bot[bot] merged 1 commit into
openshift:oadp-devfrom
shubham-pampattiwar:feat/kdm-sts-bound-sa-token
Aug 5, 2026
Merged

feat: use velero SA and add bound-sa-token volume for KDM controller#2349
openshift-merge-bot[bot] merged 1 commit into
openshift:oadp-devfrom
shubham-pampattiwar:feat/kdm-sts-bound-sa-token

Conversation

@shubham-pampattiwar

@shubham-pampattiwar shubham-pampattiwar commented Aug 4, 2026

Copy link
Copy Markdown
Member

Summary

  • Switch KDM controller deployment from oadp-kubevirt-datamover-controller-manager SA to velero SA, since KDM is always deployed by OADP and the velero SA already has IAM trust configured on STS clusters
  • Add bound-sa-token projected volume and mount to the KDM controller deployment for STS authentication
  • Update CSV serviceAccountName entries to bind KDM RBAC permissions to the velero SA

Test plan

  • Verify unit tests pass (go test ./internal/controller/ -run "TestEnsureKubevirtDatamoverRequiredSpecs|TestBuildKubevirtDatamoverDeployment")
  • Deploy on a ROSA STS or OCP STS cluster with OADP STS configuration
  • Verify KDM controller pod starts successfully with velero SA
  • Verify KDM controller can authenticate to S3 for BSL checkpoint lookup
  • Verify non-STS clusters are unaffected
  • Verify KDM controller retains required RBAC permissions (can manage DataUploads, Pods, VMBs)

Companion PR: migtools/kubevirt-datamover-controller#158 - adds bound-sa-token volume to datamover pod
Parent issue: migtools/kubevirt-datamover-controller#25

Fixes: migtools/kubevirt-datamover-controller#24

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Updated KubeVirt DataMover deployments to use the Velero service account.
    • Added a projected OpenShift service-account token with the required audience and one-hour expiration.
    • Mounted the token read-only at the expected path for deployment authentication.
    • Consolidated required Kubernetes, KubeVirt, Velero, authentication, and authorization permissions into the Velero permission set.
    • Updated leader-election, metrics, and related access bindings to use the Velero service account consistently.

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: a0f725a9-b6a5-4180-820d-64423477212c

📥 Commits

Reviewing files that changed from the base of the PR and between 65aba4d and 0aa7038.

📒 Files selected for processing (7)
  • bundle/manifests/oadp-operator.clusterserviceversion.yaml
  • config/kubevirt-datamover-controller_rbac/kustomization.yaml
  • config/kubevirt-datamover-controller_rbac/leader_election_role_binding.yaml
  • config/kubevirt-datamover-controller_rbac/metrics_auth_role_binding.yaml
  • config/kubevirt-datamover-controller_rbac/role_binding.yaml
  • internal/controller/kubevirt_datamover_controller.go
  • internal/controller/kubevirt_datamover_controller_test.go
💤 Files with no reviewable changes (1)
  • config/kubevirt-datamover-controller_rbac/kustomization.yaml
🚧 Files skipped from review as they are similar to previous changes (6)
  • config/kubevirt-datamover-controller_rbac/role_binding.yaml
  • config/kubevirt-datamover-controller_rbac/metrics_auth_role_binding.yaml
  • config/kubevirt-datamover-controller_rbac/leader_election_role_binding.yaml
  • internal/controller/kubevirt_datamover_controller.go
  • internal/controller/kubevirt_datamover_controller_test.go
  • bundle/manifests/oadp-operator.clusterserviceversion.yaml

Walkthrough

The KubeVirt datamover now uses the velero service account, consolidated Velero permissions, and a projected OpenShift service-account token mounted at the STS token path.

Changes

KubeVirt datamover STS authentication

Layer / File(s) Summary
Consolidate datamover permissions
bundle/manifests/oadp-operator.clusterserviceversion.yaml
The Velero permission set receives the KubeVirt datamover permissions. Permission service-account assignments now point to the velero service account through the controller permission sets.
Configure deployment token and RBAC bindings
internal/controller/kubevirt_datamover_controller.go, config/kubevirt-datamover-controller_rbac/*.yaml
The deployment uses velero and mounts a read-only projected OpenShift token at /var/run/secrets/openshift/serviceaccount. Leader-election, metrics-auth, and controller RBAC bindings target velero.
Validate the deployment configuration
internal/controller/kubevirt_datamover_controller_test.go
Tests verify the velero service account, projected bound-sa-token volume, token settings, and read-only mount.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant KubeVirtDatamoverController
  participant KubeVirtDatamoverDeployment
  participant OpenShiftSTS
  KubeVirtDatamoverController->>KubeVirtDatamoverDeployment: Create deployment with velero service account
  KubeVirtDatamoverController->>KubeVirtDatamoverDeployment: Mount projected token at /var/run/secrets/openshift/serviceaccount
  KubeVirtDatamoverDeployment->>OpenShiftSTS: Use openshift-audience token
Loading

Possibly related PRs

Suggested reviewers: joeavaikath, sseago

🚥 Pre-merge checks | ✅ 13 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Test Structure And Quality ⚠️ Warning Ginkgo table tests use context.Background for Kubernetes Create/Get/Delete calls, have no bounded waits, and contain bare Expect assertions without diagnostic messages. Use BeforeEach for setup, bounded contexts or Eventually with timeouts for Kubernetes operations, and add messages to every Gomega assertion.
✅ Passed checks (13 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the service account change and projected token volume added for the KDM controller.
Description check ✅ Passed The description explains the purpose, implementation, testing plan, linked work, and affected STS behavior, despite different section headings from the template.
Linked Issues check ✅ Passed The changes satisfy issue #24 requirements for the OADP-side KDM controller, including velero RBAC, service account use, and bound-sa-token mounting.
Out of Scope Changes check ✅ Passed All changes support issue #24 by updating KDM controller deployment, RBAC bindings, CSV permissions, and related tests.
Stable And Deterministic Test Names ✅ Passed The changed test file adds no test titles. Existing Ginkgo entries and Go subtest names are static; namespace values remain in test bodies only.
Microshift Test Compatibility ✅ Passed The PR adds no new Ginkgo tests. It only updates existing Go unit-test assertions, and no unavailable MicroShift APIs or namespaces are added.
Single Node Openshift (Sno) Test Compatibility ✅ Passed The PR adds no new Ginkgo e2e tests. Changes are unit/envtest assertions in internal/controller and contain no SNO-sensitive multi-node or HA assumptions.
Topology-Aware Scheduling Compatibility ✅ Passed The diff adds only a projected token volume, service-account changes, and RBAC updates; replicas remains 1, with no affinity, topology spread, node selector, toleration, or PDB constraint added.
Ote Binary Stdout Contract ✅ Passed The PR changes only KDM deployment specs and assertions; the added Go lines contain no stdout, klog, suite-setup, main, or init writes.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed The commit changes only controller/unit tests; no tests/e2e files or new external-network or IPv4-specific test logic were added.
No-Weak-Crypto ✅ Passed The patch adds only a projected service-account token and RBAC changes; no weak algorithm, crypto API, custom crypto, or secret/token value comparison is introduced.
Container-Privileges ✅ Passed The PR adds no privileged, hostPID, hostNetwork, hostIPC, SYS_ADMIN, root, or escalation settings; the KDM container drops ALL capabilities and disables privilege escalation, with runAsNonRoot at p...
No-Sensitive-Data-In-Logs ✅ Passed The commit adds a projected token mount and RBAC only; it adds no logging calls or log fields containing tokens, passwords, keys, PII, hostnames, or customer data.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@openshift-ci
openshift-ci Bot requested review from Joeavaikath and sseago August 4, 2026 01:13
@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Aug 4, 2026

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/controller/kubevirt_datamover_controller_test.go`:
- Around line 952-963: The volume assertions in both test blocks should validate
the ServiceAccountTokenProjection fields, not only that Projected is non-nil.
Extend the checks around hasBoundSATokenVolume to require Audience "openshift",
ExpirationSeconds 3600, and Path "token", while preserving the existing
volume-name and projected-source requirements.
- Around line 976-986: The test currently verifies the bound service-account
mount only when no existing containers are provided, leaving the
existing-manager reconciliation path uncovered. Add or update a test case with
an existing “manager” container, run reconciliation, then apply the same
volume-mount assertions to the updated manager container, including name, mount
path, and read-only status.

In `@internal/controller/kubevirt_datamover_controller.go`:
- Around line 267-271: The existing-manager reconciliation path does not add the
projected STS token mount. In
internal/controller/kubevirt_datamover_controller.go:267-271, update the
existing manager container branch to upsert the bound-sa-token mount at the
configured path with read-only access, reusing the same mount definition as
newly created managers. In
internal/controller/kubevirt_datamover_controller_test.go:976-986, extend the
existing manager container test to assert that this mount is present.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 71e04d4e-08bd-462d-9fee-c80fe3bc4a9d

📥 Commits

Reviewing files that changed from the base of the PR and between 789130a and 72e3610.

📒 Files selected for processing (3)
  • bundle/manifests/oadp-operator.clusterserviceversion.yaml
  • internal/controller/kubevirt_datamover_controller.go
  • internal/controller/kubevirt_datamover_controller_test.go

Comment on lines +952 to +963
// Verify bound-sa-token projected volume is present on pod spec
hasBoundSATokenVolume := false
for _, v := range volumes {
if v.Name == "bound-sa-token" && v.VolumeSource.Projected != nil {
hasBoundSATokenVolume = true
break
}
}
if !hasBoundSATokenVolume {
t.Error("expected bound-sa-token projected volume on pod spec")
}

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Assert the token projection fields.

The new checks only require VolumeSource.Projected != nil. They do not verify ServiceAccountTokenProjection. Assert Audience == "openshift", ExpirationSeconds == 3600, and Path == "token" in both test blocks. A wrong token file contract would pass these tests and break STS authentication.

Also applies to: 1252-1274

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/controller/kubevirt_datamover_controller_test.go` around lines 952 -
963, The volume assertions in both test blocks should validate the
ServiceAccountTokenProjection fields, not only that Projected is non-nil. Extend
the checks around hasBoundSATokenVolume to require Audience "openshift",
ExpirationSeconds 3600, and Path "token", while preserving the existing
volume-name and projected-source requirements.

Comment on lines +976 to +986

hasBoundSATokenMount := false
for _, vm := range container.VolumeMounts {
if vm.Name == "bound-sa-token" && vm.MountPath == "/var/run/secrets/openshift/serviceaccount" && vm.ReadOnly {
hasBoundSATokenMount = true
break
}
}
if !hasBoundSATokenMount {
t.Error("expected bound-sa-token volumeMount on container")
}

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Test the existing-manager reconciliation path.

This assertion is guarded by len(tt.existingContainers) == 0. The existing-manager test can pass without the bound-sa-token mount. Add a case that verifies the mount after updating an existing manager container.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/controller/kubevirt_datamover_controller_test.go` around lines 976 -
986, The test currently verifies the bound service-account mount only when no
existing containers are provided, leaving the existing-manager reconciliation
path uncovered. Add or update a test case with an existing “manager” container,
run reconciliation, then apply the same volume-mount assertions to the updated
manager container, including name, mount path, and read-only status.

Comment thread internal/controller/kubevirt_datamover_controller.go
@shubham-pampattiwar
shubham-pampattiwar force-pushed the feat/kdm-sts-bound-sa-token branch from 72e3610 to d9f4514 Compare August 4, 2026 01:41

@coderabbitai coderabbitai Bot 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.

🧹 Nitpick comments (1)
bundle/manifests/oadp-operator.clusterserviceversion.yaml (1)

1252-1371: 🔒 Security & Privacy | 🔵 Trivial

Document the KubeVirt DataMover RBAC blast radius.

The controller uses serviceAccountName: "velero"; oadp-kubevirt-datamover-controller-manager is the Deployment name, not a ServiceAccount reference. Document the velero ServiceAccount’s wildcard cluster-wide permissions and the STS trust requirement in the security review.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@bundle/manifests/oadp-operator.clusterserviceversion.yaml` around lines 1252
- 1371, Update the security review documentation associated with the KubeVirt
DataMover RBAC manifest to identify serviceAccountName "velero" as the
controller identity, not the oadp-kubevirt-datamover-controller-manager
Deployment. Document that this ServiceAccount has wildcard cluster-wide
permissions and explicitly record the required STS trust relationship.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@bundle/manifests/oadp-operator.clusterserviceversion.yaml`:
- Around line 1252-1371: Update the security review documentation associated
with the KubeVirt DataMover RBAC manifest to identify serviceAccountName
"velero" as the controller identity, not the
oadp-kubevirt-datamover-controller-manager Deployment. Document that this
ServiceAccount has wildcard cluster-wide permissions and explicitly record the
required STS trust relationship.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: d0b7f748-80e2-4b91-8327-5699d4dd8c92

📥 Commits

Reviewing files that changed from the base of the PR and between 72e3610 and d9f4514.

📒 Files selected for processing (7)
  • bundle/manifests/oadp-operator.clusterserviceversion.yaml
  • config/kubevirt-datamover-controller_rbac/kustomization.yaml
  • config/kubevirt-datamover-controller_rbac/leader_election_role_binding.yaml
  • config/kubevirt-datamover-controller_rbac/metrics_auth_role_binding.yaml
  • config/kubevirt-datamover-controller_rbac/role_binding.yaml
  • internal/controller/kubevirt_datamover_controller.go
  • internal/controller/kubevirt_datamover_controller_test.go
💤 Files with no reviewable changes (1)
  • config/kubevirt-datamover-controller_rbac/kustomization.yaml
🚧 Files skipped from review as they are similar to previous changes (2)
  • internal/controller/kubevirt_datamover_controller.go
  • internal/controller/kubevirt_datamover_controller_test.go

@shubham-pampattiwar

Copy link
Copy Markdown
Member Author

STS Testing Passed

Tested end-to-end on an AWS STS cluster (OCP 4.22, CCO Manual mode) with a cirros VM backup.

  • KDM controller running with velero SA and bound-sa-token volume mounted
  • BSL Available (Velero STS auth working)
  • Datamover pod authenticated to S3 via AssumeRoleWithWebIdentity
  • Backup completed successfully, data verified in S3 bucket

Full test report: migtools/kubevirt-datamover-controller#24 (comment)

@shubham-pampattiwar

Copy link
Copy Markdown
Member Author

/retest

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

Didn't we just get suggested by the Telco team to use a separate service account for RBAC between different controllers?

kaovilai
kaovilai previously approved these changes Aug 4, 2026

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

This PR slightly contradicts #2318

but it does pass https://redhat-best-practices-for-k8s.github.io/guide/#k8s-best-practices-automount-services-for-pods https://github.com/redhat-best-practices-for-k8s/certsuite/blob/main/CATALOG.md#access-control-pod-automount-service-account-token

But the KubeVirt Data Mover is highly coupled to using Velero Backup, unlike the CLI Server, so this may be okay.

@kaovilai

kaovilai commented Aug 4, 2026

Copy link
Copy Markdown
Member

/cherry-pick oadp-1.6

@openshift-cherrypick-robot

Copy link
Copy Markdown
Contributor

@kaovilai: once the present PR merges, I will cherry-pick it on top of oadp-1.6 in a new PR and assign it to you.

Details

In response to this:

/cherry-pick oadp-1.6

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@kaovilai

kaovilai commented Aug 4, 2026

Copy link
Copy Markdown
Member

need rebase: #2352 merged

@openshift-ci openshift-ci Bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Aug 5, 2026
On OpenShift STS clusters, pods authenticate to AWS using projected
service account tokens via the Cloud Credential Operator. The KDM
controller deployment was using a separate service account that had no
IAM trust configured, and was missing the bound-sa-token projected
volume needed for STS authentication.

Switch the KDM controller deployment to use the velero service account
(which already has IAM trust on STS clusters) and add the bound-sa-token
projected volume and mount. KDM is always deployed by OADP and never
standalone, so a separate SA is unnecessary. Update kustomize configs
to bind KDM RBAC permissions to the velero SA.

Fixes: migtools/kubevirt-datamover-controller#24

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@openshift-ci openshift-ci Bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Aug 5, 2026
@kaovilai

kaovilai commented Aug 5, 2026

Copy link
Copy Markdown
Member

/lgtm

@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label Aug 5, 2026
@openshift-ci

openshift-ci Bot commented Aug 5, 2026

Copy link
Copy Markdown

@shubham-pampattiwar: all tests passed!

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

@openshift-ci

openshift-ci Bot commented Aug 5, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: kaovilai, shubham-pampattiwar, sseago

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:
  • OWNERS [kaovilai,shubham-pampattiwar,sseago]

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-merge-bot
openshift-merge-bot Bot merged commit 5b6f637 into openshift:oadp-dev Aug 5, 2026
15 checks passed
@openshift-cherrypick-robot

Copy link
Copy Markdown
Contributor

@kaovilai: new pull request created: #2359

Details

In response to this:

/cherry-pick oadp-1.6

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

kaovilai added a commit to kaovilai/oadp-operator that referenced this pull request Aug 5, 2026
Resolving the CSV merge conflict against upstream's velero-SA RBAC
restructuring (PR openshift#2349) by taking upstream's side lost a small
generated permission block (events create/patch). make bundle
regenerates it correctly.

Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. lgtm Indicates that a PR is ready to be merged.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feat: Support AWS STS authentication (OpenShift CCO/STS)

4 participants