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

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

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.