Configuring Authorization Policies

Authors
Bradley Beddoes
Andre Zitelli
Shaun Mangelsdorf

Applicable Versions
Beta 2

Overview

The Enterprise Sign On Engine (ESOE) features a powerful authorization engine. ESOE controls which identities may access your enterprises resources. A wide range of identities are supported for authentication purposes. ESOE uses a language based on the XACML 2.0 standard released by OASIS. We've intentionally cut this down and called it Lightweight XACML (LXACML) for the following reasons:

  1. When demonstrating the design to clients many where worried about the complexity of the XACML specification and getting their heads around its concepts. The fact that ESOE would act as the decision point was a weird enough concept on its own. A request was put forward to find a suitable stepping stone.
  2. Our primary target initially was web based resources. This is a high volume environment in many cases which means that asking PDP for every single request was not going to be possible, we needed to cache responses, doing so with the full XACML specification was extremely complex
  3. XACML 3.0 specification was to be ratified shortly.

The core PDP is currently LXACML compliant. However, in the near future, we plan to offer an XACML 3.0 fully compliant sister PDP. This will allow ESOE for access resources where the use of the full XACML spec is warranted and caching is not required due to access volumes.

The design team feels we have struck a pretty good balance in the features that LXACML offers in regards to its bigger brother.

To describe how the PDP works internally you should consult the ESOE Administrators Guide

Lets start with an example...

The following simple policy is a good place to start as an example:
<Policy PolicyId="urn:simpletest">
       <Description>Simple Test Policy. 1 Rule. 1 Resource in 1 target.</Description>
      <Target>
        <Resources>
          <Resource>
            <AttributeValue>/default/.*</AttributeValue>
          </Resource>
        </Resources>
      </Target>
      <Rule Effect="Permit" RuleId="1">
        <Description>Simple test Rule. Permit all at default target.</Description>
      </Rule>
    </Policy>

The above rule defines the policy target resource /default/.* and one Rule. As the Rule does not define any target resources, the policy target resource will be applied to it when processing authorization requests. The Rule has no conditions, and the effect of the rule is PERMIT.

If a request is made for http://myservice.company.com/default/index.html, it will be matched against the policy resource target regular expression and the effect of the rule will be applied, resulting in the authorization processor returning PERMIT.

If any resource that does not start with /default is requested, it will fail to match any target resources and the default decision will be returned.

Components of a Policy

A Policy is made up of the following components
  • <Policy> - A set of rules applicable to some resource
  • <Target> - The set of decision requests, identified by definitions for resource, subject and action, that a rule or policy intended to evaluate
  • <Rule> - A target, an effect and a condition. A component of a policy
  • <Condition> - An expression of predicates. A function that evaluates to "True", "False" or "Indeterminate". Must be True for the rule effect to come into operation.
  • <Apply> - A boolean operator that may embed other <Apply> elements. Evaluates expressions to come to a boolean decision to supply to the condition.
  • <SubjectAttributeDesignator> - Specifies an attribute about the users identity that the rule wishes to make comparisons on.
    NB: The attribute itself does not need to be made available to the SPEP software, your ESOE administrator can provide you with a full list of attributes
  • <AttributeValue> - Specifies a value that must be present or match in defined form for its associated SubjectAttributeDesignator

By combining these powerful results can be achieved. A single policy can have an unlimited number of Rule elements, which, in turn, can have multiple boolean operators applied. Multiple policies also can be applied to a single service. Where this is the case, the combining algorithm used is such that all targets in all policies that match a resource request will be evaluated.

Available comparators

The following are able to be supplied to the <Apply> element as values for FunctionId
  • or - This function SHALL return "False" if it has no arguments and SHALL return "True" if at least one of its arguments evaluates to "True". The order of evaluation SHALL be from first argument to last. The evaluation SHALL stop with a result of "True" if any argument evaluates to "True", leaving the rest of the arguments unevaluated.
  • and - This function SHALL return "True" if it has no arguments and SHALL return "False" if one of its arguments evaluates to "False". The order of evaluation SHALL be from first argument to last. The evaluation SHALL stop with a result of "False" if any argument evaluates to "False", leaving the rest of the arguments unevaluated.
  • not - This function SHALL take one argument of data-type "http://www.w3.org/2001/XMLSchema#boolean". If the argument evaluates to "True", then the result of the expression SHALL be "False". If the argument evaluates to "False", then the result of the expression SHALL be "True".
  • string-equal - This function SHALL take two arguments of data-type "http://www.w3.org/2001/XMLSchema#string" and SHALL return an "http://www.w3.org/2001/XMLSchema#boolean". The function SHALL return "True" if and only if the value of both of its arguments are of equal length and each string is determined to be equal byte-by-byte according to the function "integer-equal". Otherwise, it SHALL return "False".
  • string-regexp-match - This function decides a regular expression match. It SHALL take two arguments of "http://www.w3.org/2001/XMLSchema#string" and SHALL return an "http://www.w3.org/2001/XMLSchema#boolean". The first argument SHALL be a regular expression and the second argument SHALL be a general string.
  • string-normalize-space - The function will have a result of the identified <AttributeValue> being normalized by stripping off all leading and trailing white space
  • string-normalize-to-lower-case - The function will have a result of the identified <AttributeValue> having each of its uppercase characters converted to its lowercase equivalent.

The default service policy

When a new service is created it has a policy associated with it by default as shown below:
<?xml version="1.0" encoding="UTF-16"?>
<Policy PolicyId="spep-0" 
    xmlns="http://www.qut.com/middleware/lxacmlSchema">
    <Description>
        First service policy, applies to all resources of the service -
        Please change this description
    </Description>
    <Target>
        <Resources>
            <Resource>
                <AttributeValue>.*</AttributeValue>
            </Resource>
        </Resources>
    </Target>
    <Rule Effect="Deny" RuleId="spep-rule-0">
        <Description>
            This rule causes all resource to be denied by default
        </Description>
    </Rule>
</Policy>

This means that every request to access the service will be denied . You need to extend the policy to support your particular applications.

Important points about Policy writing

  1. Each value for the PolicyId attribute across your service must be unique
  2. Each value for the RuleId attribute across your service must be unique
  3. For the Effect of a rule to be applied the Condition element must resolve to true (or not exist for that rule)
  4. Check out our Policy Templates for policy snippets you can simply copy and paste to get going quickly

Finally, ESOE policy is very powerful and flexible. You are given more than enough rope to hang yourself. For example, if OpenID and/or Shibboleth integration are enabled, you need to be very careful which resources you allow external users access to. Consider carefully what your enterprise requires and the potential risks involved. Make sure your policy is correct. If you are not sure, get your ESOE system administrator to validate your policies for you. THINK HARD ABOUT YOUR ENTERPRISE'S POLICY! TEST, TEST, TEST!

More example policies

Probably the best way to teach the syntax is through a variety of examples please review the below and ask questions if you need help with understanding.

Example 1

<Policy PolicyId="urn:policy:complexity:1">
      <Description>A complex policy with multiple rules and conditions. All permit rules must be recorded in the response.</Description>
      <Target>
        <Resources>
          <Resource>
            <AttributeValue>/default/.*</AttributeValue>
          </Resource>
          <Resource>
            <AttributeValue>.*/other/.*</AttributeValue>
          </Resource>
          <Resource>
            <AttributeValue>[A-Z]*/regex/\d*/[y]{2}.*</AttributeValue>
          </Resource>
        </Resources>
      </Target>
      <Rule Effect="Permit" RuleId="complexity:1-1">
        <Description>Permit access to any resources matched for this policy if the 'username' attribute contains a z</Description>
        <Condition>
          <Apply FunctionId="string-regex-match">
                  <SubjectAttributeDesignator AttributeId="username" />
                  <AttributeValue>.*z.*</AttributeValue>
          </Apply>
        </Condition>
      </Rule>
       <Rule Effect="Permit" RuleId="complexity:1-1a">
        <Description>Permit access to these resources if the 'username' attribute is equal to zitelli</Description>
        <Target>
            <Resources>
                      <Resource>
                          <AttributeValue>/default/-i.*</AttributeValue>
                      </Resource>
                      <Resource>
                          <AttributeValue>/other/not/so/public.*</AttributeValue>
                      </Resource>
              </Resources>
        </Target>
        <Condition>
          <Apply FunctionId="string-equal">
                  <SubjectAttributeDesignator AttributeId="username" />
                  <Apply FunctionId="string-normalize-to-lower-case" />
                  <AttributeValue>zitelli</AttributeValue>
          </Apply>
        </Condition>
      </Rule>
      <Rule Effect="Deny" RuleId="complexity:1-2">
          <Description>DENY everyone access to following resources</Description>
          <Target>
              <Resources>
                  <Resource>
                      <AttributeValue>/default/private/.*</AttributeValue>
                  </Resource>
                  <Resource>
                      <AttributeValue>/other/secret/.*</AttributeValue>
                  </Resource>
              </Resources>
          </Target>
      </Rule>
      <Rule Effect="Deny" RuleId="complexity:1-3">
          <Description>No subject attribute designator = Invalid Rule. Any matches on these targets will
           result in a deny being returned by the PDP.</Description>
          <Target>
              <Resources>
                  <Resource>
                      <AttributeValue>/other/test/brokenrule.jsp</AttributeValue>
                  </Resource>
              </Resources>
          </Target>
          <Condition>
          <Apply FunctionId="string-regex-match">
                  <AttributeValue>.*z.*</AttributeValue>
          </Apply>
        </Condition>
      </Rule>
    </Policy>

Example 2

<!--  all rules in this policy must apply to default target. Not a good example of usage but good for testing -->
    <Policy PolicyId="urn:qut:policy:complex:4">
        <Description>Description</Description>
        <Target>
            <Resources>
                <Resource>
                    <AttributeValue>/default/private/.*</AttributeValue>
                </Resource>
                <Resource>
                    <AttributeValue>
                        /default/something/hello.jsp
                    </AttributeValue>
                </Resource>
                <Resource>
                    <AttributeValue>/painful/.*</AttributeValue>
                </Resource>
            </Resources>
        </Target>
        <Rule Effect="Permit" RuleId="complexity:4-5g4">
            <Description>Description</Description>
            <Condition>
                <Apply FunctionId="string-regex-match">
                    <SubjectAttributeDesignator AttributeId="username" />
                    <AttributeValue>smith</AttributeValue>
                    <AttributeValue>.*zitelli.*</AttributeValue>
                </Apply>
            </Condition>
        </Rule>
        <Rule Effect="Permit" RuleId="complexity:4-64">
            <Description>Description</Description>
        </Rule>
        <Rule Effect="Permit" RuleId="complexity:4-cond:1">
            <Description>Complex conditions</Description>
            <!--  any users who email attribute contains the regex -->
            <Condition>
                <!--  all 3 apply elements must evaluate to false. A fairly useless condition though.-->
                <Apply FunctionId="not">
                    <Apply FunctionId="string-regex-match">
                        <SubjectAttributeDesignator
                            AttributeId="username" />
                        <AttributeValue>zffitelli</AttributeValue>
                    </Apply>
                    <Apply FunctionId="string-regex-match">
                        <SubjectAttributeDesignator AttributeId="email" />
                        <AttributeValue>.*s4ghh.*</AttributeValue>
                    </Apply>
                    <Apply FunctionId="string-regex-match">
                        <SubjectAttributeDesignator AttributeId="type" />
                        <AttributeValue>test</AttributeValue>
                    </Apply>
                </Apply>
            </Condition>
        </Rule>
        <Rule Effect="Permit" RuleId="complexity:4-cond:OUCH">
            <Description>
                Complex conditions. This condition reads as: ( username
                = beddoes and email contains beddoes AND type !=
                part-time-staff or student) OR (username = zitelli and
                email contains zitelli AND type != part-time-staff or
                student)
            </Description>
            <Target>
                <Resources>
                    <Resource>
                        <AttributeValue>
                            /painful/new/complex/rule.target
                        </AttributeValue>
                    </Resource>
                </Resources>
            </Target>
            <Condition>
                <Apply FunctionId="or">
                    <Apply FunctionId="and">
                        <Apply FunctionId="and">
                            <Apply FunctionId="string-equal">
                                <SubjectAttributeDesignator
                                    AttributeId="username" />
                                <AttributeValue>beddoes</AttributeValue>
                            </Apply>
                            <Apply FunctionId="string-regex-match">
                                <SubjectAttributeDesignator AttributeId="email" />
                                <AttributeValue>.*eddoes.*</AttributeValue>
                            </Apply>
                        </Apply>
                        <Apply FunctionId="not">
                            <Apply FunctionId="string-equal">
                                <SubjectAttributeDesignator
                                    AttributeId="type" />
                                <AttributeValue>part-time-staff</AttributeValue>
                            </Apply>
                            <Apply FunctionId="string-equal">
                                <SubjectAttributeDesignator
                                    AttributeId="type" />
                                <AttributeValue>student</AttributeValue>
                            </Apply>
                        </Apply>
                    </Apply>
                    <Apply FunctionId="and">
                        <Apply FunctionId="and">
                            <Apply FunctionId="string-equal">
                                <SubjectAttributeDesignator
                                    AttributeId="username" />
                                <AttributeValue>zitelli</AttributeValue>
                            </Apply>
                            <Apply FunctionId="string-regex-match">
                                <SubjectAttributeDesignator
                                    AttributeId="email" />
                                <AttributeValue>.*zitelli.*</AttributeValue>
                            </Apply>
                        </Apply>
                        <Apply FunctionId="or">
                            <Apply FunctionId="string-equal">
                                <SubjectAttributeDesignator AttributeId="type" />
                                <AttributeValue>part-time-staff</AttributeValue>
                                <Apply FunctionId="string-normalize-to-lower-case" />
                            </Apply>
                            <Apply FunctionId="string-regex-match">
                                <SubjectAttributeDesignator
                                    AttributeId="type" />
                                <AttributeValue>student</AttributeValue>
                                <Apply FunctionId="string-normalize-to-lower-case" />
                                <Apply FunctionId="string-normalize-space" />
                            </Apply>
                        </Apply>
                    </Apply>
                </Apply>
            </Condition>
        </Rule>
    </Policy>

Feedback

We aim to continually improve this documentation set to make it as easy as possible for new users and seasoned users alike create detailed authorization policies. We welcome any comments or additions you may have on the ESOE users mailing list at any time.

Also available in: HTML TXT