Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id B1C13200B9A for ; Fri, 7 Oct 2016 17:10:07 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id B0923160AE8; Fri, 7 Oct 2016 15:10:07 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id C4054160AD6 for ; Fri, 7 Oct 2016 17:10:06 +0200 (CEST) Received: (qmail 15468 invoked by uid 500); 7 Oct 2016 15:10:05 -0000 Mailing-List: contact commits-help@hive.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: hive-dev@hive.apache.org Delivered-To: mailing list commits@hive.apache.org Received: (qmail 15457 invoked by uid 99); 7 Oct 2016 15:10:05 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 07 Oct 2016 15:10:05 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id ACD41DFD4C; Fri, 7 Oct 2016 15:10:05 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: spena@apache.org To: commits@hive.apache.org Message-Id: X-Mailer: ASF-Git Admin Mailer Subject: hive git commit: HIVE-14889: Beeline leaks sensitive environment variables of HiveServer2 when you type set; (Vihang Karajgaonkar, reviewed by Sergio Pena) Date: Fri, 7 Oct 2016 15:10:05 +0000 (UTC) archived-at: Fri, 07 Oct 2016 15:10:07 -0000 Repository: hive Updated Branches: refs/heads/branch-2.1 3327795cc -> eb1d5d01a 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/eb1d5d01 Tree: http://git-wip-us.apache.org/repos/asf/hive/tree/eb1d5d01 Diff: http://git-wip-us.apache.org/repos/asf/hive/diff/eb1d5d01 Branch: refs/heads/branch-2.1 Commit: eb1d5d01a480d89e830d4533effa25fc8f4bd9a6 Parents: 3327795 Author: Sergio Pena Authored: Fri Oct 7 10:05:03 2016 -0500 Committer: Sergio Pena Committed: Fri Oct 7 10:06:19 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/eb1d5d01/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 190b92a..0ac28e3 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 removedConfigs = Sets.newHashSet("hive.mapred.supports.subdirectories","hive.enforce.sorting","hive.enforce.bucketing"); + 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 entry : mapToSortedMap(System.getenv()).entrySet()) { + if(isHidden(entry.getKey())) { + continue; + } ss.out.println(ENV_PREFIX+entry.getKey() + "=" + entry.getValue()); } for (Map.Entry 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/eb1d5d01/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 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 ; + */ + 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 newenv) throws Exception { + Class[] classes = Collections.class.getDeclaredClasses(); + Map 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 map = (Map) obj; + map.clear(); + map.putAll(newenv); + } + } } }