Skip to content
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

fix: also skip basic authentication for authentication.skip.paths #9669

Merged
merged 4 commits into from
Nov 2, 2022

Conversation

lucasbru
Copy link
Member

Description

There is the KSQL parameter authentication.skip.paths that disables authentication for specific paths. Currently, the parameter is ignored for basic authentication, which is probably a bug or at least very confusing to users.

This change moves the handling of authentication.skip.paths from specific auth handlers to the AuthHandlers class, which allows us to skip any authentication/authorization for paths that match authentication.skip.paths.

This change introduces a new Provider called SKIP, that works very similar to the existing SYSTEM Provider - it means that all other authentication / authorization provides. It is enabled for authentication.skip.paths and for 3 hard-coded paths. We also slightly simplify the handling of the SYSTEM authorization to bring it in line with SKIP.

Testing done

We port the existing, provider-specic unit tests to AuthHandlers.

I also performed manual testing with the settings

authentication.skip.paths=/skippath
authentication.method=BASIC
authentication.realm=KsqlServer-Props
authentication.roles=users

and the same JAAS configuration in the ticket #9206
and checking

curl localhost:8088/skippath # not found
curl localhost:8088/v1/metadata # works
curl localhost:8088/noskippath # unauthorized
curl -u "my_user:my_password" localhost:8088/skippath # not found
curl -u "my_user:my_password" localhost:8088/v1/metadata # works
curl -u "my_user:my_password" localhost:8088/noskippath # not found

Fixes #9206

Reviewer checklist

  • Ensure docs are updated if necessary. (eg. if a user visible feature is being added or changed).
  • Ensure relevant issues are linked (description should include text like "Fixes #")

@lucasbru lucasbru requested a review from a team as a code owner October 26, 2022 11:50
@lucasbru lucasbru self-assigned this Oct 26, 2022
@lucasbru lucasbru requested a review from spena October 26, 2022 11:52
@@ -236,7 +236,6 @@ private void createQuery(final String suffix) {
TEST_HARNESS.getKafkaCluster().waitForTopicsToBePresent(SINK_TOPIC + suffix);
}

@NotNull
Copy link
Member Author

Choose a reason for hiding this comment

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

For some reason, spotbugs kept thinking this can return null. Looks to me like a false alarm, not why I'm getting it.

@lucasbru
Copy link
Member Author

@spena and/or @AlanConfluent could you maybe have a look?

new KsqlAuthorizationProviderHandler(server, ksqlAuthorizationProvider)));
selectiveHandler(
new KsqlAuthorizationProviderHandler(server, ksqlAuthorizationProvider),
provider -> provider == Provider.JAAS || provider == Provider.PLUGIN
Copy link
Member

Choose a reason for hiding this comment

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

Did we just implicitly only fall through to here if it was jaas or plugin and now you're just formally checking that?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, mostly. For SYSTEM there was a check inside KsqlAuthorizationProviderHandler that skipped authorization. The other two options were JAAS and PLUGIN, otherwise the selectHandler fails.

I moved those checks here to at least have the selection logic in one file and not spread across the various concrete implementations.

Copy link
Member

Choose a reason for hiding this comment

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

That makes sense. It's better to have it centralized here.

) {
return rc -> {
if (rc.data().get(PROVIDER_KEY) != provider) {
if (!providerTest.test((Provider)rc.data().get(PROVIDER_KEY))) {
Copy link
Member

Choose a reason for hiding this comment

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

I know you didn't change this part of the logic, but this looks slightly scary that it skips this handler if the particular provider is different from what we expect. It just seems a little error prone that we decide which auth to use and invoke a handler in two different places. Maybe this is because we have to statically install all the handers, but only invoke one of them at request-time? Just a general comment -- not sure if you have any ideas.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, I totally agree. This could be a vertx-ish architectural style, but I'm not sure if it is achieving anything in our setting. It should be possible to have a single wrapping handler to call the sub-handlers -- essentially, merge selectHandler and selectiveHandler into one, so that you can use plain old control-flow for handler selection instead of passing around PROVIDER values. I didn't want to make this too large of a refactoring, but if you want to go down this road with me, I could try.

Copy link
Member

Choose a reason for hiding this comment

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

No need for anything in this PR, more just thoughts while reading surrounding code. We can consider that as a followup if you do more changes in this area.

@@ -130,6 +150,11 @@ private static void selectHandler(
context.next();
return;
}
if (skipPathsPattern.matcher(context.normalizedPath()).matches()) {
Copy link
Member

Choose a reason for hiding this comment

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

Nit: Maybe put this first to match the previous order of checks in the plugin. Shouldn't make any difference, but just to be safe.

Copy link
Member Author

Choose a reason for hiding this comment

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

done

@@ -58,28 +68,36 @@ static void setupAuthHandlers(final Server server, final Router router,
systemAuthenticationHandler.ifPresent(handler -> registerAuthHandler(router, handler));
Copy link
Member

Choose a reason for hiding this comment

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

I don't think it should matter whether they're considered system authenticated before you check the path because it only has the effect of skipping any subsequent checks if they are.

Copy link
Member Author

Choose a reason for hiding this comment

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

ack

@@ -120,8 +138,10 @@ private static Handler<RoutingContext> wrappedHandler(
* In order of preference, we see if the user is the system user, then we check for
* JAAS configurations, and finally we check to see if there's a plugin we can use
*/
private static void selectHandler(
// default visibility for testing
Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

neat! done

Copy link
Member

@spena spena left a comment

Choose a reason for hiding this comment

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

Just one minor comment.
LGTM

@@ -120,11 +139,18 @@ private static Handler<RoutingContext> wrappedHandler(
* In order of preference, we see if the user is the system user, then we check for
Copy link
Member

Choose a reason for hiding this comment

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

Can you modify this comment for the order of preference? Btw, wouldn't check for SYSTEM be the step 1, then check for SKIP path?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, see comment from Alan above. I would think SYSTEM goes first as well, but the original order in the code is SKIP first, and since it shouldn't really make a difference, the idea is to not risk breaking some existing behavior unknowingly.

@lucasbru lucasbru merged commit 05c7123 into confluentinc:master Nov 2, 2022
@lucasbru lucasbru deleted the fix_skippaths branch November 2, 2022 11:13
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.

Unable to skip basic authentication for specified paths in ksqldb-server
3 participants