Skip to content

Commit 64ac4cf

Browse files
optimize batch access query functions (#198)
* saving progress * updates * updates
1 parent 69a76b2 commit 64ac4cf

File tree

6 files changed

+450
-169
lines changed

6 files changed

+450
-169
lines changed

src/main/java/gov/nist/csd/pm/core/common/prohibition/ContainerCondition.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@ public class ContainerCondition implements Serializable {
88
private long id;
99
private boolean complement;
1010

11-
public ContainerCondition() {
12-
}
13-
1411
public ContainerCondition(long id, boolean complement) {
1512
this.id = id;
1613
this.complement = complement;

src/main/java/gov/nist/csd/pm/core/pap/query/AccessQuerier.java

Lines changed: 53 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import gov.nist.csd.pm.core.common.graph.dag.UserDagResult;
1313
import gov.nist.csd.pm.core.common.graph.node.Node;
1414
import gov.nist.csd.pm.core.common.graph.relationship.AccessRightSet;
15+
import gov.nist.csd.pm.core.pap.query.access.CachedTargetEvaluator;
1516
import gov.nist.csd.pm.core.pap.query.access.Explainer;
1617
import gov.nist.csd.pm.core.pap.query.access.TargetEvaluator;
1718
import gov.nist.csd.pm.core.pap.query.access.UserEvaluator;
@@ -37,31 +38,26 @@ public AccessQuerier(PolicyStore store) {
3738

3839
@Override
3940
public AccessRightSet computePrivileges(UserContext userCtx, TargetContext targetCtx) throws PMException {
40-
// traverse the user side of the graph to get the associations
41-
UserEvaluator userEvaluator = new UserEvaluator(store);
42-
UserDagResult userDagResult = userEvaluator.evaluate(userCtx);
41+
UserDagResult userDagResult = evaluateUser(userCtx);
4342

4443
// traverse the target side of the graph to get permissions per policy class
4544
TargetEvaluator targetEvaluator = new TargetEvaluator(store);
46-
TargetDagResult targetDagResult = targetEvaluator.evaluate(userDagResult, targetCtx);
4745

4846
// resolve the permissions
49-
return resolvePrivileges(userDagResult, targetDagResult, store.operations().getResourceOperations());
47+
return computePrivileges(userDagResult, targetCtx, targetEvaluator);
5048
}
5149

5250
@Override
5351
public List<AccessRightSet> computePrivileges(UserContext userCtx, List<TargetContext> targetCtxs) throws PMException {
5452
// traverse the user side of the graph to get the associations
55-
UserEvaluator userEvaluator = new UserEvaluator(store);
56-
UserDagResult userDagResult = userEvaluator.evaluate(userCtx);
53+
UserDagResult userDagResult = evaluateUser(userCtx);
5754

5855
// traverse the target side of the graph to get permissions per policy class
59-
TargetEvaluator targetEvaluator = new TargetEvaluator(store);
56+
TargetEvaluator targetEvaluator = new CachedTargetEvaluator(store);
6057

6158
List<AccessRightSet> accessRightSets = new ArrayList<>();
6259
for (TargetContext targetCtx : targetCtxs) {
63-
TargetDagResult targetDagResult = targetEvaluator.evaluate(userDagResult, targetCtx);
64-
AccessRightSet privs = resolvePrivileges(userDagResult, targetDagResult, store.operations().getResourceOperations());
60+
AccessRightSet privs = computePrivileges(userDagResult, targetCtx, targetEvaluator);
6561

6662
accessRightSets.add(privs);
6763
}
@@ -92,25 +88,29 @@ public AccessRightSet computeDeniedPrivileges(UserContext userCtx, TargetContext
9288
public Map<Long, AccessRightSet> computeCapabilityList(UserContext userCtx) throws PMException {
9389
Map<Long, AccessRightSet> results = new HashMap<>();
9490

95-
//get border nodes. Can be OA or UA. Return empty set if no attrs are reachable
91+
// get border nodes. Can be OA or UA. Return empty set if no attrs are reachable
9692
UserEvaluator userEvaluator = new UserEvaluator(store);
9793
UserDagResult userDagResult = userEvaluator.evaluate(userCtx);
9894
if (userDagResult.borderTargets().isEmpty()) {
9995
return results;
10096
}
10197

98+
CachedTargetEvaluator cachedTargetEvaluator = new CachedTargetEvaluator(store);
99+
102100
for(long borderTarget : userDagResult.borderTargets().keySet()) {
103101
// compute permissions on the border attr
104-
getAndStorePrivileges(results, userDagResult, borderTarget);
102+
AccessRightSet arset = computePrivileges(userDagResult, new TargetContext(borderTarget), cachedTargetEvaluator);
103+
results.put(borderTarget, arset);
105104

106105
// compute decisions for the subgraph of the border attr
107-
Set<Long> descendants = getAscendants(borderTarget);
108-
for (long descendant : descendants) {
109-
if (results.containsKey(descendant)) {
106+
Set<Long> ascendants = getAscendants(borderTarget);
107+
for (long ascendant : ascendants) {
108+
if (results.containsKey(ascendant)) {
110109
continue;
111110
}
112111

113-
getAndStorePrivileges(results, userDagResult, descendant);
112+
arset = computePrivileges(userDagResult, new TargetContext(ascendant), cachedTargetEvaluator);
113+
results.put(ascendant, arset);
114114
}
115115
}
116116

@@ -129,8 +129,12 @@ public Map<Long, AccessRightSet> computeCapabilityList(UserContext userCtx) thro
129129
public Map<Long, AccessRightSet> computeACL(TargetContext targetCtx) throws PMException {
130130
Map<Long, AccessRightSet> acl = new HashMap<>();
131131
Collection<Long> search = store.graph().search(U, NO_PROPERTIES);
132+
133+
TargetEvaluator targetEvaluator = new CachedTargetEvaluator(store);
132134
for (long user : search) {
133-
AccessRightSet list = this.computePrivileges(new UserContext(user), targetCtx);
135+
UserDagResult userDagResult = evaluateUser(new UserContext(user));
136+
137+
AccessRightSet list = this.computePrivileges(userDagResult, targetCtx, targetEvaluator);
134138
acl.put(user, list);
135139
}
136140

@@ -139,9 +143,7 @@ public Map<Long, AccessRightSet> computeACL(TargetContext targetCtx) throws PMEx
139143

140144
@Override
141145
public Map<Long, AccessRightSet> computeDestinationAttributes(UserContext userCtx) throws PMException {
142-
return new UserEvaluator(store)
143-
.evaluate(userCtx)
144-
.borderTargets();
146+
return evaluateUser(userCtx).borderTargets();
145147
}
146148

147149
@Override
@@ -153,17 +155,27 @@ public SubgraphPrivileges computeSubgraphPrivileges(UserContext userCtx, long ro
153155
subgraphs.add(computeSubgraphPrivileges(userCtx, adjacent));
154156
}
155157

156-
return new SubgraphPrivileges(store.graph().getNodeById(root), computePrivileges(userCtx, new TargetContext(root)), subgraphs);
158+
UserDagResult userDagResult = evaluateUser(userCtx);
159+
TargetEvaluator targetEvaluator = new TargetEvaluator(store);
160+
161+
return new SubgraphPrivileges(
162+
store.graph().getNodeById(root),
163+
computePrivileges(userDagResult, new TargetContext(root), targetEvaluator),
164+
subgraphs
165+
);
157166
}
158167

159168
@Override
160169
public Map<Node, AccessRightSet> computeAdjacentAscendantPrivileges(UserContext userCtx, long root) throws PMException {
161170
Map<Node, AccessRightSet> ascendantPrivs = new HashMap<>();
162171

172+
UserDagResult userDagResult = evaluateUser(userCtx);
173+
TargetEvaluator targetEvaluator = new TargetEvaluator(store);
174+
163175
Collection<Long> adjacentAscendants = store.graph().getAdjacentAscendants(root);
164176
for (long adjacentAscendant : adjacentAscendants) {
165177
Node node = store.graph().getNodeById(adjacentAscendant);
166-
ascendantPrivs.put(node, computePrivileges(userCtx, new TargetContext(adjacentAscendant)));
178+
ascendantPrivs.put(node, computePrivileges(userDagResult, new TargetContext(adjacentAscendant), targetEvaluator));
167179
}
168180

169181
return ascendantPrivs;
@@ -173,10 +185,13 @@ public Map<Node, AccessRightSet> computeAdjacentAscendantPrivileges(UserContext
173185
public Map<Node, AccessRightSet> computeAdjacentDescendantPrivileges(UserContext userCtx, long root) throws PMException {
174186
Map<Node, AccessRightSet> descendantPrivs = new HashMap<>();
175187

188+
UserDagResult userDagResult = evaluateUser(userCtx);
189+
TargetEvaluator targetEvaluator = new TargetEvaluator(store);
190+
176191
Collection<Long> adjacentDescendants = store.graph().getAdjacentDescendants(root);
177192
for (long adjacentDescendant : adjacentDescendants) {
178193
Node node = store.graph().getNodeById(adjacentDescendant);
179-
descendantPrivs.put(node, computePrivileges(userCtx, new TargetContext(adjacentDescendant)));
194+
descendantPrivs.put(node, computePrivileges(userDagResult, new TargetContext(adjacentDescendant), targetEvaluator));
180195
}
181196

182197
return descendantPrivs;
@@ -192,20 +207,21 @@ public Explain explain(UserContext userCtx, TargetContext targetCtx) throws PMEx
192207
public Map<Node, AccessRightSet> computePersonalObjectSystem(UserContext userCtx) throws PMException {
193208
Map<Long, AccessRightSet> pos = new HashMap<>();
194209

210+
UserDagResult userDagResult = evaluateUser(userCtx);
211+
CachedTargetEvaluator cachedTargetEvaluator = new CachedTargetEvaluator(store);
212+
195213
for (long pc : store.graph().getPolicyClasses()) {
196214
new GraphStoreBFS(store.graph())
197215
.withDirection(Direction.ASCENDANTS)
198216
.withVisitor(n -> {
199-
AccessRightSet privs = computePrivileges(userCtx, new TargetContext(n));
217+
AccessRightSet privs = computePrivileges(userDagResult, new TargetContext(n), cachedTargetEvaluator);
200218
if (privs.isEmpty()) {
201219
return;
202220
}
203221

204222
pos.put(n, privs);
205223
})
206-
.withSinglePathShortCircuit(n -> {
207-
return pos.containsKey(n);
208-
})
224+
.withSinglePathShortCircuit(pos::containsKey)
209225
.walk(pc);
210226
}
211227

@@ -217,11 +233,9 @@ public Map<Node, AccessRightSet> computePersonalObjectSystem(UserContext userCtx
217233
return posWithNodes;
218234
}
219235

220-
private void getAndStorePrivileges(Map<Long, AccessRightSet> arsetMap, UserDagResult userDagResult, long target) throws PMException {
221-
TargetDagResult result = new TargetEvaluator(store)
222-
.evaluate(userDagResult, new TargetContext(target));
223-
AccessRightSet privileges = resolvePrivileges(userDagResult, result, store.operations().getResourceOperations());
224-
arsetMap.put(target, privileges);
236+
private UserDagResult evaluateUser(UserContext userCtx) throws PMException {
237+
UserEvaluator userEvaluator = new UserEvaluator(store);
238+
return userEvaluator.evaluate(userCtx);
225239
}
226240

227241
private Set<Long> getAscendants(long vNode) throws PMException {
@@ -240,4 +254,11 @@ private Set<Long> getAscendants(long vNode) throws PMException {
240254

241255
return ret;
242256
}
257+
258+
private AccessRightSet computePrivileges(UserDagResult userDagResult, TargetContext targetCtx, TargetEvaluator targetEvaluator) throws PMException {
259+
TargetDagResult targetDagResult = targetEvaluator.evaluate(userDagResult, targetCtx);
260+
261+
// resolve the permissions
262+
return resolvePrivileges(userDagResult, targetDagResult, store.operations().getResourceOperations());
263+
}
243264
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package gov.nist.csd.pm.core.pap.query.access;
2+
3+
import gov.nist.csd.pm.core.common.exception.PMException;
4+
import gov.nist.csd.pm.core.common.graph.dag.TargetDagResult;
5+
import gov.nist.csd.pm.core.common.graph.dag.UserDagResult;
6+
import gov.nist.csd.pm.core.common.graph.relationship.AccessRightSet;
7+
import gov.nist.csd.pm.core.pap.query.model.context.TargetContext;
8+
import gov.nist.csd.pm.core.pap.store.PolicyStore;
9+
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
10+
import it.unimi.dsi.fastutil.longs.LongArrayList;
11+
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
12+
13+
import java.util.Collection;
14+
import java.util.Map;
15+
import java.util.Set;
16+
17+
public class CachedTargetEvaluator extends TargetEvaluator {
18+
19+
private UserDagResult cachedUserDagResult;
20+
private final Map<Long, Map<Long, AccessRightSet>> cachedVisitedNodes;
21+
22+
public CachedTargetEvaluator(PolicyStore policyStore) {
23+
super(policyStore);
24+
this.cachedVisitedNodes = new Long2ObjectOpenHashMap<>();
25+
}
26+
27+
@Override
28+
public TargetDagResult evaluate(UserDagResult userDagResult, TargetContext targetContext) throws PMException {
29+
// If UserDagResult has changed, clear the cache
30+
if (cachedUserDagResult == null || !cachedUserDagResult.equals(userDagResult)) {
31+
cachedUserDagResult = userDagResult;
32+
cachedVisitedNodes.clear();
33+
}
34+
35+
return super.evaluate(userDagResult, targetContext);
36+
}
37+
38+
@Override
39+
protected TraversalState initializeEvaluationState(UserDagResult userDagResult, TargetContext targetCtx) throws PMException {
40+
Collection<Long> firstLevelDescs = new LongArrayList();
41+
if (targetCtx.isNode()) {
42+
firstLevelDescs.addAll(policyStore.graph().getAdjacentDescendants(targetCtx.getTargetId()));
43+
} else {
44+
firstLevelDescs.addAll(targetCtx.getAttributeIds());
45+
}
46+
47+
Set<Long> userProhibitionTargets = collectUserProhibitionTargets(userDagResult.prohibitions());
48+
Set<Long> visitedProhibitionTargets = new LongOpenHashSet();
49+
50+
// Use cached visitedNodes instead of creating a new one
51+
return new TraversalState(
52+
firstLevelDescs,
53+
userProhibitionTargets,
54+
cachedVisitedNodes,
55+
visitedProhibitionTargets
56+
);
57+
}
58+
}

0 commit comments

Comments
 (0)