This is an automated email from the ASF dual-hosted git repository.
jackie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pinot.git
The following commit(s) were added to refs/heads/master by this push:
new 7f5a8ae568 Provide user access to all tables except tableX (#14839)
7f5a8ae568 is described below
commit 7f5a8ae568b5127b42abaed4c8bd2cbe13766fd9
Author: Daniil Roman <[email protected]>
AuthorDate: Thu Feb 20 18:38:03 2025 +0100
Provide user access to all tables except tableX (#14839)
---
.../utils/config/AccessControlUserConfigUtils.java | 7 +++-
.../helix/core/PinotHelixResourceManager.java | 10 +++--
.../apache/pinot/core/auth/BasicAuthPrincipal.java | 13 ++++++-
.../org/apache/pinot/core/auth/BasicAuthUtils.java | 9 ++++-
.../pinot/core/auth/ZkBasicAuthPrincipal.java | 4 +-
.../org/apache/pinot/core/auth/BasicAuthTest.java | 43 +++++++++++++++-------
.../apache/pinot/core/auth/ZkBasicAuthTest.java | 29 ++++++++++-----
.../apache/pinot/spi/config/user/UserConfig.java | 11 ++++++
.../pinot/spi/utils/builder/UserConfigBuilder.java | 8 +++-
9 files changed, 99 insertions(+), 35 deletions(-)
diff --git
a/pinot-common/src/main/java/org/apache/pinot/common/utils/config/AccessControlUserConfigUtils.java
b/pinot-common/src/main/java/org/apache/pinot/common/utils/config/AccessControlUserConfigUtils.java
index a31439cb2c..b910ca6187 100644
---
a/pinot-common/src/main/java/org/apache/pinot/common/utils/config/AccessControlUserConfigUtils.java
+++
b/pinot-common/src/main/java/org/apache/pinot/common/utils/config/AccessControlUserConfigUtils.java
@@ -46,6 +46,7 @@ public class AccessControlUserConfigUtils {
String role = simpleFields.get(UserConfig.ROLE_KEY);
List<String> tableList = znRecord.getListField(UserConfig.TABLES_KEY);
+ List<String> excludeTableList =
znRecord.getListField(UserConfig.EXCLUDE_TABLES_KEY);
List<String> permissionListFromZNRecord =
znRecord.getListField(UserConfig.PERMISSIONS_KEY);
List<AccessType> permissionList = null;
@@ -53,7 +54,7 @@ public class AccessControlUserConfigUtils {
permissionList = permissionListFromZNRecord.stream()
.map(x -> AccessType.valueOf(x)).collect(Collectors.toList());
}
- return new UserConfig(username, password, component, role, tableList,
permissionList);
+ return new UserConfig(username, password, component, role, tableList,
excludeTableList, permissionList);
}
public static ZNRecord toZNRecord(UserConfig userConfig)
@@ -73,6 +74,10 @@ public class AccessControlUserConfigUtils {
if (tableList != null) {
listFields.put(UserConfig.TABLES_KEY, userConfig.getTables());
}
+ List<String> excludeTableList = userConfig.getExcludeTables();
+ if (excludeTableList != null) {
+ listFields.put(UserConfig.EXCLUDE_TABLES_KEY,
userConfig.getExcludeTables());
+ }
List<AccessType> permissionList = userConfig.getPermissios();
if (permissionList != null) {
diff --git
a/pinot-controller/src/main/java/org/apache/pinot/controller/helix/core/PinotHelixResourceManager.java
b/pinot-controller/src/main/java/org/apache/pinot/controller/helix/core/PinotHelixResourceManager.java
index fd36bf44ea..5351d48063 100644
---
a/pinot-controller/src/main/java/org/apache/pinot/controller/helix/core/PinotHelixResourceManager.java
+++
b/pinot-controller/src/main/java/org/apache/pinot/controller/helix/core/PinotHelixResourceManager.java
@@ -1670,12 +1670,14 @@ public class PinotHelixResourceManager {
if
(CollectionUtils.isEmpty(ZKMetadataProvider.getAllUserName(_propertyStore))) {
String initUsername = controllerConf.getInitAccessControlUsername();
String initPassword = controllerConf.getInitAccessControlPassword();
- addUser(new UserConfig(initUsername, initPassword,
ComponentType.CONTROLLER.name(), RoleType.ADMIN.name(), null,
- null));
+ addUser(new UserConfig(initUsername, initPassword,
ComponentType.CONTROLLER.name(), RoleType.ADMIN.name(),
+ null, null, null));
addUser(
- new UserConfig(initUsername, initPassword,
ComponentType.BROKER.name(), RoleType.ADMIN.name(), null, null));
+ new UserConfig(initUsername, initPassword,
ComponentType.BROKER.name(), RoleType.ADMIN.name(),
+ null, null, null));
addUser(
- new UserConfig(initUsername, initPassword,
ComponentType.SERVER.name(), RoleType.ADMIN.name(), null, null));
+ new UserConfig(initUsername, initPassword,
ComponentType.SERVER.name(), RoleType.ADMIN.name(),
+ null, null, null));
}
}
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/auth/BasicAuthPrincipal.java
b/pinot-core/src/main/java/org/apache/pinot/core/auth/BasicAuthPrincipal.java
index 20831a0257..f53fd8c495 100644
---
a/pinot-core/src/main/java/org/apache/pinot/core/auth/BasicAuthPrincipal.java
+++
b/pinot-core/src/main/java/org/apache/pinot/core/auth/BasicAuthPrincipal.java
@@ -29,12 +29,15 @@ public class BasicAuthPrincipal {
private final String _name;
private final String _token;
private final Set<String> _tables;
+ private final Set<String> _excludeTables;
private final Set<String> _permissions;
- public BasicAuthPrincipal(String name, String token, Set<String> tables,
Set<String> permissions) {
+ public BasicAuthPrincipal(String name, String token, Set<String> tables,
Set<String> excludeTables,
+ Set<String> permissions) {
_name = name;
_token = token;
_tables = tables;
+ _excludeTables = excludeTables;
_permissions = permissions.stream().map(s ->
s.toLowerCase()).collect(Collectors.toSet());
}
@@ -47,9 +50,17 @@ public class BasicAuthPrincipal {
}
public boolean hasTable(String tableName) {
+ return isTableIncluded(tableName) && isTableNotExcluded(tableName);
+ }
+
+ private boolean isTableIncluded(String tableName) {
return _tables.isEmpty() || _tables.contains(tableName);
}
+ private boolean isTableNotExcluded(String tableName) {
+ return !_excludeTables.contains(tableName);
+ }
+
public boolean hasPermission(String permission) {
return _permissions.isEmpty() ||
_permissions.contains(permission.toLowerCase());
}
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/auth/BasicAuthUtils.java
b/pinot-core/src/main/java/org/apache/pinot/core/auth/BasicAuthUtils.java
index ab4caa91b3..94f6b6bd95 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/auth/BasicAuthUtils.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/auth/BasicAuthUtils.java
@@ -37,6 +37,7 @@ public final class BasicAuthUtils {
private static final String PASSWORD = "password";
private static final String PERMISSIONS = "permissions";
private static final String TABLES = "tables";
+ private static final String EXCLUDE_TABLES = "excludeTables";
private static final String ALL = "*";
private BasicAuthUtils() {
@@ -72,10 +73,11 @@ public final class BasicAuthUtils {
Preconditions.checkArgument(StringUtils.isNotBlank(password), "must
provide a password for %s", name);
Set<String> tables = extractSet(configuration, prefix + "." + name + "."
+ TABLES);
+ Set<String> excludeTables = extractSet(configuration, prefix + "." +
name + "." + EXCLUDE_TABLES);
Set<String> permissions = extractSet(configuration, prefix + "." + name
+ "." + PERMISSIONS);
return new BasicAuthPrincipal(name,
org.apache.pinot.common.auth.BasicAuthUtils.toBasicAuthToken(name, password),
- tables, permissions);
+ tables, excludeTables, permissions);
}).collect(Collectors.toList());
}
@@ -92,13 +94,16 @@ public final class BasicAuthUtils {
Set<String> tables = Optional.ofNullable(user.getTables())
.orElseGet(() -> Collections.emptyList())
.stream().collect(Collectors.toSet());
+ Set<String> excludeTables =
Optional.ofNullable(user.getExcludeTables())
+ .orElseGet(() -> Collections.emptyList())
+ .stream().collect(Collectors.toSet());
Set<String> permissions = Optional.ofNullable(user.getPermissios())
.orElseGet(() -> Collections.emptyList())
.stream().map(x -> x.toString())
.collect(Collectors.toSet());
return new ZkBasicAuthPrincipal(name,
org.apache.pinot.common.auth.BasicAuthUtils.toBasicAuthToken(name, password),
password,
- component, role, tables, permissions);
+ component, role, tables, excludeTables, permissions);
}).collect(Collectors.toList());
}
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/auth/ZkBasicAuthPrincipal.java
b/pinot-core/src/main/java/org/apache/pinot/core/auth/ZkBasicAuthPrincipal.java
index 93f97943ce..a4ee23e035 100644
---
a/pinot-core/src/main/java/org/apache/pinot/core/auth/ZkBasicAuthPrincipal.java
+++
b/pinot-core/src/main/java/org/apache/pinot/core/auth/ZkBasicAuthPrincipal.java
@@ -31,8 +31,8 @@ public class ZkBasicAuthPrincipal extends BasicAuthPrincipal {
private final String _role;
public ZkBasicAuthPrincipal(String name, String token, String password,
String component, String role,
- Set<String> tables, Set<String> permissions) {
- super(name, token, tables, permissions);
+ Set<String> tables, Set<String> excludeTables, Set<String>
permissions) {
+ super(name, token, tables, excludeTables, permissions);
_component = component;
_role = role;
_password = password;
diff --git
a/pinot-core/src/test/java/org/apache/pinot/core/auth/BasicAuthTest.java
b/pinot-core/src/test/java/org/apache/pinot/core/auth/BasicAuthTest.java
index bcadc8b886..20897c8ee7 100644
--- a/pinot-core/src/test/java/org/apache/pinot/core/auth/BasicAuthTest.java
+++ b/pinot-core/src/test/java/org/apache/pinot/core/auth/BasicAuthTest.java
@@ -19,6 +19,7 @@
package org.apache.pinot.core.auth;
import com.google.common.collect.ImmutableSet;
+import java.util.Collections;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -26,26 +27,40 @@ import org.testng.annotations.Test;
public class BasicAuthTest {
@Test
- public void testBasicAuthPrincipal()
- throws Exception {
- Assert.assertTrue(new BasicAuthPrincipal("name", "token",
ImmutableSet.of("myTable"), ImmutableSet.of("READ"))
+ public void testBasicAuthPrincipal() {
+ Assert.assertTrue(new BasicAuthPrincipal("name", "token",
ImmutableSet.of("myTable"), Collections.emptySet(),
+ ImmutableSet.of("READ"))
.hasTable("myTable"));
- Assert.assertTrue(
- new BasicAuthPrincipal("name", "token", ImmutableSet.of("myTable",
"myTable1"), ImmutableSet.of("Read"))
- .hasTable("myTable1"));
- Assert.assertFalse(new BasicAuthPrincipal("name", "token",
ImmutableSet.of("myTable"), ImmutableSet.of("read"))
+ Assert.assertTrue(new BasicAuthPrincipal("name", "token",
ImmutableSet.of("myTable", "myTable1"),
+ Collections.emptySet(), ImmutableSet.of("Read"))
.hasTable("myTable1"));
- Assert.assertFalse(
- new BasicAuthPrincipal("name", "token", ImmutableSet.of("myTable",
"myTable1"), ImmutableSet.of("read"))
- .hasTable("myTable2"));
+ Assert.assertFalse(new BasicAuthPrincipal("name", "token",
ImmutableSet.of("myTable"), Collections.emptySet(),
+ ImmutableSet.of("read"))
+ .hasTable("myTable1"));
+ Assert.assertFalse(new BasicAuthPrincipal("name", "token",
ImmutableSet.of("myTable", "myTable1"),
+ Collections.emptySet(), ImmutableSet.of("read"))
+ .hasTable("myTable2"));
+ Assert.assertFalse(new BasicAuthPrincipal("name", "token",
ImmutableSet.of("myTable"), ImmutableSet.of("myTable"),
+ ImmutableSet.of("read"))
+ .hasTable("myTable"));
+ Assert.assertFalse(new BasicAuthPrincipal("name", "token",
Collections.emptySet(), ImmutableSet.of("myTable"),
+ ImmutableSet.of("read"))
+ .hasTable("myTable"));
+ Assert.assertTrue(new BasicAuthPrincipal("name", "token",
ImmutableSet.of("myTable"), ImmutableSet.of("myTable1"),
+ ImmutableSet.of("read"))
+ .hasTable("myTable"));
- Assert.assertTrue(new BasicAuthPrincipal("name", "token",
ImmutableSet.of("myTable"), ImmutableSet.of("READ"))
+ Assert.assertTrue(new BasicAuthPrincipal("name", "token",
ImmutableSet.of("myTable"), Collections.emptySet(),
+ ImmutableSet.of("READ"))
.hasPermission("read"));
- Assert.assertTrue(new BasicAuthPrincipal("name", "token",
ImmutableSet.of("myTable"), ImmutableSet.of("Read"))
+ Assert.assertTrue(new BasicAuthPrincipal("name", "token",
ImmutableSet.of("myTable"), Collections.emptySet(),
+ ImmutableSet.of("Read"))
.hasPermission("READ"));
- Assert.assertTrue(new BasicAuthPrincipal("name", "token",
ImmutableSet.of("myTable"), ImmutableSet.of("read"))
+ Assert.assertTrue(new BasicAuthPrincipal("name", "token",
ImmutableSet.of("myTable"), Collections.emptySet(),
+ ImmutableSet.of("read"))
.hasPermission("Read"));
- Assert.assertFalse(new BasicAuthPrincipal("name", "token",
ImmutableSet.of("myTable"), ImmutableSet.of("read"))
+ Assert.assertFalse(new BasicAuthPrincipal("name", "token",
ImmutableSet.of("myTable"), Collections.emptySet(),
+ ImmutableSet.of("read"))
.hasPermission("write"));
}
}
diff --git
a/pinot-core/src/test/java/org/apache/pinot/core/auth/ZkBasicAuthTest.java
b/pinot-core/src/test/java/org/apache/pinot/core/auth/ZkBasicAuthTest.java
index 274505a543..8ddecec764 100644
--- a/pinot-core/src/test/java/org/apache/pinot/core/auth/ZkBasicAuthTest.java
+++ b/pinot-core/src/test/java/org/apache/pinot/core/auth/ZkBasicAuthTest.java
@@ -19,6 +19,7 @@
package org.apache.pinot.core.auth;
import com.google.common.collect.ImmutableSet;
+import java.util.Collections;
import org.apache.pinot.spi.config.user.ComponentType;
import org.apache.pinot.spi.config.user.RoleType;
import org.testng.Assert;
@@ -28,32 +29,40 @@ import org.testng.annotations.Test;
public class ZkBasicAuthTest {
@Test
- public void testBasicAuthPrincipal()
- throws Exception {
+ public void testBasicAuthPrincipal() {
Assert.assertTrue(new ZkBasicAuthPrincipal("name", "token", "password",
ComponentType.CONTROLLER.name(), RoleType.ADMIN.name(),
ImmutableSet.of("myTable"),
- ImmutableSet.of("READ")).hasTable("myTable"));
+ Collections.emptySet(),
ImmutableSet.of("READ")).hasTable("myTable"));
Assert.assertTrue(new ZkBasicAuthPrincipal("name", "token", "password",
ComponentType.CONTROLLER.name(), RoleType.ADMIN.name(),
ImmutableSet.of("myTable", "myTable1"),
- ImmutableSet.of("Read")).hasTable("myTable1"));
+ Collections.emptySet(),
ImmutableSet.of("Read")).hasTable("myTable1"));
Assert.assertFalse(new ZkBasicAuthPrincipal("name", "token",
"password",
ComponentType.CONTROLLER.name(), RoleType.ADMIN.name(),
ImmutableSet.of("myTable"),
- ImmutableSet.of("read")).hasTable("myTable1"));
+ Collections.emptySet(),
ImmutableSet.of("read")).hasTable("myTable1"));
Assert.assertFalse(new ZkBasicAuthPrincipal("name", "token",
"password",
ComponentType.CONTROLLER.name(), RoleType.ADMIN.name(),
ImmutableSet.of("myTable", "myTable1"),
- ImmutableSet.of("read")).hasTable("myTable2"));
+ Collections.emptySet(),
ImmutableSet.of("read")).hasTable("myTable2"));
+ Assert.assertFalse(new ZkBasicAuthPrincipal("name", "token",
"password",
+ ComponentType.CONTROLLER.name(), RoleType.ADMIN.name(),
ImmutableSet.of("myTable", "myTable1"),
+ ImmutableSet.of("myTable3"),
ImmutableSet.of("Read")).hasTable("myTable3"));
+ Assert.assertTrue(new ZkBasicAuthPrincipal("name", "token", "password",
+ ComponentType.CONTROLLER.name(), RoleType.ADMIN.name(),
ImmutableSet.of("myTable", "myTable1"),
+ ImmutableSet.of("myTable"),
ImmutableSet.of("read")).hasTable("myTable1"));
+ Assert.assertFalse(new ZkBasicAuthPrincipal("name", "token",
"password",
+ ComponentType.CONTROLLER.name(), RoleType.ADMIN.name(),
Collections.emptySet(),
+ ImmutableSet.of("myTable"),
ImmutableSet.of("read")).hasTable("myTable"));
Assert.assertTrue(new ZkBasicAuthPrincipal("name", "token", "password",
ComponentType.CONTROLLER.name(), RoleType.ADMIN.name(),
ImmutableSet.of("myTable"),
- ImmutableSet.of("READ")).hasPermission("read"));
+ Collections.emptySet(),
ImmutableSet.of("READ")).hasPermission("read"));
Assert.assertTrue(new ZkBasicAuthPrincipal("name", "token", "password",
ComponentType.CONTROLLER.name(), RoleType.ADMIN.name(),
ImmutableSet.of("myTable"),
- ImmutableSet.of("Read")).hasPermission("READ"));
+ Collections.emptySet(),
ImmutableSet.of("Read")).hasPermission("READ"));
Assert.assertTrue(new ZkBasicAuthPrincipal("name", "token", "password",
ComponentType.CONTROLLER.name(), RoleType.ADMIN.name(),
ImmutableSet.of("myTable"),
- ImmutableSet.of("read")).hasPermission("Read"));
+ Collections.emptySet(),
ImmutableSet.of("read")).hasPermission("Read"));
Assert.assertFalse(new ZkBasicAuthPrincipal("name", "token",
"password",
ComponentType.CONTROLLER.name(), RoleType.ADMIN.name(),
ImmutableSet.of("myTable"),
- ImmutableSet.of("read")).hasPermission("write"));
+ Collections.emptySet(),
ImmutableSet.of("read")).hasPermission("write"));
}
}
diff --git
a/pinot-spi/src/main/java/org/apache/pinot/spi/config/user/UserConfig.java
b/pinot-spi/src/main/java/org/apache/pinot/spi/config/user/UserConfig.java
index bfe9d0a8c9..cd05cd7d83 100644
--- a/pinot-spi/src/main/java/org/apache/pinot/spi/config/user/UserConfig.java
+++ b/pinot-spi/src/main/java/org/apache/pinot/spi/config/user/UserConfig.java
@@ -35,6 +35,7 @@ public class UserConfig extends BaseJsonConfig {
public static final String ROLE_KEY = "role";
public static final String AUTH_TOKEN_KEY = "authToken";
public static final String TABLES_KEY = "tables";
+ public static final String EXCLUDE_TABLES_KEY = "excludeTables";
public static final String PERMISSIONS_KEY = "permissions";
@JsonPropertyDescription("The name of User")
@@ -52,6 +53,9 @@ public class UserConfig extends BaseJsonConfig {
@JsonPropertyDescription("The tables owned of User")
private List<String> _tables;
+ @JsonPropertyDescription("The tables excluded for User")
+ private List<String> _excludeTables;
+
@JsonPropertyDescription("The table permission of User")
private List<AccessType> _permissions;
@@ -61,6 +65,7 @@ public class UserConfig extends BaseJsonConfig {
@JsonProperty(value = COMPONET_KEY, required = true) String component,
@JsonProperty(value = ROLE_KEY, required = true) String role,
@JsonProperty(value = TABLES_KEY) @Nullable List<String> tableList,
+ @JsonProperty(value = EXCLUDE_TABLES_KEY) @Nullable List<String>
excludeTableList,
@JsonProperty(value = PERMISSIONS_KEY) @Nullable List<AccessType>
permissionList
) {
Preconditions.checkArgument(username != null, "'username' must be
configured");
@@ -72,6 +77,7 @@ public class UserConfig extends BaseJsonConfig {
_componentType = ComponentType.valueOf(component.toUpperCase());
_roleType = RoleType.valueOf(role.toUpperCase());
_tables = tableList;
+ _excludeTables = excludeTableList;
_permissions = permissionList;
}
@@ -98,6 +104,11 @@ public class UserConfig extends BaseJsonConfig {
return _tables;
}
+ @JsonProperty(EXCLUDE_TABLES_KEY)
+ public List<String> getExcludeTables() {
+ return _excludeTables;
+ }
+
@JsonProperty(PERMISSIONS_KEY)
public List<AccessType> getPermissios() {
return _permissions;
diff --git
a/pinot-spi/src/main/java/org/apache/pinot/spi/utils/builder/UserConfigBuilder.java
b/pinot-spi/src/main/java/org/apache/pinot/spi/utils/builder/UserConfigBuilder.java
index 5afbf639ac..c2c70c9f75 100644
---
a/pinot-spi/src/main/java/org/apache/pinot/spi/utils/builder/UserConfigBuilder.java
+++
b/pinot-spi/src/main/java/org/apache/pinot/spi/utils/builder/UserConfigBuilder.java
@@ -31,6 +31,7 @@ public class UserConfigBuilder {
private String _password;
private RoleType _roleType;
private List<String> _tableList;
+ private List<String> _excludeTableList;
private List<AccessType> _permissionList;
public UserConfigBuilder setComponentType(ComponentType componentType) {
@@ -58,6 +59,11 @@ public class UserConfigBuilder {
return this;
}
+ public UserConfigBuilder setExcludeTableList(List<String>
excludeTableList) {
+ _excludeTableList = excludeTableList;
+ return this;
+ }
+
public UserConfigBuilder setPermissionList(List<AccessType>
permissionList) {
_permissionList = permissionList;
return this;
@@ -65,6 +71,6 @@ public class UserConfigBuilder {
public UserConfig build() {
return new UserConfig(_username, _password, _componentType.toString(),
_roleType.toString(), _tableList,
- _permissionList);
+ _excludeTableList, _permissionList);
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]