Repository: hive Updated Branches: refs/heads/master e1fa2787f -> 15039c05b
HIVE-14889: Beeline leaks sensitive environment variables of HiveServer2 when you type set; (Vihang Karajgaonkar, reviewed by Sergio Pena) Project: http://git-wip-us.apache.org/repos/asf/hive/repo Commit: http://git-wip-us.apache.org/repos/asf/hive/commit/15039c05 Tree: http://git-wip-us.apache.org/repos/asf/hive/tree/15039c05 Diff: http://git-wip-us.apache.org/repos/asf/hive/diff/15039c05 Branch: refs/heads/master Commit: 15039c05b75ddd955dac0fe66b9aef486a45f1a1 Parents: e1fa278 Author: Sergio Pena <[email protected]> Authored: Fri Oct 7 10:05:03 2016 -0500 Committer: Sergio Pena <[email protected]> Committed: Fri Oct 7 10:05:03 2016 -0500 ---------------------------------------------------------------------- .../hadoop/hive/ql/processors/SetProcessor.java | 33 +++++- .../hive/ql/processors/TestSetProcessor.java | 114 ++++++++++++++++--- 2 files changed, 129 insertions(+), 18 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/hive/blob/15039c05/ql/src/java/org/apache/hadoop/hive/ql/processors/SetProcessor.java ---------------------------------------------------------------------- diff --git a/ql/src/java/org/apache/hadoop/hive/ql/processors/SetProcessor.java b/ql/src/java/org/apache/hadoop/hive/ql/processors/SetProcessor.java index c9d06ba..eab1886 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/processors/SetProcessor.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/processors/SetProcessor.java @@ -54,6 +54,8 @@ public class SetProcessor implements CommandProcessor { private static final String prefix = "set: "; private static final Set<String> removedConfigs = Sets.newHashSet("hive.mapred.supports.subdirectories","hive.enforce.sorting","hive.enforce.bucketing", "hive.outerjoin.supports.filters"); + private static final String[] PASSWORD_STRINGS = new String[] {"password", "paswd", "pswd"}; + public static boolean getBoolean(String value) { if (value.equals("on") || value.equals("true")) { return true; @@ -88,16 +90,35 @@ public class SetProcessor implements CommandProcessor { } for (Map.Entry<String, String> entry : mapToSortedMap(System.getenv()).entrySet()) { + if(isHidden(entry.getKey())) { + continue; + } ss.out.println(ENV_PREFIX+entry.getKey() + "=" + entry.getValue()); } for (Map.Entry<String, String> entry : propertiesToSortedMap(System.getProperties()).entrySet() ) { + if(isHidden(entry.getKey())) { + continue; + } ss.out.println(SYSTEM_PREFIX+entry.getKey() + "=" + entry.getValue()); } } + /* + * Checks if the value contains any of the PASSWORD_STRINGS and if yes + * return true + */ + private boolean isHidden(String key) { + for(String p : PASSWORD_STRINGS) { + if(key.toLowerCase().contains(p)) { + return true; + } + } + return false; + } + private void dumpOption(String s) { SessionState ss = SessionState.get(); @@ -249,7 +270,11 @@ public class SetProcessor implements CommandProcessor { String propName = varname.substring(SYSTEM_PREFIX.length()); String result = System.getProperty(propName); if (result != null) { - ss.out.println(SYSTEM_PREFIX + propName + "=" + result); + if(isHidden(propName)) { + ss.out.println(SYSTEM_PREFIX + propName + " is a hidden config"); + } else { + ss.out.println(SYSTEM_PREFIX + propName + "=" + result); + } return createProcessorSuccessResponse(); } else { ss.out.println(propName + " is undefined as a system property"); @@ -258,7 +283,11 @@ public class SetProcessor implements CommandProcessor { } else if (varname.indexOf(ENV_PREFIX) == 0) { String var = varname.substring(ENV_PREFIX.length()); if (System.getenv(var) != null) { - ss.out.println(ENV_PREFIX + var + "=" + System.getenv(var)); + if(isHidden(var)) { + ss.out.println(ENV_PREFIX + var + " is a hidden config"); + } else { + ss.out.println(ENV_PREFIX + var + "=" + System.getenv(var)); + } return createProcessorSuccessResponse(); } else { ss.out.println(varname + " is undefined as an environmental variable"); http://git-wip-us.apache.org/repos/asf/hive/blob/15039c05/ql/src/test/org/apache/hadoop/hive/ql/processors/TestSetProcessor.java ---------------------------------------------------------------------- diff --git a/ql/src/test/org/apache/hadoop/hive/ql/processors/TestSetProcessor.java b/ql/src/test/org/apache/hadoop/hive/ql/processors/TestSetProcessor.java index bff643a..4eb4941 100644 --- a/ql/src/test/org/apache/hadoop/hive/ql/processors/TestSetProcessor.java +++ b/ql/src/test/org/apache/hadoop/hive/ql/processors/TestSetProcessor.java @@ -20,35 +20,117 @@ package org.apache.hadoop.hive.ql.processors; import java.io.ByteArrayOutputStream; import java.io.PrintStream; - -import junit.framework.Assert; +import java.lang.reflect.Field; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import org.apache.hadoop.hive.conf.HiveConf; +import org.apache.hadoop.hive.conf.SystemVariables; import org.apache.hadoop.hive.ql.session.SessionState; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; public class TestSetProcessor { - @Test - public void testHiddenConfig() throws Exception { + private static final String TEST_SYSTEM_PROPERTY = "testSystemPropertyPassword"; + private static final String TEST_SYSTEM_PROPERTY_VALUE = "testSystemPropertyValue"; + private static final String TEST_ENV_VAR_PASSWORD_VALUE = "testEnvPasswordValue"; + private static final String TEST_ENV_VAR_PASSWORD = "testEnvPassword"; + private ByteArrayOutputStream baos; + private static SessionState state; + private SetProcessor processor; + + @BeforeClass + public static void before() throws Exception { + Map<String, String> env = new HashMap<>(); + env.put(TEST_ENV_VAR_PASSWORD, TEST_ENV_VAR_PASSWORD_VALUE); + setEnv(env); + System.setProperty(TEST_SYSTEM_PROPERTY, TEST_SYSTEM_PROPERTY_VALUE); HiveConf conf = new HiveConf(); SessionState.start(conf); - SessionState state = SessionState.get(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - state.out = new PrintStream(baos); - SetProcessor processor = new SetProcessor(); - processor.run(""); - state.out.flush(); - String ret = baos.toString(); - Assert.assertFalse(ret.contains(HiveConf.ConfVars.METASTOREPWD.varname + "=")); - Assert.assertFalse(ret.contains(HiveConf.ConfVars.HIVE_SERVER2_SSL_KEYSTORE_PASSWORD.varname + "=")); + state = SessionState.get(); + } + @Before + public void setupTest() { baos = new ByteArrayOutputStream(); state.out = new PrintStream(baos); - processor.run(HiveConf.ConfVars.METASTOREPWD.varname); + processor = new SetProcessor(); + } + + @Test + public void testHiddenConfig() throws Exception { + runSetProcessor(""); + String output = baos.toString(); + Assert.assertFalse(output.contains(HiveConf.ConfVars.METASTOREPWD.varname + "=")); + Assert.assertFalse(output.contains(HiveConf.ConfVars.HIVE_SERVER2_SSL_KEYSTORE_PASSWORD.varname + "=")); + } + + @Test + public void testHiddenConfigSetVarName() { + runSetProcessor(HiveConf.ConfVars.METASTOREPWD.varname); + String output = baos.toString(); + Assert.assertTrue(output.contains("hidden")); + } + + @Test + public void testEnvPasswordMask() throws Exception { + runSetProcessor(""); + String output = baos.toString(); + Assert.assertFalse(output.contains(TEST_ENV_VAR_PASSWORD + "=")); + } + + @Test + public void testEnvPasswordMaskIndividual() throws Exception { + runSetProcessor(SystemVariables.ENV_PREFIX + TEST_ENV_VAR_PASSWORD); + String output = baos.toString(); + Assert.assertFalse(output.contains(TEST_ENV_VAR_PASSWORD_VALUE)); + Assert.assertTrue(output.contains("hidden")); + } + + @Test + public void testSystemProperty() throws Exception { + runSetProcessor(""); + String output = baos.toString(); + Assert.assertFalse(output.contains(TEST_SYSTEM_PROPERTY + "=")); + } + + @Test + public void testSystemPropertyIndividual() throws Exception { + runSetProcessor(SystemVariables.SYSTEM_PREFIX + TEST_SYSTEM_PROPERTY); + String output = baos.toString(); + Assert.assertFalse(output.contains(TEST_SYSTEM_PROPERTY_VALUE)); + Assert.assertTrue(output.contains("hidden")); + } + + /* + * Simulates the set <command>; + */ + private void runSetProcessor(String command) { + processor.run(command); state.out.flush(); - ret = new String(baos.toByteArray()); - Assert.assertTrue(baos.toString().contains("hidden")); + } + + /* + * Dirty hack to set the environment variables using reflection code. This method is for testing + * purposes only and should not be used elsewhere + */ + private final static void setEnv(Map<String, String> newenv) throws Exception { + Class[] classes = Collections.class.getDeclaredClasses(); + Map<String, String> env = System.getenv(); + for (Class cl : classes) { + if ("java.util.Collections$UnmodifiableMap".equals(cl.getName())) { + Field field = cl.getDeclaredField("m"); + field.setAccessible(true); + Object obj = field.get(env); + Map<String, String> map = (Map<String, String>) obj; + map.clear(); + map.putAll(newenv); + } + } } }
