Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Support compound app:userName rules in connector authorization#700

Merged
ursetta-netflix merged 1 commit into
masterfrom
connector-auth-compound-rules
Apr 30, 2026
Merged

Support compound app:userName rules in connector authorization#700
ursetta-netflix merged 1 commit into
masterfrom
connector-auth-compound-rules

Conversation

@ursetta-netflix

@ursetta-netflix ursetta-netflix commented Apr 28, 2026

Copy link
Copy Markdown
Collaborator

Summary

Extends connector authorization (connector.authorized-callers) to support compound rules of the form app:userName, in addition to the existing plain app entries.

  • Plain entry (e.g. app1) — matches on SsoDirectCallerAppName only. Unchanged behavior.
  • Compound entry (e.g. app2:user2) — requires both SsoDirectCallerAppName AND the request userName to match exactly.

Motivation

After #690, connector authorization checks SsoDirectCallerAppName against a flat allow list. This is too coarse for callers like:

MetacatRequestContext{userName='user2', ..., additionalContext='{SsoDirectCallerAppName=app2, ...}'}

Allowing all of app2 would over-grant. We want a way to grant access only when both the direct caller app and the userName line up — e.g. app2 + user2 only — while leaving existing app-only entries working for other callers.

Changes

  • New AuthorizedCaller value class (appName required, userName nullable) with a matches(callerApp, callerUserName) method.
  • ConnectorFactoryDecorator now parses each comma token, splitting on the first : to build compound rules. Empty tokens are skipped; matching remains case-sensitive.
  • ConnectorAuthorizationUtil.checkAuthorization reads userName from the request context and uses anyMatch over the allow-list rules. Deny logs include the userName for easier debugging.
  • The four Authorizing*Service decorators (Catalog, Database, Table, Partition) now hold Set<AuthorizedCaller> instead of Set<String>.

Config example

connector.authorization-required=true
connector.authorized-callers=app1,app2,app3:user1

Behavior with the above:

SsoDirectCallerAppName userName Result
app1 any allowed
app3 user1 allowed
app3 user2 denied
app3 null denied
other user2 denied

Backwards compatibility

Configs with no : in any entry parse to rules with userName=null and behave identically to the previous implementation. No deployment-time action needed for existing connectors.

Test plan

  • ./gradlew :metacat-common-server:test — all targeted specs pass
  • New cases in ConnectorAuthorizationUtilSpec: compound match, userName mismatch, null userName, mixed plain+compound list, app mismatch
  • New parsing test in ConnectorFactoryDecoratorSpec for app:userName syntax
  • Existing Authorizing*ServiceSpec tests migrated to AuthorizedCaller and continue to pass

Extend connector.authorized-callers to accept entries of the form
`app:userName` in addition to plain `app` entries. Plain entries continue
to match on SsoDirectCallerAppName only; compound entries require both
SsoDirectCallerAppName AND the request userName to match exactly. This
allows narrow grants like `hadoop:idm-worker` without broadening access
to all hadoop-app callers.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@ursetta-netflix ursetta-netflix marked this pull request as ready for review April 30, 2026 14:51
if (!appName.equals(callerAppName)) {
return false;
}
if (userName == null) {

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.

are there any edge cases where the username filed is not a null value but it's populated with a value that should be treated as null?

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.

example having "null" as user for example

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.

follow up, should an empty string be considered as null here?

@ursetta-netflix ursetta-netflix Apr 30, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

username here is from the catalog configuration like user in app:user. So this will always either be a value we set, or null if it's not colon separated like app2.

So we will only compare a string we set ie: user to the callerUserName which is in the request. So we are expecting the request to explicitly match the known string or we deny.

@ursetta-netflix ursetta-netflix merged commit bf3f765 into master Apr 30, 2026
4 checks passed
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.

4 participants