Search code examples
design-patternsxacmlabac

Using ABAC, how do I express a rule that subject A is allowed to share resource X with subject B?


Using ABAC, it is quite easy to express rules like:

A Subject (with position = 'Manager') is allowed to perform Action (with name = 'Write') on a Resource (with class = 'Document' and type = 'Report').

However, when controlling sharing events, you need to specify two types of Subjects: the person who does the sharing, and the intended recipient.

For example: a Manager might wish to share a report with a Junior in her department.

It is possible to write this as a series of rules involving both types of Subject, but how do you express the "directedness" of sharing, e.g., the Manager can share with the Junior but not vice-versa? I have tried several approaches but they all seem very verbose because of the Subject->Resource->Subject structure and I am not sure that they truly capture all the semantics of access-controlled sharing of content, such as might happen in an online social network.

Perhaps there is an underlying ABAC 'design pattern' for this....


Solution

  • There are a couple of ways you could model this in ABAC. I'll be using ALFA as a language in my example. ALFA translates directly into XACML.

    Using additional resource attributes

    Managers can share reports with junior staff in their department.

    In pseudo-code, it would become

    A user with role == "manager" can do action == "share" on object of type == "report" if user.department == recipient.department AND recipient.level == "junior"

    In this example, the attributes are defined as below:

    • role of category access-subject, type string
    • action of category action, type string
    • type of category resource, type string
    • user.department of category access-subject, type string
    • recipient.department of category resource, type string
    • recipient.level of category resource, type string

    Using the recipient-subject category

    Now, of course, you could argue that the recipient is not a resource but rather... a recipient. That's why XACML invented another type of subject category, the recipient-subject (urn:oasis:names:tc:xacml:1.0:subject-category:recipient-subject).

    As a matter of fact, XACML lets you define your own custom categories in addition to the standard ones. As a reminder XACML provides

    • urn:oasis:names:tc:xacml:3.0:attribute-category:resource
    • urn:oasis:names:tc:xacml:3.0:attribute-category:action
    • urn:oasis:names:tc:xacml:3.0:attribute-category:environment
    • urn:oasis:names:tc:xacml:1.0:subject-category:access-subject
    • urn:oasis:names:tc:xacml:1.0:subject-category:recipient-subject
    • urn:oasis:names:tc:xacml:1.0:subject-category:intermediary-subject
    • urn:oasis:names:tc:xacml:1.0:subject-category:codebase
    • urn:oasis:names:tc:xacml:1.0:subject-category:requesting-machine

    With that in mind, the attributes become:

    • role of category access-subject, type string
    • action of category action, type string
    • type of category resource, type string
    • user.department of category access-subject, type string
    • recipient.department of category recipient-subject, type string
    • recipient.level of category recipient-subject, type string

    And the ALFA policy becomes

    /**
     * Control access to reports
     */
    policyset report{
        target clause objectType == "report"
        apply firstApplicable
        /**
         * Share reports
         */
        policy shareReport{
            target clause actionId == "share"
            apply firstApplicable
            /**
             * Managers can share reports if...
             */
            rule managers{
                target clause user.role == "manager" and recipient.level == "junior"
                condition user.department == recipient.department
                permit
            }
        }
    } 
    

    In XACML the policy becomes

    <?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
        PolicyCombiningAlgId="urn:oasis:names:tc:xacml:1.0:policy-combining-algorithm:first-applicable"
        PolicySetId="http://axiomatics.com/alfa/identifier/com.axio.report"
        Version="1.0"
        xmlns:xacml3="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17">
        <xacml3:Description>Control access to reports</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">report</xacml3:AttributeValue>
                        <xacml3:AttributeDesignator
                            AttributeId="com.axiomatics.objectType"
                            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:Policy
            PolicyId="http://axiomatics.com/alfa/identifier/com.axio.report.shareReport"
            RuleCombiningAlgId="urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:first-applicable"
            Version="1.0">
            <xacml3:Description>Share reports</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">share</xacml3:AttributeValue>
                            <xacml3:AttributeDesignator
                                AttributeId="com.axiomatics.actionId"
                                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:Rule Effect="Permit"
                RuleId="com.axio.report.shareReport.managers">
                <xacml3:Description>Managers can share reports if...
                </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">manager</xacml3:AttributeValue>
                                <xacml3:AttributeDesignator
                                    AttributeId="com.axiomatics.user.role"
                                    Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"
                                    DataType="http://www.w3.org/2001/XMLSchema#string"
                                    MustBePresent="false" />
                            </xacml3:Match>
                            <xacml3:Match
                                MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
                                <xacml3:AttributeValue
                                    DataType="http://www.w3.org/2001/XMLSchema#string">junior</xacml3:AttributeValue>
                                <xacml3:AttributeDesignator
                                    AttributeId="com.axiomatics.recipient.level"
                                    Category="urn:oasis:names:tc:xacml:1.0:subject-category:recipient-subject"
                                    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:3.0:function:any-of-any">
                        <xacml3:Function
                            FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-equal" />
                        <xacml3:AttributeDesignator
                            AttributeId="com.axiomatics.user.department"
                            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="com.axiomatics.recipient.department"
                            Category="urn:oasis:names:tc:xacml:1.0:subject-category:recipient-subject"
                            DataType="http://www.w3.org/2001/XMLSchema#string"
                            MustBePresent="false" />
                    </xacml3:Apply>
                </xacml3:Condition>
            </xacml3:Rule>
        </xacml3:Policy>
    </xacml3:PolicySet>