[opt](ranger) modify and enhance the feature of ranger access controller (#34392) (#34426)

bp #34392
This commit is contained in:
Mingyu Chen
2024-05-06 17:08:47 +08:00
committed by GitHub
parent ab5ee81811
commit 3cb0deae9c
8 changed files with 297 additions and 15 deletions

View File

@ -68,7 +68,6 @@ public abstract class RangerAccessController implements CatalogAccessController
}
}
public static void checkRequestResults(Collection<RangerAccessResult> results, String name)
throws AuthorizationException {
for (RangerAccessResult result : results) {
@ -82,7 +81,8 @@ public abstract class RangerAccessController implements CatalogAccessController
throw new AuthorizationException(String.format(
"Permission denied: user [%s] does not have privilege for [%s] command on [%s]",
result.getAccessRequest().getUser(), name,
result.getAccessRequest().getResource().getAsString().replaceAll("/", ".")));
Optional.ofNullable(result.getAccessRequest().getResource().getAsString())
.orElse("unknown resource").replaceAll("/", ".")));
}
}
}
@ -135,12 +135,27 @@ public abstract class RangerAccessController implements CatalogAccessController
if (StringUtils.isEmpty(maskType)) {
return Optional.empty();
}
String transformer = policy.getMaskTypeDef().getTransformer();
if (StringUtils.isEmpty(transformer)) {
return Optional.empty();
switch (maskType) {
case "MASK_NULL":
return Optional.of(new RangerDataMaskPolicy(currentUser, ctl, db, tbl, col, policy.getPolicyId(),
policy.getPolicyVersion(), maskType, "NULL"));
case "MASK_NONE":
return Optional.empty();
case "CUSTOM":
String maskedValue = policy.getMaskedValue();
if (StringUtils.isEmpty(maskedValue)) {
return Optional.empty();
}
return Optional.of(new RangerDataMaskPolicy(currentUser, ctl, db, tbl, col, policy.getPolicyId(),
policy.getPolicyVersion(), maskType, maskedValue.replace("{col}", col)));
default:
String transformer = policy.getMaskTypeDef().getTransformer();
if (StringUtils.isEmpty(transformer)) {
return Optional.empty();
}
return Optional.of(new RangerDataMaskPolicy(currentUser, ctl, db, tbl, col, policy.getPolicyId(),
policy.getPolicyVersion(), maskType, transformer.replace("{col}", col)));
}
return Optional.of(new RangerDataMaskPolicy(currentUser, ctl, db, tbl, col, policy.getPolicyId(),
policy.getPolicyVersion(), maskType, transformer.replace("{col}", col)));
}
protected abstract RangerAccessRequestImpl createRequest(UserIdentity currentUser);

View File

@ -46,9 +46,11 @@ public enum DorisAccessType {
} else if (priv == PrivPredicate.SHOW_VIEW) {
return SHOW_VIEW;
} else if (priv == PrivPredicate.SHOW_RESOURCES) {
return SHOW_RESOURCES;
// For Ranger, there is only USAGE priv for RESOURCE and WORKLOAD_GROUP.
// So when checking SHOW_XXX priv, convert it to USAGE priv and pass to Ranger.
return USAGE;
} else if (priv == PrivPredicate.SHOW_WORKLOAD_GROUP) {
return SHOW_WORKLOAD_GROUP;
return USAGE;
} else if (priv == PrivPredicate.GRANT) {
return GRANT;
} else if (priv == PrivPredicate.ADMIN) {

View File

@ -23,7 +23,9 @@ import org.apache.doris.catalog.authorizer.ranger.RangerAccessController;
import org.apache.doris.cluster.ClusterNamespace;
import org.apache.doris.common.AuthorizationException;
import org.apache.doris.mysql.privilege.PrivPredicate;
import org.apache.doris.resource.workloadgroup.WorkloadGroupMgr;
import com.google.common.annotations.VisibleForTesting;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
@ -41,7 +43,7 @@ import java.util.stream.Collectors;
public class RangerDorisAccessController extends RangerAccessController {
private static final Logger LOG = LogManager.getLogger(RangerDorisAccessController.class);
private RangerDorisPlugin dorisPlugin;
private RangerBasePlugin dorisPlugin;
// private static ScheduledThreadPoolExecutor logFlushTimer = ThreadPoolManager.newDaemonScheduledThreadPool(1,
// "ranger-doris-audit-log-flusher-timer", true);
// private RangerHiveAuditHandler auditHandler;
@ -53,6 +55,11 @@ public class RangerDorisAccessController extends RangerAccessController {
// logFlushTimer.scheduleAtFixedRate(new RangerHiveAuditLogFlusher(auditHandler), 10, 20L, TimeUnit.SECONDS);
}
@VisibleForTesting
public RangerDorisAccessController(RangerBasePlugin plugin) {
dorisPlugin = plugin;
}
private RangerAccessRequestImpl createRequest(UserIdentity currentUser, DorisAccessType accessType) {
RangerAccessRequestImpl request = createRequest(currentUser);
request.setAction(accessType.name());
@ -117,6 +124,10 @@ public class RangerDorisAccessController extends RangerAccessController {
@Override
public boolean checkDbPriv(UserIdentity currentUser, String ctl, String db, PrivPredicate wanted) {
boolean res = checkCtlPriv(currentUser, ctl, wanted);
if (res) {
return true;
}
RangerDorisResource resource = new RangerDorisResource(DorisObjectType.DATABASE, ctl,
ClusterNamespace.getNameFromFullName(db));
return checkPrivilege(currentUser, DorisAccessType.toAccessType(wanted), resource);
@ -124,6 +135,11 @@ public class RangerDorisAccessController extends RangerAccessController {
@Override
public boolean checkTblPriv(UserIdentity currentUser, String ctl, String db, String tbl, PrivPredicate wanted) {
boolean res = checkDbPriv(currentUser, ctl, db, wanted);
if (res) {
return true;
}
RangerDorisResource resource = new RangerDorisResource(DorisObjectType.TABLE,
ctl, ClusterNamespace.getNameFromFullName(db), tbl);
return checkPrivilege(currentUser, DorisAccessType.toAccessType(wanted), resource);
@ -132,6 +148,11 @@ public class RangerDorisAccessController extends RangerAccessController {
@Override
public void checkColsPriv(UserIdentity currentUser, String ctl, String db, String tbl, Set<String> cols,
PrivPredicate wanted) throws AuthorizationException {
boolean res = checkTblPriv(currentUser, ctl, db, tbl, wanted);
if (res) {
return;
}
List<RangerDorisResource> resources = new ArrayList<>();
for (String col : cols) {
RangerDorisResource resource = new RangerDorisResource(DorisObjectType.COLUMN,
@ -150,6 +171,10 @@ public class RangerDorisAccessController extends RangerAccessController {
@Override
public boolean checkWorkloadGroupPriv(UserIdentity currentUser, String workloadGroupName, PrivPredicate wanted) {
// 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;
}
RangerDorisResource resource = new RangerDorisResource(DorisObjectType.WORKLOAD_GROUP, workloadGroupName);
return checkPrivilege(currentUser, DorisAccessType.toAccessType(wanted), resource);
}

View File

@ -184,7 +184,9 @@ public class RangerHiveAccessController extends RangerAccessController {
@Override
public boolean checkWorkloadGroupPriv(UserIdentity currentUser, String workloadGroupName, PrivPredicate wanted) {
return false;
// Not support workload group privilege in ranger hive plugin.
// So always return true to pass the check
return true;
}
@Override

View File

@ -55,8 +55,15 @@ public class PrintableMap<K, V> {
SENSITIVE_KEY.add("bos_secret_accesskey");
SENSITIVE_KEY.add("jdbc.password");
SENSITIVE_KEY.add("elasticsearch.password");
SENSITIVE_KEY.addAll(Arrays.asList(S3Properties.SECRET_KEY, ObsProperties.SECRET_KEY, OssProperties.SECRET_KEY,
GCSProperties.SECRET_KEY, CosProperties.SECRET_KEY, GlueProperties.SECRET_KEY, MCProperties.SECRET_KEY,
SENSITIVE_KEY.addAll(Arrays.asList(
S3Properties.SECRET_KEY,
S3Properties.Env.SECRET_KEY,
ObsProperties.SECRET_KEY,
OssProperties.SECRET_KEY,
GCSProperties.SECRET_KEY,
CosProperties.SECRET_KEY,
GlueProperties.SECRET_KEY,
MCProperties.SECRET_KEY,
DLFProperties.SECRET_KEY));
HIDDEN_KEY = Sets.newHashSet();
HIDDEN_KEY.addAll(S3Properties.Env.FS_KEYS);

View File

@ -386,12 +386,13 @@ public class Auth implements Writable {
public boolean checkWorkloadGroupPriv(UserIdentity currentUser, String workloadGroupName, PrivPredicate wanted) {
readLock();
try {
Set<Role> roles = getRolesByUserWithLdap(currentUser);
// currently stream load not support ip based auth, so normal should not auth temporary
// need remove later
if (WorkloadGroupMgr.DEFAULT_GROUP_NAME.equals(workloadGroupName)) {
return true;
}
Set<Role> roles = getRolesByUserWithLdap(currentUser);
for (Role role : roles) {
if (role.checkWorkloadGroupPriv(workloadGroupName, wanted)) {
return true;

View File

@ -68,7 +68,7 @@ public class DateTrunc extends ScalarFunction
final String constParam = ((VarcharLiteral) getArgument(1)).getStringValue().toLowerCase();
if (!Lists.newArrayList("year", "quarter", "month", "week", "day", "hour", "minute", "second")
.contains(constParam)) {
throw new AnalysisException("date_trunc function second param only support argument is"
throw new AnalysisException("date_trunc function second param only support argument is "
+ "year|quarter|month|week|day|hour|minute|second");
}
}