Below is an XACML policy, for Chinese Walls, which uses stringAtLeastOneMemberOf
to compare two attributes two see if they contain the same value of a list of values.
I.e. if the subject requesting access to an object has a label [1, 4, 5]
and the object has a label [2, 3, 5]
then access will be denied as both contain 5
.
attribute subjectConflicts {
id = "urn:oasis:names:tc:xacml:1.0:subject:subject-conflicts"
type = string
category = subjectCat
}
attribute resourceConflicts {
id = "urn:oasis:names:tc:xacml:1.0:resource:resource-conflicts"
type = string
category = resourceCat
}
namespace models {
import Attributes.*
/*
*
* This policy implements the Chinese Wall model.
*
*/
policy ChineseWall {
target clause resourceType=="calcert"
apply firstApplicable
/*
* Check subject is not in conflict with object OEMs and calibrators
*
* This rule will deny access is user.label contains at least 1 value that is also present
* in object.label
*/
rule noconflict {
target clause actionId=="read" or actionId=="write"
condition stringAtLeastOneMemberOf(subjectConflicts, resourceConflicts)
deny
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!--This file was generated by the ALFA Plugin for Eclipse from Axiomatics AB (http://www.axiomatics.com).-->
<!--Any modification to this file will be lost upon recompilation of the source ALFA file-->
<xacml3:Policy xmlns:xacml3="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" PolicyId="http://axiomatics.com/alfa/identifier/models.ChineseWall" RuleCombiningAlgId="urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:first-applicable" Version="1.0">
<xacml3:Description>This policy implements the Chinese Wall model.</xacml3:Description>
<xacml3:PolicyDefaults>
<xacml3:XPathVersion>http://www.w3.org/TR/1999/REC-xpath-19991116</xacml3:XPathVersion>
</xacml3:PolicyDefaults>
<xacml3:Target>
<xacml3:AnyOf>
<xacml3:AllOf>
<xacml3:Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
<xacml3:AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">calcert</xacml3:AttributeValue>
<xacml3:AttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-type" Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="false" />
</xacml3:Match>
</xacml3:AllOf>
</xacml3:AnyOf>
</xacml3:Target>
<xacml3:Rule Effect="Deny" RuleId="models.ChineseWall.noconflict">
<xacml3:Description>Check subject is not in conflict with object OEMs and calibrators
This rule will deny access is user.label contains at least 1 value that is also present
in object.label</xacml3:Description>
<xacml3:Target>
<xacml3:AnyOf>
<xacml3:AllOf>
<xacml3:Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
<xacml3:AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">read</xacml3:AttributeValue>
<xacml3:AttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id" Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="false" />
</xacml3:Match>
</xacml3:AllOf>
<xacml3:AllOf>
<xacml3:Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
<xacml3:AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">write</xacml3:AttributeValue>
<xacml3:AttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id" Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="false" />
</xacml3:Match>
</xacml3:AllOf>
</xacml3:AnyOf>
</xacml3:Target>
<xacml3:Condition>
<xacml3:Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-at-least-one-member-of">
<xacml3:AttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:subject:subject-conflicts" Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="false" />
<xacml3:AttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-conflicts" Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="false" />
</xacml3:Apply>
</xacml3:Condition>
</xacml3:Rule>
</xacml3:Policy>
I am using the Authzforce Core PDP for Java to emulate the PDP and I evaluate the request as follows:
private DecisionRequest parseJSONAndBuildXACML(JSONObject obj) {
DecisionRequestBuilder builder = server.pdpEngine.getEngine().newRequestBuilder(-1, -1);
/** Add Principle **/
// Principle ID
AttributeFqn principleID = AttributeFqns.newInstance(XACML_1_0_ACCESS_SUBJECT.value(), Optional.empty(), XacmlAttributeId.XACML_1_0_SUBJECT_ID.value());
AttributeBag<?> principleIDValue = Bags.singletonAttributeBag(StandardDatatypes.STRING, new StringValue("Principle" + obj.getJSONObject("principle").getString("id")));
builder.putNamedAttributeIfAbsent(principleID, principleIDValue);
// Principle Label
AttributeFqn principleLabel = AttributeFqns.newInstance(XACML_1_0_ACCESS_SUBJECT.value(), Optional.<String>empty(), XACML_1_0_SUBJECT_LABEL);
AttributeBag<?> principleLabelValue = Bags.singletonAttributeBag(StandardDatatypes.INTEGER, new IntegerValue(new MediumInteger(obj.getJSONObject("principle").getInt("label"))));
builder.putNamedAttributeIfAbsent(principleLabel, principleLabelValue);
// Principle Conflict Set
AttributeFqn principleConflicts = AttributeFqns.newInstance(XACML_1_0_ACCESS_SUBJECT.value(), Optional.empty(), XACML_1_0_SUBJECT_CONFLICTS);
Collection<StringValue> pconflicts = getStringListFromJsonArray(obj.getJSONObject("principle").getJSONArray("conflicts"));
AttributeBag<?> principleConflictsValue = Bags.newAttributeBag(StandardDatatypes.STRING, pconflicts);
//AttributeBag<?> principleConflictsValue = Bags.singletonAttributeBag(StandardDatatypes.STRING, new StringValue(obj.getJSONObject("principle").getString("conflicts")));
builder.putNamedAttributeIfAbsent(principleConflicts, principleConflictsValue);
// Object ID
AttributeFqn objectID = AttributeFqns.newInstance(XACML_3_0_RESOURCE.value(), Optional.empty(), XACML_1_0_RESOURCE_ID.value());
AttributeBag<?> objectIDValue = Bags.singletonAttributeBag(StandardDatatypes.STRING, new StringValue(obj.getJSONObject("object").getString("id")));
builder.putNamedAttributeIfAbsent(objectID, objectIDValue);
// Object Type
AttributeFqn objectType = AttributeFqns.newInstance(XACML_3_0_RESOURCE.value(), Optional.empty(), XACML_1_0_RESOURCE_TYPE);
AttributeBag<?> objectTypeValue = Bags.singletonAttributeBag(StandardDatatypes.STRING, new StringValue(obj.getJSONObject("object").getString("type")));
builder.putNamedAttributeIfAbsent(objectType, objectTypeValue);
// Object Label
AttributeFqn objectLabel = AttributeFqns.newInstance(XACML_3_0_RESOURCE.value(), Optional.<String>empty(), XACML_1_0_RESOURCE_LABEL);
AttributeBag<?> objectLabelValue = Bags.singletonAttributeBag(StandardDatatypes.INTEGER, new IntegerValue(new MediumInteger(obj.getJSONObject("object").getInt("label"))));
builder.putNamedAttributeIfAbsent(objectLabel, objectLabelValue);
// Object Conflict Set
AttributeFqn objectConflicts = AttributeFqns.newInstance(XACML_3_0_RESOURCE.value(), Optional.empty(), XACML_1_0_RESOURCE_CONFLICTS);
Collection<StringValue> oconflicts = getStringListFromJsonArray(obj.getJSONObject("object").getJSONArray("conflicts"));
AttributeBag<?> objectConflictsValue = Bags.newAttributeBag(StandardDatatypes.STRING, oconflicts);
//AttributeBag<?> objectConflictsValue = Bags.singletonAttributeBag(StandardDatatypes.STRING, new StringValue(obj.getJSONObject("object").getString("conflicts")));
builder.putNamedAttributeIfAbsent(objectConflicts, objectConflictsValue);
// Action
AttributeFqn action = AttributeFqns.newInstance(XACML_3_0_ACTION.value(), Optional.empty(), XacmlAttributeId.XACML_1_0_ACTION_ID.value());
AttributeBag<?> actionValue = Bags.singletonAttributeBag(StandardDatatypes.STRING, new StringValue(obj.getString("action")));
builder.putNamedAttributeIfAbsent(action, actionValue);
return builder.build(false);
}
The JSONObject
in this case is just how I send the request from my client to the PDP engine. Other policies work, the problem here is I am sending a String i.e. "[2, 4, 5]"
to the bag, but it always results in a NotApplicable
. Is there are list type that I should be using here instead to conform with the policy?
Here is the JSON I am sending:
{
"principle": {
"conflicts": [
"1",
"2",
"10"
],
"id": "Principle 1",
"label": 3
},
"action": "read",
"object": {
"conflicts": [
"4",
"5",
"9"
],
"id": "Object 1",
"label": 2,
"type": "calcert"
}
}
To be more precise, the JSON output in the java code to Authzforce for the conflict set will be a string i.e. "[2,3,5]"
whereas I think this needs to be another format (since it always results in NotApplicable), but this is my question.
You need to fix at least 2 issues in your code:
Since you want a bag from a list of Strings, possibly more than one, you have to use the more generic Bags.newAttributeBag(...)
- second argument must be your actual List of Strings - instead of Bags.singletonAttributeBag()
. Only then will it be treated by the PDP as multiple AttributeValues of type String.
You are using the same subject attribute XACML_1_0_SUBJECT_CONFLICTS
twice, and second time is for objectConflicts attribute, so I guess this is wrong and needs to be fixed since this must be the resource attribute urn:oasis:names:tc:xacml:1.0:resource:resource-conflicts
instead.