jerqi commented on code in PR #6100:
URL: https://github.com/apache/gravitino/pull/6100#discussion_r1903750541
##########
authorizations/authorization-common/src/main/java/org/apache/gravitino/authorization/common/PathBasedMetadataObject.java:
##########
@@ -94,4 +96,37 @@ public void validateAuthorizationMetadataObject() throws
IllegalArgumentExceptio
name != null, "Cannot create a path based metadata object with null
name");
}
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (!(o instanceof PathBasedMetadataObject)) {
+ return false;
+ }
+
+ PathBasedMetadataObject that = (PathBasedMetadataObject) o;
+ return java.util.Objects.equals(name, that.name)
+ && java.util.Objects.equals(parent, that.parent)
+ && java.util.Objects.equals(path, that.path)
+ && type == that.type;
+ }
+
+ @Override
+ public int hashCode() {
+ return java.util.Objects.hash(name, parent, path, type);
Review Comment:
Why do we need `java.util.Objects.hash` instead `Objects.hash`?
##########
api/src/main/java/org/apache/gravitino/authorization/MetadataObjectChange.java:
##########
@@ -44,10 +45,11 @@ static MetadataObjectChange rename(
* Remove a metadata entity MetadataObjectChange.
*
* @param metadataObject The metadata object.
+ * @param locations The locations of the metadata object.
* @return return a MetadataObjectChange for the remove metadata object.
*/
- static MetadataObjectChange remove(MetadataObject metadataObject) {
- return new RemoveMetadataObject(metadataObject);
+ static MetadataObjectChange remove(MetadataObject metadataObject,
List<String> locations) {
Review Comment:
@xunliu Left comment.
##########
authorizations/authorization-chain/src/test/java/org/apache/gravitino/authorization/chain/integration/test/TestChainedAuthorizationIT.java:
##########
@@ -307,11 +367,6 @@ void testChangeOwner() throws InterruptedException {
// TODO
}
- @Test
Review Comment:
Why do we remove this test case?
##########
authorizations/authorization-common/src/main/java/org/apache/gravitino/authorization/common/PathBasedMetadataObject.java:
##########
@@ -94,4 +96,37 @@ public void validateAuthorizationMetadataObject() throws
IllegalArgumentExceptio
name != null, "Cannot create a path based metadata object with null
name");
}
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (!(o instanceof PathBasedMetadataObject)) {
+ return false;
+ }
+
+ PathBasedMetadataObject that = (PathBasedMetadataObject) o;
+ return java.util.Objects.equals(name, that.name)
+ && java.util.Objects.equals(parent, that.parent)
+ && java.util.Objects.equals(path, that.path)
+ && type == that.type;
+ }
+
+ @Override
+ public int hashCode() {
+ return java.util.Objects.hash(name, parent, path, type);
+ }
+
+ @Override
+ public String toString() {
+ return "MetadataObject: [fullName="
+ + fullName()
+ + "], [path="
Review Comment:
Path may be null if metadata object is table or schema.
##########
authorizations/authorization-ranger/src/main/java/org/apache/gravitino/authorization/ranger/RangerAuthorizationHDFSPlugin.java:
##########
@@ -118,27 +128,310 @@ public List<String> policyResourceDefinesRule() {
return ImmutableList.of(RangerDefines.PolicyResource.PATH.getName());
}
+ String getAuthorizationPath(PathBasedMetadataObject pathBasedMetadataObject)
{
+ return HDFS_PATTERN.matcher(pathBasedMetadataObject.path()).replaceAll("");
+ }
+
+ /**
+ * Find the managed policy for the ranger securable object.
+ *
+ * @param authzMetadataObject The ranger securable object to find the
managed policy.
+ * @return The managed policy for the metadata object.
+ */
+ public RangerPolicy findManagedPolicy(AuthorizationMetadataObject
authzMetadataObject)
+ throws AuthorizationPluginException {
+ List<RangerPolicy> policies = wildcardSearchPolies(authzMetadataObject);
+ if (!policies.isEmpty()) {
+ /**
+ * Because Ranger doesn't support the precise search, Ranger will return
the policy meets the
+ * wildcard(*,?) conditions, If you use `/a/b` condition to search
policy, the Ranger will
+ * match `/a/b1`, `/a/b2`, `/a/b*`, So we need to manually precisely
filter this research
+ * results.
+ */
+ List<String> nsMetadataObj = authzMetadataObject.names();
+ PathBasedMetadataObject pathAuthzMetadataObject =
+ (PathBasedMetadataObject) authzMetadataObject;
+ Map<String, String> preciseFilters = new HashMap<>();
+ for (int i = 0; i < nsMetadataObj.size() && i <
policyResourceDefinesRule().size(); i++) {
+ preciseFilters.put(
+ policyResourceDefinesRule().get(i),
getAuthorizationPath(pathAuthzMetadataObject));
+ }
+ policies =
+ policies.stream()
+ .filter(
+ policy ->
+ policy.getResources().entrySet().stream()
+ .allMatch(
+ entry ->
+ preciseFilters.containsKey(entry.getKey())
+ && entry.getValue().getValues().size()
== 1
+ && entry
+ .getValue()
+ .getValues()
+
.contains(preciseFilters.get(entry.getKey()))))
+ .collect(Collectors.toList());
+ }
+ // Only return the policies that are managed by Gravitino.
+ if (policies.size() > 1) {
+ throw new AuthorizationPluginException("Each metadata object can have at
most one policy.");
+ }
+
+ if (policies.isEmpty()) {
+ return null;
+ }
+
+ RangerPolicy policy = policies.get(0);
+ // Delegating Gravitino management policies cannot contain duplicate
privilege
+ policy.getPolicyItems().forEach(RangerHelper::checkPolicyItemAccess);
+ policy.getDenyPolicyItems().forEach(RangerHelper::checkPolicyItemAccess);
+
policy.getRowFilterPolicyItems().forEach(RangerHelper::checkPolicyItemAccess);
+
policy.getDataMaskPolicyItems().forEach(RangerHelper::checkPolicyItemAccess);
+
+ return policy;
+ }
+
+ @Override
+ /** Wildcard search the Ranger policies in the different Ranger service. */
+ protected List<RangerPolicy> wildcardSearchPolies(
+ AuthorizationMetadataObject authzMetadataObject) {
+ Preconditions.checkArgument(authzMetadataObject instanceof
PathBasedMetadataObject);
+ PathBasedMetadataObject pathBasedMetadataObject =
(PathBasedMetadataObject) authzMetadataObject;
+ List<String> resourceDefines = policyResourceDefinesRule();
+ Map<String, String> searchFilters = new HashMap<>();
+ searchFilters.put(SearchFilter.SERVICE_NAME, rangerServiceName);
+ resourceDefines.stream()
+ .forEach(
+ resourceDefine -> {
+ searchFilters.put(
+ SearchFilter.RESOURCE_PREFIX + resourceDefine,
+ getAuthorizationPath(pathBasedMetadataObject));
+ });
+ try {
+ return rangerClient.findPolicies(searchFilters);
+ } catch (RangerServiceException e) {
+ throw new AuthorizationPluginException(e, "Failed to find the policies
in the Ranger");
+ }
+ }
+
+ /**
+ * IF rename the SCHEMA, Need to rename these the relevant policies,
`{schema}`, `{schema}.*`,
+ * `{schema}.*.*` <br>
+ * IF rename the TABLE, Need to rename these the relevant policies,
`{schema}.*`, `{schema}.*.*`
+ * <br>
+ */
+ @Override
+ protected void doRenameMetadataObject(
+ AuthorizationMetadataObject authzMetadataObject,
+ AuthorizationMetadataObject newAuthzMetadataObject) {
+ Preconditions.checkArgument(
+ authzMetadataObject instanceof PathBasedMetadataObject,
+ "The metadata object must be a PathBasedMetadataObject");
+ Preconditions.checkArgument(
+ newAuthzMetadataObject instanceof PathBasedMetadataObject,
+ "The metadata object must be a PathBasedMetadataObject");
+ updatePolicyByMetadataObject(
+ newAuthzMetadataObject.type().metadataObjectType(),
+ authzMetadataObject,
+ newAuthzMetadataObject);
+ }
+
+ @Override
+ protected void updatePolicyByMetadataObject(
+ MetadataObject.Type operationType,
+ AuthorizationMetadataObject oldAuthzMetaobject,
+ AuthorizationMetadataObject newAuthzMetaobject) {
+ PathBasedMetadataObject newPathBasedMetadataObject =
+ (PathBasedMetadataObject) newAuthzMetaobject;
+ List<RangerPolicy> oldPolicies = wildcardSearchPolies(oldAuthzMetaobject);
+ List<RangerPolicy> existNewPolicies =
wildcardSearchPolies(newAuthzMetaobject);
+ if (oldPolicies.isEmpty()) {
+ LOG.warn("Cannot find the Ranger policy for the metadata object({})!",
oldAuthzMetaobject);
+ return;
+ }
+ if (!existNewPolicies.isEmpty()) {
+ LOG.warn("The Ranger policy for the metadata object({}) already
exists!", newAuthzMetaobject);
+ }
+ oldPolicies.stream()
+ .forEach(
+ policy -> {
+ try {
+ // Update the policy name is following Gravitino's spec
+
policy.setName(getAuthorizationPath(newPathBasedMetadataObject));
+ // Update the policy resource name to new name
+ policy
+ .getResources()
+ .put(
+ rangerHelper.policyResourceDefines.get(0),
+ new RangerPolicy.RangerPolicyResource(
+ getAuthorizationPath(newPathBasedMetadataObject)));
+
+ boolean alreadyExist =
+ existNewPolicies.stream()
+ .anyMatch(
+ existNewPolicy ->
+
existNewPolicy.getName().equals(policy.getName())
+ ||
existNewPolicy.getResources().equals(policy.getResources()));
+ if (alreadyExist) {
+ LOG.warn(
+ "The Ranger policy for the metadata object({}) already
exists!",
+ newAuthzMetaobject);
+ return;
+ }
+
+ // Update the policy
+ rangerClient.updatePolicy(policy.getId(), policy);
+ } catch (RangerServiceException e) {
+ LOG.error("Failed to rename the policy {}!", policy);
+ throw new RuntimeException(e);
+ }
+ });
+ }
+
+ /**
+ * IF remove the SCHEMA, need to remove these the relevant policies,
`{schema}`, `{schema}.*`,
+ * `{schema}.*.*` <br>
+ * IF remove the TABLE, need to remove these the relevant policies,
`{schema}.*`, `{schema}.*.*`
+ * <br>
+ * IF remove the COLUMN, Only need to remove `{schema}.*.*` <br>
+ */
+ @Override
+ protected void doRemoveMetadataObject(AuthorizationMetadataObject
authzMetadataObject) {
+ if (authzMetadataObject.type().equals(SCHEMA)) {
+ doRemoveSchemaMetadataObject(authzMetadataObject);
+ } else if (authzMetadataObject.type().equals(TABLE)) {
+ doRemoveTableMetadataObject(authzMetadataObject);
+ } else if (authzMetadataObject.type().equals(COLUMN)
+ || authzMetadataObject.type().equals(PATH)) {
+ removePolicyByMetadataObject(authzMetadataObject);
+ } else {
+ throw new IllegalArgumentException(
+ "Unsupported authorization metadata object type: " +
authzMetadataObject.type());
+ }
+ }
+
+ /**
+ * Remove the SCHEMA, Need to remove these the relevant policies,
`{schema}`, `{schema}.*`,
+ * `{schema}.*.*` permissions.
+ */
+ private void doRemoveSchemaMetadataObject(AuthorizationMetadataObject
authzMetadataObject) {
+ Preconditions.checkArgument(
+ authzMetadataObject instanceof PathBasedMetadataObject,
+ "The metadata object must be a PathBasedMetadataObject");
+ Preconditions.checkArgument(
+ authzMetadataObject.type() == SCHEMA, "The metadata object type must
be SCHEMA");
+ Preconditions.checkArgument(
+ authzMetadataObject.names().size() == 1, "The metadata object names
must be 1");
+ if (RangerHelper.RESOURCE_ALL.equals(authzMetadataObject.name())) {
+ // Remove all schema in this catalog
+ NameIdentifier[] catalogs =
+
GravitinoEnv.getInstance().catalogDispatcher().listCatalogs(Namespace.of(metalake));
Review Comment:
Why do you need list Catalogs? This plugin is only in one catalog.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]