Комплексная авторизация с использованием XACML

Моя компания стремится внедрить централизованную службу безопасности, и, похоже, популярным стандартом для нее является XACML. У меня сложный сценарий авторизации, и мне трудно понять, как его можно определить с помощью атрибутов для политик XACML.

Система, над которой я работаю, имеет несколько частей, относящихся к этому сценарию аутентификации:

  • Пользователи создают проекты, чтобы организовать свою работу. У каждого проекта есть список членов команды и зрителей (пользователей или групп, которые могут просматривать проект, но не могут его изменять).
  • В рамках этих проектов пользователи создают рецепты, описывающие, как что-то должно производиться.
  • Пользователи делают запросы на изготовление этих рецептов другой группой.

В случае, если пользователь хочет просмотреть рецепт определенного предмета, должно выполняться любое из следующих условий:

  • Пользователь должен быть владельцем рецепта (человеком, который его написал).
  • Пользователь должен быть членом команды проекта, в котором был создан рецепт. (напрямую или через членство в группе)
  • Пользователь должен быть членом группы, производящей рецепт. (Им нужно увидеть рецепт для его изготовления.)
  • Пользователь должен быть членом группы, которая разработала рецепт в течение последних двух недель. (то есть после выполнения запроса на изготовление рецепта они могут продолжать просматривать рецепт в течение двух недель, чтобы исправить любые проблемы.)
  • Пользователь должен быть администратором.

С этими правилами кажется, что атрибуты, необходимые для определения, может ли пользователь просматривать рецепт, включают:

  • Пользователь
  • Членство в группе пользователя (для доступа к проекту, производственной группе или доступу администратора)
  • Члены команды проекта и зрители
  • Заявки на изготовление рецепта

Вопросов:

  • Как PIP будет собирать эту информацию? Прямо из базы данных? Через служебные вызовы в систему, которая хранит эту информацию?
  • Как эта информация будет представлена ​​для XACML (в целом)? В большинстве примеров, которые я видел, используются простые модели, которые не используют наборы данных (например, список производственных запросов); просто атрибуты непосредственно на объекте, к которому осуществляется доступ. Будут ли данные как-то сглажены, например "isBeingManufacturedByUserGroup"? (и если да, то как можно определить значение этого атрибута?)
  • Как будет структурирована политика для оценки этих правил?
  • Есть ли альтернативы для обработки такого рода авторизации (кроме XACML)? Сможет ли OAuth 2.0 легче справиться с подобными проблемами?

person Shawn    schedule 04.01.2017    source источник


Ответы (1)


(отказ от ответственности - я работаю в Axiomatics, ведущей реализации XACML и ABAC)

Отличный вопрос. Я фактически составил жизненный цикл политики авторизации, который проводит пользователей через процесс сбора требований, определения атрибутов и реализации политик.

«Жизненный

В вашем случае давайте рассмотрим ваши требования

Сбор требований

Ваши первоначальные требования

Должно выполняться любое из следующих утверждений:

  • Пользователь должен быть владельцем рецепта (человеком, который его написал).
  • Пользователь должен быть членом команды проекта, в котором был создан рецепт. (напрямую или через членство в группе)
  • Пользователь должен быть членом группы, производящей рецепт. (Им нужно увидеть рецепт для его изготовления.)
  • Пользователь должен быть членом группы, которая разработала рецепт в течение последних двух недель. (то есть после выполнения запроса на изготовление рецепта они могут продолжать просматривать рецепт в течение двух недель, чтобы исправить любые проблемы.)
  • Пользователь должен быть администратором.

Реструктуризация требований

Мне нравится переделывать требования как подлежащее - глагол - объект, например. Пользователь может просмотреть рецепт ... На основе этой модели ваши первоначальные требования могут быть переформулированы следующим образом:

  1. Пользователь может просмотреть рецепт, которым владеет.
  2. Пользователь может просмотреть рецепт, созданный внутри проекта, к которому он принадлежит.
  3. Пользователь может просматривать рецепт на стадии производства, который принадлежит к (производственной) группе, к которой принадлежит пользователь.
  4. Пользователь может просматривать рецепт на стадии изготовления, которая принадлежит к группе (производственной), к которой принадлежит пользователь, и если дата изготовления находится в пределах 2 недель от сегодняшней даты.
  5. Администраторы могут просматривать рецепты.

Определить атрибуты

Вы можете разбить атрибуты на разные категории (или грамматические функции). XACML сам использует категории, поэтому это естественный шаг к реализации с использованием XACML (или ALFA) .

Атрибуты темы

  • userId: ключевой атрибут в этой категории. Он будет использоваться для идентификации пользователя, а также для получения всех других производных атрибутов.
  • проект: список проектов, к которым принадлежит пользователь
  • группа: список групп, к которым принадлежит пользователь
  • роль: роль пользователя, например.

Атрибуты ресурсов

  • objectType: это атрибут, который вы используете, чтобы различать разные типы элементов, к которым вы хотите контролировать доступ, например. рецепт, документ или транзакция
  • recipeId: ключевой атрибут рецептов. Он будет использоваться для определения того, к какому конкретному рецепту вы хотите получить доступ, а также будет служить ключом для поиска других атрибутов, например. состояние, в котором находится рецепт, группа и проект, к которому он принадлежит.
  • группа: группа, к которой принадлежит рецепт
  • project: проект, которому принадлежит рецепт

Атрибуты действия

В этой категории, судя по всему, у вас есть только:

  • actionId с потенциальными значениями {просмотр, редактирование, удаление ...}.

Требования переписаны с использованием атрибутов

  1. Любой может выполнить действие == "просмотр" для objectType == "рецепт", если recipe.owner == userId
  2. Любой может выполнить действие == "просмотр" для objectType == "рецепт", если recipe.project == user.project
  3. Любой может выполнить действие == "просмотр" для objectType == "рецепт", если recipe.stage == "производство" и recipe.group == user.group.
  4. Любой может выполнить действие == "просмотр" для objectType == "recipe", если recipe.stage == "made" и recipe.group == user.group и currentDate ‹= recipe.manufacturedDate +" 2 недели ".
  5. Любой человек с ролью == "администратор" может выполнить действие == "просмотр" для objectType == "рецепт".

Реализация политик с использованием ALFA или XACML

Следующим шагом будет реализация вашей политики. Вы можете использовать ALFA (сокращенный язык для авторизации). Axiomatics имеет плагин Eclipse, который переводит ALFA в XACML 3.0.

Давайте создадим набор политик, который обрабатывает рецепты. Этот набор политик будет содержать политику, которая обрабатывает представление действий. Эта политика, в свою очередь, будет содержать правила, учитывающие каждое требование.

policyset recipe{
    target clause objectType == "recipe"
    apply firstApplicable
    /**
     * View recipes
     */
    policy viewRecipe{
        target clause actionId == "view"
        apply firstApplicable
        /**
         * Administrators can view all recipes
         */
        rule administrator{
            target clause user.role == "administrator"
            permit
        }
        /**
         * Recipe owners can view their own recipes
         */
        rule owner{
            permit
            condition user.userId == recipe.owner
        }
        /**
         * Users can view recipes in their project
         */
         rule sameProject{
             permit
             condition user.assignedProject == recipe.assignedProject
         }
        /**
         * Users can view recipes in their project
         */
         rule sameGroup{
             target clause recipe.stage == "manufacturing"
             permit
             condition user.assignedGroup == recipe.assignedGroup
         }
        /**
         * Users can view recipes in their project
         */
         rule sameGroupManufactured{
             target clause recipe.stage == "manufacturing"
             permit
             condition user.assignedGroup == recipe.assignedGroup && currentDate<=dateTimeAddDayTimeDuration(dateTimeOneAndOnly(recipe.manufacturedDate),"P14D":dayTimeDuration)
         }
    }
}

Использование пунктов информации о политике

Как PIP будет собирать эту информацию? Прямо из базы данных? Через служебные вызовы в систему, которая хранит эту информацию?

PIP - это просто абстрактное понятие источника внешнего атрибута. Это может быть что угодно. В разных реализациях будут разные разъемы PIP. Например, сервер политики Axiomatics предоставляет соединители для служб SQL, LDAP и REST. Это покрывает большинство потребностей клиента.

XACML и OAuth 2.0

Вы сравниваете обе технологии, но они чем-то немного отличаются. OAuth 2.0 в первую очередь ориентирован на аутентификацию. Он собирался победить анти-шаблон пароля. Затем возникла необходимость определить разрешения или, как их называют в OAuth, области действия. Однако эти области являются только пунктуальными разрешениями. Вы по-прежнему полагаетесь на то, что целевое приложение публикует набор допустимых областей, и вы по-прежнему не можете выполнять детальный контроль доступа. Мой коллега написал по этой теме блог из трех частей, первую часть которого вы можете прочтите здесь.

Надеюсь, это поможет. Не стесняйтесь задавать уточняющие вопросы или писать мне в Твиттере.

Вывод 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:PolicySet xmlns:xacml3="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17"
    PolicySetId="http://axiomatics.com/alfa/identifier/so.recipe"
    PolicyCombiningAlgId="urn:oasis:names:tc:xacml:1.0:policy-combining-algorithm:first-applicable"
    Version="1.0">
    <xacml3:Description>Control access to recipes</xacml3:Description>
    <xacml3:PolicySetDefaults>
        <xacml3:XPathVersion>http://www.w3.org/TR/1999/REC-xpath-19991116</xacml3:XPathVersion>
    </xacml3:PolicySetDefaults>
    <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">recipe</xacml3:AttributeValue>
                    <xacml3:AttributeDesignator 
                        AttributeId="so.objectType"
                        DataType="http://www.w3.org/2001/XMLSchema#string"
                        Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource"
                        MustBePresent="false"
                    />
                </xacml3:Match>
            </xacml3:AllOf>
        </xacml3:AnyOf>
    </xacml3:Target>
    <xacml3:Policy xmlns:xacml3="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17"
        PolicyId="http://axiomatics.com/alfa/identifier/so.recipe.viewRecipe"
        RuleCombiningAlgId="urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:first-applicable"
        Version="1.0">
        <xacml3:Description>View recipes</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">view</xacml3:AttributeValue>
                        <xacml3:AttributeDesignator 
                            AttributeId="so.actionId"
                            DataType="http://www.w3.org/2001/XMLSchema#string"
                            Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action"
                            MustBePresent="false"
                        />
                    </xacml3:Match>
                </xacml3:AllOf>
            </xacml3:AnyOf>
        </xacml3:Target>
        <xacml3:Rule 
                Effect="Permit"
                RuleId="http://axiomatics.com/alfa/identifier/so.recipe.viewRecipe.administrator">
            <xacml3:Description>Administrators can view all recipes</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">administrator</xacml3:AttributeValue>
                            <xacml3:AttributeDesignator 
                                AttributeId="so.user.role"
                                DataType="http://www.w3.org/2001/XMLSchema#string"
                                Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"
                                MustBePresent="false"
                            />
                        </xacml3:Match>
                    </xacml3:AllOf>
                </xacml3:AnyOf>
            </xacml3:Target>
        </xacml3:Rule>
        <xacml3:Rule 
                Effect="Permit"
                RuleId="http://axiomatics.com/alfa/identifier/so.recipe.viewRecipe.owner">
            <xacml3:Description>Recipe owners can view their own recipes</xacml3:Description>
            <xacml3:Target />
            <xacml3:Condition>
                <xacml3:Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:any-of-any">
                    <xacml3:Function FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-equal"/>
                    <xacml3:AttributeDesignator 
                        AttributeId="so.user.userId"
                        DataType="http://www.w3.org/2001/XMLSchema#string"
                        Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"
                        MustBePresent="false"
                    />
                    <xacml3:AttributeDesignator 
                        AttributeId="so.recipe.owner"
                        DataType="http://www.w3.org/2001/XMLSchema#string"
                        Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource"
                        MustBePresent="false"
                    />
                </xacml3:Apply>
            </xacml3:Condition>
        </xacml3:Rule>
        <xacml3:Rule 
                Effect="Permit"
                RuleId="http://axiomatics.com/alfa/identifier/so.recipe.viewRecipe.sameProject">
            <xacml3:Description>Users can view recipes in their project</xacml3:Description>
            <xacml3:Target />
            <xacml3:Condition>
                <xacml3:Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:any-of-any">
                    <xacml3:Function FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-equal"/>
                    <xacml3:AttributeDesignator 
                        AttributeId="so.user.assignedProject"
                        DataType="http://www.w3.org/2001/XMLSchema#string"
                        Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"
                        MustBePresent="false"
                    />
                    <xacml3:AttributeDesignator 
                        AttributeId="so.recipe.assignedProject"
                        DataType="http://www.w3.org/2001/XMLSchema#string"
                        Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource"
                        MustBePresent="false"
                    />
                </xacml3:Apply>
            </xacml3:Condition>
        </xacml3:Rule>
        <xacml3:Rule 
                Effect="Permit"
                RuleId="http://axiomatics.com/alfa/identifier/so.recipe.viewRecipe.sameGroup">
            <xacml3:Description>Users can view recipes in their project</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">manufacturing</xacml3:AttributeValue>
                            <xacml3:AttributeDesignator 
                                AttributeId="so.recipe.stage"
                                DataType="http://www.w3.org/2001/XMLSchema#string"
                                Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource"
                                MustBePresent="false"
                            />
                        </xacml3:Match>
                    </xacml3:AllOf>
                </xacml3:AnyOf>
            </xacml3:Target>
            <xacml3:Condition>
                <xacml3:Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:any-of-any">
                    <xacml3:Function FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-equal"/>
                    <xacml3:AttributeDesignator 
                        AttributeId="so.user.assignedGroup"
                        DataType="http://www.w3.org/2001/XMLSchema#string"
                        Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"
                        MustBePresent="false"
                    />
                    <xacml3:AttributeDesignator 
                        AttributeId="so.recipe.assignedGroup"
                        DataType="http://www.w3.org/2001/XMLSchema#string"
                        Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource"
                        MustBePresent="false"
                    />
                </xacml3:Apply>
            </xacml3:Condition>
        </xacml3:Rule>
        <xacml3:Rule 
                Effect="Permit"
                RuleId="http://axiomatics.com/alfa/identifier/so.recipe.viewRecipe.sameGroupManufactured">
            <xacml3:Description>Users can view recipes in their project</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">manufacturing</xacml3:AttributeValue>
                            <xacml3:AttributeDesignator 
                                AttributeId="so.recipe.stage"
                                DataType="http://www.w3.org/2001/XMLSchema#string"
                                Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource"
                                MustBePresent="false"
                            />
                        </xacml3:Match>
                    </xacml3:AllOf>
                </xacml3:AnyOf>
            </xacml3:Target>
            <xacml3:Condition>
                <xacml3:Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:and">
                    <xacml3:Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:any-of-any">
                        <xacml3:Function FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-equal"/>
                        <xacml3:AttributeDesignator 
                            AttributeId="so.user.assignedGroup"
                            DataType="http://www.w3.org/2001/XMLSchema#string"
                            Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"
                            MustBePresent="false"
                        />
                        <xacml3:AttributeDesignator 
                            AttributeId="so.recipe.assignedGroup"
                            DataType="http://www.w3.org/2001/XMLSchema#string"
                            Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource"
                            MustBePresent="false"
                        />
                    </xacml3:Apply>
                    <xacml3:Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:any-of">
                        <xacml3:Function FunctionId="urn:oasis:names:tc:xacml:1.0:function:dateTime-greater-than-or-equal"/>
                        <xacml3:Apply FunctionId="urn:oasis:names:tc:xacml:3.0:function:dateTime-add-dayTimeDuration" >
                            <xacml3:Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:dateTime-one-and-only" >
                                <xacml3:AttributeDesignator 
                                    AttributeId="so.recipe.manufacturedDate"
                                    DataType="http://www.w3.org/2001/XMLSchema#dateTime"
                                    Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource"
                                    MustBePresent="false"
                                />
                            </xacml3:Apply>
                            <xacml3:AttributeValue
                                DataType="http://www.w3.org/2001/XMLSchema#dayTimeDuration">P14D</xacml3:AttributeValue>
                        </xacml3:Apply>
                        <xacml3:AttributeDesignator 
                            AttributeId="currentDate"
                            DataType="http://www.w3.org/2001/XMLSchema#dateTime"
                            Category="urn:oasis:names:tc:xacml:3.0:attribute-category:environment"
                            MustBePresent="false"
                        />
                    </xacml3:Apply>
                </xacml3:Apply>
            </xacml3:Condition>
        </xacml3:Rule>
    </xacml3:Policy>
</xacml3:PolicySet>
person David Brossard    schedule 05.01.2017
comment
Это фантастическая информация - большое спасибо. У меня есть продолжение: в наборе правил у вас есть ссылки на user.AssignedProject и user.AssignedGroup (или user.project и user.group). Возможно, это было неясно в исходном сообщении, но пользователь может быть членом команды в нескольких проектах и ​​состоять в нескольких группах - как это будет обрабатываться реализацией XACML? Или он уплощен, как соединение SQL, где каждая комбинация значений повторяется индивидуально? - person Shawn; 05.01.2017
comment
Мне было интересно об этом (мощности). Есть функции, которые вы можете использовать для этого. Вместо выполнения == вы можете использовать stringIsIn или stringAtLeastOneMemberOf - person David Brossard; 05.01.2017
comment
Значит, нужно было где-то выполнить сглаживание? Например, user.groups (множественное число) будет объединенной строкой идентификаторов для каждой группы, в которую они входят? (и группы, членами которых являются эти группы) - person Shawn; 05.01.2017
comment
Нет. Атрибуты в XACML многозначны. Таким образом, атрибут user.groups может иметь несколько значений. Нет необходимости сглаживать или объединять - person David Brossard; 05.01.2017
comment
Нужно ли объединять иерархическую информацию (группы групп) в единый список групп (идентификаторы групп)? Или есть способ пройти по иерархии? - person Shawn; 05.01.2017
comment
по умолчанию, если вы определяете один атрибут группы, вы получите набор значений группы, но вы также можете смоделировать иерархию - person David Brossard; 05.01.2017