From 2c3c29c41ac9295c47b0862e357528b20e1a9a32 Mon Sep 17 00:00:00 2001 From: Harbor Liu <460660596@qq.com> Date: Fri, 21 Feb 2025 16:59:52 +0800 Subject: [PATCH] Support Group Provider Signed-off-by: HangyuanLiu <460660596@qq.com> --- .../authentication/AuthenticationMgr.java | 60 +++++++++ .../authentication/FileGroupProvider.java | 125 ++++++++++++++++++ .../authentication/GroupProvider.java | 65 +++++++++ .../authentication/GroupProviderFactory.java | 50 +++++++ .../com/starrocks/authentication/JwkMgr.java | 20 ++- .../OpenIdConnectAuthenticationProvider.java | 19 ++- .../SecurityIntegrationFactory.java | 1 - .../authentication/UnixGroupProvider.java | 49 +++++++ .../java/com/starrocks/persist/EditLog.java | 11 ++ .../persist/EditLogDeserializer.java | 2 + .../starrocks/persist/GroupProviderLog.java | 43 ++++++ .../com/starrocks/persist/OperationType.java | 6 + .../com/starrocks/persist/gson/GsonUtils.java | 9 ++ .../com/starrocks/qe/DDLStmtExecutor.java | 18 +++ .../java/com/starrocks/qe/ShowExecutor.java | 51 +++++++ .../com/starrocks/sql/analyzer/Analyzer.java | 30 +++++ .../GroupProviderStatementAnalyzer.java | 87 ++++++++++++ .../com/starrocks/sql/ast/AstVisitor.java | 22 +++ .../ast/group/CreateGroupProviderStmt.java | 45 +++++++ .../sql/ast/group/DropGroupProviderStmt.java | 37 ++++++ .../group/ShowCreateGroupProviderStmt.java | 51 +++++++ .../sql/ast/group/ShowGroupProvidersStmt.java | 50 +++++++ .../com/starrocks/sql/parser/AstBuilder.java | 39 ++++++ .../com/starrocks/sql/parser/StarRocks.g4 | 26 +++- .../com/starrocks/sql/parser/StarRocksLex.g4 | 2 + .../R/test_group_provider | 24 ++++ .../T/test_group_provider | 9 ++ 27 files changed, 932 insertions(+), 19 deletions(-) create mode 100644 fe/fe-core/src/main/java/com/starrocks/authentication/FileGroupProvider.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authentication/GroupProvider.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authentication/GroupProviderFactory.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authentication/UnixGroupProvider.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/persist/GroupProviderLog.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/analyzer/GroupProviderStatementAnalyzer.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/ast/group/CreateGroupProviderStmt.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/ast/group/DropGroupProviderStmt.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/ast/group/ShowCreateGroupProviderStmt.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/ast/group/ShowGroupProvidersStmt.java create mode 100644 test/sql/test_security_integration/R/test_group_provider create mode 100644 test/sql/test_security_integration/T/test_group_provider diff --git a/fe/fe-core/src/main/java/com/starrocks/authentication/AuthenticationMgr.java b/fe/fe-core/src/main/java/com/starrocks/authentication/AuthenticationMgr.java index 540d01fee378b..054e32183b1e2 100644 --- a/fe/fe-core/src/main/java/com/starrocks/authentication/AuthenticationMgr.java +++ b/fe/fe-core/src/main/java/com/starrocks/authentication/AuthenticationMgr.java @@ -28,18 +28,23 @@ import com.starrocks.mysql.MysqlPassword; import com.starrocks.mysql.privilege.AuthPlugin; import com.starrocks.persist.EditLog; +import com.starrocks.persist.GroupProviderLog; import com.starrocks.persist.ImageWriter; +import com.starrocks.persist.OperationType; import com.starrocks.persist.metablock.MapEntryConsumer; import com.starrocks.persist.metablock.SRMetaBlockEOFException; import com.starrocks.persist.metablock.SRMetaBlockException; import com.starrocks.persist.metablock.SRMetaBlockID; import com.starrocks.persist.metablock.SRMetaBlockReader; import com.starrocks.persist.metablock.SRMetaBlockWriter; +import com.starrocks.qe.ConnectContext; import com.starrocks.server.GlobalStateMgr; import com.starrocks.sql.analyzer.SemanticException; import com.starrocks.sql.ast.CreateUserStmt; import com.starrocks.sql.ast.DropUserStmt; import com.starrocks.sql.ast.UserIdentity; +import com.starrocks.sql.ast.group.CreateGroupProviderStmt; +import com.starrocks.sql.ast.group.DropGroupProviderStmt; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -48,6 +53,7 @@ import java.net.URL; import java.net.URLClassLoader; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -71,6 +77,9 @@ public class AuthenticationMgr { @SerializedName(value = "m") private Map userNameToProperty = new HashMap<>(); + @SerializedName("gp") + protected Map nameToGroupProviderMap = new ConcurrentHashMap<>(); + @SerializedName("sim") protected Map nameToSecurityIntegrationMap = new ConcurrentHashMap<>(); @@ -658,6 +667,17 @@ public void loadV2(SRMetaBlockReader reader) throws IOException, SRMetaBlockExce this.isLoaded = true; this.userNameToProperty = ret.userNameToProperty; this.userToAuthenticationInfo = ret.userToAuthenticationInfo; + + this.nameToSecurityIntegrationMap = ret.nameToSecurityIntegrationMap; + this.nameToGroupProviderMap = ret.nameToGroupProviderMap; + + for (Map.Entry entry : nameToGroupProviderMap.entrySet()) { + try { + entry.getValue().init(); + } catch (Exception e) { + LOG.error("failed to init group provider", e); + } + } } public UserProperty getUserProperty(String userName) { @@ -757,4 +777,44 @@ public void replayDropSecurityIntegration(String name) throws DdlException { dropSecurityIntegration(name, true); } + + // ---------------------------------------- Group Provider Statement -------------------------------------- + + public void createGroupProviderStatement(CreateGroupProviderStmt stmt, ConnectContext context) throws DdlException { + GroupProvider groupProvider = GroupProviderFactory.createGroupProvider(stmt.getName(), stmt.getPropertyMap()); + groupProvider.init(); + this.nameToGroupProviderMap.put(stmt.getName(), groupProvider); + + GlobalStateMgr.getCurrentState().getEditLog().logEdit(OperationType.OP_CREATE_GROUP_PROVIDER, + new GroupProviderLog(stmt.getName(), stmt.getPropertyMap())); + } + + public void replayCreateGroupProvider(String name, Map properties) { + GroupProvider groupProvider = GroupProviderFactory.createGroupProvider(name, properties); + try { + groupProvider.init(); + this.nameToGroupProviderMap.put(name, groupProvider); + } catch (DdlException e) { + LOG.error("Failed to create group provider '{}'", name, e); + } + } + + public void dropGroupProviderStatement(DropGroupProviderStmt stmt, ConnectContext context) { + this.nameToGroupProviderMap.remove(stmt.getName()); + + GlobalStateMgr.getCurrentState().getEditLog().logEdit(OperationType.OP_DROP_GROUP_PROVIDER, + new GroupProviderLog(stmt.getName(), null)); + } + + public void replayDropGroupProvider(String name) { + this.nameToGroupProviderMap.remove(name); + } + + public List getAllGroupProviders() { + return new ArrayList<>(nameToGroupProviderMap.values()); + } + + public GroupProvider getGroupProvider(String name) { + return nameToGroupProviderMap.get(name); + } } diff --git a/fe/fe-core/src/main/java/com/starrocks/authentication/FileGroupProvider.java b/fe/fe-core/src/main/java/com/starrocks/authentication/FileGroupProvider.java new file mode 100644 index 0000000000000..0057fe0972008 --- /dev/null +++ b/fe/fe-core/src/main/java/com/starrocks/authentication/FileGroupProvider.java @@ -0,0 +1,125 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed 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 +// +// https://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 com.starrocks.authentication; + +import com.starrocks.StarRocksFE; +import com.starrocks.common.DdlException; +import com.starrocks.sql.analyzer.SemanticException; +import com.starrocks.sql.ast.UserIdentity; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.net.URL; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class FileGroupProvider extends GroupProvider { + private static final Logger LOG = LogManager.getLogger(FileGroupProvider.class); + + public static final String TYPE = "file"; + + public static final String GROUP_FILE_URL = "group_file_url"; + + public static final Set REQUIRED_PROPERTIES = new HashSet<>(List.of( + FileGroupProvider.GROUP_FILE_URL)); + + private final Map> userGroups; + + public FileGroupProvider(String name, Map properties) { + super(name, properties); + this.userGroups = new HashMap<>(); + } + + @Override + public void init() throws DdlException { + String groupFileUrl = properties.get(GROUP_FILE_URL); + + try { + InputStream fileInputStream = null; + try { + if (groupFileUrl.startsWith("http://") || groupFileUrl.startsWith("https://")) { + fileInputStream = new URL(groupFileUrl).openStream(); + } else { + String filePath = StarRocksFE.STARROCKS_HOME_DIR + "/conf/" + groupFileUrl; + fileInputStream = new FileInputStream(filePath); + } + + String s = readInputStreamToString(fileInputStream, StandardCharsets.UTF_8); + for (String line : s.split("\r?\n")) { + if (line.trim().isEmpty()) { + continue; + } + + String[] parts = line.split(":"); + String groupName = parts[0]; + String[] users = parts[1].split(","); + + for (String user : users) { + user = user.trim(); + userGroups.putIfAbsent(user, new HashSet<>()); + userGroups.get(user).add(groupName); + } + } + } finally { + if (fileInputStream != null) { + fileInputStream.close(); + } + } + } catch (IOException e) { + throw new DdlException(e.getMessage()); + } + } + + @Override + public Set getGroup(UserIdentity userIdentity) { + return userGroups.getOrDefault(userIdentity.getUser(), new HashSet<>()); + } + + @Override + public void checkProperty() throws SemanticException { + REQUIRED_PROPERTIES.forEach(s -> { + if (!properties.containsKey(s)) { + throw new SemanticException("missing required property: " + s); + } + }); + } + + public static String readInputStreamToString(final InputStream stream, final Charset charset) throws IOException { + final int bufferSize = 1024; + final char[] buffer = new char[bufferSize]; + final StringBuilder out = new StringBuilder(); + + try (Reader in = new InputStreamReader(stream, charset)) { + while (true) { + int rsz = in.read(buffer, 0, buffer.length); + if (rsz < 0) { + break; + } + out.append(buffer, 0, rsz); + } + return out.toString(); + } + } +} diff --git a/fe/fe-core/src/main/java/com/starrocks/authentication/GroupProvider.java b/fe/fe-core/src/main/java/com/starrocks/authentication/GroupProvider.java new file mode 100644 index 0000000000000..b062f87380b56 --- /dev/null +++ b/fe/fe-core/src/main/java/com/starrocks/authentication/GroupProvider.java @@ -0,0 +1,65 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed 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 +// +// https://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 com.starrocks.authentication; + +import com.google.gson.annotations.SerializedName; +import com.starrocks.common.DdlException; +import com.starrocks.sql.analyzer.SemanticException; +import com.starrocks.sql.ast.UserIdentity; + +import java.util.Map; +import java.util.Set; + +public abstract class GroupProvider { + public static final String GROUP_PROVIDER_PROPERTY_TYPE_KEY = "type"; + + @SerializedName(value = "n") + protected String name; + @SerializedName(value = "m") + protected Map properties; + + public GroupProvider(String name, Map properties) { + this.name = name; + this.properties = properties; + } + + public void init() throws DdlException { + + } + + public void destory() { + + } + + public String getName() { + return name; + } + + public String getType() { + return properties.get("type"); + } + + public Map getProperties() { + return properties; + } + + public String getComment() { + return ""; + } + + public abstract Set getGroup(UserIdentity userIdentity); + + public abstract void checkProperty() throws SemanticException; +} diff --git a/fe/fe-core/src/main/java/com/starrocks/authentication/GroupProviderFactory.java b/fe/fe-core/src/main/java/com/starrocks/authentication/GroupProviderFactory.java new file mode 100644 index 0000000000000..c6c455a4cd2cf --- /dev/null +++ b/fe/fe-core/src/main/java/com/starrocks/authentication/GroupProviderFactory.java @@ -0,0 +1,50 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed 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 +// +// https://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 com.starrocks.authentication; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableSortedSet; +import com.starrocks.sql.analyzer.SemanticException; + +import java.util.Map; + +public class GroupProviderFactory { + + private static final ImmutableSortedSet SUPPORT_GROUP_PROVIDER = + ImmutableSortedSet.orderedBy(String.CASE_INSENSITIVE_ORDER) + .add(UnixGroupProvider.TYPE) + .add(FileGroupProvider.TYPE) + .build(); + + public static void checkGroupProviderIsSupported(String groupProviderType) { + if (!SUPPORT_GROUP_PROVIDER.contains(groupProviderType)) { + throw new SemanticException("unsupported group provider type '" + groupProviderType + "'"); + } + } + public static GroupProvider createGroupProvider(String name, Map propertyMap) { + String type = propertyMap.get(GroupProvider.GROUP_PROVIDER_PROPERTY_TYPE_KEY); + checkGroupProviderIsSupported(type); + + GroupProvider groupProvider = null; + if (type.equalsIgnoreCase(FileGroupProvider.TYPE)) { + groupProvider = new FileGroupProvider(name, propertyMap); + } else if (type.equalsIgnoreCase(UnixGroupProvider.TYPE)) { + groupProvider = new UnixGroupProvider(name, propertyMap); + } + + Preconditions.checkNotNull(groupProvider); + return groupProvider; + } +} diff --git a/fe/fe-core/src/main/java/com/starrocks/authentication/JwkMgr.java b/fe/fe-core/src/main/java/com/starrocks/authentication/JwkMgr.java index b1bc77debc9d8..644bd81457352 100644 --- a/fe/fe-core/src/main/java/com/starrocks/authentication/JwkMgr.java +++ b/fe/fe-core/src/main/java/com/starrocks/authentication/JwkMgr.java @@ -25,13 +25,19 @@ public class JwkMgr { public JWKSet getJwkSet(String jwksUrl) throws IOException, ParseException { - InputStream jwksInputStream; - if (jwksUrl.startsWith("http://") || jwksUrl.startsWith("https://")) { - jwksInputStream = new URL(jwksUrl).openStream(); - } else { - String filePath = StarRocksFE.STARROCKS_HOME_DIR + "/conf/" + jwksUrl; - jwksInputStream = new FileInputStream(filePath); + InputStream jwksInputStream = null; + try { + if (jwksUrl.startsWith("http://") || jwksUrl.startsWith("https://")) { + jwksInputStream = new URL(jwksUrl).openStream(); + } else { + String filePath = StarRocksFE.STARROCKS_HOME_DIR + "/conf/" + jwksUrl; + jwksInputStream = new FileInputStream(filePath); + } + return JWKSet.load(jwksInputStream); + } finally { + if (jwksInputStream != null) { + jwksInputStream.close(); + } } - return JWKSet.load(jwksInputStream); } } diff --git a/fe/fe-core/src/main/java/com/starrocks/authentication/OpenIdConnectAuthenticationProvider.java b/fe/fe-core/src/main/java/com/starrocks/authentication/OpenIdConnectAuthenticationProvider.java index ff5a0da272535..801f481fecf95 100644 --- a/fe/fe-core/src/main/java/com/starrocks/authentication/OpenIdConnectAuthenticationProvider.java +++ b/fe/fe-core/src/main/java/com/starrocks/authentication/OpenIdConnectAuthenticationProvider.java @@ -22,9 +22,7 @@ import com.starrocks.sql.ast.UserAuthOption; import com.starrocks.sql.ast.UserIdentity; -import java.io.IOException; import java.nio.ByteBuffer; -import java.text.ParseException; public class OpenIdConnectAuthenticationProvider implements AuthenticationProvider { public static final String PLUGIN_NAME = AuthPlugin.AUTHENTICATION_OPENID_CONNECT.name(); @@ -56,17 +54,18 @@ public UserAuthenticationInfo analyzeAuthOption(UserIdentity userIdentity, UserA @Override public void authenticate(String user, String host, byte[] authResponse, byte[] randomString, UserAuthenticationInfo authenticationInfo) throws AuthenticationException { - ByteBuffer authBuffer = ByteBuffer.wrap(authResponse); - //1 Byte for capability mysql client - MysqlProto.readInt1(authBuffer); - byte[] openIdConnect = MysqlProto.readLenEncodedString(authBuffer); - - JWKSet jwkSet; try { + ByteBuffer authBuffer = ByteBuffer.wrap(authResponse); + //1 Byte for capability mysql client + MysqlProto.readInt1(authBuffer); + byte[] openIdConnect = MysqlProto.readLenEncodedString(authBuffer); + + JWKSet jwkSet; + jwkSet = GlobalStateMgr.getCurrentState().getJwkMgr().getJwkSet(jwksUrl); - } catch (IOException | ParseException e) { + OpenIdConnectVerifier.verify(new String(openIdConnect), user, jwkSet, principalFiled, requireIssuer, requireAudience); + } catch (Exception e) { throw new AuthenticationException(e.getMessage()); } - OpenIdConnectVerifier.verify(new String(openIdConnect), user, jwkSet, principalFiled, requireIssuer, requireAudience); } } \ No newline at end of file diff --git a/fe/fe-core/src/main/java/com/starrocks/authentication/SecurityIntegrationFactory.java b/fe/fe-core/src/main/java/com/starrocks/authentication/SecurityIntegrationFactory.java index c3d72504fc4d8..9d87f84375364 100644 --- a/fe/fe-core/src/main/java/com/starrocks/authentication/SecurityIntegrationFactory.java +++ b/fe/fe-core/src/main/java/com/starrocks/authentication/SecurityIntegrationFactory.java @@ -34,7 +34,6 @@ public static void checkSecurityIntegrationIsSupported(String securityIntegratio public static SecurityIntegration createSecurityIntegration(String name, Map propertyMap) { String type = propertyMap.get(SecurityIntegration.SECURITY_INTEGRATION_PROPERTY_TYPE_KEY); - checkSecurityIntegrationIsSupported(type); SecurityIntegration securityIntegration = null; diff --git a/fe/fe-core/src/main/java/com/starrocks/authentication/UnixGroupProvider.java b/fe/fe-core/src/main/java/com/starrocks/authentication/UnixGroupProvider.java new file mode 100644 index 0000000000000..490600dde7ebc --- /dev/null +++ b/fe/fe-core/src/main/java/com/starrocks/authentication/UnixGroupProvider.java @@ -0,0 +1,49 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed 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 +// +// https://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 com.starrocks.authentication; + +import com.starrocks.sql.analyzer.SemanticException; +import com.starrocks.sql.ast.UserIdentity; +import org.apache.hadoop.security.UserGroupInformation; + +import java.util.Map; +import java.util.Set; + +public class UnixGroupProvider extends GroupProvider { + public static final String TYPE = "unix"; + + public UnixGroupProvider(String name, Map properties) { + super(name, properties); + } + + @Override + public Set getGroup(UserIdentity userIdentity) { + Set userGroups = Set.of(); + + UserGroupInformation ugi = UserGroupInformation.createRemoteUser(userIdentity.getUser()); + String[] groups = ugi.getGroupNames(); + + if (groups != null && groups.length > 0) { + userGroups = Set.of(groups); + } + + return userGroups; + } + + @Override + public void checkProperty() throws SemanticException { + + } +} diff --git a/fe/fe-core/src/main/java/com/starrocks/persist/EditLog.java b/fe/fe-core/src/main/java/com/starrocks/persist/EditLog.java index 27fbd5cc6eb5f..1b78e46b0afb8 100644 --- a/fe/fe-core/src/main/java/com/starrocks/persist/EditLog.java +++ b/fe/fe-core/src/main/java/com/starrocks/persist/EditLog.java @@ -1142,6 +1142,17 @@ public void loadJournal(GlobalStateMgr globalStateMgr, JournalEntity journal) authenticationMgr.replayDropSecurityIntegration(info.name); break; } + case OperationType.OP_CREATE_GROUP_PROVIDER: { + GroupProviderLog groupProviderLog = (GroupProviderLog) journal.data(); + GlobalStateMgr.getCurrentState().getAuthenticationMgr().replayCreateGroupProvider( + groupProviderLog.getName(), groupProviderLog.getPropertyMap()); + break; + } + case OperationType.OP_DROP_GROUP_PROVIDER: { + GroupProviderLog groupProviderLog = (GroupProviderLog) journal.data(); + GlobalStateMgr.getCurrentState().getAuthenticationMgr().replayDropGroupProvider(groupProviderLog.getName()); + break; + } default: { if (Config.metadata_ignore_unknown_operation_type) { LOG.warn("UNKNOWN Operation Type {}", opCode); diff --git a/fe/fe-core/src/main/java/com/starrocks/persist/EditLogDeserializer.java b/fe/fe-core/src/main/java/com/starrocks/persist/EditLogDeserializer.java index acb21be1bbeae..efca3dafab9b0 100644 --- a/fe/fe-core/src/main/java/com/starrocks/persist/EditLogDeserializer.java +++ b/fe/fe-core/src/main/java/com/starrocks/persist/EditLogDeserializer.java @@ -248,6 +248,8 @@ public class EditLogDeserializer { .put(OperationType.OP_CREATE_SECURITY_INTEGRATION, SecurityIntegrationPersistInfo.class) .put(OperationType.OP_ALTER_SECURITY_INTEGRATION, SecurityIntegrationPersistInfo.class) .put(OperationType.OP_DROP_SECURITY_INTEGRATION, SecurityIntegrationPersistInfo.class) + .put(OperationType.OP_CREATE_GROUP_PROVIDER, GroupProviderLog.class) + .put(OperationType.OP_DROP_GROUP_PROVIDER, GroupProviderLog.class) .build(); public static Writable deserialize(Short opCode, DataInput in) throws IOException { diff --git a/fe/fe-core/src/main/java/com/starrocks/persist/GroupProviderLog.java b/fe/fe-core/src/main/java/com/starrocks/persist/GroupProviderLog.java new file mode 100644 index 0000000000000..33a68bba58278 --- /dev/null +++ b/fe/fe-core/src/main/java/com/starrocks/persist/GroupProviderLog.java @@ -0,0 +1,43 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed 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 +// +// https://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 com.starrocks.persist; + +import com.google.gson.annotations.SerializedName; + +import java.util.Map; + +public class GroupProviderLog extends GenericNameWithPropsPersistInfo { + @SerializedName(value = "t") + private String type; + + @SerializedName(value = "c") + private String comment; + + public GroupProviderLog(String name, Map propertyMap) { + super(name, propertyMap); + } + + public String getType() { + return type; + } + + public String getName() { + return name; + } + + public String getComment() { + return comment; + } +} diff --git a/fe/fe-core/src/main/java/com/starrocks/persist/OperationType.java b/fe/fe-core/src/main/java/com/starrocks/persist/OperationType.java index 39122ee995f41..d84a66db16adb 100644 --- a/fe/fe-core/src/main/java/com/starrocks/persist/OperationType.java +++ b/fe/fe-core/src/main/java/com/starrocks/persist/OperationType.java @@ -593,6 +593,12 @@ public class OperationType { @IgnorableOnReplayFailed public static final short OP_DELETE_SQL_QUERY_BLACK_LIST = 13521; + @IgnorableOnReplayFailed + public static final short OP_CREATE_GROUP_PROVIDER = 13530; + + @IgnorableOnReplayFailed + public static final short OP_DROP_GROUP_PROVIDER = 13531; + /** * NOTICE: OperationType cannot use a value exceeding 20000, please follow the above sequence number */ diff --git a/fe/fe-core/src/main/java/com/starrocks/persist/gson/GsonUtils.java b/fe/fe-core/src/main/java/com/starrocks/persist/gson/GsonUtils.java index 50d68f1043ac9..ee47874e57fca 100644 --- a/fe/fe-core/src/main/java/com/starrocks/persist/gson/GsonUtils.java +++ b/fe/fe-core/src/main/java/com/starrocks/persist/gson/GsonUtils.java @@ -70,8 +70,11 @@ import com.starrocks.alter.OptimizeJobV2; import com.starrocks.alter.RollupJobV2; import com.starrocks.alter.SchemaChangeJobV2; +import com.starrocks.authentication.FileGroupProvider; +import com.starrocks.authentication.GroupProvider; import com.starrocks.authentication.OIDCSecurityIntegration; import com.starrocks.authentication.SecurityIntegration; +import com.starrocks.authentication.UnixGroupProvider; import com.starrocks.authorization.CatalogPEntryObject; import com.starrocks.authorization.DbPEntryObject; import com.starrocks.authorization.FunctionPEntryObject; @@ -348,6 +351,11 @@ public class GsonUtils { RuntimeTypeAdapterFactory.of(SecurityIntegration.class, "clazz") .registerSubtype(OIDCSecurityIntegration.class, "OIDCSecurityIntegration"); + private static final RuntimeTypeAdapterFactory GROUP_PROVIDER_RUNTIME_TYPE_ADAPTER_FACTORY = + RuntimeTypeAdapterFactory.of(GroupProvider.class, "clazz") + .registerSubtype(FileGroupProvider.class, "FileGroupProvider") + .registerSubtype(UnixGroupProvider.class, "UnixGroupProvider"); + private static final RuntimeTypeAdapterFactory WAREHOUSE_TYPE_ADAPTER_FACTORY = RuntimeTypeAdapterFactory .of(Warehouse.class, "clazz") .registerSubtype(DefaultWarehouse.class, "DefaultWarehouse"); @@ -457,6 +465,7 @@ public class GsonUtils { .registerTypeAdapterFactory(SNAPSHOT_INFO_TYPE_ADAPTER_FACTORY) .registerTypeAdapterFactory(P_ENTRY_OBJECT_RUNTIME_TYPE_ADAPTER_FACTORY) .registerTypeAdapterFactory(SEC_INTEGRATION_RUNTIME_TYPE_ADAPTER_FACTORY) + .registerTypeAdapterFactory(GROUP_PROVIDER_RUNTIME_TYPE_ADAPTER_FACTORY) .registerTypeAdapterFactory(WAREHOUSE_TYPE_ADAPTER_FACTORY) .registerTypeAdapterFactory(LOAD_JOB_TYPE_RUNTIME_ADAPTER_FACTORY) .registerTypeAdapterFactory(TXN_COMMIT_ATTACHMENT_TYPE_RUNTIME_ADAPTER_FACTORY) diff --git a/fe/fe-core/src/main/java/com/starrocks/qe/DDLStmtExecutor.java b/fe/fe-core/src/main/java/com/starrocks/qe/DDLStmtExecutor.java index c29eca7d3b81c..91afa759d6c14 100644 --- a/fe/fe-core/src/main/java/com/starrocks/qe/DDLStmtExecutor.java +++ b/fe/fe-core/src/main/java/com/starrocks/qe/DDLStmtExecutor.java @@ -138,6 +138,8 @@ import com.starrocks.sql.ast.SyncStmt; import com.starrocks.sql.ast.TruncateTableStmt; import com.starrocks.sql.ast.UninstallPluginStmt; +import com.starrocks.sql.ast.group.CreateGroupProviderStmt; +import com.starrocks.sql.ast.group.DropGroupProviderStmt; import com.starrocks.sql.ast.integration.AlterSecurityIntegrationStatement; import com.starrocks.sql.ast.integration.CreateSecurityIntegrationStatement; import com.starrocks.sql.ast.integration.DropSecurityIntegrationStatement; @@ -621,6 +623,22 @@ public ShowResultSet visitDropSecurityIntegrationStatement(DropSecurityIntegrati return null; } + @Override + public ShowResultSet visitCreateGroupProviderStatement(CreateGroupProviderStmt statement, ConnectContext context) { + ErrorReport.wrapWithRuntimeException(() -> { + AuthenticationMgr authenticationMgr = GlobalStateMgr.getCurrentState().getAuthenticationMgr(); + authenticationMgr.createGroupProviderStatement(statement, context); + }); + return null; + } + + @Override + public ShowResultSet visitDropGroupProviderStatement(DropGroupProviderStmt statement, ConnectContext context) { + AuthenticationMgr authenticationMgr = GlobalStateMgr.getCurrentState().getAuthenticationMgr(); + authenticationMgr.dropGroupProviderStatement(statement, context); + return null; + } + @Override public ShowResultSet visitSetUserPropertyStatement(SetUserPropertyStmt stmt, ConnectContext context) { ErrorReport.wrapWithRuntimeException(() -> { diff --git a/fe/fe-core/src/main/java/com/starrocks/qe/ShowExecutor.java b/fe/fe-core/src/main/java/com/starrocks/qe/ShowExecutor.java index b03d8decaa0a7..bbf6e93162513 100644 --- a/fe/fe-core/src/main/java/com/starrocks/qe/ShowExecutor.java +++ b/fe/fe-core/src/main/java/com/starrocks/qe/ShowExecutor.java @@ -46,6 +46,7 @@ import com.starrocks.analysis.TableName; import com.starrocks.analysis.TableRef; import com.starrocks.authentication.AuthenticationMgr; +import com.starrocks.authentication.GroupProvider; import com.starrocks.authentication.SecurityIntegration; import com.starrocks.authentication.UserAuthenticationInfo; import com.starrocks.authorization.AccessDeniedException; @@ -229,6 +230,8 @@ import com.starrocks.sql.ast.ShowUserStmt; import com.starrocks.sql.ast.ShowVariablesStmt; import com.starrocks.sql.ast.UserIdentity; +import com.starrocks.sql.ast.group.ShowCreateGroupProviderStmt; +import com.starrocks.sql.ast.group.ShowGroupProvidersStmt; import com.starrocks.sql.ast.integration.ShowCreateSecurityIntegrationStatement; import com.starrocks.sql.ast.integration.ShowSecurityIntegrationStatement; import com.starrocks.sql.ast.pipe.DescPipeStmt; @@ -2108,6 +2111,54 @@ public ShowResultSet visitShowCreateSecurityIntegrationStatement(ShowCreateSecur return new ShowResultSet(statement.getMetaData(), infos); } + @Override + public ShowResultSet visitShowGroupProvidersStatement(ShowGroupProvidersStmt statement, ConnectContext context) { + AuthenticationMgr authenticationManager = GlobalStateMgr.getCurrentState().getAuthenticationMgr(); + List groupProviderLogs = authenticationManager.getAllGroupProviders(); + List> infos = new ArrayList<>(); + for (GroupProvider groupProviderLog : groupProviderLogs) { + List info = new ArrayList<>(); + info.add(groupProviderLog.getName()); + info.add(groupProviderLog.getType()); + if (groupProviderLog.getComment().isEmpty()) { + info.add(FeConstants.NULL_STRING); + } else { + info.add(groupProviderLog.getComment()); + } + infos.add(info); + } + + // sort by type, then by name + List> sortedList = infos.stream() + .sorted( + Comparator.comparing((List sublist) -> sublist.get(1)) + .thenComparing((List sublist) -> sublist.get(0)) + ) + .collect(Collectors.toList()); + + return new ShowResultSet(statement.getMetaData(), sortedList); + } + + @Override + public ShowResultSet visitShowCreateGroupProviderStatement(ShowCreateGroupProviderStmt statement, + ConnectContext context) { + AuthenticationMgr authenticationManager = GlobalStateMgr.getCurrentState().getAuthenticationMgr(); + + String name = statement.getName(); + List> infos = new ArrayList<>(); + GroupProvider groupProviderLog = authenticationManager.getGroupProvider(name); + if (groupProviderLog != null) { + Map propertyMap = groupProviderLog.getProperties(); + String propString = propertyMap.entrySet().stream() + .map(entry -> "\"" + entry.getKey() + "\" = \"" + entry.getValue() + "\"") + .collect(Collectors.joining(",\n")); + infos.add(Lists.newArrayList(name, + "CREATE GROUP PROVIDER `" + name + + "` PROPERTIES (\n" + propString + "\n)")); + } + return new ShowResultSet(statement.getMetaData(), infos); + } + @Override public ShowResultSet visitAdminShowReplicaStatusStatement(AdminShowReplicaStatusStmt statement, ConnectContext context) { List> results; diff --git a/fe/fe-core/src/main/java/com/starrocks/sql/analyzer/Analyzer.java b/fe/fe-core/src/main/java/com/starrocks/sql/analyzer/Analyzer.java index 833d040b7bccc..2159c090f1e9e 100644 --- a/fe/fe-core/src/main/java/com/starrocks/sql/analyzer/Analyzer.java +++ b/fe/fe-core/src/main/java/com/starrocks/sql/analyzer/Analyzer.java @@ -148,6 +148,10 @@ import com.starrocks.sql.ast.UpdateStmt; import com.starrocks.sql.ast.UseCatalogStmt; import com.starrocks.sql.ast.UseDbStmt; +import com.starrocks.sql.ast.group.CreateGroupProviderStmt; +import com.starrocks.sql.ast.group.DropGroupProviderStmt; +import com.starrocks.sql.ast.group.ShowCreateGroupProviderStmt; +import com.starrocks.sql.ast.group.ShowGroupProvidersStmt; import com.starrocks.sql.ast.integration.AlterSecurityIntegrationStatement; import com.starrocks.sql.ast.integration.CreateSecurityIntegrationStatement; import com.starrocks.sql.ast.integration.DropSecurityIntegrationStatement; @@ -836,6 +840,32 @@ public Void visitShowCreateSecurityIntegrationStatement(ShowCreateSecurityIntegr return null; } + // ---------------------------------------- Group Provider Statement ------------------------------------- + + @Override + public Void visitCreateGroupProviderStatement(CreateGroupProviderStmt statement, ConnectContext context) { + GroupProviderStatementAnalyzer.analyze(statement, context); + return null; + } + + @Override + public Void visitDropGroupProviderStatement(DropGroupProviderStmt statement, ConnectContext context) { + GroupProviderStatementAnalyzer.analyze(statement, context); + return null; + } + + @Override + public Void visitShowCreateGroupProviderStatement(ShowCreateGroupProviderStmt statement, ConnectContext context) { + GroupProviderStatementAnalyzer.analyze(statement, context); + return null; + } + + @Override + public Void visitShowGroupProvidersStatement(ShowGroupProvidersStmt statement, ConnectContext context) { + GroupProviderStatementAnalyzer.analyze(statement, context); + return null; + } + // -------------------------------------- Data Cache Management Statement ----------------------------------------- @Override diff --git a/fe/fe-core/src/main/java/com/starrocks/sql/analyzer/GroupProviderStatementAnalyzer.java b/fe/fe-core/src/main/java/com/starrocks/sql/analyzer/GroupProviderStatementAnalyzer.java new file mode 100644 index 0000000000000..1c1ac07dc46e9 --- /dev/null +++ b/fe/fe-core/src/main/java/com/starrocks/sql/analyzer/GroupProviderStatementAnalyzer.java @@ -0,0 +1,87 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed 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 +// +// https://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 com.starrocks.sql.analyzer; + +import com.google.common.base.Preconditions; +import com.starrocks.authentication.AuthenticationMgr; +import com.starrocks.authentication.GroupProvider; +import com.starrocks.authentication.GroupProviderFactory; +import com.starrocks.qe.ConnectContext; +import com.starrocks.server.GlobalStateMgr; +import com.starrocks.sql.ast.AstVisitor; +import com.starrocks.sql.ast.StatementBase; +import com.starrocks.sql.ast.group.CreateGroupProviderStmt; +import com.starrocks.sql.ast.group.DropGroupProviderStmt; +import com.starrocks.sql.ast.group.ShowCreateGroupProviderStmt; +import com.starrocks.sql.ast.group.ShowGroupProvidersStmt; + +import java.util.Map; + +public class GroupProviderStatementAnalyzer { + public static void analyze(StatementBase statement, ConnectContext context) { + new GroupProviderStatementAnalyzer.GroupProviderStatementAnalyzerVisitor().analyze(statement, context); + } + + public static class GroupProviderStatementAnalyzerVisitor implements AstVisitor { + + public void analyze(StatementBase statement, ConnectContext context) { + visit(statement, context); + } + + @Override + public Void visitCreateGroupProviderStatement(CreateGroupProviderStmt statement, ConnectContext context) { + Map properties = statement.getPropertyMap(); + String groupProviderType = properties.get("type"); + if (groupProviderType == null) { + throw new SemanticException("missing required property: type"); + } + + GroupProvider groupProvider = GroupProviderFactory.createGroupProvider(statement.getName(), properties); + Preconditions.checkNotNull(groupProvider); + groupProvider.checkProperty(); + + AuthenticationMgr authenticationMgr = GlobalStateMgr.getCurrentState().getAuthenticationMgr(); + if (authenticationMgr.getGroupProvider(statement.getName()) != null) { + throw new SemanticException("Group Provider '" + statement.getName() + "' already exists"); + } + return null; + } + + @Override + public Void visitDropGroupProviderStatement(DropGroupProviderStmt statement, ConnectContext context) { + AuthenticationMgr authenticationMgr = GlobalStateMgr.getCurrentState().getAuthenticationMgr(); + if (authenticationMgr.getGroupProvider(statement.getName()) == null) { + throw new SemanticException("Group Provider '" + statement.getName() + "' not found"); + } + + return null; + } + + @Override + public Void visitShowCreateGroupProviderStatement(ShowCreateGroupProviderStmt statement, ConnectContext context) { + AuthenticationMgr authenticationMgr = GlobalStateMgr.getCurrentState().getAuthenticationMgr(); + if (authenticationMgr.getGroupProvider(statement.getName()) == null) { + throw new SemanticException("Group Provider '" + statement.getName() + "' not found"); + } + + return null; + } + + @Override + public Void visitShowGroupProvidersStatement(ShowGroupProvidersStmt statement, ConnectContext context) { + return null; + } + } +} diff --git a/fe/fe-core/src/main/java/com/starrocks/sql/ast/AstVisitor.java b/fe/fe-core/src/main/java/com/starrocks/sql/ast/AstVisitor.java index ee91e85ce76b5..926274aa60336 100644 --- a/fe/fe-core/src/main/java/com/starrocks/sql/ast/AstVisitor.java +++ b/fe/fe-core/src/main/java/com/starrocks/sql/ast/AstVisitor.java @@ -58,6 +58,10 @@ import com.starrocks.sql.ast.feedback.ClearPlanAdvisorStmt; import com.starrocks.sql.ast.feedback.DelPlanAdvisorStmt; import com.starrocks.sql.ast.feedback.ShowPlanAdvisorStmt; +import com.starrocks.sql.ast.group.CreateGroupProviderStmt; +import com.starrocks.sql.ast.group.DropGroupProviderStmt; +import com.starrocks.sql.ast.group.ShowCreateGroupProviderStmt; +import com.starrocks.sql.ast.group.ShowGroupProvidersStmt; import com.starrocks.sql.ast.integration.AlterSecurityIntegrationStatement; import com.starrocks.sql.ast.integration.CreateSecurityIntegrationStatement; import com.starrocks.sql.ast.integration.DropSecurityIntegrationStatement; @@ -795,6 +799,24 @@ default R visitShowSecurityIntegrationStatement(ShowSecurityIntegrationStatement return visitShowStatement(statement, context); } + // ------------------------------------------- Group Provider Statement ---------------------------------------------------- + + default R visitCreateGroupProviderStatement(CreateGroupProviderStmt statement, C context) { + return visitDDLStatement(statement, context); + } + + default R visitDropGroupProviderStatement(DropGroupProviderStmt statement, C context) { + return visitDDLStatement(statement, context); + } + + default R visitShowCreateGroupProviderStatement(ShowCreateGroupProviderStmt statement, C context) { + return visitShowStatement(statement, context); + } + + default R visitShowGroupProvidersStatement(ShowGroupProvidersStmt statement, C context) { + return visitShowStatement(statement, context); + } + // ---------------------------------------- Backup Restore Statement ----------------------------------------------- default R visitBackupStatement(BackupStmt statement, C context) { diff --git a/fe/fe-core/src/main/java/com/starrocks/sql/ast/group/CreateGroupProviderStmt.java b/fe/fe-core/src/main/java/com/starrocks/sql/ast/group/CreateGroupProviderStmt.java new file mode 100644 index 0000000000000..9470daa6271b3 --- /dev/null +++ b/fe/fe-core/src/main/java/com/starrocks/sql/ast/group/CreateGroupProviderStmt.java @@ -0,0 +1,45 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed 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 +// +// https://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 com.starrocks.sql.ast.group; + +import com.starrocks.sql.ast.AstVisitor; +import com.starrocks.sql.ast.DdlStmt; +import com.starrocks.sql.parser.NodePosition; + +import java.util.Map; + +public class CreateGroupProviderStmt extends DdlStmt { + private final String name; + private final Map propertyMap; + + public CreateGroupProviderStmt(String name, Map propertyMap, NodePosition pos) { + super(pos); + this.name = name; + this.propertyMap = propertyMap; + } + + public String getName() { + return name; + } + + public Map getPropertyMap() { + return propertyMap; + } + + @Override + public R accept(AstVisitor visitor, C context) { + return visitor.visitCreateGroupProviderStatement(this, context); + } +} diff --git a/fe/fe-core/src/main/java/com/starrocks/sql/ast/group/DropGroupProviderStmt.java b/fe/fe-core/src/main/java/com/starrocks/sql/ast/group/DropGroupProviderStmt.java new file mode 100644 index 0000000000000..0874acac6dfd5 --- /dev/null +++ b/fe/fe-core/src/main/java/com/starrocks/sql/ast/group/DropGroupProviderStmt.java @@ -0,0 +1,37 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed 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 +// +// https://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 com.starrocks.sql.ast.group; + +import com.starrocks.sql.ast.AstVisitor; +import com.starrocks.sql.ast.DdlStmt; +import com.starrocks.sql.parser.NodePosition; + +public class DropGroupProviderStmt extends DdlStmt { + private final String name; + + public DropGroupProviderStmt(String name, NodePosition pos) { + super(pos); + this.name = name; + } + + public String getName() { + return name; + } + + @Override + public R accept(AstVisitor visitor, C context) { + return visitor.visitDropGroupProviderStatement(this, context); + } +} diff --git a/fe/fe-core/src/main/java/com/starrocks/sql/ast/group/ShowCreateGroupProviderStmt.java b/fe/fe-core/src/main/java/com/starrocks/sql/ast/group/ShowCreateGroupProviderStmt.java new file mode 100644 index 0000000000000..ccd3a85c5a832 --- /dev/null +++ b/fe/fe-core/src/main/java/com/starrocks/sql/ast/group/ShowCreateGroupProviderStmt.java @@ -0,0 +1,51 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed 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 +// +// https://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 com.starrocks.sql.ast.group; + +import com.starrocks.catalog.Column; +import com.starrocks.catalog.ScalarType; +import com.starrocks.qe.ShowResultSetMetaData; +import com.starrocks.sql.ast.AstVisitor; +import com.starrocks.sql.ast.ShowStmt; +import com.starrocks.sql.parser.NodePosition; + +public class ShowCreateGroupProviderStmt extends ShowStmt { + private static final ShowResultSetMetaData META_DATA = + ShowResultSetMetaData.builder() + .addColumn(new Column("Group Provider", ScalarType.createVarchar(60))) + .addColumn(new Column("Create Group Provider", ScalarType.createVarchar(500))) + .build(); + + private final String groupName; + + public ShowCreateGroupProviderStmt(String groupName, NodePosition pos) { + super(pos); + this.groupName = groupName; + } + + public String getName() { + return groupName; + } + + @Override + public ShowResultSetMetaData getMetaData() { + return META_DATA; + } + + @Override + public R accept(AstVisitor visitor, C context) { + return visitor.visitShowCreateGroupProviderStatement(this, context); + } +} diff --git a/fe/fe-core/src/main/java/com/starrocks/sql/ast/group/ShowGroupProvidersStmt.java b/fe/fe-core/src/main/java/com/starrocks/sql/ast/group/ShowGroupProvidersStmt.java new file mode 100644 index 0000000000000..40449343d2b21 --- /dev/null +++ b/fe/fe-core/src/main/java/com/starrocks/sql/ast/group/ShowGroupProvidersStmt.java @@ -0,0 +1,50 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed 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 +// +// https://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 com.starrocks.sql.ast.group; + +import com.starrocks.catalog.Column; +import com.starrocks.catalog.ScalarType; +import com.starrocks.qe.ShowResultSetMetaData; +import com.starrocks.sql.ast.AstVisitor; +import com.starrocks.sql.ast.ShowStmt; +import com.starrocks.sql.parser.NodePosition; + +public class ShowGroupProvidersStmt extends ShowStmt { + private static final ShowResultSetMetaData META_DATA; + + static { + ShowResultSetMetaData.Builder builder = ShowResultSetMetaData.builder(); + + builder.addColumn(new Column("Name", ScalarType.createVarchar(100))); + builder.addColumn(new Column("Type", ScalarType.createVarchar(100))); + builder.addColumn(new Column("Comment", ScalarType.createVarchar(300))); + + META_DATA = builder.build(); + } + + public ShowGroupProvidersStmt(NodePosition pos) { + super(pos); + } + + @Override + public ShowResultSetMetaData getMetaData() { + return META_DATA; + } + + @Override + public R accept(AstVisitor visitor, C context) { + return visitor.visitShowGroupProvidersStatement(this, context); + } +} diff --git a/fe/fe-core/src/main/java/com/starrocks/sql/parser/AstBuilder.java b/fe/fe-core/src/main/java/com/starrocks/sql/parser/AstBuilder.java index 3908b2ab3382f..ed9084144c830 100644 --- a/fe/fe-core/src/main/java/com/starrocks/sql/parser/AstBuilder.java +++ b/fe/fe-core/src/main/java/com/starrocks/sql/parser/AstBuilder.java @@ -469,6 +469,10 @@ import com.starrocks.sql.ast.feedback.ClearPlanAdvisorStmt; import com.starrocks.sql.ast.feedback.DelPlanAdvisorStmt; import com.starrocks.sql.ast.feedback.ShowPlanAdvisorStmt; +import com.starrocks.sql.ast.group.CreateGroupProviderStmt; +import com.starrocks.sql.ast.group.DropGroupProviderStmt; +import com.starrocks.sql.ast.group.ShowCreateGroupProviderStmt; +import com.starrocks.sql.ast.group.ShowGroupProvidersStmt; import com.starrocks.sql.ast.integration.AlterSecurityIntegrationStatement; import com.starrocks.sql.ast.integration.CreateSecurityIntegrationStatement; import com.starrocks.sql.ast.integration.DropSecurityIntegrationStatement; @@ -6687,6 +6691,41 @@ public ParseNode visitShowSecurityIntegrationStatement( return new ShowSecurityIntegrationStatement(createPos(context)); } + // ---------------------------------------- Group Provider Statement -------------------------------------- + + @Override + public ParseNode visitCreateGroupProviderStatement(StarRocksParser.CreateGroupProviderStatementContext context) { + String name = ((Identifier) visit(context.identifier())).getValue(); + Map propertyMap = new HashMap<>(); + if (context.properties() != null) { + List propertyList = visit(context.properties().property(), Property.class); + for (Property property : propertyList) { + propertyMap.put(property.getKey(), property.getValue()); + } + } + return new CreateGroupProviderStmt(name, propertyMap, createPos(context)); + } + + @Override + public ParseNode visitDropGroupProviderStatement( + StarRocksParser.DropGroupProviderStatementContext context) { + String name = ((Identifier) visit(context.identifier())).getValue(); + return new DropGroupProviderStmt(name, createPos(context)); + } + + @Override + public ParseNode visitShowCreateGroupProviderStatement( + StarRocksParser.ShowCreateGroupProviderStatementContext context) { + String name = ((Identifier) visit(context.identifier())).getValue(); + return new ShowCreateGroupProviderStmt(name, createPos(context)); + } + + @Override + public ParseNode visitShowGroupProvidersStatement( + StarRocksParser.ShowGroupProvidersStatementContext context) { + return new ShowGroupProvidersStmt(createPos(context)); + } + // ------------------------------------------- Expression ---------------------------------------------------------- @Override diff --git a/fe/fe-core/src/main/java/com/starrocks/sql/parser/StarRocks.g4 b/fe/fe-core/src/main/java/com/starrocks/sql/parser/StarRocks.g4 index 8086749a90889..fe11828c385da 100644 --- a/fe/fe-core/src/main/java/com/starrocks/sql/parser/StarRocks.g4 +++ b/fe/fe-core/src/main/java/com/starrocks/sql/parser/StarRocks.g4 @@ -229,6 +229,12 @@ statement | showSecurityIntegrationStatement | showCreateSecurityIntegrationStatement + // Group Provider Statement + | createGroupProviderStatement + | dropGroupProviderStatement + | showGroupProvidersStatement + | showCreateGroupProviderStatement + // Backup Restore Statement | backupStatement | cancelBackupStatement @@ -1803,6 +1809,24 @@ showCreateSecurityIntegrationStatement : SHOW CREATE SECURITY INTEGRATION identifier ; +// ------------------------------------------- Group Provider Statement ------------------------------------------ + +createGroupProviderStatement + : CREATE GROUP PROVIDER identifier properties + ; + +dropGroupProviderStatement + : DROP GROUP PROVIDER identifier + ; + +showGroupProvidersStatement + : SHOW GROUP PROVIDERS + ; + +showCreateGroupProviderStatement + : SHOW CREATE GROUP PROVIDER identifier + ; + // ---------------------------------------- Backup Restore Statement --------------------------------------------------- backupStatement @@ -3004,7 +3028,7 @@ nonReserved | NAME | NAMES | NEGATIVE | NO | NODE | NODES | NONE | NULLS | NUMBER | NUMERIC | OBSERVER | OF | OFFSET | ONLY | OPTIMIZER | OPEN | OPERATE | OPTION | OVERWRITE | OFF | PARTITIONS | PASSWORD | PATH | PAUSE | PENDING | PERCENTILE_UNION | PIVOT | PLAN | PLUGIN | PLUGINS | POLICY | POLICIES - | PERCENT_RANK | PREDICATE | PRECEDING | PRIORITY | PROC | PROCESSLIST | PROFILE | PROFILELIST | PRIVILEGES | PROBABILITY | PROPERTIES | PROPERTY | PIPE | PIPES + | PERCENT_RANK | PREDICATE | PRECEDING | PRIORITY | PROC | PROCESSLIST | PROFILE | PROFILELIST | PROVIDER | PROVIDERS | PRIVILEGES | PROBABILITY | PROPERTIES | PROPERTY | PIPE | PIPES | QUARTER | QUERY | QUERIES | QUEUE | QUOTA | QUALIFY | REASON | REMOVE | REWRITE | RANDOM | RANK | RECOVER | REFRESH | REPAIR | REPEATABLE | REPLACE_IF_NOT_NULL | REPLICA | REPOSITORY | REPOSITORIES diff --git a/fe/fe-core/src/main/java/com/starrocks/sql/parser/StarRocksLex.g4 b/fe/fe-core/src/main/java/com/starrocks/sql/parser/StarRocksLex.g4 index 5c878e2df8d6f..5b8c1c0766acc 100644 --- a/fe/fe-core/src/main/java/com/starrocks/sql/parser/StarRocksLex.g4 +++ b/fe/fe-core/src/main/java/com/starrocks/sql/parser/StarRocksLex.g4 @@ -341,6 +341,8 @@ PROFILE: 'PROFILE'; PROFILELIST: 'PROFILELIST'; PROPERTIES: 'PROPERTIES'; PROPERTY: 'PROPERTY'; +PROVIDER: 'PROVIDER'; +PROVIDERS: 'PROVIDERS'; QUALIFY: 'QUALIFY'; QUARTER: 'QUARTER'; QUERY: 'QUERY'; diff --git a/test/sql/test_security_integration/R/test_group_provider b/test/sql/test_security_integration/R/test_group_provider new file mode 100644 index 0000000000000..809d15ddf909a --- /dev/null +++ b/test/sql/test_security_integration/R/test_group_provider @@ -0,0 +1,24 @@ +-- name: test_group_provider +create group provider foo properties("type" = "foo"); +-- result: +E: (1064, "Getting analyzing error. Detail message: unsupported group provider type 'foo'.") +-- !result +create group provider unix_group_provider properties("type" = "unix"); +-- result: +-- !result +show create group provider unix_group_provider; +-- result: +unix_group_provider CREATE GROUP PROVIDER `unix_group_provider` PROPERTIES ( +"type" = "unix" +) +-- !result +show group providers; +-- result: +unix_group_provider unix None +-- !result +drop group provider unix_group_provider; +-- result: +-- !result +show group providers; +-- result: +-- !result \ No newline at end of file diff --git a/test/sql/test_security_integration/T/test_group_provider b/test/sql/test_security_integration/T/test_group_provider new file mode 100644 index 0000000000000..7765db9b2d9ad --- /dev/null +++ b/test/sql/test_security_integration/T/test_group_provider @@ -0,0 +1,9 @@ +-- name: test_group_provider + +create group provider foo properties("type" = "foo"); + +create group provider unix_group_provider properties("type" = "unix"); +show create group provider unix_group_provider; +show group providers; +drop group provider unix_group_provider; +show group providers;