Skip to content

OADP-7660: Document NonAdminBSL requires long-term credentials#334

Open
kaovilai wants to merge 1 commit intomigtools:oadp-devfrom
kaovilai:OADP-7660-nonadminbsl-credential-requirements
Open

OADP-7660: Document NonAdminBSL requires long-term credentials#334
kaovilai wants to merge 1 commit intomigtools:oadp-devfrom
kaovilai:OADP-7660-nonadminbsl-credential-requirements

Conversation

@kaovilai
Copy link
Copy Markdown
Member

@kaovilai kaovilai commented Mar 28, 2026

Summary

  • Documents that NonAdminBSL must use long-term cloud credentials (access keys, service account JSON, client secrets) stored in the non-admin user's namespace
  • Explains why short-lived credentials (AWS STS, GCP WIF, Azure WI) are not supported for NonAdminBSL:
    • Projected SA token belongs to the admin Velero identity, not a per-user identity
    • No per-namespace cloud identity scoping — all users would share the same cloud permissions
    • Credential files are copied verbatim without format validation
    • Azure WI is broken for per-BSL use (vmware-tanzu/velero#9657)
  • Includes required credential Secret formats for AWS, GCP, and Azure
  • Provides security recommendations for administrators managing non-admin credentials

Related

Note

Responses generated with Claude

Generated with Claude Code
via Happy

Summary by CodeRabbit

Release Notes

  • Documentation
    • Added documentation on NonAdminBackupStorageLocation credential requirements, detailing supported long-term credential formats for AWS, GCP, and Azure, explaining why short-lived mechanisms are unsupported, and providing security best practices for credential management.

Document that NonAdminBSL must use long-term cloud credentials stored
in the non-admin user's namespace. Explain why short-lived credentials
(AWS STS, GCP WIF, Azure WI) are not supported: the projected SA token
belongs to the admin Velero identity, there is no per-namespace cloud
identity scoping, and credential files are copied without format
validation.

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-ci
Copy link
Copy Markdown

openshift-ci bot commented Mar 28, 2026

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@openshift-ci-robot
Copy link
Copy Markdown
Collaborator

openshift-ci-robot commented Mar 28, 2026

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

Details

In response to this:

Summary

  • Documents that NonAdminBSL must use long-term cloud credentials (access keys, service account JSON, client secrets) stored in the non-admin user's namespace
  • Explains why short-lived credentials (AWS STS, GCP WIF, Azure WI) are not supported for NonAdminBSL:
  • Projected SA token belongs to the admin Velero identity, not a per-user identity
  • No per-namespace cloud identity scoping — all users would share the same cloud permissions
  • Credential files are copied verbatim without format validation
  • Azure WI is broken for per-BSL use (vmware-tanzu/velero#9657)
  • Includes required credential Secret formats for AWS, GCP, and Azure
  • Provides security recommendations for administrators managing non-admin credentials

Related

[!Note]
Responses generated with Claude

Generated with Claude Code
via Happy

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.

@openshift-ci
Copy link
Copy Markdown

openshift-ci bot commented Mar 28, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: kaovilai

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:

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

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 28, 2026

📝 Walkthrough

Walkthrough

A new documentation page is added that specifies credential requirements for NonAdminBackupStorageLocation (NonAdminBSL), explaining why short-lived credential mechanisms are unsupported, detailing the credential flow, required formats for AWS/GCP/Azure, and providing security recommendations.

Changes

Cohort / File(s) Summary
NonAdminBSL Credential Requirements Documentation
docs/nonadminbsl_credential_requirements.md
New documentation page detailing that NonAdminBSL requires long-term cloud credentials via Secrets, explains why short-lived mechanisms (AWS STS, GCP Workload Identity Federation, Azure Workload Identity) are unsupported, describes credential flow and format requirements for AWS/GCP/Azure, provides example manifest, and includes security recommendations.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~5 minutes

Poem

🐰 A tale of credentials, oh so clear,
Long-lived secrets must appear,
Short-lived tokens need not apply,
NonAdminBSL explains the why!
✨ Documentation hops along with care,
Securing backups everywhere!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The linked issue #9657 is about implementing per-BSL Azure Workload Identity code changes, but this PR only adds documentation stating long-term credentials are currently required. The PR does not implement the code changes needed to resolve the linked issue. Either implement the code changes specified in #9657 (modifying Azure credential handling to support per-BSL Workload Identity), or clarify the relationship between the documentation and the linked issue requirements.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title directly and accurately summarizes the main change—documenting that NonAdminBSL requires long-term credentials, which is exactly what the new documentation file specifies.
Description check ✅ Passed The PR description covers the 'Why the changes were made' section with clear explanation of the documentation purpose and related issues, but is missing the 'How to test the changes' section from the repository template.
Out of Scope Changes check ✅ Passed The PR adds only documentation about credential requirements and does not include any code changes outside the scope of documenting current NonAdminBSL constraints and long-term credential formats.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

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

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@oadp-snyk
Copy link
Copy Markdown

oadp-snyk commented Mar 28, 2026

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@kaovilai kaovilai marked this pull request as ready for review March 28, 2026 06:46
Copilot AI review requested due to automatic review settings March 28, 2026 06:46
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds explicit documentation clarifying that NonAdminBackupStorageLocation (NonAdminBSL) currently requires long-term, per-namespace cloud credentials and that short-lived identity mechanisms are unsupported due to how NAC syncs credentials into Velero.

Changes:

  • Introduces a new doc describing current NonAdminBSL credential flow (Secret sync + Velero credential file usage).
  • Documents why AWS STS / GCP WIF / Azure Workload Identity are not supported for NonAdminBSL today.
  • Provides example Secret formats for AWS/GCP/Azure and admin security recommendations.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

### NonAdminBSL referencing the Secret

```yaml
apiVersion: nac.oadp.openshift.io/v1alpha1
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

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

The apiVersion in the NonAdminBackupStorageLocation example is incorrect for this repo. CRDs and samples use the oadp.openshift.io/v1alpha1 API group (not nac.oadp.openshift.io/v1alpha1), so the manifest as written won’t apply.

Suggested change
apiVersion: nac.oadp.openshift.io/v1alpha1
apiVersion: oadp.openshift.io/v1alpha1

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +10
# NonAdminBSL Credential Requirements: Long-Term Credentials Only

_Jira: [OADP-7660](https://redhat.atlassian.net/browse/OADP-7660)_

## Overview

NonAdminBackupStorageLocation (NonAdminBSL) requires non-admin users to provide long-term cloud credentials (access keys, service account JSON keys, client secrets) stored in a Secret in their own namespace.
Short-lived, cloud-native credential mechanisms (AWS STS, GCP Workload Identity Federation, Azure Workload Identity) are **not supported** for NonAdminBSL and **must not be used**.

## How NonAdminBSL Credentials Work Today
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

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

This doc consistently uses the acronym “NonAdminBSL”, but the rest of the repo’s docs and user-facing naming tends to use “NABSL” (matching the CRD shortName nabsl). Consider standardizing on “NABSL”, or explicitly stating both (e.g., “Non-Admin BackupStorageLocation (NABSL, also referred to as NonAdminBSL in code)”) to avoid confusing readers.

Copilot uses AI. Check for mistakes.
_Jira: [OADP-7660](https://redhat.atlassian.net/browse/OADP-7660)_

## Overview

Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

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

This new doc doesn’t appear to be linked from README.md or other docs pages, so it’s easy to miss. Consider adding a cross-link from an existing entry point (e.g., README “Using NAC” / NABSL section or docs/non_admin_user.md) so users can discover these credential constraints.

Suggested change
For general non-admin usage and workflow, see the [Non-admin user guide](./non_admin_user.md). This page focuses specifically on credential constraints for NonAdminBSL.

Copilot uses AI. Check for mistakes.
@openshift-ci-robot
Copy link
Copy Markdown
Collaborator

openshift-ci-robot commented Mar 28, 2026

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

Details

In response to this:

Summary

  • Documents that NonAdminBSL must use long-term cloud credentials (access keys, service account JSON, client secrets) stored in the non-admin user's namespace
  • Explains why short-lived credentials (AWS STS, GCP WIF, Azure WI) are not supported for NonAdminBSL:
  • Projected SA token belongs to the admin Velero identity, not a per-user identity
  • No per-namespace cloud identity scoping — all users would share the same cloud permissions
  • Credential files are copied verbatim without format validation
  • Azure WI is broken for per-BSL use (vmware-tanzu/velero#9657)
  • Includes required credential Secret formats for AWS, GCP, and Azure
  • Provides security recommendations for administrators managing non-admin credentials

Related

[!Note]
Responses generated with Claude

Generated with Claude Code
via Happy

Summary by CodeRabbit

Release Notes

  • Documentation
  • Added documentation on NonAdminBackupStorageLocation credential requirements, detailing supported long-term credential formats for AWS, GCP, and Azure, explaining why short-lived mechanisms are unsupported, and providing security best practices for credential management.

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.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
docs/nonadminbsl_credential_requirements.md (1)

84-103: Consider noting that the GCP example shows core fields only.

The GCP service account JSON example includes the essential fields but omits some optional fields commonly present in full service account key files (e.g., auth_provider_x509_cert_url, client_x509_cert_url). While the example is sufficient for demonstration purposes, you might consider adding a note that actual GCP service account JSON files may contain additional fields.

📝 Optional clarification

Add a note after line 103:

       "token_uri": "https://oauth2.googleapis.com/token"
     }
+
+_Note: Actual GCP service account JSON files may include additional fields such as `auth_provider_x509_cert_url` and `client_x509_cert_url`._
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/nonadminbsl_credential_requirements.md` around lines 84 - 103, The GCP
service account JSON example under the YAML block (the stringData: cloud secret
example) shows only core fields; add a brief note immediately after that snippet
stating this is a minimal example and actual GCP service account key JSON files
often include additional fields (e.g., auth_provider_x509_cert_url,
client_x509_cert_url and other metadata) and that those extra fields are
acceptable when using the secret.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/nonadminbsl_credential_requirements.md`:
- Around line 10-15: Update the GitHub permalink range in
docs/nonadminbsl_credential_requirements.md for the NonAdminBSL controller
reference: replace the existing `#L736-L841` range with `#L736-L849` so the link
covers the full syncSecrets function in the NonAdminBSL controller (syncSecrets)
reference; leave the Velero FileStore.Path() reference unchanged.

---

Nitpick comments:
In `@docs/nonadminbsl_credential_requirements.md`:
- Around line 84-103: The GCP service account JSON example under the YAML block
(the stringData: cloud secret example) shows only core fields; add a brief note
immediately after that snippet stating this is a minimal example and actual GCP
service account key JSON files often include additional fields (e.g.,
auth_provider_x509_cert_url, client_x509_cert_url and other metadata) and that
those extra fields are acceptable when using the secret.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: bd3c6e79-ec05-4518-9f5f-f3eb7efb72ee

📥 Commits

Reviewing files that changed from the base of the PR and between 31a3bfc and 578e4e2.

📒 Files selected for processing (1)
  • docs/nonadminbsl_credential_requirements.md

Comment on lines +10 to +15
## How NonAdminBSL Credentials Work Today

The non-admin user creates a Secret in their namespace containing cloud credentials.
The [NonAdminBSL controller](https://github.com/migtools/oadp-non-admin/blob/31a3bfc20310898fae5a438005d0d242240d0fbb/internal/controller/nonadminbackupstoragelocation_controller.go#L736-L841) copies this Secret into the OADP namespace and references the copy in the Velero BSL's `spec.credential` field.
Velero's [`FileStore.Path()`](https://github.com/vmware-tanzu/velero/blob/6e91e72e655568dd6944ca7bb3cf00b6c7fbb3c8/internal/credentials/file_store.go#L66-L88) writes the secret data to a temporary file on disk and passes the file path to the cloud plugin via `config["credentialsFile"]`.

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

🏁 Script executed:

#!/bin/bash
# Description: Verify GitHub permalink URLs return 200 and check if line ranges are valid

echo "Checking GitHub URL accessibility..."

# Check NonAdminBSL controller syncSecrets reference
url1="https://github.com/migtools/oadp-non-admin/blob/31a3bfc20310898fae5a438005d0d242240d0fbb/internal/controller/nonadminbackupstoragelocation_controller.go#L736-L841"
echo "URL 1: $url1"
curl -s -o /dev/null -w "HTTP Status: %{http_code}\n" -L "$url1"

# Check Velero FileStore.Path() reference  
url2="https://github.com/vmware-tanzu/velero/blob/6e91e72e655568dd6944ca7bb3cf00b6c7fbb3c8/internal/credentials/file_store.go#L66-L88"
echo "URL 2: $url2"
curl -s -o /dev/null -w "HTTP Status: %{http_code}\n" -L "$url2"

# Check Azure credential reference
url3="https://github.com/vmware-tanzu/velero/blob/6e91e72e655568dd6944ca7bb3cf00b6c7fbb3c8/pkg/util/azure/credential.go#L48-L54"
echo "URL 3: $url3"
curl -s -o /dev/null -w "HTTP Status: %{http_code}\n" -L "$url3"

Repository: migtools/oadp-non-admin

Length of output: 588


🏁 Script executed:

#!/bin/bash
# Verify line ranges are correct by fetching raw file content

echo "=== Checking NonAdminBSL controller.go ==="
raw_url1="https://raw.githubusercontent.com/migtools/oadp-non-admin/31a3bfc20310898fae5a438005d0d242240d0fbb/internal/controller/nonadminbackupstoragelocation_controller.go"
curl -s "$raw_url1" | sed -n '735,850p' | head -20

echo ""
echo "=== Checking Velero FileStore.Path() ==="
raw_url2="https://raw.githubusercontent.com/vmware-tanzu/velero/6e91e72e655568dd6944ca7bb3cf00b6c7fbb3c8/internal/credentials/file_store.go"
curl -s "$raw_url2" | sed -n '60,95p'

echo ""
echo "=== Line count check for controller.go ==="
curl -s "$raw_url1" | wc -l

echo ""
echo "=== Checking context around line 736-841 in controller.go ==="
curl -s "$raw_url1" | sed -n '735p;736p;737p;840p;841p;842p'

Repository: migtools/oadp-non-admin

Length of output: 2711


🏁 Script executed:

#!/bin/bash
# Find the actual end of syncSecrets function

raw_url="https://raw.githubusercontent.com/migtools/oadp-non-admin/31a3bfc20310898fae5a438005d0d242240d0fbb/internal/controller/nonadminbackupstoragelocation_controller.go"

# Get the file and find where syncSecrets starts
echo "=== Finding syncSecrets function boundaries ==="
curl -s "$raw_url" | awk '
/^func \(r \*NonAdminBackupStorageLocationReconciler\) syncSecrets/ {
    start = NR
    depth = 0
}
start && NR >= start {
    for (i = 1; i <= length($0); i++) {
        c = substr($0, i, 1)
        if (c == "{") depth++
        if (c == "}") depth--
    }
    if (depth == 0 && NR > start) {
        print "Function starts at line: " start
        print "Function ends at line: " NR
        exit
    }
}
'

echo ""
echo "=== Lines around 841 ==="
curl -s "$raw_url" | sed -n '838,845p' | cat -n

echo ""
echo "=== Lines around 850 ==="
curl -s "$raw_url" | sed -n '847,856p' | cat -n

Repository: migtools/oadp-non-admin

Length of output: 1041


Correct the GitHub line range for the NonAdminBSL controller reference.

The syncSecrets function in the NonAdminBSL controller actually extends to line 849, not line 841. Update the GitHub permalink from #L736-L841 to #L736-L849 to capture the complete function. The Velero FileStore.Path() reference is accurate.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/nonadminbsl_credential_requirements.md` around lines 10 - 15, Update the
GitHub permalink range in docs/nonadminbsl_credential_requirements.md for the
NonAdminBSL controller reference: replace the existing `#L736-L841` range with
`#L736-L849` so the link covers the full syncSecrets function in the NonAdminBSL
controller (syncSecrets) reference; leave the Velero FileStore.Path() reference
unchanged.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Azure: Enable per-BSL Workload Identity credentials by reading from creds map

4 participants