Skip to content

Commit

Permalink
SAMZA-589; sanitize sensitive data beore displaying configs to UI
Browse files Browse the repository at this point in the history
  • Loading branch information
twbecker authored and criccomini committed Mar 16, 2015
1 parent 8170149 commit cad2c82
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 7 deletions.
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ rat {
'**/.git/**',
'**/.gitignore',
'**/.gradle/**',
'**/.idea/**',
'**/.project',
'**/.settings/**',
'**/.DS_Store/**',
Expand Down
5 changes: 4 additions & 1 deletion docs/learn/documentation/versioned/jobs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ Configuration keys that absolutely must be defined for a Samza job are:

### Configuration Keys

A complete list of configuration keys can be found on the [Configuration Table](configuration-table.html) page.
A complete list of configuration keys can be found on the [Configuration Table](configuration-table.html) page. Note
that configuration keys prefixed with "sensitive." are treated specially, in that the values associated with such keys
will be masked in logs and Samza's YARN ApplicationMaster UI. This is to prevent accidental disclosure only; no
encryption is done.

## [Packaging »](packaging.html)
5 changes: 5 additions & 0 deletions samza-api/src/main/java/org/apache/samza/config/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
* Store and retrieve named, typed values as configuration for classes implementing this interface.
*/
public abstract class Config implements Map<String, String> {
public static final String SENSITIVE_PREFIX = "sensitive.";
public static final String SENSITIVE_MASK = "********";

public Config subset(String prefix) {
return subset(prefix, true);
}
Expand Down Expand Up @@ -221,6 +224,8 @@ public Date getDate(String k, SimpleDateFormat format, Date defaultValue) {
}
}

public abstract Config sanitize();

public void clear() {
throw new ConfigException("Config is immutable.");
}
Expand Down
21 changes: 18 additions & 3 deletions samza-api/src/main/java/org/apache/samza/config/MapConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@
*/
public class MapConfig extends Config {
private final Map<String, String> map;

public MapConfig() {
this.map = Collections.emptyMap();
}

public MapConfig(Map<String, String> map) {
this(Collections.singletonList(map));
}
Expand Down Expand Up @@ -78,6 +78,21 @@ public boolean containsValue(Object v) {
return map.containsKey(v);
}

@Override
public Config sanitize() {
return new MapConfig(sanitizeMap());
}

private Map<String, String> sanitizeMap() {
Map<String, String> sanitized = new HashMap<String, String>(map);
for (Entry<String, String> entry : sanitized.entrySet()) {
if (entry.getKey().startsWith(SENSITIVE_PREFIX)) {
entry.setValue(SENSITIVE_MASK);
}
}
return sanitized;
}

@Override
public int hashCode() {
final int prime = 31;
Expand Down Expand Up @@ -105,6 +120,6 @@ public boolean equals(Object obj) {

@Override
public String toString() {
return map.toString();
return sanitizeMap().toString();
}
}
21 changes: 20 additions & 1 deletion samza-api/src/test/java/org/apache/samza/config/TestConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

package org.apache.samza.config;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.*;

import java.util.Map;
import java.util.HashMap;
Expand Down Expand Up @@ -61,4 +61,23 @@ public void testgetShortAndLong() {
Class c4 = getClass(mc.getLong("testkey", defaultLong));
assertEquals(Long.class, c4);
}

@Test
public void testSanitize() {
Map<String, String> m = new HashMap<String, String>() {{
put("key1", "value1");
put("key2", "value2");
put("sensitive.key3", "secret1");
put("sensitive.key4", "secret2");
}};

Config config = new MapConfig(m);
assertFalse(config.toString().contains("secret"));

Config sanitized = config.sanitize();
assertEquals("value1", sanitized.get("key1"));
assertEquals("value2", sanitized.get("key2"));
assertEquals(Config.SENSITIVE_MASK, sanitized.get("sensitive.key3"));
assertEquals(Config.SENSITIVE_MASK, sanitized.get("sensitive.key4"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,6 @@ class ApplicationMasterRestServlet(config: Config, state: SamzaAppMasterState, r
}

get("/config") {
jsonMapper.writeValueAsString(new HashMap[String, Object](config.toMap))
jsonMapper.writeValueAsString(new HashMap[String, Object](config.sanitize.toMap))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class ApplicationMasterWebServlet(config: Config, state: SamzaAppMasterState) ex

get("/") {
layoutTemplate("/WEB-INF/views/index.scaml",
"config" -> TreeMap(config.toMap.toArray: _*),
"config" -> TreeMap(config.sanitize.toMap.toArray: _*),
"state" -> state,
"rmHttpAddress" -> WebAppUtils.getRMWebAppURLWithScheme(yarnConfig))
}
Expand Down

0 comments on commit cad2c82

Please sign in to comment.