Skip to content

OADP-6540: Skip restore of k8s RBAC system rolebindings#402

Merged
openshift-merge-bot[bot] merged 2 commits into
openshift:oadp-devfrom
kaovilai:OADP-6540-skip-rbac-system-rolebindings
Jun 8, 2026
Merged

OADP-6540: Skip restore of k8s RBAC system rolebindings#402
openshift-merge-bot[bot] merged 2 commits into
openshift:oadp-devfrom
kaovilai:OADP-6540-skip-rbac-system-rolebindings

Conversation

@kaovilai

@kaovilai kaovilai commented Jun 8, 2026

Copy link
Copy Markdown
Member

Summary

  • Add K8sRestorePlugin in the rolebindings package for rolebindings (rbac.authorization.k8s.io) that skips system rolebindings (system:image-pullers, system:image-builders, system:deployers)
  • Export SystemRoleBindings map for reuse across both OCP and k8s restore plugins
  • Rename existing restore files to ocp_restore.go / ocp_restore_test.go for clarity
  • Modernize Makefile build image (golang:1.25) and flags

Problem

When restoring with namespace mapping (e.g. ns-ans-b), pods in the target namespace fail with ErrImagePull / ImagePullBackOff because they can't pull from the internal registry.

The root cause is that OpenShift auto-creates system:image-pullers when a namespace is created, with subjects pointing to the correct target namespace (system:serviceaccounts:ns-b). But Velero also restores the backed-up rbac.authorization.k8s.io/v1/RoleBinding named system:image-pullers, which overwrites the auto-created one with subjects still pointing to the source namespace (system:serviceaccounts:ns-a). Service accounts in ns-b then lack pull permissions for ns-b's image registry.

PR #311 fixed this for authorization.openshift.io rolebindings by skipping the three system rolebindings. But OpenShift stores rolebindings as rbac.authorization.k8s.io in etcd — the authorization.openshift.io API is a proxy/compatibility layer, not separate storage. Velero backs up both API groups because rolebindings is not in Velero's cohabitatingResources() dedup list. So the rbac.authorization.k8s.io variants were still being restored and overwriting the correct auto-created ones.

Fix

Skip the same three system rolebindings (system:image-pullers, system:image-builders, system:deployers) for the rbac.authorization.k8s.io API group. OpenShift creates these automatically with correct subject namespace references when a project is created, so they should never be restored from backup.

Test plan

  • Unit tests for K8sRestorePlugin (skip system, pass-through custom)
  • Existing rolebindings tests pass with exported SystemRoleBindings
  • go build ./velero-plugins/... compiles clean
  • E2E: Restore with namespace mapping, verify rbac.authorization.k8s.io/v1/RoleBinding system:image-pullers shows as (skipped) in velero logs
  • E2E: system:image-pullers subjects in target namespace correctly reference system:serviceaccounts:test-rb-target (not source namespace)

Fixes: https://issues.redhat.com/browse/OADP-6540

🤖 Generated with Claude Code

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Jun 8, 2026
@openshift-ci-robot

openshift-ci-robot commented Jun 8, 2026

Copy link
Copy Markdown

@kaovilai: This pull request references OADP-6540 which is a valid jira issue.

Details

In response to this:

Summary

  • Add RestoreItemAction for rolebindings (rbac.authorization.k8s.io) that skips system rolebindings (system:image-pullers, system:image-builders, system:deployers)
  • Export SystemRoleBindings from existing rolebindings package for reuse
  • Fixes namespace mapping restore causing ErrImagePull due to stale subject references in k8s RBAC rolebindings

Root Cause

PR #311 added skip logic for authorization.openshift.io rolebindings only. OpenShift stores rolebindings as rbac.authorization.k8s.io in etcd and exposes them via both API groups. Velero backs up both variants (rolebindings are not in Velero's cohabitating resources dedup list). During restore with namespace mapping, the k8s RBAC variants were restored with old namespace subjects, overwriting the correct auto-created ones.

Test plan

  • Unit tests for new rbacrolebindings plugin (skip system, pass-through custom)
  • Existing rolebindings tests pass with exported SystemRoleBindings
  • go build ./velero-plugins/... compiles clean
  • E2E: Restore with namespace mapping, verify rbac.authorization.k8s.io/v1/RoleBinding system:image-pullers shows as (skipped)
  • E2E: Pods can pull images from internal registry in mapped namespace

Fixes: https://issues.redhat.com/browse/OADP-6540

🤖 Generated with Claude Code

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 openshift-eng/jira-lifecycle-plugin repository.

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown

Walkthrough

Adds a Kubernetes RBAC rolebindings restore plugin that reuses an exported OpenShift system-rolebinding allowlist, registers the plugin in main.go, adds unit tests, splits README docs for OpenShift vs RBAC rolebindings, and modernizes the Makefile to use golang:1.25 with simplified Docker mounts.

Changes

Kubernetes RBAC Role Bindings Restore Plugin

Layer / File(s) Summary
Extract shared system rolebindings allowlist
velero-plugins/rolebindings/ocp_restore.go
The systemRoleBindings allowlist is renamed and exported to SystemRoleBindings so both OpenShift and Kubernetes RBAC restore plugins can reference it when skipping automatically-created system rolebindings during restore.
Kubernetes RBAC restore plugin implementation and tests
velero-plugins/rolebindings/k8s_restore.go, velero-plugins/rolebindings/k8s_restore_test.go
New K8sRestorePlugin type targets Kubernetes RBAC rolebindings resources. On execute, it unmarshals the rolebinding, logs entry/metadata, and conditionally skips restore when the name is in SystemRoleBindings; unit tests verify AppliesTo and the conditional skip logic for named system rolebindings.
Register K8s RBAC restore plugin
velero-plugins/main.go
Registers the new restore action "openshift.io/27-rbac-role-bindings-restore-plugin" in main() using newRBACRoleBindingRestorePlugin, which instantiates K8sRestorePlugin with the provided logger.
Documentation for dual role binding restore variants
README.md
Resources list now enumerates Role Bindings separately for authorization.openshift.io (OpenShift) and rbac.authorization.k8s.io (Kubernetes RBAC). Plugin descriptions are split into two subsections documenting each API group and the shared behavior of skipping system rolebindings.
Modernize build system to golang:1.25
Makefile
Updates BUILD_IMAGE to golang:1.25. The _output/$(BIN) recipe is rewritten to build from a mounted /workspace, use a single .go/.cache mount, set GOCACHE and GOFLAGS (-mod=mod -buildvcs=false), and simplify directory setup by removing the prior temporary workspace and multiple stdlib/pkg mounts.

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 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 Line 30 uses logrus.New() while line 19 and 49 codebase tests use test.NewLogger(). Assertions lack messages on lines 24, 26, 97, 98. Change line 30 logrus.New() to test.NewLogger(). Add assertion messages to lines 24, 26, 97, 98 (e.g., "AppliesTo should not error", "SkipRestore should be true for system rolebindings")
✅ Passed checks (13 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding a Kubernetes RBAC system rolebindings skip mechanism, which is the primary addition across the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Stable And Deterministic Test Names ✅ Passed Tests use Go's standard testing package with t.Run(), not Ginkgo. Custom check is inapplicable as it requires Ginkgo test syntax (It(), Describe(), etc.).
Microshift Test Compatibility ✅ Passed No Ginkgo e2e tests added in this PR. Only standard Go unit tests are included, which are outside the scope of this MicroShift compatibility check.
Single Node Openshift (Sno) Test Compatibility ✅ Passed PR contains no Ginkgo e2e tests—only standard Go unit tests for plugin functionality. SNO compatibility check does not apply.
Topology-Aware Scheduling Compatibility ✅ Passed PR is for Velero plugin code (backup/restore logic), not deployment manifests or operator code. No scheduling constraints, affinity rules, or workload specs introduced.
Ote Binary Stdout Contract ✅ Passed All code changes use logrus FieldLogger for logging (not stdout), no direct fmt.Print/log.Print calls, and factory function only instantiates plugins without process-level side effects.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed No new Ginkgo e2e tests were added; only standard Go unit tests using testing.T and testify. The check applies only to Ginkgo e2e tests.
No-Weak-Crypto ✅ Passed No weak cryptographic algorithms (MD5, SHA1, DES, RC4, 3DES, Blowfish, ECB), custom crypto implementations, or non-constant-time secret comparisons detected in the PR changes.
Container-Privileges ✅ Passed PR contains no Kubernetes manifests or container security configurations; changes are documentation, Go code, and build config without privilege escalation flags.
No-Sensitive-Data-In-Logs ✅ Passed All logging statements only log Kubernetes resource metadata (name, API version) and generic messages. No passwords, tokens, API keys, PII, credentials, or other sensitive data are exposed.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@openshift-ci openshift-ci Bot requested review from eemcmullan and sseago June 8, 2026 13:54
@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jun 8, 2026
@kaovilai

kaovilai commented Jun 8, 2026

Copy link
Copy Markdown
Member Author

/cherry-pick oadp-1.6

PR openshift#311 added skip logic for system rolebindings (system:image-pullers,
system:image-builders, system:deployers) but only for the
authorization.openshift.io API group. OpenShift stores these as
rbac.authorization.k8s.io objects and exposes them via both API groups.
Velero backs up both variants since rolebindings are not in Velero's
cohabitating resources dedup list.

During restore with namespace mapping, the k8s RBAC variants were
restored with stale subject references (old namespace), overwriting
the correct auto-created rolebindings and causing ErrImagePull.

Add a new RestoreItemAction for rolebindings (rbac.authorization.k8s.io)
that skips the same system rolebindings, letting OpenShift create them
with correct namespace references.

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com>
@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 Jun 8, 2026

Copy link
Copy Markdown
Member Author

/cherry-pick oadp-1.5

@kaovilai kaovilai force-pushed the OADP-6540-skip-rbac-system-rolebindings branch from 3918c36 to 999496b Compare June 8, 2026 14:00
@openshift-cherrypick-robot

Copy link
Copy Markdown
Contributor

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

Details

In response to this:

/cherry-pick oadp-1.5

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 Jun 8, 2026

Copy link
Copy Markdown
Member Author

/cherry-pick oadp-1.4

@openshift-cherrypick-robot

Copy link
Copy Markdown
Contributor

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

Details

In response to this:

/cherry-pick oadp-1.4

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.

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
velero-plugins/rolebindings/restore.go (1)

40-41: ⚠️ Potential issue | 🟠 Major

Handle JSON marshal/unmarshal errors in rolebinding restore flow.

  • velero-plugins/rolebindings/ocp_restore.go ignores json.Marshal/json.Unmarshal errors at lines 40-41 and 65-66, risking incorrect SystemRoleBindings skip decisions and returning malformed restore objects.
  • velero-plugins/rolebindings/k8s_restore.go also ignores json.Marshal/json.Unmarshal errors at lines 28-29 before evaluating SystemRoleBindings, so failed decoding can cause system rolebindings to be restored when they should be skipped.
Proposed fix
 import (
 	"encoding/json"
+	"fmt"
 	"strings"
@@
 	roleBinding := apiauthorization.RoleBinding{}
-	itemMarshal, _ := json.Marshal(input.Item)
-	json.Unmarshal(itemMarshal, &roleBinding)
+	itemMarshal, err := json.Marshal(input.Item)
+	if err != nil {
+		return nil, fmt.Errorf("marshal restore item: %w", err)
+	}
+	if err := json.Unmarshal(itemMarshal, &roleBinding); err != nil {
+		return nil, fmt.Errorf("unmarshal rolebinding: %w", err)
+	}
@@
 	var out map[string]interface{}
-	objrec, _ := json.Marshal(roleBinding)
-	json.Unmarshal(objrec, &out)
+	objrec, err := json.Marshal(roleBinding)
+	if err != nil {
+		return nil, fmt.Errorf("marshal rolebinding output: %w", err)
+	}
+	if err := json.Unmarshal(objrec, &out); err != nil {
+		return nil, fmt.Errorf("unmarshal output object: %w", err)
+	}
🤖 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 `@velero-plugins/rolebindings/restore.go` around lines 40 - 41, The code is
ignoring errors from json.Marshal/json.Unmarshal when decoding input.Item into
roleBinding (used to check SystemRoleBindings), which can lead to wrong skip
decisions or malformed restores; update the restore logic in the functions that
decode input.Item (the blocks using itemMarshal := json.Marshal(input.Item) and
json.Unmarshal(itemMarshal, &roleBinding) in ocp_restore.go and k8s_restore.go)
to capture and handle both marshal and unmarshal errors: check the error
returned by json.Marshal and json.Unmarshal, and on error either return the
error up the Restore flow or log and safely skip/abort the restore as
appropriate for SystemRoleBindings checking; ensure the variable roleBinding and
the SystemRoleBindings evaluation only proceed when decoding succeeded.

Source: Coding guidelines

🤖 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 `@velero-plugins/rbacrolebindings/restore.go`:
- Around line 29-30: The code currently ignores json.Marshal/json.Unmarshal
errors when converting input.Item to roleBinding/out in the Execute functions,
which can produce zero-value structs and incorrect skip/restore behavior; update
the Execute implementations (references: Execute, variable roleBinding in
velero-plugins/rolebindings/k8s_restore.go and the out variable in
velero-plugins/rolebindings/ocp_restore.go) to check the error returned by
json.Marshal and json.Unmarshal, and handle failures by returning or logging the
error and aborting the restore flow for that item rather than proceeding with a
zero-value object.

---

Outside diff comments:
In `@velero-plugins/rolebindings/restore.go`:
- Around line 40-41: The code is ignoring errors from
json.Marshal/json.Unmarshal when decoding input.Item into roleBinding (used to
check SystemRoleBindings), which can lead to wrong skip decisions or malformed
restores; update the restore logic in the functions that decode input.Item (the
blocks using itemMarshal := json.Marshal(input.Item) and
json.Unmarshal(itemMarshal, &roleBinding) in ocp_restore.go and k8s_restore.go)
to capture and handle both marshal and unmarshal errors: check the error
returned by json.Marshal and json.Unmarshal, and on error either return the
error up the Restore flow or log and safely skip/abort the restore as
appropriate for SystemRoleBindings checking; ensure the variable roleBinding and
the SystemRoleBindings evaluation only proceed when decoding succeeded.
🪄 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: ac42bc5a-7ac1-4775-a38f-7259e96278b3

📥 Commits

Reviewing files that changed from the base of the PR and between fe9b727 and 3918c36.

📒 Files selected for processing (5)
  • README.md
  • velero-plugins/main.go
  • velero-plugins/rbacrolebindings/restore.go
  • velero-plugins/rbacrolebindings/restore_test.go
  • velero-plugins/rolebindings/restore.go

Comment thread velero-plugins/rbacrolebindings/restore.go Outdated

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

Actionable comments posted: 2

🤖 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 `@velero-plugins/rolebindings/k8s_restore.go`:
- Around line 28-29: The code ignores errors from json.Marshal and
json.Unmarshal when converting input.Item into roleBinding, which can leave
roleBinding zero-valued and cause incorrect logic or panics; update the block
around json.Marshal and json.Unmarshal (referencing input.Item and roleBinding)
to check both error returns, handle them appropriately (e.g., log the error via
the existing logger or return/continue with an error), and avoid proceeding with
a malformed roleBinding—ensure you propagate or handle the error path instead of
discarding it.
- Around line 24-41: The Execute method in K8sRestorePlugin currently ignores
input.Restore.Spec.NamespaceMapping and simply returns the RoleBinding unchanged
(besides skipping SystemRoleBindings), which can leave subject namespaces stale;
update K8sRestorePlugin.Execute to detect input.Restore.Spec.NamespaceMapping,
iterate over the deserialized rbacv1.RoleBinding.Subjects and rewrite any
Subject.Namespace (and serviceaccount-style Subject.Name portions like
"system:serviceaccount:<ns>:<name>" if present) using the mapping, then marshal
the modified roleBinding back into the output item returned by
velero.NewRestoreItemActionExecuteOutput; keep the existing SystemRoleBindings
name check but do not skip non-system rolebindings based solely on name.
🪄 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: 7163bba9-446d-4553-9672-5140175f2946

📥 Commits

Reviewing files that changed from the base of the PR and between 3918c36 and 999496b.

📒 Files selected for processing (7)
  • Makefile
  • README.md
  • velero-plugins/main.go
  • velero-plugins/rolebindings/k8s_restore.go
  • velero-plugins/rolebindings/k8s_restore_test.go
  • velero-plugins/rolebindings/ocp_restore.go
  • velero-plugins/rolebindings/ocp_restore_test.go
✅ Files skipped from review due to trivial changes (1)
  • README.md

Comment on lines +24 to +41
func (p *K8sRestorePlugin) Execute(input *velero.RestoreItemActionExecuteInput) (*velero.RestoreItemActionExecuteOutput, error) {
p.Log.Info("[rbac-rolebinding-restore] Entering RBAC Role Bindings restore plugin")

roleBinding := rbacv1.RoleBinding{}
itemMarshal, _ := json.Marshal(input.Item)
json.Unmarshal(itemMarshal, &roleBinding)

p.Log.Infof("[rbac-rolebinding-restore] role binding - %s, API version %s", roleBinding.Name, roleBinding.APIVersion)

if SystemRoleBindings[roleBinding.Name] {
p.Log.Infof("[rbac-rolebinding-restore] Skipping system rolebinding %s as it will be automatically created", roleBinding.Name)
return &velero.RestoreItemActionExecuteOutput{
SkipRestore: true,
}, nil
}

return velero.NewRestoreItemActionExecuteOutput(input.Item), nil
}

@coderabbitai coderabbitai Bot Jun 8, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check for namespace mapping patterns in rolebinding restore plugins

echo "=== Checking if authorization.openshift.io rolebindings are also backed up as rbac.authorization.k8s.io ==="
rg -n -C3 'authorization\.openshift\.io' velero-plugins/rolebindings/

echo -e "\n=== Checking NamespaceMapping usage in restore plugins ==="
rg -n 'NamespaceMapping' velero-plugins/ --type go -A3 -B3

echo -e "\n=== Checking AppliesTo resource selectors for rolebindings ==="
ast-grep --pattern $'func ($) AppliesTo() $_ {
  $$$
  IncludedResources: $$$
  $$$
}'

Repository: openshift/openshift-velero-plugin

Length of output: 15391


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== rolebindings directory ==="
ls -la velero-plugins/rolebindings

echo -e "\n=== AppliesTo implementations in rolebindings plugins ==="
rg -n "func \\(p \\*.*\\) AppliesTo\\(" velero-plugins/rolebindings/*.go
rg -n "IncludedResources" velero-plugins/rolebindings/*.go

echo -e "\n=== NamespaceMapping usage in rolebindings plugins ==="
rg -n "NamespaceMapping" velero-plugins/rolebindings/*.go

echo -e "\n=== k8s_restore.go Execute() details around unmarshalling/skip logic ==="
sed -n '1,120p' velero-plugins/rolebindings/k8s_restore.go

echo -e "\n=== ocp_restore.go Execute() details around namespace mapping ==="
sed -n '1,160p' velero-plugins/rolebindings/ocp_restore.go

echo -e "\n=== k8s_restore_test.go (look for NamespaceMapping / subject mapping behavior) ==="
sed -n '1,220p' velero-plugins/rolebindings/k8s_restore_test.go

Repository: openshift/openshift-velero-plugin

Length of output: 10563


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== clusterrolebindings/restore.go (namespace mapping logic) ==="
sed -n '1,220p' velero-plugins/clusterrolebindings/restore.go

Repository: openshift/openshift-velero-plugin

Length of output: 2255


Add NamespaceMapping handling for Kubernetes rolebindings restore

  • velero-plugins/rolebindings/k8s_restore.go ignores input.Restore.Spec.NamespaceMapping and restores custom rbacv1.RoleBinding unchanged (only skips SystemRoleBindings by name), so subject namespace references can remain stale.
  • velero-plugins/rolebindings/ocp_restore.go and velero-plugins/clusterrolebindings/restore.go both apply NamespaceMapping by rewriting subject/identity namespace fields; k8s_restore.go should implement the equivalent namespace swapping for rbacv1.RoleBinding.Subjects (and any subject.Name serviceaccount-group namespace portions) when NamespaceMapping is set.
  • Skipping custom K8s rolebindings isn’t necessary: k8s_restore.go targets rolebindings, while ocp_restore.go targets rolebinding.authorization.openshift.io (different resource selectors).
🤖 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 `@velero-plugins/rolebindings/k8s_restore.go` around lines 24 - 41, The Execute
method in K8sRestorePlugin currently ignores input.Restore.Spec.NamespaceMapping
and simply returns the RoleBinding unchanged (besides skipping
SystemRoleBindings), which can leave subject namespaces stale; update
K8sRestorePlugin.Execute to detect input.Restore.Spec.NamespaceMapping, iterate
over the deserialized rbacv1.RoleBinding.Subjects and rewrite any
Subject.Namespace (and serviceaccount-style Subject.Name portions like
"system:serviceaccount:<ns>:<name>" if present) using the mapping, then marshal
the modified roleBinding back into the output item returned by
velero.NewRestoreItemActionExecuteOutput; keep the existing SystemRoleBindings
name check but do not skip non-system rolebindings based solely on name.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Not needed — Velero's built-in RoleBindingAction already handles Subject.Namespace remapping for k8s RBAC rolebindings. Multiple RestoreItemActions chain — our plugin runs first (skip system ones), then Velero's built-in runs on non-system ones and handles namespace mapping.

For system rolebindings, we skip them entirely (SkipRestore: true) so OpenShift creates fresh ones with correct subjects — no namespace remapping needed.

The embedded namespace in Subject.Name (e.g. system:serviceaccounts:<ns>) is an OpenShift-specific pattern that only appears in the system rolebindings we're skipping. Custom k8s RBAC rolebindings use Subject.Namespace field which Velero's built-in handles.

Note

Responses generated with Claude

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@kaovilai, thanks for the detailed explanation — that makes sense. Velero's built-in RoleBindingAction chaining after this plugin, handling Subject.Namespace remapping for non-system rolebindings, fully covers the namespace mapping concern. And since system rolebindings are skipped entirely, there's nothing to remap for them. I'll withdraw the comment.


✏️ Learnings added
Learnt from: kaovilai
Repo: openshift/openshift-velero-plugin PR: 402
File: velero-plugins/rolebindings/k8s_restore.go:24-46
Timestamp: 2026-06-08T16:56:41.949Z
Learning: In `openshift/openshift-velero-plugin`, the `K8sRestorePlugin` in `velero-plugins/rolebindings/k8s_restore.go` does NOT need to handle `NamespaceMapping` / `Subject.Namespace` remapping for k8s RBAC rolebindings (`rbac.authorization.k8s.io/v1/RoleBinding`). Velero's built-in `RoleBindingAction` (at `pkg/restore/actions/rolebinding_action.go`) already handles `Subject.Namespace` remapping. Multiple RestoreItemActions chain: the OpenShift plugin runs first and skips system rolebindings (`system:image-pullers`, `system:image-builders`, `system:deployers`) with `SkipRestore: true`, then Velero's built-in action runs on the remaining non-system ones and applies namespace mapping. System rolebindings are skipped entirely so namespace remapping is irrelevant for them. The `system:serviceaccounts:<ns>` embedded namespace pattern in `Subject.Name` is OpenShift-specific and only appears in the system rolebindings that are being skipped.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Comment thread velero-plugins/rolebindings/k8s_restore.go Outdated
@kaovilai

kaovilai commented Jun 8, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com>
@kaovilai

kaovilai commented Jun 8, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@openshift-ci

openshift-ci Bot commented Jun 8, 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-ci

openshift-ci Bot commented Jun 8, 2026

Copy link
Copy Markdown

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

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

Actionable comments posted: 1

🤖 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 `@Makefile`:
- Line 19: The build recipe producing _output/$(BIN) currently ignores ARCH
because docker run uses BUILD_IMAGE without specifying platform or Go envs;
update the Makefile build recipe so it passes the intended architecture into the
container: add --platform=linux/$(ARCH) to the docker run invocation (or set
GOOS/GOARCH env vars inside the container) and export GOARCH from ARCH (e.g.,
set GOARCH=$(ARCH) via -e GOARCH=$(ARCH)) so go build inside the container
honors the requested architecture; ensure this change is applied to the rule
that references BUILD_IMAGE and creates _output/$(BIN).
🪄 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: a877713b-1bcb-436d-a44c-99abb04be286

📥 Commits

Reviewing files that changed from the base of the PR and between fe9b727 and b3793d7.

📒 Files selected for processing (7)
  • Makefile
  • README.md
  • velero-plugins/main.go
  • velero-plugins/rolebindings/k8s_restore.go
  • velero-plugins/rolebindings/k8s_restore_test.go
  • velero-plugins/rolebindings/ocp_restore.go
  • velero-plugins/rolebindings/ocp_restore_test.go

Comment thread Makefile
REPO ?= github.com/konveyor/openshift-velero-plugin

BUILD_IMAGE ?= openshift/origin-release:golang-1.14
BUILD_IMAGE ?= golang:1.25

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

Does the official golang:1.25Docker image publish multi-architecture manifests, and whenGOOS/GOARCHare unset doesgo build default to the container's OS/architecture?

💡 Result:

The official golang:1.25 Docker image publishes multi-architecture manifests [1][2]. These manifests allow the Docker engine to automatically pull the appropriate image for the host's architecture (such as amd64, arm64v8, or others) [1][3]. When GOOS and GOARCH are unset, the go build command defaults to the OS and architecture of the environment where the command is executed [4][5]. In the context of a running Docker container, this corresponds to the OS and architecture of that container [3][5]. The Go toolchain determines these default values based on its own build configuration and the system's runtime environment [4][6][7].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail
ls -la
if [ ! -f Makefile ]; then echo "Makefile not found"; exit 1; fi
nl -ba Makefile | sed -n '1,120p'

Repository: openshift/openshift-velero-plugin

Length of output: 1062


🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "=== Makefile: lines 1-120 with numbers (awk) ==="
awk '{printf "%d:%s\n", NR, $0}' Makefile | sed -n '1,120p'

echo "=== Makefile: relevant vars and recipe parts ==="
rg -n "BUILD_IMAGE|ARCH\s*\?=|DOCKER_BUILD_ARGS|docker run|go build" Makefile || true

Repository: openshift/openshift-velero-plugin

Length of output: 3840


🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n "_output/\$\(\s*BIN\s*\)|_output/" -S . || true
rg -n "ARCH\s*\?=|DOCKER_BUILD_ARGS|CLUSTER_OS|CLUSTER_ARCH|BUILD_IMAGE" -S Makefile Dockerfile velero-plugins -g'!*/vendor/*' || true

Repository: openshift/openshift-velero-plugin

Length of output: 1302


🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "=== Dockerfile ==="
nl -ba Dockerfile | sed -n '1,120p'
echo "=== konflux.Dockerfile ==="
nl -ba konflux.Dockerfile | sed -n '1,120p'

Repository: openshift/openshift-velero-plugin

Length of output: 157


🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "=== Dockerfile: numbered head ==="
awk '{printf "%d:%s\n", NR, $0}' Dockerfile | sed -n '1,140p'

echo "=== konflux.Dockerfile: numbered head ==="
awk '{printf "%d:%s\n", NR, $0}' konflux.Dockerfile | sed -n '1,220p'

Repository: openshift/openshift-velero-plugin

Length of output: 3171


🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n "make (build|docker|container)|_output/\$\(BIN\)|_output/velero-plugins|_output/" . -g'!.git/*' -S

Repository: openshift/openshift-velero-plugin

Length of output: 825


🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n "\bARCH\b|_output/\$\(\s*BIN\s*\)" . -S -g'!vendor/*' -g'!**/node_modules/*'

Repository: openshift/openshift-velero-plugin

Length of output: 105


🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "=== Makefile (full) ==="
cat Makefile

echo "=== README: lines around make build/container ==="
rg -n "\$ make (build|container)|make build|make container" README.md
sed -n '1,120p' README.md
sed -n '50,120p' README.md
sed -n '120,220p' README.md

Repository: openshift/openshift-velero-plugin

Length of output: 20451


Make make build honor $(ARCH) when using golang:1.25

golang:1.25 is multi-arch, and the docker run used for _output/$(BIN) doesn’t set --platform, GOOS, or GOARCH, so go build defaults to the container/host architecture; meanwhile ARCH ?= amd64 is unused in that recipe. This can produce _output/$(BIN) for an architecture different from what you intend.

Suggested fix
 BUILD_IMAGE ?= golang:1.25
@@
 	docker run \
+				 --platform=linux/$(ARCH) \
 				 --rm \
 				 -v $$(pwd):/workspace:z \
 				 -v $$(pwd)/.go/.cache:/go/.cache:z \
 				 -w /workspace \
+				 -e GOOS=linux \
+				 -e GOARCH=$(ARCH) \
 				 -e GOCACHE=/go/.cache \
 				 -e GOFLAGS="-mod=mod -buildvcs=false" \
 				 $(BUILD_IMAGE) \
 				 go build -tags $(BUILDTAGS) -v -o _output/$(BIN) ./$(BIN)
🤖 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 `@Makefile` at line 19, The build recipe producing _output/$(BIN) currently
ignores ARCH because docker run uses BUILD_IMAGE without specifying platform or
Go envs; update the Makefile build recipe so it passes the intended architecture
into the container: add --platform=linux/$(ARCH) to the docker run invocation
(or set GOOS/GOARCH env vars inside the container) and export GOARCH from ARCH
(e.g., set GOARCH=$(ARCH) via -e GOARCH=$(ARCH)) so go build inside the
container honors the requested architecture; ensure this change is applied to
the rule that references BUILD_IMAGE and creates _output/$(BIN).

@sseago

sseago commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

/lgtm

@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label Jun 8, 2026
@openshift-merge-bot openshift-merge-bot Bot merged commit 9b14f61 into openshift:oadp-dev Jun 8, 2026
4 checks passed
@openshift-cherrypick-robot

Copy link
Copy Markdown
Contributor

@kaovilai: new pull request created: #403

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.

@openshift-cherrypick-robot

Copy link
Copy Markdown
Contributor

@kaovilai: #402 failed to apply on top of branch "oadp-1.5":

Applying: OADP-6540: Skip restore of k8s RBAC system rolebindings
Using index info to reconstruct a base tree...
M	Makefile
M	README.md
M	velero-plugins/main.go
Falling back to patching base and 3-way merge...
Auto-merging velero-plugins/main.go
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Auto-merging Makefile
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
hint: When you have resolved this problem, run "git am --continue".
hint: If you prefer to skip this patch, run "git am --skip" instead.
hint: To restore the original branch and stop patching, run "git am --abort".
hint: Disable this message with "git config set advice.mergeConflict false"
Patch failed at 0001 OADP-6540: Skip restore of k8s RBAC system rolebindings

Details

In response to this:

/cherry-pick oadp-1.5

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.

@openshift-cherrypick-robot

Copy link
Copy Markdown
Contributor

@kaovilai: #402 failed to apply on top of branch "oadp-1.4":

Applying: OADP-6540: Skip restore of k8s RBAC system rolebindings
Using index info to reconstruct a base tree...
M	Makefile
M	README.md
M	velero-plugins/main.go
Falling back to patching base and 3-way merge...
Auto-merging velero-plugins/main.go
CONFLICT (content): Merge conflict in velero-plugins/main.go
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Auto-merging Makefile
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
hint: When you have resolved this problem, run "git am --continue".
hint: If you prefer to skip this patch, run "git am --skip" instead.
hint: To restore the original branch and stop patching, run "git am --abort".
hint: Disable this message with "git config set advice.mergeConflict false"
Patch failed at 0001 OADP-6540: Skip restore of k8s RBAC system rolebindings

Details

In response to this:

/cherry-pick oadp-1.4

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 Jun 8, 2026

Copy link
Copy Markdown
Member Author

Verification

Tested with OADP 1.6.0 downstream build on OCP 5.0 (arm64):

  • FBC: quay.io/redhat-user-workloads/ocp-art-tenant/art-fbc:v5.0__operator_nvr__oadp-operator-container-1.6.0-202606041057.p2.g747216b.assembly.stream.el9
  • Plugin override: quay.io/tkaovila/openshift-velero-plugin:[OADP-6540](https://redhat.atlassian.net/browse/OADP-6540) via DPA unsupportedOverrides.openshiftPluginImageFqin

Backup of test-rb-source namespace, restore with namespace mapping to test-rb-target:

Both API groups now skip system rolebindings:

rbac.authorization.k8s.io:
  system:deployers → Skipping system rolebinding system:deployers as it will be automatically created
  system:image-builders → Skipping system rolebinding system:image-builders as it will be automatically created
  system:image-pullers → Skipping system rolebinding system:image-pullers as it will be automatically created

authorization.openshift.io:
  system:deployers → Skipping (existing ocp_restore.go)
  system:image-builders → Skipping (existing ocp_restore.go)
  system:image-pullers → Skipping (existing ocp_restore.go)

Subjects in target namespace point to correct namespace:

[{"apiGroup":"rbac.authorization.k8s.io","kind":"Group","name":"system:serviceaccounts:test-rb-target"}]

Note

Responses generated with Claude

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. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. lgtm Indicates that a PR is ready to be merged.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants