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]

Reply via email to