This is an automated email from the ASF dual-hosted git repository.
gavinchou 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 d72635e919b [chore](tde) Add scoped KMS credentials to regression
clusters (#64564)
d72635e919b is described below
commit d72635e919b495627812e152c617828fc85d82af
Author: Jamie <[email protected]>
AuthorDate: Tue Jul 7 01:50:48 2026 +0800
[chore](tde) Add scoped KMS credentials to regression clusters (#64564)
- Add provider-scoped TDE credential options for AWS and Aliyun in
doris-compose.
- Pass scoped TDE credentials into FE container environment variables.
- Extend regression cluster options/configuration for scoped
credentials.
- Mask TDE credential values in regression logs and log only set/unset
status for configured secrets.
---
docker/runtime/doris-compose/cluster.py | 25 ++++++++++-
docker/runtime/doris-compose/command.py | 25 +++++++++++
docker/runtime/doris-compose/resource/init_fe.sh | 4 ++
.../org/apache/doris/regression/Config.groovy | 32 +++++++++++++-
.../apache/doris/regression/ConfigOptions.groovy | 32 +++++++++++++-
.../doris/regression/suite/SuiteCluster.groovy | 51 +++++++++++++++++++++-
6 files changed, 163 insertions(+), 6 deletions(-)
diff --git a/docker/runtime/doris-compose/cluster.py
b/docker/runtime/doris-compose/cluster.py
index 769a1af4be0..965c4057b9d 100644
--- a/docker/runtime/doris-compose/cluster.py
+++ b/docker/runtime/doris-compose/cluster.py
@@ -371,6 +371,18 @@ class Node(object):
def get_tde_sk(self):
return self.cluster.tde_sk
+ def get_tde_aws_ak(self):
+ return getattr(self.cluster, "tde_aws_ak", "")
+
+ def get_tde_aws_sk(self):
+ return getattr(self.cluster, "tde_aws_sk", "")
+
+ def get_tde_aliyun_ak(self):
+ return getattr(self.cluster, "tde_aliyun_ak", "")
+
+ def get_tde_aliyun_sk(self):
+ return getattr(self.cluster, "tde_aliyun_sk", "")
+
def get_default_named_ports(self):
# port_name : default_port
# the port_name come from fe.conf, be.conf, cloud.conf, etc
@@ -414,6 +426,10 @@ class Node(object):
"ENABLE_STORAGE_VAULT": 1 if getattr(self.cluster,
"enable_storage_vault", False) else 0,
"TDE_AK": self.get_tde_ak(),
"TDE_SK": self.get_tde_sk(),
+ "TDE_AWS_AK": self.get_tde_aws_ak(),
+ "TDE_AWS_SK": self.get_tde_aws_sk(),
+ "TDE_ALIYUN_AK": self.get_tde_aliyun_ak(),
+ "TDE_ALIYUN_SK": self.get_tde_aliyun_sk(),
}
if self.cluster.is_cloud:
@@ -933,6 +949,7 @@ class Cluster(object):
local_network_ip, fe_follower, be_disks, be_cluster, reg_be,
extra_hosts, env, coverage_dir, cloud_store_config,
sql_mode_node_mgr, be_metaservice_endpoint, be_cluster_id,
tde_ak, tde_sk,
+ tde_aws_ak, tde_aws_sk, tde_aliyun_ak, tde_aliyun_sk,
external_ms_cluster, instance_id, cluster_snapshot="",
enable_storage_vault=False):
self.name = name
@@ -974,6 +991,10 @@ class Cluster(object):
self.be_cluster_id = be_cluster_id
self.tde_ak = tde_ak
self.tde_sk = tde_sk
+ self.tde_aws_ak = tde_aws_ak
+ self.tde_aws_sk = tde_aws_sk
+ self.tde_aliyun_ak = tde_aliyun_ak
+ self.tde_aliyun_sk = tde_aliyun_sk
@staticmethod
def new(name, image, is_cloud, is_root_user, fe_config, be_config,
@@ -981,6 +1002,7 @@ class Cluster(object):
fe_follower, be_disks, be_cluster, reg_be, extra_hosts, env,
coverage_dir, cloud_store_config, sql_mode_node_mgr,
be_metaservice_endpoint, be_cluster_id, tde_ak, tde_sk,
+ tde_aws_ak, tde_aws_sk, tde_aliyun_ak, tde_aliyun_sk,
external_ms_cluster, instance_id, cluster_snapshot="",
enable_storage_vault=False):
if not os.path.exists(LOCAL_DORIS_PATH):
@@ -997,7 +1019,8 @@ class Cluster(object):
be_disks, be_cluster, reg_be, extra_hosts, env,
coverage_dir, cloud_store_config,
sql_mode_node_mgr, be_metaservice_endpoint,
- be_cluster_id, tde_ak, tde_sk,
external_ms_cluster,
+ be_cluster_id, tde_ak, tde_sk, tde_aws_ak,
tde_aws_sk,
+ tde_aliyun_ak, tde_aliyun_sk,
external_ms_cluster,
instance_id, cluster_snapshot,
enable_storage_vault)
os.makedirs(cluster.get_path(), exist_ok=True)
os.makedirs(get_status_path(name), exist_ok=True)
diff --git a/docker/runtime/doris-compose/command.py
b/docker/runtime/doris-compose/command.py
index 11151ca7f1b..d3cb0821b4a 100644
--- a/docker/runtime/doris-compose/command.py
+++ b/docker/runtime/doris-compose/command.py
@@ -554,6 +554,30 @@ class UpCommand(Command):
default="",
help="tde sk")
+ parser.add_argument(
+ "--tde-aws-ak",
+ type=str,
+ default="",
+ help="tde aws ak")
+
+ parser.add_argument(
+ "--tde-aws-sk",
+ type=str,
+ default="",
+ help="tde aws sk")
+
+ parser.add_argument(
+ "--tde-aliyun-ak",
+ type=str,
+ default="",
+ help="tde aliyun ak")
+
+ parser.add_argument(
+ "--tde-aliyun-sk",
+ type=str,
+ default="",
+ help="tde aliyun sk")
+
# if default==True, use this style to parser, like --detach
if self._support_boolean_action():
parser.add_argument(
@@ -684,6 +708,7 @@ class UpCommand(Command):
args.be_disks if args.be_disks is not None else ["HDD=1"],
args.be_cluster, args.reg_be, args.extra_hosts, args.env,
args.coverage_dir, cloud_store_config, args.sql_mode_node_mgr,
args.be_metaservice_endpoint, args.be_cluster_id, args.tde_ak,
args.tde_sk,
+ args.tde_aws_ak, args.tde_aws_sk, args.tde_aliyun_ak,
args.tde_aliyun_sk,
external_ms_cluster, instance_id, cluster_snapshot,
enable_storage_vault)
LOG.info("Create new cluster {} succ, cluster path is {}".format(
diff --git a/docker/runtime/doris-compose/resource/init_fe.sh
b/docker/runtime/doris-compose/resource/init_fe.sh
index 4e3a3ffffe7..380d791e362 100755
--- a/docker/runtime/doris-compose/resource/init_fe.sh
+++ b/docker/runtime/doris-compose/resource/init_fe.sh
@@ -92,6 +92,10 @@ fe_daemon() {
run_fe() {
export DORIS_TDE_AK=${TDE_AK}
export DORIS_TDE_SK=${TDE_SK}
+ export DORIS_TDE_AWS_AK=${TDE_AWS_AK}
+ export DORIS_TDE_AWS_SK=${TDE_AWS_SK}
+ export DORIS_TDE_ALIYUN_AK=${TDE_ALIYUN_AK}
+ export DORIS_TDE_ALIYUN_SK=${TDE_ALIYUN_SK}
health_log "run start_fe.sh"
# Add cluster_snapshot parameter for first startup only (
diff --git
a/regression-test/framework/src/main/groovy/org/apache/doris/regression/Config.groovy
b/regression-test/framework/src/main/groovy/org/apache/doris/regression/Config.groovy
index c666af4162c..3b5e335a96c 100644
---
a/regression-test/framework/src/main/groovy/org/apache/doris/regression/Config.groovy
+++
b/regression-test/framework/src/main/groovy/org/apache/doris/regression/Config.groovy
@@ -170,6 +170,10 @@ class Config {
public String tdeAk
public String tdeSk
+ public String tdeAwsAk
+ public String tdeAwsSk
+ public String tdeAliyunAk
+ public String tdeAliyunSk
public String tdeKeyEndpoint
public String tdeKeyRegion
public String tdeKeyProvider
@@ -240,6 +244,10 @@ class Config {
String cloudVersion,
String tdeAk,
String tdeSk,
+ String tdeAwsAk,
+ String tdeAwsSk,
+ String tdeAliyunAk,
+ String tdeAliyunSk,
String tdeKeyEndpoint,
String tdeKeyRegion,
String tdeKeyProvider,
@@ -304,6 +312,10 @@ class Config {
this.cloudVersion = cloudVersion
this.tdeAk = tdeAk
this.tdeSk = tdeSk
+ this.tdeAwsAk = tdeAwsAk
+ this.tdeAwsSk = tdeAwsSk
+ this.tdeAliyunAk = tdeAliyunAk
+ this.tdeAliyunSk = tdeAliyunSk
this.tdeKeyEndpoint = tdeKeyEndpoint
this.tdeKeyRegion = tdeKeyRegion
this.tdeKeyProvider = tdeKeyProvider
@@ -313,6 +325,10 @@ class Config {
this.enableClusterSnapshot = enableClusterSnapshot
}
+ static String secretStatus(String value) {
+ return value == null || value == "" ? "unset" : "set"
+ }
+
static String removeDirectoryPrefix(String str) {
def prefixes = ["./regression-test/suites/", "regression-test/suites/"]
@@ -512,9 +528,17 @@ class Config {
log.info("cloudVersion is ${config.cloudVersion}".toString())
config.tdeAk = cmd.getOptionValue(tdeAkOpt, config.tdeAk)
- log.info("tdeAk is ${config.tdeAk}".toString())
+ log.info("tdeAk is ${secretStatus(config.tdeAk)}".toString())
config.tdeSk = cmd.getOptionValue(tdeSkOpt, config.tdeSk)
- log.info("tdeSk is ${config.tdeSk}".toString())
+ log.info("tdeSk is ${secretStatus(config.tdeSk)}".toString())
+ config.tdeAwsAk = cmd.getOptionValue(tdeAwsAkOpt, config.tdeAwsAk)
+ log.info("tdeAwsAk is ${secretStatus(config.tdeAwsAk)}".toString())
+ config.tdeAwsSk = cmd.getOptionValue(tdeAwsSkOpt, config.tdeAwsSk)
+ log.info("tdeAwsSk is ${secretStatus(config.tdeAwsSk)}".toString())
+ config.tdeAliyunAk = cmd.getOptionValue(tdeAliyunAkOpt,
config.tdeAliyunAk)
+ log.info("tdeAliyunAk is
${secretStatus(config.tdeAliyunAk)}".toString())
+ config.tdeAliyunSk = cmd.getOptionValue(tdeAliyunSkOpt,
config.tdeAliyunSk)
+ log.info("tdeAliyunSk is
${secretStatus(config.tdeAliyunSk)}".toString())
config.tdeKeyEndpoint = cmd.getOptionValue(tdeKeyEndpointOpt,
config.tdeKeyEndpoint)
log.info("tdeKeyEndpoint is ${config.tdeKeyEndpoint}".toString())
config.tdeKeyRegion = cmd.getOptionValue(tdeKeyRegionOpt,
config.tdeKeyRegion)
@@ -657,6 +681,10 @@ class Config {
configToString(obj.cloudVersion),
configToString(obj.tdeAk),
configToString(obj.tdeSk),
+ configToString(obj.tdeAwsAk),
+ configToString(obj.tdeAwsSk),
+ configToString(obj.tdeAliyunAk),
+ configToString(obj.tdeAliyunSk),
configToString(obj.tdeKeyEndpoint),
configToString(obj.tdeKeyRegion),
configToString(obj.tdeKeyProvider),
diff --git
a/regression-test/framework/src/main/groovy/org/apache/doris/regression/ConfigOptions.groovy
b/regression-test/framework/src/main/groovy/org/apache/doris/regression/ConfigOptions.groovy
index 0f55f55fabb..c62599a5976 100644
---
a/regression-test/framework/src/main/groovy/org/apache/doris/regression/ConfigOptions.groovy
+++
b/regression-test/framework/src/main/groovy/org/apache/doris/regression/ConfigOptions.groovy
@@ -100,6 +100,10 @@ class ConfigOptions {
static Option cloudVersionOpt
static Option tdeAkOpt
static Option tdeSkOpt
+ static Option tdeAwsAkOpt
+ static Option tdeAwsSkOpt
+ static Option tdeAliyunAkOpt
+ static Option tdeAliyunSkOpt
static Option tdeKeyEndpointOpt
static Option tdeKeyRegionOpt
static Option tdeKeyProviderOpt
@@ -611,14 +615,34 @@ class ConfigOptions {
.build()
tdeAkOpt = Option.builder("tdeAk")
.required(false)
- .hasArg(false)
+ .hasArg(true)
.desc("TDE Access Key")
.build();
tdeSkOpt = Option.builder("tdeSk")
.required(false)
- .hasArg(false)
+ .hasArg(true)
.desc("TDE Secret Key")
.build();
+ tdeAwsAkOpt = Option.builder("tdeAwsAk")
+ .required(false)
+ .hasArg(true)
+ .desc("TDE AWS Access Key")
+ .build();
+ tdeAwsSkOpt = Option.builder("tdeAwsSk")
+ .required(false)
+ .hasArg(true)
+ .desc("TDE AWS Secret Key")
+ .build();
+ tdeAliyunAkOpt = Option.builder("tdeAliyunAk")
+ .required(false)
+ .hasArg(true)
+ .desc("TDE Aliyun Access Key")
+ .build();
+ tdeAliyunSkOpt = Option.builder("tdeAliyunSk")
+ .required(false)
+ .hasArg(true)
+ .desc("TDE Aliyun Secret Key")
+ .build();
tdeKeyEndpointOpt = Option.builder("tdeKeyEndpoint")
.required(false)
.hasArg(false)
@@ -714,6 +738,10 @@ class ConfigOptions {
.addOption(cloudVersionOpt)
.addOption(tdeAkOpt)
.addOption(tdeSkOpt)
+ .addOption(tdeAwsAkOpt)
+ .addOption(tdeAwsSkOpt)
+ .addOption(tdeAliyunAkOpt)
+ .addOption(tdeAliyunSkOpt)
.addOption(tdeKeyEndpointOpt)
.addOption(tdeKeyRegionOpt)
.addOption(tdeKeyProviderOpt)
diff --git
a/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/SuiteCluster.groovy
b/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/SuiteCluster.groovy
index ef5282eb218..899ba118f5e 100644
---
a/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/SuiteCluster.groovy
+++
b/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/SuiteCluster.groovy
@@ -100,6 +100,10 @@ class ClusterOptions {
String tdeAk = "";
String tdeSk = "";
+ String tdeAwsAk = "";
+ String tdeAwsSk = "";
+ String tdeAliyunAk = "";
+ String tdeAliyunSk = "";
// Use external meta service cluster (shared MS/FDB)
// Specify the cluster name that provides MS/FDB services
@@ -422,6 +426,26 @@ class SuiteCluster {
cmd += options.tdeSk
}
+ if (options.tdeAwsAk != null && options.tdeAwsAk != "") {
+ cmd += ['--tde-aws-ak']
+ cmd += options.tdeAwsAk
+ }
+
+ if (options.tdeAwsSk != null && options.tdeAwsSk != "") {
+ cmd += ['--tde-aws-sk']
+ cmd += options.tdeAwsSk
+ }
+
+ if (options.tdeAliyunAk != null && options.tdeAliyunAk != "") {
+ cmd += ['--tde-aliyun-ak']
+ cmd += options.tdeAliyunAk
+ }
+
+ if (options.tdeAliyunSk != null && options.tdeAliyunSk != "") {
+ cmd += ['--tde-aliyun-sk']
+ cmd += options.tdeAliyunSk
+ }
+
if (options.externalMsCluster != null && options.externalMsCluster !=
"") {
cmd += ['--external-ms', options.externalMsCluster]
}
@@ -914,9 +938,34 @@ class SuiteCluster {
}
// Execute command with proper argument list to avoid shell escaping issues
+ private static List<String> maskSensitiveArgs(List<String> cmdList) {
+ Set<String> sensitiveOptions = [
+ '--tde-ak',
+ '--tde-sk',
+ '--tde-aws-ak',
+ '--tde-aws-sk',
+ '--tde-aliyun-ak',
+ '--tde-aliyun-sk'
+ ] as Set
+ List<String> masked = []
+ boolean maskNext = false
+ for (String arg : cmdList) {
+ if (maskNext) {
+ masked += '***'
+ maskNext = false
+ continue
+ }
+ masked += arg
+ if (sensitiveOptions.contains(arg)) {
+ maskNext = true
+ }
+ }
+ return masked
+ }
+
private Object runCmdList(List<String> cmdList, int timeoutSecond = 60)
throws Exception {
def fullCmdList = ['python', '-W', 'ignore', config.dorisComposePath]
+ cmdList + ['-v', '--output-json']
- logger.info('Run doris compose cmd: {}', fullCmdList.join(' '))
+ logger.info('Run doris compose cmd: {}',
maskSensitiveArgs(fullCmdList).join(' '))
def proc = fullCmdList.execute()
def outBuf = new StringBuilder()
def errBuf = new StringBuilder()
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]