You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by sm...@apache.org on 2013/05/22 08:09:38 UTC

svn commit: r1485073 - in /incubator/ambari/trunk: ./ ambari-server/src/main/java/org/apache/ambari/server/configuration/ ambari-server/src/main/java/org/apache/ambari/server/utils/ ambari-server/src/test/java/org/apache/ambari/server/security/ ambari-...

Author: smohanty
Date: Wed May 22 06:09:38 2013
New Revision: 1485073

URL: http://svn.apache.org/r1485073
Log:
AMBARI-2181. keys/pass.txt file is readable by everyone. (smohanty)

Added:
    incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/utils/TestShellCommandUtil.java
Modified:
    incubator/ambari/trunk/CHANGES.txt
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/utils/ShellCommandUtil.java
    incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/security/TestPassFileGeneration.java

Modified: incubator/ambari/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/CHANGES.txt?rev=1485073&r1=1485072&r2=1485073&view=diff
==============================================================================
--- incubator/ambari/trunk/CHANGES.txt (original)
+++ incubator/ambari/trunk/CHANGES.txt Wed May 22 06:09:38 2013
@@ -873,6 +873,8 @@ Trunk (unreleased changes):
 
  BUG FIXES
 
+ AMBARI-2181. keys/pass.txt file is readable by everyone. (smohanty)
+
  AMBARI-2177. HBase Smoke Test shows success even if it fails. (smohanty)
 
  AMBARI-2176. Incorrect unit displayed for "dfs.datanode.du.reserved" and

Modified: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java?rev=1485073&r1=1485072&r2=1485073&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java (original)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java Wed May 22 06:09:38 2013
@@ -22,6 +22,7 @@ import org.apache.ambari.server.orm.JPAT
 import org.apache.ambari.server.orm.PersistenceType;
 import org.apache.ambari.server.security.ClientSecurityType;
 import org.apache.ambari.server.security.authorization.LdapServerProperties;
+import org.apache.ambari.server.utils.ShellCommandUtil;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang.RandomStringUtils;
 import org.slf4j.Logger;
@@ -253,7 +254,8 @@ public class Configuration {
         randStr = RandomStringUtils.randomAlphanumeric(Integer
             .parseInt(configsMap.get(SRVR_CRT_PASS_LEN_KEY)));
         FileUtils.writeStringToFile(passFile, randStr);
-
+        ShellCommandUtil.setUnixFilePermissions(
+               ShellCommandUtil.MASK_OWNER_ONLY_RW, passFile.getAbsolutePath());
       } catch (IOException e) {
         e.printStackTrace();
         throw new RuntimeException(

Modified: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/utils/ShellCommandUtil.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/utils/ShellCommandUtil.java?rev=1485073&r1=1485072&r2=1485073&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/utils/ShellCommandUtil.java (original)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/utils/ShellCommandUtil.java Wed May 22 06:09:38 2013
@@ -20,11 +20,18 @@ package org.apache.ambari.server.utils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
 /**
  * Logs OpenSsl command exit code with description
  */
 public class ShellCommandUtil {
   private static final Log LOG = LogFactory.getLog(ShellCommandUtil.class);
+  private static Object WindowsProcessLaunchLock = new Object();
+
   /*
   public static String LogAndReturnOpenSslExitCode(String command, int exitCode) {
     logOpenSslExitCode(command, exitCode);
@@ -69,4 +76,143 @@ public class ShellCommandUtil {
         return "unsupported code";
     }
   }
+
+
+  /** Set to true when run on Windows platforms */
+  public static final boolean WINDOWS
+          = System.getProperty("os.name").startsWith("Windows");
+
+  /** Set to true when run on Linux platforms */
+  public static final boolean LINUX
+          = System.getProperty("os.name").startsWith("Linux");
+
+  /** Set to true when run on Mac OS platforms */
+  public static final boolean MAC
+          = System.getProperty("os.name").startsWith("Mac");
+
+  /** Set to true when run if platform is detected to be UNIX compatible */
+  public static final boolean UNIX_LIKE = LINUX || MAC;
+
+  /**
+   * Permission mask 600 allows only owner to read and modify file.
+   * Other users (except root) can't read/modify file
+   */
+  public static final String MASK_OWNER_ONLY_RW = "600";
+
+  /**
+   * Permission mask 777 allows everybody to read/modify/execute file
+   */
+  public static final String MASK_EVERYBODY_RWX = "777";
+
+
+  /**
+   * Gets file permissions on Unix-like systems.
+   * Under Windows, command always returns MASK_EVERYBODY_RWX
+   * @param path
+   */
+  public static String getUnixFilePermissions(String path) {
+    String result = null;
+    if (UNIX_LIKE) {
+      try {
+        result = runCommand(new String[]{"stat", "-c", "%a", path}).getStdout();
+      } catch (IOException e) {
+        // Improbable
+        LOG.warn(String.format("Can not perform stat on %s", path), e);
+      } catch (InterruptedException e) {
+        LOG.warn(String.format("Can not perform stat on %s", path), e);
+      }
+    } else {
+      LOG.debug(String.format("Not performing stat -s \"%%a\" command on file %s " +
+              "because current OS is not Unix-like. Returning 777", path));
+      result = MASK_EVERYBODY_RWX;
+    }
+    return result.trim();
+  }
+
+  /**
+   * Sets file permissions to a given value on Unix-like systems.
+   * On Windows, command is silently ignored
+   * @param path
+   * @param mode
+   */
+  public static void setUnixFilePermissions(String mode, String path) {
+    if (UNIX_LIKE) {
+      try {
+        runCommand(new String[]{"chmod", mode, path});
+      } catch (IOException e) {
+        // Improbable
+        LOG.warn(String.format("Can not perform chmod %s %s", mode, path), e);
+      } catch (InterruptedException e) {
+        LOG.warn(String.format("Can not perform chmod %s %s", mode, path), e);
+      }
+    } else {
+      LOG.debug(String.format("Not performing chmod %s command for file %s " +
+              "because current OS is not Unix-like ", mode, path));
+    }
+  }
+
+  public static Result runCommand(String [] args) throws IOException,
+          InterruptedException {
+    ProcessBuilder builder = new ProcessBuilder(args);
+    Process process;
+    if (WINDOWS) {
+      synchronized (WindowsProcessLaunchLock) {
+        // To workaround the race condition issue with child processes
+        // inheriting unintended handles during process launch that can
+        // lead to hangs on reading output and error streams, we
+        // serialize process creation. More info available at:
+        // http://support.microsoft.com/kb/315939
+        process = builder.start();
+      }
+    } else {
+      process = builder.start();
+    }
+    //TODO: not sure whether output buffering will work properly
+    // if command output is too intensive
+    process.waitFor();
+    String stdout = streamToString(process.getInputStream());
+    String stderr = streamToString(process.getErrorStream());
+    int exitCode = process.exitValue();
+    return new Result(exitCode, stdout, stderr);
+  }
+
+  private static String streamToString(InputStream is) throws IOException {
+    InputStreamReader isr = new InputStreamReader(is);
+    BufferedReader reader = new BufferedReader(isr);
+    StringBuilder sb = new StringBuilder();
+    String line = null;
+    while ((line = reader.readLine()) != null) {
+      sb.append(line).append("\n");
+    }
+    return sb.toString();
+  }
+
+  static class Result {
+
+    Result(int exitCode, String stdout, String stderr) {
+      this.exitCode = exitCode;
+      this.stdout = stdout;
+      this.stderr = stderr;
+    }
+
+    private final int exitCode;
+    private final String stdout;
+    private final String stderr;
+
+    int getExitCode() {
+      return exitCode;
+    }
+
+    String getStdout() {
+      return stdout;
+    }
+
+    String getStderr() {
+      return stderr;
+    }
+
+    public boolean isSuccessful() {
+      return exitCode == 0;
+    }
+  }
 }

Modified: incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/security/TestPassFileGeneration.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/security/TestPassFileGeneration.java?rev=1485073&r1=1485072&r2=1485073&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/security/TestPassFileGeneration.java (original)
+++ incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/security/TestPassFileGeneration.java Wed May 22 06:09:38 2013
@@ -25,6 +25,7 @@ import java.util.Properties;
 import java.util.Random;
 
 import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.utils.ShellCommandUtil;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang.RandomStringUtils;
 import org.junit.After;
@@ -122,6 +123,15 @@ public class TestPassFileGeneration exte
 
     assertEquals(pass.length(), passLen);
 
+    if (ShellCommandUtil.UNIX_LIKE) {
+      String permissions = ShellCommandUtil.
+              getUnixFilePermissions(passFile.getAbsolutePath());
+      assertEquals(ShellCommandUtil.MASK_OWNER_ONLY_RW, permissions);
+    } else {
+      //Do nothing
+    }
+    // Cleanup
+    passFile.delete();
   }
 
 }

Added: incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/utils/TestShellCommandUtil.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/utils/TestShellCommandUtil.java?rev=1485073&view=auto
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/utils/TestShellCommandUtil.java (added)
+++ incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/utils/TestShellCommandUtil.java Wed May 22 06:09:38 2013
@@ -0,0 +1,133 @@
+/**
+ * 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.ambari.server.utils;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import junit.framework.TestCase;
+import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.security.CertGenerationTest;
+import org.apache.ambari.server.security.CertificateManager;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.RandomStringUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.util.Properties;
+import java.util.Random;
+
+public class TestShellCommandUtil extends TestCase {
+
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  protected Constructor<Configuration> getConfigurationConstructor() {
+    try {
+      return Configuration.class.getConstructor(Properties.class);
+    } catch (NoSuchMethodException e) {
+      throw new RuntimeException(
+          "Expected constructor not found in Configuration.java", e);
+    }
+  }
+
+  @Before
+  public void setUp() throws IOException {
+    try {
+      temp.create();
+    } catch (IOException e) {
+      e.printStackTrace();
+    }
+  }
+
+  @After
+  public void tearDown() throws IOException {
+    temp.delete();
+  }
+
+  @Test
+  public void testOSDetection() throws Exception {
+    // At least check, that only one OS is selected
+    assertTrue(ShellCommandUtil.LINUX ^ ShellCommandUtil.WINDOWS
+            ^ ShellCommandUtil.MAC);
+    assertTrue(ShellCommandUtil.LINUX || ShellCommandUtil.MAC ==
+            ShellCommandUtil.UNIX_LIKE);
+  }
+
+  @Test
+  public void testUnixFilePermissions() throws Exception {
+    File dummyFile = new File(temp.getRoot() + File.separator + "dummy");
+    new FileOutputStream(dummyFile).close();
+    if (ShellCommandUtil.UNIX_LIKE) {
+      ShellCommandUtil.setUnixFilePermissions("600",
+              dummyFile.getAbsolutePath());
+      String p = ShellCommandUtil.getUnixFilePermissions(
+              dummyFile.getAbsolutePath());
+      assertEquals("600", p);
+
+      ShellCommandUtil.setUnixFilePermissions("444",
+              dummyFile.getAbsolutePath());
+      p = ShellCommandUtil.getUnixFilePermissions(
+              dummyFile.getAbsolutePath());
+      assertEquals("444", p);
+
+      ShellCommandUtil.setUnixFilePermissions("777",
+              dummyFile.getAbsolutePath());
+      p = ShellCommandUtil.getUnixFilePermissions(
+              dummyFile.getAbsolutePath());
+      assertEquals("777", p);
+
+    } else {
+      // Next command is silently ignored, it's OK
+      ShellCommandUtil.setUnixFilePermissions(ShellCommandUtil.MASK_OWNER_ONLY_RW,
+              dummyFile.getAbsolutePath());
+      // On Windows, output is always MASK_EVERYBODY_RWX
+      String p = ShellCommandUtil.getUnixFilePermissions(
+              dummyFile.getAbsolutePath());
+      assertEquals(p, ShellCommandUtil.MASK_EVERYBODY_RWX);
+    }
+  }
+
+
+  @Test
+  public void testRunCommand() throws Exception {
+    ShellCommandUtil.Result result = null;
+    if (ShellCommandUtil.UNIX_LIKE) {
+      result = ShellCommandUtil.
+              runCommand(new String [] {"echo", "dummy"});
+      assertEquals(0, result.getExitCode());
+      assertEquals("dummy\n", result.getStdout());
+      assertEquals("", result.getStderr());
+      assertTrue(result.isSuccessful());
+
+      result = ShellCommandUtil.
+              runCommand(new String [] {"false"});
+      assertEquals(1, result.getExitCode());
+      assertFalse(result.isSuccessful());
+    } else {
+      // Skipping this test under Windows
+    }
+  }
+}