Внимание! Компонент В данный момент к прямому использованию не пригоден, в связи с поставленными Issues, При желании Вы можете внести свой вклад в развитие данного компонента в конечном итоге с расчетом на результат и интегрирование с другими фреймворками и библиотеками.
- Контекст - это источник информации на момент вычисления доступа. (Что?(Объект) Кто?(Пользователь) Зачем?(Применяемое действие), Где?(Данные окружения))
- Вычисляемый - Объект который можно вычислить благодаря Контексту и получить Результат вычисления, субъективно, имеется ввиду что то одно из Правила, Политики или Группы политик.
- Комбинатор - метод перебора множества Вычисляемых, комбинирующий решения дочерних Вычисляемых поголовно, таким образом чтобы дать результирующее решение контейнера.
- Агрегатор - контейнер содержащий множество Вычисляемых объектов и использующий Комбинатор для результата вычисления.
- Цель - это абстрактный барьер перед выполнением Агрегации, является провайдером Условий.
- Правило - это конкретный объект вычисляющий решение, также является провайдером одного Условия.
- Условие - заданная сверка двух значений, значения каждого операнда(стороны сравнения) могут представлятся статично или ссылкой на Контекст.
- Политика - Агрегатор Правил, проверяет применимость Цели к Контексту, после чего выполняет дальнейшую Агрегацию.
- Группа политик - Агрегатор Политик, проверяет применимость Цели к Контексту, после чего выполняет дальнейшую Агрегацию.
- NOT_APPLICABLE (Не применимо) - Условия Целей или Правил не соответствуют Контексту.
- INDETERMINATE (Не определено) - Ошибка помешавшая выявить решение
- PERMIT (Разрешить) TRUE - Разрешение
- DENY (Заретить) FALSE - Запрет
Итоговое решение может быть только PERMIT или DENY
-
NOT_APPLICABLE - это означает что ни один Вычисляемый не имел соответствий с Контекстом, поэтому итоговое значение будет назначено исходя из базирования менеджера(Разрешающий(Permit) или Запрещающий(Deny))
-
INDETERMINATE - склонен к отказу, т.к вычислить всё до конца не удастся изза ошибки на этапах связанных с вычислениями или завершения оных.
-
NOT_APPLICABLE - Возможно интерпретировать из NULL значения, т.к NOT_APPLICABLE является переопределяемым от контейнера (итоговое)
-
INDETERMINATE - Возможно реализовать при помощи Исключений
<?php
use Jungle\User\AccessControl\Adapter\PolicyAdater\Memory as MemoryPolicyAdapter;
use Jungle\User\AccessControl\Context;
use Jungle\User\AccessControl\Manager;
use Jungle\User\AccessControl\Matchable;
include './loader.php';
$manager = new Manager();
$resolver = new Matchable\Resolver\ConditionResolver();
$manager->setConditionResolver($resolver);
// .........$combiner_set declaration
$manager->setCombiner('delegate', new Matchable\Combiner($combiner_set['delegate']));
$manager->setCombiner('delegate_same', new Matchable\Combiner($combiner_set['delegate_same']));
$manager->setCombiner('same', new Matchable\Combiner($combiner_set['same']));
$manager->setCombiner('same_only', new Matchable\Combiner($combiner_set['same_only']));
$manager->setCombiner('same_by_same', new Matchable\Combiner($combiner_set['same_by_same']));
$manager->setCombiner('permit_by_permit', new Matchable\Combiner($combiner_set['permit_by_permit']));
$manager->setCombiner('deny_by_deny', new Matchable\Combiner($combiner_set['deny_by_deny']));
$manager->setCombiner('dispute', new Matchable\Combiner($combiner_set['dispute']));
$manager->setCombiner('dispute_all', new Matchable\Combiner($combiner_set['dispute_all']));
$manager->setDefaultCombiner('dispute_all');
$manager->setMainCombiner('dispute_all');
$manager->setDefaultEffect(Matchable::PERMIT);
$manager->setSameEffect(Matchable::DENY);
// .........$aggregator main declaration
// ............$context main declaration
$manager->setAggregator($aggregator);
$manager->setContext($context);
$aggregator = new MemoryPolicyAdapter(null);
$aggregator->build([
'policies' => [[
'effect' => true,
'name' => 'Работа с Записками',
'target' => [
'all_of' => '[object::class] = Note',
],
'combiner' => 'delegate',
'rules' => [[
'condition' => '[user.group] = Administrators'
],[
'condition' => '[object.owner_id] = [user.id]'
],[
'condition' => '[object.public] = true'
]]
],[
'effect' => true,
'name' => 'Администраторы',
'combiner' => 'dispute',
'obligation' => function(){
echo 'Вседозволенные Администраторы';
},
'target' => [
'all_of' => [
'[user.group] = Administrators',
]
],
],[
'effect' => false,
'name' => 'Анонимы',
'combiner' => 'dispute',
'target' => [
'all_of' => [
'[object::class] = Document',
'[user.group] = Anonymous',
]
],
'obligation' => function(){
echo 'Мы запрещаем работать здесь анонимам';
},
'policies' => [[
'effect' => true,
'rules' => [[
'condition' => '[action.name] = Read'
]],
'obligation' => function(){
echo 'Просматривать можно';
},
],[
'effect' => true,
'rules' => [[
'condition' => '[scope.time.week_day] in [TIME.WORK_DAYS]'
]],
'obligation' => function(){
echo 'Слава богу будние дни';
},
]],
],[
'effect' => false,
'name' => 'CurrentToken',
'obligation' => function(){
echo 'По токену Есть ограничения';
},
'combiner' => 'same_by_same',
'policies' => [[
'effect' => true,
'target' => [ 'all_of' => [ '[user.group] = Administrators', ], ],
'obligation' => function(){
echo 'Администраторам можно';
},
],[
'effect' => true,
'target' => [ 'all_of' => [ '[action.name] = Read', ], ],
'obligation' => function(){
echo 'Просмотр для токенов доступен';
},
],[
'effect' => true,
'combiner' => 'same_by_same',
'rules' => [[ 'condition' => '[scope.time.week_day] in [TIME.WORK_DAYS]' ]],
'obligation' => function(){
echo 'В рабочие дни токен работает';
},
]],
],[
'name' => 'Deny',
'effect' => false,
'target' => [
'all_of' => [
'[user.group] != Administrators'
]
],
'obligation' => function(){
echo 'Технические работы';
},
]]
]);
$context = new Context();
$context->setProperties([
'user' => [
'id' => 1,
'name' => 'John',
'login' => 'john.mail@site.com',
'group' => 'Anonymous',
'email' => 'john.mail@site.com',
'photo' => '/user/123223/avatar.jpg'
],
'route' => [
'module' => null,
'controller' => null,
'action' => null,
'params' => null
],
'client' => [
'request' => & $_REQUEST,
'server' => & $_SERVER,
'cookies' => & $_COOKIE,
'session' => & $_SESSION
]
], true);
Комбинатор нужно подбирать достаточно скурпулезно в зависимости от задач авторизации действий.
Агрегатор использует Комбинатор для вычисления своего решения.
Агрегатор базируется на эффекте.
Агрегатор может быть Не применим, это вычисляется при помощи Комбинирования дочерних Вычисляющих
- А.
delegate
Решение первого применимого дочернего делегируется как результат вычисления Агрегатора - Б.
delegate_same
Аналогия [A], но Агрегатор всегда является Применимым, при не применимости дочерних, его эффект будет в приоритете. - В.
same_only
Решение Агрегатора если минимум 1 дочерний равен Эффекту Агрегатора, и ни одного Противоположного - Г.
same_soft
Аналогия [В], но допускаются Не применимые
Принцип комбинирования ложится на пошаговый перебор, каждый раз нового Вычисляемого и на основе его Решения происходит реакции способные выдать итоговое решение, заранее или в конце итераций
Реакции определяются следующими событиями
Поведение при "Не применимых"
Поведение при "Не определенных"
Поведение при "Разрешающих"
Поведение при "Запрещающих"
Плейсхолдеры:
{same}
- Подстановка эффекта политики-контейнера{!same}
- Если не равно эффекту политики-контейнера{current}
- Эффект текущего правила
Описание ключей конфигурационного массива:
-
default
- Эффект по умолчанию, который выставляется перед перебором плавил в политике-контейнере -
empty
- Если политика-контейнер пустая и не содержит правил -
applicable
- Поведение при applicable Элементеcheck
- Проверка ЕСЛИcheck
- Может быть в качестве switch case case case- В таком случае значение должно быть индексным массивом, где каждый элемент будет в качестве правила(массива как и
applicable
)
- В таком случае значение должно быть индексным массивом, где каждый элемент будет в качестве правила(массива как и
early
- Закончить комбинирование не продолжая переборeffect
- Выставить эффект например{current}
-
not_applicable
- Поведение при not_applicable (Описывается как иapplicable
) -
deny
- Поведение при deny Элементе (Описывается как иapplicable
) -
permit
- Поведение при permit Элементе (Описывается как иapplicable
)
Пример:
$combiner_set = [
'delegate' => [
'default' => 'not_applicable',
'applicable' => [
'early' => true,
'effect' => '{current}'
],
],
'delegate_same' => [
'default' => '{same}',
'applicable' => [
'early' => true,
'effect' => '{current}'
],
],
'dispute' => [
'default' => '{same}',
'empty' => '{same}',
'applicable' => [
'check' => '{!same}',
'early' => true,
'effect' => '{current}'
],
],
'dispute_all' => [
'default' => '{same}',
'empty' => '{same}',
'applicable' => [
'check' => [[
'check' => '{!same}',
'effect' => '{current}'
],[
'check' => '{same}',
'early' => true,
'effect' => '{current}'
]]
],
],
'permit_by_permit' => [
'return_only' => 'permit',
'default' => 'not_applicable',
'empty' => 'not_applicable',
'deny' => [
'early' => true,
'effect' => 'not_applicable'
],
'permit' => [
'effect' => '{current}'
],
],
'deny_by_deny' => [
'return_only' => 'deny',
'default' => 'not_applicable',
'empty' => 'not_applicable',
'deny' => [
'effect' => '{current}'
],
'permit' => [
'early' => true,
'effect' => 'not_applicable'
],
],
'same_by_same' => [
'default' => 'not_applicable',
'empty' => 'not_applicable',
'applicable' => [
'check' => [[
'check' => '{!same}',
'early' => true,
'effect' => 'not_applicable'
],[
'check' => '{same}',
'effect' => '{same}'
]]
],
],
'same' => [
'default' => '{same}',
'empty' => '{same}',
'applicable' => [
'check' => '{!same}',
'early' => true,
'effect' => '{current}'
],
],
'same_only' => [
'default'=> '{same}',
'not_applicable' => [
'effect' => '{current}'
],
'applicable' => [
'check' => '{!same}',
'early' => true,
'effect' => '{current}'
]
],
];
Принцип был интерпретирован, переосмыслен и реализован по данной статье
ABAC предоставляет возможность, проверить права доступа на объект, до непосредственной выборки таковых из базы данных, посредством предварительной подготовки WHERE условий, которые должны совпадать для соответствия нужному решению ABAC Менеджера, таким образам результатом выборки будут объекты удовлетворяющие нужный эффект Все решается путем сбора Предикатов из Условий которые были проверены.
$object = new Context\ObjectAccessor([
'class' => 'Note',
'phantom' => [
'owner_id' => 2,
],
'predicate_effect' = true,
]);
$result = $manager->enforce('Read',$object, true);
if($result->isAllowed() === $object->getPredicateEffect()){
echo '<p><pre>';
var_dump($object->getSelectConditions());
echo '</pre></p>';
}else{
echo '<p><pre>';
var_dump($result->getEffect());
echo '</pre></p>';
}
Результат будет содержать WHERE совместимое выражение, которое следует добавить в критерии последующего запроса:
array(3) {
[0]=>
array(3) {
[0]=>
string(6) "public"
[1]=>
string(1) "="
[2]=>
bool(true)
}
[1]=>
string(3) "AND"
[2]=>
array(1) {
[0]=>
array(3) {
[0]=>
string(8) "owner_id"
[1]=>
string(1) "="
[2]=>
int(2)
}
}
}