Skip to content

Commit

Permalink
review: move authZ targets into PolarisResolutionManifest
Browse files Browse the repository at this point in the history
  • Loading branch information
dimas-b committed Nov 30, 2024
1 parent 75841e7 commit c9b9545
Show file tree
Hide file tree
Showing 8 changed files with 202 additions and 295 deletions.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -490,14 +490,10 @@ public boolean matchesOrIsSubsumedBy(
public void authorizeOrThrow(
@Nonnull PolarisResolutionManifest manifest,
@Nonnull PolarisAuthorizableOperation authzOp,
@Nonnull ActivatedEntitySelector entitySelector,
@Nonnull List<AuthEntitySelector> targetSelectors,
@Nonnull List<AuthEntitySelector> secondarySelectors) {
boolean considerCatalogRoles) {

List<PolarisResolvedPathWrapper> targets =
targetSelectors.stream().map(s -> s.fromManifest(manifest)).collect(Collectors.toList());
List<PolarisResolvedPathWrapper> secondaries =
secondarySelectors.stream().map(s -> s.fromManifest(manifest)).collect(Collectors.toList());
List<PolarisResolvedPathWrapper> targets = manifest.authorizationTargets();
List<PolarisResolvedPathWrapper> secondaries = manifest.authorizationSecondaries();

PolarisEntity principal = manifest.getResolvedPolarisPrincipal();
if (principal == null) {
Expand All @@ -507,7 +503,10 @@ public void authorizeOrThrow(
authPrincipal.getName(), authPrincipal.getPrincipalEntityId());
}

Set<PolarisBaseEntity> activatedEntities = entitySelector.fromManifest(manifest);
Set<PolarisBaseEntity> activatedEntities =
considerCatalogRoles
? manifest.getAllActivatedCatalogRoleAndPrincipalRoles()
: manifest.getAllActivatedPrincipalRoleEntities();

boolean enforceCredentialRotationRequiredState =
featureConfig.getConfiguration(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
package org.apache.polaris.core.auth;

import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import java.util.List;
import org.apache.polaris.core.persistence.resolver.PolarisResolutionManifest;

/** Interface for invoking authorization checks. */
Expand All @@ -38,45 +36,11 @@ public interface PolarisAuthorizer {
*
* @param manifest defines the input for authorization checks.
* @param operation the operation being authorized.
* @param activatedEntities selector for roles that should be considered by the authorization
* checks
* @param targets target entities affected by the operation (e.g. tables)
* @param secondaries secondary entities affected by the operation (e.g. grantee)
* @param considerCatalogRoles whether catalog roles should be considered ({@code true}) or only
* principal roles ({@code false}).
*/
void authorizeOrThrow(
@Nonnull PolarisResolutionManifest manifest,
@Nonnull PolarisAuthorizableOperation operation,
@Nonnull ActivatedEntitySelector activatedEntities,
@Nonnull List<AuthEntitySelector> targets,
@Nonnull List<AuthEntitySelector> secondaries);

/**
* Convenience redirect for {@link #authorizeOrThrow(PolarisResolutionManifest,
* PolarisAuthorizableOperation, ActivatedEntitySelector, List, List)}
*/
default void authorizeOrThrow(
@Nonnull PolarisResolutionManifest manifest,
@Nonnull PolarisAuthorizableOperation operation,
@Nonnull ActivatedEntitySelector activatedEntities,
@Nullable AuthEntitySelector target) {
authorizeOrThrow(manifest, operation, activatedEntities, target, null);
}

/**
* Convenience redirect for {@link #authorizeOrThrow(PolarisResolutionManifest,
* PolarisAuthorizableOperation, ActivatedEntitySelector, List, List)}
*/
default void authorizeOrThrow(
@Nonnull PolarisResolutionManifest manifest,
@Nonnull PolarisAuthorizableOperation operation,
@Nonnull ActivatedEntitySelector activatedEntities,
@Nullable AuthEntitySelector target,
@Nullable AuthEntitySelector secondary) {
authorizeOrThrow(
manifest,
operation,
activatedEntities,
target == null ? List.of() : List.of(target),
secondary == null ? List.of() : List.of(secondary));
}
boolean considerCatalogRoles);
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
Expand Down Expand Up @@ -67,6 +68,8 @@ public class PolarisResolutionManifest implements PolarisResolutionManifestCatal
private final Multimap<String, PolarisEntityType> addedTopLevelNames = HashMultimap.create();

private final Map<Object, ResolverPath> passthroughPaths = new HashMap<>();
private final List<Getter> primaryTargets = new ArrayList<>();
private final List<Getter> secondaryTargets = new ArrayList<>();

// For applicable operations, this represents the topmost root entity which services as an
// authorization parent for all other entities that reside at the root level, such as
Expand Down Expand Up @@ -99,6 +102,18 @@ public PolarisResolutionManifest(
addTopLevelName(PolarisEntityConstants.getRootContainerName(), PolarisEntityType.ROOT, true);
}

public List<PolarisResolvedPathWrapper> authorizationTargets() {
return primaryTargets.stream().map(g -> g.get(this)).collect(Collectors.toList());
}

public List<PolarisResolvedPathWrapper> authorizationSecondaries() {
return secondaryTargets.stream().map(g -> g.get(this)).collect(Collectors.toList());
}

public void addRootContainer(AuthorizationTargetType targetType) {
targetType.addTo(this, Getter.rootContainer());
}

/** Adds a name of a top-level entity (Catalog, Principal, PrincipalRole) to be resolved. */
public void addTopLevelName(String entityName, PolarisEntityType entityType, boolean isOptional) {
addedTopLevelNames.put(entityName, entityType);
Expand All @@ -109,6 +124,15 @@ public void addTopLevelName(String entityName, PolarisEntityType entityType, boo
}
}

public void addTopLevelName(
AuthorizationTargetType targetType,
String entityName,
PolarisEntityType entityType,
boolean isOptional) {
addTopLevelName(entityName, entityType, isOptional);
targetType.addTo(this, Getter.topLevelEntity(entityName, entityType));
}

/**
* Adds a path that will be statically resolved with the primary Resolver when resolveAll() is
* called, and which contributes to the resolution status of whether all paths have successfully
Expand All @@ -124,6 +148,26 @@ public void addPath(ResolverPath path, Object key) {
++currentPathIndex;
}

public void addPath(AuthorizationTargetType targetType, ResolverPath path, Object key) {
addPath(path, key);
targetType.addTo(this, Getter.path(key));
}

public void addPath(
AuthorizationTargetType targetType, ResolverPath path, Object key, Runnable notFoundHandler) {
addPath(path, key);
targetType.addTo(this, Getter.path(key, notFoundHandler));
}

public void addPath(
AuthorizationTargetType targetType,
ResolverPath path,
Object key,
PolarisEntitySubType subType) {
addPath(path, key);
targetType.addTo(this, Getter.path(key, subType));
}

/**
* Adds a path that is allowed to be dynamically resolved with a new Resolver when
* getPassthroughResolvedPath is called. These paths are also included in the primary static
Expand All @@ -134,6 +178,16 @@ public void addPassthroughPath(ResolverPath path, Object key) {
passthroughPaths.put(key, path);
}

public void addPassthroughPath(
AuthorizationTargetType targetType,
ResolverPath path,
Object key,
PolarisEntitySubType subType,
Runnable notFoundHandler) {
addPassthroughPath(path, key);
targetType.addTo(this, Getter.path(key, subType, notFoundHandler));
}

public ResolverStatus resolveAll() {
primaryResolverStatus = primaryResolver.resolveAll();
// TODO: This could be a race condition where a Principal is dropped after initial authn
Expand Down Expand Up @@ -420,4 +474,60 @@ public PolarisResolvedPathWrapper getResolvedTopLevelEntity(
: new PolarisResolvedPathWrapper(
List.of(resolvedRootContainerEntity, new ResolvedPolarisEntity(resolvedCacheEntry)));
}

public enum AuthorizationTargetType {
PRIMARY(m -> m.primaryTargets),
SECONDARY(m -> m.secondaryTargets),
;

private final Function<PolarisResolutionManifest, List<Getter>> list;

AuthorizationTargetType(Function<PolarisResolutionManifest, List<Getter>> list) {
this.list = list;
}

private void addTo(PolarisResolutionManifest manifest, Getter getter) {
list.apply(manifest).add(getter);
}
}

private interface Getter {
PolarisResolvedPathWrapper get(PolarisResolutionManifest manifest);

static Getter rootContainer() {
return PolarisResolutionManifest::getResolvedRootContainerEntityAsPath;
}

static Getter topLevelEntity(String entityName, PolarisEntityType type) {
return m -> m.getResolvedTopLevelEntity(entityName, type);
}

static Getter path(Object key, PolarisEntitySubType subType) {
return path(key, subType, () -> {});
}

static Getter path(Object key, PolarisEntitySubType subType, Runnable notFoundHandler) {
return manifest -> {
PolarisResolvedPathWrapper resolved = manifest.getResolvedPath(key, subType, true);
if (resolved == null) {
notFoundHandler.run();
}
return resolved;
};
}

static Getter path(Object key) {
return path(key, () -> {});
}

static Getter path(Object key, Runnable notFoundHandler) {
return manifest -> {
PolarisResolvedPathWrapper resolved = manifest.getResolvedPath(key, true);
if (resolved == null) {
notFoundHandler.run();
}
return resolved;
};
}
}
}
Loading

0 comments on commit c9b9545

Please sign in to comment.