In XACML and ALFA, how can I achieve a layered set of policies that check environment attributes?

571 views Asked by At

I want to write a layered policy whereby the first layer will always check the environment such as:

  • checking the user has a valid IP-address,
  • checking the time is within a valid time frame and day of the week
  • the user's device is a valid device

The lower layers will take care of the actual requested actions e.g. add, view, update, delete on a certain set of resources such as medical records, insurance data, bank accounts...

In plain English, the rules look like the following

Policy that permits if all environment rules return permit

  • Rule1: Only allow users with an IP-address that is in the range of [bag with ip-address ranges]
  • Rule2: Only allow requests for actions from monday to friday
  • Rule3: Only allow requests for actions from 7:00 AM to 22:00 PM
  • Rule4: Only allow requests for actions from a Desktop or a laptop

How can this be done using ALFA, the Axiomatics Language for Authorization?

1

There are 1 answers

1
David Brossard On BEST ANSWER

This is a good question and there are several good ways of doing it. One example would be to rewrite the logic and express the following:

  • PolicySet with a combining algorithm of first-applicable
    • deny if time is wrong
    • deny if device is invalid
    • deny if IP is not in valid range
    • set of possible actions and resources-based policies yielding a Permit.

This is what it looks like in ALFA:

namespace com.axiomatics.example{
    policyset global{       
        apply firstApplicable
        policy securityChecks{
            apply firstApplicable
            rule denyOutsideOfficeHours{
                deny
            }
            rule denyInvalidDevice{
                deny
            }
            rule denyInvalidIP{
                deny
            }
        }

        policyset myBusinessPolicies{
            apply firstApplicable
            /**
             * Add your business policies here
             */
        }

    }
}

This is merely the scaffolding. Let's now look at the attributes we need:

  • the current time
  • the user's current IP
  • the user's device type

We will not worry about how we obtained these values. It is up to the Policy Enforcement Point or Policy Information Point to worry about that.

The first rule will use the currentTime attribute. It is a default attribute in ALFA and is defined as follows:

attribute currentTime {
    id = "urn:oasis:names:tc:xacml:1.0:environment:current-time"
    type = time
    category = environmentCat
}

The updated rule now looks like the following:

rule denyOutsideOfficeHours{
    target clause currentTime<"09:00:00":time or currentTime>"17:00:00":time
    deny
}

In this example we use static lower and upper limits (9am and 5pm respectively) but these could also be attributes in which case we'd have to use a condition rather than a target. Note the ALFA notation used to convert the string value into the relevant datatype: "17:00:00":time.

The second rule looks as follows:

rule denyInvalidDevice{
    condition not(stringIsIn(stringOneAndOnly(deviceType), stringBag("laptop","desktop")))
    deny
}

In this rule, we have to use a condition because it is impossible to express a negative constraint in a target. The condition checks that there is an attribute called deviceType and that it contains a single value, no more and no less. That value must not be equal to either laptop or desktop in order for the deny to kick in. By the way, string comparison in XACML is case-sensitive by default.

The last rule is similar and again we have to use a condition to negate the test. Here we use the ipAddressRegexpMAtch XACML function to check whether the user's IP (subjectLocalityIpAddress) matches a given IP address pattern.

rule denyInvalidIP{
    condition not(
        ipAddressRegexpMatch(
            "^(10)\\.(10)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9])\\:([80|443])$", 
            ipAddressOneAndOnly(subjectLocalityIpAddress)
        )
    )
    deny
}

Note that the the backslash had to be escaped with another backslash. This is due to the ALFA syntax. The XACML policy itself, once converted to XML, will not contain 2 backslash characters.

The resulting policy all combined together is the following:

namespace com.axiomatics.example{
    import Attributes.*

    attribute deviceType{
        category = subjectCat
        id = "deviceType"
        type = string
    }

    attribute userIP{
        category = subjectCat
        id = "deviceType"
        type = string
    }

    policyset global{       
        apply firstApplicable
        policy securityChecks{
            apply firstApplicable
            rule denyOutsideOfficeHours{
                target clause currentTime<"09:00:00":time or currentTime>"17:00:00":time
                deny
            }
            rule denyInvalidDevice{
                condition not(stringIsIn(stringOneAndOnly(deviceType), stringBag("laptop","desktop")))
                deny
            }
            rule denyInvalidIP{
                condition not(
                    ipAddressRegexpMatch(
                        "^(10)\\.(10)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9])\\:([80|443])$", 
                        ipAddressOneAndOnly(subjectLocalityIpAddress)
                    )
                )
                deny
            }
        }

        policyset myBusinessPolicies{
            apply firstApplicable
            /**
             * Add your business policies here
             */
        }

    }
}

I hope this helps. Send us your questions via Stackoverflow or via our Developer's Blog.