You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by el...@apache.org on 2017/11/27 22:50:09 UTC
[1/2] hbase git commit: HBASE-19318 Use the PB service interface as
the judge of whether some security feature exists
Repository: hbase
Updated Branches:
refs/heads/branch-2 96e63ac7b -> e42d20f8d
refs/heads/master f88671661 -> 5c1acf479
HBASE-19318 Use the PB service interface as the judge of whether some security feature exists
Hard-coded checks on HBase implementations (e.g. AccessController and
VisibilityController) preclude custom implementations of authorization
and visibility labels (Apache Ranger).
Signed-off-by: Ted Yu <te...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/5c1acf47
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/5c1acf47
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/5c1acf47
Branch: refs/heads/master
Commit: 5c1acf4792a7f7b6a5ace11c2fa4d172ede46b4e
Parents: f886716
Author: Josh Elser <el...@apache.org>
Authored: Wed Nov 22 11:14:40 2017 -0500
Committer: Josh Elser <el...@apache.org>
Committed: Mon Nov 27 17:49:23 2017 -0500
----------------------------------------------------------------------
.../hadoop/hbase/master/MasterRpcServices.java | 50 +++++-
.../master/TestMasterCoprocessorServices.java | 170 +++++++++++++++++++
2 files changed, 214 insertions(+), 6 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/hbase/blob/5c1acf47/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java
index 1a8fd06..ce85b66 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java
@@ -47,6 +47,7 @@ import org.apache.hadoop.hbase.client.TableDescriptor;
import org.apache.hadoop.hbase.client.TableState;
import org.apache.hadoop.hbase.client.VersionInfoUtil;
import org.apache.hadoop.hbase.client.replication.ReplicationPeerConfigUtil;
+import org.apache.hadoop.hbase.coprocessor.MasterCoprocessor;
import org.apache.hadoop.hbase.errorhandling.ForeignException;
import org.apache.hadoop.hbase.exceptions.UnknownProtocolException;
import org.apache.hadoop.hbase.ipc.CoprocessorRpcUtils;
@@ -64,6 +65,8 @@ import org.apache.hadoop.hbase.procedure2.LockType;
import org.apache.hadoop.hbase.procedure2.LockedResource;
import org.apache.hadoop.hbase.procedure2.Procedure;
import org.apache.hadoop.hbase.procedure2.ProcedureUtil;
+import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.AccessControlService;
+import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.VisibilityLabelsService;
import org.apache.hadoop.hbase.quotas.MasterQuotaManager;
import org.apache.hadoop.hbase.quotas.QuotaObserverChore;
import org.apache.hadoop.hbase.quotas.QuotaUtil;
@@ -1768,9 +1771,9 @@ public class MasterRpcServices extends RSRpcServices
} else {
capabilities.add(SecurityCapabilitiesResponse.Capability.SIMPLE_AUTHENTICATION);
}
- // The AccessController can provide AUTHORIZATION and CELL_AUTHORIZATION
- if (master.cpHost != null &&
- master.cpHost.findCoprocessor(AccessController.class.getName()) != null) {
+ // A coprocessor that implements AccessControlService can provide AUTHORIZATION and
+ // CELL_AUTHORIZATION
+ if (master.cpHost != null && hasAccessControlServiceCoprocessor(master.cpHost)) {
if (AccessController.isAuthorizationSupported(master.getConfiguration())) {
capabilities.add(SecurityCapabilitiesResponse.Capability.AUTHORIZATION);
}
@@ -1778,9 +1781,8 @@ public class MasterRpcServices extends RSRpcServices
capabilities.add(SecurityCapabilitiesResponse.Capability.CELL_AUTHORIZATION);
}
}
- // The VisibilityController can provide CELL_VISIBILITY
- if (master.cpHost != null &&
- master.cpHost.findCoprocessor(VisibilityController.class.getName()) != null) {
+ // A coprocessor that implements VisibilityLabelsService can provide CELL_VISIBILITY.
+ if (master.cpHost != null && hasVisibilityLabelsServiceCoprocessor(master.cpHost)) {
if (VisibilityController.isCellAuthorizationSupported(master.getConfiguration())) {
capabilities.add(SecurityCapabilitiesResponse.Capability.CELL_VISIBILITY);
}
@@ -1792,6 +1794,42 @@ public class MasterRpcServices extends RSRpcServices
return response.build();
}
+ /**
+ * Determines if there is a MasterCoprocessor deployed which implements
+ * {@link org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.AccessControlService.Interface}.
+ */
+ boolean hasAccessControlServiceCoprocessor(MasterCoprocessorHost cpHost) {
+ return checkCoprocessorWithService(
+ cpHost.findCoprocessors(MasterCoprocessor.class), AccessControlService.Interface.class);
+ }
+
+ /**
+ * Determines if there is a MasterCoprocessor deployed which implements
+ * {@link org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.VisibilityLabelsService.Interface}.
+ */
+ boolean hasVisibilityLabelsServiceCoprocessor(MasterCoprocessorHost cpHost) {
+ return checkCoprocessorWithService(
+ cpHost.findCoprocessors(MasterCoprocessor.class),
+ VisibilityLabelsService.Interface.class);
+ }
+
+ /**
+ * Determines if there is a coprocessor implementation in the provided argument which extends
+ * or implements the provided {@code service}.
+ */
+ boolean checkCoprocessorWithService(
+ List<MasterCoprocessor> coprocessorsToCheck, Class<?> service) {
+ if (coprocessorsToCheck == null || coprocessorsToCheck.isEmpty()) {
+ return false;
+ }
+ for (MasterCoprocessor cp : coprocessorsToCheck) {
+ if (service.isAssignableFrom(cp.getClass())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private MasterSwitchType convert(MasterProtos.MasterSwitchType switchType) {
switch (switchType) {
case SPLIT:
http://git-wip-us.apache.org/repos/asf/hbase/blob/5c1acf47/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestMasterCoprocessorServices.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestMasterCoprocessorServices.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestMasterCoprocessorServices.java
new file mode 100644
index 0000000..af550ab
--- /dev/null
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestMasterCoprocessorServices.java
@@ -0,0 +1,170 @@
+/*
+ * 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.hbase.master;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.apache.hadoop.hbase.JMXListener;
+import org.apache.hadoop.hbase.coprocessor.MasterCoprocessor;
+import org.apache.hadoop.hbase.coprocessor.MasterObserver;
+import org.apache.hadoop.hbase.coprocessor.RegionCoprocessor;
+import org.apache.hadoop.hbase.coprocessor.RegionObserver;
+import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.AccessControlService;
+import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.CheckPermissionsRequest;
+import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.CheckPermissionsResponse;
+import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.GetUserPermissionsRequest;
+import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.GetUserPermissionsResponse;
+import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.GrantRequest;
+import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.GrantResponse;
+import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.RevokeRequest;
+import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.RevokeResponse;
+import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.GetAuthsRequest;
+import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.GetAuthsResponse;
+import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.ListLabelsRequest;
+import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.ListLabelsResponse;
+import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.SetAuthsRequest;
+import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.VisibilityLabelsRequest;
+import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.VisibilityLabelsResponse;
+import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.VisibilityLabelsService;
+import org.apache.hadoop.hbase.security.access.AccessController;
+import org.apache.hadoop.hbase.security.visibility.VisibilityController;
+import org.apache.hadoop.hbase.testclassification.SmallTests;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import com.google.protobuf.RpcCallback;
+import com.google.protobuf.RpcController;
+
+/**
+ * Tests that the MasterRpcServices is correctly searching for implementations of the
+ * Coprocessor Service and not just the "default" implementations of those services.
+ */
+@Category({SmallTests.class})
+public class TestMasterCoprocessorServices {
+ private static class MockAccessController implements AccessControlService.Interface,
+ MasterCoprocessor, RegionCoprocessor, MasterObserver, RegionObserver {
+
+ @Override
+ public void grant(RpcController controller, GrantRequest request,
+ RpcCallback<GrantResponse> done) {}
+
+ @Override
+ public void revoke(RpcController controller, RevokeRequest request,
+ RpcCallback<RevokeResponse> done) {}
+
+ @Override
+ public void getUserPermissions(RpcController controller, GetUserPermissionsRequest request,
+ RpcCallback<GetUserPermissionsResponse> done) {}
+
+ @Override
+ public void checkPermissions(RpcController controller, CheckPermissionsRequest request,
+ RpcCallback<CheckPermissionsResponse> done) {}
+ }
+
+ private static class MockVisibilityController implements VisibilityLabelsService.Interface,
+ MasterCoprocessor, RegionCoprocessor, MasterObserver, RegionObserver {
+
+ @Override
+ public void addLabels(RpcController controller, VisibilityLabelsRequest request,
+ RpcCallback<VisibilityLabelsResponse> done) {
+ }
+
+ @Override
+ public void setAuths(RpcController controller, SetAuthsRequest request,
+ RpcCallback<VisibilityLabelsResponse> done) {
+ }
+
+ @Override
+ public void clearAuths(RpcController controller, SetAuthsRequest request,
+ RpcCallback<VisibilityLabelsResponse> done) {
+ }
+
+ @Override
+ public void getAuths(RpcController controller, GetAuthsRequest request,
+ RpcCallback<GetAuthsResponse> done) {
+ }
+
+ @Override
+ public void listLabels(RpcController controller, ListLabelsRequest request,
+ RpcCallback<ListLabelsResponse> done) {
+ }
+ }
+
+ private MasterRpcServices masterServices;
+
+ @SuppressWarnings("unchecked")
+ @Before
+ public void setup() {
+ masterServices = mock(MasterRpcServices.class);
+ when(masterServices.hasAccessControlServiceCoprocessor(
+ any(MasterCoprocessorHost.class))).thenCallRealMethod();
+ when(masterServices.hasVisibilityLabelsServiceCoprocessor(
+ any(MasterCoprocessorHost.class))).thenCallRealMethod();
+ when(masterServices.checkCoprocessorWithService(
+ any(List.class), any(Class.class))).thenCallRealMethod();
+ }
+
+ @Test
+ public void testAccessControlServices() {
+ MasterCoprocessor defaultImpl = new AccessController();
+ MasterCoprocessor customImpl = new MockAccessController();
+ MasterCoprocessor unrelatedImpl = new JMXListener();
+ assertTrue(masterServices.checkCoprocessorWithService(
+ Collections.singletonList(defaultImpl), AccessControlService.Interface.class));
+ assertTrue(masterServices.checkCoprocessorWithService(
+ Collections.singletonList(customImpl), AccessControlService.Interface.class));
+ assertFalse(masterServices.checkCoprocessorWithService(
+ Collections.emptyList(), AccessControlService.Interface.class));
+ assertFalse(masterServices.checkCoprocessorWithService(
+ null, AccessControlService.Interface.class));
+ assertFalse(masterServices.checkCoprocessorWithService(
+ Collections.singletonList(unrelatedImpl), AccessControlService.Interface.class));
+ assertTrue(masterServices.checkCoprocessorWithService(
+ Arrays.asList(unrelatedImpl, customImpl), AccessControlService.Interface.class));
+ assertTrue(masterServices.checkCoprocessorWithService(
+ Arrays.asList(unrelatedImpl, defaultImpl), AccessControlService.Interface.class));
+ }
+
+ @Test
+ public void testVisibilityLabelServices() {
+ MasterCoprocessor defaultImpl = new VisibilityController();
+ MasterCoprocessor customImpl = new MockVisibilityController();
+ MasterCoprocessor unrelatedImpl = new JMXListener();
+ assertTrue(masterServices.checkCoprocessorWithService(
+ Collections.singletonList(defaultImpl), VisibilityLabelsService.Interface.class));
+ assertTrue(masterServices.checkCoprocessorWithService(
+ Collections.singletonList(customImpl), VisibilityLabelsService.Interface.class));
+ assertFalse(masterServices.checkCoprocessorWithService(
+ Collections.emptyList(), VisibilityLabelsService.Interface.class));
+ assertFalse(masterServices.checkCoprocessorWithService(
+ null, VisibilityLabelsService.Interface.class));
+ assertFalse(masterServices.checkCoprocessorWithService(
+ Collections.singletonList(unrelatedImpl), VisibilityLabelsService.Interface.class));
+ assertTrue(masterServices.checkCoprocessorWithService(
+ Arrays.asList(unrelatedImpl, customImpl), VisibilityLabelsService.Interface.class));
+ assertTrue(masterServices.checkCoprocessorWithService(
+ Arrays.asList(unrelatedImpl, defaultImpl), VisibilityLabelsService.Interface.class));
+ }
+}
[2/2] hbase git commit: HBASE-19318 Use the PB service interface as
the judge of whether some security feature exists
Posted by el...@apache.org.
HBASE-19318 Use the PB service interface as the judge of whether some security feature exists
Hard-coded checks on HBase implementations (e.g. AccessController and
VisibilityController) preclude custom implementations of authorization
and visibility labels (Apache Ranger).
Signed-off-by: Ted Yu <te...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/e42d20f8
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/e42d20f8
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/e42d20f8
Branch: refs/heads/branch-2
Commit: e42d20f8ddd4c27d6138e71ec78d0fbfe59790a4
Parents: 96e63ac
Author: Josh Elser <el...@apache.org>
Authored: Wed Nov 22 11:14:40 2017 -0500
Committer: Josh Elser <el...@apache.org>
Committed: Mon Nov 27 17:49:41 2017 -0500
----------------------------------------------------------------------
.../hadoop/hbase/master/MasterRpcServices.java | 50 +++++-
.../master/TestMasterCoprocessorServices.java | 170 +++++++++++++++++++
2 files changed, 214 insertions(+), 6 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/hbase/blob/e42d20f8/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java
index 1a8fd06..ce85b66 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java
@@ -47,6 +47,7 @@ import org.apache.hadoop.hbase.client.TableDescriptor;
import org.apache.hadoop.hbase.client.TableState;
import org.apache.hadoop.hbase.client.VersionInfoUtil;
import org.apache.hadoop.hbase.client.replication.ReplicationPeerConfigUtil;
+import org.apache.hadoop.hbase.coprocessor.MasterCoprocessor;
import org.apache.hadoop.hbase.errorhandling.ForeignException;
import org.apache.hadoop.hbase.exceptions.UnknownProtocolException;
import org.apache.hadoop.hbase.ipc.CoprocessorRpcUtils;
@@ -64,6 +65,8 @@ import org.apache.hadoop.hbase.procedure2.LockType;
import org.apache.hadoop.hbase.procedure2.LockedResource;
import org.apache.hadoop.hbase.procedure2.Procedure;
import org.apache.hadoop.hbase.procedure2.ProcedureUtil;
+import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.AccessControlService;
+import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.VisibilityLabelsService;
import org.apache.hadoop.hbase.quotas.MasterQuotaManager;
import org.apache.hadoop.hbase.quotas.QuotaObserverChore;
import org.apache.hadoop.hbase.quotas.QuotaUtil;
@@ -1768,9 +1771,9 @@ public class MasterRpcServices extends RSRpcServices
} else {
capabilities.add(SecurityCapabilitiesResponse.Capability.SIMPLE_AUTHENTICATION);
}
- // The AccessController can provide AUTHORIZATION and CELL_AUTHORIZATION
- if (master.cpHost != null &&
- master.cpHost.findCoprocessor(AccessController.class.getName()) != null) {
+ // A coprocessor that implements AccessControlService can provide AUTHORIZATION and
+ // CELL_AUTHORIZATION
+ if (master.cpHost != null && hasAccessControlServiceCoprocessor(master.cpHost)) {
if (AccessController.isAuthorizationSupported(master.getConfiguration())) {
capabilities.add(SecurityCapabilitiesResponse.Capability.AUTHORIZATION);
}
@@ -1778,9 +1781,8 @@ public class MasterRpcServices extends RSRpcServices
capabilities.add(SecurityCapabilitiesResponse.Capability.CELL_AUTHORIZATION);
}
}
- // The VisibilityController can provide CELL_VISIBILITY
- if (master.cpHost != null &&
- master.cpHost.findCoprocessor(VisibilityController.class.getName()) != null) {
+ // A coprocessor that implements VisibilityLabelsService can provide CELL_VISIBILITY.
+ if (master.cpHost != null && hasVisibilityLabelsServiceCoprocessor(master.cpHost)) {
if (VisibilityController.isCellAuthorizationSupported(master.getConfiguration())) {
capabilities.add(SecurityCapabilitiesResponse.Capability.CELL_VISIBILITY);
}
@@ -1792,6 +1794,42 @@ public class MasterRpcServices extends RSRpcServices
return response.build();
}
+ /**
+ * Determines if there is a MasterCoprocessor deployed which implements
+ * {@link org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.AccessControlService.Interface}.
+ */
+ boolean hasAccessControlServiceCoprocessor(MasterCoprocessorHost cpHost) {
+ return checkCoprocessorWithService(
+ cpHost.findCoprocessors(MasterCoprocessor.class), AccessControlService.Interface.class);
+ }
+
+ /**
+ * Determines if there is a MasterCoprocessor deployed which implements
+ * {@link org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.VisibilityLabelsService.Interface}.
+ */
+ boolean hasVisibilityLabelsServiceCoprocessor(MasterCoprocessorHost cpHost) {
+ return checkCoprocessorWithService(
+ cpHost.findCoprocessors(MasterCoprocessor.class),
+ VisibilityLabelsService.Interface.class);
+ }
+
+ /**
+ * Determines if there is a coprocessor implementation in the provided argument which extends
+ * or implements the provided {@code service}.
+ */
+ boolean checkCoprocessorWithService(
+ List<MasterCoprocessor> coprocessorsToCheck, Class<?> service) {
+ if (coprocessorsToCheck == null || coprocessorsToCheck.isEmpty()) {
+ return false;
+ }
+ for (MasterCoprocessor cp : coprocessorsToCheck) {
+ if (service.isAssignableFrom(cp.getClass())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private MasterSwitchType convert(MasterProtos.MasterSwitchType switchType) {
switch (switchType) {
case SPLIT:
http://git-wip-us.apache.org/repos/asf/hbase/blob/e42d20f8/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestMasterCoprocessorServices.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestMasterCoprocessorServices.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestMasterCoprocessorServices.java
new file mode 100644
index 0000000..af550ab
--- /dev/null
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestMasterCoprocessorServices.java
@@ -0,0 +1,170 @@
+/*
+ * 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.hbase.master;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.apache.hadoop.hbase.JMXListener;
+import org.apache.hadoop.hbase.coprocessor.MasterCoprocessor;
+import org.apache.hadoop.hbase.coprocessor.MasterObserver;
+import org.apache.hadoop.hbase.coprocessor.RegionCoprocessor;
+import org.apache.hadoop.hbase.coprocessor.RegionObserver;
+import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.AccessControlService;
+import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.CheckPermissionsRequest;
+import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.CheckPermissionsResponse;
+import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.GetUserPermissionsRequest;
+import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.GetUserPermissionsResponse;
+import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.GrantRequest;
+import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.GrantResponse;
+import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.RevokeRequest;
+import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.RevokeResponse;
+import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.GetAuthsRequest;
+import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.GetAuthsResponse;
+import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.ListLabelsRequest;
+import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.ListLabelsResponse;
+import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.SetAuthsRequest;
+import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.VisibilityLabelsRequest;
+import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.VisibilityLabelsResponse;
+import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.VisibilityLabelsService;
+import org.apache.hadoop.hbase.security.access.AccessController;
+import org.apache.hadoop.hbase.security.visibility.VisibilityController;
+import org.apache.hadoop.hbase.testclassification.SmallTests;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import com.google.protobuf.RpcCallback;
+import com.google.protobuf.RpcController;
+
+/**
+ * Tests that the MasterRpcServices is correctly searching for implementations of the
+ * Coprocessor Service and not just the "default" implementations of those services.
+ */
+@Category({SmallTests.class})
+public class TestMasterCoprocessorServices {
+ private static class MockAccessController implements AccessControlService.Interface,
+ MasterCoprocessor, RegionCoprocessor, MasterObserver, RegionObserver {
+
+ @Override
+ public void grant(RpcController controller, GrantRequest request,
+ RpcCallback<GrantResponse> done) {}
+
+ @Override
+ public void revoke(RpcController controller, RevokeRequest request,
+ RpcCallback<RevokeResponse> done) {}
+
+ @Override
+ public void getUserPermissions(RpcController controller, GetUserPermissionsRequest request,
+ RpcCallback<GetUserPermissionsResponse> done) {}
+
+ @Override
+ public void checkPermissions(RpcController controller, CheckPermissionsRequest request,
+ RpcCallback<CheckPermissionsResponse> done) {}
+ }
+
+ private static class MockVisibilityController implements VisibilityLabelsService.Interface,
+ MasterCoprocessor, RegionCoprocessor, MasterObserver, RegionObserver {
+
+ @Override
+ public void addLabels(RpcController controller, VisibilityLabelsRequest request,
+ RpcCallback<VisibilityLabelsResponse> done) {
+ }
+
+ @Override
+ public void setAuths(RpcController controller, SetAuthsRequest request,
+ RpcCallback<VisibilityLabelsResponse> done) {
+ }
+
+ @Override
+ public void clearAuths(RpcController controller, SetAuthsRequest request,
+ RpcCallback<VisibilityLabelsResponse> done) {
+ }
+
+ @Override
+ public void getAuths(RpcController controller, GetAuthsRequest request,
+ RpcCallback<GetAuthsResponse> done) {
+ }
+
+ @Override
+ public void listLabels(RpcController controller, ListLabelsRequest request,
+ RpcCallback<ListLabelsResponse> done) {
+ }
+ }
+
+ private MasterRpcServices masterServices;
+
+ @SuppressWarnings("unchecked")
+ @Before
+ public void setup() {
+ masterServices = mock(MasterRpcServices.class);
+ when(masterServices.hasAccessControlServiceCoprocessor(
+ any(MasterCoprocessorHost.class))).thenCallRealMethod();
+ when(masterServices.hasVisibilityLabelsServiceCoprocessor(
+ any(MasterCoprocessorHost.class))).thenCallRealMethod();
+ when(masterServices.checkCoprocessorWithService(
+ any(List.class), any(Class.class))).thenCallRealMethod();
+ }
+
+ @Test
+ public void testAccessControlServices() {
+ MasterCoprocessor defaultImpl = new AccessController();
+ MasterCoprocessor customImpl = new MockAccessController();
+ MasterCoprocessor unrelatedImpl = new JMXListener();
+ assertTrue(masterServices.checkCoprocessorWithService(
+ Collections.singletonList(defaultImpl), AccessControlService.Interface.class));
+ assertTrue(masterServices.checkCoprocessorWithService(
+ Collections.singletonList(customImpl), AccessControlService.Interface.class));
+ assertFalse(masterServices.checkCoprocessorWithService(
+ Collections.emptyList(), AccessControlService.Interface.class));
+ assertFalse(masterServices.checkCoprocessorWithService(
+ null, AccessControlService.Interface.class));
+ assertFalse(masterServices.checkCoprocessorWithService(
+ Collections.singletonList(unrelatedImpl), AccessControlService.Interface.class));
+ assertTrue(masterServices.checkCoprocessorWithService(
+ Arrays.asList(unrelatedImpl, customImpl), AccessControlService.Interface.class));
+ assertTrue(masterServices.checkCoprocessorWithService(
+ Arrays.asList(unrelatedImpl, defaultImpl), AccessControlService.Interface.class));
+ }
+
+ @Test
+ public void testVisibilityLabelServices() {
+ MasterCoprocessor defaultImpl = new VisibilityController();
+ MasterCoprocessor customImpl = new MockVisibilityController();
+ MasterCoprocessor unrelatedImpl = new JMXListener();
+ assertTrue(masterServices.checkCoprocessorWithService(
+ Collections.singletonList(defaultImpl), VisibilityLabelsService.Interface.class));
+ assertTrue(masterServices.checkCoprocessorWithService(
+ Collections.singletonList(customImpl), VisibilityLabelsService.Interface.class));
+ assertFalse(masterServices.checkCoprocessorWithService(
+ Collections.emptyList(), VisibilityLabelsService.Interface.class));
+ assertFalse(masterServices.checkCoprocessorWithService(
+ null, VisibilityLabelsService.Interface.class));
+ assertFalse(masterServices.checkCoprocessorWithService(
+ Collections.singletonList(unrelatedImpl), VisibilityLabelsService.Interface.class));
+ assertTrue(masterServices.checkCoprocessorWithService(
+ Arrays.asList(unrelatedImpl, customImpl), VisibilityLabelsService.Interface.class));
+ assertTrue(masterServices.checkCoprocessorWithService(
+ Arrays.asList(unrelatedImpl, defaultImpl), VisibilityLabelsService.Interface.class));
+ }
+}