diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMMultiTenantManagerImpl.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMMultiTenantManagerImpl.java index d611f5632cc..580f7d78850 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMMultiTenantManagerImpl.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMMultiTenantManagerImpl.java @@ -55,12 +55,10 @@ import org.apache.hadoop.ozone.om.multitenant.BucketNameSpace; import org.apache.hadoop.ozone.om.multitenant.CachedTenantState; import org.apache.hadoop.ozone.om.multitenant.CachedTenantState.CachedAccessIdInfo; -import org.apache.hadoop.ozone.om.multitenant.InMemoryMultiTenantAccessController; import org.apache.hadoop.ozone.om.multitenant.MultiTenantAccessController; import org.apache.hadoop.ozone.om.multitenant.MultiTenantAccessController.Policy; import org.apache.hadoop.ozone.om.multitenant.MultiTenantAccessController.Role; import org.apache.hadoop.ozone.om.multitenant.OzoneTenant; -import org.apache.hadoop.ozone.om.multitenant.RangerClientMultiTenantAccessController; import org.apache.hadoop.ozone.om.multitenant.Tenant; import org.apache.hadoop.ozone.om.service.OMRangerBGSyncService; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.UserAccessIdInfo; @@ -112,14 +110,7 @@ public OMMultiTenantManagerImpl(OzoneManager ozoneManager, loadTenantCacheFromDB(); - boolean devSkipRanger = conf.getBoolean( - OZONE_OM_TENANT_DEV_SKIP_RANGER, false); - - if (devSkipRanger) { - this.accessController = new InMemoryMultiTenantAccessController(); - } else { - this.accessController = new RangerClientMultiTenantAccessController(conf); - } + accessController = MultiTenantAccessController.create(conf); cacheOp = new CacheOp(tenantCache, tenantCacheLock); authorizerOp = new AuthorizerOp(accessController, diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/multitenant/MultiTenantAccessController.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/multitenant/MultiTenantAccessController.java index 4afd6da34e8..a97f7500815 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/multitenant/MultiTenantAccessController.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/multitenant/MultiTenantAccessController.java @@ -17,6 +17,8 @@ package org.apache.hadoop.ozone.om.multitenant; +import static org.apache.hadoop.ozone.om.OMMultiTenantManagerImpl.OZONE_OM_TENANT_DEV_SKIP_RANGER; + import java.io.IOException; import java.util.ArrayList; import java.util.Collection; @@ -28,7 +30,9 @@ import java.util.Objects; import java.util.Optional; import java.util.Set; +import org.apache.hadoop.hdds.conf.ConfigurationSource; import org.apache.hadoop.ozone.security.acl.IAccessAuthorizer; +import org.apache.ratis.util.ReflectionUtils; /** * Defines the operations needed for multi-tenant access control. @@ -504,4 +508,18 @@ public Policy build() { } } } + + /** Create {@code MultiTenantAccessController} implementation. */ + static MultiTenantAccessController create(ConfigurationSource conf) { + if (conf.getBoolean(OZONE_OM_TENANT_DEV_SKIP_RANGER, false)) { + return new InMemoryMultiTenantAccessController(); + } + + final String className = "org.apache.hadoop.ozone.om.multitenant.RangerClientMultiTenantAccessController"; + return ReflectionUtils.newInstance( + ReflectionUtils.getClass(className, MultiTenantAccessController.class), + new Class[] {ConfigurationSource.class}, + conf + ); + } } diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/multitenant/RangerClientMultiTenantAccessController.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/multitenant/RangerClientMultiTenantAccessController.java index 812a8f70b39..b776d7981eb 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/multitenant/RangerClientMultiTenantAccessController.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/multitenant/RangerClientMultiTenantAccessController.java @@ -35,7 +35,7 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; +import org.apache.hadoop.hdds.conf.ConfigurationSource; import org.apache.hadoop.ozone.OmUtils; import org.apache.hadoop.ozone.OzoneConsts; import org.apache.hadoop.ozone.security.acl.IAccessAuthorizer; @@ -70,7 +70,7 @@ public class RangerClientMultiTenantAccessController implements // execUser for Ranger private final String shortName; - public RangerClientMultiTenantAccessController(OzoneConfiguration conf) + public RangerClientMultiTenantAccessController(ConfigurationSource conf) throws IOException { aclToString = MultiTenantAccessController.getRangerAclStrings(); diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/multitenant/TestMultiTenantAccessController.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/multitenant/MultiTenantAccessControllerTests.java similarity index 84% rename from hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/multitenant/TestMultiTenantAccessController.java rename to hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/multitenant/MultiTenantAccessControllerTests.java index e5f5888311f..f84e81e07d5 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/multitenant/TestMultiTenantAccessController.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/multitenant/MultiTenantAccessControllerTests.java @@ -17,12 +17,9 @@ package org.apache.hadoop.ozone.om.multitenant; -import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_KERBEROS_KEYTAB_FILE_KEY; -import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_KERBEROS_PRINCIPAL_KEY; -import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_RANGER_HTTPS_ADDRESS_KEY; -import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_RANGER_SERVICE; import static org.apache.hadoop.ozone.om.OMMultiTenantManager.OZONE_TENANT_RANGER_ROLE_DESCRIPTION; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assumptions.assumeThatCode; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -36,26 +33,22 @@ import java.util.Map; import java.util.UUID; import java.util.stream.Collectors; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; import org.apache.hadoop.ozone.om.multitenant.MultiTenantAccessController.Acl; import org.apache.hadoop.ozone.om.multitenant.MultiTenantAccessController.Policy; import org.apache.hadoop.ozone.om.multitenant.MultiTenantAccessController.Role; import org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType; -import org.apache.hadoop.security.authentication.util.KerberosName; -import org.apache.ozone.test.GenericTestUtils; -import org.apache.ranger.RangerClient; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.slf4j.LoggerFactory; -import org.slf4j.event.Level; /** * To test MultiTenantAccessController with Ranger Client. */ -public class TestMultiTenantAccessController { +public abstract class MultiTenantAccessControllerTests { private MultiTenantAccessController controller; private List users; + protected abstract MultiTenantAccessController createSubject(); + @BeforeEach public void setupUsers() { // If testing against a real cluster, users must already be added to Ranger. @@ -64,64 +57,10 @@ public void setupUsers() { users.add("hdfs"); } - /** - * Use this setup to test against a simulated Ranger instance. - */ @BeforeEach public void setupUnitTest() { - controller = new InMemoryMultiTenantAccessController(); - } - - /** - * Use this setup to test against a live Ranger instance. - */ -// @BeforeEach - public void setupClusterTest() throws Exception { - - // Set up truststore - System.setProperty("javax.net.ssl.trustStore", - "/path/to/cm-auto-global_truststore.jks"); - - // Specify Kerberos client config (krb5.conf) path - System.setProperty("java.security.krb5.conf", "/etc/krb5.conf"); - - // Enable Kerberos debugging - System.setProperty("sun.security.krb5.debug", "true"); - - // DEFAULT rule uses the default realm configured in krb5.conf - KerberosName.setRules("DEFAULT"); - - final OzoneConfiguration conf = new OzoneConfiguration(); - - // These config keys must be properly set when the test is run: - // - // OZONE_RANGER_HTTPS_ADDRESS_KEY - // OZONE_RANGER_SERVICE - // OZONE_OM_KERBEROS_PRINCIPAL_KEY - // OZONE_OM_KERBEROS_KEYTAB_FILE_KEY - - // Same as OM ranger-ozone-security.xml ranger.plugin.ozone.policy.rest.url - conf.set(OZONE_RANGER_HTTPS_ADDRESS_KEY, - "https://RANGER_HOST:6182/"); - - // Same as OM ranger-ozone-security.xml ranger.plugin.ozone.service.name - conf.set(OZONE_RANGER_SERVICE, "cm_ozone"); - - conf.set(OZONE_OM_KERBEROS_PRINCIPAL_KEY, - "om/instance@REALM"); - - conf.set(OZONE_OM_KERBEROS_KEYTAB_FILE_KEY, - "/path/to/ozone.keytab"); - - // TODO: Test with clear text username and password as well. -// conf.set(OZONE_OM_RANGER_HTTPS_ADMIN_API_USER, "rangeruser"); -// conf.set(OZONE_OM_RANGER_HTTPS_ADMIN_API_PASSWD, "passwd"); - - // (Optional) Enable RangerClient debug log - GenericTestUtils.setLogLevel( - LoggerFactory.getLogger(RangerClient.class), Level.DEBUG); - - controller = new RangerClientMultiTenantAccessController(conf); + controller = createSubject(); + assumeThatCode(() -> controller.getRangerServicePolicyVersion()).doesNotThrowAnyException(); } @Test diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/multitenant/TestInMemoryMultiTenantAccessController.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/multitenant/TestInMemoryMultiTenantAccessController.java new file mode 100644 index 00000000000..e9d0660aa62 --- /dev/null +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/multitenant/TestInMemoryMultiTenantAccessController.java @@ -0,0 +1,35 @@ +/* + * 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.om.multitenant; + +import static org.apache.hadoop.ozone.om.OMMultiTenantManagerImpl.OZONE_OM_TENANT_DEV_SKIP_RANGER; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; + +import org.apache.hadoop.hdds.conf.InMemoryConfiguration; +import org.apache.hadoop.hdds.conf.MutableConfigurationSource; + +class TestInMemoryMultiTenantAccessController extends MultiTenantAccessControllerTests { + + @Override + protected MultiTenantAccessController createSubject() { + MutableConfigurationSource conf = new InMemoryConfiguration(); + conf.setBoolean(OZONE_OM_TENANT_DEV_SKIP_RANGER, true); + return assertInstanceOf(InMemoryMultiTenantAccessController.class, MultiTenantAccessController.create(conf)); + } + +} diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/multitenant/TestRangerClientMultiTenantAccessController.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/multitenant/TestRangerClientMultiTenantAccessController.java new file mode 100644 index 00000000000..e994056a4b6 --- /dev/null +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/multitenant/TestRangerClientMultiTenantAccessController.java @@ -0,0 +1,86 @@ +/* + * 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.om.multitenant; + +import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_KERBEROS_KEYTAB_FILE_KEY; +import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_KERBEROS_PRINCIPAL_KEY; +import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_RANGER_HTTPS_ADDRESS_KEY; +import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_RANGER_SERVICE; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; + +import org.apache.hadoop.hdds.conf.InMemoryConfiguration; +import org.apache.hadoop.hdds.conf.MutableConfigurationSource; +import org.apache.hadoop.security.authentication.util.KerberosName; +import org.apache.ozone.test.GenericTestUtils; +import org.apache.ozone.test.tag.Unhealthy; +import org.apache.ranger.RangerClient; +import org.slf4j.LoggerFactory; +import org.slf4j.event.Level; + +@Unhealthy("Requires a Ranger endpoint") +class TestRangerClientMultiTenantAccessController extends MultiTenantAccessControllerTests { + + @Override + protected MultiTenantAccessController createSubject() { + MutableConfigurationSource conf = new InMemoryConfiguration(); + + // Set up truststore + System.setProperty("javax.net.ssl.trustStore", + "/path/to/cm-auto-global_truststore.jks"); + + // Specify Kerberos client config (krb5.conf) path + System.setProperty("java.security.krb5.conf", "/etc/krb5.conf"); + + // Enable Kerberos debugging + System.setProperty("sun.security.krb5.debug", "true"); + + // DEFAULT rule uses the default realm configured in krb5.conf + KerberosName.setRules("DEFAULT"); + + // These config keys must be properly set when the test is run: + // + // OZONE_RANGER_HTTPS_ADDRESS_KEY + // OZONE_RANGER_SERVICE + // OZONE_OM_KERBEROS_PRINCIPAL_KEY + // OZONE_OM_KERBEROS_KEYTAB_FILE_KEY + + // Same as OM ranger-ozone-security.xml ranger.plugin.ozone.policy.rest.url + conf.set(OZONE_RANGER_HTTPS_ADDRESS_KEY, + "https://localhost:6182/"); + + // Same as OM ranger-ozone-security.xml ranger.plugin.ozone.service.name + conf.set(OZONE_RANGER_SERVICE, "cm_ozone"); + + conf.set(OZONE_OM_KERBEROS_PRINCIPAL_KEY, + "om/_HOST@EXAMPLE.COM"); + + conf.set(OZONE_OM_KERBEROS_KEYTAB_FILE_KEY, + "/path/to/ozone.keytab"); + + // TODO: Test with clear text username and password as well. +// conf.set(OZONE_OM_RANGER_HTTPS_ADMIN_API_USER, "rangeruser"); +// conf.set(OZONE_OM_RANGER_HTTPS_ADMIN_API_PASSWD, "passwd"); + + // (Optional) Enable RangerClient debug log + GenericTestUtils.setLogLevel( + LoggerFactory.getLogger(RangerClient.class), Level.DEBUG); + + return assertInstanceOf(RangerClientMultiTenantAccessController.class, MultiTenantAccessController.create(conf)); + } + +}