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 a90f57d43a HDDS-9701. Shareable /tmp dir doesn't work as sticky-bit 
with Ranger (#5613)
a90f57d43a is described below

commit a90f57d43ab2d510eeb0f1907d428b05b3f4c271
Author: Christos Bisias <[email protected]>
AuthorDate: Wed Jan 10 17:13:47 2024 +0200

    HDDS-9701. Shareable /tmp dir doesn't work as sticky-bit with Ranger (#5613)
---
 .../main/java/org/apache/hadoop/ozone/OFSPath.java |  6 ++
 .../ozone/security/acl/OzoneAuthorizerFactory.java | 22 +++++--
 .../ozone/security/acl/SharedTmpDirAuthorizer.java | 59 +++++++++++++++++
 .../security/acl/TestOzoneAuthorizerFactory.java   | 39 +++++++++++
 .../security/acl/TestSharedTmpDirAuthorizer.java   | 77 ++++++++++++++++++++++
 5 files changed, 199 insertions(+), 4 deletions(-)

diff --git 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OFSPath.java 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OFSPath.java
index 22c865b10e..61ae0879f7 100644
--- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OFSPath.java
+++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OFSPath.java
@@ -22,6 +22,7 @@ import com.google.common.base.Preconditions;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.hdds.conf.OzoneConfiguration;
+import org.apache.hadoop.ozone.security.acl.OzoneObjInfo;
 import org.apache.hadoop.security.UserGroupInformation;
 import org.apache.http.ParseException;
 import org.apache.hadoop.hdds.annotation.InterfaceAudience;
@@ -92,6 +93,11 @@ public class OFSPath {
     initOFSPath(fsPath.toUri(), endsWithSlash);
   }
 
+  public static boolean isSharedTmpBucket(OzoneObjInfo objInfo) {
+    return OFS_MOUNT_TMP_VOLUMENAME.equals(objInfo.getVolumeName()) &&
+        OFS_SHARED_TMP_BUCKETNAME.equals(objInfo.getBucketName());
+  }
+
   private void initOFSPath(URI uri, boolean endsWithSlash) {
     // Scheme is case-insensitive
     String scheme = uri.getScheme();
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 5a5b1a7f26..ea2f2a1da3 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
@@ -25,6 +25,8 @@ import org.apache.hadoop.ozone.om.OzoneManager;
 import org.apache.hadoop.ozone.om.PrefixManager;
 
 import static 
org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ACL_AUTHORIZER_CLASS;
+import static 
org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_ENABLE_OFS_SHARED_TMP_DIR;
+import static 
org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_ENABLE_OFS_SHARED_TMP_DIR_DEFAULT;
 import static org.apache.hadoop.util.ReflectionUtils.newInstance;
 
 /**
@@ -79,16 +81,28 @@ public final class OzoneAuthorizerFactory {
     }
 
     final IAccessAuthorizer authorizer = newInstance(clazz, conf);
-    return authorizer instanceof OzoneNativeAuthorizer
-        ? configure((OzoneNativeAuthorizer) authorizer, om, km, pm)
-        : authorizer;
+
+    if (authorizer instanceof OzoneNativeAuthorizer) {
+      return configure((OzoneNativeAuthorizer) authorizer, om, km, pm);
+    }
+
+    // If authorizer isn't native and shareable tmp dir is enabled,
+    // then return the shared tmp hybrid authorizer.
+    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),
+          authorizer);
+    }
+
+    return authorizer;
   }
 
   /**
    * Configure {@link OzoneNativeAuthorizer}.
    * @return same instance for convenience
    */
-  private static IAccessAuthorizer configure(
+  private static OzoneNativeAuthorizer configure(
       OzoneNativeAuthorizer authorizer,
       OzoneManager om, KeyManager km, PrefixManager pm
   ) {
diff --git 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/security/acl/SharedTmpDirAuthorizer.java
 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/security/acl/SharedTmpDirAuthorizer.java
new file mode 100644
index 0000000000..f3c1a35fd3
--- /dev/null
+++ 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/security/acl/SharedTmpDirAuthorizer.java
@@ -0,0 +1,59 @@
+/*
+ * 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.OFSPath;
+import org.apache.hadoop.ozone.om.exceptions.OMException;
+
+import java.util.Objects;
+
+/**
+ * SharedTmp implementation of {@link IAccessAuthorizer}.
+ */
+public class SharedTmpDirAuthorizer implements IAccessAuthorizer {
+
+  private final OzoneNativeAuthorizer ozoneNativeAuthorizer;
+  private final IAccessAuthorizer authorizer;
+
+  public SharedTmpDirAuthorizer(OzoneNativeAuthorizer ozoneNativeAuthorizer,
+      IAccessAuthorizer authorizer) {
+    this.ozoneNativeAuthorizer = ozoneNativeAuthorizer;
+    this.authorizer = authorizer;
+  }
+
+  /**
+   * Check access for a given ozoneObject.
+   *
+   * @param ozObject object for which access needs to be checked.
+   * @param context Context object encapsulating all user related information.
+   * @return true if user has access else false.
+   */
+  @Override
+  public boolean checkAccess(IOzoneObj ozObject, RequestContext context)
+      throws OMException {
+    Objects.requireNonNull(ozObject);
+    Objects.requireNonNull(context);
+
+    if (ozObject instanceof OzoneObjInfo) {
+      OzoneObjInfo objInfo = (OzoneObjInfo) ozObject;
+      if (OFSPath.isSharedTmpBucket(objInfo)) {
+        return ozoneNativeAuthorizer.checkAccess(ozObject, context);
+      }
+    }
+    return authorizer.checkAccess(ozObject, context);
+  }
+}
diff --git 
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/security/acl/TestOzoneAuthorizerFactory.java
 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/security/acl/TestOzoneAuthorizerFactory.java
index 868c7f80a1..127170debc 100644
--- 
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/security/acl/TestOzoneAuthorizerFactory.java
+++ 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/security/acl/TestOzoneAuthorizerFactory.java
@@ -21,12 +21,17 @@ import org.apache.hadoop.hdds.conf.OzoneConfiguration;
 import org.apache.hadoop.ozone.om.OzoneManager;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 import org.junit.jupiter.params.provider.ValueSource;
 
 import javax.annotation.Nonnull;
 
+import java.util.stream.Stream;
+
 import static 
org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ACL_AUTHORIZER_CLASS;
 import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ACL_ENABLED;
+import static 
org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_ENABLE_OFS_SHARED_TMP_DIR;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertInstanceOf;
 import static org.junit.jupiter.api.Assertions.assertNotSame;
@@ -36,6 +41,12 @@ import static org.mockito.Mockito.when;
 
 class TestOzoneAuthorizerFactory {
 
+  private static Stream<Arguments> tmpSharedDirAuthArgs() {
+    return Stream.of(
+        Arguments.of(true, SharedTmpDirAuthorizer.class),
+        Arguments.of(false, MockThirdPartyAuthorizer.class));
+  }
+
   @Test
   void aclsDisabled() {
     // GIVEN
@@ -85,6 +96,29 @@ class TestOzoneAuthorizerFactory {
     assertSameInstanceForSnapshot(om, omAuth);
   }
 
+  @ParameterizedTest
+  @MethodSource("tmpSharedDirAuthArgs")
+  void sharedTmpDirAuthorizer(boolean tmpDirEnabled,
+      Class<? extends IAccessAuthorizer> expectedClazz) {
+    // GIVEN
+    OzoneConfiguration conf = new OzoneConfiguration();
+    conf.setBoolean(OZONE_ACL_ENABLED, true);
+    conf.setBoolean(OZONE_OM_ENABLE_OFS_SHARED_TMP_DIR, tmpDirEnabled);
+    conf.setClass(OZONE_ACL_AUTHORIZER_CLASS,
+        MockThirdPartyAuthorizer.class, IAccessAuthorizer.class);
+
+    OzoneManager om = omMock(conf, true);
+
+    // WHEN
+    IAccessAuthorizer omAuth =
+        OzoneAuthorizerFactory.forOM(om);
+
+    // THEN
+    assertInstanceOf(expectedClazz, omAuth);
+
+    assertSameInstanceForSnapshot(om, omAuth);
+  }
+
   private static void assertSameInstanceForSnapshot(
       OzoneManager om, IAccessAuthorizer omAuth) {
     // GIVEN
@@ -131,6 +165,11 @@ class TestOzoneAuthorizerFactory {
     conf.setBoolean(OZONE_ACL_ENABLED, aclEnabled);
     conf.setClass(OZONE_ACL_AUTHORIZER_CLASS, clazz, IAccessAuthorizer.class);
 
+    return omMock(conf, aclEnabled);
+  }
+
+  private static OzoneManager omMock(OzoneConfiguration conf,
+      boolean aclEnabled) {
     OzoneManager om = mock(OzoneManager.class);
     when(om.getConfiguration())
         .thenReturn(conf);
diff --git 
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/security/acl/TestSharedTmpDirAuthorizer.java
 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/security/acl/TestSharedTmpDirAuthorizer.java
new file mode 100644
index 0000000000..ff3609b810
--- /dev/null
+++ 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/security/acl/TestSharedTmpDirAuthorizer.java
@@ -0,0 +1,77 @@
+/*
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.exceptions.OMException;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.mockito.Mockito;
+
+import java.util.stream.Stream;
+
+/**
+ * Tests for {@link SharedTmpDirAuthorizer}.
+ */
+public class TestSharedTmpDirAuthorizer {
+
+  private static OzoneNativeAuthorizer nativeAuthorizer;
+  private static IAccessAuthorizer authorizer;
+  private static SharedTmpDirAuthorizer sharedTmpDirAuthorizer;
+
+  @BeforeAll
+  public static void setUp() {
+    nativeAuthorizer = Mockito.mock(OzoneNativeAuthorizer.class);
+    authorizer = Mockito.mock(TestOzoneAuthorizerFactory
+                                  .MockThirdPartyAuthorizer.class);
+
+    sharedTmpDirAuthorizer =
+        new SharedTmpDirAuthorizer(nativeAuthorizer, authorizer);
+  }
+
+  private static Stream<Arguments> ozoneObjArgs() {
+    return Stream.of(
+        Arguments.of("tmp", "tmp", true),
+        Arguments.of("tmp", "bucket1", false),
+        Arguments.of("vol1", "tmp", false),
+        Arguments.of("vol1", "bucket1", false));
+  }
+
+  @ParameterizedTest
+  @MethodSource("ozoneObjArgs")
+  public void testCheckAccess(String volumeName,
+      String bucketName, boolean isNative) throws OMException {
+    OzoneObjInfo objInfo = OzoneObjInfo.Builder.newBuilder()
+                               .setResType(OzoneObj.ResourceType.KEY)
+                               .setStoreType(OzoneObj.StoreType.OZONE)
+                               .setVolumeName(volumeName)
+                               .setBucketName(bucketName)
+                               .setKeyName("key1")
+                               .build();
+
+    RequestContext context = Mockito.mock(RequestContext.class);
+    sharedTmpDirAuthorizer.checkAccess(objInfo, context);
+
+    if (isNative) {
+      Mockito.verify(nativeAuthorizer).checkAccess(objInfo, context);
+    } else {
+      Mockito.verify(authorizer).checkAccess(objInfo, context);
+    }
+  }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to