Search code examples
xacmlabacalfa

1:n relationships and complex attribute types in ALFA


I'm trying to enter our database model into ALFA in order to check the capabilities of ALFA and XACML.

Are attributes like the following possible? How would look the rules then?

1:n by list of strings

namespace com.mycompany {
   namespace resources {
       namespace patient {
                attribute trustedDoctorIds{
                    category = resourceCat
                    id = "trustedDoctorIds"
                    type = list<string> //maybe it should be bag[string]
                }                
       }
   }
}

1:n by list of complex type

namespace com.mycompany {
   namespace resources {
       namespace patient {
                attribute trustedDoctors{
                    category = resourceCat
                    id = "trustedDoctors"
                    type = list<doctor> //maybe it should be bag[doctor]
                } 
       }
   }

   namespace subjects {
      namespace doctor {
          attribute id {
                    category = subjectCat
                    id = "id"
                    type = string
          }
          attribute lastname {
                    category = subjectCat
                    id = "lastname"
                    type = string
          }
      }
   }
}

Solution

  • You have a great question there.

    By default all attributes in ALFA and XACML are multi-valued. Attributes are bags of values rather than single values. This means that when you define the following,

                attribute trustedDoctorIds{
                    category = resourceCat
                    id = "trustedDoctorIds"
                    type = string
                }     
    

    This means the attribute has a type of string and it can be multi-valued. You could choose to express cardinality information in the comments above the attribute definition e.g.

    /**
     * This attribute, trustedDoctorIds, contains the list of doctors a patient 
     *trusts. The list can have 0 or more values.
     */
    

    The policy is the one that will convey how many values there can be depending on the functiosn being used.

    For instance, you could write a condition that states

    stringOneAndOnly(trustedDoctorIds)==stringOneAndOnly(userId)
    

    In that case, you are forcing each attribute to have one value and one value only. If you have 0 or more than 1 value, then the evaluation of the XACML policy will yield Indeterminate.

    In a XACML (or ALFA) target, when you write:

    trustedDoctorIds == "Joe"
    

    You are saying: if there is at least one value in trustedDoctorIds equal to 'Joe'...

    In an ALFA condition, when you write

    trustedDoctorIds==userId
    

    You are saying: *if there is at least one value in trustedDoctorIds equal to at least one value in userId

    Note: I always use singular names for my attributes when I can. It's a convention, not a hard limit. Remembering the cardinality of your attributes will help later in your policy testing.

    Answers to the comments

    What would be a plural name you try to avoid by your convention?

    Well trustedDoctorId***s*** looks rather plural to me. I would use trustedDoctorId unless you know that the attribute is necessarily always multi-valued.

    So, this should be possible: In my request I provide resource.patient.trustedDoctorIds=="2,13,67" and subject.doctor.id=="6". How would the rule then look like in ALFA? Smth. like "resource.patient.trustedDoctorIds.contains(subject.doctor.id) permit"

    The rule would look like the following:

    stringIsIn(stringOneAndOnly(subject.doctor.id),resource.patient.trustedDoctorIds)
    

    Make sure that you provide multiple values in your request, not one value that contains comma-separated values. Send in [1,2,3] rather than "1,2,3".

    Further edits

    So, by [2,13,67] the result is deny as expected and not permit like with "2,13,67" and doctorId==6. I chose that example on purpose, since the stringIsIn function would result unwantedly with true since 6 is included in 67

    Do not confuse stringIsIn() and stringContains().

    • stringIsIn(a, b) takes in 2 parameters a and b where a is an atomic value and b is a bag of values. stringIsIn(a, b) returns true if the value of a is in the bag of values of b.
    • stringContains(a, b) takes in 2 parameters a and b that are both atomic values of type string. It returns true if the string value a is found inside b.
    Example:
    • stringIsIn(stringOneAndOnly(userCitizenship), stringBag("Swedish", "German")) returns true if the user has a single citizenship equal to either of Swedish or German.
    • stringContains("a", "alfa") returns true if the second string contains the first one. So it returns true in this example.