You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ozone.apache.org by sa...@apache.org on 2023/04/21 08:44:20 UTC
[ozone] branch master updated: HDDS-8455. Om supports read only administrators. (#4565)
This is an automated email from the ASF dual-hosted git repository.
sammichen 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 e7cd92c467 HDDS-8455. Om supports read only administrators. (#4565)
e7cd92c467 is described below
commit e7cd92c4671fa4e49ea9c2bb816744c2b3fd61ea
Author: z-bb <35...@users.noreply.github.com>
AuthorDate: Fri Apr 21 16:44:13 2023 +0800
HDDS-8455. Om supports read only administrators. (#4565)
---
.../org/apache/hadoop/ozone/OzoneConfigKeys.java | 10 ++-
.../common/src/main/resources/ozone-default.xml | 18 +++++
.../apache/hadoop/ozone/om/OmMetadataReader.java | 17 ++++-
.../apache/hadoop/ozone/om/OzoneConfigUtil.java | 16 +++++
.../org/apache/hadoop/ozone/om/OzoneManager.java | 7 ++
.../ozone/security/acl/OzoneNativeAuthorizer.java | 28 ++++++--
.../security/acl/TestOzoneAdministrators.java | 80 ++++++++++++++++++++++
7 files changed, 164 insertions(+), 12 deletions(-)
diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneConfigKeys.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneConfigKeys.java
index ede1b4fd87..e4e4d4e85d 100644
--- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneConfigKeys.java
+++ b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneConfigKeys.java
@@ -179,9 +179,15 @@ public final class OzoneConfigKeys {
"ozone.administrators.groups";
public static final String OZONE_S3_ADMINISTRATORS =
- "ozone.s3.administrators";
+ "ozone.s3.administrators";
public static final String OZONE_S3_ADMINISTRATORS_GROUPS =
- "ozone.s3.administrators.groups";
+ "ozone.s3.administrators.groups";
+
+ public static final String OZONE_READONLY_ADMINISTRATORS =
+ "ozone.readonly.administrators";
+ public static final String OZONE_READONLY_ADMINISTRATORS_GROUPS =
+ "ozone.readonly.administrators.groups";
+
/**
* Used only for testing purpose. Results in making every user an admin.
* */
diff --git a/hadoop-hdds/common/src/main/resources/ozone-default.xml b/hadoop-hdds/common/src/main/resources/ozone-default.xml
index 1879ac4f6c..c5186258e3 100644
--- a/hadoop-hdds/common/src/main/resources/ozone-default.xml
+++ b/hadoop-hdds/common/src/main/resources/ozone-default.xml
@@ -1635,6 +1635,24 @@
</description>
</property>
+ <property>
+ <name>ozone.readonly.administrators</name>
+ <value/>
+ <description>
+ Ozone read only admin users delimited by the comma.
+ If set, This is the list of users are allowed to read operations skip checkAccess.
+ </description>
+ </property>
+
+ <property>
+ <name>ozone.readonly.administrators.groups</name>
+ <value/>
+ <description>
+ Ozone read only admin groups delimited by the comma.
+ If set, This is the list of groups are allowed to read operations skip checkAccess.
+ </description>
+ </property>
+
<property>
<name>ozone.s3g.volume.name</name>
<value>s3v</value>
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OmMetadataReader.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OmMetadataReader.java
index 0d25596f9a..5818b64da2 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OmMetadataReader.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OmMetadataReader.java
@@ -44,6 +44,7 @@ import org.apache.hadoop.util.ReflectionUtils;
import org.apache.hadoop.util.Time;
import org.slf4j.Logger;
import java.net.InetAddress;
+import java.util.Collection;
import java.util.List;
import java.util.Map;
@@ -114,8 +115,8 @@ public class OmMetadataReader implements IOmMetadataReader, Auditor {
authorizer.setBucketManager(bucketManager);
authorizer.setKeyManager(keyManager);
authorizer.setPrefixManager(prefixManager);
- authorizer.setOzoneAdmins(
- new OzoneAdmins(ozoneManager.getOmAdminUsernames()));
+ authorizer.setOzoneAdmins(ozoneManager.getOmAdmins());
+ authorizer.setOzoneReadOnlyAdmins(getOmReadOnlyAdmins(configuration));
authorizer.setAllowListAllVolumes(allowListAllVolumes);
} else {
isNativeAuthorizerEnabled = false;
@@ -580,5 +581,15 @@ public class OmMetadataReader implements IOmMetadataReader, Auditor {
return ResourceType.KEY;
}
-
+ private OzoneAdmins getOmReadOnlyAdmins(OzoneConfiguration configuration) {
+ // Get read only admin list
+ Collection<String> omReadOnlyAdmins =
+ OzoneConfigUtil.getOzoneReadOnlyAdminsFromConfig(
+ configuration);
+ Collection<String> omReadOnlyAdminsGroups =
+ OzoneConfigUtil.getOzoneReadOnlyAdminsGroupsFromConfig(
+ configuration);
+ return new OzoneAdmins(omReadOnlyAdmins,
+ omReadOnlyAdminsGroups);
+ }
}
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneConfigUtil.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneConfigUtil.java
index 7a54a9e211..fcb74ae6b9 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneConfigUtil.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneConfigUtil.java
@@ -33,6 +33,8 @@ import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ADMINISTRATORS;
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ADMINISTRATORS_GROUPS;
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_S3_ADMINISTRATORS;
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_S3_ADMINISTRATORS_GROUPS;
+import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_READONLY_ADMINISTRATORS;
+import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_READONLY_ADMINISTRATORS_GROUPS;
/**
* Utility class for ozone configurations.
@@ -77,6 +79,14 @@ public final class OzoneConfigUtil {
return ozAdmins;
}
+ /**
+ * Return list of Ozone Read only admin Usernames from config.
+ */
+ static Collection<String> getOzoneReadOnlyAdminsFromConfig(
+ OzoneConfiguration conf) {
+ return conf.getTrimmedStringCollection(OZONE_READONLY_ADMINISTRATORS);
+ }
+
static Collection<String> getOzoneAdminsGroupsFromConfig(
OzoneConfiguration conf) {
return conf.getTrimmedStringCollection(OZONE_ADMINISTRATORS_GROUPS);
@@ -94,6 +104,12 @@ public final class OzoneConfigUtil {
return s3AdminsGroup;
}
+ static Collection<String> getOzoneReadOnlyAdminsGroupsFromConfig(
+ OzoneConfiguration conf) {
+ return conf.getTrimmedStringCollection(
+ OZONE_READONLY_ADMINISTRATORS_GROUPS);
+ }
+
public static ReplicationConfig resolveReplicationConfigPreference(
HddsProtos.ReplicationType clientType,
HddsProtos.ReplicationFactor clientFactor,
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 7f63862805..bc4162177f 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
@@ -4034,6 +4034,13 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl
return omAdmins.getAdminGroups();
}
+ /**
+ * Return OzoneAdmins.
+ */
+ public OzoneAdmins getOmAdmins() {
+ return omAdmins;
+ }
+
/**
* Return true if a UserGroupInformation is OM admin, false otherwise.
* @param callerUgi Caller UserGroupInformation
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/security/acl/OzoneNativeAuthorizer.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/security/acl/OzoneNativeAuthorizer.java
index f60f7be1fe..d7079fa952 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/security/acl/OzoneNativeAuthorizer.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/security/acl/OzoneNativeAuthorizer.java
@@ -34,8 +34,6 @@ import org.slf4j.LoggerFactory;
import java.util.Objects;
import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.INVALID_REQUEST;
-import static org.apache.hadoop.ozone.security.acl.OzoneObj.ResourceType.BUCKET;
-import static org.apache.hadoop.ozone.security.acl.OzoneObj.ResourceType.VOLUME;
/**
* Public API for Ozone ACLs. Security providers providing support for Ozone
@@ -52,6 +50,7 @@ public class OzoneNativeAuthorizer implements IAccessAuthorizer {
private KeyManager keyManager;
private PrefixManager prefixManager;
private OzoneAdmins ozAdmins;
+ private OzoneAdmins ozReadOnlyAdmins;
private boolean allowListAllVolumes;
public OzoneNativeAuthorizer() {
@@ -92,11 +91,21 @@ public class OzoneNativeAuthorizer implements IAccessAuthorizer {
}
// bypass all checks for admin
- boolean isAdmin = isAdmin(context.getClientUgi());
+ boolean isAdmin = isAdmin(ozAdmins, context.getClientUgi());
if (isAdmin) {
return true;
}
+ // bypass read checks for read only admin users
+ boolean isReadOnlyAdmin = isAdmin(ozReadOnlyAdmins,
+ context.getClientUgi());
+ if (isReadOnlyAdmin
+ && (context.getAclRights() == ACLType.READ
+ || context.getAclRights() == ACLType.READ_ACL
+ || context.getAclRights() == ACLType.LIST)) {
+ return true;
+ }
+
boolean isOwner = isOwner(context.getClientUgi(), context.getOwnerName());
boolean isListAllVolume = ((context.getAclRights() == ACLType.LIST) &&
objInfo.getVolumeName().equals(OzoneConsts.OZONE_ROOT));
@@ -106,7 +115,7 @@ public class OzoneNativeAuthorizer implements IAccessAuthorizer {
ACLType parentAclRight = OzoneAclUtils.getParentNativeAcl(
context.getAclRights(), objInfo.getResourceType());
-
+
parentContext = RequestContext.newBuilder()
.setClientUgi(context.getClientUgi())
.setIp(context.getIp())
@@ -195,6 +204,10 @@ public class OzoneNativeAuthorizer implements IAccessAuthorizer {
this.ozAdmins = ozoneAdmins;
}
+ public void setOzoneReadOnlyAdmins(OzoneAdmins ozoneReadOnlyAdmins) {
+ this.ozReadOnlyAdmins = ozoneReadOnlyAdmins;
+ }
+
public OzoneAdmins getOzoneAdmins() {
return ozAdmins;
}
@@ -217,13 +230,14 @@ public class OzoneNativeAuthorizer implements IAccessAuthorizer {
return false;
}
- private boolean isAdmin(UserGroupInformation callerUgi) {
+ private boolean isAdmin(OzoneAdmins pOzAdmins,
+ UserGroupInformation callerUgi) {
Preconditions.checkNotNull(callerUgi, "callerUgi should not be null!");
- if (ozAdmins == null) {
+ if (pOzAdmins == null) {
return false;
}
- return ozAdmins.isAdmin(callerUgi);
+ return pOzAdmins.isAdmin(callerUgi);
}
}
diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/security/acl/TestOzoneAdministrators.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/security/acl/TestOzoneAdministrators.java
index 896415b86b..68fb289c22 100644
--- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/security/acl/TestOzoneAdministrators.java
+++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/security/acl/TestOzoneAdministrators.java
@@ -57,6 +57,48 @@ public class TestOzoneAdministrators {
}
}
+ @Test
+ public void testBucketOperation() throws OMException {
+ UserGroupInformation.createUserForTesting("testuser",
+ new String[]{"testgroup"});
+ try {
+ OzoneObj obj = getTestBucketobj("testbucket");
+ RequestContext context = getUserRequestContext("testuser",
+ IAccessAuthorizer.ACLType.LIST);
+ nativeAuthorizer.setOzoneReadOnlyAdmins(new OzoneAdmins(
+ Collections.singletonList("testuser"), null));
+ Assert.assertTrue("matching read only admins are allowed to preform" +
+ "read operations", nativeAuthorizer.checkAccess(obj, context));
+
+ context = getUserRequestContext("testuser",
+ IAccessAuthorizer.ACLType.READ);
+ Assert.assertTrue("matching read only admins are allowed to preform" +
+ "read operations", nativeAuthorizer.checkAccess(obj, context));
+
+ context = getUserRequestContext("testuser",
+ IAccessAuthorizer.ACLType.READ_ACL);
+ Assert.assertTrue("matching read only admins are allowed to preform" +
+ "read operations", nativeAuthorizer.checkAccess(obj, context));
+
+ context = getUserRequestContext("testuser",
+ IAccessAuthorizer.ACLType.WRITE);
+ RequestContext finalContext = context;
+ // ACLType is WRITE
+ // execute volumeManager.checkAccess volumeManager is null
+ Assert.assertThrows(NullPointerException.class,
+ () -> nativeAuthorizer.checkAccess(obj, finalContext));
+
+ nativeAuthorizer.setOzoneReadOnlyAdmins(new OzoneAdmins(
+ null, Collections.singletonList("testgroup")));
+ context = getUserRequestContext("testuser",
+ IAccessAuthorizer.ACLType.READ_ACL);
+ Assert.assertTrue("matching read only admins are allowed to preform" +
+ "read operations", nativeAuthorizer.checkAccess(obj, context));
+ } finally {
+ UserGroupInformation.reset();
+ }
+ }
+
@Test
public void testListAllVolume() throws Exception {
UserGroupInformation.createUserForTesting("testuser",
@@ -97,6 +139,21 @@ public class TestOzoneAdministrators {
asList(new String[]{"testuser2", "testuser3"})));
Assert.assertFalse("mismatching admins are not allowed perform " +
"admin operations", nativeAuthorizer.checkAccess(obj, context));
+
+ nativeAuthorizer.setOzoneReadOnlyAdmins(new OzoneAdmins(
+ Collections.singletonList("testuser"), null));
+ if (context.getAclRights() == IAccessAuthorizer.ACLType.LIST) {
+ Assert.assertTrue("matching read only user are allowed to preform" +
+ "read operations", nativeAuthorizer.checkAccess(obj, context));
+ } else if (context.getAclRights() == IAccessAuthorizer.ACLType.CREATE) {
+ Assert.assertFalse("mismatching read only user are allowed to preform" +
+ "read operations", nativeAuthorizer.checkAccess(obj, context));
+ }
+
+ nativeAuthorizer.setOzoneReadOnlyAdmins(new OzoneAdmins(
+ Collections.singletonList("testuser1"), null));
+ Assert.assertFalse("mismatching read only user are allowed to preform" +
+ "read operations", nativeAuthorizer.checkAccess(obj, context));
}
private void testGroupAdminOperations(OzoneObj obj, RequestContext context)
@@ -112,6 +169,22 @@ public class TestOzoneAdministrators {
Assert.assertFalse("Users from mismatching admin groups " +
"are allowed to perform admin operations",
nativeAuthorizer.checkAccess(obj, context));
+
+ nativeAuthorizer.setOzoneReadOnlyAdmins(new OzoneAdmins(
+ null, Collections.singletonList("testgroup")));
+ if (context.getAclRights() == IAccessAuthorizer.ACLType.LIST) {
+ Assert.assertTrue("matching read only groups are allowed to preform" +
+ "read operations", nativeAuthorizer.checkAccess(obj, context));
+ } else if (context.getAclRights() == IAccessAuthorizer.ACLType.CREATE) {
+ Assert.assertFalse("mismatching read only groups are allowed to " +
+ "preform read operations",
+ nativeAuthorizer.checkAccess(obj, context));
+ }
+
+ nativeAuthorizer.setOzoneReadOnlyAdmins(new OzoneAdmins(
+ null, Collections.singletonList("testgroup1")));
+ Assert.assertFalse("mismatching read only groups are allowed to preform" +
+ "read operations", nativeAuthorizer.checkAccess(obj, context));
}
private RequestContext getUserRequestContext(String username,
@@ -129,4 +202,11 @@ public class TestOzoneAdministrators {
.setStoreType(OzoneObj.StoreType.OZONE)
.setVolumeName(volumename).build();
}
+
+ private OzoneObj getTestBucketobj(String bucketname) {
+ return OzoneObjInfo.Builder.newBuilder()
+ .setResType(OzoneObj.ResourceType.BUCKET)
+ .setStoreType(OzoneObj.StoreType.OZONE)
+ .setVolumeName(bucketname).build();
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@ozone.apache.org
For additional commands, e-mail: commits-help@ozone.apache.org