Repository: kafka
Updated Branches:
  refs/heads/trunk 0a508a436 -> b08882213


KAFKA-5764; Add toLowerCase support to sasl.kerberos.principal.to.local rule 
(KIP-203)

Author: Manikumar Reddy <manikumar.re...@gmail.com>

Reviewers: Jason Gustafson <ja...@confluent.io>

Closes #3800 from omkreddy/KAFKA-5764-REGEX


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

Branch: refs/heads/trunk
Commit: b08882213489706c663785f2c94d76584ba6e856
Parents: 0a508a4
Author: Manikumar Reddy <manikumar.re...@gmail.com>
Authored: Tue Dec 12 15:47:49 2017 -0800
Committer: Jason Gustafson <ja...@confluent.io>
Committed: Tue Dec 12 15:47:57 2017 -0800

----------------------------------------------------------------------
 .../common/security/kerberos/KerberosRule.java  | 12 ++++-
 .../security/kerberos/KerberosShortNamer.java   | 13 ++---
 .../security/kerberos/KerberosNameTest.java     | 57 ++++++++++++++++++--
 docs/security.html                              | 11 +++-
 4 files changed, 82 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kafka/blob/b0888221/clients/src/main/java/org/apache/kafka/common/security/kerberos/KerberosRule.java
----------------------------------------------------------------------
diff --git 
a/clients/src/main/java/org/apache/kafka/common/security/kerberos/KerberosRule.java
 
b/clients/src/main/java/org/apache/kafka/common/security/kerberos/KerberosRule.java
index 40a9a1f..37820df 100644
--- 
a/clients/src/main/java/org/apache/kafka/common/security/kerberos/KerberosRule.java
+++ 
b/clients/src/main/java/org/apache/kafka/common/security/kerberos/KerberosRule.java
@@ -17,6 +17,7 @@
 package org.apache.kafka.common.security.kerberos;
 
 import java.io.IOException;
+import java.util.Locale;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -44,6 +45,7 @@ class KerberosRule {
     private final Pattern fromPattern;
     private final String toPattern;
     private final boolean repeat;
+    private final boolean toLowerCase;
 
     KerberosRule(String defaultRealm) {
         this.defaultRealm = defaultRealm;
@@ -54,10 +56,11 @@ class KerberosRule {
         fromPattern = null;
         toPattern = null;
         repeat = false;
+        toLowerCase = false;
     }
 
     KerberosRule(String defaultRealm, int numOfComponents, String format, 
String match, String fromPattern,
-                 String toPattern, boolean repeat) {
+                 String toPattern, boolean repeat, boolean toLowerCase) {
         this.defaultRealm = defaultRealm;
         isDefault = false;
         this.numOfComponents = numOfComponents;
@@ -67,6 +70,7 @@ class KerberosRule {
                 fromPattern == null ? null : Pattern.compile(fromPattern);
         this.toPattern = toPattern;
         this.repeat = repeat;
+        this.toLowerCase = toLowerCase;
     }
 
     @Override
@@ -95,6 +99,9 @@ class KerberosRule {
                     buf.append('g');
                 }
             }
+            if (toLowerCase) {
+                buf.append("/L");
+            }
         }
         return buf.toString();
     }
@@ -182,6 +189,9 @@ class KerberosRule {
         if (result != null && NON_SIMPLE_PATTERN.matcher(result).find()) {
             throw new NoMatchingRule("Non-simple name " + result + " after 
auth_to_local rule " + this);
         }
+        if (toLowerCase && result != null) {
+            result = result.toLowerCase(Locale.ENGLISH);
+        }
         return result;
     }
 }

http://git-wip-us.apache.org/repos/asf/kafka/blob/b0888221/clients/src/main/java/org/apache/kafka/common/security/kerberos/KerberosShortNamer.java
----------------------------------------------------------------------
diff --git 
a/clients/src/main/java/org/apache/kafka/common/security/kerberos/KerberosShortNamer.java
 
b/clients/src/main/java/org/apache/kafka/common/security/kerberos/KerberosShortNamer.java
index 1db984a..69b4689 100644
--- 
a/clients/src/main/java/org/apache/kafka/common/security/kerberos/KerberosShortNamer.java
+++ 
b/clients/src/main/java/org/apache/kafka/common/security/kerberos/KerberosShortNamer.java
@@ -33,7 +33,7 @@ public class KerberosShortNamer {
     /**
      * A pattern for parsing a auth_to_local rule.
      */
-    private static final Pattern RULE_PARSER = 
Pattern.compile("((DEFAULT)|(RULE:\\[(\\d*):([^\\]]*)](\\(([^)]*)\\))?(s/([^/]*)/([^/]*)/(g)?)?))");
+    private static final Pattern RULE_PARSER = 
Pattern.compile("((DEFAULT)|((RULE:\\[(\\d*):([^\\]]*)](\\(([^)]*)\\))?(s/([^/]*)/([^/]*)/(g)?)?/?(L)?)))");
 
     /* Rules for the translation of the principal name into an operating 
system name */
     private final List<KerberosRule> principalToLocalRules;
@@ -60,12 +60,13 @@ public class KerberosShortNamer {
                 result.add(new KerberosRule(defaultRealm));
             } else {
                 result.add(new KerberosRule(defaultRealm,
-                        Integer.parseInt(matcher.group(4)),
-                        matcher.group(5),
-                        matcher.group(7),
-                        matcher.group(9),
+                        Integer.parseInt(matcher.group(5)),
+                        matcher.group(6),
+                        matcher.group(8),
                         matcher.group(10),
-                        "g".equals(matcher.group(11))));
+                        matcher.group(11),
+                        "g".equals(matcher.group(12)),
+                        "L".equals(matcher.group(13))));
 
             }
         }

http://git-wip-us.apache.org/repos/asf/kafka/blob/b0888221/clients/src/test/java/org/apache/kafka/common/security/kerberos/KerberosNameTest.java
----------------------------------------------------------------------
diff --git 
a/clients/src/test/java/org/apache/kafka/common/security/kerberos/KerberosNameTest.java
 
b/clients/src/test/java/org/apache/kafka/common/security/kerberos/KerberosNameTest.java
index 3fbd310..1acd80c 100644
--- 
a/clients/src/test/java/org/apache/kafka/common/security/kerberos/KerberosNameTest.java
+++ 
b/clients/src/test/java/org/apache/kafka/common/security/kerberos/KerberosNameTest.java
@@ -19,22 +19,23 @@ package org.apache.kafka.common.security.kerberos;
 import org.junit.Test;
 
 import java.io.IOException;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
 
 public class KerberosNameTest {
 
     @Test
     public void testParse() throws IOException {
-        List<String> rules = new ArrayList<>(Arrays.asList(
+        List<String> rules = Arrays.asList(
             "RULE:[1:$1](App\\..*)s/App\\.(.*)/$1/g",
             "RULE:[2:$1](App\\..*)s/App\\.(.*)/$1/g",
             "DEFAULT"
-        ));
+        );
+
         KerberosShortNamer shortNamer = 
KerberosShortNamer.fromUnparsedRules("REALM.COM", rules);
 
         KerberosName name = 
KerberosName.parse("App.service-name/example....@realm.com");
@@ -55,4 +56,54 @@ public class KerberosNameTest {
         assertEquals("REALM.COM", name.realm());
         assertEquals("user", shortNamer.shortName(name));
     }
+
+    @Test
+    public void testToLowerCase() throws Exception {
+        List<String> rules = Arrays.asList(
+            "RULE:[1:$1]/L",
+            "RULE:[2:$1](Test.*)s/ABC///L",
+            "RULE:[2:$1](ABC.*)s/ABC/XYZ/g/L",
+            "RULE:[2:$1](App\\..*)s/App\\.(.*)/$1/g/L",
+            "RULE:[2:$1]/L",
+            "DEFAULT"
+        );
+
+        KerberosShortNamer shortNamer = 
KerberosShortNamer.fromUnparsedRules("REALM.COM", rules);
+
+        KerberosName name = KerberosName.parse("u...@realm.com");
+        assertEquals("user", shortNamer.shortName(name));
+
+        name = KerberosName.parse("TestABC/h...@foo.com");
+        assertEquals("test", shortNamer.shortName(name));
+
+        name = KerberosName.parse("ABC_User_ABC/h...@foo.com");
+        assertEquals("xyz_user_xyz", shortNamer.shortName(name));
+
+        name = KerberosName.parse("App.SERVICE-name/example....@realm.com");
+        assertEquals("service-name", shortNamer.shortName(name));
+
+        name = KerberosName.parse("User/r...@realm.com");
+        assertEquals("user", shortNamer.shortName(name));
+    }
+
+    @Test
+    public void testInvalidRules() throws Exception {
+        testInvalidRule(Arrays.asList("default"));
+        testInvalidRule(Arrays.asList("DEFAUL"));
+        testInvalidRule(Arrays.asList("DEFAULT/L"));
+        testInvalidRule(Arrays.asList("DEFAULT/g"));
+
+        testInvalidRule(Arrays.asList("rule:[1:$1]"));
+        testInvalidRule(Arrays.asList("RULE:[1:$1/L"));
+        testInvalidRule(Arrays.asList("RULE:[1:$1]/l"));
+        testInvalidRule(Arrays.asList("RULE:[2:$1](ABC.*)s/ABC/XYZ/L/g"));
+    }
+
+    private void testInvalidRule(List<String> rules) {
+        try {
+            KerberosShortNamer.fromUnparsedRules("REALM.COM", rules);
+            fail("should have thrown IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/kafka/blob/b0888221/docs/security.html
----------------------------------------------------------------------
diff --git a/docs/security.html b/docs/security.html
index 8c1bda9..c8e20ea 100644
--- a/docs/security.html
+++ b/docs/security.html
@@ -671,7 +671,16 @@
     By default, the SSL user name will be of the form 
"CN=writeuser,OU=Unknown,O=Unknown,L=Unknown,ST=Unknown,C=Unknown". One can 
change that by setting a customized PrincipalBuilder in server.properties like 
the following.
     <pre>principal.builder.class=CustomizedPrincipalBuilderClass</pre>
     By default, the SASL user name will be the primary part of the Kerberos 
principal. One can change that by setting 
<code>sasl.kerberos.principal.to.local.rules</code> to a customized rule in 
server.properties.
-    The format of <code>sasl.kerberos.principal.to.local.rules</code> is a 
list where each rule works in the same way as the auth_to_local in <a 
href="http://web.mit.edu/Kerberos/krb5-latest/doc/admin/conf_files/krb5_conf.html";>Kerberos
 configuration file (krb5.conf)</a>. Each rules starts with RULE: and contains 
an expression in the format [n:string](regexp)s/pattern/replacement/g. See the 
kerberos documentation for more details. An example of adding a rule to 
properly translate u...@mydomain.com to user while also keeping the default 
rule in place is:
+    The format of <code>sasl.kerberos.principal.to.local.rules</code> is a 
list where each rule works in the same way as the auth_to_local in <a 
href="http://web.mit.edu/Kerberos/krb5-latest/doc/admin/conf_files/krb5_conf.html";>Kerberos
 configuration file (krb5.conf)</a>. This also support additional lowercase 
rule, to force the translated result to be all lower case. This is done by 
adding a "/L" to the end of the rule. check below formats for syntax.
+    Each rules starts with RULE: and contains an expression as the following 
formats. See the kerberos documentation for more details.
+    <pre>
+        RULE:[n:string](regexp)s/pattern/replacement/
+        RULE:[n:string](regexp)s/pattern/replacement/g
+        RULE:[n:string](regexp)s/pattern/replacement//L
+        RULE:[n:string](regexp)s/pattern/replacement/g/L
+    </pre>
+
+    An example of adding a rule to properly translate u...@mydomain.com to 
user while also keeping the default rule in place is:
     
<pre>sasl.kerberos.principal.to.local.rules=RULE:[1:$1@$0](.*@MYDOMAIN.COM)s/@.*//,DEFAULT</pre>
 
     <h4><a id="security_authz_cli" href="#security_authz_cli">Command Line 
Interface</a></h4>

Reply via email to