Skip to content

Commit

Permalink
- modify memory access evaluators to only perform one traversal
Browse files Browse the repository at this point in the history
- remove access checks in the PDP AccessQueryAdjudicator
- removed computePolicyClassAccessRights as the functionality is copied in explain
  • Loading branch information
joshua-roberts committed Nov 14, 2024
1 parent 0f17049 commit 95cb39e
Show file tree
Hide file tree
Showing 16 changed files with 121 additions and 125 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public class MemoryAccessQuerier extends AccessQuerier {
public MemoryAccessQuerier(PolicyStore memoryPolicyStore) {
super(memoryPolicyStore);
}

@Override
public AccessRightSet computePrivileges(UserContext userCtx, TargetContext targetCtx) throws PMException {
// traverse the user side of the graph to get the associations
Expand All @@ -38,38 +39,42 @@ public AccessRightSet computePrivileges(UserContext userCtx, TargetContext targe
}

@Override
public AccessRightSet computeDeniedPrivileges(UserContext userCtx, TargetContext targetCtx) throws PMException {
AccessRightSet accessRights = new AccessRightSet();

public List<AccessRightSet> computePrivileges(UserContext userCtx, List<TargetContext> targetCtxs) throws PMException {
// traverse the user side of the graph to get the associations
MemoryUserEvaluator userEvaluator = new MemoryUserEvaluator(store);
UserDagResult userDagResult = userEvaluator.evaluate(userCtx);
if (userDagResult.borderTargets().isEmpty()) {
return accessRights;
}

// traverse the target side of the graph to get permissions per policy class
MemoryTargetEvaluator targetEvaluator = new MemoryTargetEvaluator(store);
TargetDagResult targetDagResult = targetEvaluator.evaluate(userDagResult, targetCtx);

// resolve the permissions
return resolveDeniedAccessRights(userDagResult, targetDagResult);
List<AccessRightSet> accessRightSets = new ArrayList<>();
for (TargetContext targetCtx : targetCtxs) {
TargetDagResult targetDagResult = targetEvaluator.evaluate(userDagResult, targetCtx);
AccessRightSet privs = resolvePrivileges(userDagResult, targetDagResult, store.operations().getResourceOperations());

accessRightSets.add(privs);
}

return accessRightSets;
}

@Override
public Map<String, AccessRightSet> computePolicyClassAccessRights(UserContext userCtx, TargetContext targetCtx) throws PMException {
public AccessRightSet computeDeniedPrivileges(UserContext userCtx, TargetContext targetCtx) throws PMException {
AccessRightSet accessRights = new AccessRightSet();

// traverse the user side of the graph to get the associations
MemoryUserEvaluator userEvaluator = new MemoryUserEvaluator(store);
UserDagResult userDagResult = userEvaluator.evaluate(userCtx);
if (userDagResult.borderTargets().isEmpty()) {
return new HashMap<>();
return accessRights;
}

// traverse the target side of the graph to get permissions per policy class
MemoryTargetEvaluator targetEvaluator = new MemoryTargetEvaluator(store);
TargetDagResult targetDagResult = targetEvaluator.evaluate(userDagResult, targetCtx);

return targetDagResult.pcMap();
// resolve the permissions
return resolveDeniedAccessRights(userDagResult, targetDagResult);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ private List<PolicyClassExplain> resolvePaths(UserContext userCtx, TargetContext
MemoryUserExplainer userExplainer = new MemoryUserExplainer(policyStore);
MemoryTargetExplainer targetExplainer = new MemoryTargetExplainer(policyStore);
Map<String, Map<Path, List<Association>>> targetPaths = targetExplainer.explainTarget(targetCtx);
Map<String, Set<Path>> userPaths = userExplainer.explainUser(userCtx, targetPaths);
Map<String, Set<Path>> userPaths = userExplainer.explainIntersectionOfTargetPaths(userCtx, targetPaths);

List<PolicyClassExplain> result = new ArrayList<>();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package gov.nist.csd.pm.impl.memory.pap.access;

import gov.nist.csd.pm.pap.exception.NodeDoesNotExistException;
import gov.nist.csd.pm.pap.exception.PMException;
import gov.nist.csd.pm.pap.graph.dag.*;
import gov.nist.csd.pm.pap.graph.node.Node;
Expand Down Expand Up @@ -31,6 +30,8 @@ public MemoryTargetEvaluator(PolicyStore policyStore) {
* each policy class.
*/
public TargetDagResult evaluate(UserDagResult userCtx, TargetContext targetCtx) throws PMException {
targetCtx.checkExists(policyStore.graph());

Collection<String> policyClasses = policyStore.graph().getPolicyClasses();
Map<String, AccessRightSet> borderTargets = userCtx.borderTargets();
Set<String> userProhibitionTargets = collectUserProhibitionTargets(userCtx.prohibitions());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@ public MemoryTargetExplainer(PolicyStore policyStore) {
}

public Map<String, Map<Path, List<Association>>> explainTarget(TargetContext targetCtx) throws PMException {
targetCtx.checkExists(policyStore.graph());

Collection<String> policyClasses = policyStore.graph().getPolicyClasses();

// initialize map with policy classes
Map<String, Map<Path, List<Association>>> pcMap = new HashMap<>();
Map<String, Map<List<String>, List<Association>>> pcPathAssociations = new HashMap<>();
for (String pc : policyClasses) {
pcPathAssociations.put(pc, new HashMap<>(Map.of(new ArrayList<>(List.of(pc)), new ArrayList<>())));
Expand Down Expand Up @@ -75,6 +76,8 @@ public Map<String, Map<Path, List<Association>>> explainTarget(TargetContext tar
}

// convert the map created above into a map where the policy classes are the keys
Map<String, Map<Path, List<Association>>> pcMap = new HashMap<>();

for (String target : nodes) {
Map<List<String>, List<Association>> targetPathAssocs = pcPathAssociations.get(target);
for (Map.Entry<List<String>, List<Association>> entry : targetPathAssocs.entrySet()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public MemoryUserEvaluator(PolicyStore policyStore) {
* @return a Map of target nodes that the subject can reach via associations and the operations the user has on each.
*/
protected UserDagResult evaluate(UserContext userCtx) throws PMException {
userCtx.checkExists(policyStore.graph());

final Map<String, AccessRightSet> borderTargets = new HashMap<>();
// initialize with the prohibitions or the provided process
final Set<Prohibition> reachedProhibitions = new HashSet<>(getProhibitionsWithSubject(userCtx.getProcess()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ public MemoryUserExplainer(PolicyStore policyStore) {
this.policyStore = policyStore;
}

public Map<String, Set<Path>> explainUser(UserContext userCtx, Map<String, Map<Path, List<Association>>> targetPaths) throws PMException {
public Map<String, Set<Path>> explainIntersectionOfTargetPaths(UserContext userCtx, Map<String, Map<Path, List<Association>>> targetPaths) throws PMException {
userCtx.checkExists(policyStore.graph());

// initialize map with the UAs of the target path associations
Map<String, Set<Path>> associationUAPaths = new HashMap<>();
Set<String> uasFromTargetPathAssociations = new HashSet<>(getUAsFromTargetPathAssociations(targetPaths));
Expand Down Expand Up @@ -53,10 +55,12 @@ public Map<String, Set<Path>> explainUser(UserContext userCtx, Map<String, Map<P
if (userCtx.isUser()) {
String user = userCtx.getUser();
nodes.add(user);

dfs.walk(user);
} else {
List<String> attributes = userCtx.getAttributes();
nodes.addAll(attributes);

dfs.walk(attributes);
}

Expand Down
28 changes: 18 additions & 10 deletions src/main/java/gov/nist/csd/pm/pap/graph/node/NodeType.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,29 @@
* OS = Operation Set
*/
public enum NodeType implements Serializable {
OA("OA"),
UA("UA"),
U("U"),
O("O"),
PC("PC"),
ANY("ANY");
OA(0),
UA(1),
U(2),
O(3),
PC(4),
ANY(5);

private final String label;
private final int i;

NodeType(String label) {
this.label = label;
NodeType(int i) {
this.i = i;
}

public String toString() {
return label;
return switch (i) {
case 0 -> "OA";
case 1 -> "UA";
case 2 -> "U";
case 3 -> "O";
case 4 -> "PC";
case 5 -> "ANY";
default -> throw new IllegalStateException("Unexpected value: " + i);
};
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ public class AdminAccessRights {
public static final String CREATE_ADMIN_ROUTINE = "create_admin_routine";
public static final String DELETE_ADMIN_ROUTINE = "delete_admin_routine";


// policy review
public static final String REVIEW_POLICY = "review_policy";

Expand Down
31 changes: 11 additions & 20 deletions src/main/java/gov/nist/csd/pm/pap/op/PrivilegeChecker.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,26 +41,14 @@ public void check(UserContext userCtx, String target, Collection<String> toCheck
}

public void check(UserContext userCtx, UserContext target, Collection<String> toCheck) throws PMException {
TargetContext targetContext;
if (target.isUser()) {
targetContext = new TargetContext(target.getUser());
} else {
targetContext = new TargetContext(target.getAttributes());
}
TargetContext targetContext = new TargetContext(target);

AccessRightSet computed = pap.query().access().computePrivileges(userCtx, targetContext);

checkOrThrow(userCtx, targetContext, computed, toCheck);
}

public void check(UserContext userCtx, TargetContext target, Collection<String> toCheck) throws PMException {
TargetContext targetContext;
if (target.isNode()) {
targetContext = new TargetContext(target.getTarget());
} else {
targetContext = new TargetContext(target.getAttributes());
}

public void check(UserContext userCtx, TargetContext targetContext, Collection<String> toCheck) throws PMException {
AccessRightSet computed = pap.query().access().computePrivileges(userCtx, targetContext);

checkOrThrow(userCtx, targetContext, computed, toCheck);
Expand All @@ -76,12 +64,6 @@ public void check(UserContext userCtx, List<String> targets, String... toCheck)
}
}

public void check(UserContext userCtx, Collection<String> targets, String... toCheck) throws PMException {
for (String target : targets) {
check(userCtx, target, toCheck);
}
}

public void checkPattern(UserContext userCtx, Pattern pattern, String toCheck) throws PMException {
ReferencedNodes referencedNodes = pattern.getReferencedNodes();
if (referencedNodes.isAny()) {
Expand Down Expand Up @@ -109,4 +91,13 @@ private void checkOrThrow(UserContext userContext, TargetContext targetContext,
}
}
}

private void checkOrThrow(UserContext userCtx, List<TargetContext> targetContexts, List<AccessRightSet> privileges, Collection<String> toCheck) throws PMException {
for (int i = 0; i < targetContexts.size(); i++) {
TargetContext targetContext = targetContexts.get(i);
AccessRightSet privs = privileges.get(i);

checkOrThrow(userCtx, targetContext, privs, toCheck);
}
}
}
22 changes: 11 additions & 11 deletions src/main/java/gov/nist/csd/pm/pap/query/AccessQuery.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import gov.nist.csd.pm.pap.query.model.subgraph.SubgraphPrivileges;
import gov.nist.csd.pm.pap.query.model.explain.Explain;

import java.util.List;
import java.util.Map;

/**
Expand All @@ -26,26 +27,25 @@ public interface AccessQuery {
AccessRightSet computePrivileges(UserContext userCtx, TargetContext targetCtx) throws PMException;

/**
* Compute the privileges that are denied for the user on the target node.The provided User and Target contexts,
* allow for the specification of a single node or a list of attributes.
* Compute the privileges the user has on each target node. The provided User and Target contexts, allow for the
* specification of a single node or a list of attributes.
*
* @param userCtx The user and process or list of attributes and process. Process is optional.
* @param targetCtx The target node or list of attributes.
* @return An AccessRightSet that contains the users denied privileges on the target node.
* @param targetCtxs The target nodes.
* @return An AccessRightSet that contains the users privileges on the target node.
* @throws PMException If there is an error in the PM.
*/
AccessRightSet computeDeniedPrivileges(UserContext userCtx, TargetContext targetCtx) throws PMException;
List<AccessRightSet> computePrivileges(UserContext userCtx, List<TargetContext> targetCtxs) throws PMException;

/**
* Compute the access rights that a user has access to under each policy class the target is an ascendant of. This
* does not include prohibitions. The provided User and Target contexts, allow for the specification of a single
* node or a list of attributes.
*
* Compute the privileges that are denied for the user on the target node.The provided User and Target contexts,
* allow for the specification of a single node or a list of attributes.
* @param userCtx The user and process or list of attributes and process. Process is optional.
* @param targetCtx The target node or list of attributes.
* @return A mapping of policy class names to the access rights the user has under them on the target node.
* @return An AccessRightSet that contains the users denied privileges on the target node.
* @throws PMException If there is an error in the PM.
*/
Map<String, AccessRightSet> computePolicyClassAccessRights(UserContext userCtx, TargetContext targetCtx) throws PMException;
AccessRightSet computeDeniedPrivileges(UserContext userCtx, TargetContext targetCtx) throws PMException;

/**
* Compute a mapping of all the nodes the user has access to the access rights they have on each. The provided
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package gov.nist.csd.pm.pap.query.model.context;

import java.util.ArrayList;
import gov.nist.csd.pm.pap.exception.NodeDoesNotExistException;
import gov.nist.csd.pm.pap.exception.PMException;
import gov.nist.csd.pm.pap.store.GraphStore;

import java.util.List;
import java.util.Objects;

Expand All @@ -13,6 +16,14 @@ public TargetContext(String target) {
this.target = target;
}

public TargetContext(UserContext target) {
if (target.isUser()) {
this.target = target.getUser();
} else {
this.attributes = target.getAttributes();
}
}

public TargetContext(List<String> attributes) {
this.attributes = attributes;
}
Expand All @@ -37,6 +48,20 @@ public boolean isNode() {
return target != null;
}

public void checkExists(GraphStore graphStore) throws PMException {
if (isNode()) {
if (!graphStore.nodeExists(target)) {
throw new NodeDoesNotExistException(target);
}
} else {
for (String attribute : attributes) {
if (!graphStore.nodeExists(attribute)) {
throw new NodeDoesNotExistException(attribute);
}
}
}
}

@Override
public String toString() {
String s = "%s";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package gov.nist.csd.pm.pap.query.model.context;

import gov.nist.csd.pm.pap.exception.NodeDoesNotExistException;
import gov.nist.csd.pm.pap.exception.PMException;
import gov.nist.csd.pm.pap.store.GraphStore;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

Expand Down Expand Up @@ -57,6 +60,20 @@ public boolean isUser() {
return user != null;
}

public void checkExists(GraphStore graphStore) throws PMException {
if (isUser()) {
if (!graphStore.nodeExists(user)) {
throw new NodeDoesNotExistException(user);
}
} else {
for (String attribute : attributes) {
if (!graphStore.nodeExists(attribute)) {
throw new NodeDoesNotExistException(attribute);
}
}
}
}

@Override
public String toString() {
String s = "%s";
Expand Down
1 change: 0 additions & 1 deletion src/main/java/gov/nist/csd/pm/pdp/PDPTx.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ public PolicyQueryAdjudicator query() {
@Override
public void setPMLOperations(Map<String, PMLOperation> pmlOperations) throws PMException {
privilegeChecker.check(userCtx, AdminPolicyNode.PM_ADMIN_OBJECT.nodeName(), SET_PML_OPS);

super.setPMLOperations(pmlOperations);
}

Expand Down
Loading

0 comments on commit 95cb39e

Please sign in to comment.