Search code examples
oauth-2.0authorizationxacmlabacalfa

Switch from custom ABAC to XACML


I'm going to secure my Spring Cloud Application with OAuth2 and XACML (using AuthZForce).

I've implemented a simple ABAC solution, that can handle the following use-case, but I want to switch to XACML. Is it possible?

old domain

I have (in database):

  • policies (e.g. subject.id==resource.ownerId), that are checked by the enfocement-point to make a decision
  • permissions (e.g. DELETE_USER), that have some defined policies
  • roles (e.g. EMPLOYEE), that hold some permissions
  • features (e.g. PREMIUM), that hold some default and by company usable roles and permissions
  • companies, that have some features
  • users, that are assigned to company

use-case

Now a user from a company can create a new role ROLE_X. He can assign some permissions to this role.

UPDATE

Because this question originally contains two different questions, I decided to outsource the second question (AuthZForce for Spring Cloud)


Solution

  • Where you store policies is largely irrelevant. It will depend on the engine you use e.g. AuthZForce (I've pinged the author so he can chip in), SunXACML, WSO2, or Axiomatics.

    Disclaimer: I work for Axiomatics. We do use a database to store XACML policies but that does not change the authorization requirements or modelling.

    I have a couple comments on your original post.

    • subject.id==resource.ownerId is what we typically call a condition in XACML. You compare 2 attributes together to implement a relationship.
    • You mention permissions e.g. DELETE_USER. In XACML you typically split those up into atomic attributes e.g. an action on the one hand and an object or resource on the other (USER). While RBAC is role- and permission-based, ABAC is attribute-based. Ideally those attributes denote a single aspect (being a user, trying to delete...)
    • ROLE still exists in ABAC. It will be the basis for your policies.
    • features and companies are attributes you would use.

    With that in mind, you can write policies such as the following (using ALFA notation):

    namespace axiomatics{
    
        namespace user{
            attribute role{
                category = subjectCat
                id = "axiomatics.user.role"
                type = string
            }
            attribute company{
                category = subjectCat
                id = "axiomatics.user.company"
                type = string
            }
            attribute userId{
                category = subjectCat
                id = "axiomatics.user.userId"
                type = string
            }
        }
    
        namespace action{
            attribute actionId{
                category = actionCat
                id = "axiomatics.action.actionId"
                type = string
            }        
        }
    
        namespace resource{
            attribute company{
                category = resourceCat
                id = "axiomatics.resource.company"
                type = string
            }
            attribute owner{
                category = resourceCat
                id = "axiomatics.resource.owner"
                type = string
            }
        }
    
        policyset springapp{
            apply firstApplicable
            policy employees{
                target clause user.role == "employee"
                apply firstApplicable
                /**
                 * Employees can create roles in their own company
                 */
                 rule createRole{
                     target clause action.actionId=="create"
                     condition user.company==resource.company
                     permit
                 }
                 /**
                  * Employees can delete roles they own
                  */
                rule allowDelete{
                    target clause action.actionId == "delete"
                    condition user.userId == resource.owner
                    permit
                }
            }
        }
    }