-
Notifications
You must be signed in to change notification settings - Fork 3k
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
feat(auth): add group membership field resolver provider #8846
feat(auth): add group membership field resolver provider #8846
Conversation
|
||
// 1. Fetch all policies | ||
final List<DataHubPolicyInfo> policiesToEvaluate = _policyCache.getOrDefault(ALL, new ArrayList<>()); | ||
|
||
Urn actorUrn = UrnUtils.getUrn(actor); | ||
final ResolvedResourceSpec actorResolvedResourceSpec = _resourceSpecResolver.resolve(new ResourceSpec(actorUrn.getEntityType(), actor)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see the idea here.. nice!
Do we need to resolve the resource spec at this point, or can we do it later on once we absolutely know that group membership is required. I want to make sure that we avoid making any additional lookups until we absolutely have to
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So there are two options:
- As it is implemented now, resolving the actor and pass it to the PolicyEngine. It is true that at this point we do not know if group membership is required. However, according to this line, no field is resolved until it is explicitly called/obtained.
- The other option implies passing the
_resourceSpecResolver
to the PolicyEngine class. The PolicyEngine class is initialized in the DatahubAuthorizer constructor while the_resourceSpecResolver
in the init function. So if we want to follow this approach, the PolicyEngine class should be initialized in the init method after the resolver. Not sure if this has any implications.
metadata-service/auth-impl/src/main/java/com/datahub/authorization/DataHubAuthorizer.java
Show resolved
Hide resolved
return false; | ||
} | ||
|
||
final ResolvedResourceSpec actorResolvedResourceSpec = _resourceSpecResolver.resolve( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same question as above here - is there any way we can pass down the ResourceSpec and simple resolve once we need to?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same answer applies here.
request.getPrivilege(), | ||
resourceSpec | ||
); | ||
return result.isGranted(); | ||
} | ||
|
||
private Optional<Urn> getUrnFromRequestActor(String actor) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we confirm that this will always be an urn from the caller? I don't think we have any cases where this will NOT be an urn, but want to make sure I'm not missing anything
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function was created as a result of moving logic that was already there. I think is highly improbable that this will NOT be an urn. If in agreement we can use UrnUtils.getUrn
instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fine - let's go with this.
I do think in future we will want to make the auth layer a bit more opinionated and work in the URN types instead of raw strings. That was probably a bad call initially
metadata-service/auth-impl/src/main/java/com/datahub/authorization/PolicyEngine.java
Outdated
Show resolved
Hide resolved
final Set<Urn> groups = resolveGroups(actor, context); | ||
return actorFilter.isAllGroups() || (actorFilter.hasGroups() && Objects.requireNonNull(actorFilter.getGroups()) | ||
.stream() | ||
final Set<String> groups = actorResolvedResourceSpec.getGroupMembership(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
metadata-service/auth-impl/src/main/java/com/datahub/authorization/PolicyEngine.java
Show resolved
Hide resolved
...va/com/datahub/authorization/fieldresolverprovider/GroupMembershipFieldResolverProvider.java
Show resolved
Hide resolved
/** | ||
* Groups of which the entity (only applies to corpUser) is a member | ||
*/ | ||
GROUP_MEMBERSHIP |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice!
metadata-service/auth-impl/src/main/java/com/datahub/authorization/PolicyEngine.java
Show resolved
Hide resolved
} | ||
|
||
public List<String> getGrantedPrivileges( | ||
final List<DataHubPolicyInfo> policies, | ||
final Urn actor, | ||
final Optional<ResolvedResourceSpec> resource) { | ||
final ResolvedEntitySpec resolvedActorSpec, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actor?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same answer as for the previous comment.
} | ||
|
||
/** | ||
* Returns true if the privilege portion of a DataHub policy matches a the privilege being evaluated, false otherwise. | ||
*/ | ||
private boolean isPrivilegeMatch( | ||
final String requestPrivilege, | ||
final List<String> policyPrivileges, | ||
final PolicyEvaluationContext context) { | ||
final List<String> policyPrivileges) { | ||
return policyPrivileges.contains(requestPrivilege); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thank u!
@@ -199,7 +175,7 @@ private boolean isResourceMatch( | |||
// No resource defined on the policy. | |||
return true; | |||
} | |||
if (!requestResource.isPresent()) { | |||
if (requestResource.isEmpty()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice!
@@ -218,31 +194,31 @@ private PolicyMatchFilter getFilter(DataHubResourceFilter policyResourceFilter) | |||
} | |||
PolicyMatchCriterionArray criteria = new PolicyMatchCriterionArray(); | |||
if (policyResourceFilter.hasType()) { | |||
criteria.add(new PolicyMatchCriterion().setField(ResourceFieldType.RESOURCE_TYPE.name()) | |||
criteria.add(new PolicyMatchCriterion().setField(EntityFieldType.TYPE.name()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice renaming. much cleane!
final DataHubActorFilter actorFilter, | ||
final Optional<ResolvedResourceSpec> resourceSpec, | ||
final Optional<ResolvedEntitySpec> resourceSpec, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seeing this, i am thinking we should always say "actorSpec" and "resourceSpec"
metadata-service/auth-impl/src/main/java/com/datahub/authorization/PolicyEngine.java
Show resolved
Hide resolved
when(_entityClient.batchGetV2(eq(CORP_USER_ENTITY_NAME), eq(Collections.singleton(unauthorizedUserUrn)), any(), | ||
any())).thenReturn(unauthorizedEntityResponseMap); | ||
when(_entityClient.batchGetV2(eq(CORP_USER_ENTITY_NAME), eq(Collections.singleton(unauthorizedUserUrn)), | ||
eq(Collections.singleton(ROLE_MEMBERSHIP_ASPECT_NAME)), any())).thenReturn(unauthorizedEntityResponseMap); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice improvements to the test!
@@ -1184,21 +1170,6 @@ private EntityResponse createUnauthorizedEntityResponse() throws URISyntaxExcept | |||
final EntityResponse entityResponse = new EntityResponse(); | |||
final EnvelopedAspectMap aspectMap = new EnvelopedAspectMap(); | |||
|
|||
final CorpUserInfo userInfo = new CorpUserInfo(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
strange that we were fetching this
/** | ||
* Field that this hydrator is hydrating | ||
*/ | ||
EntityFieldType getFieldType(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice renames!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once the conflicts are resolved, let's merge.
Nice work, @amanda-her !
Really appreciate all the hard work on this.
# Conflicts: # metadata-auth/auth-api/src/main/java/com/datahub/authorization/ResolvedResourceSpec.java # metadata-auth/auth-api/src/main/java/com/datahub/authorization/ResourceFieldType.java # metadata-service/auth-impl/src/main/java/com/datahub/authorization/DefaultResourceSpecResolver.java
Hello @jjoyce0510 . We have solved the merge conflicts and think the branch is ready to be merged. |
Merging through the flakes on the final smoke test. Unrelated to these changes. |
In this pull request the following topics have been addressed:
isGroupMatch
in PolicyEngine class to check that a user belongs to at least one group if policy applies to all groups.Checklist