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 2020/08/03 11:31:39 UTC

[directory-kerby] branch trunk updated: DIRKRB-746 Verify kadmin principal in HAS remote kadmin tool. Contributed by Jiayi Liu.

This is an automated email from the ASF dual-hosted git repository.

plusplusjiajia pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/directory-kerby.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 7b4286a  DIRKRB-746 Verify kadmin principal in HAS remote kadmin tool. Contributed by Jiayi Liu.
7b4286a is described below

commit 7b4286aa5646bd54d8dfd3ca74b604ddc109d716
Author: Li Jiajia <lj...@alibaba-inc.com>
AuthorDate: Mon Aug 3 19:31:12 2020 +0800

    DIRKRB-746 Verify kadmin principal in HAS remote kadmin tool. Contributed by Jiayi Liu.
---
 has-project/docs/deploy-spnego.md                  |  4 +-
 .../kerby/has/client/HasAuthAdminClient.java       |  3 +-
 .../kerby/has/server/web/rest/KadminApi.java       | 51 ++++++++++++++++++++++
 kerby-dist/has-dist/conf/admin.conf                |  2 +-
 .../tool/admin/remote/AdminRemoteTool.java         |  3 ++
 5 files changed, 59 insertions(+), 4 deletions(-)

diff --git a/has-project/docs/deploy-spnego.md b/has-project/docs/deploy-spnego.md
index 803c345..3f18907 100644
--- a/has-project/docs/deploy-spnego.md
+++ b/has-project/docs/deploy-spnego.md
@@ -28,5 +28,5 @@ To use Kerberos SPNEGO as the authentication mechanism, the authentication filte
 ## 2. Client Side Configuration(in client side admin.conf)
 
 - filter_auth_type the keyword kerberos.  For example: filter_auth_type = kerberos
-- admin_keytab: The path to the keytab file containing the credential for the admin principal. For example: admin_keytab = /etc/has/admin.keytab
-- admin_keytab_principal: The admin principal. For example: admin_keytab_principal = kadmin/<YOUR-REALM.COM>@<YOUR-REALM.COM>
+- admin_keytab: The path to the keytab file containing the credential for the admin principal(kadmin/<YOUR-REALM.COM>@<YOUR-REALM.COM>). For example: admin_keytab = /etc/has/admin.keytab
+- realm: The realm of KDC. For example: realm = YOUR-REALM.COM
diff --git a/has-project/has-client/src/main/java/org/apache/kerby/has/client/HasAuthAdminClient.java b/has-project/has-client/src/main/java/org/apache/kerby/has/client/HasAuthAdminClient.java
index 22a39f9..d6cd9a3 100644
--- a/has-project/has-client/src/main/java/org/apache/kerby/has/client/HasAuthAdminClient.java
+++ b/has-project/has-client/src/main/java/org/apache/kerby/has/client/HasAuthAdminClient.java
@@ -23,6 +23,7 @@ import org.apache.kerby.KOptions;
 import org.apache.kerby.has.common.HasConfig;
 import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.admin.kadmin.Kadmin;
+import org.apache.kerby.kerberos.kerb.common.KrbUtil;
 import org.codehaus.jettison.json.JSONArray;
 import org.codehaus.jettison.json.JSONException;
 import org.slf4j.Logger;
@@ -384,7 +385,7 @@ public class HasAuthAdminClient implements Kadmin {
 
     @Override
     public String getKadminPrincipal() {
-        return null;
+        return KrbUtil.makeKadminPrincipal(hasConfig.getRealm()).getName();
     }
 
     @Override
diff --git a/has-project/has-server/src/main/java/org/apache/kerby/has/server/web/rest/KadminApi.java b/has-project/has-server/src/main/java/org/apache/kerby/has/server/web/rest/KadminApi.java
index 040bf8a..21a35d5 100644
--- a/has-project/has-server/src/main/java/org/apache/kerby/has/server/web/rest/KadminApi.java
+++ b/has-project/has-server/src/main/java/org/apache/kerby/has/server/web/rest/KadminApi.java
@@ -17,12 +17,14 @@
  */
 package org.apache.kerby.has.server.web.rest;
 
+import org.apache.hadoop.security.authentication.server.AuthenticationToken;
 import org.apache.kerby.has.server.HasServer;
 import org.apache.kerby.has.server.web.WebServer;
 import org.apache.kerby.has.server.web.rest.param.PasswordParam;
 import org.apache.kerby.has.server.web.rest.param.PrincipalParam;
 import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.admin.kadmin.local.LocalKadminImpl;
+import org.apache.kerby.kerberos.kerb.common.KrbUtil;
 import org.apache.kerby.kerberos.kerb.request.KrbIdentity;
 import org.apache.kerby.kerberos.kerb.server.KdcSetting;
 import org.apache.kerby.kerberos.kerb.type.base.EncryptionKey;
@@ -44,6 +46,7 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import java.io.File;
+import java.security.Principal;
 import java.util.List;
 import java.util.Map;
 
@@ -76,6 +79,9 @@ public class KadminApi {
         if (globalModeVlue.equals(isGlobal)) {
             global = true;
         }
+        if (!isAdminPrincipal()) {
+            return Response.status(Response.Status.FORBIDDEN).entity("kadmin principal required.\n").build();
+        }
         if (httpRequest.isSecure()) {
             WebServer.LOG.info("Exporting keytab file for " + principal + "...");
             String msg;
@@ -152,6 +158,9 @@ public class KadminApi {
     @Path("/listprincipals")
     @Produces(MediaType.APPLICATION_JSON)
     public Response listPrincipals(@QueryParam("exp") String exp) {
+        if (!isAdminPrincipal()) {
+            return Response.status(Response.Status.FORBIDDEN).entity("kadmin principal required.\n").build();
+        }
         if (httpRequest.isSecure()) {
             WebServer.LOG.info("Request to get principals.");
             String msg;
@@ -196,6 +205,9 @@ public class KadminApi {
                                  final PrincipalParam principal,
                                  @QueryParam(PasswordParam.NAME) @DefaultValue(PasswordParam.DEFAULT)
                                  final PasswordParam password) {
+        if (!isAdminPrincipal()) {
+            return Response.status(Response.Status.FORBIDDEN).entity("kadmin principal required.\n").build();
+        }
         if (httpRequest.isSecure()) {
             WebServer.LOG.info("Request to add the principal named " + principal.getValue());
             String msg;
@@ -244,6 +256,9 @@ public class KadminApi {
     @Produces(MediaType.TEXT_PLAIN)
     public Response renamePrincipal(@QueryParam("oldprincipal") String oldPrincipal,
                                     @QueryParam("newprincipal") String newPrincipal) {
+        if (!isAdminPrincipal()) {
+            return Response.status(Response.Status.FORBIDDEN).entity("kadmin principal required.\n").build();
+        }
         if (httpRequest.isSecure()) {
             WebServer.LOG.info("Request to rename " + oldPrincipal + " to " + newPrincipal);
             String msg;
@@ -289,6 +304,9 @@ public class KadminApi {
     @Produces(MediaType.TEXT_PLAIN)
     public Response deletePrincipal(@QueryParam(PrincipalParam.NAME) @DefaultValue(PrincipalParam.DEFAULT)
                                     final PrincipalParam principal) {
+        if (!isAdminPrincipal()) {
+            return Response.status(Response.Status.FORBIDDEN).entity("kadmin principal required.\n").build();
+        }
         if (httpRequest.isSecure()) {
             WebServer.LOG.info("Request to delete the principal named " + principal.getValue());
             String msg;
@@ -331,6 +349,9 @@ public class KadminApi {
                                    final PrincipalParam principal,
                                    @QueryParam(PasswordParam.NAME) @DefaultValue(PasswordParam.DEFAULT)
                                    final PasswordParam newPassword) {
+        if (!isAdminPrincipal()) {
+            return Response.status(Response.Status.FORBIDDEN).entity("kadmin principal required.\n").build();
+        }
         if (httpRequest.isSecure()) {
             WebServer.LOG.info("Request to add the principal named " + principal.getValue());
             String msg;
@@ -380,6 +401,9 @@ public class KadminApi {
     @Produces(MediaType.APPLICATION_JSON)
     public Response getPrincipal(@QueryParam(PrincipalParam.NAME) @DefaultValue(PrincipalParam.DEFAULT)
                                  final PrincipalParam principal) {
+        if (!isAdminPrincipal()) {
+            return Response.status(Response.Status.FORBIDDEN).entity("kadmin principal required.\n").build();
+        }
         if (httpRequest.isSecure()) {
             WebServer.LOG.info("Request to get a principal named " + principal.getValue());
             String msg;
@@ -422,5 +446,32 @@ public class KadminApi {
         }
         return Response.status(Response.Status.FORBIDDEN).entity("HTTPS required.\n").build();
     }
+
+    private boolean isAdminPrincipal() {
+        HasServer hasServer = WebServer.getHasServerFromContext(context);
+        String serverFilterAuthType = hasServer.getWebServer().getConf().getFilterAuthType();
+        if (!serverFilterAuthType.equals("kerberos")) {
+            // When filter_auth_type is not kerberos, there is no need to check the admin principal
+            return true;
+        }
+        Principal requestPrincipal = httpRequest.getUserPrincipal();
+        if (requestPrincipal == null) {
+            WebServer.LOG.warn("Request principal is null.");
+            return false;
+        }
+        if (requestPrincipal instanceof AuthenticationToken) {
+            KdcSetting serverSetting = hasServer.getKdcServer().getKdcSetting();
+            String adminPrincipal = KrbUtil.makeKadminPrincipal(serverSetting.getKdcRealm()).getName();
+            boolean check = adminPrincipal.equals(requestPrincipal.getName());
+            if (!check) {
+                WebServer.LOG.warn("Client tries to pass the authentication using principal "
+                        + requestPrincipal.getName());
+            }
+            return check;
+        } else {
+            WebServer.LOG.warn("Abnormal authentication token " + requestPrincipal.getClass().getCanonicalName());
+            return false;
+        }
+    }
 }
 
diff --git a/kerby-dist/has-dist/conf/admin.conf b/kerby-dist/has-dist/conf/admin.conf
index 5e30899..3ae7289 100644
--- a/kerby-dist/has-dist/conf/admin.conf
+++ b/kerby-dist/has-dist/conf/admin.conf
@@ -19,5 +19,5 @@
     https_host = plusplus-desktop
     https_port = 8092
     admin_keytab = /etc/has/admin.keytab
-    admin_keytab_principal = kadmin/HADOOP.COM@HADOOP.COM
     filter_auth_type = kerberos
+    realm = HADOOP.COM
diff --git a/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/admin/remote/AdminRemoteTool.java b/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/admin/remote/AdminRemoteTool.java
index 544cec7..96e38ee 100644
--- a/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/admin/remote/AdminRemoteTool.java
+++ b/kerby-tool/has-tool/src/main/java/org/apache/kerby/kerberos/tool/admin/remote/AdminRemoteTool.java
@@ -21,6 +21,7 @@ package org.apache.kerby.kerberos.tool.admin.remote;
 
 import org.apache.kerby.has.client.HasAuthAdminClient;
 import org.apache.kerby.has.common.HasConfig;
+import org.apache.kerby.has.common.HasConfigKey;
 import org.apache.kerby.has.common.HasException;
 import org.apache.kerby.has.common.util.HasUtil;
 import org.apache.kerby.kerberos.kerb.KrbException;
@@ -110,6 +111,8 @@ public class AdminRemoteTool {
 
         if (hasConfig.getFilterAuthType().equals("kerberos")) {
             authHasAdminClient = new HasAuthAdminClient(hasConfig);
+            String adminPrincipal = authHasAdminClient.getKadminPrincipal();
+            hasConfig.setString(HasConfigKey.ADMIN_KEYTAB_PRINCIPAL, adminPrincipal);
         }
 
         System.out.println("enter \"cmd\" to see legal commands.");