Skip to content

Commit

Permalink
Onboard onto clusterPrivileges
Browse files Browse the repository at this point in the history
Signed-off-by: Derek Ho <dxho@amazon.com>
  • Loading branch information
derek-ho committed Dec 30, 2024
1 parent e39df0d commit ad63974
Showing 1 changed file with 56 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
Expand Down Expand Up @@ -323,6 +324,8 @@ static class ClusterPrivileges {

private final ImmutableSet<String> wellKnownClusterActions;

private final FlattenedActionGroups actionGroups;

/**
* Creates pre-computed cluster privileges based on the given parameters.
* <p>
Expand Down Expand Up @@ -399,6 +402,7 @@ static class ClusterPrivileges {
this.rolesWithWildcardPermissions = rolesWithWildcardPermissions.build();
this.rolesToActionMatcher = rolesToActionMatcher.build();
this.wellKnownClusterActions = wellKnownClusterActions;
this.actionGroups = actionGroups;
}

/**
Expand Down Expand Up @@ -432,17 +436,60 @@ PrivilegesEvaluatorResponse providesPrivilege(PrivilegesEvaluationContext contex
}

// 4: Evaluate api tokens
if (context.getUser().getName().startsWith("apitoken")) {
String jti = context.getUser().getName().split(":")[1];
log.info(context.getApiTokenIndexListenerCache().getJtis().get(jti).getClusterPerm().toString());
return providesClusterPrivilegeForApiToken(context, Set.of(action), false);
}

if (context.getApiTokenIndexListenerCache().getJtis().get(jti) != null
&& context.getApiTokenIndexListenerCache().getJtis().get(jti).getClusterPerm().contains(action)) {
/**
* Evaluates cluster privileges for api tokens. It does so by checking exact match, regex match, * match, and action group match in a non-optimized, naive way.
* First it expands all action groups to get all the actions and patterns of actions. Then it checks * if not an explicit check, then for exact match, then for pattern match.
*/
PrivilegesEvaluatorResponse providesClusterPrivilegeForApiToken(
PrivilegesEvaluationContext context,
Set<String> actions,
Boolean explicit
) {
String userName = context.getUser().getName();
String jti = context.getUser().getName().split(":")[1];
if (userName.startsWith("apitoken") && context.getApiTokenIndexListenerCache().getJtis().get(jti) != null) {
List<String> clusterPermissions = context.getApiTokenIndexListenerCache().getJtis().get(jti).getClusterPerm();
// Expand the action groups
ImmutableSet<String> resolvedClusterPermissions = actionGroups.resolve(
context.getApiTokenIndexListenerCache().getJtis().get(jti).getClusterPerm()
);
log.info(resolvedClusterPermissions);

// Check for wildcard permission
if (!explicit) {
if (resolvedClusterPermissions.contains("*")) {
return PrivilegesEvaluatorResponse.ok();
}
}

// Check for exact match
if (!Collections.disjoint(resolvedClusterPermissions, actions)) {
return PrivilegesEvaluatorResponse.ok();
}
}

return PrivilegesEvaluatorResponse.insufficient(action);
// Check for pattern matches (like "cluster:*")
for (String permission : resolvedClusterPermissions) {
// Skip exact matches as we already checked those
if (!permission.contains("*")) {
continue;
}

WildcardMatcher permissionMatcher = WildcardMatcher.from(permission);
for (String action : actions) {
if (permissionMatcher.test(action)) {
return PrivilegesEvaluatorResponse.ok();
}
}
}
}
if (actions.size() == 1) {
return PrivilegesEvaluatorResponse.insufficient(actions.iterator().next());
} else {
return PrivilegesEvaluatorResponse.insufficient("any of " + actions);
}
}

/**
Expand Down Expand Up @@ -475,15 +522,7 @@ PrivilegesEvaluatorResponse providesExplicitPrivilege(PrivilegesEvaluationContex
}
}

if (context.getUser().getName().startsWith("apitoken")) {
String jti = context.getUser().getName().split(":")[1];
if (context.getApiTokenIndexListenerCache().getJtis().get(jti) != null
&& context.getApiTokenIndexListenerCache().getJtis().get(jti).getClusterPerm().contains(action)) {
return PrivilegesEvaluatorResponse.ok();
}
}

return PrivilegesEvaluatorResponse.insufficient(action);
return providesClusterPrivilegeForApiToken(context, Set.of(action), true);
}

/**
Expand Down Expand Up @@ -519,19 +558,7 @@ PrivilegesEvaluatorResponse providesAnyPrivilege(PrivilegesEvaluationContext con
}
}

if (context.getUser().getName().startsWith("apitoken")) {
String jti = context.getUser().getName().split(":")[1];
if (context.getApiTokenIndexListenerCache().getJtis().get(jti) != null
&& context.getApiTokenIndexListenerCache().getJtis().get(jti).getClusterPerm().stream().anyMatch(actions::contains)) {
return PrivilegesEvaluatorResponse.ok();
}
}

if (actions.size() == 1) {
return PrivilegesEvaluatorResponse.insufficient(actions.iterator().next());
} else {
return PrivilegesEvaluatorResponse.insufficient("any of " + actions);
}
return providesClusterPrivilegeForApiToken(context, actions, false);
}
}

Expand Down

0 comments on commit ad63974

Please sign in to comment.