Отправка запроса XACML с несколькими значениями в сумке для оценки политикой - PullRequest
1 голос
/ 04 июля 2019

Ниже приведена политика XACML для китайских стен, которая использует stringAtLeastOneMemberOf для сравнения двух атрибутов, два из которых определяют, содержат ли они одно и то же значение списка значений.

Т.е. если субъект запрашивает доступ кобъект имеет метку [1, 4, 5], а объект имеет метку [2, 3, 5], тогда в доступе будет отказано, так как оба содержат 5.

Политика Китайской стены

Код ALFA

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 для Java для эмуляции PDP и Iоцените запрос следующим образом:

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"
    }
}

Challenge

Чтобы бытьболее точно, вывод JSON в коде Java для Authzforce для набора конфликтов будет строкой, то есть "[2,3,5]", тогда как я думаю, что это должен быть другой формат (так как это всегда приводит к NotApplicable), но это мой вопрос.

Ответы [ 2 ]

2 голосов
/ 06 июля 2019

Вам необходимо исправить как минимум 2 проблемы в вашем коде:

  1. Так как вам нужен пакет из списка строк, возможно, из более чем одного, вы должны использовать более общий Bags.newAttributeBag(...) - второй аргумент должен быть вашим фактическим списком строк - вместо Bags.singletonAttributeBag(). Только тогда он будет обработан PDP как несколько значений AttributeValues ​​типа String.

  2. Вы используете один и тот же атрибут субъекта XACML_1_0_SUBJECT_CONFLICTS дважды, и второй раз - для атрибута objectConflicts , поэтому я думаю, что это неправильно и должно быть исправлено, поскольку это должен быть атрибут ресурса urn:oasis:names:tc:xacml:1.0:resource:resource-conflicts вместо.

0 голосов
/ 06 июля 2019

Прежде всего вы должны понимать, что все атрибуты в 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());
        }
    }
}
...