Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -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/[email protected],testuser/[email protected]"
OZONE-SITE.XML_ozone.administrators="testuser/[email protected],testuser/[email protected],recon/[email protected]"

OZONE-SITE.XML_hdds.datanode.dir=/data/hdds
HDFS-SITE.XML_dfs.datanode.address=0.0.0.0:1019
Expand Down
10 changes: 5 additions & 5 deletions hadoop-ozone/dist/src/main/smoketest/spnego/web.robot
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,13 @@

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;
Expand Down Expand Up @@ -87,7 +91,8 @@ public void init() throws Exception {
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)
Expand Down Expand Up @@ -119,6 +124,9 @@ public void testDoGet() throws ServletException, IOException {
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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
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;

Expand All @@ -47,12 +48,25 @@
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/[email protected]`
* If Kerberos is not enabled, simply append the login user name to
* `ozone.administrator`, e.g. `scm`
*/
public class OMDBCheckpointServlet extends HttpServlet {

Expand Down Expand Up @@ -89,6 +103,25 @@ public void init() throws ServletException {
}
}

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.
*
Expand All @@ -106,6 +139,33 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) {
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 {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3542,7 +3542,7 @@ public OzoneDelegationTokenSecretManager getDelegationTokenMgr() {
/**
* Return list of OzoneAdministrators.
*/
private Collection<String> getOzoneAdmins(OzoneConfiguration conf)
Collection<String> getOzoneAdmins(OzoneConfiguration conf)
throws IOException {
Collection<String> ozAdmins =
conf.getTrimmedStringCollection(OZONE_ADMINISTRATORS);
Expand Down