This is an automated email from the ASF dual-hosted git repository.
kirs pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new 2edc65c694d [feat](auth) support querying authentication integrations
from system table (#61246)
2edc65c694d is described below
commit 2edc65c694df31ad63832bc9ff4f959865af9571
Author: Calvin Kirs <[email protected]>
AuthorDate: Tue Mar 17 12:34:56 2026 +0800
[feat](auth) support querying authentication integrations from system
table (#61246)
### What problem does this PR solve?
#60361
`AUTHENTICATION INTEGRATION` currently has no system-table query entry,
so users cannot inspect existing integrations through SQL in a
consistent way with other metadata objects.
At the same time, upstream has already introduced unified audit metadata
for `AuthenticationIntegrationMeta`, including:
- `createUser`
- `createTime`
- `alterUser`
- `modifyTime`
But these fields are not exposed through a queryable metadata path yet.
This PR adds a system table for querying authentication integrations and
synchronizes the query result with the new audit metadata.
### What is changed
- Add `information_schema.authentication_integrations`
- Wire the schema table through FE/BE/Thrift
- Expose the following columns:
- `NAME`
- `TYPE`
- `PROPERTIES`
- `COMMENT`
- `CREATE_USER`
- `CREATE_TIME`
- `ALTER_USER`
- `MODIFY_TIME`
- Mask sensitive properties in query results
- existing password/secret/token/keytab-style keys remain masked
- keys with prefix `secret.` are also masked
- Add FE unit tests and regression coverage for querying this system
table
### Example
```sql
SELECT *
FROM information_schema.authentication_integrations;
SELECT
name,
type,
comment,
create_user,
create_time,
alter_user,
modify_time,
properties
FROM information_schema.authentication_integrations
ORDER BY name;
### Why is this safe?
- This change only adds metadata query capability
- It does not change existing CREATE/ALTER/DROP AUTHENTICATION
INTEGRATION semantics
- Sensitive properties are masked only in display/query results, not
modified in persisted metadata
### Test
- FE unit test:
- org.apache.doris.service.FrontendServiceImplTest
- org.apache.doris.catalog.SchemaTableTest
- Regression test:
-
regression-test/suites/auth_p0/test_authentication_integration_auth.groovy
---
.../schema_authentication_integrations_scanner.cpp | 148 +++++++++++++++++++++
.../schema_authentication_integrations_scanner.h | 53 ++++++++
be/src/information_schema/schema_scanner.cpp | 3 +
.../org/apache/doris/analysis/SchemaTableType.java | 4 +-
.../java/org/apache/doris/catalog/SchemaTable.java | 11 ++
.../doris/tablefunction/MetadataGenerator.java | 96 +++++++++++++
.../org/apache/doris/catalog/SchemaTableTest.java | 10 ++
.../doris/service/FrontendServiceImplTest.java | 56 ++++++++
gensrc/thrift/Descriptors.thrift | 1 +
gensrc/thrift/FrontendService.thrift | 1 +
.../test_authentication_integration_auth.groovy | 35 ++++-
11 files changed, 415 insertions(+), 3 deletions(-)
diff --git
a/be/src/information_schema/schema_authentication_integrations_scanner.cpp
b/be/src/information_schema/schema_authentication_integrations_scanner.cpp
new file mode 100644
index 00000000000..c1edd00aa7c
--- /dev/null
+++ b/be/src/information_schema/schema_authentication_integrations_scanner.cpp
@@ -0,0 +1,148 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "information_schema/schema_authentication_integrations_scanner.h"
+
+#include <utility>
+
+#include "core/block/block.h"
+#include "core/data_type/data_type_factory.hpp"
+#include "core/string_ref.h"
+#include "information_schema/schema_helper.h"
+#include "runtime/exec_env.h"
+#include "runtime/runtime_state.h"
+#include "util/client_cache.h"
+#include "util/thrift_rpc_helper.h"
+
+namespace doris {
+#include "common/compile_check_begin.h"
+
+std::vector<SchemaScanner::ColumnDesc>
SchemaAuthenticationIntegrationsScanner::_s_tbls_columns = {
+ {"NAME", TYPE_VARCHAR, sizeof(StringRef), true},
+ {"TYPE", TYPE_VARCHAR, sizeof(StringRef), true},
+ {"PROPERTIES", TYPE_STRING, sizeof(StringRef), true},
+ {"COMMENT", TYPE_STRING, sizeof(StringRef), true},
+ {"CREATE_USER", TYPE_STRING, sizeof(StringRef), true},
+ {"CREATE_TIME", TYPE_STRING, sizeof(StringRef), true},
+ {"ALTER_USER", TYPE_STRING, sizeof(StringRef), true},
+ {"MODIFY_TIME", TYPE_STRING, sizeof(StringRef), true},
+};
+
+SchemaAuthenticationIntegrationsScanner::SchemaAuthenticationIntegrationsScanner()
+ : SchemaScanner(_s_tbls_columns,
TSchemaTableType::SCH_AUTHENTICATION_INTEGRATIONS) {}
+
+Status SchemaAuthenticationIntegrationsScanner::start(RuntimeState* state) {
+ if (!_is_init) {
+ return Status::InternalError("used before initialized.");
+ }
+ _block_rows_limit = state->batch_size();
+ _rpc_timeout_ms = state->execution_timeout() * 1000;
+ return Status::OK();
+}
+
+Status
SchemaAuthenticationIntegrationsScanner::_get_authentication_integrations_block_from_fe()
{
+ TNetworkAddress master_addr =
ExecEnv::GetInstance()->cluster_info()->master_fe_addr;
+
+ TSchemaTableRequestParams schema_table_request_params;
+ for (int i = 0; i < _s_tbls_columns.size(); i++) {
+ schema_table_request_params.__isset.columns_name = true;
+
schema_table_request_params.columns_name.emplace_back(_s_tbls_columns[i].name);
+ }
+
schema_table_request_params.__set_current_user_ident(*_param->common_param->current_user_ident);
+ if (_param->common_param->frontend_conjuncts) {
+ schema_table_request_params.__set_frontend_conjuncts(
+ *_param->common_param->frontend_conjuncts);
+ }
+
+ TFetchSchemaTableDataRequest request;
+
request.__set_schema_table_name(TSchemaTableName::AUTHENTICATION_INTEGRATIONS);
+ request.__set_schema_table_params(schema_table_request_params);
+
+ TFetchSchemaTableDataResult result;
+ RETURN_IF_ERROR(ThriftRpcHelper::rpc<FrontendServiceClient>(
+ master_addr.hostname, master_addr.port,
+ [&request, &result](FrontendServiceConnection& client) {
+ client->fetchSchemaTableData(result, request);
+ },
+ _rpc_timeout_ms));
+
+ Status status(Status::create(result.status));
+ if (!status.ok()) {
+ LOG(WARNING) << "fetch authentication integrations from FE failed,
errmsg=" << status;
+ return status;
+ }
+
+ _authentication_integrations_block = Block::create_unique();
+ for (int i = 0; i < _s_tbls_columns.size(); ++i) {
+ auto data_type =
+
DataTypeFactory::instance().create_data_type(_s_tbls_columns[i].type, true);
+ _authentication_integrations_block->insert(ColumnWithTypeAndName(
+ data_type->create_column(), data_type,
_s_tbls_columns[i].name));
+ }
+ _authentication_integrations_block->reserve(_block_rows_limit);
+
+ std::vector<TRow> result_data = std::move(result.data_batch);
+ if (!result_data.empty()) {
+ auto col_size = result_data[0].column_value.size();
+ if (col_size != _s_tbls_columns.size()) {
+ return Status::InternalError<false>(
+ "authentication integrations schema is not match for FE
and BE");
+ }
+ }
+
+ for (int i = 0; i < result_data.size(); i++) {
+ const TRow& row = result_data[i];
+ for (int j = 0; j < _s_tbls_columns.size(); j++) {
+ RETURN_IF_ERROR(insert_block_column(row.column_value[j], j,
+
_authentication_integrations_block.get(),
+ _s_tbls_columns[j].type));
+ }
+ }
+ return Status::OK();
+}
+
+Status SchemaAuthenticationIntegrationsScanner::get_next_block_internal(Block*
block, bool* eos) {
+ if (!_is_init) {
+ return Status::InternalError("Used before initialized.");
+ }
+
+ if (nullptr == block || nullptr == eos) {
+ return Status::InternalError("input pointer is nullptr.");
+ }
+
+ if (_authentication_integrations_block == nullptr) {
+ RETURN_IF_ERROR(_get_authentication_integrations_block_from_fe());
+ _total_rows =
static_cast<int>(_authentication_integrations_block->rows());
+ }
+
+ if (_row_idx == _total_rows) {
+ *eos = true;
+ return Status::OK();
+ }
+
+ int current_batch_rows = std::min(_block_rows_limit, _total_rows -
_row_idx);
+ MutableBlock mblock = MutableBlock::build_mutable_block(block);
+ RETURN_IF_ERROR(mblock.add_rows(_authentication_integrations_block.get(),
_row_idx,
+ current_batch_rows));
+ _row_idx += current_batch_rows;
+
+ *eos = _row_idx == _total_rows;
+ return Status::OK();
+}
+
+#include "common/compile_check_end.h"
+} // namespace doris
diff --git
a/be/src/information_schema/schema_authentication_integrations_scanner.h
b/be/src/information_schema/schema_authentication_integrations_scanner.h
new file mode 100644
index 00000000000..285a6a1a24a
--- /dev/null
+++ b/be/src/information_schema/schema_authentication_integrations_scanner.h
@@ -0,0 +1,53 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include <gen_cpp/FrontendService_types.h>
+
+#include <vector>
+
+#include "common/status.h"
+#include "information_schema/schema_scanner.h"
+
+namespace doris {
+class RuntimeState;
+class Block;
+
+class SchemaAuthenticationIntegrationsScanner : public SchemaScanner {
+ ENABLE_FACTORY_CREATOR(SchemaAuthenticationIntegrationsScanner);
+
+public:
+ SchemaAuthenticationIntegrationsScanner();
+ ~SchemaAuthenticationIntegrationsScanner() override = default;
+
+ Status start(RuntimeState* state) override;
+ Status get_next_block_internal(Block* block, bool* eos) override;
+
+ static std::vector<SchemaScanner::ColumnDesc> _s_tbls_columns;
+
+private:
+ Status _get_authentication_integrations_block_from_fe();
+
+ int _block_rows_limit = 4096;
+ int _row_idx = 0;
+ int _total_rows = 0;
+ int _rpc_timeout_ms = 3000;
+ std::unique_ptr<Block> _authentication_integrations_block = nullptr;
+};
+
+} // namespace doris
diff --git a/be/src/information_schema/schema_scanner.cpp
b/be/src/information_schema/schema_scanner.cpp
index a03c40b28c1..a4f0b5e2103 100644
--- a/be/src/information_schema/schema_scanner.cpp
+++ b/be/src/information_schema/schema_scanner.cpp
@@ -43,6 +43,7 @@
#include "core/value/hll.h"
#include "exec/pipeline/dependency.h"
#include "information_schema/schema_active_queries_scanner.h"
+#include "information_schema/schema_authentication_integrations_scanner.h"
#include "information_schema/schema_backend_active_tasks.h"
#include "information_schema/schema_backend_configuration_scanner.h"
#include "information_schema/schema_backend_kerberos_ticket_cache.h"
@@ -261,6 +262,8 @@ std::unique_ptr<SchemaScanner>
SchemaScanner::create(TSchemaTableType::type type
return SchemaColumnDataSizesScanner::create_unique();
case TSchemaTableType::SCH_FILE_CACHE_INFO:
return SchemaFileCacheInfoScanner::create_unique();
+ case TSchemaTableType::SCH_AUTHENTICATION_INTEGRATIONS:
+ return SchemaAuthenticationIntegrationsScanner::create_unique();
default:
return SchemaDummyScanner::create_unique();
break;
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/analysis/SchemaTableType.java
b/fe/fe-core/src/main/java/org/apache/doris/analysis/SchemaTableType.java
index 02ea8a610a4..ad3d2655dcb 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/SchemaTableType.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/SchemaTableType.java
@@ -114,7 +114,9 @@ public enum SchemaTableType {
SCH_COLUMN_DATA_SIZES("COLUMN_DATA_SIZES", "COLUMN_DATA_SIZES",
TSchemaTableType.SCH_COLUMN_DATA_SIZES),
SCH_DATABASE_PROPERTIES("DATABASE_PROPERTIES", "DATABASE_PROPERTIES",
- TSchemaTableType.SCH_DATABASE_PROPERTIES);
+ TSchemaTableType.SCH_DATABASE_PROPERTIES),
+ SCH_AUTHENTICATION_INTEGRATIONS("AUTHENTICATION_INTEGRATIONS",
"AUTHENTICATION_INTEGRATIONS",
+ TSchemaTableType.SCH_AUTHENTICATION_INTEGRATIONS);
private static final String dbName = "INFORMATION_SCHEMA";
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/SchemaTable.java
b/fe/fe-core/src/main/java/org/apache/doris/catalog/SchemaTable.java
index d2f11508db2..d3da150b3fa 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/SchemaTable.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/SchemaTable.java
@@ -816,6 +816,17 @@ public class SchemaTable extends Table {
.column("MAX_RESERVED_SNAPSHOTS",
ScalarType.createType(PrimitiveType.BIGINT))
.column("SNAPSHOT_INTERVAL_SECONDS",
ScalarType.createType(PrimitiveType.BIGINT))
.build()))
+ .put("authentication_integrations",
+ new SchemaTable(SystemIdGenerator.getNextId(),
"authentication_integrations", TableType.SCHEMA,
+ builder().column("NAME", ScalarType.createVarchar(256))
+ .column("TYPE", ScalarType.createVarchar(64))
+ .column("PROPERTIES",
ScalarType.createStringType())
+ .column("COMMENT", ScalarType.createStringType())
+ .column("CREATE_USER",
ScalarType.createStringType())
+ .column("CREATE_TIME",
ScalarType.createStringType())
+ .column("ALTER_USER",
ScalarType.createStringType())
+ .column("MODIFY_TIME",
ScalarType.createStringType())
+ .build()))
.build();
private boolean fetchAllFe = false;
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/MetadataGenerator.java
b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/MetadataGenerator.java
index fd70373fbdb..97af4edbafc 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/MetadataGenerator.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/MetadataGenerator.java
@@ -18,6 +18,7 @@
package org.apache.doris.tablefunction;
import org.apache.doris.analysis.UserIdentity;
+import org.apache.doris.authentication.AuthenticationIntegrationMeta;
import org.apache.doris.blockrule.SqlBlockRule;
import org.apache.doris.catalog.Column;
import org.apache.doris.catalog.DataProperty;
@@ -47,6 +48,7 @@ import org.apache.doris.common.Pair;
import org.apache.doris.common.proc.FrontendsProcNode;
import org.apache.doris.common.proc.PartitionsProcDir;
import org.apache.doris.common.profile.RuntimeProfile;
+import org.apache.doris.common.util.DatasourcePrintableMap;
import org.apache.doris.common.util.DebugUtil;
import org.apache.doris.common.util.NetUtils;
import org.apache.doris.common.util.TimeUtils;
@@ -128,7 +130,9 @@ import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
@@ -158,6 +162,8 @@ public class MetadataGenerator {
private static final ImmutableMap<String, Integer>
SQL_BLOCK_RULE_STATUS_COLUMN_TO_INDEX;
+ private static final ImmutableMap<String, Integer>
AUTHENTICATION_INTEGRATIONS_COLUMN_TO_INDEX;
+
static {
ImmutableMap.Builder<String, Integer> activeQueriesbuilder = new
ImmutableMap.Builder();
List<Column> activeQueriesColList =
SchemaTable.TABLE_MAP.get("active_queries").getFullSchema();
@@ -235,6 +241,15 @@ public class MetadataGenerator {
sqlBlockRuleStatusBuilder.put(sqlBlockRuleStatusBuilderColList.get(i).getName().toLowerCase(),
i);
}
SQL_BLOCK_RULE_STATUS_COLUMN_TO_INDEX =
sqlBlockRuleStatusBuilder.build();
+
+ ImmutableMap.Builder<String, Integer>
authenticationIntegrationsBuilder = new ImmutableMap.Builder();
+ List<Column> authenticationIntegrationsColList =
SchemaTable.TABLE_MAP.get("authentication_integrations")
+ .getFullSchema();
+ for (int i = 0; i < authenticationIntegrationsColList.size(); i++) {
+ authenticationIntegrationsBuilder.put(
+
authenticationIntegrationsColList.get(i).getName().toLowerCase(), i);
+ }
+ AUTHENTICATION_INTEGRATIONS_COLUMN_TO_INDEX =
authenticationIntegrationsBuilder.build();
}
public static TFetchSchemaTableDataResult
getMetadataTable(TFetchSchemaTableDataRequest request) throws TException {
@@ -349,6 +364,10 @@ public class MetadataGenerator {
result = sqlBlockRuleStatusMetadataResult(schemaTableParams);
columnIndex = SQL_BLOCK_RULE_STATUS_COLUMN_TO_INDEX;
break;
+ case AUTHENTICATION_INTEGRATIONS:
+ result =
authenticationIntegrationsMetadataResult(schemaTableParams);
+ columnIndex = AUTHENTICATION_INTEGRATIONS_COLUMN_TO_INDEX;
+ break;
default:
return errorResult("invalid schema table name.");
}
@@ -689,6 +708,83 @@ public class MetadataGenerator {
return result;
}
+ private static TFetchSchemaTableDataResult
authenticationIntegrationsMetadataResult(
+ TSchemaTableRequestParams params) {
+ if (!params.isSetCurrentUserIdent()) {
+ return errorResult("current user ident is not set.");
+ }
+ UserIdentity currentUserIdentity =
UserIdentity.fromThrift(params.getCurrentUserIdent());
+ TFetchSchemaTableDataResult result = new TFetchSchemaTableDataResult();
+ List<TRow> dataBatch = Lists.newArrayList();
+ result.setDataBatch(dataBatch);
+ result.setStatus(new TStatus(TStatusCode.OK));
+ if
(!Env.getCurrentEnv().getAccessManager().checkGlobalPriv(currentUserIdentity,
PrivPredicate.ADMIN)) {
+ return result;
+ }
+
+ List<Expression> conjuncts = Collections.EMPTY_LIST;
+ if (params.isSetFrontendConjuncts()) {
+ conjuncts =
FrontendConjunctsUtils.convertToExpression(params.getFrontendConjuncts());
+ }
+ List<Expression> nameConjuncts =
FrontendConjunctsUtils.filterBySlotName(conjuncts, "NAME");
+ List<Expression> typeConjuncts =
FrontendConjunctsUtils.filterBySlotName(conjuncts, "TYPE");
+
+ for (AuthenticationIntegrationMeta meta :
Env.getCurrentEnv().getAuthenticationIntegrationMgr()
+ .getAuthenticationIntegrations().values()) {
+ if (FrontendConjunctsUtils.isFiltered(nameConjuncts, "NAME",
meta.getName())
+ || FrontendConjunctsUtils.isFiltered(typeConjuncts,
"TYPE", meta.getType())) {
+ continue;
+ }
+ TRow row = new TRow();
+ row.addToColumnValue(new TCell().setStringVal(meta.getName()));
+ row.addToColumnValue(new TCell().setStringVal(meta.getType()));
+ row.addToColumnValue(new
TCell().setStringVal(maskAuthenticationProperties(meta.getProperties())));
+ if (meta.getComment() == null) {
+ row.addToColumnValue(new TCell());
+ } else {
+ row.addToColumnValue(new
TCell().setStringVal(meta.getComment()));
+ }
+ row.addToColumnValue(new
TCell().setStringVal(meta.getCreateUser()));
+ row.addToColumnValue(new
TCell().setStringVal(meta.getCreateTimeString()));
+ row.addToColumnValue(new
TCell().setStringVal(meta.getAlterUser()));
+ row.addToColumnValue(new
TCell().setStringVal(meta.getModifyTimeString()));
+ dataBatch.add(row);
+ }
+ return result;
+ }
+
+ private static String maskAuthenticationProperties(Map<String, String>
properties) {
+ Map<String, String> maskedProperties = new LinkedHashMap<>();
+ for (Map.Entry<String, String> entry : properties.entrySet()) {
+ if (shouldMaskAuthenticationProperty(entry.getKey())) {
+ maskedProperties.put(entry.getKey(),
DatasourcePrintableMap.PASSWORD_MASK);
+ } else {
+ maskedProperties.put(entry.getKey(), entry.getValue());
+ }
+ }
+ return new DatasourcePrintableMap<>(maskedProperties, "=", true,
false).toString();
+ }
+
+ private static boolean shouldMaskAuthenticationProperty(String key) {
+ String lowerCaseKey = key.toLowerCase(Locale.ROOT);
+ return DatasourcePrintableMap.SENSITIVE_KEY.contains(key)
+ || lowerCaseKey.startsWith("secret.")
+ || lowerCaseKey.endsWith(".password")
+ || lowerCaseKey.endsWith("_password")
+ || lowerCaseKey.equals("secret")
+ || lowerCaseKey.endsWith(".secret")
+ || lowerCaseKey.endsWith("_secret")
+ || lowerCaseKey.endsWith(".secret_key")
+ || lowerCaseKey.endsWith("_secret_key")
+ || lowerCaseKey.endsWith(".token")
+ || lowerCaseKey.endsWith("_token")
+ || lowerCaseKey.endsWith(".credential")
+ || lowerCaseKey.endsWith("_credential")
+ || lowerCaseKey.endsWith(".keytab")
+ || lowerCaseKey.endsWith("_keytab")
+ || lowerCaseKey.endsWith("keytab_content");
+ }
+
private static TFetchSchemaTableDataResult
viewDependencyMetadataResult(TSchemaTableRequestParams params) {
if (!params.isSetCurrentUserIdent()) {
return errorResult("current user ident is not set.");
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/catalog/SchemaTableTest.java
b/fe/fe-core/src/test/java/org/apache/doris/catalog/SchemaTableTest.java
index 03c6d092eab..9970d50a37a 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/catalog/SchemaTableTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/catalog/SchemaTableTest.java
@@ -92,5 +92,15 @@ public class SchemaTableTest {
SchemaTable viewDependency = (SchemaTable)
SchemaTable.TABLE_MAP.get("view_dependency");
Assertions.assertFalse(viewDependency.shouldFetchAllFe());
Assertions.assertFalse(viewDependency.shouldAddAgg());
+
+ SchemaTable authenticationIntegrations =
+ (SchemaTable)
SchemaTable.TABLE_MAP.get("authentication_integrations");
+ Assertions.assertFalse(authenticationIntegrations.shouldFetchAllFe());
+ Assertions.assertFalse(authenticationIntegrations.shouldAddAgg());
+ Assertions.assertEquals(8,
authenticationIntegrations.getFullSchema().size());
+ Assertions.assertEquals("CREATE_USER",
authenticationIntegrations.getFullSchema().get(4).getName());
+ Assertions.assertEquals("CREATE_TIME",
authenticationIntegrations.getFullSchema().get(5).getName());
+ Assertions.assertEquals("ALTER_USER",
authenticationIntegrations.getFullSchema().get(6).getName());
+ Assertions.assertEquals("MODIFY_TIME",
authenticationIntegrations.getFullSchema().get(7).getName());
}
}
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/service/FrontendServiceImplTest.java
b/fe/fe-core/src/test/java/org/apache/doris/service/FrontendServiceImplTest.java
index f78d1bdf6e7..00903892b23 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/service/FrontendServiceImplTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/service/FrontendServiceImplTest.java
@@ -23,6 +23,7 @@ import org.apache.doris.catalog.OlapTable;
import org.apache.doris.catalog.Partition;
import org.apache.doris.common.Config;
import org.apache.doris.common.FeConstants;
+import org.apache.doris.common.util.DatasourcePrintableMap;
import org.apache.doris.nereids.parser.NereidsParser;
import org.apache.doris.nereids.trees.plans.commands.CreateDatabaseCommand;
import org.apache.doris.nereids.trees.plans.commands.CreateTableCommand;
@@ -41,6 +42,7 @@ import org.apache.doris.thrift.TMetadataTableRequestParams;
import org.apache.doris.thrift.TMetadataType;
import org.apache.doris.thrift.TNullableStringLiteral;
import org.apache.doris.thrift.TSchemaTableName;
+import org.apache.doris.thrift.TSchemaTableRequestParams;
import org.apache.doris.thrift.TShowUserRequest;
import org.apache.doris.thrift.TShowUserResult;
import org.apache.doris.thrift.TStatusCode;
@@ -57,6 +59,7 @@ import org.junit.rules.ExpectedException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
@@ -247,4 +250,57 @@ public class FrontendServiceImplTest {
TShowUserResult result = impl.showUser(request);
System.out.println(result);
}
+
+ @Test
+ public void testFetchAuthenticationIntegrationsSchemaTableData() throws
Exception {
+ String integrationName = "test_authentication_integration";
+
Env.getCurrentEnv().getAuthenticationIntegrationMgr().dropAuthenticationIntegration(integrationName,
true);
+
+ LinkedHashMap<String, String> properties = new LinkedHashMap<>();
+ properties.put("type", "ldap");
+ properties.put("server", "ldap://127.0.0.1:389");
+ properties.put("bind_password", "plain_secret");
+ properties.put("secret.endpoint", "masked_by_prefix");
+ Env.getCurrentEnv().getAuthenticationIntegrationMgr()
+ .createAuthenticationIntegration(
+ integrationName, false, properties, "ldap comment",
connectContext.getQualifiedUser());
+
+ try {
+ FrontendServiceImpl impl = new FrontendServiceImpl(exeEnv);
+ TFetchSchemaTableDataRequest request = new
TFetchSchemaTableDataRequest();
+
request.setSchemaTableName(TSchemaTableName.AUTHENTICATION_INTEGRATIONS);
+ TSchemaTableRequestParams params = new TSchemaTableRequestParams();
+
params.setCurrentUserIdent(connectContext.getCurrentUserIdentity().toThrift());
+ request.setSchemaTableParams(params);
+
+ TFetchSchemaTableDataResult result =
impl.fetchSchemaTableData(request);
+ Assert.assertEquals(TStatusCode.OK,
result.getStatus().getStatusCode());
+
+ List<String> rowValues = result.getDataBatch().stream()
+ .filter(row ->
integrationName.equals(row.getColumnValue().get(0).getStringVal()))
+ .map(row -> row.getColumnValue().stream()
+ .map(cell -> cell.isSetStringVal() ?
cell.getStringVal() : null)
+ .collect(Collectors.toList()))
+ .findFirst()
+ .orElseThrow(() -> new
java.lang.AssertionError("authentication integration row not found"));
+
+ Assert.assertEquals(integrationName, rowValues.get(0));
+ Assert.assertEquals("ldap", rowValues.get(1));
+ Assert.assertTrue(rowValues.get(2).contains("\"server\" =
\"ldap://127.0.0.1:389\""));
+ Assert.assertTrue(rowValues.get(2).contains(
+ "\"bind_password\" = \"" +
DatasourcePrintableMap.PASSWORD_MASK + "\""));
+ Assert.assertTrue(rowValues.get(2).contains(
+ "\"secret.endpoint\" = \"" +
DatasourcePrintableMap.PASSWORD_MASK + "\""));
+ Assert.assertFalse(rowValues.get(2).contains("plain_secret"));
+ Assert.assertFalse(rowValues.get(2).contains("masked_by_prefix"));
+ Assert.assertEquals("ldap comment", rowValues.get(3));
+ Assert.assertEquals(connectContext.getQualifiedUser(),
rowValues.get(4));
+ Assert.assertNotNull(rowValues.get(5));
+ Assert.assertFalse(rowValues.get(5).isEmpty());
+ Assert.assertEquals(connectContext.getQualifiedUser(),
rowValues.get(6));
+ Assert.assertEquals(rowValues.get(5), rowValues.get(7));
+ } finally {
+
Env.getCurrentEnv().getAuthenticationIntegrationMgr().dropAuthenticationIntegration(integrationName,
true);
+ }
+ }
}
diff --git a/gensrc/thrift/Descriptors.thrift b/gensrc/thrift/Descriptors.thrift
index 730a74ae6f3..7d3883c9f9b 100644
--- a/gensrc/thrift/Descriptors.thrift
+++ b/gensrc/thrift/Descriptors.thrift
@@ -214,6 +214,7 @@ enum TSchemaTableType {
SCH_LOAD_JOBS = 64;
SCH_FILE_CACHE_INFO = 65;
SCH_DATABASE_PROPERTIES = 66;
+ SCH_AUTHENTICATION_INTEGRATIONS = 67;
}
enum THdfsCompression {
diff --git a/gensrc/thrift/FrontendService.thrift
b/gensrc/thrift/FrontendService.thrift
index ccd082e7f52..aeb5b06efb6 100644
--- a/gensrc/thrift/FrontendService.thrift
+++ b/gensrc/thrift/FrontendService.thrift
@@ -870,6 +870,7 @@ enum TSchemaTableName {
VIEW_DEPENDENCY = 11,
SQL_BLOCK_RULE_STATUS = 12,
DATABASE_PROPERTIES = 13,
+ AUTHENTICATION_INTEGRATIONS = 14,
}
struct TMetadataTableRequestParams {
diff --git
a/regression-test/suites/auth_p0/test_authentication_integration_auth.groovy
b/regression-test/suites/auth_p0/test_authentication_integration_auth.groovy
index c65ac577574..caec26467d2 100644
--- a/regression-test/suites/auth_p0/test_authentication_integration_auth.groovy
+++ b/regression-test/suites/auth_p0/test_authentication_integration_auth.groovy
@@ -35,7 +35,8 @@ suite("test_authentication_integration_auth", "p0,auth") {
PROPERTIES (
'type'='ldap',
'ldap.server'='ldap://127.0.0.1:389',
- 'ldap.admin_password'='123456'
+ 'ldap.admin_password'='123456',
+ 'secret.endpoint'='secret_create_value'
)
COMMENT 'for regression test'
"""
@@ -60,12 +61,42 @@ suite("test_authentication_integration_auth", "p0,auth") {
ALTER AUTHENTICATION INTEGRATION ${integrationName}
SET PROPERTIES (
'ldap.server'='ldap://127.0.0.1:1389',
- 'ldap.admin_password'='abcdef'
+ 'ldap.admin_password'='abcdef',
+ 'secret.endpoint'='secret_alter_value'
)
"""
sql """ALTER AUTHENTICATION INTEGRATION ${integrationName} SET COMMENT
'updated comment'"""
+ def result = sql """
+ SELECT
+ NAME,
+ TYPE,
+ PROPERTIES,
+ COMMENT,
+ CREATE_USER,
+ CREATE_TIME,
+ ALTER_USER,
+ MODIFY_TIME
+ FROM information_schema.authentication_integrations
+ WHERE NAME = '${integrationName}'
+ ORDER BY NAME
+ """
+ assertEquals(1, result.size())
+ assertEquals(8, result[0].size())
+ assertEquals(integrationName, result[0][0])
+ assertEquals("ldap", result[0][1])
+ assertTrue(result[0][2].contains("\"ldap.server\" =
\"ldap://127.0.0.1:1389\""))
+ assertTrue(result[0][2].contains("\"ldap.admin_password\" = \"*XXX\""))
+ assertTrue(result[0][2].contains("\"secret.endpoint\" = \"*XXX\""))
+ assertTrue(!result[0][2].contains("abcdef"))
+ assertTrue(!result[0][2].contains("secret_alter_value"))
+ assertEquals("updated comment", result[0][3])
+ assertTrue(result[0][4] != null && result[0][4].length() > 0)
+ assertTrue(result[0][5] != null && result[0][5].length() > 0)
+ assertTrue(result[0][6] != null && result[0][6].length() > 0)
+ assertTrue(result[0][7] != null && result[0][7].length() > 0)
+
test {
sql """DROP AUTHENTICATION INTEGRATION
${integrationName}_not_exist"""
exception "does not exist"
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]