This is an automated email from the ASF dual-hosted git repository.
rzo1 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/storm.git
The following commit(s) were added to refs/heads/master by this push:
new c030b1b7a Apply one redaction rule to configuration served and logged
by Storm (#9069)
c030b1b7a is described below
commit c030b1b7a0e42d38ac3ac6fcb1532a545ac76db4
Author: Richard Zowalla <[email protected]>
AuthorDate: Fri Sep 4 15:44:59 2026 +0200
Apply one redaction rule to configuration served and logged by Storm (#9069)
* Apply one redaction rule to configuration served by the Nimbus API
Nimbus hands configuration to clients from more than one operation, and the
treatment differed between them. getNimbusConf and getTopologyConf redact
credential values before returning them. getTopologyPageInfo did not, and it
serves the daemon configuration merged with the topology configuration, so
it
returned strictly more than either of the other two.
Route both topology-facing operations through a single helper so the rule is
the same wherever Nimbus serializes a configuration map for a client:
- getTopologyPageInfo masks before serializing into
TopologyPageInfo.topology_conf, which the UI renders as the
"configuration"
field of the topology page and of the metrics response.
- getTopologyConf moves from maskPasswords to maskCredentials. That
additionally covers keys no annotated field declares, since plugins read
their own keys straight out of the map, so an operator-supplied password
key in a topology configuration is covered too.
- The Blowfish tuple serializer key is handled inside the helper rather than
repeated at each call site. Its constant lives outside the config classes,
so the annotation scan cannot see it, and its name matches no credential
pattern.
Masking applies to the copy that gets serialized. The daemon's own
configuration and the stored topology configuration are left alone, and
workers continue to read real values from the blobstore-distributed
configuration rather than from these responses.
The only consumers of TopologyPageInfo.topology_conf are the two UI display
paths in UIHelpers, so no functional reader loses a value it depends on.
* Stop logging configuration values that carry credentials
Seven sites wrote a configuration map, or an object that stringifies one,
straight into a log:
- RedisKeyValueStateProvider logged the full merged worker configuration on
its error path. Worker masks that same map two frames away.
- CommonKafkaSpoutConfig.toString appended every Kafka property value.
KafkaSpoutConfig already overrode it without them, so only the Trident
spouts, which inherit the base, were affected.
- KafkaBolt.toString appended the producer properties.
- HdfsSpout logged each HDFS configuration override value.
- TopologySpoutLag logged the whole component configuration.
- ResourceUtils trace-logged the component json_conf, for bolts and spouts.
- StormSubmitter logged the serialized topology configuration.
Where the credential name pattern is enough, the value is masked. Where it
is
not -- sasl.jaas.config matches neither the annotation set nor the pattern
--
the log now names the keys instead of their values, which is what these
lines
were diagnostically useful for anyway.
Also corrects the "proerties" spelling in KafkaBolt.toString.
---
.../org/apache/storm/hdfs/spout/HdfsSpout.java | 4 +-
.../org/apache/storm/kafka/bolt/KafkaBolt.java | 2 +-
.../spout/internal/CommonKafkaSpoutConfig.java | 2 +-
.../redis/state/RedisKeyValueStateProvider.java | 3 +-
.../src/jvm/org/apache/storm/StormSubmitter.java | 10 +-
.../org/apache/storm/utils/TopologySpoutLag.java | 2 +-
.../org/apache/storm/daemon/nimbus/Nimbus.java | 29 +++-
.../storm/scheduler/resource/ResourceUtils.java | 4 +-
.../nimbus/NimbusGetTopologyPageInfoTest.java | 155 +++++++++++++++++++++
9 files changed, 195 insertions(+), 16 deletions(-)
diff --git
a/external/storm-hdfs/src/main/java/org/apache/storm/hdfs/spout/HdfsSpout.java
b/external/storm-hdfs/src/main/java/org/apache/storm/hdfs/spout/HdfsSpout.java
index 446fb8585..c7a2bb161 100644
---
a/external/storm-hdfs/src/main/java/org/apache/storm/hdfs/spout/HdfsSpout.java
+++
b/external/storm-hdfs/src/main/java/org/apache/storm/hdfs/spout/HdfsSpout.java
@@ -34,6 +34,7 @@ import org.apache.storm.task.TopologyContext;
import org.apache.storm.topology.OutputFieldsDeclarer;
import org.apache.storm.topology.base.BaseRichSpout;
import org.apache.storm.tuple.Fields;
+import org.apache.storm.utils.ConfigUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -416,7 +417,8 @@ public class HdfsSpout extends BaseRichSpout {
Map<String, Object> map = (Map<String, Object>)
conf.get(configKey);
if (map != null) {
for (String keyName : map.keySet()) {
- LOG.info("HDFS Config override : {} = {} ", keyName,
String.valueOf(map.get(keyName)));
+ LOG.info("HDFS Config override : {} = {} ", keyName,
+ ConfigUtils.isCredentialKey(keyName) ? "*****" :
String.valueOf(map.get(keyName)));
this.hdfsConfig.set(keyName,
String.valueOf(map.get(keyName)));
}
try {
diff --git
a/external/storm-kafka-client/src/main/java/org/apache/storm/kafka/bolt/KafkaBolt.java
b/external/storm-kafka-client/src/main/java/org/apache/storm/kafka/bolt/KafkaBolt.java
index 498499965..5929cafe8 100644
---
a/external/storm-kafka-client/src/main/java/org/apache/storm/kafka/bolt/KafkaBolt.java
+++
b/external/storm-kafka-client/src/main/java/org/apache/storm/kafka/bolt/KafkaBolt.java
@@ -242,6 +242,6 @@ public class KafkaBolt<K, V> extends
BaseTickTupleAwareRichBolt {
+ " topicSelector: " + topicSelector
+ " fireAndForget: " + fireAndForget
+ " async: " + async
- + " proerties: " + boltSpecifiedProperties;
+ + " properties: " + boltSpecifiedProperties.stringPropertyNames();
}
}
diff --git
a/external/storm-kafka-client/src/main/java/org/apache/storm/kafka/spout/internal/CommonKafkaSpoutConfig.java
b/external/storm-kafka-client/src/main/java/org/apache/storm/kafka/spout/internal/CommonKafkaSpoutConfig.java
index d0e748232..ad31f40f9 100644
---
a/external/storm-kafka-client/src/main/java/org/apache/storm/kafka/spout/internal/CommonKafkaSpoutConfig.java
+++
b/external/storm-kafka-client/src/main/java/org/apache/storm/kafka/spout/internal/CommonKafkaSpoutConfig.java
@@ -268,7 +268,7 @@ public abstract class CommonKafkaSpoutConfig<K, V>
implements Serializable {
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
- .append("kafkaProps", kafkaProps)
+ .append("kafkaProps", kafkaProps.keySet())
.append("partitionRefreshPeriodMs", partitionRefreshPeriodMs)
.append("pollTimeoutMs", pollTimeoutMs)
.append("topicFilter", topicFilter)
diff --git
a/external/storm-redis/src/main/java/org/apache/storm/redis/state/RedisKeyValueStateProvider.java
b/external/storm-redis/src/main/java/org/apache/storm/redis/state/RedisKeyValueStateProvider.java
index 26518d4b6..b8cd377c1 100644
---
a/external/storm-redis/src/main/java/org/apache/storm/redis/state/RedisKeyValueStateProvider.java
+++
b/external/storm-redis/src/main/java/org/apache/storm/redis/state/RedisKeyValueStateProvider.java
@@ -25,6 +25,7 @@ import org.apache.storm.state.Serializer;
import org.apache.storm.state.State;
import org.apache.storm.state.StateProvider;
import org.apache.storm.task.TopologyContext;
+import org.apache.storm.utils.ConfigUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -39,7 +40,7 @@ public class RedisKeyValueStateProvider implements
StateProvider {
try {
return getRedisKeyValueState(namespace, topoConf, context,
getStateConfig(topoConf));
} catch (Exception ex) {
- LOG.error("Error loading config from storm conf {}", topoConf);
+ LOG.error("Error loading config from storm conf {}",
ConfigUtils.maskCredentials(topoConf));
throw new RuntimeException(ex);
}
}
diff --git a/storm-client/src/jvm/org/apache/storm/StormSubmitter.java
b/storm-client/src/jvm/org/apache/storm/StormSubmitter.java
index 1bc5627e1..d522fd95b 100644
--- a/storm-client/src/jvm/org/apache/storm/StormSubmitter.java
+++ b/storm-client/src/jvm/org/apache/storm/StormSubmitter.java
@@ -45,6 +45,7 @@ import org.apache.storm.shade.net.minidev.json.JSONValue;
import org.apache.storm.shade.org.apache.commons.lang3.StringUtils;
import org.apache.storm.thrift.TException;
import org.apache.storm.utils.BufferFileInputStream;
+import org.apache.storm.utils.ConfigUtils;
import org.apache.storm.utils.NimbusClient;
import org.apache.storm.utils.Utils;
import org.apache.storm.utils.WrappedInvalidTopologyException;
@@ -264,6 +265,7 @@ public class StormSubmitter {
}
try {
String serConf = JSONValue.toJSONString(topoConf);
+ String maskedSerConf =
JSONValue.toJSONString(ConfigUtils.maskCredentials(topoConf));
try (NimbusClient client =
NimbusClient.Builder.withConf(conf).asUser(asUser).build()) {
if (!isTopologyNameAllowed(name, client)) {
throw new RuntimeException("Topology name " + name + " is
either not allowed or it already exists on the cluster");
@@ -291,7 +293,8 @@ public class StormSubmitter {
try {
setDependencyBlobsToTopology(topology, jarsBlobKeys,
artifactsBlobKeys);
- submitTopologyInDistributeMode(name, topology, opts,
progressListener, asUser, conf, serConf, client);
+ submitTopologyInDistributeMode(name, topology, opts,
progressListener, asUser, conf, serConf,
+ maskedSerConf, client);
} catch (AlreadyAliveException | InvalidTopologyException |
AuthorizationException e) {
// the topology was rejected, so the blobs it refers to
are unreachable; their keys are
// unique to this submission, so nothing else can be using
them
@@ -349,10 +352,11 @@ public class StormSubmitter {
private static void submitTopologyInDistributeMode(String name,
StormTopology topology, SubmitOptions opts,
ProgressListener
progressListener, String asUser, Map<String, Object> conf,
- String serConf,
NimbusClient client) throws TException {
+ String serConf, String
maskedSerConf, NimbusClient client)
+ throws TException {
try {
String jar = submitJarAs(conf, System.getProperty("storm.jar"),
progressListener, client);
- LOG.info("Submitting topology {} in distributed mode with conf
{}", name, serConf);
+ LOG.info("Submitting topology {} in distributed mode with conf
{}", name, maskedSerConf);
Utils.addVersions(topology);
if (opts != null) {
client.getClient().submitTopologyWithOpts(name, jar, serConf,
topology, opts);
diff --git a/storm-core/src/jvm/org/apache/storm/utils/TopologySpoutLag.java
b/storm-core/src/jvm/org/apache/storm/utils/TopologySpoutLag.java
index d9bbc92b7..8875e9e52 100644
--- a/storm-core/src/jvm/org/apache/storm/utils/TopologySpoutLag.java
+++ b/storm-core/src/jvm/org/apache/storm/utils/TopologySpoutLag.java
@@ -116,7 +116,7 @@ public class TopologySpoutLag {
}
private static List<String>
getCommandLineOptionsForNewKafkaSpout(Map<String, Object> jsonConf) {
- LOGGER.debug("json configuration: {}", jsonConf);
+ LOGGER.debug("json configuration keys: {}", jsonConf.keySet());
List<String> commands = new ArrayList<>();
commands.add("-t");
diff --git
a/storm-server/src/main/java/org/apache/storm/daemon/nimbus/Nimbus.java
b/storm-server/src/main/java/org/apache/storm/daemon/nimbus/Nimbus.java
index 1698a5ce8..cc08fe220 100644
--- a/storm-server/src/main/java/org/apache/storm/daemon/nimbus/Nimbus.java
+++ b/storm-server/src/main/java/org/apache/storm/daemon/nimbus/Nimbus.java
@@ -794,6 +794,24 @@ public class Nimbus implements Iface, Shutdownable,
DaemonCommon {
return tc.readTopology(topoId, NIMBUS_SUBJECT);
}
+ /**
+ * Mask the credential values in a config map that is about to be
serialized to a client. Nimbus serves config over
+ * several read-only operations, and a caller authorized for those is not
necessarily authorized to hold the cluster's
+ * or the topology's secrets. This covers what {@link
ConfigUtils#maskCredentials(Map)} covers, plus the Blowfish
+ * tuple-serializer key, whose constant lives outside the config classes
so the annotation scan cannot see it and
+ * whose name matches no credential pattern.
+ *
+ * @param conf the config about to be served
+ * @return a copy of the config with credential values replaced
+ */
+ private static Map<String, Object> maskCredentialsForApi(Map<String,
Object> conf) {
+ Map<String, Object> masked = new
HashMap<>(ConfigUtils.maskCredentials(conf));
+ if (masked.get(BlowfishTupleSerializer.SECRET_KEY) instanceof String) {
+ masked.put(BlowfishTupleSerializer.SECRET_KEY, "*****");
+ }
+ return masked;
+ }
+
/**
* convert {topology-id -> SchedulerAssignment} to {topology-id ->
{executor [node port]}}.
*
@@ -4732,7 +4750,10 @@ public class Nimbus implements Iface, Shutdownable,
DaemonCommon {
topoPageInfo.set_name(topoName);
topoPageInfo.set_status(extractStatusStr(base));
topoPageInfo.set_uptime_secs(Time.deltaSecs(launchTimeSecs));
- topoPageInfo.set_topology_conf(JSONValue.toJSONString(topoConf));
+ // topoConf is the daemon conf merged with the topology conf, so
it carries Nimbus secrets
+ // (the ZooKeeper digest payload, Thrift/Netty TLS store
passwords) on top of the topology's own.
+ // getTopologyPageInfo is a topology read-only operation, so mask
before it leaves Nimbus.
+
topoPageInfo.set_topology_conf(JSONValue.toJSONString(maskCredentialsForApi(topoConf)));
topoPageInfo.set_replication_count(getBlobReplicationCount(ConfigUtils.masterStormCodeKey(topoId)));
if (base.is_set_component_debug()) {
DebugOptions debug = base.get_component_debug().get(topoId);
@@ -5046,11 +5067,7 @@ public class Nimbus implements Iface, Shutdownable,
DaemonCommon {
Map<String, Object> checkConf = Utils.merge(conf, topoConf);
String topoName = (String) checkConf.get(Config.TOPOLOGY_NAME);
checkAuthorization(topoName, checkConf, "getTopologyConf");
- Map<String, Object> maskedConf = new
HashMap<>(ConfigUtils.maskPasswords(topoConf));
- if (maskedConf.get(BlowfishTupleSerializer.SECRET_KEY) instanceof
String) {
- maskedConf.put(BlowfishTupleSerializer.SECRET_KEY, "*****");
- }
- return JSONValue.toJSONString(maskedConf);
+ return JSONValue.toJSONString(maskCredentialsForApi(topoConf));
} catch (Exception e) {
LOG.warn("Get topo conf exception. (topology id='{}')", id, e);
if (e instanceof TException) {
diff --git
a/storm-server/src/main/java/org/apache/storm/scheduler/resource/ResourceUtils.java
b/storm-server/src/main/java/org/apache/storm/scheduler/resource/ResourceUtils.java
index 401758fbc..e4a523ca6 100644
---
a/storm-server/src/main/java/org/apache/storm/scheduler/resource/ResourceUtils.java
+++
b/storm-server/src/main/java/org/apache/storm/scheduler/resource/ResourceUtils.java
@@ -46,7 +46,7 @@ public class ResourceUtils {
NormalizedResourceRequest topologyResources = new
NormalizedResourceRequest(bolt.getValue().get_common(),
topologyConf, bolt.getKey());
if (LOG.isTraceEnabled()) {
- LOG.trace("Turned {} into {}",
bolt.getValue().get_common().get_json_conf(), topologyResources);
+ LOG.trace("Turned component {} into {}", bolt.getKey(),
topologyResources);
}
boltResources.put(bolt.getKey(), topologyResources);
}
@@ -71,7 +71,7 @@ public class ResourceUtils {
NormalizedResourceRequest topologyResources = new
NormalizedResourceRequest(spout.getValue().get_common(),
topologyConf, spout.getKey());
if (LOG.isTraceEnabled()) {
- LOG.trace("Turned {} into {}",
spout.getValue().get_common().get_json_conf(), topologyResources);
+ LOG.trace("Turned component {} into {}", spout.getKey(),
topologyResources);
}
spoutResources.put(spout.getKey(), topologyResources);
}
diff --git
a/storm-server/src/test/java/org/apache/storm/daemon/nimbus/NimbusGetTopologyPageInfoTest.java
b/storm-server/src/test/java/org/apache/storm/daemon/nimbus/NimbusGetTopologyPageInfoTest.java
new file mode 100644
index 000000000..c9bf4d2c5
--- /dev/null
+++
b/storm-server/src/test/java/org/apache/storm/daemon/nimbus/NimbusGetTopologyPageInfoTest.java
@@ -0,0 +1,155 @@
+/*
+ * 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.
+ */
+
+package org.apache.storm.daemon.nimbus;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import net.minidev.json.JSONValue;
+
+import org.apache.storm.Config;
+import org.apache.storm.DaemonConfig;
+import org.apache.storm.LocalCluster;
+import org.apache.storm.blobstore.BlobStore;
+import org.apache.storm.cluster.IStormClusterState;
+import org.apache.storm.generated.StormBase;
+import org.apache.storm.generated.StormTopology;
+import org.apache.storm.generated.TopologyPageInfo;
+import org.apache.storm.generated.TopologyStatus;
+import
org.apache.storm.scheduler.resource.TestUtilsForResourceAwareScheduler.TestSpout;
+import org.apache.storm.security.serialization.BlowfishTupleSerializer;
+import org.apache.storm.topology.TopologyBuilder;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentMatchers;
+import org.mockito.Mockito;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * getTopologyPageInfo serves the daemon configuration merged with the
topology configuration, and it is a
+ * topology read-only operation, so a principal that is only allowed to look
at a topology reaches it. The
+ * merged map must therefore not carry credential values off the daemon.
+ */
+public class NimbusGetTopologyPageInfoTest {
+
+ private static final String MASKED = "*****";
+ private static final String TOPO_NAME =
"test-get-topology-page-info-masking";
+ private static final String TOPO_ID = "fake-id";
+
+ private static final String PLUGIN_SECRET_KEY = "some.plugin.password";
+ private static final String NIMBUS_KEYSTORE_PASSWORD_KEY =
"nimbus.thrift.tls.keystore.password";
+
+ @SuppressWarnings("unchecked")
+ private static Map<String, Object> parse(String json) {
+ return (Map<String, Object>) JSONValue.parse(json);
+ }
+
+ private static StormTopology userTopology() {
+ TopologyBuilder builder = new TopologyBuilder();
+ // setNumTasks so the component conf carries topology.tasks, which
submit-time normalization
+ // would otherwise have filled in before the conf reached the cache
this test mocks
+ builder.setSpout("spout-1", new TestSpout(), 1).setNumTasks(1);
+ return builder.createTopology();
+ }
+
+ private static Map<String, Object> storedTopoConf() {
+ Map<String, Object> topoConf = new HashMap<>();
+ topoConf.put(Config.TOPOLOGY_NAME, TOPO_NAME);
+ topoConf.put(Config.TOPOLOGY_WORKERS, 1);
+ topoConf.put(Config.TOPOLOGY_ACKER_EXECUTORS, 0);
+ topoConf.put(Config.TOPOLOGY_EVENTLOGGER_EXECUTORS, 0);
+ topoConf.put(Config.TOPOLOGY_MESSAGE_TIMEOUT_SECS, 30);
+ topoConf.put(Config.STORM_ZOOKEEPER_TOPOLOGY_AUTH_PAYLOAD,
"topology-zk-secret");
+ topoConf.put(BlowfishTupleSerializer.SECRET_KEY, "0123456789abcdef");
+ return topoConf;
+ }
+
+ private static StormBase stormBase() {
+ StormBase base = new StormBase();
+ base.set_name(TOPO_NAME);
+ base.set_owner("some-owner");
+ base.set_status(TopologyStatus.ACTIVE);
+ base.set_num_workers(1);
+ base.set_launch_time_secs(1);
+ return base;
+ }
+
+ @Test
+ public void getTopologyPageInfoMasksDaemonAndTopologyCredentials() throws
Exception {
+ IStormClusterState clusterState =
Mockito.mock(IStormClusterState.class);
+ BlobStore blobStore = Mockito.mock(BlobStore.class);
+ TopoCache topoCache = Mockito.mock(TopoCache.class);
+
+ Map<String, Object> storedConf = storedTopoConf();
+
+ Map<String, Object> daemonConf = new HashMap<>();
+ daemonConf.put(DaemonConfig.NIMBUS_AUTHORIZER,
"org.apache.storm.security.auth.authorizer.NoopAuthorizer");
+ daemonConf.put(DaemonConfig.SUPERVISOR_AUTHORIZER,
"org.apache.storm.security.auth.authorizer.NoopAuthorizer");
+ // the daemon-side values that the merge pulls in on top of the
topology's own conf
+ daemonConf.put(Config.STORM_ZOOKEEPER_AUTH_PAYLOAD,
"cluster-zk-digest-secret");
+ daemonConf.put(NIMBUS_KEYSTORE_PASSWORD_KEY, "keystore-secret");
+ daemonConf.put(PLUGIN_SECRET_KEY, "plugin-secret");
+
+ try (LocalCluster cluster = new LocalCluster.Builder()
+ .withClusterState(clusterState)
+ .withBlobStore(blobStore)
+ .withTopoCache(topoCache)
+ .withDaemonConf(daemonConf)
+ .build()) {
+ Nimbus nimbus = cluster.getNimbus();
+
+ Mockito.when(topoCache.readTopoConf(Mockito.any(String.class),
ArgumentMatchers.any()))
+ .thenReturn(storedConf);
+ Mockito.when(topoCache.readTopology(Mockito.any(String.class),
ArgumentMatchers.any()))
+ .thenReturn(userTopology());
+ Mockito.when(clusterState.stormBase(Mockito.eq(TOPO_ID),
ArgumentMatchers.any()))
+ .thenReturn(stormBase());
+ Mockito.when(clusterState.assignmentInfo(Mockito.eq(TOPO_ID),
ArgumentMatchers.any()))
+ .thenReturn(null);
+
+ TopologyPageInfo pageInfo = nimbus.getTopologyPageInfo(TOPO_ID,
":all-time", false);
+ Map<String, Object> served = parse(pageInfo.get_topology_conf());
+
+ // daemon-side credentials, which only this operation merges in
+ assertEquals(MASKED,
served.get(Config.STORM_ZOOKEEPER_AUTH_PAYLOAD),
+ "the cluster ZooKeeper auth payload should be masked");
+ assertEquals(MASKED, served.get(NIMBUS_KEYSTORE_PASSWORD_KEY),
+ "TLS keystore passwords should be masked");
+ assertEquals(MASKED, served.get(PLUGIN_SECRET_KEY),
+ "a plugin key whose name denotes a secret should be masked");
+
+ // topology-side credentials, masked on getTopologyConf and
equally reachable here
+ assertEquals(MASKED,
served.get(Config.STORM_ZOOKEEPER_TOPOLOGY_AUTH_PAYLOAD),
+ "the topology ZooKeeper auth payload should be masked");
+ assertEquals(MASKED,
served.get(BlowfishTupleSerializer.SECRET_KEY),
+ "the tuple serializer key should be masked");
+
+ // values that carry no credential are served untouched
+ assertEquals(TOPO_NAME, served.get(Config.TOPOLOGY_NAME));
+ assertEquals(1, ((Number)
served.get(Config.TOPOLOGY_WORKERS)).intValue());
+ assertEquals(30, ((Number)
served.get(Config.TOPOLOGY_MESSAGE_TIMEOUT_SECS)).intValue());
+
+ // masking is applied to the served copy, never to the daemon's
own configuration
+ assertEquals("cluster-zk-digest-secret",
nimbus.getConf().get(Config.STORM_ZOOKEEPER_AUTH_PAYLOAD),
+ "the daemon conf should keep its own values");
+ assertEquals("topology-zk-secret",
storedConf.get(Config.STORM_ZOOKEEPER_TOPOLOGY_AUTH_PAYLOAD),
+ "the stored topology conf should keep its own values");
+ }
+ }
+}