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