Прежде всего вы должны понимать, что все атрибуты в XACML по умолчанию являются пакетами значений. Итак, urn:oasis:names:tc:xacml:1.0:resource:resource-conflicts
- это мешок, который может содержать 0 (ноль), 1 или более значений. Но, тем не менее, это сумка. Это верно для любого атрибута в ALFA / XACML. Это означает, что когда вы пишете:
target clause resourceType=="calcert"
Вы на самом деле говорите , если есть хотя бы одно значение resourceType
, равное calcert
...
В вашем случае вы используете функцию с именем stringAtLeastOneMemberOf
. Эта функция принимает два пакета типа string и возвращает true, если первый пакет содержит хотя бы одно значение, присутствующее во втором пакете. Он похож на stringIsIn
за исключением того, что последний принимает атомную строку и пакет с цепочками. Вы должны написать stringIsIn(stringOneAndOnly(a), b)
, чтобы это работало. Атрибут a также должен быть сумкой, содержащей одно значение.
В вашем случае у вас есть 2 атрибута (subjectConflicts
и resourceConflicts
), которые могут быть многозначными. Это означает, что если вы «напечатаете» их, вы увидите что-то вроде [«a», «b», «c», «a»]. Это мешок ценностей. Кстати, сумки могут содержать дубликаты. И порядок не имеет значения (ни порядок атрибутов, ни порядок значений атрибутов).
Теперь вам нужно отправить запрос XACML JSON, который представляет это. Результирующий JSON должен выглядеть следующим образом:
Пример запроса JSON
В этом примере оба атрибута являются многозначными:
{
"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 для запросов / ответов
В своем коде вы используете PEP SDK от AuthZForce. Кирилл в своем другом ответе указал на главную ошибку:
AttributeBag<?> objectConflictsValue = Bags.singletonAttributeBag(StandardDatatypes.STRING, new StringValue(obj.getJSONObject("object").getString("conflicts")));
Проблема в том, что вы добавляете полное строковое представление конфликтов ["1", ...] внутри одного значения внутри пакета XACML, а не добавляете каждую часть по отдельности.
В моем примере я использовал свой собственный Java JSON PEP SDK . Код выглядит следующим образом:
Либо добавьте каждое значение одно за другим:
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());
}
}
}