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]