HBASE-7331. Add access control for region open and close, and stopping the regionserver (Vandana Ayyalasomayajula)
git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1422094 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
5dbff1427d
commit
1ef0621695
|
@ -62,14 +62,14 @@ public abstract class BaseRegionObserver implements RegionObserver {
|
|||
public void stop(CoprocessorEnvironment e) throws IOException { }
|
||||
|
||||
@Override
|
||||
public void preOpen(ObserverContext<RegionCoprocessorEnvironment> e) { }
|
||||
public void preOpen(ObserverContext<RegionCoprocessorEnvironment> e) throws IOException { }
|
||||
|
||||
@Override
|
||||
public void postOpen(ObserverContext<RegionCoprocessorEnvironment> e) { }
|
||||
|
||||
@Override
|
||||
public void preClose(ObserverContext<RegionCoprocessorEnvironment> e,
|
||||
boolean abortRequested) { }
|
||||
public void preClose(ObserverContext<RegionCoprocessorEnvironment> c, boolean abortRequested)
|
||||
throws IOException { }
|
||||
|
||||
@Override
|
||||
public void postClose(ObserverContext<RegionCoprocessorEnvironment> e,
|
||||
|
|
|
@ -64,6 +64,8 @@ import java.util.jar.JarFile;
|
|||
public abstract class CoprocessorHost<E extends CoprocessorEnvironment> {
|
||||
public static final String REGION_COPROCESSOR_CONF_KEY =
|
||||
"hbase.coprocessor.region.classes";
|
||||
public static final String REGIONSERVER_COPROCESSOR_CONF_KEY =
|
||||
"hbase.coprocessor.regionserver.classes";
|
||||
public static final String USER_REGION_COPROCESSOR_CONF_KEY =
|
||||
"hbase.coprocessor.user.region.classes";
|
||||
public static final String MASTER_COPROCESSOR_CONF_KEY =
|
||||
|
|
|
@ -58,8 +58,9 @@ public interface RegionObserver extends Coprocessor {
|
|||
/**
|
||||
* Called before the region is reported as open to the master.
|
||||
* @param c the environment provided by the region server
|
||||
* @throws IOException if an error occurred on the coprocessor
|
||||
*/
|
||||
void preOpen(final ObserverContext<RegionCoprocessorEnvironment> c);
|
||||
void preOpen(final ObserverContext<RegionCoprocessorEnvironment> c) throws IOException;
|
||||
|
||||
/**
|
||||
* Called after the region is reported as open to the master.
|
||||
|
@ -261,9 +262,10 @@ public interface RegionObserver extends Coprocessor {
|
|||
* Called before the region is reported as closed to the master.
|
||||
* @param c the environment provided by the region server
|
||||
* @param abortRequested true if the region server is aborting
|
||||
* @throws IOException
|
||||
*/
|
||||
void preClose(final ObserverContext<RegionCoprocessorEnvironment> c,
|
||||
boolean abortRequested);
|
||||
boolean abortRequested) throws IOException;
|
||||
|
||||
/**
|
||||
* Called after the region is reported as closed to the master.
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
*
|
||||
* 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.coprocessor;
|
||||
|
||||
import org.apache.hadoop.hbase.CoprocessorEnvironment;
|
||||
import org.apache.hadoop.hbase.regionserver.RegionServerServices;
|
||||
|
||||
public interface RegionServerCoprocessorEnvironment extends CoprocessorEnvironment {
|
||||
/**
|
||||
* Gets the region server services.
|
||||
*
|
||||
* @return the region server services
|
||||
*/
|
||||
RegionServerServices getRegionServerServices();
|
||||
}
|
|
@ -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.hbase.coprocessor;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.hadoop.hbase.Coprocessor;
|
||||
|
||||
public interface RegionServerObserver extends Coprocessor {
|
||||
|
||||
/**
|
||||
* Called before stopping region server.
|
||||
* @param env An instance of RegionServerCoprocessorEnvironment
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
*/
|
||||
void preStopRegionServer(
|
||||
final ObserverContext<RegionServerCoprocessorEnvironment> env)
|
||||
throws IOException;
|
||||
}
|
|
@ -432,6 +432,8 @@ public class HRegionServer implements ClientProtocol,
|
|||
* The reference to the QosFunction
|
||||
*/
|
||||
private final QosFunction qosFunction;
|
||||
|
||||
private RegionServerCoprocessorHost rsHost;
|
||||
|
||||
/**
|
||||
* Starts a HRegionServer at the default location
|
||||
|
@ -517,6 +519,7 @@ public class HRegionServer implements ClientProtocol,
|
|||
"hbase.regionserver.kerberos.principal", this.isa.getHostName());
|
||||
regionServerAccounting = new RegionServerAccounting();
|
||||
cacheConfig = new CacheConfig(conf);
|
||||
this.rsHost = new RegionServerCoprocessorHost(this, this.conf);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1574,10 +1577,15 @@ public class HRegionServer implements ClientProtocol,
|
|||
|
||||
@Override
|
||||
public void stop(final String msg) {
|
||||
this.stopped = true;
|
||||
LOG.info("STOPPED: " + msg);
|
||||
// Wakes run() if it is sleeping
|
||||
sleeper.skipSleepCycle();
|
||||
try {
|
||||
this.rsHost.preStop(msg);
|
||||
this.stopped = true;
|
||||
LOG.info("STOPPED: " + msg);
|
||||
// Wakes run() if it is sleeping
|
||||
sleeper.skipSleepCycle();
|
||||
} catch (IOException exp) {
|
||||
LOG.warn("The region server did not stop", exp);
|
||||
}
|
||||
}
|
||||
|
||||
public void waitForServerOnline(){
|
||||
|
@ -2097,6 +2105,10 @@ public class HRegionServer implements ClientProtocol,
|
|||
public ZooKeeperWatcher getZooKeeperWatcher() {
|
||||
return this.zooKeeper;
|
||||
}
|
||||
|
||||
public RegionServerCoprocessorHost getCoprocessorHost(){
|
||||
return this.rsHost;
|
||||
}
|
||||
|
||||
|
||||
public ConcurrentSkipListMap<byte[], Boolean> getRegionsInTransitionInRS() {
|
||||
|
@ -2398,6 +2410,17 @@ public class HRegionServer implements ClientProtocol,
|
|||
*/
|
||||
protected boolean closeRegion(HRegionInfo region, final boolean abort,
|
||||
final boolean zk, final int versionOfClosingNode, ServerName sn) {
|
||||
//Check for permissions to close.
|
||||
HRegion actualRegion = this.getFromOnlineRegions(region.getEncodedName());
|
||||
if ((actualRegion != null) && (actualRegion.getCoprocessorHost() != null)) {
|
||||
try {
|
||||
actualRegion.getCoprocessorHost().preClose(false);
|
||||
} catch (IOException exp) {
|
||||
LOG.warn("Unable to close region", exp);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.regionsInTransitionInRS.containsKey(region.getEncodedNameAsBytes())) {
|
||||
LOG.warn("Received close for region we are already opening or closing; " +
|
||||
region.getEncodedName());
|
||||
|
@ -3380,6 +3403,10 @@ public class HRegionServer implements ClientProtocol,
|
|||
checkIfRegionInTransition(region.getEncodedNameAsBytes(), OPEN);
|
||||
HRegion onlineRegion = getFromOnlineRegions(region.getEncodedName());
|
||||
if (null != onlineRegion) {
|
||||
//Check if the region can actually be opened.
|
||||
if( onlineRegion.getCoprocessorHost() != null){
|
||||
onlineRegion.getCoprocessorHost().preOpen();
|
||||
}
|
||||
// See HBASE-5094. Cross check with META if still this RS is owning
|
||||
// the region.
|
||||
Pair<HRegionInfo, ServerName> p = MetaReader.getRegion(
|
||||
|
@ -3459,6 +3486,10 @@ public class HRegionServer implements ClientProtocol,
|
|||
String encodedRegionName =
|
||||
ProtobufUtil.getRegionEncodedName(request.getRegion());
|
||||
byte[] encodedName = Bytes.toBytes(encodedRegionName);
|
||||
HRegion region = getRegionByEncodedName(encodedRegionName);
|
||||
if(region.getCoprocessorHost() != null){
|
||||
region.getCoprocessorHost().preClose(false);
|
||||
}
|
||||
Boolean openAction = regionsInTransitionInRS.get(encodedName);
|
||||
if (openAction != null) {
|
||||
if (openAction.booleanValue()) {
|
||||
|
@ -3466,7 +3497,7 @@ public class HRegionServer implements ClientProtocol,
|
|||
}
|
||||
checkIfRegionInTransition(encodedName, CLOSE);
|
||||
}
|
||||
HRegion region = getRegionByEncodedName(encodedRegionName);
|
||||
|
||||
requestCount.increment();
|
||||
LOG.info("Received close region: " + region.getRegionNameAsString() +
|
||||
". Version of ZK closing node:" + versionOfClosingNode +
|
||||
|
|
|
@ -36,7 +36,6 @@ import org.apache.hadoop.conf.Configuration;
|
|||
import org.apache.hadoop.fs.Path;
|
||||
import org.apache.hadoop.hbase.Coprocessor;
|
||||
import org.apache.hadoop.hbase.CoprocessorEnvironment;
|
||||
import org.apache.hadoop.hbase.HBaseConfiguration;
|
||||
import org.apache.hadoop.hbase.HConstants;
|
||||
import org.apache.hadoop.hbase.HRegionInfo;
|
||||
import org.apache.hadoop.hbase.HTableDescriptor;
|
||||
|
@ -53,8 +52,8 @@ import org.apache.hadoop.hbase.coprocessor.CoprocessorService;
|
|||
import org.apache.hadoop.hbase.coprocessor.ObserverContext;
|
||||
import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
|
||||
import org.apache.hadoop.hbase.coprocessor.RegionObserver;
|
||||
import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
|
||||
import org.apache.hadoop.hbase.filter.ByteArrayComparable;
|
||||
import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
|
||||
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
|
||||
import org.apache.hadoop.hbase.ipc.CoprocessorProtocol;
|
||||
import org.apache.hadoop.hbase.regionserver.wal.HLogKey;
|
||||
|
@ -267,17 +266,19 @@ public class RegionCoprocessorHost
|
|||
}
|
||||
|
||||
/**
|
||||
* Invoked before a region open
|
||||
* Invoked before a region open.
|
||||
*
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
*/
|
||||
public void preOpen() {
|
||||
public void preOpen() throws IOException {
|
||||
ObserverContext<RegionCoprocessorEnvironment> ctx = null;
|
||||
for (RegionEnvironment env: coprocessors) {
|
||||
if (env.getInstance() instanceof RegionObserver) {
|
||||
ctx = ObserverContext.createAndPrepare(env, ctx);
|
||||
try {
|
||||
((RegionObserver)env.getInstance()).preOpen(ctx);
|
||||
((RegionObserver) env.getInstance()).preOpen(ctx);
|
||||
} catch (Throwable e) {
|
||||
handleCoprocessorThrowableNoRethrow(env, e);
|
||||
handleCoprocessorThrowable(env, e);
|
||||
}
|
||||
if (ctx.shouldComplete()) {
|
||||
break;
|
||||
|
@ -295,7 +296,7 @@ public class RegionCoprocessorHost
|
|||
if (env.getInstance() instanceof RegionObserver) {
|
||||
ctx = ObserverContext.createAndPrepare(env, ctx);
|
||||
try {
|
||||
((RegionObserver)env.getInstance()).postOpen(ctx);
|
||||
((RegionObserver) env.getInstance()).postOpen(ctx);
|
||||
} catch (Throwable e) {
|
||||
handleCoprocessorThrowableNoRethrow(env, e);
|
||||
}
|
||||
|
@ -310,15 +311,15 @@ public class RegionCoprocessorHost
|
|||
* Invoked before a region is closed
|
||||
* @param abortRequested true if the server is aborting
|
||||
*/
|
||||
public void preClose(boolean abortRequested) {
|
||||
public void preClose(boolean abortRequested) throws IOException {
|
||||
ObserverContext<RegionCoprocessorEnvironment> ctx = null;
|
||||
for (RegionEnvironment env: coprocessors) {
|
||||
if (env.getInstance() instanceof RegionObserver) {
|
||||
ctx = ObserverContext.createAndPrepare(env, ctx);
|
||||
try {
|
||||
((RegionObserver)env.getInstance()).preClose(ctx, abortRequested);
|
||||
((RegionObserver) env.getInstance()).preClose(ctx, abortRequested);
|
||||
} catch (Throwable e) {
|
||||
handleCoprocessorThrowableNoRethrow(env, e);
|
||||
handleCoprocessorThrowable(env, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -334,7 +335,7 @@ public class RegionCoprocessorHost
|
|||
if (env.getInstance() instanceof RegionObserver) {
|
||||
ctx = ObserverContext.createAndPrepare(env, ctx);
|
||||
try {
|
||||
((RegionObserver)env.getInstance()).postClose(ctx, abortRequested);
|
||||
((RegionObserver) env.getInstance()).postClose(ctx, abortRequested);
|
||||
} catch (Throwable e) {
|
||||
handleCoprocessorThrowableNoRethrow(env, e);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
/**
|
||||
*
|
||||
* 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.regionserver;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Comparator;
|
||||
|
||||
import org.apache.hadoop.conf.Configuration;
|
||||
import org.apache.hadoop.hbase.Coprocessor;
|
||||
import org.apache.hadoop.hbase.CoprocessorEnvironment;
|
||||
import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
|
||||
import org.apache.hadoop.hbase.coprocessor.ObserverContext;
|
||||
import org.apache.hadoop.hbase.coprocessor.RegionServerCoprocessorEnvironment;
|
||||
import org.apache.hadoop.hbase.coprocessor.RegionServerObserver;
|
||||
|
||||
public class RegionServerCoprocessorHost extends
|
||||
CoprocessorHost<RegionServerCoprocessorHost.RegionServerEnvironment> {
|
||||
|
||||
private RegionServerServices rsServices;
|
||||
|
||||
public RegionServerCoprocessorHost(RegionServerServices rsServices,
|
||||
Configuration conf) {
|
||||
this.rsServices = rsServices;
|
||||
this.conf = conf;
|
||||
// load system default cp's from configuration.
|
||||
loadSystemCoprocessors(conf, REGIONSERVER_COPROCESSOR_CONF_KEY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegionServerEnvironment createEnvironment(Class<?> implClass,
|
||||
Coprocessor instance, int priority, int sequence, Configuration conf) {
|
||||
return new RegionServerEnvironment(implClass, instance, priority,
|
||||
sequence, conf, this.rsServices);
|
||||
}
|
||||
|
||||
public void preStop(String message) throws IOException {
|
||||
ObserverContext<RegionServerCoprocessorEnvironment> ctx = null;
|
||||
for (RegionServerEnvironment env : coprocessors) {
|
||||
if (env.getInstance() instanceof RegionServerObserver) {
|
||||
ctx = ObserverContext.createAndPrepare(env, ctx);
|
||||
((RegionServerObserver) env.getInstance()).preStopRegionServer(ctx);
|
||||
if (ctx.shouldComplete()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Coprocessor environment extension providing access to region server
|
||||
* related services.
|
||||
*/
|
||||
static class RegionServerEnvironment extends CoprocessorHost.Environment
|
||||
implements RegionServerCoprocessorEnvironment {
|
||||
|
||||
private RegionServerServices regionServerServices;
|
||||
|
||||
public RegionServerEnvironment(final Class<?> implClass,
|
||||
final Coprocessor impl, final int priority, final int seq,
|
||||
final Configuration conf, final RegionServerServices services) {
|
||||
super(impl, priority, seq, conf);
|
||||
this.regionServerServices = services;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegionServerServices getRegionServerServices() {
|
||||
return regionServerServices;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Environment priority comparator. Coprocessors are chained in sorted
|
||||
* order.
|
||||
*/
|
||||
static class EnvironmentPriorityComparator implements
|
||||
Comparator<CoprocessorEnvironment> {
|
||||
public int compare(final CoprocessorEnvironment env1,
|
||||
final CoprocessorEnvironment env2) {
|
||||
if (env1.getPriority() < env2.getPriority()) {
|
||||
return -1;
|
||||
} else if (env1.getPriority() > env2.getPriority()) {
|
||||
return 1;
|
||||
}
|
||||
if (env1.getLoadSequence() < env2.getLoadSequence()) {
|
||||
return -1;
|
||||
} else if (env1.getLoadSequence() > env2.getLoadSequence()) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -64,6 +64,7 @@ import org.apache.hadoop.hbase.security.AccessDeniedException;
|
|||
import org.apache.hadoop.hbase.security.User;
|
||||
import org.apache.hadoop.hbase.security.access.Permission.Action;
|
||||
import org.apache.hadoop.hbase.util.Bytes;
|
||||
import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
|
||||
|
||||
import com.google.common.collect.ListMultimap;
|
||||
import com.google.common.collect.Lists;
|
||||
|
@ -105,7 +106,7 @@ import static org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.Acc
|
|||
* </p>
|
||||
*/
|
||||
public class AccessController extends BaseRegionObserver
|
||||
implements MasterObserver, AccessControllerProtocol,
|
||||
implements MasterObserver, RegionServerObserver, AccessControllerProtocol,
|
||||
AccessControlService.Interface, CoprocessorService {
|
||||
/**
|
||||
* Represents the result of an authorization check for logging and error
|
||||
|
@ -514,17 +515,31 @@ public class AccessController extends BaseRegionObserver
|
|||
|
||||
/* ---- MasterObserver implementation ---- */
|
||||
public void start(CoprocessorEnvironment env) throws IOException {
|
||||
// if running on HMaster
|
||||
|
||||
ZooKeeperWatcher zk = null;
|
||||
if (env instanceof MasterCoprocessorEnvironment) {
|
||||
MasterCoprocessorEnvironment e = (MasterCoprocessorEnvironment)env;
|
||||
this.authManager = TableAuthManager.get(
|
||||
e.getMasterServices().getZooKeeper(),
|
||||
e.getConfiguration());
|
||||
// if running on HMaster
|
||||
MasterCoprocessorEnvironment mEnv = (MasterCoprocessorEnvironment) env;
|
||||
zk = mEnv.getMasterServices().getZooKeeper();
|
||||
} else if (env instanceof RegionServerCoprocessorEnvironment) {
|
||||
RegionServerCoprocessorEnvironment rsEnv = (RegionServerCoprocessorEnvironment) env;
|
||||
zk = rsEnv.getRegionServerServices().getZooKeeper();
|
||||
} else if (env instanceof RegionCoprocessorEnvironment) {
|
||||
// if running at region
|
||||
regionEnv = (RegionCoprocessorEnvironment) env;
|
||||
zk = regionEnv.getRegionServerServices().getZooKeeper();
|
||||
}
|
||||
|
||||
// if running at region
|
||||
if (env instanceof RegionCoprocessorEnvironment) {
|
||||
regionEnv = (RegionCoprocessorEnvironment)env;
|
||||
// If zk is null or IOException while obtaining auth manager,
|
||||
// throw RuntimeException so that the coprocessor is unloaded.
|
||||
if (zk != null) {
|
||||
try {
|
||||
this.authManager = TableAuthManager.get(zk, env.getConfiguration());
|
||||
} catch (IOException ioe) {
|
||||
throw new RuntimeException("Error obtaining TableAuthManager", ioe);
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("Error obtaining TableAuthManager, zk found null.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -763,28 +778,36 @@ public class AccessController extends BaseRegionObserver
|
|||
|
||||
/* ---- RegionObserver implementation ---- */
|
||||
|
||||
@Override
|
||||
public void preOpen(ObserverContext<RegionCoprocessorEnvironment> e)
|
||||
throws IOException {
|
||||
RegionCoprocessorEnvironment env = e.getEnvironment();
|
||||
final HRegion region = env.getRegion();
|
||||
if (region == null) {
|
||||
LOG.error("NULL region from RegionCoprocessorEnvironment in preOpen()");
|
||||
return;
|
||||
} else {
|
||||
HRegionInfo regionInfo = region.getRegionInfo();
|
||||
if (isSpecialTable(regionInfo)) {
|
||||
isSystemOrSuperUser(regionEnv.getConfiguration());
|
||||
} else {
|
||||
requirePermission(Action.ADMIN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postOpen(ObserverContext<RegionCoprocessorEnvironment> c) {
|
||||
RegionCoprocessorEnvironment e = c.getEnvironment();
|
||||
final HRegion region = e.getRegion();
|
||||
RegionCoprocessorEnvironment env = c.getEnvironment();
|
||||
final HRegion region = env.getRegion();
|
||||
if (region == null) {
|
||||
LOG.error("NULL region from RegionCoprocessorEnvironment in postOpen()");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.authManager = TableAuthManager.get(
|
||||
e.getRegionServerServices().getZooKeeper(),
|
||||
regionEnv.getConfiguration());
|
||||
} catch (IOException ioe) {
|
||||
// pass along as a RuntimeException, so that the coprocessor is unloaded
|
||||
throw new RuntimeException("Error obtaining TableAuthManager", ioe);
|
||||
}
|
||||
|
||||
if (AccessControlLists.isAclRegion(region)) {
|
||||
aclRegion = true;
|
||||
try {
|
||||
initialize(e);
|
||||
initialize(env);
|
||||
} catch (IOException ex) {
|
||||
// if we can't obtain permissions, it's better to fail
|
||||
// than perform checks incorrectly
|
||||
|
@ -1269,4 +1292,43 @@ public class AccessController extends BaseRegionObserver
|
|||
}
|
||||
return tableName;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void preClose(ObserverContext<RegionCoprocessorEnvironment> e, boolean abortRequested)
|
||||
throws IOException {
|
||||
requirePermission(Action.ADMIN);
|
||||
}
|
||||
|
||||
private void isSystemOrSuperUser(Configuration conf) throws IOException {
|
||||
User user = User.getCurrent();
|
||||
if (user == null) {
|
||||
throw new IOException("Unable to obtain the current user, " +
|
||||
"authorization checks for internal operations will not work correctly!");
|
||||
}
|
||||
|
||||
String currentUser = user.getShortName();
|
||||
List<String> superusers = Lists.asList(currentUser, conf.getStrings(
|
||||
AccessControlLists.SUPERUSER_CONF_KEY, new String[0]));
|
||||
|
||||
User activeUser = getActiveUser();
|
||||
if (!(superusers.contains(activeUser.getShortName()))) {
|
||||
throw new AccessDeniedException("User '" + (user != null ? user.getShortName() : "null") +
|
||||
"is not system or super user.");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSpecialTable(HRegionInfo regionInfo) {
|
||||
byte[] tableName = regionInfo.getTableName();
|
||||
return tableName.equals(AccessControlLists.ACL_TABLE_NAME)
|
||||
|| tableName.equals(Bytes.toBytes("-ROOT-"))
|
||||
|| tableName.equals(Bytes.toBytes(".META."));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preStopRegionServer(
|
||||
ObserverContext<RegionServerCoprocessorEnvironment> env)
|
||||
throws IOException {
|
||||
requirePermission(Permission.Action.ADMIN);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.apache.hadoop.hbase.HRegionInfo;
|
|||
import org.apache.hadoop.hbase.HTableDescriptor;
|
||||
import org.apache.hadoop.hbase.LargeTests;
|
||||
import org.apache.hadoop.hbase.ServerName;
|
||||
import org.apache.hadoop.hbase.UnknownRowLockException;
|
||||
import org.apache.hadoop.hbase.client.Append;
|
||||
import org.apache.hadoop.hbase.client.Delete;
|
||||
import org.apache.hadoop.hbase.client.Get;
|
||||
|
@ -49,6 +50,7 @@ import org.apache.hadoop.hbase.client.Scan;
|
|||
import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment;
|
||||
import org.apache.hadoop.hbase.coprocessor.ObserverContext;
|
||||
import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
|
||||
import org.apache.hadoop.hbase.coprocessor.RegionServerCoprocessorEnvironment;
|
||||
import org.apache.hadoop.hbase.master.MasterCoprocessorHost;
|
||||
import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
|
||||
import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos;
|
||||
|
@ -56,6 +58,7 @@ import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.AccessCont
|
|||
import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.CheckPermissionsRequest;
|
||||
import org.apache.hadoop.hbase.regionserver.HRegion;
|
||||
import org.apache.hadoop.hbase.regionserver.RegionCoprocessorHost;
|
||||
import org.apache.hadoop.hbase.regionserver.RegionServerCoprocessorHost;
|
||||
import org.apache.hadoop.hbase.security.AccessDeniedException;
|
||||
import org.apache.hadoop.hbase.security.User;
|
||||
import org.apache.hadoop.hbase.security.access.Permission.Action;
|
||||
|
@ -84,7 +87,7 @@ public class TestAccessController {
|
|||
private static User SUPERUSER;
|
||||
// user granted with all global permission
|
||||
private static User USER_ADMIN;
|
||||
// user with rw permissions
|
||||
// user with rw permissions on column family.
|
||||
private static User USER_RW;
|
||||
// user with read-only permissions
|
||||
private static User USER_RO;
|
||||
|
@ -100,6 +103,7 @@ public class TestAccessController {
|
|||
|
||||
private static MasterCoprocessorEnvironment CP_ENV;
|
||||
private static RegionCoprocessorEnvironment RCP_ENV;
|
||||
private static RegionServerCoprocessorEnvironment RSCP_ENV;
|
||||
private static AccessController ACCESS_CONTROLLER;
|
||||
|
||||
@BeforeClass
|
||||
|
@ -114,6 +118,10 @@ public class TestAccessController {
|
|||
ACCESS_CONTROLLER = (AccessController) cpHost.findCoprocessor(AccessController.class.getName());
|
||||
CP_ENV = cpHost.createEnvironment(AccessController.class, ACCESS_CONTROLLER,
|
||||
Coprocessor.PRIORITY_HIGHEST, 1, conf);
|
||||
RegionServerCoprocessorHost rsHost = TEST_UTIL.getMiniHBaseCluster().getRegionServer(0)
|
||||
.getCoprocessorHost();
|
||||
RSCP_ENV = rsHost.createEnvironment(AccessController.class, ACCESS_CONTROLLER,
|
||||
Coprocessor.PRIORITY_HIGHEST, 1, conf);
|
||||
|
||||
// Wait for the ACL table to become available
|
||||
TEST_UTIL.waitTableAvailable(AccessControlLists.ACL_TABLE_NAME, 5000);
|
||||
|
@ -1363,4 +1371,44 @@ public class TestAccessController {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStopRegionServer() throws Exception {
|
||||
PrivilegedExceptionAction action = new PrivilegedExceptionAction() {
|
||||
public Object run() throws Exception {
|
||||
ACCESS_CONTROLLER.preStopRegionServer(ObserverContext.createAndPrepare(RSCP_ENV, null));
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
verifyAllowed(action, SUPERUSER, USER_ADMIN);
|
||||
verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, USER_NONE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOpenRegion() throws Exception {
|
||||
PrivilegedExceptionAction action = new PrivilegedExceptionAction() {
|
||||
public Object run() throws Exception {
|
||||
ACCESS_CONTROLLER.preOpen(ObserverContext.createAndPrepare(RCP_ENV, null));
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
verifyAllowed(action, SUPERUSER, USER_ADMIN);
|
||||
verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloseRegion() throws Exception {
|
||||
PrivilegedExceptionAction action = new PrivilegedExceptionAction() {
|
||||
public Object run() throws Exception {
|
||||
ACCESS_CONTROLLER.preClose(ObserverContext.createAndPrepare(RCP_ENV, null), false);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
verifyAllowed(action, SUPERUSER, USER_ADMIN);
|
||||
verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue