-
Notifications
You must be signed in to change notification settings - Fork 332
Implement OpaPolarisAuthorizer #2680
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
adutra
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @sungwy for this draft PR, I couldn't resist and took a look 😄
This is really interesting imho and a very nice addition to Polaris. We need to start thinking about ways to make Polaris RBAC fully pluggable.
.../auth/opa/impl/src/main/java/org/apache/polaris/extension/auth/opa/OpaPolarisAuthorizer.java
Show resolved
Hide resolved
...sions/auth/opa/src/main/java/org/apache/polaris/extension/auth/opa/OpaPolarisAuthorizer.java
Outdated
Show resolved
Hide resolved
runtime/service/src/main/java/org/apache/polaris/service/config/AuthorizationConfiguration.java
Outdated
Show resolved
Hide resolved
runtime/service/src/main/java/org/apache/polaris/service/config/ServiceProducers.java
Outdated
Show resolved
Hide resolved
runtime/service/src/main/java/org/apache/polaris/service/config/ServiceProducers.java
Outdated
Show resolved
Hide resolved
dimas-b
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very interesting idea! Just some preliminary comments below :)
|
Thanks for working on it @sungwy ! Looking forward to the RFC/design doc! |
| if (Strings.isNullOrEmpty(cachedToken)) { | ||
| throw new RuntimeException( | ||
| "Bearer token is unexpectedly empty. This should not happen after successful construction."); | ||
| } | ||
| return cachedToken; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
technically this is still racy since cachedToken is volatile... it is not likely to materialize as a bug, but the code pattern looks a bit worrisome 😅 why not load the value into a local var, check and return from local?
e.g. return Preconditions.checkNotNull(cachedToken, "Bearer token is unexpectedly empty ...")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this is outdated now with the new commits.
Make token-refresh asynchronous ...
snazy
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One nit, everything else beside int-tests LGTM.
For integration-tests, I'm thinking of having non-Quarkus integration tests against an OPA testcontainer in the "main" OPA module.
I've prepared some stuff for tests in this commit (here as well):
- Add a starter for an integration test in the "main" module
- Updated the existing int tests
Idea is to have the majority of integration-tests in the "main" module and only a smoke-test in runtime-service.
I think we can then get rid of the opa-tests module and can move the "main" module one directory level up.
BTW: Please add an entry for the "main" module to :polaris-bom.
WDYT?
.../impl/src/main/java/org/apache/polaris/extension/auth/opa/token/FileBearerTokenProvider.java
Outdated
Show resolved
Hide resolved
| if (Strings.isNullOrEmpty(cachedToken)) { | ||
| throw new RuntimeException( | ||
| "Bearer token is unexpectedly empty. This should not happen after successful construction."); | ||
| } | ||
| return cachedToken; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this is outdated now with the new commits.
reduce volatile reads from 2 -> 1 Co-authored-by: Robert Stupp <[email protected]>
Thanks again @snazy :) Let me take a look at your draft PR and see if I can get rid of the Just so I'm clear: is your suggestion to move the QuarkusIntegrationTest annotated tests back into |
Yes and no ;) Have non-Quarkus integration tests (like |
| } | ||
|
|
||
| private void scheduleRefreshAttempt(Duration delay) { | ||
| this.refreshTask = asyncExec.schedule(this::refreshTokenAttempt, delay); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice reuse of existing functionality 🚀
| // In this case we wait for the configured amount of time | ||
| // (5 seconds in production, much lower in tests). | ||
| try { | ||
| return initialTokenFuture.get(initialTokenWaitMillis, TimeUnit.MILLISECONDS); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
optional: I do not want to disturb the impl. at this stage as it looks pretty solid to me... but I suppose it could be simplified this way:
- keep a
volatilereference to aCompletionStagewith token data getTokenalways calls.get()with a timeout- the initial ref. to the
CompletionStageis make in the constructor by scheduling a refresh task - when refresh completes it will update the
CompletionStageand reschedule - the
CompletionStagewill be "complete" in all cases but the initial refresh, so.get()calls will not wait except possibly on the first call. - we have less fields and less
ifs (hopefully) in this class (onlyrefreshTaskand theCompletionStage)
WDYT?
polaris-core/build.gradle.kts
Outdated
| testFixturesApi(libs.jakarta.ws.rs.api) | ||
|
|
||
| compileOnly(libs.jakarta.annotation.api) | ||
| compileOnly(libs.jakarta.enterprise.cdi.api) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC, we had some prior discussions about avoiding CDI annotations in core as a convention...
If it's required only for @Identifier("internal") on DefaultPolarisAuthorizerFactory, I'd propose remove the annotation from the class and make a producer method for it in ServiceProducers.
Alternatively, we could remove DefaultPolarisAuthorizerFactory completely and update ServiceProducers to "manually" use PolarisAuthorizerImpl if Instance<PolarisAuthorizerFactory> is not resolvable in CDI.
WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @dimas-b these are great suggestions. Thank you for giving me the background context on the package discussions.
I've added a Producer method in ServiceProducers and removed the cdi dependency from polaris-core
I actually found it very helpful to have the Quarkus integration tests because it helped verify the @dimas-b - I would love to get your thoughts on this suggestion as well |
I've added the |
Yes, we will need them in BOM as well. A separate PR sounds good to me. |
dimas-b
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry about the delay. This PR LGTM in its current state, except the dep. on CDI annotations in polaris-core.
The current tests layout LGTM. So, if @snazy is ok with that, I think we're pretty close to merging.
Re: CDI in core, we can probably discuss that on the dev ML if you prefer to keep the annotation. The reason I flagged it is not my personal objection, but the fact that IIRC it was discussed before and the agreement in the community was to avoid CDI-specific annotations in core.
|
@dimas-b - I've addressed the concern regarding the |
dimas-b
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 👍 @sungwy : Many thanks for the contribution and for bearing with the long review process 😉
|
Woohoo! Thank you @dimas-b ! And @snazy @flyrain and @adutra for the reviews as well. This was a great way for me to get up to speed with the project, so thanks for your interest and patience in reviewing this PR as well. I'll be following this up with some more PRs (docs, schema, etc) and we'll start integrating this into our platform. |
|
|
||
| implementation(libs.jakarta.servlet.api) | ||
|
|
||
| runtimeOnly(project(":polaris-async-vertx")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need this dependency? Is this only for test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this actually is the CDI implementation of polaris-async-api AsyncExec that's optimized for Quarkus applications. Hence, we need it as a runtimeOnly dependency in polaris-runtime-service
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’m good with using the Vert.x async executor since we’re already on Quarkus. The polaris-async-vertx module currently lives under /persistence/nosql, but it’s really part of the async infrastructure rather than a NoSQL implementation detail. We could consider moving it out of that directory, though it doesn’t need to be done in this PR.
Resolves #138
RFC: https://docs.google.com/document/d/1HadMFygjbuZathZZPanO6cFVorx0Ju0FopkICxX1tCE/edit?tab=t.0
Mailing list discussion: https://lists.apache.org/thread/54qdbsxs3j7wwhv3tsccqj6qng5lqgmz
Some followup items highlighted as a part of this PR review:
OpaHttpClientFactorythat utilizesPoolingHttpClientConnectionManagerto get opa-http-client to be more production ready