You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by pl...@apache.org on 2018/07/06 06:29:24 UTC

directory-kerby git commit: DIRKRB-722 Add HAS client login tool.

Repository: directory-kerby
Updated Branches:
  refs/heads/trunk 5ec8b2053 -> 9a02da485


DIRKRB-722 Add HAS client login tool.


Project: http://git-wip-us.apache.org/repos/asf/directory-kerby/repo
Commit: http://git-wip-us.apache.org/repos/asf/directory-kerby/commit/9a02da48
Tree: http://git-wip-us.apache.org/repos/asf/directory-kerby/tree/9a02da48
Diff: http://git-wip-us.apache.org/repos/asf/directory-kerby/diff/9a02da48

Branch: refs/heads/trunk
Commit: 9a02da4859ccf94b5ba08567aeca488f109479c6
Parents: 5ec8b20
Author: plusplusjiajia <ji...@intel.com>
Authored: Fri Jul 6 14:29:16 2018 +0800
Committer: plusplusjiajia <ji...@intel.com>
Committed: Fri Jul 6 14:29:16 2018 +0800

----------------------------------------------------------------------
 .../apache/kerby/has/common/HasConfigKey.java   |   2 +-
 .../kerby/has/common/util/HasJaasLoginUtil.java | 110 ++++++++
 .../apache/kerby/has/common/util/HasUtil.java   |   2 +-
 kerby-dist/has-dist/bin/admin-local.sh          |   2 +-
 kerby-dist/has-dist/bin/login-test.sh           |  34 +++
 .../tool/hclient/HasClientLoginTool.java        | 272 +++++++++++++++++++
 6 files changed, 419 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9a02da48/has-project/has-common/src/main/java/org/apache/kerby/has/common/HasConfigKey.java
----------------------------------------------------------------------
diff --git a/has-project/has-common/src/main/java/org/apache/kerby/has/common/HasConfigKey.java b/has-project/has-common/src/main/java/org/apache/kerby/has/common/HasConfigKey.java
index 272ab0e..d4cc474 100644
--- a/has-project/has-common/src/main/java/org/apache/kerby/has/common/HasConfigKey.java
+++ b/has-project/has-common/src/main/java/org/apache/kerby/has/common/HasConfigKey.java
@@ -26,7 +26,7 @@ public enum HasConfigKey implements ConfigKey {
     HTTP_PORT,
     HTTPS_HOST,
     HTTPS_PORT,
-    AUTH_TYPE("RAM"),
+    AUTH_TYPE("MySQL"),
     REALM,
     ENABLE_CONF,
     SSL_SERVER_CONF("/etc/has/ssl-server.conf"),

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9a02da48/has-project/has-common/src/main/java/org/apache/kerby/has/common/util/HasJaasLoginUtil.java
----------------------------------------------------------------------
diff --git a/has-project/has-common/src/main/java/org/apache/kerby/has/common/util/HasJaasLoginUtil.java b/has-project/has-common/src/main/java/org/apache/kerby/has/common/util/HasJaasLoginUtil.java
new file mode 100644
index 0000000..a4c9590
--- /dev/null
+++ b/has-project/has-common/src/main/java/org/apache/kerby/has/common/util/HasJaasLoginUtil.java
@@ -0,0 +1,110 @@
+/**
+ *  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.kerby.has.common.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.AppConfigurationEntry;
+import javax.security.auth.login.Configuration;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * JAAS utilities for Has login.
+ */
+public class HasJaasLoginUtil {
+    public static final Logger LOG = LoggerFactory.getLogger(HasJaasLoginUtil.class);
+
+    public static final boolean ENABLE_DEBUG = true;
+
+    private static String getKrb5LoginModuleName() {
+        return System.getProperty("java.vendor").contains("IBM")
+            ? "com.ibm.security.auth.module.Krb5LoginModule"
+            : "org.apache.kerby.has.client.HasLoginModule";
+    }
+
+    /**
+     * Log a user in from a tgt ticket.
+     *
+     * @throws IOException
+     */
+    public static synchronized Subject loginUserFromTgtTicket(String hadoopSecurityHas) throws IOException {
+
+        TICKET_KERBEROS_OPTIONS.put("hadoopSecurityHas", hadoopSecurityHas);
+        Subject subject = new Subject();
+        Configuration conf = new HasJaasConf();
+        String confName = "ticket-kerberos";
+        LoginContext loginContext = null;
+        try {
+            loginContext = new LoginContext(confName, subject, null, conf);
+        } catch (LoginException e) {
+            throw new IOException("Fail to create LoginContext for " + e);
+        }
+        try {
+            loginContext.login();
+            LOG.info("Login successful for user "
+                + subject.getPrincipals().iterator().next().getName());
+        } catch (LoginException e) {
+            throw new IOException("Login failure for " + e);
+        }
+        return loginContext.getSubject();
+    }
+
+    /**
+     * Has Jaas config.
+     */
+    static class HasJaasConf extends Configuration {
+        @Override
+        public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
+
+            return new AppConfigurationEntry[]{
+                TICKET_KERBEROS_LOGIN};
+        }
+    }
+
+    private static final Map<String, String> BASIC_JAAS_OPTIONS =
+        new HashMap<String, String>();
+
+    static {
+        String jaasEnvVar = System.getenv("HADOOP_JAAS_DEBUG");
+        if (jaasEnvVar != null && "true".equalsIgnoreCase(jaasEnvVar)) {
+            BASIC_JAAS_OPTIONS.put("debug", String.valueOf(ENABLE_DEBUG));
+        }
+    }
+
+    private static final Map<String, String> TICKET_KERBEROS_OPTIONS =
+        new HashMap<String, String>();
+
+    static {
+        TICKET_KERBEROS_OPTIONS.put("doNotPrompt", "true");
+        TICKET_KERBEROS_OPTIONS.put("useTgtTicket", "true");
+        TICKET_KERBEROS_OPTIONS.putAll(BASIC_JAAS_OPTIONS);
+    }
+
+    private static final AppConfigurationEntry TICKET_KERBEROS_LOGIN =
+        new AppConfigurationEntry(getKrb5LoginModuleName(),
+            AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL,
+            TICKET_KERBEROS_OPTIONS);
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9a02da48/has-project/has-common/src/main/java/org/apache/kerby/has/common/util/HasUtil.java
----------------------------------------------------------------------
diff --git a/has-project/has-common/src/main/java/org/apache/kerby/has/common/util/HasUtil.java b/has-project/has-common/src/main/java/org/apache/kerby/has/common/util/HasUtil.java
index 6b01058..c972955 100644
--- a/has-project/has-common/src/main/java/org/apache/kerby/has/common/util/HasUtil.java
+++ b/has-project/has-common/src/main/java/org/apache/kerby/has/common/util/HasUtil.java
@@ -51,7 +51,7 @@ public class HasUtil {
             }
             return hasConfig;
         } else {
-            throw new HasException(hasConfFile.getName() + "not found in "
+            throw new HasException(hasConfFile.getName() + " not found in "
                 + hasConfFile.getParent() + ". ");
         }
     }

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9a02da48/kerby-dist/has-dist/bin/admin-local.sh
----------------------------------------------------------------------
diff --git a/kerby-dist/has-dist/bin/admin-local.sh b/kerby-dist/has-dist/bin/admin-local.sh
index 1b0cc67..84b3918 100644
--- a/kerby-dist/has-dist/bin/admin-local.sh
+++ b/kerby-dist/has-dist/bin/admin-local.sh
@@ -42,7 +42,7 @@ cd ${HAS_HOME}
 
 for var in $*; do
   if [ X"$var" = X"-D" ]; then
-    DEBUG="-Xdebug -Xrunjdwp:transport=dt_socket,address=8002,server=y,suspend=n"
+    DEBUG="-Xdebug -Xrunjdwp:transport=dt_socket,address=8013,server=y,suspend=n"
   elif [ ! -d "$var" ]; then
     args="$args $var"
   fi

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9a02da48/kerby-dist/has-dist/bin/login-test.sh
----------------------------------------------------------------------
diff --git a/kerby-dist/has-dist/bin/login-test.sh b/kerby-dist/has-dist/bin/login-test.sh
new file mode 100644
index 0000000..4db4dcf
--- /dev/null
+++ b/kerby-dist/has-dist/bin/login-test.sh
@@ -0,0 +1,34 @@
+#!/usr/bin/env bash
+
+# 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.
+
+APP_MAIN=org.apache.kerby.kerberos.tool.hclient.HasClientLoginTool
+
+# Get HAS_HOME directory
+bin=`dirname "$0"`
+HAS_HOME=`cd ${bin}/..; pwd`
+cd ${HAS_HOME}
+
+for var in $*; do
+  if [ X"$var" = X"-D" ]; then
+    DEBUG="-Xdebug -Xrunjdwp:transport=dt_socket,address=8014,server=y,suspend=y"
+  else
+    args="$args $var"
+  fi
+done
+
+java ${DEBUG} -classpath target/lib/*:. ${APP_MAIN} ${args}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9a02da48/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/hclient/HasClientLoginTool.java
----------------------------------------------------------------------
diff --git a/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/hclient/HasClientLoginTool.java b/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/hclient/HasClientLoginTool.java
new file mode 100644
index 0000000..a49a7e7
--- /dev/null
+++ b/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/hclient/HasClientLoginTool.java
@@ -0,0 +1,272 @@
+/**
+ *  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.kerby.kerberos.tool.hclient;
+
+import org.apache.kerby.has.client.HasAuthAdminClient;
+import org.apache.kerby.has.client.HasClient;
+import org.apache.kerby.has.common.HasConfig;
+import org.apache.kerby.has.common.HasException;
+import org.apache.kerby.has.common.util.HasJaasLoginUtil;
+import org.apache.kerby.has.common.util.HasUtil;
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.client.JaasKrbUtil;
+import org.apache.kerby.kerberos.kerb.server.KdcConfig;
+import org.apache.kerby.kerberos.kerb.server.KdcUtil;
+import org.apache.kerby.kerberos.kerb.type.ticket.TgtTicket;
+import org.apache.kerby.util.OSUtil;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginException;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+public class HasClientLoginTool {
+    private static List<String> principalList = new ArrayList<String>();
+    private static List<File>  keytabList = new ArrayList<File>();
+
+    private static final String KEYTAB_USAGE = (OSUtil.isWindows()
+        ? "Usage: bin\\k=login-test.cmd" : "Usage: sh bin/login-test.sh")
+        + " [add|run|delete] [conf_dir] [work_dir] [number]\n"
+        + "\n";
+
+    private static final String TGT_USAGE = (OSUtil.isWindows()
+        ? "Usage: bin\\k=login-test.cmd" : "Usage: sh bin/login-test.sh")
+        + " tgt [conf_dir]\n"
+        + "\n";
+
+    private static void printKeytabUsage(String error) {
+        System.err.println(error + "\n");
+        System.err.println(KEYTAB_USAGE);
+        System.exit(-1);
+    }
+
+    private static void printTgtUsage(String error) {
+        System.err.println(error + "\n");
+        System.err.println(TGT_USAGE);
+        System.exit(-1);
+    }
+
+    public static class Task implements Runnable {
+        private int index;
+
+        Task(int index) {
+            this.index = index;
+        }
+
+        @Override
+        public void run() {
+            Subject subject = null;
+            try {
+                subject = JaasKrbUtil.loginUsingKeytab(principalList.get(index),
+                    keytabList.get(index));
+            } catch (LoginException e) {
+                System.err.println("Fail to login using keytab. " + e);
+            }
+            System.out.println("Login succeeded for user: "
+                + subject.getPrincipals().iterator().next());
+        }
+    }
+
+    public static void main(String[] args) {
+
+        if (args.length < 2) {
+            System.err.println(TGT_USAGE);
+            System.err.println(KEYTAB_USAGE);
+            return;
+        }
+
+        String cmd = args[0];
+        File confDir;
+        File workDir;
+
+        if (cmd.equals("tgt")) {
+            if (args.length != 2) {
+                printTgtUsage("Need 2 args.");
+                return;
+            }
+
+            confDir = new File(args[1]);
+            if (!confDir.exists()) {
+                printTgtUsage("Need the valid conf dir.");
+                return;
+            }
+            File confFile = new File(confDir, "admin.conf");
+            HasConfig hasConfig;
+            try {
+                hasConfig = HasUtil.getHasConfig(confFile);
+            } catch (HasException e) {
+                System.err.println(e.getMessage());
+                return;
+            }
+            if (hasConfig == null) {
+                System.err.println("admin.conf not exist in " + confDir.getAbsolutePath());
+                return;
+            }
+            String host = hasConfig.getHttpsHost();
+            String port = hasConfig.getHttpsPort();
+            String type = hasConfig.getPluginName();
+
+            HasClient hasClient = new HasClient();
+            TgtTicket tgtTicket;
+            try {
+                tgtTicket = hasClient.requestTgt();
+            } catch (HasException e) {
+                System.err.println("Errors occurred when getting TGT. " + e.getMessage());
+                return;
+            }
+
+            System.out.println("Get the tgt ticket successfully!");
+            System.out.println("The client principal of tgt ticket: " + tgtTicket.getClientPrincipal());
+
+            Subject subject = null;
+            try {
+                subject = HasJaasLoginUtil.loginUserFromTgtTicket(
+                    "https://" + host + ":" + port + "/has/v1?auth_type=" + type);
+            } catch (IOException e) {
+                System.err.println("Errors occurred when login user with TGT. " + e.getMessage());
+                return;
+            }
+
+            System.out.println("Principal: " + subject.getPrincipals().iterator().next());
+        } else {
+            if (args.length != 4) {
+                printKeytabUsage("Need 4 args.");
+                return;
+            }
+
+            confDir = new File(args[1]);
+            workDir = new File(args[2]);
+
+            if (!confDir.exists()) {
+                printKeytabUsage("Need the valid conf dir.");
+                return;
+            }
+            if (!workDir.exists()) {
+                printKeytabUsage("Need the valid work dir.");
+                return;
+            }
+
+            int taskNum = Integer.parseInt(args[3]);
+
+            System.out.println("The task num is: " + taskNum);
+
+            if (taskNum <= 0) {
+                printKeytabUsage("The task num must be greater than zero");
+                System.exit(-1);
+            }
+
+            HasAuthAdminClient authHasAdminClient = null;
+            File confFile = new File(confDir, "admin.conf");
+            HasConfig hasConfig = null;
+            try {
+                hasConfig = HasUtil.getHasConfig(confFile);
+            } catch (HasException e) {
+                System.err.println(e.getMessage());
+                return;
+            }
+
+            if (hasConfig == null) {
+                System.err.println("admin.conf not exist in " + confDir.getAbsolutePath());
+                return;
+            }
+
+            if (hasConfig.getFilterAuthType().equals("kerberos")) {
+                authHasAdminClient = new HasAuthAdminClient(hasConfig);
+            }
+
+            String realm = null;
+            try {
+                KdcConfig kdcConfig = KdcUtil.getKdcConfig(confDir);
+                realm = kdcConfig.getKdcRealm();
+            } catch (KrbException e) {
+                printKeytabUsage(e.getMessage());
+            }
+
+            if (cmd.equals("add")) {
+                for (int i = 0; i < taskNum; i++) {
+                    String principal = "test" + i + "@" + realm;
+                    try {
+                        authHasAdminClient.addPrincipal(principal);
+                    } catch (KrbException e) {
+                        System.err.println("Errors occurred when adding principal. "
+                            + e.getMessage());
+                        return;
+                    }
+                    File keytabFile = new File(workDir, i + ".keytab");
+                    try {
+                        authHasAdminClient.exportKeytab(keytabFile, principal);
+                    } catch (KrbException e) {
+                        System.err.println("Errors occurred when exporting the keytabs. "
+                            + e.getMessage());
+                        return;
+                    }
+                    System.out.println("Add principals and keytabs successfully.");
+                }
+            } else if (cmd.equals("run")) {
+                ExecutorService exec;
+                for (int i = 0; i < taskNum; i++) {
+                    String principal = "test" + i + "@" + realm;
+                    principalList.add(i, principal);
+                    File file = new File(workDir, i + ".keytab");
+                    keytabList.add(i, file);
+                }
+                System.out.println("Start the login test.");
+                Long startTime = System.currentTimeMillis();
+                exec = Executors.newFixedThreadPool(5);
+                for (int i = 0; i < taskNum; ++i) {
+                    exec.submit(new Task(i));
+                }
+                exec.shutdown();
+                try {
+                    exec.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
+                } catch (InterruptedException e) {
+                    System.err.println(e.getMessage());
+                    return;
+                }
+                Long endTime = System.currentTimeMillis();
+                System.out.println("Finish the login test.");
+                System.out.println("Cost time: " + (endTime - startTime) + "ms");
+            } else if (cmd.equals("delete")) {
+                for (int i = 0; i < taskNum; i++) {
+                    String principal = "test" + i + "@" + realm;
+                    try {
+                        authHasAdminClient.deletePrincipal(principal);
+                    } catch (KrbException e) {
+                        System.err.println("Errors occurred when deleting the principal. "
+                            + e.getMessage());
+                        continue;
+                    }
+                    File file = new File(workDir, i + ".keytab");
+                    if (!file.delete()) {
+                        System.err.println("Failed to delete " + i + ".keytab.");
+                    }
+                }
+                System.out.println("Delete principals and keytabs successfully.");
+            } else {
+                printKeytabUsage("Need the cmd with add, run or delete.");
+            }
+        }
+    }
+}