Skip to content

[ISSUE #11470] fix(proxy): fail closed on admin methods missing an ACL mapping - #11471

Open
Felix-Gong wants to merge 1 commit into
apache:developfrom
Felix-Gong:fix/proxy-admin-auth-fail-closed-unmapped
Open

Felix-Gong wants to merge 1 commit into
apache:developfrom
Felix-Gong:fix/proxy-admin-auth-fail-closed-unmapped

Conversation

@Felix-Gong

Copy link
Copy Markdown
Contributor

Fixes #11470

ProxyAdminAuthInterceptor skipped authorization for any method missing from METHOD_PERMISSIONS — the branch was resourceAction != null && authzEnabled, so an unmapped served method ran with authentication only, in both normal and fail-closed (grpcAdminServerAuthEnable) configurations. Nothing is unmapped on develop today, but the Admin surface grows through rocketmq-apis (three recent expansions) and nothing pins the proto against the hand-written map, so the next RPC added without an entry would be an unauthorized path by construction.

Two changes, one theme:

  • Runtime: when authorizationEnabled is on, a method without a proxy.admin.* mapping is now closed with PERMISSION_DENIED instead of being served. Open mode (cluster auth fully off) is untouched.
  • Drift guard: everyServedAdminMethodHasAnAclMapping walks AdminGrpc.getServiceDescriptor() and asserts every served RPC resolves to a resource/action, so CI fails the moment a new proto RPC lands without someone deciding its ACL.

Red/green: unmappedMethodIsDeniedWhenAuthorizationEnabled passes on the current code (verified by stashing the fix — it asserts startCall never happens and the status is PERMISSION_DENIED). ProxyAdminAuthInterceptorTest 9/9, full proxy module 455 tests green on JDK 11.

Coordination: PR #11363 (for #11362) changes resolveSourceIp in the same two files — different concern (which address is evaluated vs whether an authorization decision exists at all). The hunks are adjacent where it updates the resolveSourceIp(call) call site inside the block this PR restructures; a trivial rebase either way, happy to rebase once it lands.

… an ACL mapping

ProxyAdminAuthInterceptor treated an absent METHOD_PERMISSIONS entry
as 'no check needed': the authz branch required resourceAction != null,
so a served method without a mapping ran straight through to the
handler with authentication only, even with the cluster authorization
switch on and even in fail-closed mode.

The admin server serves only the 16 mapped Admin RPCs today, but the
surface grows through rocketmq-apis (three Admin expansions in recent
commits), so the next RPC added without an entry here would be an
unauthorized call path including mutations.

Deny unmapped methods with PERMISSION_DENIED whenever authorization is
enabled, and add a completeness test that walks
AdminGrpc.getServiceDescriptor() so CI fails on map drift the moment
a new RPC lands.

Red/green: unmappedMethodIsDeniedWhenAuthorizationEnabled was verified
to fail on the old pass-through code by stashing the fix. Proxy
module: 455 tests green, 9 in ProxyAdminAuthInterceptorTest, JDK 11.

@RockteMQ-AI RockteMQ-AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review by github-manager-bot

Summary

Security hardening: fail-closed authorization for admin gRPC methods that lack an ACL mapping in ProxyAdminAuthInterceptor.

Findings

  • [Info] ProxyAdminAuthInterceptor.java:196-202 — Clean restructuring. The old resourceAction != null && authzEnabled short-circuited the entire authz block when a method had no mapping. The new structure correctly enters the authz block first, then denies unmapped methods with PERMISSION_DENIED. This is the right fail-closed pattern.
  • [Info] ProxyAdminAuthInterceptorTest.java — Two-layer test coverage is solid:
    • everyServedAdminMethodHasAnAclMapping() acts as a CI drift guard — fails the moment a new proto RPC lands without an ACL entry.
    • unmappedMethodIsDeniedWhenAuthorizationEnabled() verifies the runtime deny behavior with proper mockito verification (never().startCall() + PERMISSION_DENIED assertion).
  • [Info] PR description is excellent — clearly documents the vulnerability window, the fix rationale, red/green verification, and coordination note with PR #11363.

Suggestions

  • Minor: the @SuppressWarnings("unchecked") on unmappedMethodIsDeniedWhenAuthorizationEnabled appears unnecessary — no unchecked operations are visible in the test body. Consider removing it to keep the annotation surface minimal. (Non-blocking.)

Verdict

Well-crafted security fix. The fail-closed approach is the correct pattern for an expanding admin API surface. LGTM.


Automated review by github-manager-bot

@RockteMQ-AI RockteMQ-AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review by github-manager-bot

Summary

Fail-closed security fix: when authorization is enabled, admin methods without an ACL mapping are now denied with PERMISSION_DENIED instead of being served with authentication only. Adds a drift guard test that walks AdminGrpc.getServiceDescriptor() and fails CI if a new RPC lands without an entry in METHOD_PERMISSIONS.

Findings

  • [Critical → Fixed] The original code (resourceAction != null && authzEnabled) meant an unmapped method would skip the ACL branch entirely when authorization was enabled. This is a fail-open bug by construction — any future RPC added to the proto without a corresponding map entry would be served without authorization. The fix correctly inverts the logic: if authzEnabled is on, a missing mapping is now a hard deny.
  • [Info] The drift guard test everyServedAdminMethodHasAnAclMapping is excellent — it pins the proto-to-ACL mapping invariant at CI time, so the next RPC expansion cannot silently introduce an unauthorized path.
  • [Info] The PERMISSION_DENIED status with a descriptive message pointing at the map is helpful for developers adding new RPCs — they'll know exactly what to do.
  • [Info] Open mode (cluster auth fully off) is correctly untouched by this change.

Suggestions

  • Consider adding a comment in METHOD_PERMISSIONS (or a separate doc) listing the process for adding a new admin RPC: add proto method → add map entry → add test. This makes the drift guard self-documenting.

This is an important security hardening. The fix is minimal, correct, and the drift guard test ensures the invariant holds going forward.


Automated review by github-manager-bot

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Proxy Admin authorization is skipped for methods missing from the permission map

2 participants