This is an automated email from the ASF dual-hosted git repository.
yuqi1129 pushed a commit to branch branch-1.3
in repository https://gitbox.apache.org/repos/asf/gravitino.git
The following commit(s) were added to refs/heads/branch-1.3 by this push:
new 7b64aefcff [Cherry-pick to branch-1.3] [#11412] feat(auth): Add
initialize(Config) to PrincipalMapper and GroupMapper interfaces (#11411)
(#11420)
7b64aefcff is described below
commit 7b64aefcfff9c02126db0953f448bfb1bfcedc13
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Thu Jun 4 15:25:07 2026 +0800
[Cherry-pick to branch-1.3] [#11412] feat(auth): Add initialize(Config) to
PrincipalMapper and GroupMapper interfaces (#11411) (#11420)
**Cherry-pick Information:**
- Original commit: 95be458a81c7e5f58732d6d1d9841ebc7f7e9cc0
- Target branch: `branch-1.3`
- Status: ✅ Clean cherry-pick (no conflicts)
Co-authored-by: Bharath Krishna <[email protected]>
---
.../org/apache/gravitino/auth/GroupMapper.java | 11 +++++++
.../apache/gravitino/auth/GroupMapperFactory.java | 37 ++++++++++++----------
.../org/apache/gravitino/auth/PrincipalMapper.java | 11 +++++++
.../gravitino/auth/PrincipalMapperFactory.java | 36 ++++++++++++---------
.../gravitino/auth/TestGroupMapperFactory.java | 35 +++++++++++++++++---
.../gravitino/auth/TestPrincipalMapperFactory.java | 33 ++++++++++++++++---
.../server/authentication/JwksTokenValidator.java | 4 +--
.../authentication/KerberosAuthenticator.java | 2 +-
.../authentication/StaticSignKeyValidator.java | 4 +--
9 files changed, 128 insertions(+), 45 deletions(-)
diff --git a/core/src/main/java/org/apache/gravitino/auth/GroupMapper.java
b/core/src/main/java/org/apache/gravitino/auth/GroupMapper.java
index 65acf7b7d2..2e744c4355 100644
--- a/core/src/main/java/org/apache/gravitino/auth/GroupMapper.java
+++ b/core/src/main/java/org/apache/gravitino/auth/GroupMapper.java
@@ -20,6 +20,7 @@
package org.apache.gravitino.auth;
import java.util.List;
+import org.apache.gravitino.Config;
import org.apache.gravitino.UserGroup;
/**
@@ -30,6 +31,16 @@ import org.apache.gravitino.UserGroup;
*/
public interface GroupMapper {
+ /**
+ * Initializes the mapper with server configuration. Called by the factory
after instantiation.
+ *
+ * <p>Custom implementations can override this to read additional
configuration properties. The
+ * default implementation is a no-op for backward compatibility.
+ *
+ * @param config the server configuration
+ */
+ default void initialize(Config config) {}
+
/**
* Maps a list of group strings to a new list of group strings.
*
diff --git
a/core/src/main/java/org/apache/gravitino/auth/GroupMapperFactory.java
b/core/src/main/java/org/apache/gravitino/auth/GroupMapperFactory.java
index d66cd46f91..61b12ea639 100644
--- a/core/src/main/java/org/apache/gravitino/auth/GroupMapperFactory.java
+++ b/core/src/main/java/org/apache/gravitino/auth/GroupMapperFactory.java
@@ -19,6 +19,7 @@
package org.apache.gravitino.auth;
+import org.apache.gravitino.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -34,30 +35,34 @@ public class GroupMapperFactory {
*
* @param mapperType the type of the mapper (e.g., "regex" or fully
qualified class name)
* @param regexPattern the regex pattern to use (only for "regex" mapper
type)
+ * @param config the server configuration passed to {@link
GroupMapper#initialize(Config)}
* @return a configured GroupMapper instance
* @throws IllegalArgumentException if the mapper type is invalid or
initialization fails
*/
- public static GroupMapper create(String mapperType, String regexPattern) {
+ public static GroupMapper create(String mapperType, String regexPattern,
Config config) {
+ GroupMapper mapper;
if ("regex".equalsIgnoreCase(mapperType)) {
if (regexPattern == null) {
throw new IllegalArgumentException("Regex pattern cannot be null for
regex mapper");
}
- return new RegexGroupMapper(regexPattern);
- }
-
- try {
- Class<?> clazz = Class.forName(mapperType);
- if (!GroupMapper.class.isAssignableFrom(clazz)) {
- throw new IllegalArgumentException(
- "Class " + mapperType + " does not implement GroupMapper");
+ mapper = new RegexGroupMapper(regexPattern);
+ } else {
+ try {
+ Class<?> clazz = Class.forName(mapperType);
+ if (!GroupMapper.class.isAssignableFrom(clazz)) {
+ throw new IllegalArgumentException(
+ "Class " + mapperType + " does not implement GroupMapper");
+ }
+ mapper = (GroupMapper) clazz.getDeclaredConstructor().newInstance();
+ } catch (ClassNotFoundException e) {
+ LOG.error("Failed to load GroupMapper class: {}", mapperType, e);
+ throw new IllegalArgumentException("Failed to load GroupMapper class:
" + mapperType, e);
+ } catch (Exception e) {
+ LOG.error("Failed to create GroupMapper: {}", mapperType, e);
+ throw new IllegalArgumentException("Failed to create GroupMapper: " +
mapperType, e);
}
- return (GroupMapper) clazz.getDeclaredConstructor().newInstance();
- } catch (ClassNotFoundException e) {
- LOG.error("Failed to load GroupMapper class: {}", mapperType, e);
- throw new IllegalArgumentException("Failed to load GroupMapper class: "
+ mapperType, e);
- } catch (Exception e) {
- LOG.error("Failed to create GroupMapper: {}", mapperType, e);
- throw new IllegalArgumentException("Failed to create GroupMapper: " +
mapperType, e);
}
+ mapper.initialize(config);
+ return mapper;
}
}
diff --git a/core/src/main/java/org/apache/gravitino/auth/PrincipalMapper.java
b/core/src/main/java/org/apache/gravitino/auth/PrincipalMapper.java
index f4af0e6c3d..dedce4d0ad 100644
--- a/core/src/main/java/org/apache/gravitino/auth/PrincipalMapper.java
+++ b/core/src/main/java/org/apache/gravitino/auth/PrincipalMapper.java
@@ -20,6 +20,7 @@
package org.apache.gravitino.auth;
import java.security.Principal;
+import org.apache.gravitino.Config;
/**
* Interface for mapping authenticated principals to user identities.
@@ -29,6 +30,16 @@ import java.security.Principal;
*/
public interface PrincipalMapper {
+ /**
+ * Initializes the mapper with server configuration. Called by the factory
after instantiation.
+ *
+ * <p>Custom implementations can override this to read additional
configuration properties. The
+ * default implementation is a no-op for backward compatibility.
+ *
+ * @param config the server configuration
+ */
+ default void initialize(Config config) {}
+
/**
* Maps a principal string to a Principal object.
*
diff --git
a/core/src/main/java/org/apache/gravitino/auth/PrincipalMapperFactory.java
b/core/src/main/java/org/apache/gravitino/auth/PrincipalMapperFactory.java
index 01439fd020..613b48de51 100644
--- a/core/src/main/java/org/apache/gravitino/auth/PrincipalMapperFactory.java
+++ b/core/src/main/java/org/apache/gravitino/auth/PrincipalMapperFactory.java
@@ -19,6 +19,8 @@
package org.apache.gravitino.auth;
+import org.apache.gravitino.Config;
+
/** Factory class for creating {@link PrincipalMapper} instances. */
public class PrincipalMapperFactory {
@@ -30,27 +32,31 @@ public class PrincipalMapperFactory {
* @param mapperType "regex" for built-in regex mapper, or fully qualified
class name for custom
* mapper
* @param regexPattern the regex pattern (only used when mapperType is
"regex")
+ * @param config the server configuration passed to {@link
PrincipalMapper#initialize(Config)}
* @return a configured PrincipalMapper instance
* @throws IllegalArgumentException if the mapper cannot be created
*/
- public static PrincipalMapper create(String mapperType, String regexPattern)
{
+ public static PrincipalMapper create(String mapperType, String regexPattern,
Config config) {
+ PrincipalMapper mapper;
if ("regex".equalsIgnoreCase(mapperType)) {
- return new RegexPrincipalMapper(regexPattern);
- }
-
- // Load custom mapper class
- try {
- Class<?> clazz = Class.forName(mapperType);
- if (!PrincipalMapper.class.isAssignableFrom(clazz)) {
+ mapper = new RegexPrincipalMapper(regexPattern);
+ } else {
+ // Load custom mapper class
+ try {
+ Class<?> clazz = Class.forName(mapperType);
+ if (!PrincipalMapper.class.isAssignableFrom(clazz)) {
+ throw new IllegalArgumentException(
+ "Class " + mapperType + " does not implement PrincipalMapper");
+ }
+ mapper = (PrincipalMapper)
clazz.getDeclaredConstructor().newInstance();
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException("Unknown principal mapper type: " +
mapperType, e);
+ } catch (Exception e) {
throw new IllegalArgumentException(
- "Class " + mapperType + " does not implement PrincipalMapper");
+ "Failed to instantiate principal mapper: " + mapperType, e);
}
- return (PrincipalMapper) clazz.getDeclaredConstructor().newInstance();
- } catch (ClassNotFoundException e) {
- throw new IllegalArgumentException("Unknown principal mapper type: " +
mapperType, e);
- } catch (Exception e) {
- throw new IllegalArgumentException(
- "Failed to instantiate principal mapper: " + mapperType, e);
}
+ mapper.initialize(config);
+ return mapper;
}
}
diff --git
a/core/src/test/java/org/apache/gravitino/auth/TestGroupMapperFactory.java
b/core/src/test/java/org/apache/gravitino/auth/TestGroupMapperFactory.java
index 35dc34c8e5..6b7dbc6b29 100644
--- a/core/src/test/java/org/apache/gravitino/auth/TestGroupMapperFactory.java
+++ b/core/src/test/java/org/apache/gravitino/auth/TestGroupMapperFactory.java
@@ -29,14 +29,17 @@ import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
+import org.apache.gravitino.Config;
import org.apache.gravitino.UserGroup;
import org.junit.jupiter.api.Test;
public class TestGroupMapperFactory {
+ private final Config config = new Config(false) {};
+
@Test
public void testCreateRegexMapper() {
- GroupMapper mapper = GroupMapperFactory.create("regex", "group-(.*)");
+ GroupMapper mapper = GroupMapperFactory.create("regex", "group-(.*)",
config);
assertNotNull(mapper);
assertTrue(mapper instanceof RegexGroupMapper);
@@ -53,7 +56,7 @@ public class TestGroupMapperFactory {
@Test
public void testCreateRegexMapperWithDefaultPattern() {
- GroupMapper mapper = GroupMapperFactory.create("regex", "^(.*)$");
+ GroupMapper mapper = GroupMapperFactory.create("regex", "^(.*)$", config);
assertNotNull(mapper);
assertTrue(mapper instanceof RegexGroupMapper);
@@ -70,7 +73,7 @@ public class TestGroupMapperFactory {
@Test
public void testCreateRegexMapperWithSlash() {
- GroupMapper mapper = GroupMapperFactory.create("regex", "/(.*)");
+ GroupMapper mapper = GroupMapperFactory.create("regex", "/(.*)", config);
assertNotNull(mapper);
assertTrue(mapper instanceof RegexGroupMapper);
@@ -91,12 +94,21 @@ public class TestGroupMapperFactory {
assertThrows(
IllegalArgumentException.class,
() -> {
- GroupMapperFactory.create("unknown.InvalidClass", null);
+ GroupMapperFactory.create("unknown.InvalidClass", null, config);
});
assertTrue(exception.getMessage().contains("Failed to load GroupMapper
class"));
}
public static class TestCustomGroupMapper implements GroupMapper {
+ private boolean initialized = false;
+ private Config receivedConfig;
+
+ @Override
+ public void initialize(Config config) {
+ this.initialized = true;
+ this.receivedConfig = config;
+ }
+
@Override
public List<UserGroup> map(List<Object> groups) {
if (groups == null) {
@@ -106,12 +118,16 @@ public class TestGroupMapperFactory {
.map(g -> new UserGroup(Optional.empty(), "custom:" + g.toString()))
.collect(Collectors.toList());
}
+
+ public boolean isInitialized() {
+ return initialized;
+ }
}
@Test
public void testCreateCustomMapperWithInlineClass() {
String className = TestCustomGroupMapper.class.getName();
- GroupMapper mapper = GroupMapperFactory.create(className, null);
+ GroupMapper mapper = GroupMapperFactory.create(className, null, config);
assertNotNull(mapper);
assertTrue(mapper instanceof TestCustomGroupMapper);
@@ -122,4 +138,13 @@ public class TestGroupMapperFactory {
assertEquals(1, mappedGroups.size());
assertEquals("custom:foo", mappedGroups.get(0).getGroupname());
}
+
+ @Test
+ public void testCustomMapperInitializeCalledWithConfig() {
+ String className = TestCustomGroupMapper.class.getName();
+ GroupMapper mapper = GroupMapperFactory.create(className, null, config);
+ TestCustomGroupMapper custom = (TestCustomGroupMapper) mapper;
+ assertTrue(custom.isInitialized());
+ assertEquals(config, custom.receivedConfig);
+ }
}
diff --git
a/core/src/test/java/org/apache/gravitino/auth/TestPrincipalMapperFactory.java
b/core/src/test/java/org/apache/gravitino/auth/TestPrincipalMapperFactory.java
index 117e6167a8..9b0a024cfe 100644
---
a/core/src/test/java/org/apache/gravitino/auth/TestPrincipalMapperFactory.java
+++
b/core/src/test/java/org/apache/gravitino/auth/TestPrincipalMapperFactory.java
@@ -25,14 +25,17 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.security.Principal;
+import org.apache.gravitino.Config;
import org.apache.gravitino.UserPrincipal;
import org.junit.jupiter.api.Test;
public class TestPrincipalMapperFactory {
+ private final Config config = new Config(false) {};
+
@Test
public void testCreateRegexMapper() {
- PrincipalMapper mapper = PrincipalMapperFactory.create("regex",
"([^@]+)@.*");
+ PrincipalMapper mapper = PrincipalMapperFactory.create("regex",
"([^@]+)@.*", config);
assertNotNull(mapper);
assertTrue(mapper instanceof RegexPrincipalMapper);
@@ -43,7 +46,7 @@ public class TestPrincipalMapperFactory {
@Test
public void testCreateRegexMapperWithDefaultPattern() {
- PrincipalMapper mapper = PrincipalMapperFactory.create("regex", "^(.*)$");
+ PrincipalMapper mapper = PrincipalMapperFactory.create("regex", "^(.*)$",
config);
assertNotNull(mapper);
assertTrue(mapper instanceof RegexPrincipalMapper);
@@ -59,25 +62,47 @@ public class TestPrincipalMapperFactory {
assertThrows(
IllegalArgumentException.class,
() -> {
- PrincipalMapperFactory.create("unknown.InvalidClass", null);
+ PrincipalMapperFactory.create("unknown.InvalidClass", null,
config);
});
assertTrue(exception.getMessage().contains("Unknown principal mapper
type"));
}
public static class TestCustomMapper implements PrincipalMapper {
+ private boolean initialized = false;
+ private Config receivedConfig;
+
+ @Override
+ public void initialize(Config config) {
+ this.initialized = true;
+ this.receivedConfig = config;
+ }
+
@Override
public Principal map(String principal) {
return new UserPrincipal("custom:" + principal);
}
+
+ public boolean isInitialized() {
+ return initialized;
+ }
}
@Test
public void testCreateCustomMapperWithInlineClass() {
String className = TestCustomMapper.class.getName();
- PrincipalMapper mapper = PrincipalMapperFactory.create(className, null);
+ PrincipalMapper mapper = PrincipalMapperFactory.create(className, null,
config);
assertNotNull(mapper);
assertTrue(mapper instanceof TestCustomMapper);
Principal principal = mapper.map("foo");
assertEquals("custom:foo", principal.getName());
}
+
+ @Test
+ public void testCustomMapperInitializeCalledWithConfig() {
+ String className = TestCustomMapper.class.getName();
+ PrincipalMapper mapper = PrincipalMapperFactory.create(className, null,
config);
+ TestCustomMapper custom = (TestCustomMapper) mapper;
+ assertTrue(custom.isInitialized());
+ assertEquals(config, custom.receivedConfig);
+ }
}
diff --git
a/server-common/src/main/java/org/apache/gravitino/server/authentication/JwksTokenValidator.java
b/server-common/src/main/java/org/apache/gravitino/server/authentication/JwksTokenValidator.java
index cdbf294357..32e47b84e1 100644
---
a/server-common/src/main/java/org/apache/gravitino/server/authentication/JwksTokenValidator.java
+++
b/server-common/src/main/java/org/apache/gravitino/server/authentication/JwksTokenValidator.java
@@ -78,12 +78,12 @@ public class JwksTokenValidator implements
OAuthTokenValidator {
// Create principal mapper based on configuration
String mapperType = config.get(OAuthConfig.PRINCIPAL_MAPPER);
String regexPattern =
config.get(OAuthConfig.PRINCIPAL_MAPPER_REGEX_PATTERN);
- this.principalMapper = PrincipalMapperFactory.create(mapperType,
regexPattern);
+ this.principalMapper = PrincipalMapperFactory.create(mapperType,
regexPattern, config);
// Create group mapper based on configuration
String groupMapperType = config.get(OAuthConfig.GROUP_MAPPER);
String groupRegexPattern =
config.get(OAuthConfig.GROUP_MAPPER_REGEX_PATTERN);
- this.groupMapper = GroupMapperFactory.create(groupMapperType,
groupRegexPattern);
+ this.groupMapper = GroupMapperFactory.create(groupMapperType,
groupRegexPattern, config);
LOG.info("Initializing JWKS token validator");
diff --git
a/server-common/src/main/java/org/apache/gravitino/server/authentication/KerberosAuthenticator.java
b/server-common/src/main/java/org/apache/gravitino/server/authentication/KerberosAuthenticator.java
index 801133834f..5f10b1bd56 100644
---
a/server-common/src/main/java/org/apache/gravitino/server/authentication/KerberosAuthenticator.java
+++
b/server-common/src/main/java/org/apache/gravitino/server/authentication/KerberosAuthenticator.java
@@ -81,7 +81,7 @@ public class KerberosAuthenticator implements Authenticator {
// "HTTP/host" from "HTTP/host@REALM")
String mapperType = config.get(KerberosConfig.PRINCIPAL_MAPPER);
String regexPattern =
config.get(KerberosConfig.PRINCIPAL_MAPPER_REGEX_PATTERN);
- this.principalMapper = PrincipalMapperFactory.create(mapperType,
regexPattern);
+ this.principalMapper = PrincipalMapperFactory.create(mapperType,
regexPattern, config);
gssManager =
Subject.doAs(
diff --git
a/server-common/src/main/java/org/apache/gravitino/server/authentication/StaticSignKeyValidator.java
b/server-common/src/main/java/org/apache/gravitino/server/authentication/StaticSignKeyValidator.java
index efc857041e..611712e84d 100644
---
a/server-common/src/main/java/org/apache/gravitino/server/authentication/StaticSignKeyValidator.java
+++
b/server-common/src/main/java/org/apache/gravitino/server/authentication/StaticSignKeyValidator.java
@@ -85,12 +85,12 @@ public class StaticSignKeyValidator implements
OAuthTokenValidator {
// Create principal mapper based on configuration
String mapperType = config.get(OAuthConfig.PRINCIPAL_MAPPER);
String regexPattern =
config.get(OAuthConfig.PRINCIPAL_MAPPER_REGEX_PATTERN);
- this.principalMapper = PrincipalMapperFactory.create(mapperType,
regexPattern);
+ this.principalMapper = PrincipalMapperFactory.create(mapperType,
regexPattern, config);
// Create group mapper based on configuration
String groupMapperType = config.get(OAuthConfig.GROUP_MAPPER);
String groupRegexPattern =
config.get(OAuthConfig.GROUP_MAPPER_REGEX_PATTERN);
- this.groupMapper = GroupMapperFactory.create(groupMapperType,
groupRegexPattern);
+ this.groupMapper = GroupMapperFactory.create(groupMapperType,
groupRegexPattern, config);
}
@Override