branch-2.1:[fix](auth)fix when authentication, the permissions of multiple roles should be merged #52349 (#52947)
pick #52349
This commit is contained in:
@ -266,8 +266,9 @@ public class Auth implements Writable {
|
||||
readLock();
|
||||
try {
|
||||
Set<Role> roles = getRolesByUserWithLdap(currentUser);
|
||||
PrivBitSet savedPrivs = PrivBitSet.of();
|
||||
for (Role role : roles) {
|
||||
if (role.checkGlobalPriv(wanted)) {
|
||||
if (role.checkGlobalPriv(wanted, savedPrivs)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -289,8 +290,9 @@ public class Auth implements Writable {
|
||||
readLock();
|
||||
try {
|
||||
Set<Role> roles = getRolesByUserWithLdap(currentUser);
|
||||
PrivBitSet savedPrivs = PrivBitSet.of();
|
||||
for (Role role : roles) {
|
||||
if (role.checkCtlPriv(ctl, wanted)) {
|
||||
if (role.checkCtlPriv(ctl, wanted, savedPrivs)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -312,8 +314,9 @@ public class Auth implements Writable {
|
||||
readLock();
|
||||
try {
|
||||
Set<Role> roles = getRolesByUserWithLdap(currentUser);
|
||||
PrivBitSet savedPrivs = PrivBitSet.of();
|
||||
for (Role role : roles) {
|
||||
if (role.checkDbPriv(ctl, db, wanted)) {
|
||||
if (role.checkDbPriv(ctl, db, wanted, savedPrivs)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -335,8 +338,9 @@ public class Auth implements Writable {
|
||||
readLock();
|
||||
try {
|
||||
Set<Role> roles = getRolesByUserWithLdap(currentUser);
|
||||
PrivBitSet savedPrivs = PrivBitSet.of();
|
||||
for (Role role : roles) {
|
||||
if (role.checkTblPriv(ctl, db, tbl, wanted)) {
|
||||
if (role.checkTblPriv(ctl, db, tbl, wanted, savedPrivs)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -363,8 +367,9 @@ public class Auth implements Writable {
|
||||
|
||||
private boolean checkColPriv(String ctl, String db, String tbl,
|
||||
String col, PrivPredicate wanted, Set<Role> roles) {
|
||||
PrivBitSet savedPrivs = PrivBitSet.of();
|
||||
for (Role role : roles) {
|
||||
if (role.checkColPriv(ctl, db, tbl, col, wanted)) {
|
||||
if (role.checkColPriv(ctl, db, tbl, col, wanted, savedPrivs)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -376,8 +381,9 @@ public class Auth implements Writable {
|
||||
readLock();
|
||||
try {
|
||||
Set<Role> roles = getRolesByUserWithLdap(currentUser);
|
||||
PrivBitSet savedPrivs = PrivBitSet.of();
|
||||
for (Role role : roles) {
|
||||
if (role.checkResourcePriv(resourceName, wanted)) {
|
||||
if (role.checkResourcePriv(resourceName, wanted, savedPrivs)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -398,28 +404,9 @@ public class Auth implements Writable {
|
||||
}
|
||||
|
||||
Set<Role> roles = getRolesByUserWithLdap(currentUser);
|
||||
PrivBitSet savedPrivs = PrivBitSet.of();
|
||||
for (Role role : roles) {
|
||||
if (role.checkWorkloadGroupPriv(workloadGroupName, wanted)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} finally {
|
||||
readUnlock();
|
||||
}
|
||||
}
|
||||
|
||||
// ==== Other ====
|
||||
/*
|
||||
* Check if current user has certain privilege.
|
||||
* This method will check the given privilege levels
|
||||
*/
|
||||
public boolean checkHasPriv(ConnectContext ctx, PrivPredicate priv, PrivLevel... levels) {
|
||||
readLock();
|
||||
try {
|
||||
Set<Role> roles = getRolesByUserWithLdap(ctx.getCurrentUserIdentity());
|
||||
for (Role role : roles) {
|
||||
if (role.checkHasPriv(priv, levels)) {
|
||||
if (role.checkWorkloadGroupPriv(workloadGroupName, wanted, savedPrivs)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -235,13 +235,11 @@ public class Role implements Writable, GsonPostProcessable {
|
||||
mergeNotCheck(other);
|
||||
}
|
||||
|
||||
public boolean checkGlobalPriv(PrivPredicate wanted) {
|
||||
PrivBitSet savedPrivs = PrivBitSet.of();
|
||||
public boolean checkGlobalPriv(PrivPredicate wanted, PrivBitSet savedPrivs) {
|
||||
return checkGlobalInternal(wanted, savedPrivs);
|
||||
}
|
||||
|
||||
public boolean checkCtlPriv(String ctl, PrivPredicate wanted) {
|
||||
PrivBitSet savedPrivs = PrivBitSet.of();
|
||||
public boolean checkCtlPriv(String ctl, PrivPredicate wanted, PrivBitSet savedPrivs) {
|
||||
if (checkGlobalInternal(wanted, savedPrivs)
|
||||
|| checkCatalogInternal(ctl, wanted, savedPrivs)) {
|
||||
return true;
|
||||
@ -285,8 +283,7 @@ public class Role implements Writable, GsonPostProcessable {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean checkDbPriv(String ctl, String db, PrivPredicate wanted) {
|
||||
PrivBitSet savedPrivs = PrivBitSet.of();
|
||||
public boolean checkDbPriv(String ctl, String db, PrivPredicate wanted, PrivBitSet savedPrivs) {
|
||||
if (checkGlobalInternal(wanted, savedPrivs)
|
||||
|| checkCatalogInternal(ctl, wanted, savedPrivs)
|
||||
|| checkDbInternal(ctl, db, wanted, savedPrivs)) {
|
||||
@ -357,8 +354,7 @@ public class Role implements Writable, GsonPostProcessable {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean checkTblPriv(String ctl, String db, String tbl, PrivPredicate wanted) {
|
||||
PrivBitSet savedPrivs = PrivBitSet.of();
|
||||
public boolean checkTblPriv(String ctl, String db, String tbl, PrivPredicate wanted, PrivBitSet savedPrivs) {
|
||||
if (checkGlobalInternal(wanted, savedPrivs)
|
||||
|| checkCatalogInternal(ctl, wanted, savedPrivs)
|
||||
|| checkDbInternal(ctl, db, wanted, savedPrivs)
|
||||
@ -378,12 +374,14 @@ public class Role implements Writable, GsonPostProcessable {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean checkColPriv(String ctl, String db, String tbl, String col, PrivPredicate wanted) {
|
||||
public boolean checkColPriv(String ctl, String db, String tbl, String col, PrivPredicate wanted,
|
||||
PrivBitSet savedPrivs) {
|
||||
Optional<Privilege> colPrivilege = wanted.getColPrivilege();
|
||||
if (!colPrivilege.isPresent()) {
|
||||
throw new IllegalStateException("this privPredicate should not use checkColPriv:" + wanted);
|
||||
}
|
||||
return checkTblPriv(ctl, db, tbl, wanted) || onlyCheckColPriv(ctl, db, tbl, col, colPrivilege.get());
|
||||
return checkTblPriv(ctl, db, tbl, wanted, savedPrivs) || onlyCheckColPriv(ctl, db, tbl, col,
|
||||
colPrivilege.get());
|
||||
}
|
||||
|
||||
private boolean onlyCheckColPriv(String ctl, String db, String tbl, String col,
|
||||
@ -400,8 +398,7 @@ public class Role implements Writable, GsonPostProcessable {
|
||||
return Privilege.satisfy(savedPrivs, wanted);
|
||||
}
|
||||
|
||||
public boolean checkResourcePriv(String resourceName, PrivPredicate wanted) {
|
||||
PrivBitSet savedPrivs = PrivBitSet.of();
|
||||
public boolean checkResourcePriv(String resourceName, PrivPredicate wanted, PrivBitSet savedPrivs) {
|
||||
if (checkGlobalInternal(wanted, savedPrivs)
|
||||
|| checkResourceInternal(resourceName, wanted, savedPrivs)) {
|
||||
return true;
|
||||
@ -418,12 +415,11 @@ public class Role implements Writable, GsonPostProcessable {
|
||||
return Privilege.satisfy(savedPrivs, wanted);
|
||||
}
|
||||
|
||||
public boolean checkWorkloadGroupPriv(String workloadGroupName, PrivPredicate wanted) {
|
||||
public boolean checkWorkloadGroupPriv(String workloadGroupName, PrivPredicate wanted, PrivBitSet savedPrivs) {
|
||||
// For compatibility with older versions, it is not needed to check the privileges of the default group.
|
||||
if (WorkloadGroupMgr.DEFAULT_GROUP_NAME.equals(workloadGroupName)) {
|
||||
return true;
|
||||
}
|
||||
PrivBitSet savedPrivs = PrivBitSet.of();
|
||||
// usage priv not in global, but grant_priv may in global
|
||||
if (checkGlobalInternal(wanted, savedPrivs)
|
||||
|| checkWorkloadGroupInternal(workloadGroupName, wanted, savedPrivs)) {
|
||||
@ -502,22 +498,6 @@ public class Role implements Writable, GsonPostProcessable {
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
public boolean checkCanEnterCluster(String clusterName) {
|
||||
if (checkGlobalPriv(PrivPredicate.ALL)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (dbPrivTable.hasClusterPriv(clusterName)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (tablePrivTable.hasClusterPriv(clusterName)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private void grantPrivs(ResourcePattern resourcePattern, PrivBitSet privs) throws DdlException {
|
||||
if (privs.isEmpty()) {
|
||||
return;
|
||||
|
||||
@ -198,7 +198,7 @@ public class RoleManager implements Writable, GsonPostProcessable {
|
||||
if (limitedRole != null && !limitedRole.contains(role.getRoleName())) {
|
||||
continue;
|
||||
}
|
||||
String isGrantable = role.checkGlobalPriv(PrivPredicate.ADMIN) ? "YES" : "NO";
|
||||
String isGrantable = role.checkGlobalPriv(PrivPredicate.ADMIN, PrivBitSet.of()) ? "YES" : "NO";
|
||||
|
||||
for (Map.Entry<WorkloadGroupPattern, PrivBitSet> entry : role.getWorkloadGroupPatternToPrivs().entrySet()) {
|
||||
List<String> row = Lists.newArrayList();
|
||||
|
||||
@ -21,6 +21,7 @@ suite("test_grant_priv") {
|
||||
def user1 = 'test_grant_priv_user1'
|
||||
def user2 = 'test_grant_priv_user2'
|
||||
def role1 = 'test_grant_priv_role1'
|
||||
def role2 = 'test_grant_priv_role2'
|
||||
def pwd = '123456'
|
||||
def dbName = 'test_grant_priv_db'
|
||||
def tokens = context.config.jdbcUrl.split('/')
|
||||
@ -29,6 +30,7 @@ suite("test_grant_priv") {
|
||||
sql """drop user if exists ${user1}"""
|
||||
sql """drop user if exists ${user2}"""
|
||||
sql """drop role if exists ${role1}"""
|
||||
sql """drop role if exists ${role2}"""
|
||||
sql """DROP DATABASE IF EXISTS ${dbName}"""
|
||||
|
||||
sql """CREATE DATABASE ${dbName}"""
|
||||
@ -82,5 +84,41 @@ suite("test_grant_priv") {
|
||||
sql """drop user if exists ${user1}"""
|
||||
sql """drop user if exists ${user2}"""
|
||||
sql """drop role if exists ${role1}"""
|
||||
sql """drop role if exists ${role2}"""
|
||||
|
||||
sql """CREATE ROLE ${role1}"""
|
||||
sql """CREATE ROLE ${role2}"""
|
||||
sql """CREATE USER '${user1}' IDENTIFIED BY '${pwd}'"""
|
||||
// for login
|
||||
sql """grant select_priv on ${dbName}.* to ${user1}"""
|
||||
sql """CREATE USER '${user2}' IDENTIFIED BY '${pwd}'"""
|
||||
sql """grant grant_priv on *.*.* to role '${role1}'"""
|
||||
sql """grant select_priv on *.*.* to role '${role2}'"""
|
||||
sql """grant '${role1}' to ${user1}"""
|
||||
// test only have role1 can not grant
|
||||
connect(user1, "${pwd}", url) {
|
||||
test {
|
||||
sql """grant select_priv on *.*.* to ${user2}"""
|
||||
exception "denied"
|
||||
}
|
||||
}
|
||||
sql """revoke '${role1}' from ${user1}"""
|
||||
sql """grant '${role2}' to ${user1}"""
|
||||
// test only have role2 can not grant
|
||||
connect(user1, "${pwd}", url) {
|
||||
test {
|
||||
sql """grant select_priv on *.*.* to ${user2}"""
|
||||
exception "denied"
|
||||
}
|
||||
}
|
||||
// test both have role1 and role2 can grant to other
|
||||
sql """grant '${role1}' to ${user1}"""
|
||||
connect(user1, "${pwd}", url) {
|
||||
sql """grant select_priv on *.*.* to ${user2}"""
|
||||
}
|
||||
sql """drop user if exists ${user1}"""
|
||||
sql """drop user if exists ${user2}"""
|
||||
sql """drop role if exists ${role1}"""
|
||||
sql """drop role if exists ${role2}"""
|
||||
sql """DROP DATABASE IF EXISTS ${dbName}"""
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user