Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ request adding CHANGELOG notes for breaking (!) changes and possibly other secti

### Deprecations

* The property `polaris.active-roles-provider.type` is deprecated in favor of
`polaris.authentication.active-roles-provider.type`. The old property is still supported, but will be removed in a
future release.

### Fixes

### Commits
Expand Down
3 changes: 3 additions & 0 deletions runtime/defaults/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -144,14 +144,17 @@ polaris.rate-limiter.token-bucket.type=default
polaris.rate-limiter.token-bucket.requests-per-second=9999
polaris.rate-limiter.token-bucket.window=PT10S

# This property is DEPRECATED for removal; use polaris.authentication.active-roles-provider.type instead
polaris.active-roles-provider.type=default
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we also add an item in this page? https://polaris.apache.org/in-dev/unreleased/configuration/.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, good point, but I'd say it might be best to do it as a separate PR so as not to bloat the scope of this (very narrow) change.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also, we are preparing a full documentation page on authentication, stay tuned :-)


# Polaris authentication settings
polaris.authentication.type=internal
polaris.authentication.authenticator.type=default
polaris.authentication.active-roles-provider.type=${polaris.active-roles-provider.type}
# Per-realm overrides:
# polaris.authentication.realm1.type=external
# polaris.authentication.realm1.authenticator.type=custom
# polaris.authentication.realm1.active-roles-provider.type=custom

# Options effective when using internal auth (can be overridden in per realm):
polaris.authentication.token-service.type=default
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ public interface QuarkusAuthenticationRealmConfiguration extends AuthenticationR
@Override
QuarkusAuthenticatorConfiguration authenticator();

@Override
QuarkusActiveRolesProviderConfiguration activeRolesProvider();

@Override
QuarkusTokenServiceConfiguration tokenService();

Expand Down Expand Up @@ -70,4 +73,14 @@ interface QuarkusTokenBrokerConfiguration extends TokenBrokerConfiguration {
@WithDefault("rsa-key-pair")
String type();
}

interface QuarkusActiveRolesProviderConfiguration extends ActiveRolesProviderConfiguration {

/**
* The type of the active roles provider. Must be a registered {@link
* org.apache.polaris.service.auth.ActiveRolesProvider} identifier.
*/
@WithDefault("default")
String type();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@
import org.apache.polaris.service.ratelimiter.RateLimiter;
import org.apache.polaris.service.ratelimiter.TokenBucketFactory;
import org.apache.polaris.service.task.TaskHandlerConfiguration;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.eclipse.microprofile.context.ManagedExecutor;
import org.eclipse.microprofile.context.ThreadContext;
import org.slf4j.Logger;
Expand Down Expand Up @@ -341,9 +340,11 @@ public QuarkusAuthenticationRealmConfiguration realmAuthConfig(

@Produces
public ActiveRolesProvider activeRolesProvider(
@ConfigProperty(name = "polaris.active-roles-provider.type") String activeRolesProviderType,
QuarkusAuthenticationRealmConfiguration config,
@Any Instance<ActiveRolesProvider> activeRolesProviders) {
return activeRolesProviders.select(Identifier.Literal.of(activeRolesProviderType)).get();
return activeRolesProviders
.select(Identifier.Literal.of(config.activeRolesProvider().type()))
.get();
}

@Produces
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.apache.polaris.service.quarkus.auth;

import static org.apache.polaris.service.auth.AuthenticationConfiguration.DEFAULT_REALM_KEY;
import static org.assertj.core.api.Assertions.assertThat;

import com.google.common.collect.ImmutableMap;
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.junit.QuarkusTestProfile;
import io.quarkus.test.junit.TestProfile;
import jakarta.inject.Inject;
import java.util.Map;
import org.apache.polaris.service.auth.AuthenticationType;
import org.apache.polaris.service.quarkus.auth.external.OidcConfiguration;
import org.apache.polaris.service.quarkus.auth.external.OidcTenantConfiguration;
import org.junit.jupiter.api.Test;

@QuarkusTest
@TestProfile(AuthenticationConfigurationTest.Profile.class)
public class AuthenticationConfigurationTest {

@Inject QuarkusAuthenticationConfiguration authConfig;
@Inject OidcConfiguration oidcConfig;

@Test
void smokeTest() {
Map<String, QuarkusAuthenticationRealmConfiguration> realms = authConfig.realms();
assertThat(realms).hasSize(3);

assertThat(realms.get(DEFAULT_REALM_KEY).type()).isEqualTo(AuthenticationType.MIXED);
assertThat(realms.get(DEFAULT_REALM_KEY).authenticator().type()).isEqualTo("custom");
assertThat(realms.get(DEFAULT_REALM_KEY).activeRolesProvider().type()).isEqualTo("custom");
assertThat(realms.get(DEFAULT_REALM_KEY).tokenBroker().type()).isEqualTo("custom");
assertThat(realms.get(DEFAULT_REALM_KEY).tokenService().type()).isEqualTo("custom");

assertThat(realms.get("realm1").type()).isEqualTo(AuthenticationType.INTERNAL);
assertThat(realms.get("realm1").authenticator().type()).isEqualTo("default");
assertThat(realms.get("realm1").activeRolesProvider().type()).isEqualTo("default");
assertThat(realms.get("realm1").tokenBroker().type()).isEqualTo("default");
assertThat(realms.get("realm1").tokenService().type()).isEqualTo("default");

assertThat(realms.get("realm2").type()).isEqualTo(AuthenticationType.EXTERNAL);
assertThat(realms.get("realm2").authenticator().type()).isEqualTo("default");
assertThat(realms.get("realm2").activeRolesProvider().type()).isEqualTo("default");
assertThat(realms.get("realm2").tokenBroker().type()).isEqualTo("rsa-key-pair");
assertThat(realms.get("realm2").tokenService().type()).isEqualTo("default");

Map<String, OidcTenantConfiguration> tenants = oidcConfig.tenants();
assertThat(tenants).hasSize(2);

assertThat(tenants.get(DEFAULT_REALM_KEY).principalMapper().type()).isEqualTo("custom");
assertThat(tenants.get(DEFAULT_REALM_KEY).principalRolesMapper().type()).isEqualTo("custom");

assertThat(tenants.get("tenant1").principalMapper().type()).isEqualTo("default");
assertThat(tenants.get("tenant1").principalRolesMapper().type()).isEqualTo("default");
}

public static class Profile implements QuarkusTestProfile {
@Override
public Map<String, String> getConfigOverrides() {
return ImmutableMap.<String, String>builder()

// Polaris Auth config

// Default realm: mixed auth with custom impls
.put("polaris.authentication.type", "mixed")
.put("polaris.authentication.authenticator.type", "custom")
.put("polaris.authentication.active-roles-provider.type", "custom")
.put("polaris.authentication.token-broker.type", "custom")
.put("polaris.authentication.token-service.type", "custom")
// realm1: internal auth with default impls
.put("polaris.authentication.realm1.type", "internal")
.put("polaris.authentication.realm1.authenticator.type", "default")
.put("polaris.authentication.realm1.active-roles-provider.type", "default")
.put("polaris.authentication.realm1.token-broker.type", "default")
.put("polaris.authentication.realm1.token-service.type", "default")
// realm2: external auth
.put("polaris.authentication.realm2.type", "external")

// Polaris OIDC config

// Default tenant: custom principal mapper and roles mapper
.put("polaris.oidc.principal-mapper.type", "custom")
.put("polaris.oidc.principal-roles-mapper.type", "custom")
// tenant1: default principal mapper and roles mapper
.put("polaris.oidc.tenant1.principal-mapper.type", "default")
.put("polaris.oidc.tenant1.principal-roles-mapper.type", "default")
.build();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ public interface AuthenticationRealmConfiguration {

interface AuthenticatorConfiguration {}

/**
* The configuration for the active roles provider. The active roles provider is responsible for
* determining the active roles for a given Polaris principal.
*/
ActiveRolesProviderConfiguration activeRolesProvider();

interface ActiveRolesProviderConfiguration {}

/**
* The configuration for the OAuth2 service that delivers OAuth2 tokens. Only relevant when using
* internal authentication (using Polaris as the authorization server).
Expand Down
Loading