-
Notifications
You must be signed in to change notification settings - Fork 8
/
PolicySetParser.java
257 lines (212 loc) · 9.53 KB
/
PolicySetParser.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
/*
* SNE-XACML: A high performance XACML evaluation engine.
*
* Copyright (C) 2013-2014 Canh Ngo <canhnt@gmail.com>
* System and Network Engineering Group, University of Amsterdam.
* All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package nl.uva.sne.xacml.policy.parsers;
import nl.uva.sne.midd.MIDDException;
import nl.uva.sne.midd.algorithms.CombiningAlgorithm;
import nl.uva.sne.midd.builders.ConjunctiveBuilder;
import nl.uva.sne.midd.builders.MIDDCombiner;
import nl.uva.sne.midd.nodes.AbstractNode;
import nl.uva.sne.midd.nodes.ExternalNode;
import nl.uva.sne.midd.nodes.InternalNode;
import nl.uva.sne.midd.util.GenericUtils;
import nl.uva.sne.midd.util.MIDDUtils;
import nl.uva.sne.xacml.AttributeMapper;
import nl.uva.sne.xacml.policy.finder.PolicyFinder;
import nl.uva.sne.xacml.policy.parsers.util.CombiningAlgConverterUtil;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.xml.bind.JAXBElement;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* Create MIDD from a XACML 3.0 PolicySet element.
*/
public class PolicySetParser {
private static final Logger log = LoggerFactory.getLogger(PolicySetParser.class);
private PolicySetType policyset;
private AbstractNode preCondition;
private AttributeMapper attrMapper;
private List<Object> children;
/**
* The policy finder is to lookup policy/policyset from references
*/
private PolicyFinder policyFinder;
/**
* Brief constructor not to use policy finder. It does not support references to policies or policysets.
*
* @param condition
* @param policyset
* @param attrMapper
*/
public PolicySetParser(AbstractNode condition, PolicySetType policyset,
AttributeMapper attrMapper) throws MIDDException {
this(condition, policyset, attrMapper, null);
}
/**
* @param condition a MIDD that represents the target expression of the parents' policyset.
* @param policy a XACML 3.0 policy element.
*/
public PolicySetParser(AbstractNode condition, PolicySetType policyset,
AttributeMapper attrMapper, PolicyFinder policyFinder) throws MIDDException {
if (policyset == null) {
throw new IllegalArgumentException("PolicySetType argument must not be null");
}
if (attrMapper == null) {
throw new IllegalArgumentException("AttributeMapper argument must not be null");
}
this.policyFinder = policyFinder;
this.policyset = policyset;
this.attrMapper = attrMapper;
if (condition == null) {
this.preCondition = new ExternalNode();
} else {
// this.preCondition = condition;
this.preCondition = GenericUtils.newInstance(condition);
}
}
private AbstractNode combinePolicyMIDDs(List<AbstractNode> lstMIDDs,
CombiningAlgorithm pca) throws MIDDException {
log.debug("Combining policy set " + this.policyset.getPolicySetId());
MIDDCombiner combiner = new MIDDCombiner(pca);
Iterator<AbstractNode> it = lstMIDDs.iterator();
AbstractNode root = null;
while (it.hasNext()) {
AbstractNode n = it.next();
if (root == null) {
root = n;
} else {
if (root instanceof InternalNode) {
log.debug("root size:" + MIDDUtils.countNodes((InternalNode) root));
}
if (n instanceof InternalNode) {
log.debug("child midd size:" + MIDDUtils.countNodes((InternalNode) n));
}
root = combiner.combine(root, n);
if (root instanceof InternalNode) {
log.debug("Combined midd size:" + MIDDUtils.countNodes((InternalNode) root));
}
}
}
return root;
}
/**
* Retrieve policy/policyset from the policy finder and add to the children policy or policyset lists
*
* @param idReference
*/
private void addChildrenByRef(IdReferenceType idReference) {
String id = idReference.getValue();
if (id == null || id.isEmpty()) {
log.debug("Invalid reference to policy or policyset ");
return;
}
Object obj = policyFinder.lookup(id);
if (obj instanceof PolicyType || obj instanceof PolicySetType) {
children.add(obj);
} else {
log.debug("No policy/policyset found for the reference " + id);
}
}
private void getChilden() throws XACMLParsingException {
List<JAXBElement<?>> objs = policyset.getPolicySetOrPolicyOrPolicySetIdReference();
if (objs == null || objs.size() == 0) {
throw new XACMLParsingException("No children policy/policyset found in the policyset " + policyset.getPolicySetId());
}
children = new ArrayList<>();
for (JAXBElement<?> obj : objs) {
if (obj != null) {
Object objValue = obj.getValue();
if (objValue instanceof PolicyType || objValue instanceof PolicySetType) {
children.add(objValue);
} else if (objValue instanceof IdReferenceType) {
if (policyFinder != null) {
addChildrenByRef((IdReferenceType) objValue);
} else {
log.debug("No policy finder found to lookup reference in the policy: " + policyset.getPolicySetId());
}
} else {
// we ignore other types in this version: e.g. references to rule
log.info("Unsupported object type:" + objValue.getClass() + "inside the policyset '" + policyset.getPolicySetId() + "'");
}
}
}
if (children.size() == 0) {
throw new XACMLParsingException("No children policy/policyset found in the policy: " + policyset.getPolicySetId());
}
}
private AbstractNode getTargetCondition() throws XACMLParsingException, MIDDException, MIDDParsingException {
TargetType target = policyset.getTarget();
List<AnyOfType> lstAnyOf;
if (target != null) {
lstAnyOf = target.getAnyOf();
} else {
lstAnyOf = null;
}
TargetExpression te = new TargetExpression(lstAnyOf, attrMapper);
return te.parse();
}
public AbstractNode parse() throws XACMLParsingException, MIDDException, MIDDParsingException {
// Get a MIDD to represent the policy's target expression
AbstractNode targetCondition = getTargetCondition();
if (targetCondition == null) // no applicable MIDD extracted from Target
{
return null;
}
// Conjunctive join it with the MIDD representing preconditions of the policy
AbstractNode condition = ConjunctiveBuilder.join(this.preCondition, targetCondition);
getChilden();
List<AbstractNode> lstMIDDs = new ArrayList<AbstractNode>();
// Warning: must convert children policy/policyset in its natural order to compliant with some ordered-RCAs (e.g: First-Applicable)
// Create MIDDs for children policies
for (Object obj : this.children) {
if (obj instanceof PolicyType) {
PolicyType pol = (PolicyType) obj;
PolicyParser policyParser = new PolicyParser(condition, pol, attrMapper);
// return the MIDD with XACML decisions at the external nodes
AbstractNode xacmlMIDD = policyParser.parse();
if (xacmlMIDD == null) {// a never-applicable rule
System.err.println("Found a non-transformable MIDD policy:" + pol.getPolicyId());
} else {
lstMIDDs.add(xacmlMIDD);
}
} else if (obj instanceof PolicySetType) {
PolicySetType polset = (PolicySetType) obj;
PolicySetParser psParser = new PolicySetParser(condition, polset, attrMapper, policyFinder);
// return the MIDD with XACML decisions at the external nodes
AbstractNode xacmlMIDD = psParser.parse();
if (xacmlMIDD == null) {// a never-applicable rule
log.error("Found a non-transformable MIDD policy set:" + polset.getPolicySetId());
} else {
lstMIDDs.add(xacmlMIDD);
}
} else {
throw new MIDDParsingException("Unknown children policyset type");
}
}
// combine MIDDs using policyset's policy-combining-algorithm
CombiningAlgorithm pca = CombiningAlgConverterUtil.getAlgorithm(policyset.getPolicyCombiningAlgId());
return combinePolicyMIDDs(lstMIDDs, pca);
}
}