Skip to content

Core: Remove AuthorizationTargetBinding in favor of direct resource lists#4201

Closed
flyrain wants to merge 2 commits into
apache:mainfrom
flyrain:remove-authorization-binding
Closed

Core: Remove AuthorizationTargetBinding in favor of direct resource lists#4201
flyrain wants to merge 2 commits into
apache:mainfrom
flyrain:remove-authorization-binding

Conversation

@flyrain

@flyrain flyrain commented Apr 14, 2026

Copy link
Copy Markdown
Contributor

Remove the AuthorizationTargetBinding interface and replace it with a simpler two-list API that naturally expresses 1:N relationships in authorization operations.

Problem: The binding interface forced 1:1 pairing between target and secondary resources, but many operations have 1:N cardinality. For example, attaching ONE policy to MULTIPLE tables required duplicating the policy across multiple bindings, which was then immediately flattened to separate lists.

Solution: Use direct factory method with two lists:

  • targets: resources where targetPrivileges are checked
  • secondaries: resources where secondaryPrivileges are checked

Benefits:

  • Simpler API with no intermediate wrapper objects
  • Naturally supports any cardinality (1:1, 1:N, N:M)
  • Directly maps to RbacOperationSemantics structure, which configs privileges on both target securables and secondary securables for each operation, while not restricts the mappings between them.
  • No duplication for batch operations

Please note that: the AuthorizationTargetBinding interface was introduced recently without affecting any existing Polaris version. It's safe to remove it now instead of using a deprecation process.

Checklist

  • 🛡️ Don't disclose security issues! (contact security@apache.org)
  • 🔗 Clearly explained why the changes are needed, or linked related issues: Fixes #
  • 🧪 Added/updated tests with good coverage, or manually tested (and explained how)
  • 💡 Added comments for complex logic
  • 🧾 Updated CHANGELOG.md (if needed)
  • 📚 Updated documentation in site/content/in-dev/unreleased (if needed)

Remove the AuthorizationTargetBinding interface entirely and replace it
with a simpler two-list API that naturally expresses 1:N relationships
in authorization operations.

Problem: The binding interface forced 1:1 pairing between target and
secondary resources, but many operations have 1:N cardinality. For
example, attaching ONE policy to MULTIPLE tables required duplicating
the policy across multiple bindings, which was then immediately
flattened to separate lists.

Solution: Use direct factory method with two lists:
- targets: resources where targetPrivileges are checked
- secondaries: resources where secondaryPrivileges are checked

Benefits:
- Simpler API with no intermediate wrapper objects
- Naturally supports any cardinality (1:1, 1:N, N:M)
- Directly maps to RbacOperationSemantics structure
- No duplication for batch operations

Changes:
- AuthorizationRequest: Use of(principal, op, targets, secondaries) API only
- AuthorizationTargetBinding: Deleted entire interface
- All tests: Updated to use new direct list API
- OpaPolarisAuthorizer: Updated comment reference
*
* <p><b>Examples:</b>
* <ul>
* <li>{@code ATTACH_POLICY_TO_TABLE}: targets=[policy], secondaries=[table1, table2, ...]

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.

I'm looking at the OPEN API spec to understand which APIs support multiple targets and secondaries, and Attach and Detach policy API seem to only support a single table-like target today:

AttachPolicyRequest:
type: object
required:
- target
properties:
target:
$ref: '#/components/schemas/PolicyAttachmentTarget'
parameters:
type: object
additionalProperties:
type: string
DetachPolicyRequest:
type: object
required:
- target
properties:
target:
$ref: '#/components/schemas/PolicyAttachmentTarget'
PolicyAttachmentTarget:
type: object
required:
- type
properties:
type:
type: string
description: |
Policy can be attached to different levels:
1. table-like: Policies specific to individual tables or views.
2. namespace: Policies applies to a namespace.
3. catalog: Policies that applies to a catalog
enum:
- catalog
- namespace
- table-like
example: table-like
path:
type: array
items:
type: string
description: |
A list representing the hierarchical path to the target, ordered from the namespace level down to the entity.
If the target is catalog, the path should be either empty or not set.
example: ["NS1", "NS2", "test_table_1"]

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.

Is 1->N mapping of targets to secondaries used used in detach-all option of dropPolicy?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We don't do that now. I think it's a potential use case. Removed the doc to avoid confusion

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.

Yes, I think my comment came in a bit late - I was working on a stale branch and you beat me to it :)

* <p><b>Examples:</b>
* <ul>
* <li>{@code ATTACH_POLICY_TO_TABLE}: targets=[policy], secondaries=[table1, table2, ...]
* <br>Checks POLICY_ATTACH on policy, TABLE_ATTACH_POLICY on each table

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.

I’m not fully convinced about allowing arbitrary MN mappings between targets and secondaries.

When we pass a non-unique list of M targets and N secondaries, what exactly are we intending to evaluate?

  • Are we expecting ATTACH_POLICY_TO_TABLE to be evaluated across the full Cartesian product (M × N)?
  • Or are we treating the two lists independently, where the authorization engine checks all M targets and all N secondaries without any explicit pairing semantics?

If the only non-1:1 use case we care about is 1 → N (e.g., one policy attached to multiple tables), we could instead keep the semantics explicit by constructing AuthorizationTargetBinding entries per pair and duplicating the policy and associating it with each secondary target. That makes the evaluation model unambiguous and avoids introducing implicit M × N behavior.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

As I said here #4201 (comment), this PR is nowhere to promote N:M relationship, although it is possible. This PR is to avoid mandatory 1:1 mapping between targets and secondaries. But let me know if there are solid use case to enforce 1:1 mapping. I mighty miss some discussions.

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.

I gave this a bit more thought, and given the impact on PolarisAuthorization implementations, it probably makes sense to continue the discussion on the mailing list.

I’ve responded on the DISCUSS thread you started @flyrain - looking forward to continuing the conversation there with the broader community.

@sungwy

sungwy commented Apr 14, 2026

Copy link
Copy Markdown
Contributor

Thanks for the PR @flyrain - I added some comments. I’d like to better understand the current use cases for M → N mappings between targets and secondaries to form a clearer opinion on which semantics we should adopt.

@flyrain

flyrain commented Apr 14, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the PR @flyrain - I added some comments. I’d like to better understand the current use cases for M → N mappings between targets and secondaries to form a clearer opinion on which semantics we should adopt.

Here are potential use cases, to grant a groups of privileges to multiple catalog roles. I understand we don't do that now. This PR itself also isn't intentionally promote this use case. Instead, it removes the enforcement of strictly 1:1 mapping brought by the binding class.

@dimas-b dimas-b 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.

From my POV making this SPI change without a concrete use case is going to be confusing. At the same time looking at previous comments, it does not appear that we have a concrete use case ATM 🤔

@Nonnull PolarisAuthorizableOperation operation,
@Nonnull List<AuthorizationTargetBinding> targetBindings) {
@Nonnull List<PolarisSecurable> targets,
@Nonnull List<PolarisSecurable> secondaries) {

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.

What is the intended semantics of the relationship between targets and secondaries?

If it is group-to-group association (N:M), how is the authorizer supposed to know the meaning of each of the targets and secondaries in relation to the operation? Should it check each target with respect to each secondary?

* @param principal the principal requesting authorization
* @param operation the operation to authorize
* @param targets resources where target privileges will be checked (may be empty)
* @param secondaries resources where secondary privileges will be checked (may be empty)

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.

privileges is a concept of the default (internal) Polaris RBAC model. It may not apply to other Authorizer types.

@dimas-b

dimas-b commented Apr 14, 2026

Copy link
Copy Markdown
Contributor

[...] it removes the enforcement of strictly 1:1 mapping brought by the binding class.

IIRC, AuthorizationTargetBinding was added in the new SPI specifically to help Authorizer implementors to achieve clarity. It clearly conveys the fact that the operation on a specific target related to a specific secondary should be authorized (or denied).

If targets and secondaries form a non-trivial (size > 1) set, I believe a more coherent approach would be for the caller to perform multiple authorization checks for each <op, target, secondary> tuple as appropriate for the use case. I believe the existing SPI covers that by List<AuthorizationTargetBinding>.

@flyrain

flyrain commented May 5, 2026

Copy link
Copy Markdown
Contributor Author

Hi @dimas-b, thanks for the review, as we discussed in the dev mailing thread: https://lists.apache.org/thread/o5hntqfvfhn5z9t78480nplpypddg200. I think it is less about whether the SPI can support it, and more about whether the current modeling (binding vs two lists) makes the intended
semantics clear. In particular, with two lists (targets and secondaries), it’s not obvious whether we are evaluating pairs, independent sets, or something else.

My motivation for the simpler model is to avoid over-constraining the API to 1:1 bindings while keeping the semantics flexible and future-proof. Even if today’s use cases look mostly 1:1, I’m hesitant to encode that assumption into the model. I'm also open to make the evaluation semantics explicit (independent vs pairwise), rather than relying on the shape of the API to imply it. Curious what you think.

@dimas-b

dimas-b commented May 6, 2026

Copy link
Copy Markdown
Contributor

@flyrain @sungwy : I believe we discussed this in the AuthZ sync on May 5... I tend to think we need to go back to the doc / discussion and strive for consensus there. What is the best path forward from your POV?

@flyrain

flyrain commented May 6, 2026

Copy link
Copy Markdown
Contributor Author

@flyrain @sungwy : I believe we discussed this in the AuthZ sync on May 5... I tend to think we need to go back to the doc / discussion and strive for consensus there. What is the best path forward from your POV?

I'm OK with a discussion on doc. Can we share the meeting notes and doc links in the dev mailing list first? I couldn't find it there.

@dimas-b

dimas-b commented May 7, 2026

Copy link
Copy Markdown
Contributor

@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown

This PR is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.

@github-actions github-actions Bot added the stale label Jun 8, 2026
@flyrain flyrain closed this Jun 8, 2026
@github-project-automation github-project-automation Bot moved this from PRs In Progress to Done in Basic Kanban Board Jun 8, 2026
@flyrain

flyrain commented Jun 8, 2026

Copy link
Copy Markdown
Contributor Author

Close this due to the change in #4409

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants