HBASE-11869 Support snapshot owner

This commit is contained in:
Ted Yu 2014-09-05 21:53:08 +00:00
parent cf69a13f42
commit c9e5229294
6 changed files with 315 additions and 51 deletions

View File

@ -10426,6 +10426,21 @@ public final class HBaseProtos {
* <code>optional int32 version = 5;</code>
*/
int getVersion();
// optional string owner = 6;
/**
* <code>optional string owner = 6;</code>
*/
boolean hasOwner();
/**
* <code>optional string owner = 6;</code>
*/
java.lang.String getOwner();
/**
* <code>optional string owner = 6;</code>
*/
com.google.protobuf.ByteString
getOwnerBytes();
}
/**
* Protobuf type {@code SnapshotDescription}
@ -10514,6 +10529,11 @@ public final class HBaseProtos {
version_ = input.readInt32();
break;
}
case 50: {
bitField0_ |= 0x00000020;
owner_ = input.readBytes();
break;
}
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
@ -10791,12 +10811,56 @@ public final class HBaseProtos {
return version_;
}
// optional string owner = 6;
public static final int OWNER_FIELD_NUMBER = 6;
private java.lang.Object owner_;
/**
* <code>optional string owner = 6;</code>
*/
public boolean hasOwner() {
return ((bitField0_ & 0x00000020) == 0x00000020);
}
/**
* <code>optional string owner = 6;</code>
*/
public java.lang.String getOwner() {
java.lang.Object ref = owner_;
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
owner_ = s;
}
return s;
}
}
/**
* <code>optional string owner = 6;</code>
*/
public com.google.protobuf.ByteString
getOwnerBytes() {
java.lang.Object ref = owner_;
if (ref instanceof java.lang.String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
owner_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
private void initFields() {
name_ = "";
table_ = "";
creationTime_ = 0L;
type_ = org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription.Type.FLUSH;
version_ = 0;
owner_ = "";
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
@ -10829,6 +10893,9 @@ public final class HBaseProtos {
if (((bitField0_ & 0x00000010) == 0x00000010)) {
output.writeInt32(5, version_);
}
if (((bitField0_ & 0x00000020) == 0x00000020)) {
output.writeBytes(6, getOwnerBytes());
}
getUnknownFields().writeTo(output);
}
@ -10858,6 +10925,10 @@ public final class HBaseProtos {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(5, version_);
}
if (((bitField0_ & 0x00000020) == 0x00000020)) {
size += com.google.protobuf.CodedOutputStream
.computeBytesSize(6, getOwnerBytes());
}
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
@ -10906,6 +10977,11 @@ public final class HBaseProtos {
result = result && (getVersion()
== other.getVersion());
}
result = result && (hasOwner() == other.hasOwner());
if (hasOwner()) {
result = result && getOwner()
.equals(other.getOwner());
}
result = result &&
getUnknownFields().equals(other.getUnknownFields());
return result;
@ -10939,6 +11015,10 @@ public final class HBaseProtos {
hash = (37 * hash) + VERSION_FIELD_NUMBER;
hash = (53 * hash) + getVersion();
}
if (hasOwner()) {
hash = (37 * hash) + OWNER_FIELD_NUMBER;
hash = (53 * hash) + getOwner().hashCode();
}
hash = (29 * hash) + getUnknownFields().hashCode();
memoizedHashCode = hash;
return hash;
@ -11063,6 +11143,8 @@ public final class HBaseProtos {
bitField0_ = (bitField0_ & ~0x00000008);
version_ = 0;
bitField0_ = (bitField0_ & ~0x00000010);
owner_ = "";
bitField0_ = (bitField0_ & ~0x00000020);
return this;
}
@ -11111,6 +11193,10 @@ public final class HBaseProtos {
to_bitField0_ |= 0x00000010;
}
result.version_ = version_;
if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
to_bitField0_ |= 0x00000020;
}
result.owner_ = owner_;
result.bitField0_ = to_bitField0_;
onBuilt();
return result;
@ -11146,6 +11232,11 @@ public final class HBaseProtos {
if (other.hasVersion()) {
setVersion(other.getVersion());
}
if (other.hasOwner()) {
bitField0_ |= 0x00000020;
owner_ = other.owner_;
onChanged();
}
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
@ -11451,6 +11542,80 @@ public final class HBaseProtos {
return this;
}
// optional string owner = 6;
private java.lang.Object owner_ = "";
/**
* <code>optional string owner = 6;</code>
*/
public boolean hasOwner() {
return ((bitField0_ & 0x00000020) == 0x00000020);
}
/**
* <code>optional string owner = 6;</code>
*/
public java.lang.String getOwner() {
java.lang.Object ref = owner_;
if (!(ref instanceof java.lang.String)) {
java.lang.String s = ((com.google.protobuf.ByteString) ref)
.toStringUtf8();
owner_ = s;
return s;
} else {
return (java.lang.String) ref;
}
}
/**
* <code>optional string owner = 6;</code>
*/
public com.google.protobuf.ByteString
getOwnerBytes() {
java.lang.Object ref = owner_;
if (ref instanceof String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
owner_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
/**
* <code>optional string owner = 6;</code>
*/
public Builder setOwner(
java.lang.String value) {
if (value == null) {
throw new NullPointerException();
}
bitField0_ |= 0x00000020;
owner_ = value;
onChanged();
return this;
}
/**
* <code>optional string owner = 6;</code>
*/
public Builder clearOwner() {
bitField0_ = (bitField0_ & ~0x00000020);
owner_ = getDefaultInstance().getOwner();
onChanged();
return this;
}
/**
* <code>optional string owner = 6;</code>
*/
public Builder setOwnerBytes(
com.google.protobuf.ByteString value) {
if (value == null) {
throw new NullPointerException();
}
bitField0_ |= 0x00000020;
owner_ = value;
onChanged();
return this;
}
// @@protoc_insertion_point(builder_scope:SnapshotDescription)
}
@ -16341,26 +16506,27 @@ public final class HBaseProtos {
"\014\n\004name\030\001 \002(\t\022\r\n\005value\030\002 \001(\014\"/\n\016BytesByt" +
"esPair\022\r\n\005first\030\001 \002(\014\022\016\n\006second\030\002 \002(\014\",\n" +
"\rNameInt64Pair\022\014\n\004name\030\001 \001(\t\022\r\n\005value\030\002 " +
"\001(\003\"\275\001\n\023SnapshotDescription\022\014\n\004name\030\001 \002(" +
"\001(\003\"\314\001\n\023SnapshotDescription\022\014\n\004name\030\001 \002(" +
"\t\022\r\n\005table\030\002 \001(\t\022\030\n\rcreation_time\030\003 \001(\003:" +
"\0010\022.\n\004type\030\004 \001(\0162\031.SnapshotDescription.T" +
"ype:\005FLUSH\022\017\n\007version\030\005 \001(\005\".\n\004Type\022\014\n\010D",
"ISABLED\020\000\022\t\n\005FLUSH\020\001\022\r\n\tSKIPFLUSH\020\002\"}\n\024P" +
"rocedureDescription\022\021\n\tsignature\030\001 \002(\t\022\020" +
"\n\010instance\030\002 \001(\t\022\030\n\rcreation_time\030\003 \001(\003:" +
"\0010\022&\n\rconfiguration\030\004 \003(\0132\017.NameStringPa" +
"ir\"\n\n\010EmptyMsg\"\033\n\007LongMsg\022\020\n\010long_msg\030\001 " +
"\002(\003\"\037\n\tDoubleMsg\022\022\n\ndouble_msg\030\001 \002(\001\"\'\n\r" +
"BigDecimalMsg\022\026\n\016bigdecimal_msg\030\001 \002(\014\"5\n" +
"\004UUID\022\026\n\016least_sig_bits\030\001 \002(\004\022\025\n\rmost_si" +
"g_bits\030\002 \002(\004\"K\n\023NamespaceDescriptor\022\014\n\004n" +
"ame\030\001 \002(\014\022&\n\rconfiguration\030\002 \003(\0132\017.NameS",
"tringPair\"$\n\020RegionServerInfo\022\020\n\010infoPor" +
"t\030\001 \001(\005*r\n\013CompareType\022\010\n\004LESS\020\000\022\021\n\rLESS" +
"_OR_EQUAL\020\001\022\t\n\005EQUAL\020\002\022\r\n\tNOT_EQUAL\020\003\022\024\n" +
"\020GREATER_OR_EQUAL\020\004\022\013\n\007GREATER\020\005\022\t\n\005NO_O" +
"P\020\006B>\n*org.apache.hadoop.hbase.protobuf." +
"generatedB\013HBaseProtosH\001\240\001\001"
"ype:\005FLUSH\022\017\n\007version\030\005 \001(\005\022\r\n\005owner\030\006 \001",
"(\t\".\n\004Type\022\014\n\010DISABLED\020\000\022\t\n\005FLUSH\020\001\022\r\n\tS" +
"KIPFLUSH\020\002\"}\n\024ProcedureDescription\022\021\n\tsi" +
"gnature\030\001 \002(\t\022\020\n\010instance\030\002 \001(\t\022\030\n\rcreat" +
"ion_time\030\003 \001(\003:\0010\022&\n\rconfiguration\030\004 \003(\013" +
"2\017.NameStringPair\"\n\n\010EmptyMsg\"\033\n\007LongMsg" +
"\022\020\n\010long_msg\030\001 \002(\003\"\037\n\tDoubleMsg\022\022\n\ndoubl" +
"e_msg\030\001 \002(\001\"\'\n\rBigDecimalMsg\022\026\n\016bigdecim" +
"al_msg\030\001 \002(\014\"5\n\004UUID\022\026\n\016least_sig_bits\030\001" +
" \002(\004\022\025\n\rmost_sig_bits\030\002 \002(\004\"K\n\023Namespace" +
"Descriptor\022\014\n\004name\030\001 \002(\014\022&\n\rconfiguratio",
"n\030\002 \003(\0132\017.NameStringPair\"$\n\020RegionServer" +
"Info\022\020\n\010infoPort\030\001 \001(\005*r\n\013CompareType\022\010\n" +
"\004LESS\020\000\022\021\n\rLESS_OR_EQUAL\020\001\022\t\n\005EQUAL\020\002\022\r\n" +
"\tNOT_EQUAL\020\003\022\024\n\020GREATER_OR_EQUAL\020\004\022\013\n\007GR" +
"EATER\020\005\022\t\n\005NO_OP\020\006B>\n*org.apache.hadoop." +
"hbase.protobuf.generatedB\013HBaseProtosH\001\240" +
"\001\001"
};
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
@ -16450,7 +16616,7 @@ public final class HBaseProtos {
internal_static_SnapshotDescription_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_SnapshotDescription_descriptor,
new java.lang.String[] { "Name", "Table", "CreationTime", "Type", "Version", });
new java.lang.String[] { "Name", "Table", "CreationTime", "Type", "Version", "Owner", });
internal_static_ProcedureDescription_descriptor =
getDescriptor().getMessageTypes().get(14);
internal_static_ProcedureDescription_fieldAccessorTable = new

View File

@ -164,6 +164,7 @@ message SnapshotDescription {
}
optional Type type = 4 [default = FLUSH];
optional int32 version = 5;
optional string owner = 6;
}
/**

View File

@ -45,6 +45,7 @@ import org.apache.hadoop.hbase.Stoppable;
import org.apache.hadoop.hbase.MetaTableAccessor;
import org.apache.hadoop.hbase.errorhandling.ForeignException;
import org.apache.hadoop.hbase.executor.ExecutorService;
import org.apache.hadoop.hbase.ipc.RequestContext;
import org.apache.hadoop.hbase.master.AssignmentManager;
import org.apache.hadoop.hbase.master.MasterCoprocessorHost;
import org.apache.hadoop.hbase.master.MasterFileSystem;
@ -63,6 +64,7 @@ import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.ProcedureDescripti
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.User;
import org.apache.hadoop.hbase.snapshot.ClientSnapshotDescriptionUtils;
import org.apache.hadoop.hbase.snapshot.HBaseSnapshotException;
import org.apache.hadoop.hbase.snapshot.RestoreSnapshotException;
@ -257,6 +259,18 @@ public class SnapshotManager extends MasterProcedureManager implements Stoppable
* @throws IOException For filesystem IOExceptions
*/
public void deleteSnapshot(SnapshotDescription snapshot) throws SnapshotDoesNotExistException, IOException {
// check to see if it is completed
if (!isSnapshotCompleted(snapshot)) {
throw new SnapshotDoesNotExistException(snapshot);
}
String snapshotName = snapshot.getName();
// first create the snapshot description and check to see if it exists
FileSystem fs = master.getMasterFileSystem().getFileSystem();
Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotName, rootDir);
// Get snapshot info from file system. The one passed as parameter is a "fake" snapshotInfo with
// just the "name" and it does not contains the "real" snapshot information
snapshot = SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDir);
// call coproc pre hook
MasterCoprocessorHost cpHost = master.getMasterCoprocessorHost();
@ -264,19 +278,9 @@ public class SnapshotManager extends MasterProcedureManager implements Stoppable
cpHost.preDeleteSnapshot(snapshot);
}
// check to see if it is completed
if (!isSnapshotCompleted(snapshot)) {
throw new SnapshotDoesNotExistException(snapshot);
}
String snapshotName = snapshot.getName();
LOG.debug("Deleting snapshot: " + snapshotName);
// first create the snapshot description and check to see if it exists
MasterFileSystem fs = master.getMasterFileSystem();
Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotName, rootDir);
// delete the existing snapshot
if (!fs.getFileSystem().delete(snapshotDir, true)) {
if (!fs.delete(snapshotDir, true)) {
throw new HBaseSnapshotException("Failed to delete snapshot directory: " + snapshotDir);
}
@ -540,13 +544,16 @@ public class SnapshotManager extends MasterProcedureManager implements Stoppable
throw new SnapshotCreationException("Table '" + snapshot.getTable()
+ "' doesn't exist, can't take snapshot.", snapshot);
}
SnapshotDescription.Builder builder = snapshot.toBuilder();
// if not specified, set the snapshot format
if (!snapshot.hasVersion()) {
snapshot = snapshot.toBuilder()
.setVersion(SnapshotDescriptionUtils.SNAPSHOT_LAYOUT_VERSION)
.build();
builder.setVersion(SnapshotDescriptionUtils.SNAPSHOT_LAYOUT_VERSION);
}
User user = RequestContext.getRequestUser();
if (User.isHBaseSecurityEnabled(master.getConfiguration()) && user != null) {
builder.setOwner(user.getShortName());
}
snapshot = builder.build();
// call pre coproc hook
MasterCoprocessorHost cpHost = master.getMasterCoprocessorHost();
@ -680,10 +687,12 @@ public class SnapshotManager extends MasterProcedureManager implements Stoppable
throw new SnapshotDoesNotExistException(reqSnapshot);
}
// read snapshot information
SnapshotDescription fsSnapshot = SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDir);
// Get snapshot info from file system. The reqSnapshot is a "fake" snapshotInfo with
// just the snapshot "name" and table name to restore. It does not contains the "real" snapshot
// information.
SnapshotDescription snapshot = SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDir);
SnapshotManifest manifest = SnapshotManifest.open(master.getConfiguration(), fs,
snapshotDir, fsSnapshot);
snapshotDir, snapshot);
HTableDescriptor snapshotTableDesc = manifest.getTableDescriptor();
TableName tableName = TableName.valueOf(reqSnapshot.getTable());
@ -696,9 +705,9 @@ public class SnapshotManager extends MasterProcedureManager implements Stoppable
// Execute the restore/clone operation
if (MetaTableAccessor.tableExists(master.getShortCircuitConnection(), tableName)) {
if (master.getAssignmentManager().getTableStateManager().isTableState(
TableName.valueOf(fsSnapshot.getTable()), ZooKeeperProtos.Table.State.ENABLED)) {
TableName.valueOf(snapshot.getTable()), ZooKeeperProtos.Table.State.ENABLED)) {
throw new UnsupportedOperationException("Table '" +
TableName.valueOf(fsSnapshot.getTable()) + "' must be disabled in order to " +
TableName.valueOf(snapshot.getTable()) + "' must be disabled in order to " +
"perform a restore operation" +
".");
}
@ -707,8 +716,8 @@ public class SnapshotManager extends MasterProcedureManager implements Stoppable
if (cpHost != null) {
cpHost.preRestoreSnapshot(reqSnapshot, snapshotTableDesc);
}
restoreSnapshot(fsSnapshot, snapshotTableDesc);
LOG.info("Restore snapshot=" + fsSnapshot.getName() + " as table=" + tableName);
restoreSnapshot(snapshot, snapshotTableDesc);
LOG.info("Restore snapshot=" + snapshot.getName() + " as table=" + tableName);
if (cpHost != null) {
cpHost.postRestoreSnapshot(reqSnapshot, snapshotTableDesc);
@ -718,8 +727,8 @@ public class SnapshotManager extends MasterProcedureManager implements Stoppable
if (cpHost != null) {
cpHost.preCloneSnapshot(reqSnapshot, htd);
}
cloneSnapshot(fsSnapshot, htd);
LOG.info("Clone snapshot=" + fsSnapshot.getName() + " as table=" + tableName);
cloneSnapshot(snapshot, htd);
LOG.info("Clone snapshot=" + snapshot.getName() + " as table=" + tableName);
if (cpHost != null) {
cpHost.postCloneSnapshot(reqSnapshot, htd);

View File

@ -94,6 +94,7 @@ import org.apache.hadoop.hbase.security.AccessDeniedException;
import org.apache.hadoop.hbase.security.User;
import org.apache.hadoop.hbase.security.UserProvider;
import org.apache.hadoop.hbase.security.access.Permission.Action;
import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils;
import org.apache.hadoop.hbase.util.ByteRange;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
@ -1055,7 +1056,8 @@ public class AccessController extends BaseMasterAndRegionObserver
public void preSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor)
throws IOException {
requirePermission("snapshot", Action.ADMIN);
requirePermission("snapshot", hTableDescriptor.getTableName(), null, null,
Permission.Action.ADMIN);
}
@Override
@ -1069,13 +1071,22 @@ public class AccessController extends BaseMasterAndRegionObserver
public void preRestoreSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor)
throws IOException {
requirePermission("restore", Action.ADMIN);
if (SnapshotDescriptionUtils.isSnapshotOwner(snapshot, getActiveUser())) {
requirePermission("restoreSnapshot", hTableDescriptor.getTableName(), null, null,
Permission.Action.ADMIN);
} else {
requirePermission("restore", Action.ADMIN);
}
}
@Override
public void preDeleteSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx,
final SnapshotDescription snapshot) throws IOException {
requirePermission("deleteSnapshot", Action.ADMIN);
if (SnapshotDescriptionUtils.isSnapshotOwner(snapshot, getActiveUser())) {
// Snapshot owner is allowed to delete the snapshot
} else {
requirePermission("deleteSnapshot", Action.ADMIN);
}
}
@Override

View File

@ -29,8 +29,10 @@ import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.ipc.RequestContext;
import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos;
import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
import org.apache.hadoop.hbase.security.User;
import org.apache.hadoop.hbase.snapshot.SnapshotManifestV2;
import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
import org.apache.hadoop.hbase.util.FSUtils;
@ -318,4 +320,16 @@ public class SnapshotDescriptionUtils {
}
}
/**
* Check if the user is this table snapshot's owner
* @param snapshot the table snapshot description
* @param user the user
* @return true if the user is the owner of the snapshot,
* false otherwise or the snapshot owner field is not present.
*/
public static boolean isSnapshotOwner(final SnapshotDescription snapshot, final User user) {
if (user == null) return false;
if (!snapshot.hasOwner()) return false;
return snapshot.getOwner().equals(user.getShortName());
}
}

View File

@ -88,6 +88,7 @@ import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos;
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.HBaseProtos.SnapshotDescription;
import org.apache.hadoop.hbase.regionserver.HRegion;
import org.apache.hadoop.hbase.regionserver.HRegionServer;
import org.apache.hadoop.hbase.regionserver.RegionCoprocessorHost;
@ -1824,11 +1825,17 @@ public class TestAccessController extends SecureTestUtil {
@Test
public void testSnapshot() throws Exception {
Admin admin = TEST_UTIL.getHBaseAdmin();
final HTableDescriptor htd = admin.getTableDescriptor(TEST_TABLE.getTableName());
SnapshotDescription.Builder builder = SnapshotDescription.newBuilder();
builder.setName(TEST_TABLE.getTableName().getNameAsString() + "-snapshot");
builder.setTable(TEST_TABLE.getTableName().getNameAsString());
final SnapshotDescription snapshot = builder.build();
AccessTestAction snapshotAction = new AccessTestAction() {
@Override
public Object run() throws Exception {
ACCESS_CONTROLLER.preSnapshot(ObserverContext.createAndPrepare(CP_ENV, null),
null, null);
snapshot, htd);
return null;
}
};
@ -1837,7 +1844,7 @@ public class TestAccessController extends SecureTestUtil {
@Override
public Object run() throws Exception {
ACCESS_CONTROLLER.preDeleteSnapshot(ObserverContext.createAndPrepare(CP_ENV, null),
null);
snapshot);
return null;
}
};
@ -1846,7 +1853,7 @@ public class TestAccessController extends SecureTestUtil {
@Override
public Object run() throws Exception {
ACCESS_CONTROLLER.preRestoreSnapshot(ObserverContext.createAndPrepare(CP_ENV, null),
null, null);
snapshot, htd);
return null;
}
};
@ -1860,8 +1867,8 @@ public class TestAccessController extends SecureTestUtil {
}
};
verifyAllowed(snapshotAction, SUPERUSER, USER_ADMIN);
verifyDenied(snapshotAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
verifyAllowed(snapshotAction, SUPERUSER, USER_ADMIN, USER_OWNER);
verifyDenied(snapshotAction, USER_CREATE, USER_RW, USER_RO, USER_NONE);
verifyAllowed(cloneAction, SUPERUSER, USER_ADMIN);
verifyDenied(deleteAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
@ -1873,6 +1880,62 @@ public class TestAccessController extends SecureTestUtil {
verifyDenied(cloneAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
}
@Test
public void testSnapshotWithOwner() throws Exception {
Admin admin = TEST_UTIL.getHBaseAdmin();
final HTableDescriptor htd = admin.getTableDescriptor(TEST_TABLE.getTableName());
SnapshotDescription.Builder builder = SnapshotDescription.newBuilder();
builder.setName(TEST_TABLE.getTableName().getNameAsString() + "-snapshot");
builder.setTable(TEST_TABLE.getTableName().getNameAsString());
builder.setOwner(USER_OWNER.getName());
final SnapshotDescription snapshot = builder.build();
AccessTestAction snapshotAction = new AccessTestAction() {
@Override
public Object run() throws Exception {
ACCESS_CONTROLLER.preSnapshot(ObserverContext.createAndPrepare(CP_ENV, null),
snapshot, htd);
return null;
}
};
verifyAllowed(snapshotAction, SUPERUSER, USER_ADMIN, USER_OWNER);
verifyDenied(snapshotAction, USER_CREATE, USER_RW, USER_RO, USER_NONE);
AccessTestAction deleteAction = new AccessTestAction() {
@Override
public Object run() throws Exception {
ACCESS_CONTROLLER.preDeleteSnapshot(ObserverContext.createAndPrepare(CP_ENV, null),
snapshot);
return null;
}
};
verifyAllowed(deleteAction, SUPERUSER, USER_ADMIN, USER_OWNER);
verifyDenied(deleteAction, USER_CREATE, USER_RW, USER_RO, USER_NONE);
AccessTestAction restoreAction = new AccessTestAction() {
@Override
public Object run() throws Exception {
ACCESS_CONTROLLER.preRestoreSnapshot(ObserverContext.createAndPrepare(CP_ENV, null),
snapshot, htd);
return null;
}
};
verifyAllowed(restoreAction, SUPERUSER, USER_ADMIN, USER_OWNER);
verifyDenied(restoreAction, USER_CREATE, USER_RW, USER_RO, USER_NONE);
AccessTestAction cloneAction = new AccessTestAction() {
@Override
public Object run() throws Exception {
ACCESS_CONTROLLER.preCloneSnapshot(ObserverContext.createAndPrepare(CP_ENV, null),
null, null);
return null;
}
};
// Clone by snapshot owner is not allowed , because clone operation creates a new table,
// which needs global admin permission.
verifyAllowed(cloneAction, SUPERUSER, USER_ADMIN);
verifyDenied(cloneAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
}
@Test
public void testGlobalAuthorizationForNewRegisteredRS() throws Exception {
LOG.debug("Test for global authorization for a new registered RegionServer.");