You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ozone.apache.org by el...@apache.org on 2021/01/30 07:43:53 UTC

[ozone] branch master updated: HDDS-4704. Add permission check in OMDBCheckpointServlet (#1801)

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

elek pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/master by this push:
     new d964cc9  HDDS-4704. Add permission check in OMDBCheckpointServlet (#1801)
d964cc9 is described below

commit d964cc98adeaa42d6e6ac34f4fcc591171ee7ff3
Author: Siyao Meng <50...@users.noreply.github.com>
AuthorDate: Fri Jan 29 23:43:37 2021 -0800

    HDDS-4704. Add permission check in OMDBCheckpointServlet (#1801)
---
 .../src/main/compose/ozonesecure/docker-config     |  2 +-
 .../dist/src/main/smoketest/spnego/web.robot       | 10 ++--
 .../hadoop/ozone/om/TestOMDbCheckpointServlet.java | 10 +++-
 .../hadoop/ozone/om/OMDBCheckpointServlet.java     | 60 ++++++++++++++++++++++
 .../org/apache/hadoop/ozone/om/OzoneManager.java   |  2 +-
 5 files changed, 76 insertions(+), 8 deletions(-)

diff --git a/hadoop-ozone/dist/src/main/compose/ozonesecure/docker-config b/hadoop-ozone/dist/src/main/compose/ozonesecure/docker-config
index f005131..ec94dfb 100644
--- a/hadoop-ozone/dist/src/main/compose/ozonesecure/docker-config
+++ b/hadoop-ozone/dist/src/main/compose/ozonesecure/docker-config
@@ -40,7 +40,7 @@ OZONE-SITE.XML_ozone.recon.address=recon:9891
 OZONE-SITE.XML_ozone.security.enabled=true
 OZONE-SITE.XML_ozone.acl.enabled=true
 OZONE-SITE.XML_ozone.acl.authorizer.class=org.apache.hadoop.ozone.security.acl.OzoneNativeAuthorizer
-OZONE-SITE.XML_ozone.administrators="testuser/scm@EXAMPLE.COM,testuser/s3g@EXAMPLE.COM"
+OZONE-SITE.XML_ozone.administrators="testuser/scm@EXAMPLE.COM,testuser/s3g@EXAMPLE.COM,recon/recon@EXAMPLE.COM"
 
 OZONE-SITE.XML_hdds.datanode.dir=/data/hdds
 HDFS-SITE.XML_dfs.datanode.address=0.0.0.0:1019
diff --git a/hadoop-ozone/dist/src/main/smoketest/spnego/web.robot b/hadoop-ozone/dist/src/main/smoketest/spnego/web.robot
index 0c105fe..e8bd525 100644
--- a/hadoop-ozone/dist/src/main/smoketest/spnego/web.robot
+++ b/hadoop-ozone/dist/src/main/smoketest/spnego/web.robot
@@ -23,12 +23,12 @@ Resource            ../commonlib.robot
 Test Timeout        5 minutes
 
 *** Variables ***
-${OM_URL}       http://om:9874
-${OM_DB_CHECKPOINT_URL}       http://om:9874/dbCheckpoint
-${OM_SERVICE_LIST_URL}       http://om:9874/serviceList
+${OM_URL}           http://om:9874
+${OM_DB_CHECKPOINT_URL}      ${OM_URL}/dbCheckpoint
+${OM_SERVICE_LIST_URL}       ${OM_URL}/serviceList
 
-${SCM_URL}       http://scm:9876
-${RECON_URL}       http://recon:9888
+${SCM_URL}          http://scm:9876
+${RECON_URL}        http://recon:9888
 
 ${SCM_CONF_URL}     http://scm:9876/conf
 ${SCM_JMX_URL}      http://scm:9876/jmx
diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMDbCheckpointServlet.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMDbCheckpointServlet.java
index 15fd9aa..2c66885 100644
--- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMDbCheckpointServlet.java
+++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMDbCheckpointServlet.java
@@ -41,9 +41,13 @@ import org.apache.hadoop.ozone.OzoneConsts;
 
 import org.apache.commons.io.FileUtils;
 import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ACL_ENABLED;
+import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ADMINISTRATORS;
+import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ADMINISTRATORS_WILDCARD;
 import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_OPEN_KEY_EXPIRE_THRESHOLD_SECONDS;
 import static org.apache.hadoop.ozone.OzoneConsts.OZONE_DB_CHECKPOINT_REQUEST_FLUSH;
 import static org.apache.hadoop.ozone.om.OMDBCheckpointServlet.writeOmDBCheckpointToStream;
+
+import org.apache.hadoop.security.UserGroupInformation;
 import org.junit.After;
 import org.junit.Assert;
 import static org.junit.Assert.assertNotNull;
@@ -87,7 +91,8 @@ public class TestOMDbCheckpointServlet {
     clusterId = UUID.randomUUID().toString();
     scmId = UUID.randomUUID().toString();
     omId = UUID.randomUUID().toString();
-    conf.setBoolean(OZONE_ACL_ENABLED, true);
+    conf.setBoolean(OZONE_ACL_ENABLED, false);
+    conf.set(OZONE_ADMINISTRATORS, OZONE_ADMINISTRATORS_WILDCARD);
     conf.setInt(OZONE_OPEN_KEY_EXPIRE_THRESHOLD_SECONDS, 2);
     cluster = MiniOzoneCluster.newBuilder(conf)
         .setClusterId(clusterId)
@@ -119,6 +124,9 @@ public class TestOMDbCheckpointServlet {
       doCallRealMethod().when(omDbCheckpointServletMock).init();
 
       HttpServletRequest requestMock = mock(HttpServletRequest.class);
+      // Return current user short name when asked
+      when(requestMock.getRemoteUser())
+          .thenReturn(UserGroupInformation.getCurrentUser().getShortUserName());
       HttpServletResponse responseMock = mock(HttpServletResponse.class);
 
       ServletContext servletContextMock = mock(ServletContext.class);
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMDBCheckpointServlet.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMDBCheckpointServlet.java
index 25e2755..dcb5392 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMDBCheckpointServlet.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMDBCheckpointServlet.java
@@ -30,6 +30,7 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import java.time.Duration;
 import java.time.Instant;
+import java.util.Collection;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
@@ -47,12 +48,25 @@ import org.apache.commons.compress.compressors.CompressorOutputStream;
 import org.apache.commons.compress.compressors.CompressorStreamFactory;
 import org.apache.commons.compress.utils.IOUtils;
 import org.apache.commons.lang3.StringUtils;
+
+import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ADMINISTRATORS_WILDCARD;
 import static org.apache.hadoop.ozone.OzoneConsts.OZONE_DB_CHECKPOINT_REQUEST_FLUSH;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
  * Provides the current checkpoint Snapshot of the OM DB. (tar.gz)
+ *
+ * When Ozone ACL is enabled (`ozone.acl.enabled`=`true`), only users/principals
+ * configured in `ozone.administrator` (along with the user that starts OM,
+ * which automatically becomes an Ozone administrator but not necessarily in
+ * the config) are allowed to access this endpoint.
+ *
+ * If Kerberos is enabled, the principal should be appended to
+ * `ozone.administrator`, e.g. `scm/scm@EXAMPLE.COM`
+ * If Kerberos is not enabled, simply append the login user name to
+ * `ozone.administrator`, e.g. `scm`
  */
 public class OMDBCheckpointServlet extends HttpServlet {
 
@@ -89,6 +103,25 @@ public class OMDBCheckpointServlet extends HttpServlet {
     }
   }
 
+  private boolean hasPermission(String username) {
+    // Check ACL for dbCheckpoint only when global Ozone ACL is enabled
+    if (om.getAclsEnabled()) {
+      // Only Ozone admins are allowed
+      try {
+        Collection<String> admins = om.getOzoneAdmins(om.getConfiguration());
+        if (admins.contains(OZONE_ADMINISTRATORS_WILDCARD) ||
+            admins.contains(username)) {
+          return true;
+        }
+      } catch (IOException e) {
+        LOG.warn("Error checking permission: {}", e.getMessage());
+      }
+      return false;
+    } else {
+      return true;
+    }
+  }
+
   /**
    * Process a GET request for the Ozone Manager DB checkpoint snapshot.
    *
@@ -106,6 +139,33 @@ public class OMDBCheckpointServlet extends HttpServlet {
       return;
     }
 
+    // Check ACL for dbCheckpoint only when global Ozone ACL is enable
+    if (om.getAclsEnabled()) {
+      final java.security.Principal userPrincipal = request.getUserPrincipal();
+      if (userPrincipal == null) {
+        final String remoteUser = request.getRemoteUser();
+        LOG.error("Permission denied: Unauthorized access to /dbCheckpoint,"
+            + " no user principal found. Current login user is {}.",
+            remoteUser != null ? "'" + remoteUser + "'" : "UNKNOWN");
+        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
+        return;
+      } else {
+        final String userPrincipalName = userPrincipal.getName();
+        if (!hasPermission(userPrincipalName)) {
+          LOG.error("Permission denied: User principal '{}' does not have"
+              + " access to /dbCheckpoint.\nThis can happen when Ozone Manager"
+              + " is started with a different user.\nPlease append '{}' to OM"
+              + " 'ozone.administrators' config and restart OM to grant current"
+              + " user access to this endpoint.",
+              userPrincipalName, userPrincipalName);
+          response.setStatus(HttpServletResponse.SC_FORBIDDEN);
+          return;
+        }
+        LOG.debug("Granted user principal '{}' access to /dbCheckpoint.",
+            userPrincipalName);
+      }
+    }
+
     DBCheckpoint checkpoint = null;
     try {
 
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java
index 9509c49..9158faf 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java
@@ -3542,7 +3542,7 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl
   /**
    * Return list of OzoneAdministrators.
    */
-  private Collection<String> getOzoneAdmins(OzoneConfiguration conf)
+  Collection<String> getOzoneAdmins(OzoneConfiguration conf)
       throws IOException {
     Collection<String> ozAdmins =
         conf.getTrimmedStringCollection(OZONE_ADMINISTRATORS);


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@ozone.apache.org
For additional commands, e-mail: commits-help@ozone.apache.org