Repository: ambari
Updated Branches:
  refs/heads/branch-2.5 3ebb8d496 -> 170b29340


AMBARI-18365. Add Ambari configuration options to support Kerberos token 
authentication (rlevas)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/170b2934
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/170b2934
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/170b2934

Branch: refs/heads/branch-2.5
Commit: 170b293403ec4fa11353b58d95c65dc5761bb989
Parents: c0e0a53
Author: Robert Levas <rle...@hortonworks.com>
Authored: Wed Sep 14 12:09:20 2016 -0400
Committer: Robert Levas <rle...@hortonworks.com>
Committed: Wed Sep 14 12:09:51 2016 -0400

----------------------------------------------------------------------
 .../server/configuration/Configuration.java     | 183 ++++++++++++++++++-
 .../AmbariKerberosAuthenticationProperties.java | 161 ++++++++++++++++
 .../server/configuration/ConfigurationTest.java | 136 +++++++++++++-
 ...ariKerberosAuthenticationPropertiesTest.java |  85 +++++++++
 4 files changed, 563 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/170b2934/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
index fa0f784..b70c5f4 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
@@ -1,4 +1,4 @@
-/**
+/*
  * 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
@@ -56,7 +56,9 @@ import org.apache.ambari.server.orm.PersistenceType;
 import org.apache.ambari.server.orm.dao.HostRoleCommandStatusSummaryDTO;
 import org.apache.ambari.server.orm.entities.StageEntity;
 import org.apache.ambari.server.security.ClientSecurityType;
+import 
org.apache.ambari.server.security.authentication.kerberos.AmbariKerberosAuthenticationProperties;
 import org.apache.ambari.server.security.authorization.LdapServerProperties;
+import org.apache.ambari.server.security.authorization.UserType;
 import 
org.apache.ambari.server.security.authorization.jwt.JwtAuthenticationProperties;
 import org.apache.ambari.server.security.encryption.CertificateUtils;
 import org.apache.ambari.server.security.encryption.CredentialProvider;
@@ -68,6 +70,7 @@ import org.apache.ambari.server.utils.DateUtils;
 import org.apache.ambari.server.utils.HostUtils;
 import org.apache.ambari.server.utils.Parallel;
 import org.apache.ambari.server.utils.ShellCommandUtil;
+import org.apache.ambari.server.utils.StageUtils;
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.CommandLineParser;
 import org.apache.commons.cli.DefaultParser;
@@ -1312,6 +1315,49 @@ public class Configuration {
   public static final ConfigurationProperty<String> 
JWT_ORIGINAL_URL_QUERY_PARAM = new ConfigurationProperty<>(
       "authentication.jwt.originalUrlParamName", "originalUrl");
 
+  /* 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+   * Kerberos authentication-specific properties
+   * 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 */
+  /**
+   * Determines whether to use Kerberos (SPNEGO) authentication when 
connecting Ambari.
+   */
+  @Markdown(description = "Determines whether to use Kerberos (SPNEGO) 
authentication when connecting Ambari.")
+  public static final ConfigurationProperty<Boolean> KERBEROS_AUTH_ENABLED = 
new ConfigurationProperty<>(
+      "authentication.kerberos.enabled", Boolean.FALSE);
+
+  /**
+   * The Kerberos principal name to use when verifying user-supplied Kerberos 
tokens for authentication via SPNEGO.
+   */
+  @Markdown(description = "The Kerberos principal name to use when verifying 
user-supplied Kerberos tokens for authentication via SPNEGO")
+  public static final ConfigurationProperty<String> 
KERBEROS_AUTH_SPNEGO_PRINCIPAL = new ConfigurationProperty<>(
+      "authentication.kerberos.spnego.principal", "HTTP/_HOST");
+
+  /**
+   * The Kerberos identity to use when verifying user-supplied Kerberos tokens 
for authentication via SPNEGO.
+   */
+  @Markdown(description = "The Kerberos keytab file to use when verifying 
user-supplied Kerberos tokens for authentication via SPNEGO")
+  public static final ConfigurationProperty<String> 
KERBEROS_AUTH_SPNEGO_KEYTAB_FILE = new ConfigurationProperty<>(
+      "authentication.kerberos.spnego.keytab.file", 
"/etc/security/keytabs/spnego.service.keytab");
+
+  /**
+   * A comma-delimited (ordered) list of preferred user types to use when 
finding the Ambari user
+   * account for the user-supplied Kerberos identity during authentication via 
SPNEGO.
+   */
+  @Markdown(description = "A comma-delimited (ordered) list of preferred user 
types to use when finding the Ambari user account for the user-supplied 
Kerberos identity during authentication via SPNEGO")
+  public static final ConfigurationProperty<String> KERBEROS_AUTH_USER_TYPES = 
new ConfigurationProperty<>(
+      "authentication.kerberos.user.types", "LDAP");
+
+  /**
+   * The auth-to-local rules set to use when translating a user's principal 
name to a local user name
+   * during authentication via SPNEGO.
+   */
+  @Markdown(description = "The auth-to-local rules set to use when translating 
a user's principal name to a local user name during authentication via SPNEGO.")
+  public static final ConfigurationProperty<String> 
KERBEROS_AUTH_AUTH_TO_LOCAL_RULES  = new ConfigurationProperty<>(
+      "authentication.kerberos.auth_to_local.rules", "DEFAULT");
+  /* 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+   * Kerberos authentication-specific properties (end)
+   * 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 */
+
   /**
    * The type of connection pool to use with JDBC connections to the database.
    */
@@ -2306,6 +2352,11 @@ public class Configuration {
   private Map<String, String> databaseConnectorNames = new HashMap<>();
   private Map<String, String> databasePreviousConnectorNames = new HashMap<>();
 
+  /**
+   * The Kerberos authentication-specific properties container (for 
convenience)
+   */
+  private final AmbariKerberosAuthenticationProperties 
kerberosAuthenticationProperties;
+
   static {
     if (System.getProperty("os.name").contains("Windows")) {
       DEF_ARCHIVE_EXTENSION = ".zip";
@@ -2511,6 +2562,9 @@ public class Configuration {
       configsMap.put(CLIENT_API_SSL_CRT_PASS.getKey(), password);
     }
 
+    // Capture the Kerberos authentication-related properties
+    kerberosAuthenticationProperties = 
createKerberosAuthenticationProperties();
+
     loadSSLParams();
   }
 
@@ -4437,6 +4491,15 @@ public class Configuration {
   }
 
   /**
+   * Gets the Kerberos authentication-specific properties container
+   *
+   * @return an AmbariKerberosAuthenticationProperties
+   */
+  public AmbariKerberosAuthenticationProperties 
getKerberosAuthenticationProperties() {
+    return kerberosAuthenticationProperties;
+  }
+
+  /**
    * Ambari server temp dir
    * @return server temp dir
    */
@@ -5044,4 +5107,122 @@ public class Configuration {
     String value();
   }
 
+  /**
+   * Creates an AmbariKerberosAuthenticationProperties instance containing the 
Kerberos authentication-specific
+   * properties.
+   *
+   * The relevant properties are processed to set any default values or 
translate the propery values
+   * into usable data for the Kerberos authentication logic.
+   *
+   * @return
+   */
+  private AmbariKerberosAuthenticationProperties 
createKerberosAuthenticationProperties() {
+    AmbariKerberosAuthenticationProperties kerberosAuthProperties = new 
AmbariKerberosAuthenticationProperties();
+
+    
kerberosAuthProperties.setKerberosAuthenticationEnabled(Boolean.valueOf(getProperty(KERBEROS_AUTH_ENABLED)));
+
+    // if Kerberos authentication is enabled, continue; else ignore the rest 
of related properties since
+    // they will not be used.
+    if (!kerberosAuthProperties.isKerberosAuthenticationEnabled()) {
+      return kerberosAuthProperties;
+    }
+
+    // Get and process the configured user type values to convert the 
comma-delimited string of
+    // user types into a ordered (as found in the comma-delimited value) list 
of UserType values.
+    String userTypes = getProperty(KERBEROS_AUTH_USER_TYPES);
+    List<UserType> orderedUserTypes = new ArrayList<UserType>();
+
+    String[] types = userTypes.split(",");
+    for (String type : types) {
+      type = type.trim();
+
+      if (!type.isEmpty()) {
+        try {
+          orderedUserTypes.add(UserType.valueOf(type.toUpperCase()));
+        } catch (IllegalArgumentException e) {
+          throw new IllegalArgumentException(String.format("While processing 
ordered user types from %s, " +
+                  "%s was found to be an invalid user type.",
+              KERBEROS_AUTH_USER_TYPES.getKey(), type), e);
+        }
+      }
+    }
+
+    // If no user types have been specified, assume only LDAP users...
+    if (orderedUserTypes.isEmpty()) {
+      LOG.info("No (valid) user types were specified in {}. Using the default 
value of LOCAL.",
+          KERBEROS_AUTH_USER_TYPES.getKey());
+      orderedUserTypes.add(UserType.LDAP);
+    }
+
+    kerberosAuthProperties.setOrderedUserTypes(orderedUserTypes);
+
+    // Get and process the SPNEGO principal name.  If it exists and contains 
the host replacement
+    // indicator (_HOST), replace it with the hostname of the current host.
+    String spnegoPrincipalName = getProperty(KERBEROS_AUTH_SPNEGO_PRINCIPAL);
+
+    if ((spnegoPrincipalName != null) && 
(spnegoPrincipalName.contains("_HOST"))) {
+      String hostName = StageUtils.getHostName();
+
+      if (StringUtils.isEmpty(hostName)) {
+        LOG.warn("Cannot replace _HOST in the configured SPNEGO principal name 
with the host name this host since it is not available");
+      } else {
+        LOG.info("Replacing _HOST in the configured SPNEGO principal name with 
the host name this host: {}", hostName);
+        spnegoPrincipalName = spnegoPrincipalName.replaceAll("_HOST", 
hostName);
+      }
+    }
+
+    kerberosAuthProperties.setSpnegoPrincipalName(spnegoPrincipalName);
+
+    // Validate the SPNEGO principal name to ensure it was set.
+    // Log any found issues.
+    if (StringUtils.isEmpty(kerberosAuthProperties.getSpnegoPrincipalName())) {
+      throw new IllegalArgumentException(String.format("The SPNEGO principal 
name specified in %s is empty. " +
+          "This will cause issues authenticating users using Kerberos.",
+          KERBEROS_AUTH_SPNEGO_PRINCIPAL.getKey()));
+    }
+
+    // Get the SPNEGO keytab file. There is nothing special to process for 
this value.
+    
kerberosAuthProperties.setSpnegoKeytabFilePath(getProperty(KERBEROS_AUTH_SPNEGO_KEYTAB_FILE));
+
+    // Validate the SPNEGO keytab file to ensure it was set, it exists and it 
is readable by Ambari.
+    // Log any found issues.
+    if (StringUtils.isEmpty(kerberosAuthProperties.getSpnegoKeytabFilePath())) 
{
+      throw new IllegalArgumentException(String.format("The SPNEGO keytab file 
path specified in %s is empty. " +
+              "This will cause issues authenticating users using Kerberos.",
+          KERBEROS_AUTH_SPNEGO_KEYTAB_FILE.getKey()));
+    } else {
+      File keytabFile = new 
File(kerberosAuthProperties.getSpnegoKeytabFilePath());
+      if (!keytabFile.exists()) {
+        throw new IllegalArgumentException(String.format("The SPNEGO keytab 
file path (%s) specified in %s does not exist. " +
+                "This will cause issues authenticating users using Kerberos.",
+            keytabFile.getAbsolutePath(), 
KERBEROS_AUTH_SPNEGO_KEYTAB_FILE.getKey()));
+      } else if (!keytabFile.canRead()) {
+        throw new IllegalArgumentException(String.format("The SPNEGO keytab 
file path (%s) specified in %s cannot be read. " +
+                "This will cause issues authenticating users using Kerberos.",
+            keytabFile.getAbsolutePath(), 
KERBEROS_AUTH_SPNEGO_KEYTAB_FILE.getKey()));
+      }
+    }
+
+    // Get the auth-to-local rule set. There is nothing special to process for 
this value.
+    
kerberosAuthProperties.setAuthToLocalRules(getProperty(KERBEROS_AUTH_AUTH_TO_LOCAL_RULES));
+
+    LOG.info("Kerberos authentication is enabled:\n " +
+            "\t{}: {}\n" +
+            "\t{}: {}\n" +
+            "\t{}: {}\n" +
+            "\t{}: {}\n" +
+            "\t{}: {}\n",
+        KERBEROS_AUTH_ENABLED.getKey(),
+        kerberosAuthProperties.isKerberosAuthenticationEnabled(),
+        KERBEROS_AUTH_SPNEGO_PRINCIPAL.getKey(),
+        kerberosAuthProperties.getSpnegoPrincipalName(),
+        KERBEROS_AUTH_SPNEGO_KEYTAB_FILE.getKey(),
+        kerberosAuthProperties.getSpnegoKeytabFilePath(),
+        KERBEROS_AUTH_USER_TYPES.getKey(),
+        kerberosAuthProperties.getOrderedUserTypes(),
+        KERBEROS_AUTH_AUTH_TO_LOCAL_RULES.getKey(),
+        kerberosAuthProperties.getAuthToLocalRules());
+
+    return kerberosAuthProperties;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/170b2934/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/kerberos/AmbariKerberosAuthenticationProperties.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/kerberos/AmbariKerberosAuthenticationProperties.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/kerberos/AmbariKerberosAuthenticationProperties.java
new file mode 100644
index 0000000..00466ca
--- /dev/null
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/security/authentication/kerberos/AmbariKerberosAuthenticationProperties.java
@@ -0,0 +1,161 @@
+/*
+ * 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.security.authentication.kerberos;
+
+import org.apache.ambari.server.security.authorization.UserType;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * AmbariKerberosAuthenticationProperties is a container for Kerberos 
authentication-related
+ * configuration properties. This container holds interpreted configuration 
data to be used when
+ * authenticating users using Kerberos.
+ * <p>
+ * If Kerberos authentication is not enabled for Ambari <code>{@link 
#kerberosAuthenticationEnabled} == false</code>,
+ * then there is no guarentee that any other property in this container is 
valid.
+ */
+public class AmbariKerberosAuthenticationProperties {
+
+  /**
+   * A boolean value indicating whether Kerberos authentication is enabled in 
Ambari (<code>true</code>)
+   * or not (<code>false</code>).
+   */
+  private boolean kerberosAuthenticationEnabled = false;
+
+  /**
+   * The SPNEGO principal name
+   */
+  private String spnegoPrincipalName = null;
+
+  /**
+   * The (absolute) path to the SPNEGO keytab file
+   */
+  private String spnegoKeytabFilePath = null;
+
+  /**
+   * A list of {@link UserType}s in order of preference for use when looking 
up user accounts in the
+   * Ambari database
+   */
+  private List<UserType> orderedUserTypes = Collections.emptyList();
+
+  /**
+   * Auth-to-local rules to use to feed to an auth-to-local rules processor 
used to translate
+   * principal names to local usernames.
+   */
+  private String authToLocalRules;
+
+  /**
+   * Get whether Kerberos authentication is enabled or not.
+   *
+   * @return <code>true</code> if Kerberos authentication is enabled; 
otherwise <code>false</code>
+   */
+  public boolean isKerberosAuthenticationEnabled() {
+    return kerberosAuthenticationEnabled;
+  }
+
+  /**
+   * Sets whether Kerberos authentication is enabled or not.
+   *
+   * @param kerberosAuthenticationEnabled <code>true</code> if Kerberos 
authentication is enabled; otherwise <code>false</code>
+   */
+  public void setKerberosAuthenticationEnabled(boolean 
kerberosAuthenticationEnabled) {
+    this.kerberosAuthenticationEnabled = kerberosAuthenticationEnabled;
+  }
+
+  /**
+   * Gets the configured SPNEGO principal name. This may be <code>null</code> 
if Kerberos
+   * authentication is not enabled.
+   *
+   * @return the SPNEGO principal name or <code>null</code> if Kerberos 
authentication is not enabled
+   */
+  public String getSpnegoPrincipalName() {
+    return spnegoPrincipalName;
+  }
+
+  /**
+   * Sets the configured SPNEGO principal name.
+   *
+   * @param spnegoPrincipalName a principal name
+   */
+  public void setSpnegoPrincipalName(String spnegoPrincipalName) {
+    this.spnegoPrincipalName = spnegoPrincipalName;
+  }
+
+  /**
+   * Gets the configured SPNEGO keytab file path. This may be 
<code>null</code> if Kerberos
+   * authentication is not enabled.
+   *
+   * @return the SPNEGO keytab file path or <code>null</code> if Kerberos 
authentication is not enabled
+   */
+  public String getSpnegoKeytabFilePath() {
+    return spnegoKeytabFilePath;
+  }
+
+  /**
+   * Sets the configured SPNEGO keytab file path.
+   *
+   * @param spnegoKeytabFilePath a keytab file path
+   */
+  public void setSpnegoKeytabFilePath(String spnegoKeytabFilePath) {
+    this.spnegoKeytabFilePath = spnegoKeytabFilePath;
+  }
+
+  /**
+   * Sets the list of {@link UserType}s (in preference order) to use to look 
up uer accounts in the Ambari database.
+   *
+   * @param orderedUserTypes a list of {@link UserType}s
+   */
+  public void setOrderedUserTypes(List<UserType> orderedUserTypes) {
+    if (orderedUserTypes == null) {
+      this.orderedUserTypes = Collections.emptyList();
+    } else {
+      this.orderedUserTypes = Collections.unmodifiableList(new 
ArrayList<UserType>(orderedUserTypes));
+    }
+  }
+
+  /**
+   * Gets the list of {@link UserType}s (in preference order) to use to look 
up uer accounts in the Ambari database.
+   *
+   * @return a list of {@link UserType}s
+   */
+  public List<UserType> getOrderedUserTypes() {
+    return orderedUserTypes;
+  }
+
+  /**
+   * Gets the configured auth-to-local rule set. This may be <code>null</code> 
if Kerberos
+   * authentication is not enabled.
+   *
+   * @return a string representing an auth-to-local rule set or 
<code>null</code> if Kerberos authentication is not enabled
+   */
+  public String getAuthToLocalRules() {
+    return authToLocalRules;
+  }
+
+  /**
+   * Sets the configured auth-to-local rule set.
+   *
+   * @param authToLocalRules a string representing an auth-to-local rule set
+   */
+  public void setAuthToLocalRules(String authToLocalRules) {
+    this.authToLocalRules = authToLocalRules;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/170b2934/ambari-server/src/test/java/org/apache/ambari/server/configuration/ConfigurationTest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/configuration/ConfigurationTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/configuration/ConfigurationTest.java
index f9b76f8..0397288 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/configuration/ConfigurationTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/configuration/ConfigurationTest.java
@@ -1,4 +1,4 @@
-/**
+/*
  * 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
@@ -30,6 +30,8 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.Map;
 import java.util.Properties;
 
@@ -40,8 +42,11 @@ import 
org.apache.ambari.server.configuration.Configuration.ConfigurationPropert
 import org.apache.ambari.server.configuration.Configuration.ConnectionPoolType;
 import org.apache.ambari.server.configuration.Configuration.DatabaseType;
 import 
org.apache.ambari.server.controller.metrics.ThreadPoolEnabledPropertyProvider;
+import 
org.apache.ambari.server.security.authentication.kerberos.AmbariKerberosAuthenticationProperties;
 import org.apache.ambari.server.security.authorization.LdapServerProperties;
+import org.apache.ambari.server.security.authorization.UserType;
 import org.apache.ambari.server.state.services.MetricsRetrievalService;
+import org.apache.ambari.server.utils.StageUtils;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang.RandomStringUtils;
 import org.apache.commons.lang.StringUtils;
@@ -920,4 +925,133 @@ public class ConfigurationTest {
           StringUtils.isEmpty(markdown.description()));
     }
   }
+
+  /**
+   * Tests that the Kerberos-authentication properties are read and properly 
and set in an
+   * {@link AmbariKerberosAuthenticationProperties} instance when Kerberos 
authentication is enabled.
+   */
+  @Test
+  public void testKerberosAuthenticationEnabled() throws IOException {
+    File keytabFile = temp.newFile("spnego.service.keytab");
+
+    Properties properties = new Properties();
+    properties.put(Configuration.KERBEROS_AUTH_ENABLED.getKey(), "true");
+    properties.put(Configuration.KERBEROS_AUTH_SPNEGO_KEYTAB_FILE.getKey(), 
keytabFile.getAbsolutePath());
+    properties.put(Configuration.KERBEROS_AUTH_SPNEGO_PRINCIPAL.getKey(), 
"spnego/principal@REALM");
+    properties.put(Configuration.KERBEROS_AUTH_USER_TYPES.getKey(), "LDAP, 
LOCAL");
+    properties.put(Configuration.KERBEROS_AUTH_AUTH_TO_LOCAL_RULES.getKey(), 
"DEFAULT");
+
+    Configuration configuration = new Configuration(properties);
+
+    AmbariKerberosAuthenticationProperties kerberosAuthenticationProperties = 
configuration.getKerberosAuthenticationProperties();
+
+    
Assert.assertTrue(kerberosAuthenticationProperties.isKerberosAuthenticationEnabled());
+    Assert.assertEquals(keytabFile.getAbsolutePath(), 
kerberosAuthenticationProperties.getSpnegoKeytabFilePath());
+    Assert.assertEquals("spnego/principal@REALM", 
kerberosAuthenticationProperties.getSpnegoPrincipalName());
+    Assert.assertEquals("DEFAULT", 
kerberosAuthenticationProperties.getAuthToLocalRules());
+    Assert.assertEquals(Arrays.asList(UserType.LDAP, UserType.LOCAL), 
kerberosAuthenticationProperties.getOrderedUserTypes());
+  }
+
+  /**
+   * Tests that the Kerberos-authentication properties are read and properly 
and set in an
+   * {@link AmbariKerberosAuthenticationProperties} instance when Kerberos 
authentication is enabled
+   * and default values are expected to be used for unset properties.
+   */
+  @Test
+  public void testKerberosAuthenticationEnabledUsingDefaults() throws 
IOException {
+    File keytabFile = temp.newFile("spnego.service.keytab");
+
+    Properties properties = new Properties();
+    properties.put(Configuration.KERBEROS_AUTH_ENABLED.getKey(), "true");
+    // Force a specific path to the SPNEGO keytab file since internal 
validation expects to exist
+    properties.put(Configuration.KERBEROS_AUTH_SPNEGO_KEYTAB_FILE.getKey(), 
keytabFile.getAbsolutePath());
+
+    Configuration configuration = new Configuration(properties);
+
+    AmbariKerberosAuthenticationProperties kerberosAuthenticationProperties = 
configuration.getKerberosAuthenticationProperties();
+
+    
Assert.assertTrue(kerberosAuthenticationProperties.isKerberosAuthenticationEnabled());
+    Assert.assertEquals(keytabFile.getAbsolutePath(), 
kerberosAuthenticationProperties.getSpnegoKeytabFilePath());
+    Assert.assertEquals("HTTP/" + StageUtils.getHostName(), 
kerberosAuthenticationProperties.getSpnegoPrincipalName());
+    Assert.assertEquals("DEFAULT", 
kerberosAuthenticationProperties.getAuthToLocalRules());
+    Assert.assertEquals(Collections.singletonList(UserType.LDAP), 
kerberosAuthenticationProperties.getOrderedUserTypes());
+  }
+
+  /**
+   * Tests that the Kerberos-authentication properties are read and properly 
set in an
+   * {@link AmbariKerberosAuthenticationProperties} instance when Kerberos 
authentication is disabled.
+   */
+  @Test
+  public void testKerberosAuthenticationDisabled() {
+    Properties properties = new Properties();
+    properties.put(Configuration.KERBEROS_AUTH_ENABLED.getKey(), "false");
+
+    Configuration configuration = new Configuration(properties);
+
+    AmbariKerberosAuthenticationProperties kerberosAuthenticationProperties = 
configuration.getKerberosAuthenticationProperties();
+
+    
Assert.assertFalse(kerberosAuthenticationProperties.isKerberosAuthenticationEnabled());
+    
Assert.assertNull(kerberosAuthenticationProperties.getSpnegoKeytabFilePath());
+    
Assert.assertNull(kerberosAuthenticationProperties.getSpnegoPrincipalName());
+    Assert.assertNull(kerberosAuthenticationProperties.getAuthToLocalRules());
+    Assert.assertEquals(Collections.emptyList(), 
kerberosAuthenticationProperties.getOrderedUserTypes());
+  }
+
+  @Test
+  public void testKerberosAuthenticationDisabledWithValuesSet() {
+    Properties properties = new Properties();
+    properties.put(Configuration.KERBEROS_AUTH_ENABLED.getKey(), "false");
+    properties.put(Configuration.KERBEROS_AUTH_SPNEGO_KEYTAB_FILE.getKey(), 
"/path/to/spnego/keytab/file");
+    properties.put(Configuration.KERBEROS_AUTH_SPNEGO_PRINCIPAL.getKey(), 
"spnego/principal@REALM");
+    properties.put(Configuration.KERBEROS_AUTH_USER_TYPES.getKey(), "LDAP, 
LOCAL");
+    properties.put(Configuration.KERBEROS_AUTH_AUTH_TO_LOCAL_RULES.getKey(), 
"DEFAULT");
+
+    Configuration configuration = new Configuration(properties);
+
+    AmbariKerberosAuthenticationProperties kerberosAuthenticationProperties = 
configuration.getKerberosAuthenticationProperties();
+
+    
Assert.assertFalse(kerberosAuthenticationProperties.isKerberosAuthenticationEnabled());
+    
Assert.assertNull(kerberosAuthenticationProperties.getSpnegoKeytabFilePath());
+    
Assert.assertNull(kerberosAuthenticationProperties.getSpnegoPrincipalName());
+    Assert.assertNull(kerberosAuthenticationProperties.getAuthToLocalRules());
+    Assert.assertEquals(Collections.emptyList(), 
kerberosAuthenticationProperties.getOrderedUserTypes());
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testKerberosAuthenticationEmptySPNEGOPrincipalName() throws 
IOException {
+    File keytabFile = temp.newFile("spnego.service.keytab");
+
+    Properties properties = new Properties();
+    properties.put(Configuration.KERBEROS_AUTH_ENABLED.getKey(), "true");
+    properties.put(Configuration.KERBEROS_AUTH_SPNEGO_KEYTAB_FILE.getKey(), 
keytabFile.getAbsolutePath());
+    properties.put(Configuration.KERBEROS_AUTH_SPNEGO_PRINCIPAL.getKey(), "");
+    properties.put(Configuration.KERBEROS_AUTH_USER_TYPES.getKey(), "LDAP, 
LOCAL");
+    properties.put(Configuration.KERBEROS_AUTH_AUTH_TO_LOCAL_RULES.getKey(), 
"DEFAULT");
+
+    new Configuration(properties);
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testKerberosAuthenticationEmptySPNEGOKeytabFile() {
+    Properties properties = new Properties();
+    properties.put(Configuration.KERBEROS_AUTH_ENABLED.getKey(), "true");
+    properties.put(Configuration.KERBEROS_AUTH_SPNEGO_KEYTAB_FILE.getKey(), 
"");
+    properties.put(Configuration.KERBEROS_AUTH_SPNEGO_PRINCIPAL.getKey(), 
"spnego/principal@REALM");
+    properties.put(Configuration.KERBEROS_AUTH_USER_TYPES.getKey(), "LDAP, 
LOCAL");
+    properties.put(Configuration.KERBEROS_AUTH_AUTH_TO_LOCAL_RULES.getKey(), 
"DEFAULT");
+
+    new Configuration(properties);
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testKerberosAuthenticationSPNEGOKeytabFileNotFound() {
+    Properties properties = new Properties();
+    properties.put(Configuration.KERBEROS_AUTH_ENABLED.getKey(), "true");
+    properties.put(Configuration.KERBEROS_AUTH_SPNEGO_KEYTAB_FILE.getKey(), 
"/path/to/missing/spnego/keytab/file");
+    properties.put(Configuration.KERBEROS_AUTH_SPNEGO_PRINCIPAL.getKey(), 
"spnego/principal@REALM");
+    properties.put(Configuration.KERBEROS_AUTH_USER_TYPES.getKey(), "LDAP, 
LOCAL");
+    properties.put(Configuration.KERBEROS_AUTH_AUTH_TO_LOCAL_RULES.getKey(), 
"DEFAULT");
+
+    new Configuration(properties);
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/170b2934/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/kerberos/AmbariKerberosAuthenticationPropertiesTest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/kerberos/AmbariKerberosAuthenticationPropertiesTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/kerberos/AmbariKerberosAuthenticationPropertiesTest.java
new file mode 100644
index 0000000..9c0c0ba
--- /dev/null
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/kerberos/AmbariKerberosAuthenticationPropertiesTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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.security.authentication.kerberos;
+
+import org.apache.ambari.server.security.authorization.UserType;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+
+
+public class AmbariKerberosAuthenticationPropertiesTest {
+  @Test
+  public void testKerberosAuthenticationEnabled() throws Exception {
+    AmbariKerberosAuthenticationProperties properties = new 
AmbariKerberosAuthenticationProperties();
+
+    properties.setKerberosAuthenticationEnabled(true);
+    Assert.assertEquals(true, properties.isKerberosAuthenticationEnabled());
+
+    properties.setKerberosAuthenticationEnabled(false);
+    Assert.assertEquals(false, properties.isKerberosAuthenticationEnabled());
+  }
+
+  @Test
+  public void testSpnegoPrincipalName() throws Exception {
+    AmbariKerberosAuthenticationProperties properties = new 
AmbariKerberosAuthenticationProperties();
+
+    properties.setSpnegoPrincipalName("HTTP/_h...@example.com");
+    Assert.assertEquals("HTTP/_h...@example.com", 
properties.getSpnegoPrincipalName());
+
+    properties.setSpnegoPrincipalName("something else");
+    Assert.assertEquals("something else", properties.getSpnegoPrincipalName());
+  }
+
+  @Test
+  public void testSpnegoKeytabFilePath() throws Exception {
+    AmbariKerberosAuthenticationProperties properties = new 
AmbariKerberosAuthenticationProperties();
+
+    
properties.setSpnegoKeytabFilePath("/etc/security/keytabs/spnego.service.keytab");
+    Assert.assertEquals("/etc/security/keytabs/spnego.service.keytab", 
properties.getSpnegoKeytabFilePath());
+
+    properties.setSpnegoKeytabFilePath("something else");
+    Assert.assertEquals("something else", 
properties.getSpnegoKeytabFilePath());
+  }
+
+  @Test
+  public void testOrderedUserTypes() throws Exception {
+    AmbariKerberosAuthenticationProperties properties = new 
AmbariKerberosAuthenticationProperties();
+
+    properties.setOrderedUserTypes(new 
ArrayList<UserType>(Arrays.asList(UserType.LDAP, UserType.LOCAL)));
+    Assert.assertEquals(new ArrayList<UserType>(Arrays.asList(UserType.LDAP, 
UserType.LOCAL)), properties.getOrderedUserTypes());
+
+    properties.setOrderedUserTypes(Collections.singletonList(UserType.JWT));
+    Assert.assertEquals(new 
ArrayList<UserType>(Collections.singletonList(UserType.JWT)), 
properties.getOrderedUserTypes());
+  }
+
+  @Test
+  public void testAuthToLocalRules() throws Exception {
+    AmbariKerberosAuthenticationProperties properties = new 
AmbariKerberosAuthenticationProperties();
+
+    
properties.setAuthToLocalRules("RULE:[1:$1@$0](us...@example.com)s/.*/user2/\\nDEFAULT");
+    
Assert.assertEquals("RULE:[1:$1@$0](us...@example.com)s/.*/user2/\\nDEFAULT", 
properties.getAuthToLocalRules());
+
+    properties.setAuthToLocalRules("something else");
+    Assert.assertEquals("something else", properties.getAuthToLocalRules());
+  }
+}
\ No newline at end of file

Reply via email to