Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#5336] feat(auth-ranger): Remove MANAGED_BY_GRAVITINO limit and compatible for existing ranger policy #5629

Merged
merged 15 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,6 @@ public Boolean onGroupAcquired(Group group) {
*/
private boolean doAddSecurableObject(String roleName, RangerSecurableObject securableObject) {
RangerPolicy policy = rangerHelper.findManagedPolicy(securableObject);

if (policy != null) {
// Check the policy item's accesses and roles equal the Ranger securable object's privilege
List<RangerPrivilege> allowPrivilies =
Expand All @@ -621,15 +620,19 @@ private boolean doAddSecurableObject(String roleName, RangerSecurableObject secu

Set<RangerPrivilege> policyPrivileges =
policy.getPolicyItems().stream()
.filter(policyItem -> policyItem.getRoles().contains(roleName))
.filter(
policyItem ->
policyItem.getRoles().contains(rangerHelper.rangerRoleName(roleName)))
.flatMap(policyItem -> policyItem.getAccesses().stream())
.map(RangerPolicy.RangerPolicyItemAccess::getType)
.map(RangerPrivileges::valueOf)
.collect(Collectors.toSet());

Set<RangerPrivilege> policyDenyPrivileges =
policy.getDenyPolicyItems().stream()
.filter(policyItem -> policyItem.getRoles().contains(roleName))
.filter(
policyItem ->
policyItem.getRoles().contains(rangerHelper.rangerRoleName(roleName)))
.flatMap(policyItem -> policyItem.getAccesses().stream())
.map(RangerPolicy.RangerPolicyItemAccess::getType)
.map(RangerPrivileges::valueOf)
Expand Down Expand Up @@ -738,6 +741,7 @@ private void removePolicyItemIfEqualRoleName(
RangerPolicy.RangerPolicyItem policyItem,
RangerSecurableObject rangerSecurableObject,
String roleName) {
roleName = rangerHelper.rangerRoleName(roleName);
boolean match =
policyItem.getAccesses().stream()
.allMatch(
Expand Down Expand Up @@ -974,7 +978,23 @@ private void removePolicyByMetadataObject(List<String> metadataNames) {
.forEach(
policy -> {
try {
rangerClient.deletePolicy(policy.getId());
policy.setPolicyItems(
policy.getPolicyItems().stream()
.filter(i -> !rangerHelper.isGravitinoManagedPolicyItemAccess(i))
.collect(Collectors.toList()));
policy.setDenyPolicyItems(
policy.getDenyPolicyItems().stream()
.filter(i -> !rangerHelper.isGravitinoManagedPolicyItemAccess(i))
.collect(Collectors.toList()));
policy.setRowFilterPolicyItems(
policy.getRowFilterPolicyItems().stream()
.filter(i -> !rangerHelper.isGravitinoManagedPolicyItemAccess(i))
.collect(Collectors.toList()));
policy.setDataMaskPolicyItems(
policy.getDataMaskPolicyItems().stream()
.filter(i -> !rangerHelper.isGravitinoManagedPolicyItemAccess(i))
.collect(Collectors.toList()));
rangerClient.updatePolicy(policy.getId(), policy);
} catch (RangerServiceException e) {
LOG.error("Failed to rename the policy {}!", policy);
throw new RuntimeException(e);
Expand Down Expand Up @@ -1003,25 +1023,29 @@ private void updatePolicyByMetadataObject(
.forEach(
policy -> {
try {
// Update the policy name
String policyName = policy.getName();
List<String> policyNames = Lists.newArrayList(DOT_SPLITTER.splitToList(policyName));
Preconditions.checkArgument(
policyNames.size() >= oldMetadataNames.size(),
String.format("The policy name(%s) is invalid!", policyName));
int index = operationTypeIndex.get(operationType);
if (policyNames.get(index).equals(RangerHelper.RESOURCE_ALL)) {
// Doesn't need to rename the policy `*`
return;

// Update the policy name is following Gravitino's spec
if (policy.getName().equals(DOT_JOINER.join(oldMetadataNames))) {
List<String> policyNames =
Lists.newArrayList(DOT_SPLITTER.splitToList(policyName));
Preconditions.checkArgument(
policyNames.size() >= oldMetadataNames.size(),
String.format("The policy name(%s) is invalid!", policyName));
if (policyNames.get(index).equals(RangerHelper.RESOURCE_ALL)) {
// Doesn't need to rename the policy `*`
return;
}
policyNames.set(index, newMetadataNames.get(index));
policy.setName(DOT_JOINER.join(policyNames));
}
policyNames.set(index, newMetadataNames.get(index));
// Update the policy resource name to new name
policy
.getResources()
.put(
rangerHelper.policyResourceDefines.get(index),
new RangerPolicy.RangerPolicyResource(newMetadataNames.get(index)));
policy.setName(DOT_JOINER.join(policyNames));

boolean alreadyExist =
existNewPolicies.stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
package org.apache.gravitino.authorization.ranger;

import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import java.util.HashMap;
import java.util.HashSet;
Expand Down Expand Up @@ -61,6 +60,8 @@ public class RangerHelper {
public static final String GRAVITINO_METALAKE_OWNER_ROLE = "GRAVITINO_METALAKE_OWNER_ROLE";
public static final String GRAVITINO_CATALOG_OWNER_ROLE = "GRAVITINO_CATALOG_OWNER_ROLE";

public static final String GRAVITINO_ROLE_PREFIX = "GRAVITINO_";

public RangerHelper(
RangerClient rangerClient,
String rangerAdminName,
Expand Down Expand Up @@ -142,7 +143,7 @@ void addPolicyItem(RangerPolicy policy, String roleName, RangerSecurableObject s
new RangerPolicy.RangerPolicyItemAccess();
access.setType(rangerPrivilege.getName());
policyItem.getAccesses().add(access);
policyItem.getRoles().add(roleName);
policyItem.getRoles().add(GRAVITINO_ROLE_PREFIX + roleName);
theoryxu marked this conversation as resolved.
Show resolved Hide resolved
if (Privilege.Condition.ALLOW == rangerPrivilege.condition()) {
policy.getPolicyItems().add(policyItem);
} else {
Expand All @@ -154,8 +155,8 @@ void addPolicyItem(RangerPolicy policy, String roleName, RangerSecurableObject s
.forEach(
policyItem -> {
// If the role is not in the policy item, then add it
if (!policyItem.getRoles().contains(roleName)) {
policyItem.getRoles().add(roleName);
if (!policyItem.getRoles().contains(GRAVITINO_ROLE_PREFIX + roleName)) {
policyItem.getRoles().add(GRAVITINO_ROLE_PREFIX + roleName);
theoryxu marked this conversation as resolved.
Show resolved Hide resolved
}
});
}
Expand All @@ -172,7 +173,6 @@ public List<RangerPolicy> wildcardSearchPolies(List<String> metadataNames)
throws AuthorizationPluginException {
Map<String, String> searchFilters = new HashMap<>();
searchFilters.put(SearchFilter.SERVICE_NAME, rangerServiceName);
searchFilters.put(SearchFilter.POLICY_LABELS_PARTIAL, MANAGED_BY_GRAVITINO);
for (int i = 0; i < metadataNames.size(); i++) {
searchFilters.put(
SearchFilter.RESOURCE_PREFIX + policyResourceDefines.get(i), metadataNames.get(i));
Expand Down Expand Up @@ -224,8 +224,7 @@ public RangerPolicy findManagedPolicy(RangerMetadataObject rangerMetadataObject)
}
// Only return the policies that are managed by Gravitino.
if (policies.size() > 1) {
throw new AuthorizationPluginException(
"Every metadata object has only a Gravitino managed policy.");
throw new AuthorizationPluginException("Each metadata object can have at most one policy.");
}

if (policies.isEmpty()) {
Expand All @@ -234,15 +233,28 @@ public RangerPolicy findManagedPolicy(RangerMetadataObject rangerMetadataObject)

RangerPolicy policy = policies.get(0);
// Delegating Gravitino management policies cannot contain duplicate privilege
policy.getPolicyItems().forEach(this::checkPolicyItemAccess);
policy.getDenyPolicyItems().forEach(this::checkPolicyItemAccess);
policy.getRowFilterPolicyItems().forEach(this::checkPolicyItemAccess);
policy.getDataMaskPolicyItems().forEach(this::checkPolicyItemAccess);
policy.getPolicyItems().stream()
.filter(this::isGravitinoManagedPolicyItemAccess)
.forEach(this::checkPolicyItemAccess);
policy.getDenyPolicyItems().stream()
.filter(this::isGravitinoManagedPolicyItemAccess)
.forEach(this::checkPolicyItemAccess);
policy.getRowFilterPolicyItems().stream()
.filter(this::isGravitinoManagedPolicyItemAccess)
.forEach(this::checkPolicyItemAccess);
policy.getDataMaskPolicyItems().stream()
.filter(this::isGravitinoManagedPolicyItemAccess)
.forEach(this::checkPolicyItemAccess);

return policy;
}

boolean isGravitinoManagedPolicyItemAccess(RangerPolicy.RangerPolicyItem policyItem) {
return policyItem.getRoles().stream().anyMatch(role -> role.startsWith(GRAVITINO_ROLE_PREFIX));
}

protected boolean checkRangerRole(String roleName) throws AuthorizationPluginException {
roleName = rangerRoleName(roleName);
try {
rangerClient.getRole(roleName, rangerAdminName, rangerServiceName);
} catch (RangerServiceException e) {
Expand All @@ -252,8 +264,16 @@ protected boolean checkRangerRole(String roleName) throws AuthorizationPluginExc
return true;
}

String rangerRoleName(String roleName) {
theoryxu marked this conversation as resolved.
Show resolved Hide resolved
if (roleName.startsWith(GRAVITINO_ROLE_PREFIX)) {
return roleName;
}
return GRAVITINO_ROLE_PREFIX + roleName;
}

protected GrantRevokeRoleRequest createGrantRevokeRoleRequest(
String roleName, String userName, String groupName) {
roleName = rangerRoleName(roleName);
Set<String> users =
StringUtils.isEmpty(userName) ? Sets.newHashSet() : Sets.newHashSet(userName);
Set<String> groups =
Expand All @@ -278,6 +298,7 @@ protected GrantRevokeRoleRequest createGrantRevokeRoleRequest(
* @param isOwnerRole The role is owner role or not
*/
protected RangerRole createRangerRoleIfNotExists(String roleName, boolean isOwnerRole) {
roleName = rangerRoleName(roleName);
if (isOwnerRole) {
Preconditions.checkArgument(
roleName.equalsIgnoreCase(GRAVITINO_METALAKE_OWNER_ROLE)
Expand Down Expand Up @@ -385,7 +406,6 @@ protected RangerPolicy createPolicyAddResources(RangerMetadataObject metadataObj
RangerPolicy policy = new RangerPolicy();
policy.setService(rangerServiceName);
policy.setName(metadataObject.fullName());
policy.setPolicyLabels(Lists.newArrayList(RangerHelper.MANAGED_BY_GRAVITINO));
theoryxu marked this conversation as resolved.
Show resolved Hide resolved
List<String> nsMetadataObject = metadataObject.names();
for (int i = 0; i < nsMetadataObject.size(); i++) {
RangerPolicy.RangerPolicyResource policyResource =
Expand Down Expand Up @@ -428,7 +448,7 @@ protected RangerPolicy addOwnerRoleToNewPolicy(
policyItem
.getAccesses()
.add(new RangerPolicy.RangerPolicyItemAccess(ownerPrivilege.getName()));
policyItem.getRoles().add(ownerRoleName);
policyItem.getRoles().add(rangerRoleName(ownerRoleName));
policy.getPolicyItems().add(policyItem);
});
return policy;
Expand All @@ -454,8 +474,8 @@ protected void updatePolicyOwnerRole(RangerPolicy policy, String ownerRoleName)
// Add or remove the owner role in the policy item
matchPolicyItems.forEach(
policyItem -> {
if (!policyItem.getRoles().contains(ownerRoleName)) {
policyItem.getRoles().add(ownerRoleName);
if (!policyItem.getRoles().contains(rangerRoleName(ownerRoleName))) {
policyItem.getRoles().add(rangerRoleName(ownerRoleName));
}
});

Expand All @@ -480,8 +500,8 @@ protected void updatePolicyOwnerRole(RangerPolicy policy, String ownerRoleName)
policyItem
.getAccesses()
.add(new RangerPolicy.RangerPolicyItemAccess(ownerPrivilege.getName()));
if (!policyItem.getRoles().contains(ownerRoleName)) {
policyItem.getRoles().add(ownerRoleName);
if (!policyItem.getRoles().contains(rangerRoleName(ownerRoleName))) {
policyItem.getRoles().add(rangerRoleName(ownerRoleName));
theoryxu marked this conversation as resolved.
Show resolved Hide resolved
}
policy.getPolicyItems().add(policyItem);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -327,20 +327,16 @@ public void testFindManagedPolicy() {
String dbName = currentFunName();
createHivePolicy(
Lists.newArrayList(String.format("%s*", dbName), "*"),
GravitinoITUtils.genRandomName(currentFunName()),
true);
GravitinoITUtils.genRandomName(currentFunName()));
createHivePolicy(
Lists.newArrayList(String.format("%s*", dbName), "tab*"),
GravitinoITUtils.genRandomName(currentFunName()),
true);
GravitinoITUtils.genRandomName(currentFunName()));
createHivePolicy(
Lists.newArrayList(String.format("%s3", dbName), "*"),
GravitinoITUtils.genRandomName(currentFunName()),
true);
GravitinoITUtils.genRandomName(currentFunName()));
createHivePolicy(
Lists.newArrayList(String.format("%s3", dbName), "tab*"),
GravitinoITUtils.genRandomName(currentFunName()),
true);
GravitinoITUtils.genRandomName(currentFunName()));
// findManagedPolicy function use precise search, so return null
RangerSecurableObject rangerSecurableObject =
rangerAuthHivePlugin.generateRangerSecurableObject(
Expand All @@ -354,8 +350,7 @@ public void testFindManagedPolicy() {
// Add a policy for `db3.tab1`
createHivePolicy(
Lists.newArrayList(String.format("%s3", dbName), "tab1"),
GravitinoITUtils.genRandomName(currentFunName()),
true);
GravitinoITUtils.genRandomName(currentFunName()));
// findManagedPolicy function use precise search, so return not null
Assertions.assertNotNull(rangerHelper.findManagedPolicy(rangerSecurableObject));
}
Expand All @@ -372,15 +367,14 @@ public void testManagedByGravitinoLabel() {
SecurableObjects.DOT_SPLITTER.splitToList(securableObject.fullName()));
names.remove(0); // remove catalog node
// Manual create the Ranger Policy
createHivePolicy(Lists.newArrayList(names), DOT_JOINER.join(names), false);
createHivePolicy(Lists.newArrayList(names), DOT_JOINER.join(names));
});
// Use role to create Ranger Policy
Assertions.assertThrows(
AuthorizationPluginException.class, () -> rangerAuthHivePlugin.onRoleCreated(role));
}

static void createHivePolicy(
List<String> metaObjects, String roleName, boolean labelManagedByGravitino) {
static void createHivePolicy(List<String> metaObjects, String roleName) {
Assertions.assertTrue(metaObjects.size() < 4);
Map<String, RangerPolicy.RangerPolicyResource> policyResourceMap = new HashMap<>();
for (int i = 0; i < metaObjects.size(); i++) {
Expand All @@ -404,8 +398,7 @@ static void createHivePolicy(
RangerITEnv.RANGER_HIVE_REPO_NAME,
roleName,
policyResourceMap,
Collections.singletonList(policyItem),
labelManagedByGravitino);
Collections.singletonList(policyItem));
}

static boolean deleteHivePolicy(RangerSecurableObject rangerSecurableObject) {
Expand Down Expand Up @@ -808,20 +801,16 @@ void metadataObjectChangeRemoveMetalakeOrCatalog(String funcName, MetadataObject
throws RangerServiceException {
createHivePolicy(
Lists.newArrayList(String.format("%s*", funcName), "*"),
GravitinoITUtils.genRandomName(currentFunName()),
true);
GravitinoITUtils.genRandomName(currentFunName()));
createHivePolicy(
Lists.newArrayList(String.format("%s*", funcName), "tab*"),
GravitinoITUtils.genRandomName(currentFunName()),
true);
GravitinoITUtils.genRandomName(currentFunName()));
createHivePolicy(
Lists.newArrayList(String.format("%s3", funcName), "*"),
GravitinoITUtils.genRandomName(currentFunName()),
true);
GravitinoITUtils.genRandomName(currentFunName()));
createHivePolicy(
Lists.newArrayList(String.format("%s3", funcName), "tab*"),
GravitinoITUtils.genRandomName(currentFunName()),
true);
GravitinoITUtils.genRandomName(currentFunName()));
Assertions.assertEquals(
4, rangerClient.getPoliciesInService(RangerITEnv.RANGER_HIVE_REPO_NAME).size());

Expand Down Expand Up @@ -1764,7 +1753,6 @@ private void verifyRangerSecurableObjectInRanger(
}

Assertions.assertEquals(policy.getName(), policyName);
Assertions.assertTrue(policy.getPolicyLabels().contains(RangerHelper.MANAGED_BY_GRAVITINO));

// verify namespace
List<String> metaObjNamespaces = rangerSecurableObject.names();
Expand Down
Loading
Loading