HBASE-12552 listSnapshots should list only owned snapshots for non-super user
This commit is contained in:
parent
325cdc0987
commit
890c067b66
|
@ -372,6 +372,16 @@ public abstract class BaseMasterAndRegionObserver extends BaseRegionObserver
|
|||
throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preListSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
final SnapshotDescription snapshot) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postListSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
final SnapshotDescription snapshot) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preCloneSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor)
|
||||
|
|
|
@ -365,6 +365,16 @@ public class BaseMasterObserver implements MasterObserver {
|
|||
throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preListSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
final SnapshotDescription snapshot) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postListSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
final SnapshotDescription snapshot) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preCloneSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor)
|
||||
|
|
|
@ -597,6 +597,26 @@ public interface MasterObserver extends Coprocessor {
|
|||
final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Called before listSnapshots request has been processed.
|
||||
* It can't bypass the default action, e.g., ctx.bypass() won't have effect.
|
||||
* @param ctx the environment to interact with the framework and master
|
||||
* @param snapshot the SnapshotDescriptor of the snapshot to list
|
||||
* @throws IOException
|
||||
*/
|
||||
void preListSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
final SnapshotDescription snapshot) throws IOException;
|
||||
|
||||
/**
|
||||
* Called after listSnapshots request has been processed.
|
||||
* It can't bypass the default action, e.g., ctx.bypass() won't have effect.
|
||||
* @param ctx the environment to interact with the framework and master
|
||||
* @param snapshot the SnapshotDescriptor of the snapshot to list
|
||||
* @throws IOException
|
||||
*/
|
||||
void postListSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
final SnapshotDescription snapshot) throws IOException;
|
||||
|
||||
/**
|
||||
* Called before a snapshot is cloned.
|
||||
* Called as part of restoreSnapshot RPC call.
|
||||
|
|
|
@ -727,6 +727,26 @@ public class MasterCoprocessorHost
|
|||
});
|
||||
}
|
||||
|
||||
public void preListSnapshot(final SnapshotDescription snapshot) throws IOException {
|
||||
execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {
|
||||
@Override
|
||||
public void call(MasterObserver observer, ObserverContext<MasterCoprocessorEnvironment> ctx)
|
||||
throws IOException {
|
||||
observer.preListSnapshot(ctx, snapshot);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void postListSnapshot(final SnapshotDescription snapshot) throws IOException {
|
||||
execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {
|
||||
@Override
|
||||
public void call(MasterObserver observer, ObserverContext<MasterCoprocessorEnvironment> ctx)
|
||||
throws IOException {
|
||||
observer.postListSnapshot(ctx, snapshot);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void preCloneSnapshot(final SnapshotDescription snapshot,
|
||||
final HTableDescriptor hTableDescriptor) throws IOException {
|
||||
execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {
|
||||
|
|
|
@ -31,19 +31,19 @@ import java.util.concurrent.ThreadPoolExecutor;
|
|||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.hadoop.hbase.classification.InterfaceAudience;
|
||||
import org.apache.hadoop.hbase.classification.InterfaceStability;
|
||||
import org.apache.hadoop.conf.Configuration;
|
||||
import org.apache.hadoop.fs.FSDataInputStream;
|
||||
import org.apache.hadoop.fs.FileStatus;
|
||||
import org.apache.hadoop.fs.FileSystem;
|
||||
import org.apache.hadoop.fs.Path;
|
||||
import org.apache.hadoop.hbase.TableName;
|
||||
import org.apache.hadoop.hbase.HBaseInterfaceAudience;
|
||||
import org.apache.hadoop.hbase.HConstants;
|
||||
import org.apache.hadoop.hbase.HTableDescriptor;
|
||||
import org.apache.hadoop.hbase.Stoppable;
|
||||
import org.apache.hadoop.hbase.MetaTableAccessor;
|
||||
import org.apache.hadoop.hbase.Stoppable;
|
||||
import org.apache.hadoop.hbase.TableName;
|
||||
import org.apache.hadoop.hbase.classification.InterfaceAudience;
|
||||
import org.apache.hadoop.hbase.classification.InterfaceStability;
|
||||
import org.apache.hadoop.hbase.client.TableState;
|
||||
import org.apache.hadoop.hbase.errorhandling.ForeignException;
|
||||
import org.apache.hadoop.hbase.executor.ExecutorService;
|
||||
|
@ -65,7 +65,7 @@ import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.NameStringPair;
|
|||
import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.ProcedureDescription;
|
||||
import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
|
||||
import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription.Type;
|
||||
import org.apache.hadoop.hbase.protobuf.generated.ZooKeeperProtos;
|
||||
import org.apache.hadoop.hbase.security.AccessDeniedException;
|
||||
import org.apache.hadoop.hbase.security.User;
|
||||
import org.apache.hadoop.hbase.snapshot.ClientSnapshotDescriptionUtils;
|
||||
import org.apache.hadoop.hbase.snapshot.HBaseSnapshotException;
|
||||
|
@ -214,6 +214,7 @@ public class SnapshotManager extends MasterProcedureManager implements Stoppable
|
|||
// ignore all the snapshots in progress
|
||||
FileStatus[] snapshots = fs.listStatus(snapshotDir,
|
||||
new SnapshotDescriptionUtils.CompletedSnaphotDirectoriesFilter(fs));
|
||||
MasterCoprocessorHost cpHost = master.getMasterCoprocessorHost();
|
||||
// loop through all the completed snapshots
|
||||
for (FileStatus snapshot : snapshots) {
|
||||
Path info = new Path(snapshot.getPath(), SnapshotDescriptionUtils.SNAPSHOTINFO_FILE);
|
||||
|
@ -226,7 +227,22 @@ public class SnapshotManager extends MasterProcedureManager implements Stoppable
|
|||
try {
|
||||
in = fs.open(info);
|
||||
SnapshotDescription desc = SnapshotDescription.parseFrom(in);
|
||||
if (cpHost != null) {
|
||||
try {
|
||||
cpHost.preListSnapshot(desc);
|
||||
} catch (AccessDeniedException e) {
|
||||
LOG.warn("Current user does not have access to " + desc.getName() + " snapshot. "
|
||||
+ "Either you should be owner of this snapshot or admin user.");
|
||||
// Skip this and try for next snapshot
|
||||
continue;
|
||||
}
|
||||
}
|
||||
snapshotDescs.add(desc);
|
||||
|
||||
// call coproc post hook
|
||||
if (cpHost != null) {
|
||||
cpHost.postListSnapshot(desc);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LOG.warn("Found a corrupted snapshot " + snapshot.getPath(), e);
|
||||
} finally {
|
||||
|
|
|
@ -1103,6 +1103,16 @@ public class AccessController extends BaseMasterAndRegionObserver
|
|||
Permission.Action.ADMIN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preListSnapshot(ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
final SnapshotDescription snapshot) throws IOException {
|
||||
if (SnapshotDescriptionUtils.isSnapshotOwner(snapshot, getActiveUser())) {
|
||||
// list it, if user is the owner of snapshot
|
||||
} else {
|
||||
requirePermission("listSnapshot", Action.ADMIN);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preCloneSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor)
|
||||
|
|
|
@ -122,6 +122,8 @@ public class TestMasterObserver {
|
|||
private boolean stopCalled;
|
||||
private boolean preSnapshotCalled;
|
||||
private boolean postSnapshotCalled;
|
||||
private boolean preListSnapshotCalled;
|
||||
private boolean postListSnapshotCalled;
|
||||
private boolean preCloneSnapshotCalled;
|
||||
private boolean postCloneSnapshotCalled;
|
||||
private boolean preRestoreSnapshotCalled;
|
||||
|
@ -192,6 +194,8 @@ public class TestMasterObserver {
|
|||
postBalanceSwitchCalled = false;
|
||||
preSnapshotCalled = false;
|
||||
postSnapshotCalled = false;
|
||||
preListSnapshotCalled = false;
|
||||
postListSnapshotCalled = false;
|
||||
preCloneSnapshotCalled = false;
|
||||
postCloneSnapshotCalled = false;
|
||||
preRestoreSnapshotCalled = false;
|
||||
|
@ -705,6 +709,22 @@ public class TestMasterObserver {
|
|||
return preSnapshotCalled && postSnapshotCalled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preListSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
final SnapshotDescription snapshot) throws IOException {
|
||||
preListSnapshotCalled = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postListSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
final SnapshotDescription snapshot) throws IOException {
|
||||
postListSnapshotCalled = true;
|
||||
}
|
||||
|
||||
public boolean wasListSnapshotCalled() {
|
||||
return preListSnapshotCalled && postListSnapshotCalled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preCloneSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor)
|
||||
|
@ -1315,6 +1335,11 @@ public class TestMasterObserver {
|
|||
assertTrue("Coprocessor should have been called on snapshot",
|
||||
cp.wasSnapshotCalled());
|
||||
|
||||
//Test list operation
|
||||
admin.listSnapshots();
|
||||
assertTrue("Coprocessor should have been called on snapshot list",
|
||||
cp.wasListSnapshotCalled());
|
||||
|
||||
// Test clone operation
|
||||
admin.cloneSnapshot(TEST_SNAPSHOT, TEST_CLONE);
|
||||
assertTrue("Coprocessor should have been called on snapshot clone",
|
||||
|
|
Loading…
Reference in New Issue