From 0184f967fbeb2d07529e4914da593ea6d816f93b Mon Sep 17 00:00:00 2001 From: Szabolcs Bukros Date: Fri, 18 Nov 2022 14:16:03 +0100 Subject: [PATCH 1/2] HBASE-27493: Allow namespace admins to clone snapshots created by them allow namespace admins to clone snapshots created by them --- .../security/access/AccessController.java | 3 + .../security/access/TestAccessController.java | 64 ++++++++++++++++--- 2 files changed, 59 insertions(+), 8 deletions(-) diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java index 3e4aca263293..90a51e2cb03e 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java @@ -1072,6 +1072,9 @@ public void preCloneSnapshot(final ObserverContext AuthResult result = AuthResult.allow("cloneSnapshot " + snapshot.getName(), "Snapshot owner check allowed", user, null, hTableDescriptor.getTableName(), null); AccessChecker.logResult(result); + } else if (SnapshotDescriptionUtils.isSnapshotOwner(snapshot, user)) { + requireNamespacePermission(ctx, "cloneSnapshot", + hTableDescriptor.getTableName().getNamespaceAsString(), Action.ADMIN); } else { accessChecker.requirePermission(user, "cloneSnapshot " + snapshot.getName(), null, Action.ADMIN); diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java index f6eaa36e91be..3c6031c97dfe 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java @@ -2074,16 +2074,16 @@ public Object run() throws Exception { USER_GROUP_WRITE, USER_GROUP_CREATE); verifyAllowed(cloneAction, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); - verifyDenied(deleteAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER, - USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); + verifyDenied(cloneAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER, USER_GROUP_READ, + USER_GROUP_WRITE, USER_GROUP_CREATE); verifyAllowed(restoreAction, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); verifyDenied(restoreAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); verifyAllowed(deleteAction, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); - verifyDenied(cloneAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER, USER_GROUP_READ, - USER_GROUP_WRITE, USER_GROUP_CREATE); + verifyDenied(deleteAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER, + USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); } @Test @@ -2126,18 +2126,66 @@ public Object run() throws Exception { verifyAllowed(restoreAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN); verifyDenied(restoreAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); + } - AccessTestAction cloneAction = new AccessTestAction() { + @Test + public void testCloneSnapshotWithOwner() throws Exception { + Admin admin = TEST_UTIL.getAdmin(); + final TableDescriptor originalTd = admin.getDescriptor(TEST_TABLE); + final SnapshotDescription snapshot = + new SnapshotDescription(TEST_TABLE.getNameAsString() + "-snapshot", TEST_TABLE, null, + USER_OWNER.getName()); + String namespace = "testCloneSnapshot"; + NamespaceDescriptor desc = NamespaceDescriptor.create(namespace).build(); + createNamespace(TEST_UTIL, desc); + + String differentTableString = "testtable2"; + TableName differentTable = TableName.valueOf(namespace, differentTableString); + TableDescriptor diffrentTd = TableDescriptorBuilder.newBuilder(differentTable) + .setColumnFamily(ColumnFamilyDescriptorBuilder.of(TEST_FAMILY)).build(); + + //recreating the original table + AccessTestAction cloneOriginalAction = new AccessTestAction() { @Override public Object run() throws Exception { ACCESS_CONTROLLER.preCloneSnapshot(ObserverContextImpl.createAndPrepare(CP_ENV), snapshot, - htd); + originalTd); return null; } }; - verifyAllowed(cloneAction, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN, USER_OWNER); - verifyDenied(cloneAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, + verifyAllowed(cloneOriginalAction, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN, USER_OWNER); + verifyDenied(cloneOriginalAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); + + //cloning to a different table + AccessTestAction cloneDifferentAction = new AccessTestAction() { + @Override + public Object run() throws Exception { + ACCESS_CONTROLLER.preCloneSnapshot(ObserverContextImpl.createAndPrepare(CP_ENV), snapshot, + diffrentTd); + return null; + } + }; + verifyAllowed(cloneDifferentAction, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); + verifyDenied(cloneDifferentAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, + USER_GROUP_WRITE, USER_GROUP_CREATE, USER_OWNER); + + //cloning to a different table where user is namespace admin + grantOnNamespace(TEST_UTIL, USER_OWNER.getShortName(), namespace, Action.ADMIN); + + AccessTestAction cloneNamespaceAdminAction = new AccessTestAction() { + @Override + public Object run() throws Exception { + ACCESS_CONTROLLER.preCloneSnapshot(ObserverContextImpl.createAndPrepare(CP_ENV), snapshot, + diffrentTd); + return null; + } + }; + verifyAllowed(cloneNamespaceAdminAction, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN, USER_OWNER); + verifyDenied(cloneNamespaceAdminAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, + USER_GROUP_WRITE, USER_GROUP_CREATE); + + deleteNamespace(TEST_UTIL, namespace); } @Test From 716f18335bd5acb6d14350fedf72af415edb91b6 Mon Sep 17 00:00:00 2001 From: Szabolcs Bukros Date: Mon, 2 Jan 2023 16:36:24 +0100 Subject: [PATCH 2/2] HBASE-27493: Allow namespace admins to clone snapshots created by them spotless:apply --- .../security/access/TestAccessController.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java index 3c6031c97dfe..11ae3b3ecf09 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java @@ -2132,9 +2132,8 @@ public Object run() throws Exception { public void testCloneSnapshotWithOwner() throws Exception { Admin admin = TEST_UTIL.getAdmin(); final TableDescriptor originalTd = admin.getDescriptor(TEST_TABLE); - final SnapshotDescription snapshot = - new SnapshotDescription(TEST_TABLE.getNameAsString() + "-snapshot", TEST_TABLE, null, - USER_OWNER.getName()); + final SnapshotDescription snapshot = new SnapshotDescription( + TEST_TABLE.getNameAsString() + "-snapshot", TEST_TABLE, null, USER_OWNER.getName()); String namespace = "testCloneSnapshot"; NamespaceDescriptor desc = NamespaceDescriptor.create(namespace).build(); createNamespace(TEST_UTIL, desc); @@ -2144,7 +2143,7 @@ public void testCloneSnapshotWithOwner() throws Exception { TableDescriptor diffrentTd = TableDescriptorBuilder.newBuilder(differentTable) .setColumnFamily(ColumnFamilyDescriptorBuilder.of(TEST_FAMILY)).build(); - //recreating the original table + // recreating the original table AccessTestAction cloneOriginalAction = new AccessTestAction() { @Override public Object run() throws Exception { @@ -2157,7 +2156,7 @@ public Object run() throws Exception { verifyDenied(cloneOriginalAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); - //cloning to a different table + // cloning to a different table AccessTestAction cloneDifferentAction = new AccessTestAction() { @Override public Object run() throws Exception { @@ -2170,7 +2169,7 @@ public Object run() throws Exception { verifyDenied(cloneDifferentAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE, USER_OWNER); - //cloning to a different table where user is namespace admin + // cloning to a different table where user is namespace admin grantOnNamespace(TEST_UTIL, USER_OWNER.getShortName(), namespace, Action.ADMIN); AccessTestAction cloneNamespaceAdminAction = new AccessTestAction() { @@ -2182,8 +2181,8 @@ public Object run() throws Exception { } }; verifyAllowed(cloneNamespaceAdminAction, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN, USER_OWNER); - verifyDenied(cloneNamespaceAdminAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, - USER_GROUP_WRITE, USER_GROUP_CREATE); + verifyDenied(cloneNamespaceAdminAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, + USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); deleteNamespace(TEST_UTIL, namespace); }