/* Copyright 2012-2015 SAP SE
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package eu.aniketos.securebpmn.export.xacml.export;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import com.sun.xacml.*;
import com.sun.xacml.attr.AnyURIAttribute;
import com.sun.xacml.attr.AttributeDesignator;
import com.sun.xacml.attr.AttributeValue;
import com.sun.xacml.attr.StringAttribute;
import com.sun.xacml.attr.TypeIdentifierConstants;
import com.sun.xacml.combine.PolicyCombiningAlgorithm;
import com.sun.xacml.combine.RuleCombiningAlgorithm;
import com.sun.xacml.cond.Condition;
import com.sun.xacml.cond.EqualFunction;
import com.sun.xacml.cond.Evaluatable;
import com.sun.xacml.cond.Function;
/**
* Provides the methods to create a complete XACML policy.
*
*/
public class XacmlFileBuilder {
/**
* output is used in {@link #encodePolicySet()} to provide a source for the
* XML encoded Data
*/
private OutputStream output;
private PolicySet policySet;
private List<Rule> rules;
private List<PolicyTreeElement> policies;
private List<TargetMatch> matches;
private List<TargetMatchGroup> matchGroups;
private List<TargetSection> targetSections;
public XacmlFileBuilder() throws FileNotFoundException, ParsingException, UnknownIdentifierException {
// createSodCondition();
output = new ByteArrayOutputStream();
policies = new ArrayList<PolicyTreeElement>();
rules = new ArrayList<Rule>();
matches = new ArrayList<TargetMatch>();
matchGroups = new ArrayList<TargetMatchGroup>();
targetSections = new ArrayList<TargetSection>();
}
/**
* Takes the completed {@link PolicySet} and encodes it to XML-format.
*
* @throws RuntimeException
* if encoding fails
* @return {@link XacmlFileBuilder#output} The encoded
* <code>PolicySet</code> in its XML-formatted version.
*/
public OutputStream encodePolicySet() {
try {
this.policySet.encode(output, "UTF-8");
} catch (UnsupportedEncodingException e) {
// e.printStackTrace();
throw new RuntimeException("error during encoding process", e);
}
return output;
}
/**
* Creates a new {@link PolicySet}. <br>
* </br> And clears the {@link #policies}-list for the next
* <code>PolicySet</code>
*
* @param policySetID
* the <code>PolicySet</code> identifier
* @param policyCombiningAlg
* the <code>CombiningAlgorithm</code> used on the policies in
* this set
* @param target
* the <code>Target</code> for this <code>PolicySet</code> (may
* be null)
* @param policies
* a list of the policies in this set
*/
public void createPolicySet(URI policySetID,
PolicyCombiningAlgorithm policyCombiningAlg, Target target,
List<PolicyTreeElement> policies) {
policySet = new PolicySet(policySetID, policyCombiningAlg, target,
policies);
this.policies.clear();
}
//TODO finish sod check if needed after pdp impl
/*
public boolean evalSodCondition(Task currentTask, List<Task> connectedTasks) {
// check if user of currentTask has claimed/completed any of the tasks
// in the connectedTasks list
Main_Test main_Test = new Main_Test();
TaskService ts = main_Test.getTaskService();
HistoryService hs = main_Test.getHistoryService();
// get the current user of the given sod task
org.activiti.engine.task.Task focusedTask = ts.createTaskQuery()
.processDefinitionKey(currentTask.getId()).singleResult();
String currentUser = focusedTask.getAssignee();
// check if this user has already performed an action on a connected sod
// task
for (Iterator<Task> iterator = connectedTasks.iterator(); iterator
.hasNext();) {
Task task = (Task) iterator.next();
String taskIdToCheck = task.getId();
if (hs.createHistoricTaskInstanceQuery().taskAssignee(currentUser)
.count() != 0) {
return false;
}
}
return true;
}
*/
//TODO finish sod check if needed after pdp impl
/*
public Condition createSodCondition(Task currentTask,
List<Task> connectedTasks) {
Expression expression = new EqualFunction(EqualFunction.NAME_BOOLEAN_EQUAL);
Condition condition = new Condition(expression);
return condition;
}
*/
/**
* Creates a new {@link Rule}.
*
* @param ruleID
* the identifier of the <code>Rule</code>
* @param effect
* the result if the <code>Rule</code> applies as defined in
* {@link Result}
* @param ruleDescription
* a textual description for the <code>Rule</code> (may be null)
* @param target
* the <code>Target</code> for the <code>Rule</code>, or null if
* it should be inherited from the parent <code>Policy</code> or
* <code>PolicySet</code>
* @param condition
* the <code>Condition</code> for this <code>Rule</code> (may be
* null)
*/
public void createRule(URI ruleID, int effect, String ruleDescription,
Target target, Condition condition) {
Rule rule = new Rule(ruleID, effect, ruleDescription, target, condition);
if (!rules.contains(rule)) {
rules.add(rule);
}
}
/**
* Creates a new {@link Policy}.
*
* @param policyID
* the identifier of the <code>Policy</code>
* @param ruleCombiningAlg
* the <code>CombiningAlgorithm</code> used on the rules in this
* <code>Policy</code>
* @param target
* the <code>Target</code> for the <code>Policy</code>, or null
* if it should be inherited
* @param rules
* a list of the rules in this <code>Policy</code>
*/
public void createPolicy(URI policyID,
RuleCombiningAlgorithm ruleCombiningAlg, Target target,
List<Rule> rules) {
Policy policy = new Policy(policyID, ruleCombiningAlg, target, rules);
if (!policies.contains(policy)) {
policies.add(policy);
}
this.rules.clear();
}
/**
* Creates a new {@link TargetMatch}.
*
* @param matchType
* used to determine which match type will be used <li>
* 1:Subject-Role</li> <li>2:Resource</li> <li>3:Action</li>
* @param attrValueString
* the name of the target to match
* @throws URISyntaxException
*/
public void createTargetMatch(int matchType, String attrValueString) throws URISyntaxException {
URI category = null;
URI attrType = null;
URI attrId = null;
Function function = null;
AttributeValue attrValue = null;
switch (matchType) {
case 1:
category = Constants.SUBJECT_CAT;
attrType = TypeIdentifierConstants.STRING_URI;
attrId = URI.create("urn:custom:subject:role");
function = new EqualFunction(EqualFunction.NAME_STRING_EQUAL);
attrValue = new StringAttribute(attrValueString);
break;
case 2:
category = Constants.RESOURCE_CAT;
attrType = TypeIdentifierConstants.ANYURI_URI;
attrId = Constants.RESOURCE_ID;
function = new EqualFunction(EqualFunction.NAME_ANYURI_EQUAL);
attrValue = new AnyURIAttribute(new URI(attrValueString));
break;
case 3:
category = Constants.ACTION_CAT;
attrType = TypeIdentifierConstants.STRING_URI;
attrId = Constants.ACTION_ID;
function = new EqualFunction(EqualFunction.NAME_STRING_EQUAL);
attrValue = new StringAttribute(attrValueString);
break;
default:
System.out.println("\ncategory error\n");
break;
}
Evaluatable eval = new AttributeDesignator(category, attrType, attrId,
false, null);
TargetMatch tm = new TargetMatch(function, eval, attrValue);
matches.add(tm);
}
/**
* Creates a new {@link TargetMatchGroup}. <br>
* And adds it to the local {@link #matchGroups}-list</br>
*/
private void createTargetMatchGroup() {
TargetMatchGroup tmg = new TargetMatchGroup(matches);
matchGroups.add(tmg);
}
/**
* Creates a new {@link TargetSection}. <br>
* And adds it to the local {@link #targetSections}-list</br>
*/
private void createTargetSection() {
TargetSection ts = new TargetSection(matchGroups);
targetSections.add(ts);
}
/**
* Creates a new {@link Target}. <br>
* </br> Uses {@link #createTargetMatchGroup()} and
* {@link #createTargetSection()} to create a <code>Target</code>. <br>
* It clears the {@link #matches}, {@link #matchGroups},
* {@link #targetSections}-lists for the next <code>Target</code>.</br>
*
* @return <b>target</b> the created <code>Target</code>
*/
public Target createTarget() {
createTargetMatchGroup();
createTargetSection();
Target target = new Target(getTargetSections());
matches.clear();
matchGroups.clear();
targetSections.clear();
return target;
}
/*
* non-javadoc
*
* following are the needed getters for the XacmlExportMarshaller
*/
private List<TargetSection> getTargetSections() {
return targetSections;
}
public List<Rule> getRules() {
return rules;
}
public List<PolicyTreeElement> getPolicies() {
return policies;
}
}