发送包中包含多个值的 XACML 请求以供策略评估
Sending XACML request with multiple values in bag to be evaluated by policy
下面是中国墙的 XACML 策略,它使用 stringAtLeastOneMemberOf
比较两个属性,看它们是否包含相同的值列表值。
即如果请求访问对象的主题具有标签 [1, 4, 5]
并且对象具有标签 [2, 3, 5]
则访问将被拒绝,因为两者都包含 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
}
}
}
XACML 政策
<?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>
政策执行点 (PEP) 代码
我正在使用 Authzforce Core PDP for Java 模拟 PDP,我按如下方式评估请求:
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);
}
本例中的 JSONObject
就是我将请求从客户端发送到 PDP 引擎的方式。其他策略有效,这里的问题是我向包发送一个字符串,即 "[2, 4, 5]"
,但它总是导致 NotApplicable
。是否有我应该在此处使用的列表类型以符合政策?
这是我要发送的JSON:
{
"principle": {
"conflicts": [
"1",
"2",
"10"
],
"id": "Principle 1",
"label": 3
},
"action": "read",
"object": {
"conflicts": [
"4",
"5",
"9"
],
"id": "Object 1",
"label": 2,
"type": "calcert"
}
}
挑战
更准确地说,java 代码中的 JSON 输出到 Authzforce 的冲突集将是一个字符串,即 "[2,3,5]"
而我认为这需要是另一种格式(因为它总是导致 NotApplicable),但这是我的问题。
您至少需要修复代码中的 2 个问题:
因为你想要一个字符串列表中的一个包,可能不止一个,你必须使用更通用的 Bags.newAttributeBag(...)
- 第二个参数必须是你的实际字符串列表 - 而不是 Bags.singletonAttributeBag()
。只有这样,它才会被 PDP 视为多个 String 类型的 AttributeValues。
您两次使用相同的主题属性 XACML_1_0_SUBJECT_CONFLICTS
,第二次是针对 objectConflicts 属性,所以我想这是错误的,需要将被修复,因为这必须是资源属性 urn:oasis:names:tc:xacml:1.0:resource:resource-conflicts
。
首先,您必须了解 XACML 中的所有属性在默认情况下都是值包。因此,urn:oasis:names:tc:xacml:1.0:resource:resource-conflicts
是一个可以包含 0(零)、1 或更多值的包。但它仍然是一个包。 ALFA / XACML 中的任何属性都是如此。这意味着当你写:
target clause resourceType=="calcert"
你实际上是在说 如果 resourceType
的至少一个值等于 calcert
...
在您的例子中,您使用的是一个名为 stringAtLeastOneMemberOf
的函数。此函数接收两个字符串类型的包,如果第一个包至少包含第二个包中存在的一个值,则 returns 为真。它与 stringIsIn
类似,只是后者接受一个原子字符串和一包字符串。您必须编写 stringIsIn(stringOneAndOnly(a), b)
才能使其工作。属性 a 也必须是一个包含单个值的包。
在您的例子中,您有 2 个属性(subjectConflicts
和 resourceConflicts
)可以是 multi-valued。这意味着如果您 "printed" 他们,您会看到类似 ["a"、"b"、"c"、"a"] 的内容。这是一袋价值。顺便说一句,袋子可以包含重复项。并且顺序无关紧要(属性顺序或属性值顺序)。
现在,您要做的是发送表示此内容的 XACML JSON 请求。结果 JSON 应如下所示:
样本JSON请求
在这个例子中,两个属性都是multi-valued:
{
"Request":{
"Resource":[
{
"Attribute":[
{
"AttributeId":"urn:oasis:names:tc:xacml:1.0:resource:resource-type",
"Value":"calcert"
},
{
"AttributeId":"urn:oasis:names:tc:xacml:1.0:resource:resource-conflicts",
"Value":[
"4",
"5",
"6"
]
}
]
}
],
"Action":[
{
"Attribute":[
{
"AttributeId":"urn:oasis:names:tc:xacml:1.0:action:action-id",
"Value":"read"
}
]
}
],
"AccessSubject":[
{
"Attribute":[
{
"AttributeId":"urn:oasis:names:tc:xacml:1.0:subject:subject-conflicts",
"Value":[
"1",
"2",
"3"
]
}
]
}
]
}
}
请求也可以写成
{
"Request":{
"Resource":[
{
"Attribute":[
{
"AttributeId":"urn:oasis:names:tc:xacml:1.0:resource:resource-type",
"Value":"calcert"
},
{
"AttributeId":"urn:oasis:names:tc:xacml:1.0:resource:resource-conflicts",
"Value":"4"
},
{
"AttributeId":"urn:oasis:names:tc:xacml:1.0:resource:resource-conflicts",
"Value":"5"
},
{
"AttributeId":"urn:oasis:names:tc:xacml:1.0:resource:resource-conflicts",
"Value":"6"
}
]
}
],
"Action":[
{
"Attribute":[
{
"AttributeId":"urn:oasis:names:tc:xacml:1.0:action:action-id",
"Value":"read"
}
]
}
],
"AccessSubject":[
{
"Attribute":[
{
"AttributeId":"urn:oasis:names:tc:xacml:1.0:subject:subject-conflicts",
"Value":"1"
},
{
"AttributeId":"urn:oasis:names:tc:xacml:1.0:subject:subject-conflicts",
"Value":"2"
},
{
"AttributeId":"urn:oasis:names:tc:xacml:1.0:subject:subject-conflicts",
"Value":"3"
}
]
}
]
}
}
示例 XACML JSON 响应
{
"Response":[
{
"Decision":"NotApplicable"
}
]
}
为请求/响应寻找合适的 SDK
在您的代码中,您使用了 AuthZForce 的 PEP SDK。西里尔在他的另一个回答中指出了主要错误:
AttributeBag<?> objectConflictsValue = Bags.singletonAttributeBag(StandardDatatypes.STRING, new StringValue(obj.getJSONObject("object").getString("conflicts")));
问题是您将冲突 ["1",...] 的整个字符串表示添加到 XACML 包内的单个值中,而不是单独添加每个部分。
在我的示例中,我使用了我自己的 Java JSON PEP SDK。代码如下所示:
将每个值相加 one-by-one:
resource.addAttribute(new Attribute("urn:oasis:names:tc:xacml:1.0:resource:resource-conflicts", "4"));
resource.addAttribute(new Attribute("urn:oasis:names:tc:xacml:1.0:resource:resource-conflicts", "5"));
resource.addAttribute(new Attribute("urn:oasis:names:tc:xacml:1.0:resource:resource-conflicts", "6"));
或添加为值数组:
resource.addAttribute(new Attribute("urn:oasis:names:tc:xacml:1.0:resource:resource-conflicts", new String[]{"4","5","6"}));
完整代码
package io.xacml.pep.json.so;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.xacml.json.model.Attribute;
import io.xacml.json.model.Category;
import io.xacml.json.model.Request;
import io.xacml.json.model.Response;
import io.xacml.json.model.Result;
import io.xacml.pep.json.client.AuthZClient;
import io.xacml.pep.json.client.ClientConfiguration;
import io.xacml.pep.json.client.DefaultClientConfiguration;
import io.xacml.pep.json.client.jaxrs.JaxRsAuthZClient;
import lombok.extern.slf4j.Slf4j;
/**
* This class contains sample code using JAX-RS to invoke a Policy Decision Point.
* It supports both the JSON Profile of XACML 1.0 (where the response could be either an Object or
* an Array) and the JSON Profile of XACML 1.1 (where the response is always an array - to simplify
* things)
*
* @author djob
*/
@Slf4j
public class Example {
public static void main(String[] args) {
ObjectMapper mapper = new ObjectMapper();
ClientConfiguration clientConfiguration = DefaultClientConfiguration.builder()
.pdpUrl("http://djob-hp:8080")
.username("ads-user")
.password("secret")
.build();
// Add user attributes
Category subject = new Category();
subject.addAttribute(new Attribute("urn:oasis:names:tc:xacml:1.0:subject:subject-conflicts", "1"));
subject.addAttribute(new Attribute("urn:oasis:names:tc:xacml:1.0:subject:subject-conflicts", "2"));
subject.addAttribute(new Attribute("urn:oasis:names:tc:xacml:1.0:subject:subject-conflicts", "3"));
// Add action attributes - if any
Category action = new Category();
action.addAttribute(new Attribute("urn:oasis:names:tc:xacml:1.0:action:action-id", "read"));
// Add user attributes
Category resource = new Category();
resource.addAttribute(new Attribute("urn:oasis:names:tc:xacml:1.0:resource:resource-type", "calcert"));
resource.addAttribute(new Attribute("urn:oasis:names:tc:xacml:1.0:resource:resource-conflicts", "4"));
resource.addAttribute(new Attribute("urn:oasis:names:tc:xacml:1.0:resource:resource-conflicts", "5"));
resource.addAttribute(new Attribute("urn:oasis:names:tc:xacml:1.0:resource:resource-conflicts", "6"));
Request authZRequest = new Request();
authZRequest.addAccessSubjectCategory(subject);
authZRequest.addActionCategory(action);
authZRequest.addResourceCategory(resource);
AuthZClient authZClient = new JaxRsAuthZClient(clientConfiguration, mapper);
Response authZResponse = authZClient.makeAuthorizationRequest(authZRequest);
for (Result r : authZResponse.getResults()) {
log.debug(r.getDecision().name());
}
}
}
下面是中国墙的 XACML 策略,它使用 stringAtLeastOneMemberOf
比较两个属性,看它们是否包含相同的值列表值。
即如果请求访问对象的主题具有标签 [1, 4, 5]
并且对象具有标签 [2, 3, 5]
则访问将被拒绝,因为两者都包含 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
}
}
}
XACML 政策
<?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>
政策执行点 (PEP) 代码
我正在使用 Authzforce Core PDP for Java 模拟 PDP,我按如下方式评估请求:
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);
}
本例中的 JSONObject
就是我将请求从客户端发送到 PDP 引擎的方式。其他策略有效,这里的问题是我向包发送一个字符串,即 "[2, 4, 5]"
,但它总是导致 NotApplicable
。是否有我应该在此处使用的列表类型以符合政策?
这是我要发送的JSON:
{
"principle": {
"conflicts": [
"1",
"2",
"10"
],
"id": "Principle 1",
"label": 3
},
"action": "read",
"object": {
"conflicts": [
"4",
"5",
"9"
],
"id": "Object 1",
"label": 2,
"type": "calcert"
}
}
挑战
更准确地说,java 代码中的 JSON 输出到 Authzforce 的冲突集将是一个字符串,即 "[2,3,5]"
而我认为这需要是另一种格式(因为它总是导致 NotApplicable),但这是我的问题。
您至少需要修复代码中的 2 个问题:
因为你想要一个字符串列表中的一个包,可能不止一个,你必须使用更通用的
Bags.newAttributeBag(...)
- 第二个参数必须是你的实际字符串列表 - 而不是Bags.singletonAttributeBag()
。只有这样,它才会被 PDP 视为多个 String 类型的 AttributeValues。您两次使用相同的主题属性
XACML_1_0_SUBJECT_CONFLICTS
,第二次是针对 objectConflicts 属性,所以我想这是错误的,需要将被修复,因为这必须是资源属性urn:oasis:names:tc:xacml:1.0:resource:resource-conflicts
。
首先,您必须了解 XACML 中的所有属性在默认情况下都是值包。因此,urn:oasis:names:tc:xacml:1.0:resource:resource-conflicts
是一个可以包含 0(零)、1 或更多值的包。但它仍然是一个包。 ALFA / XACML 中的任何属性都是如此。这意味着当你写:
target clause resourceType=="calcert"
你实际上是在说 如果 resourceType
的至少一个值等于 calcert
...
在您的例子中,您使用的是一个名为 stringAtLeastOneMemberOf
的函数。此函数接收两个字符串类型的包,如果第一个包至少包含第二个包中存在的一个值,则 returns 为真。它与 stringIsIn
类似,只是后者接受一个原子字符串和一包字符串。您必须编写 stringIsIn(stringOneAndOnly(a), b)
才能使其工作。属性 a 也必须是一个包含单个值的包。
在您的例子中,您有 2 个属性(subjectConflicts
和 resourceConflicts
)可以是 multi-valued。这意味着如果您 "printed" 他们,您会看到类似 ["a"、"b"、"c"、"a"] 的内容。这是一袋价值。顺便说一句,袋子可以包含重复项。并且顺序无关紧要(属性顺序或属性值顺序)。
现在,您要做的是发送表示此内容的 XACML JSON 请求。结果 JSON 应如下所示:
样本JSON请求
在这个例子中,两个属性都是multi-valued:
{
"Request":{
"Resource":[
{
"Attribute":[
{
"AttributeId":"urn:oasis:names:tc:xacml:1.0:resource:resource-type",
"Value":"calcert"
},
{
"AttributeId":"urn:oasis:names:tc:xacml:1.0:resource:resource-conflicts",
"Value":[
"4",
"5",
"6"
]
}
]
}
],
"Action":[
{
"Attribute":[
{
"AttributeId":"urn:oasis:names:tc:xacml:1.0:action:action-id",
"Value":"read"
}
]
}
],
"AccessSubject":[
{
"Attribute":[
{
"AttributeId":"urn:oasis:names:tc:xacml:1.0:subject:subject-conflicts",
"Value":[
"1",
"2",
"3"
]
}
]
}
]
}
}
请求也可以写成
{
"Request":{
"Resource":[
{
"Attribute":[
{
"AttributeId":"urn:oasis:names:tc:xacml:1.0:resource:resource-type",
"Value":"calcert"
},
{
"AttributeId":"urn:oasis:names:tc:xacml:1.0:resource:resource-conflicts",
"Value":"4"
},
{
"AttributeId":"urn:oasis:names:tc:xacml:1.0:resource:resource-conflicts",
"Value":"5"
},
{
"AttributeId":"urn:oasis:names:tc:xacml:1.0:resource:resource-conflicts",
"Value":"6"
}
]
}
],
"Action":[
{
"Attribute":[
{
"AttributeId":"urn:oasis:names:tc:xacml:1.0:action:action-id",
"Value":"read"
}
]
}
],
"AccessSubject":[
{
"Attribute":[
{
"AttributeId":"urn:oasis:names:tc:xacml:1.0:subject:subject-conflicts",
"Value":"1"
},
{
"AttributeId":"urn:oasis:names:tc:xacml:1.0:subject:subject-conflicts",
"Value":"2"
},
{
"AttributeId":"urn:oasis:names:tc:xacml:1.0:subject:subject-conflicts",
"Value":"3"
}
]
}
]
}
}
示例 XACML JSON 响应
{
"Response":[
{
"Decision":"NotApplicable"
}
]
}
为请求/响应寻找合适的 SDK
在您的代码中,您使用了 AuthZForce 的 PEP SDK。西里尔在他的另一个回答中指出了主要错误:
AttributeBag<?> objectConflictsValue = Bags.singletonAttributeBag(StandardDatatypes.STRING, new StringValue(obj.getJSONObject("object").getString("conflicts")));
问题是您将冲突 ["1",...] 的整个字符串表示添加到 XACML 包内的单个值中,而不是单独添加每个部分。
在我的示例中,我使用了我自己的 Java JSON PEP SDK。代码如下所示:
将每个值相加 one-by-one:
resource.addAttribute(new Attribute("urn:oasis:names:tc:xacml:1.0:resource:resource-conflicts", "4"));
resource.addAttribute(new Attribute("urn:oasis:names:tc:xacml:1.0:resource:resource-conflicts", "5"));
resource.addAttribute(new Attribute("urn:oasis:names:tc:xacml:1.0:resource:resource-conflicts", "6"));
或添加为值数组:
resource.addAttribute(new Attribute("urn:oasis:names:tc:xacml:1.0:resource:resource-conflicts", new String[]{"4","5","6"}));
完整代码
package io.xacml.pep.json.so;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.xacml.json.model.Attribute;
import io.xacml.json.model.Category;
import io.xacml.json.model.Request;
import io.xacml.json.model.Response;
import io.xacml.json.model.Result;
import io.xacml.pep.json.client.AuthZClient;
import io.xacml.pep.json.client.ClientConfiguration;
import io.xacml.pep.json.client.DefaultClientConfiguration;
import io.xacml.pep.json.client.jaxrs.JaxRsAuthZClient;
import lombok.extern.slf4j.Slf4j;
/**
* This class contains sample code using JAX-RS to invoke a Policy Decision Point.
* It supports both the JSON Profile of XACML 1.0 (where the response could be either an Object or
* an Array) and the JSON Profile of XACML 1.1 (where the response is always an array - to simplify
* things)
*
* @author djob
*/
@Slf4j
public class Example {
public static void main(String[] args) {
ObjectMapper mapper = new ObjectMapper();
ClientConfiguration clientConfiguration = DefaultClientConfiguration.builder()
.pdpUrl("http://djob-hp:8080")
.username("ads-user")
.password("secret")
.build();
// Add user attributes
Category subject = new Category();
subject.addAttribute(new Attribute("urn:oasis:names:tc:xacml:1.0:subject:subject-conflicts", "1"));
subject.addAttribute(new Attribute("urn:oasis:names:tc:xacml:1.0:subject:subject-conflicts", "2"));
subject.addAttribute(new Attribute("urn:oasis:names:tc:xacml:1.0:subject:subject-conflicts", "3"));
// Add action attributes - if any
Category action = new Category();
action.addAttribute(new Attribute("urn:oasis:names:tc:xacml:1.0:action:action-id", "read"));
// Add user attributes
Category resource = new Category();
resource.addAttribute(new Attribute("urn:oasis:names:tc:xacml:1.0:resource:resource-type", "calcert"));
resource.addAttribute(new Attribute("urn:oasis:names:tc:xacml:1.0:resource:resource-conflicts", "4"));
resource.addAttribute(new Attribute("urn:oasis:names:tc:xacml:1.0:resource:resource-conflicts", "5"));
resource.addAttribute(new Attribute("urn:oasis:names:tc:xacml:1.0:resource:resource-conflicts", "6"));
Request authZRequest = new Request();
authZRequest.addAccessSubjectCategory(subject);
authZRequest.addActionCategory(action);
authZRequest.addResourceCategory(resource);
AuthZClient authZClient = new JaxRsAuthZClient(clientConfiguration, mapper);
Response authZResponse = authZClient.makeAuthorizationRequest(authZRequest);
for (Result r : authZResponse.getResults()) {
log.debug(r.getDecision().name());
}
}
}