How can I write a "If..then" condition in Axiomatics

122 Views Asked by At

The decisioning is to permit if the user has required roles. The required roles and the user's current permissions are in JSON format.

Required permissions: (Saved as a attribute)

{
  "data": {
    "service1": {
      "service1.1": true
    },
    "service2": {
      "service2.1: false,
      "service2.2": true,
      "service2.3": false
    }
  }
}

User's current permissions:

{
  "data": {
    "service1": {
      "service1.1": true
    },
    "service2": {
      "service2.1: false,
      "service2.2": false,
      "service2.3": true
    }
  }
}

To make the decision, we need to check if the user has the services as true similar to required Permissions. In the above example, the user has data.service1.service1.1 as true and data.service2.service2.3 as true where the required roles being data.service1.service1.1 as true and data.service2.service2.2 as true, in this case we deny.

I wrote separate rules to check for each and every service, but that would only be a check of combination of services.

   rule service1.1{               
    permit
    condition               
      (allOf(function[booleanEqual], true, requiredRoles.data.service1.service1.1))
      &&
      (allOf(function[booleanEqual], true, requiredRoles.data.service1.service1.1))        
        on permit {
            advice reasonForPermit{
            reasonAttribute=   "Contains Valid services" 
            }
        }
    }

Would someone please help on how to write a if.. then check in alfa?

2

There are 2 best solutions below

2
On

There is no if..then construct in ALFA (or XACML). You use combining algorithms instead. In particular, onPermitApplySecond is the policy combining algorithm that resembles an if..then construct the most.

However, there is usually a simpler way to express what you want if you can make reasonably assumptions on your attribute data. In your example, for instance, if it's always guaranteed that both the required and current permissions contain exactly one boolean value for each available service, then you could write:

rule {
    target 
        clause requiredRoles_service1_1 == false or permitted_service1_1 == true
        clause requiredRoles_service2_1 == false or permitted_service2_1 == true
        ...
    permit
}

Remember that in a target, clauses are AND'ed together. This rule then checks that, for every service, the role is either not required or is given in the current permissions.

If instead it may happen than any of those attributes is not present (i.e. there are no values for the attribute), then you have to guard against that case. You can do that using a condition like the following one, but there are other ways too:

rule {
    permit
    condition
        (not(booleanIsIn(true, requiredRoles_service1_1)) || booleanIsIn(true, permitted_service1_1))
        &&
        (not(booleanIsIn(true, requiredRoles_service2_1)) || booleanIsIn(true, permitted_service2_1))
        && 
        ...
}

All in all, there are usually simpler ways to express a policy if you can massage attribute data into other forms. Having a pair of attributes per service, like in the examples above, may not be necessary.

If you could gather all required roles and current permissions in one attribute each, then the policy can be expressed much more compactly. Let's say you have two attributes, requiredRoles and permittedRoles whose values list the service roles required and permitted for a given user, respectively. In your example, this would mean that requiredRoles has value, say, ["service1.1", "service2.2"] and permittedRoles has value ["service1.1", "service2.3"]. Then you can write a rule like this:

rule {
    permit
    condition stringSubSet(requiredRoles, permittedRoles)
}
0
On

I was able to do this by creating separate attributes for each service and wrote a rule with the target clause with the service from required roles and the condition will be if the service in the permitted role is true. I combined all the rules as below in the policy using permitunlessDeny algorithm

rule rule1 {        
    target clause requiredRoles.service1_1 == true
    deny
    condition 
        not(permittedRoles.service1_1 == true)
       
    on permit {
        advice reasonForPermit {
            reasonAttribute= "User has valid services" 
        }
    }
}

Thank you for the suggestion Pablo.