Skip to content

OSAC-496: Remove subnet/tenant fallback dead code#704

Closed
tchughesiv wants to merge 6 commits into
osac-project:mainfrom
tchughesiv:OSAC-496-remove-fallback-dead-code
Closed

OSAC-496: Remove subnet/tenant fallback dead code#704
tchughesiv wants to merge 6 commits into
osac-project:mainfrom
tchughesiv:OSAC-496-remove-fallback-dead-code

Conversation

@tchughesiv

@tchughesiv tchughesiv commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

OSAC-496: Remove subnet/tenant fallback dead code (fulfillment-service)

Jira: https://redhat.atlassian.net/browse/OSAC-496
Follow-up (CLI/AAP tenancy design): https://redhat.atlassian.net/browse/OSAC-1546

Related PRs

Repo PR Role
osac-operator osac-project/osac-operator#297 Remove subnet/tenant namespace fallback in ComputeInstance controller
osac-aap osac-project/osac-aap#349 Set explicit metadata.tenant=shared in publish_templates (required for e2e-vmaas)

Note: This PR removes the server-side default of "shared" for universal-access callers. Admin/bootstrap clients (hub CLI, AAP publish_templates) must send an explicit tenant on the request — the server no longer infers it. See OSAC-1546 for the broader CLI tenancy model discussion.

osac-installer: no manual submodule bump needed — automated job picks up osac-aap after merge.

Review status

Core team review requested — tenancy logic affects all objects, not just subnets. Please do not merge until approved (review).

Summary

Removes dead tenancy fallback code after subnet became mandatory on ComputeInstance creation. Universal-access subjects no longer default to the "shared" tenant when no tenant is specified — they must provide an explicit tenant on the request. The SharedTenants set variable is removed; visibility logic uses collections.NewSet(SharedTenant) inline.

Also fixes determineAssignedTenant() to resolve an explicit request tenant before calling DetermineDefaultTenant(), so admin creates with an explicit tenant are not rejected solely because the subject has universal access.

Changes

  • DetermineDefaultTenant() returns error when assignable tenants are universal
  • Removed SharedTenants variable from tenancy_logic.go
  • Defer default-tenant lookup in generic_server.go until request/current object omit tenant
  • Map auth.ErrExplicitTenantRequired to PermissionDenied in determineAssignedTenant()
  • osac create hub: hardcode hub metadata tenant to shared (client-side explicit tenant for admin bootstrap)
  • Integration test setup: explicit shared tenant on admin creates (it_metadata.go, hub registration via sharedMetadata())
  • Updated auth and tenancy unit tests

Testing

  • Unit tests: ginkgo run -r internal — pass
  • Integration tests: ginkgo run it — pass
  • Lint: buf lint, golangci-lint, uv run dev.py lint — pass
  • e2e-vmaas: requires osac-aap PR 349 merged (publish_templates explicit tenant); osac-installer submodule updated by automation

Acceptance Criteria

  • SharedTenants variable removed from fulfillment-service
  • Infinite-tenant default fallback removed
  • All tests pass

Summary by CodeRabbit

  • Bug Fixes
    • Enforced explicit tenant selection for create/update when the subject has access to all tenants; requests that omit a tenant now fail with a permission-denied error instead of defaulting.
    • Default tenant resolution no longer overrides an existing tenant already present on the request/object.
    • Tenant visibility behavior now consistently includes the shared tenant.
    • The hub create CLI command now sets shared-tenant metadata on hub creation to keep registration working under the new enforcement.
  • New Features
    • None.

@openshift-ci

openshift-ci Bot commented Jun 15, 2026

Copy link
Copy Markdown

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

openshift-ci-robot commented Jun 15, 2026

Copy link
Copy Markdown

@tchughesiv: This pull request references OSAC-496 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the task to target the "5.0.0" version, but no target version was set.

Details

In response to this:

OSAC-496: Remove subnet/tenant fallback dead code (fulfillment-service)

Jira: https://redhat.atlassian.net/browse/OSAC-496
Companion PR: osac-operator (same Jira)

Summary

Removes dead tenancy fallback code after subnet became mandatory on ComputeInstance creation. Universal-access subjects no longer default to the "shared" tenant — they must specify an explicit tenant. The SharedTenants set variable is removed; visibility logic uses collections.NewSet(SharedTenant) inline.

Changes

  • DetermineDefaultTenant() returns error when assignable tenants are universal
  • Removed SharedTenants variable from tenancy_logic.go
  • Updated auth unit tests

Testing

  • Unit tests: ginkgo run -r internal — all pass
  • Integration tests: Not run (auth-only changes; no API surface change). Operator envtest covers reconcile paths in companion PR.
  • Lint: buf lint, uv run dev.py lint — pass

Acceptance Criteria

  • SharedTenants variable removed from fulfillment-service
  • Infinite-tenant default fallback removed
  • All tests pass (unit)

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 15, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

SharedTenants set variable is replaced by a SharedTenant string constant. DetermineDefaultTenant now returns ErrExplicitTenantRequired instead of silently defaulting to the shared tenant when the subject's assignable set is non-finite (AllTenants). GenericServer.determineAssignedTenant is reordered to preserve the current object's tenant before falling back to default logic. All integration test fixtures are updated to carry explicit shared-tenant metadata via new sharedMetadata() helper functions. Hub CLI command sets tenant metadata explicitly.

Changes

Tenancy enforcement and shared metadata propagation

Layer / File(s) Summary
SharedTenant constant and explicit-tenant error contract
internal/auth/tenancy_logic.go
Introduces ErrExplicitTenantRequired error variable and replaces the SharedTenants set variable with SharedTenant string constant; AllTenants remains defined as the universal access set. Security impact: Establishes the error contract that will be enforced at the API boundary when subjects with unlimited tenant access attempt operations without an explicit tenant.
DefaultTenancyLogic error enforcement and visible-tenant construction
internal/auth/default_tenancy_logic.go, internal/auth/default_tenancy_logic_test.go
DetermineDefaultTenant logs an error and returns ErrExplicitTenantRequired when assignable is non-finite (AllTenants) with no explicit tenant, replacing silent fallback to SharedTenant. DetermineVisibleTenants uses collections.NewSet(SharedTenant).Union() instead of SharedTenants.Union(). Test expectations updated to assert error rejection and new visible-tenant set construction. Security impact: Critical boundary enforcement—subjects cannot automatically default to a shared tenant when they have access to all tenants.
GuestTenancyLogic visible-tenant set construction
internal/auth/guest_tenancy_logic.go, internal/auth/guest_tenancy_logic_test.go
DetermineVisibleTenants switches to collections.NewSet(SharedTenant) union operand; test assertions updated to match new construction pattern.
GenericServer tenant resolution with explicit-tenant rejection
internal/servers/generic_server.go
Removes unconditional upfront DetermineDefaultTenant call. Returns current object's existing tenant immediately when request omits a tenant (preserving existing assignments). Only calls DetermineDefaultTenant when both request and current object tenants are absent. Maps ErrExplicitTenantRequired to gRPC PermissionDenied error, enforcing the security boundary at the API layer. Security impact: Subjects with AllTenants access are rejected at the API layer when attempting to create/update resources without an explicit tenant specification.
Server tenancy behavior tests
internal/servers/servers_tenancy_test.go
Adds test asserting explicit tenant succeeds when subject has AllTenants access; adds test asserting creation fails with PermissionDenied when no explicit tenant is provided and DetermineDefaultTenant returns ErrExplicitTenantRequired.
Shared metadata helper and hub CLI tenant support
it/it_metadata.go, internal/cmd/cli/create/hub/create_hub_cmd.go, it/it_tool.go
Introduces sharedMetadata() and sharedMetadataWithName() helper functions producing privatev1.Metadata with Tenant: auth.SharedTenant. Hub create CLI command sets Metadata.Tenant to auth.SharedTenant when building the hub creation request. Hub registration in tool setup explicitly sets Metadata via the new helper.
Integration test fixture metadata propagation
it/it_*.go (15 test files)
All integration test suites now supply sharedMetadata() or sharedMetadataWithName() on HostType, ClusterTemplate, compute/network resources, role, RoleBinding, and hub create requests; role reconciler tests replace inline Metadata_builder with new helper for consistency.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • osac-project/fulfillment-service#557: Introduces the SharedTenant constant and related tenancy definitions that this PR builds upon and refactors.
  • osac-project/fulfillment-service#439: Previously changed DetermineDefaultTenant's "access to all tenants" behavior to default to shared tenant; this PR converts that default into an explicit error requiring tenant specification.
  • osac-project/fulfillment-service#543: Refactored DefaultTenancyLogic functions (DetermineDefaultTenant/DetermineVisibleTenants) that this PR's error-path and visible-set changes directly modify.

Suggested labels

approved, lgtm

Suggested reviewers

  • trewest
  • akshaynadkarni
  • jhernand

Poem

⚠️ No more silent defaults for the tenant-less all,
An explicit error now guards every access call.
SharedTenants retired—a constant stands tall.
Test fixtures in order, blast radius controlled. 🔐
The security boundary holds steady and strong.

🚥 Pre-merge checks | ✅ 10 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (10 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the primary change: removing dead tenancy fallback code following subnet mandate. However, it omits mention of the critical default-tenant error handling changes and explicit tenant requirement logic.
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.
No-Hardcoded-Secrets ✅ Passed No hardcoded secrets, API keys, tokens, passwords, or credentials found. PR only introduces legitimate tenant identifiers ("shared") and error messages.
No-Weak-Crypto ✅ Passed PR makes no changes to cryptographic code; it modifies tenant/metadata access control logic only. No weak crypto algorithms (MD5, SHA1, DES, RC4, 3DES, Blowfish), ECB mode, or insecure comparisons...
No-Injection-Vectors ✅ Passed No injection vectors found. Tenant values are safely handled via parameterized format strings, type-safe proto setters, and structured logging. SharedTenant is a hardcoded constant, never concatena...
Container-Privileges ✅ Passed This PR contains no container or Kubernetes manifests—only Go source code. The container-privileges check is not applicable to Go business logic files.
No-Sensitive-Data-In-Logs ✅ Passed PR logs user identifiers in error paths only, consistent with existing codebase patterns. No passwords, tokens, API keys, or sensitive customer data exposed. Structured logging is appropriate for d...
Ai-Attribution ✅ Passed PR description and commits show no evidence of AI tool usage. No "Assisted-by", "Generated-by", or "Co-Authored-By" trailers present in OSAC-496 changes; check only applies if AI tools were used.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ 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.

@tchughesiv tchughesiv force-pushed the OSAC-496-remove-fallback-dead-code branch from c619acb to 72f4545 Compare June 15, 2026 17:50
@tchughesiv tchughesiv marked this pull request as ready for review June 15, 2026 17:52
@openshift-ci openshift-ci Bot requested review from larsks and omer-vishlitzky June 15, 2026 17:52

@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 `@internal/servers/generic_server.go`:
- Around line 1243-1251: The error handling for DetermineDefaultTenant() in the
generic_server.go file currently returns a gRPC Internal status code for all
errors, but when the error indicates a contract violation (explicit tenant
required but omitted), it should return a permission-level or client-fixable
status code like PermissionDenied or InvalidArgument instead. Inspect the error
returned by s.tenancyLogic.DetermineDefaultTenant(ctx) and conditionally map it
to the appropriate gRPC status code using grpcstatus.Errorf: if the error
indicates a missing or invalid tenant requirement, use PermissionDenied or
InvalidArgument, otherwise fall back to Internal.
🪄 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: osac-project/coderabbit/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 0f0284bc-f406-4e8f-bc0b-69ee01c79ce3

📥 Commits

Reviewing files that changed from the base of the PR and between e0370c3 and 72f4545.

📒 Files selected for processing (23)
  • internal/auth/default_tenancy_logic.go
  • internal/auth/default_tenancy_logic_test.go
  • internal/auth/guest_tenancy_logic.go
  • internal/auth/guest_tenancy_logic_test.go
  • internal/auth/tenancy_logic.go
  • internal/servers/generic_server.go
  • internal/servers/servers_tenancy_test.go
  • it/it_annotations_test.go
  • it/it_cluster_reconciler_test.go
  • it/it_compute_subnet_test.go
  • it/it_emergency_access_test.go
  • it/it_labels_test.go
  • it/it_metadata.go
  • it/it_multitenancy_test.go
  • it/it_nodeset_removal_test.go
  • it/it_private_cluster_templates_test.go
  • it/it_private_host_types_test.go
  • it/it_public_clusters_test.go
  • it/it_rest_gateway_test.go
  • it/it_role_binding_reconciler_test.go
  • it/it_role_reconciler_test.go
  • it/it_tool.go
  • it/it_version_test.go
💤 Files with no reviewable changes (1)
  • internal/auth/tenancy_logic.go

Comment thread internal/servers/generic_server.go
@tchughesiv

Copy link
Copy Markdown
Contributor Author

Addressed the CodeRabbit review on generic_server.go (default-tenant error mapping):

  • Added auth.ErrExplicitTenantRequired sentinel
  • DetermineDefaultTenant() returns it for universal-access subjects without an explicit tenant
  • determineAssignedTenant() maps it to PermissionDenied (other failures remain Internal)
  • Added unit test coverage in servers_tenancy_test.go

Fixed in 02c95ec.

Remove the SharedTenants variable and stop defaulting universal-access
subjects to the shared tenant when no explicit tenant is provided.
Defer default-tenant resolution in the generic server until the request
and current object both omit a tenant, and update integration tests to
set shared tenant explicitly on admin creates.
Introduce auth.ErrExplicitTenantRequired and map it to PermissionDenied in
determineAssignedTenant so universal-access callers get a client-actionable
status instead of Internal.
@tchughesiv tchughesiv force-pushed the OSAC-496-remove-fallback-dead-code branch from 02c95ec to ce63eca Compare June 15, 2026 18:33
@tchughesiv

Copy link
Copy Markdown
Contributor Author

/retest-required

Hub registration in CI and installer scripts uses the admin token, which
now requires an explicit tenant. Default the create hub CLI to the shared
tenant and accept an optional --tenant override.

@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 `@it/it_private_host_types_test.go`:
- Line 170: This is an optional refactor for consistency. If you choose to
improve consistency with other tests that use sharedMetadata(), consider either
extending the sharedMetadata() helper to support additional custom fields like
Finalizers, or creating a local builder pattern at the test site that starts
with sharedMetadata() and adds the custom Finalizers field. However, the current
approach of manually setting Tenant: auth.SharedTenant is acceptable and doesn't
require changes since this test has specific custom metadata requirements that
differ from other tests.

In `@it/it_tool.go`:
- Around line 2102-2104: Replace the inline metadata construction in the
Metadata field assignment with a call to the sharedMetadata() helper function.
Instead of using privatev1.Metadata_builder{Tenant: auth.SharedTenant}.Build(),
call sharedMetadata() to ensure consistency with the rest of the test suite and
reduce duplication in metadata construction patterns.
🪄 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: osac-project/coderabbit/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 7b91aad2-aadd-4be1-958a-aff63827c372

📥 Commits

Reviewing files that changed from the base of the PR and between 72f4545 and f7524bb.

📒 Files selected for processing (24)
  • internal/auth/default_tenancy_logic.go
  • internal/auth/default_tenancy_logic_test.go
  • internal/auth/guest_tenancy_logic.go
  • internal/auth/guest_tenancy_logic_test.go
  • internal/auth/tenancy_logic.go
  • internal/cmd/cli/create/hub/create_hub_cmd.go
  • internal/servers/generic_server.go
  • internal/servers/servers_tenancy_test.go
  • it/it_annotations_test.go
  • it/it_cluster_reconciler_test.go
  • it/it_compute_subnet_test.go
  • it/it_emergency_access_test.go
  • it/it_labels_test.go
  • it/it_metadata.go
  • it/it_multitenancy_test.go
  • it/it_nodeset_removal_test.go
  • it/it_private_cluster_templates_test.go
  • it/it_private_host_types_test.go
  • it/it_public_clusters_test.go
  • it/it_rest_gateway_test.go
  • it/it_role_binding_reconciler_test.go
  • it/it_role_reconciler_test.go
  • it/it_tool.go
  • it/it_version_test.go

Comment thread it/it_private_host_types_test.go
Comment thread it/it_tool.go Outdated
Address CodeRabbit nitpick for consistent metadata construction in registerHub.
@tchughesiv

tchughesiv commented Jun 15, 2026

Copy link
Copy Markdown
Contributor Author

Review responses (OSAC-496)

Fixed / addressed

Thread Response Commit
Major: map explicit-tenant-required to PermissionDenied (generic_server.go) Fixed previously ce63eca
Nitpick: use sharedMetadata() in it_tool.go hub registration Applied 45f5aa7
Hub CLI / e2e-vmaas boot failure osac create hub now defaults --tenant to shared f7524bb

Skipped (with reason)

Thread Reason
Nitpick: sharedMetadata() in it_private_host_types_test.go Test needs custom Finalizers on metadata; inline builder is clearer than extending the helper for a one-off field. CodeRabbit marked this as acceptable.

e2e-vmaas re-running on latest commits.

Remove the --tenant flag and always set hub metadata tenant to shared.
Platform hub registration only needs the shared tenant for now; a
configurable tenant flag can follow in a separate change.
@tchughesiv

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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

This kind of change requires careful review by the core team, as the tenancy logic is a key piece of the authorization infrastructure, used by all objects, not just subnets. So please don't merge this till we have approved it.

@openshift-ci

openshift-ci Bot commented Jun 15, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: tchughesiv
Once this PR has been reviewed and has the lgtm label, please ask for approval from jhernand. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found 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

@openshift-ci

openshift-ci Bot commented Jun 15, 2026

Copy link
Copy Markdown

@tchughesiv: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/e2e-vmaas b1c8b60 link true /test e2e-vmaas

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.

@jhernand

Copy link
Copy Markdown
Contributor

Regarding the assignation of the default tenant and respecting the tenant explicitly provided by the user, I think it is already working as intended. I added more tests to verify it here: #708 .

@tchughesiv

Copy link
Copy Markdown
Contributor Author

@jhernand are we saying this PR should be closed? or should i leave it open until decisions are made by core?

@tchughesiv

tchughesiv commented Jun 16, 2026

Copy link
Copy Markdown
Contributor Author

awaiting tenancy decisions via OSAC-1546

@tchughesiv tchughesiv closed this Jun 16, 2026
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.

3 participants