This is an automated email from the ASF dual-hosted git repository.
adoroszlai 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 2162402223d HDDS-13435. Add an OzoneManagerAuthorizer interface (#8840)
2162402223d is described below
commit 2162402223d5b29174ef91f3a0097d5c9d107735
Author: Tsz-Wo Nicholas Sze <[email protected]>
AuthorDate: Tue Jul 22 10:05:52 2025 -0700
HDDS-13435. Add an OzoneManagerAuthorizer interface (#8840)
---
.../ozone/security/acl/OzoneAuthorizerFactory.java | 44 ++++++----------
.../ozone/security/acl/OzoneManagerAuthorizer.java | 30 +++++++++++
.../ozone/security/acl/OzoneNativeAuthorizer.java | 44 ++++++----------
.../security/acl/TestOzoneAdministrators.java | 58 ++++++++++++----------
4 files changed, 93 insertions(+), 83 deletions(-)
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/security/acl/OzoneAuthorizerFactory.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/security/acl/OzoneAuthorizerFactory.java
index 254df7506ea..0a45cd789a2 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/security/acl/OzoneAuthorizerFactory.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/security/acl/OzoneAuthorizerFactory.java
@@ -28,11 +28,14 @@
import org.apache.hadoop.ozone.om.OmSnapshot;
import org.apache.hadoop.ozone.om.OzoneManager;
import org.apache.hadoop.ozone.om.PrefixManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Creates {@link IAccessAuthorizer} instances based on configuration.
*/
public final class OzoneAuthorizerFactory {
+ static final Logger LOG =
LoggerFactory.getLogger(OzoneAuthorizerFactory.class);
private OzoneAuthorizerFactory() {
// no instances
@@ -42,7 +45,7 @@ private OzoneAuthorizerFactory() {
* @return authorizer instance for {@link OzoneManager}
*/
public static IAccessAuthorizer forOM(OzoneManager om) {
- return create(om, om.getKeyManager(), om.getPrefixManager());
+ return create(om, om.getKeyManager(), om.getPrefixManager(), "OM");
}
/**
@@ -53,7 +56,7 @@ public static IAccessAuthorizer forSnapshot(
OzoneManager om, KeyManager keyManager, PrefixManager prefixManager
) {
return om.getAccessAuthorizer().isNative()
- ? create(om, keyManager, prefixManager)
+ ? create(om, keyManager, prefixManager, "Snapshot")
: om.getAccessAuthorizer();
}
@@ -61,9 +64,13 @@ public static IAccessAuthorizer forSnapshot(
* Creates new instance (except for {@link OzoneAccessAuthorizer},
* which is a no-op authorizer.
*/
- private static IAccessAuthorizer create(
- OzoneManager om, KeyManager km, PrefixManager pm
- ) {
+ private static IAccessAuthorizer create(OzoneManager om, KeyManager km,
PrefixManager pm, String name) {
+ final IAccessAuthorizer authorizer = createImpl(om, km, pm);
+ LOG.info("{}: Authorizer for {} is {}", om.getOMNodeId(), name,
authorizer.getClass());
+ return authorizer;
+ }
+
+ private static IAccessAuthorizer createImpl(OzoneManager om, KeyManager km,
PrefixManager pm) {
if (!om.getAclsEnabled()) {
return OzoneAccessAuthorizer.get();
}
@@ -76,14 +83,13 @@ private static IAccessAuthorizer create(
}
if (OzoneNativeAuthorizer.class == clazz) {
- final OzoneNativeAuthorizer authorizer = new OzoneNativeAuthorizer();
- return configure(authorizer, om, km, pm);
+ return new OzoneNativeAuthorizer().configure(om, km, pm);
}
final IAccessAuthorizer authorizer = newInstance(clazz, conf);
- if (authorizer instanceof OzoneNativeAuthorizer) {
- return configure((OzoneNativeAuthorizer) authorizer, om, km, pm);
+ if (authorizer instanceof OzoneManagerAuthorizer) {
+ return ((OzoneManagerAuthorizer) authorizer).configure(om, km, pm);
}
// If authorizer isn't native and shareable tmp dir is enabled,
@@ -91,31 +97,13 @@ private static IAccessAuthorizer create(
if (conf.getBoolean(OZONE_OM_ENABLE_OFS_SHARED_TMP_DIR,
OZONE_OM_ENABLE_OFS_SHARED_TMP_DIR_DEFAULT)) {
return new SharedTmpDirAuthorizer(
- configure(new OzoneNativeAuthorizer(), om, km, pm),
+ new OzoneNativeAuthorizer().configure(om, km, pm),
authorizer);
}
return authorizer;
}
- /**
- * Configure {@link OzoneNativeAuthorizer}.
- * @return same instance for convenience
- */
- private static OzoneNativeAuthorizer configure(
- OzoneNativeAuthorizer authorizer,
- OzoneManager om, KeyManager km, PrefixManager pm
- ) {
- authorizer.setVolumeManager(om.getVolumeManager());
- authorizer.setBucketManager(om.getBucketManager());
- authorizer.setKeyManager(km);
- authorizer.setPrefixManager(pm);
- authorizer.setAdminCheck(om::isAdmin);
- authorizer.setReadOnlyAdminCheck(om::isReadOnlyAdmin);
- authorizer.setAllowListAllVolumes(om::getAllowListAllVolumes);
- return authorizer;
- }
-
private static Class<? extends IAccessAuthorizer> authorizerClass(
ConfigurationSource conf) {
return conf.getClass(OZONE_ACL_AUTHORIZER_CLASS,
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/security/acl/OzoneManagerAuthorizer.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/security/acl/OzoneManagerAuthorizer.java
new file mode 100644
index 00000000000..2fe8767bf09
--- /dev/null
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/security/acl/OzoneManagerAuthorizer.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.ozone.security.acl;
+
+import org.apache.hadoop.ozone.om.KeyManager;
+import org.apache.hadoop.ozone.om.OzoneManager;
+import org.apache.hadoop.ozone.om.PrefixManager;
+
+/**
+ * A subinterface of {@link IAccessAuthorizer} specifically for Ozone Manager.
+ */
+public interface OzoneManagerAuthorizer extends IAccessAuthorizer {
+ /** Configure this authorizer. */
+ OzoneManagerAuthorizer configure(OzoneManager om, KeyManager km,
PrefixManager pm);
+}
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 84fe15f58e2..48277025ba3 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
@@ -19,7 +19,6 @@
import static
org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.INVALID_REQUEST;
-import com.google.common.annotations.VisibleForTesting;
import java.util.Objects;
import java.util.function.BooleanSupplier;
import java.util.function.Predicate;
@@ -30,6 +29,7 @@
import org.apache.hadoop.ozone.om.BucketManager;
import org.apache.hadoop.ozone.om.KeyManager;
import org.apache.hadoop.ozone.om.OzoneAclUtils;
+import org.apache.hadoop.ozone.om.OzoneManager;
import org.apache.hadoop.ozone.om.PrefixManager;
import org.apache.hadoop.ozone.om.VolumeManager;
import org.apache.hadoop.ozone.om.exceptions.OMException;
@@ -42,7 +42,7 @@
*/
@InterfaceAudience.LimitedPrivate({"HDFS", "Yarn", "Ranger", "Hive", "HBase"})
@InterfaceStability.Evolving
-public class OzoneNativeAuthorizer implements IAccessAuthorizer {
+public class OzoneNativeAuthorizer implements OzoneManagerAuthorizer {
private static final Logger LOG =
LoggerFactory.getLogger(OzoneNativeAuthorizer.class);
@@ -189,30 +189,18 @@ public boolean checkAccess(IOzoneObj ozObject,
RequestContext context)
}
}
- public void setVolumeManager(VolumeManager volumeManager) {
- this.volumeManager = volumeManager;
- }
-
- public void setBucketManager(BucketManager bucketManager) {
- this.bucketManager = bucketManager;
- }
-
- public void setKeyManager(KeyManager keyManager) {
- this.keyManager = keyManager;
- }
-
- public void setPrefixManager(PrefixManager prefixManager) {
- this.prefixManager = prefixManager;
- }
-
- @VisibleForTesting
- void setOzoneAdmins(OzoneAdmins admins) {
- setAdminCheck(admins::isAdmin);
- }
-
- @VisibleForTesting
- void setOzoneReadOnlyAdmins(OzoneAdmins readOnlyAdmins) {
- setReadOnlyAdminCheck(readOnlyAdmins::isAdmin);
+ @Override
+ public OzoneNativeAuthorizer configure(OzoneManager om, KeyManager km,
PrefixManager pm) {
+ Objects.requireNonNull(om, "om == null");
+ volumeManager = om.getVolumeManager();
+ bucketManager = om.getBucketManager();
+ allowListAllVolumes = om::getAllowListAllVolumes;
+ setAdminCheck(om::isAdmin);
+ setReadOnlyAdminCheck(om::isReadOnlyAdmin);
+
+ keyManager = km;
+ prefixManager = pm;
+ return this;
}
public void setAdminCheck(Predicate<UserGroupInformation> check) {
@@ -223,10 +211,6 @@ public void
setReadOnlyAdminCheck(Predicate<UserGroupInformation> check) {
readOnlyAdminCheck = Objects.requireNonNull(check, "read-only admin
check");
}
- public void setAllowListAllVolumes(BooleanSupplier allowListAllVolumes) {
- this.allowListAllVolumes = Objects.requireNonNull(allowListAllVolumes,
"allowListAllVolumes");
- }
-
public boolean getAllowListAllVolumes() {
return allowListAllVolumes.getAsBoolean();
}
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 cdc246b2179..97fd4cdbfce 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
@@ -24,6 +24,8 @@
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.Collections;
+import java.util.List;
+import java.util.function.Predicate;
import org.apache.hadoop.hdds.server.OzoneAdmins;
import org.apache.hadoop.ozone.om.exceptions.OMException;
import org.apache.hadoop.security.UserGroupInformation;
@@ -57,6 +59,22 @@ public void testCreateVolume() throws Exception {
}
}
+ static Predicate<UserGroupInformation> newAdminUserPredicate(List<String>
adminUsernames) {
+ return new OzoneAdmins(adminUsernames, null)::isAdmin;
+ }
+
+ static Predicate<UserGroupInformation> newAdminUserPredicate(String
adminUsername) {
+ return newAdminUserPredicate(Collections.singletonList(adminUsername));
+ }
+
+ static Predicate<UserGroupInformation> newAdminGroupPredicate(List<String>
adminGroupNames) {
+ return new OzoneAdmins(null, adminGroupNames)::isAdmin;
+ }
+
+ static Predicate<UserGroupInformation> newAdminGroupPredicate(String
adminGroupName) {
+ return newAdminGroupPredicate(Collections.singletonList(adminGroupName));
+ }
+
@Test
public void testBucketOperation() throws OMException {
UserGroupInformation.createUserForTesting("testuser",
@@ -65,8 +83,7 @@ public void testBucketOperation() throws OMException {
OzoneObj obj = getTestBucketobj("testbucket");
RequestContext context = getUserRequestContext("testuser",
IAccessAuthorizer.ACLType.LIST);
- nativeAuthorizer.setOzoneReadOnlyAdmins(new OzoneAdmins(
- Collections.singletonList("testuser"), null));
+
nativeAuthorizer.setReadOnlyAdminCheck(newAdminUserPredicate("testuser"));
assertTrue(nativeAuthorizer.checkAccess(obj, context),
"matching read only admins are allowed to preform" +
"read operations");
@@ -91,8 +108,7 @@ public void testBucketOperation() throws OMException {
assertThrows(NullPointerException.class,
() -> nativeAuthorizer.checkAccess(obj, finalContext));
- nativeAuthorizer.setOzoneReadOnlyAdmins(new OzoneAdmins(
- null, Collections.singletonList("testgroup")));
+
nativeAuthorizer.setReadOnlyAdminCheck(newAdminGroupPredicate("testgroup"));
context = getUserRequestContext("testuser",
IAccessAuthorizer.ACLType.READ_ACL);
assertTrue(nativeAuthorizer.checkAccess(obj, context),
@@ -120,37 +136,34 @@ public void testListAllVolume() throws Exception {
private void testAdminOperations(OzoneObj obj, RequestContext context)
throws OMException {
- nativeAuthorizer.setOzoneAdmins(new OzoneAdmins(Collections.emptyList()));
+
nativeAuthorizer.setAdminCheck(newAdminUserPredicate(Collections.emptyList()));
assertFalse(nativeAuthorizer.checkAccess(obj, context), "empty" +
" admin list disallow anyone to perform " +
"admin operations");
- nativeAuthorizer.setOzoneAdmins(new OzoneAdmins(
- Collections.singletonList(OZONE_ADMINISTRATORS_WILDCARD)));
+
nativeAuthorizer.setAdminCheck(newAdminUserPredicate(OZONE_ADMINISTRATORS_WILDCARD));
assertTrue(nativeAuthorizer.checkAccess(obj, context),
"wildcard admin allows everyone to perform admin" +
" operations");
- nativeAuthorizer.setOzoneAdmins(new OzoneAdmins(
- Collections.singletonList("testuser")));
+ nativeAuthorizer.setAdminCheck(newAdminUserPredicate("testuser"));
assertTrue(nativeAuthorizer.checkAccess(obj, context),
"matching admins are allowed to perform admin " +
"operations");
- nativeAuthorizer.setOzoneAdmins(new OzoneAdmins(
- asList(new String[]{"testuser2", "testuser"})));
+ nativeAuthorizer.setAdminCheck(newAdminUserPredicate(
+ asList("testuser2", "testuser")));
assertTrue(nativeAuthorizer.checkAccess(obj, context),
"matching admins are allowed to perform admin " +
"operations");
- nativeAuthorizer.setOzoneAdmins(new OzoneAdmins(
- asList(new String[]{"testuser2", "testuser3"})));
+ nativeAuthorizer.setAdminCheck(newAdminUserPredicate(
+ asList("testuser2", "testuser3")));
assertFalse(nativeAuthorizer.checkAccess(obj, context),
"mismatching admins are not allowed perform " +
"admin operations");
- nativeAuthorizer.setOzoneReadOnlyAdmins(new OzoneAdmins(
- Collections.singletonList("testuser"), null));
+ nativeAuthorizer.setReadOnlyAdminCheck(newAdminUserPredicate("testuser"));
if (context.getAclRights() == IAccessAuthorizer.ACLType.LIST) {
assertTrue(nativeAuthorizer.checkAccess(obj, context),
"matching read only user are allowed to preform" +
@@ -161,8 +174,7 @@ private void testAdminOperations(OzoneObj obj,
RequestContext context)
"read operations");
}
- nativeAuthorizer.setOzoneReadOnlyAdmins(new OzoneAdmins(
- Collections.singletonList("testuser1"), null));
+ nativeAuthorizer.setReadOnlyAdminCheck(newAdminUserPredicate("testuser1"));
assertFalse(nativeAuthorizer.checkAccess(obj, context),
"mismatching read only user are allowed to preform" +
"read operations");
@@ -170,20 +182,17 @@ private void testAdminOperations(OzoneObj obj,
RequestContext context)
private void testGroupAdminOperations(OzoneObj obj, RequestContext context)
throws OMException {
- nativeAuthorizer.setOzoneAdmins(
- new OzoneAdmins(null, asList("testgroup", "anothergroup")));
+ nativeAuthorizer.setAdminCheck(newAdminGroupPredicate(asList("testgroup",
"anothergroup")));
assertTrue(nativeAuthorizer.checkAccess(obj, context), "Users " +
"from matching admin groups " +
"are allowed to perform admin operations");
- nativeAuthorizer.setOzoneAdmins(
- new OzoneAdmins(null, asList("wronggroup")));
+ nativeAuthorizer.setAdminCheck(newAdminGroupPredicate("wronggroup"));
assertFalse(nativeAuthorizer.checkAccess(obj, context), "Users" +
" from mismatching admin groups " +
"are allowed to perform admin operations");
- nativeAuthorizer.setOzoneReadOnlyAdmins(new OzoneAdmins(
- null, Collections.singletonList("testgroup")));
+
nativeAuthorizer.setReadOnlyAdminCheck(newAdminGroupPredicate("testgroup"));
if (context.getAclRights() == IAccessAuthorizer.ACLType.LIST) {
assertTrue(nativeAuthorizer.checkAccess(obj, context),
"matching read only groups are allowed to preform" +
@@ -194,8 +203,7 @@ private void testGroupAdminOperations(OzoneObj obj,
RequestContext context)
"preform read operations");
}
- nativeAuthorizer.setOzoneReadOnlyAdmins(new OzoneAdmins(
- null, Collections.singletonList("testgroup1")));
+
nativeAuthorizer.setReadOnlyAdminCheck(newAdminGroupPredicate("testgroup1"));
assertFalse(nativeAuthorizer.checkAccess(obj, context),
"mismatching read only groups are allowed to preform" +
"read operations");
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]