瀏覽代碼

AMBARI-13060. Kerberos: Allow user to specify additional realms for auth-to-local rules (rlevas)

Robert Levas 10 年之前
父節點
當前提交
9b6d33d0cb

+ 31 - 2
ambari-server/src/main/java/org/apache/ambari/server/controller/AuthToLocalBuilder.java

@@ -20,6 +20,7 @@ package org.apache.ambari.server.controller;
 
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 import java.util.TreeSet;
@@ -65,15 +66,37 @@ public class AuthToLocalBuilder {
    */
   private boolean caseInsensitiveUser;
 
+  /**
+   * A set of additional realm names to reference when generating rules.
+   */
+  private Set<String> additionalRealms = new HashSet<String>();
+
   /**
    * Default constructor. Case insensitive support false by default
    */
   public AuthToLocalBuilder() {
-    this.caseInsensitiveUser = false;
+    this(false, null);
   }
 
-  public AuthToLocalBuilder(boolean caseInsensitiveUserSupport) {
+  /**
+   * Constructs a new AuthToLocalBuilder.
+   *
+   * @param caseInsensitiveUserSupport true indicating that case-insensitivity should be enabled;
+   *                                   false otherwise
+   * @param additionalRealms           a String containing a comma-delimited list of realm names to generate
+   *                                   default auth-to-local rules for
+   */
+  public AuthToLocalBuilder(boolean caseInsensitiveUserSupport, String additionalRealms) {
     this.caseInsensitiveUser = caseInsensitiveUserSupport;
+
+    if ((additionalRealms != null) && !additionalRealms.isEmpty()) {
+      for (String realm : additionalRealms.split("\\s*(?:\\r?\\n|,)\\s*")) {
+        realm = realm.trim();
+        if (!realm.isEmpty()) {
+          this.additionalRealms.add(realm);
+        }
+      }
+    }
   }
 
   /**
@@ -161,6 +184,11 @@ public class AuthToLocalBuilder {
     // ensure that a default rule is added for this realm
     setRules.add(createDefaultRealmRule(realm));
 
+    // ensure that a default realm rule is added for the specified additional realms
+    for (String additionalRealm : additionalRealms) {
+      setRules.add(createDefaultRealmRule(additionalRealm));
+    }
+
     if (concatenationType == null) {
       concatenationType = DEFAULT_CONCATENATION_TYPE;
     }
@@ -269,6 +297,7 @@ public class AuthToLocalBuilder {
       copy.setRules.add(rule);
     }
     copy.caseInsensitiveUser = this.caseInsensitiveUser;
+    copy.additionalRealms.addAll(this.additionalRealms);
 
     return copy;
   }

+ 4 - 1
ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java

@@ -395,8 +395,11 @@ public class KerberosHelperImpl implements KerberosHelper {
       // the 'kerberos-env' structure is expected to be available here as it was previously validated
       boolean caseInsensitiveUser = Boolean.valueOf(existingConfigurations.get("kerberos-env").get("case_insensitive_username_rules"));
 
+      // Additional realms that need to be handled according to the Kerberos Descriptor
+      String additionalRealms = kerberosDescriptor.getProperty("additional_realms");
+
       // Determine which properties need to be set
-      AuthToLocalBuilder authToLocalBuilder = new AuthToLocalBuilder(caseInsensitiveUser);
+      AuthToLocalBuilder authToLocalBuilder = new AuthToLocalBuilder(caseInsensitiveUser, additionalRealms);
       addIdentities(authToLocalBuilder, kerberosDescriptor.getIdentities(), null, existingConfigurations);
 
       authToLocalProperties = kerberosDescriptor.getAuthToLocalProperties();

+ 0 - 1
ambari-server/src/main/resources/common-services/HDFS/2.1.0.2.0/kerberos.json

@@ -45,7 +45,6 @@
           "core-site": {
             "hadoop.security.authentication": "kerberos",
             "hadoop.security.authorization": "true",
-            "hadoop.security.auth_to_local": "",
             "hadoop.proxyuser.HTTP.groups": "${hadoop-env/proxyuser_group}"
           }
         }

+ 2 - 1
ambari-server/src/main/resources/stacks/HDP/2.0.6/kerberos.json

@@ -1,7 +1,8 @@
 {
   "properties": {
     "realm": "${kerberos-env/realm}",
-    "keytab_dir": "/etc/security/keytabs"
+    "keytab_dir": "/etc/security/keytabs",
+    "additional_realms": ""
   },
   "identities": [
     {

+ 1 - 1
ambari-server/src/test/java/org/apache/ambari/server/api/services/AmbariMetaInfoTest.java

@@ -1846,7 +1846,7 @@ public class AmbariMetaInfoTest {
 
     Assert.assertNotNull(descriptor);
     Assert.assertNotNull(descriptor.getProperties());
-    Assert.assertEquals(2, descriptor.getProperties().size());
+    Assert.assertEquals(3, descriptor.getProperties().size());
 
     Assert.assertNotNull(descriptor.getIdentities());
     Assert.assertEquals(1, descriptor.getIdentities().size());

+ 84 - 1
ambari-server/src/test/java/org/apache/ambari/server/controller/AuthToLocalBuilderTest.java

@@ -57,7 +57,7 @@ public class AuthToLocalBuilderTest {
 
   @Test
   public void testRuleGeneration_caseInsensitiveSupport() {
-    AuthToLocalBuilder builder = new AuthToLocalBuilder(true);
+    AuthToLocalBuilder builder = new AuthToLocalBuilder(true, null);
 
     builder.addRule("nn/_HOST@EXAMPLE.COM", "hdfs");
     // Duplicate principal for secondary namenode, should be filtered out...
@@ -312,4 +312,87 @@ public class AuthToLocalBuilderTest {
     assertEquals(copy.generate("EXAMPLE.COM"), builder.generate("EXAMPLE.COM"));
 
   }
+
+  @Test
+  public void testAdditionalRealms() {
+    AuthToLocalBuilder builder = new AuthToLocalBuilder(false, "REALM2,REALM3, REALM1  ");
+
+    builder.addRules(
+        "RULE:[1:$1@$0](.*@FOOBAR.COM)s/@.*//\n" +
+            "DEFAULT");
+
+    builder.addRule("nn/_HOST@EXAMPLE.COM", "hdfs");
+    builder.addRule("dn/_HOST@EXAMPLE.COM", "hdfs");
+    builder.addRule("jn/_HOST@EXAMPLE.COM", "hdfs");
+    builder.addRule("rm/_HOST@EXAMPLE.COM", "yarn");
+    builder.addRule("jhs/_HOST@EXAMPLE.COM", "mapred");
+    builder.addRule("hm/_HOST@EXAMPLE.COM", "hbase");
+    builder.addRule("rs/_HOST@EXAMPLE.COM", "hbase");
+
+    assertEquals(
+        "RULE:[1:$1@$0](.*@FOOBAR.COM)s/@.*//\n" +
+            "RULE:[1:$1@$0](.*@EXAMPLE.COM)s/@.*//\n" +
+            "RULE:[1:$1@$0](.*@REALM2)s/@.*//\n" +
+            "RULE:[1:$1@$0](.*@REALM1)s/@.*//\n" +
+            "RULE:[1:$1@$0](.*@REALM3)s/@.*//\n" +
+            "RULE:[2:$1@$0](dn@EXAMPLE.COM)s/.*/hdfs/\n" +
+            "RULE:[2:$1@$0](hm@EXAMPLE.COM)s/.*/hbase/\n" +
+            "RULE:[2:$1@$0](jhs@EXAMPLE.COM)s/.*/mapred/\n" +
+            "RULE:[2:$1@$0](jn@EXAMPLE.COM)s/.*/hdfs/\n" +
+            "RULE:[2:$1@$0](nn@EXAMPLE.COM)s/.*/hdfs/\n" +
+            "RULE:[2:$1@$0](rm@EXAMPLE.COM)s/.*/yarn/\n" +
+            "RULE:[2:$1@$0](rs@EXAMPLE.COM)s/.*/hbase/\n" +
+            "DEFAULT",
+        builder.generate("EXAMPLE.COM"));
+  }
+
+  @Test
+  public void testAdditionalRealms_Null() {
+    AuthToLocalBuilder builder = new AuthToLocalBuilder(false, null);
+
+    builder.addRule("nn/_HOST@EXAMPLE.COM", "hdfs");
+    builder.addRule("dn/_HOST@EXAMPLE.COM", "hdfs");
+    builder.addRule("jn/_HOST@EXAMPLE.COM", "hdfs");
+    builder.addRule("rm/_HOST@EXAMPLE.COM", "yarn");
+    builder.addRule("jhs/_HOST@EXAMPLE.COM", "mapred");
+    builder.addRule("hm/_HOST@EXAMPLE.COM", "hbase");
+    builder.addRule("rs/_HOST@EXAMPLE.COM", "hbase");
+
+    assertEquals(
+        "RULE:[1:$1@$0](.*@EXAMPLE.COM)s/@.*//\n" +
+            "RULE:[2:$1@$0](dn@EXAMPLE.COM)s/.*/hdfs/\n" +
+            "RULE:[2:$1@$0](hm@EXAMPLE.COM)s/.*/hbase/\n" +
+            "RULE:[2:$1@$0](jhs@EXAMPLE.COM)s/.*/mapred/\n" +
+            "RULE:[2:$1@$0](jn@EXAMPLE.COM)s/.*/hdfs/\n" +
+            "RULE:[2:$1@$0](nn@EXAMPLE.COM)s/.*/hdfs/\n" +
+            "RULE:[2:$1@$0](rm@EXAMPLE.COM)s/.*/yarn/\n" +
+            "RULE:[2:$1@$0](rs@EXAMPLE.COM)s/.*/hbase/\n" +
+            "DEFAULT",
+        builder.generate("EXAMPLE.COM"));
+  }
+
+  @Test
+  public void testAdditionalRealms_Empty() {
+    AuthToLocalBuilder builder = new AuthToLocalBuilder(false, "");
+
+    builder.addRule("nn/_HOST@EXAMPLE.COM", "hdfs");
+    builder.addRule("dn/_HOST@EXAMPLE.COM", "hdfs");
+    builder.addRule("jn/_HOST@EXAMPLE.COM", "hdfs");
+    builder.addRule("rm/_HOST@EXAMPLE.COM", "yarn");
+    builder.addRule("jhs/_HOST@EXAMPLE.COM", "mapred");
+    builder.addRule("hm/_HOST@EXAMPLE.COM", "hbase");
+    builder.addRule("rs/_HOST@EXAMPLE.COM", "hbase");
+
+    assertEquals(
+        "RULE:[1:$1@$0](.*@EXAMPLE.COM)s/@.*//\n" +
+            "RULE:[2:$1@$0](dn@EXAMPLE.COM)s/.*/hdfs/\n" +
+            "RULE:[2:$1@$0](hm@EXAMPLE.COM)s/.*/hbase/\n" +
+            "RULE:[2:$1@$0](jhs@EXAMPLE.COM)s/.*/mapred/\n" +
+            "RULE:[2:$1@$0](jn@EXAMPLE.COM)s/.*/hdfs/\n" +
+            "RULE:[2:$1@$0](nn@EXAMPLE.COM)s/.*/hdfs/\n" +
+            "RULE:[2:$1@$0](rm@EXAMPLE.COM)s/.*/yarn/\n" +
+            "RULE:[2:$1@$0](rs@EXAMPLE.COM)s/.*/hbase/\n" +
+            "DEFAULT",
+        builder.generate("EXAMPLE.COM"));
+  }
 }

+ 1 - 0
ambari-server/src/test/java/org/apache/ambari/server/controller/KerberosHelperTest.java

@@ -1625,6 +1625,7 @@ public class KerberosHelperTest extends EasyMockSupport {
     ))).times(1);
 
     final KerberosDescriptor kerberosDescriptor = createMock(KerberosDescriptor.class);
+    expect(kerberosDescriptor.getProperty("additional_realms")).andReturn(null).times(1);
     expect(kerberosDescriptor.getIdentities()).andReturn(null).times(1);
     expect(kerberosDescriptor.getAuthToLocalProperties()).andReturn(null).times(1);
     expect(kerberosDescriptor.getServices()).andReturn(Collections.singletonMap("SERVICE1", serviceDescriptor1)).times(1);

+ 2 - 1
ambari-server/src/test/resources/stacks/HDP/2.0.8/kerberos.json

@@ -1,7 +1,8 @@
 {
   "properties": {
     "realm": "${cluster-env/kerberos_domain}",
-    "keytab_dir": "/etc/security/keytabs"
+    "keytab_dir": "/etc/security/keytabs",
+    "additional_realms": ""
   },
   "identities": [
     {

+ 1 - 0
ambari-web/app/mixins/wizard/addSecurityConfigs.js

@@ -215,6 +215,7 @@ App.AddSecurityConfigs = Em.Mixin.create({
         displayName: serviceName == "Cluster" ? App.format.normalizeName(propertyName) : propertyName,
         isOverridable: false,
         isEditable: propertyName != 'realm',
+        isRequired: propertyName != 'additional_realms',
         isSecureConfig: true
       };
       configs.push(App.ServiceConfigProperty.create(propertyObject));