Chapter 5. The WS-Policy Framework

Abstract

This chapter provides an introduction to the basic concepts of the WS-Policy framework, defining policy subjects and policy assertions, and explaining how policy assertions can be combined to make policy expressions.

5.1. Introduction to WS-Policy

Overview

The WS-Policy specification provides a general framework for applying policies that modify the semantics of connections and communications at runtime in a Web services application. Apache CXF security uses the WS-Policy framework to configure message protection and authentication requirements.

Policies and policy references

The simplest way to specify a policy is to embed it directly where you want to apply it. For example, to associate a policy with a specific port in the WSDL contract, you can specify it as follows:

<wsdl:definitions targetNamespace="http://tempuri.org/"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
    xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" ... >
  ...
  <wsdl:service name="PingService10">
    <wsdl:port name="UserNameOverTransport_IPingService" binding="BindingName">
      <wsp:Policy> <!-- Policy expression comes here! --> </wsp:Policy>
      <soap:address location="SOAPAddress"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

An alternative way to specify a policy is to insert a policy reference element, wsp:PolicyReference, at the point where you want to apply the policy and then insert the policy element, wsp:Policy, at some other point in the XML file. For example, to associate a policy with a specific port using a policy reference, you could use a configuration like the following:

<wsdl:definitions targetNamespace="http://tempuri.org/"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
    xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" ... >
  ...
  <wsdl:service name="PingService10">
    <wsdl:port name="UserNameOverTransport_IPingService" binding="BindingName">
      <wsp:PolicyReference URI="#PolicyID"/>
      <soap:address location="SOAPAddress"/>
    </wsdl:port>
  </wsdl:service>
  ...
  <wsp:Policy wsu:Id="PolicyID">
    <!-- Policy expression comes here ... -->
  </wsp:Policy>
</wsdl:definitions>

Where the policy reference, wsp:PolicyReference, locates the referenced policy using the ID, PolicyID (note the addition of the # prefix character in the URI attribute). The policy itself, wsp:Policy, must be identified by adding the attribute, wsu:Id="PolicyID".

Policy subjects

The entities with which policies are associated are called policy subjects. For example, you can associate a policy with an endpoint, in which case the endpoint is the policy subject. It is possible to associate multiple policies with any given policy subject. The WS-Policy framework supports the following kinds of policy subject:

Service policy subject

To associate a policy with a service, insert either a <wsp:Policy> element or a <wsp:PolicyReference> element as a sub-element of the following WSDL 1.1 element:

  • wsdl:service—apply the policy to all of the ports (endpoints) offered by this service.

Endpoint policy subject

To associate a policy with an endpoint, insert either a <wsp:Policy> element or a <wsp:PolicyReference> element as a sub-element of any of the following WSDL 1.1 elements:

  • wsdl:portType—apply the policy to all of the ports (endpoints) that use this port type.
  • wsdl:binding—apply the policy to all of the ports that use this binding.
  • wsdl:port—apply the policy to this endpoint only.

For example, you can associate a policy with an endpoint binding as follows (using a policy reference):

<wsdl:definitions targetNamespace="http://tempuri.org/"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
    xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" ... >
  ...
  <wsdl:binding name="EndpointBinding" type="i0:IPingService">
    <wsp:PolicyReference URI="#PolicyID"/>
    ...
  </wsdl:binding>
  ...
  <wsp:Policy wsu:Id="PolicyID"> ... </wsp:Policy>
  ...
</wsdl:definitions>

Operation policy subject

To associate a policy with an operation, insert either a <wsp:Policy> element or a <wsp:PolicyReference> element as a sub-element of any of the following WSDL 1.1 elements:

  • wsdl:portType/wsdl:operation
  • wsdl:binding/wsdl:operation

For example, you can associate a policy with an operation in a binding as follows (using a policy reference):

<wsdl:definitions targetNamespace="http://tempuri.org/"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
    xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" ... >
  ...
  <wsdl:binding name="EndpointBinding" type="i0:IPingService">
    <wsdl:operation name="Ping">
      <wsp:PolicyReference URI="#PolicyID"/>
      <soap:operation soapAction="http://xmlsoap.org/Ping" style="document"/>
      <wsdl:input name="PingRequest"> ... </wsdl:input>
      <wsdl:output name="PingResponse"> ... </wsdl:output>
    </wsdl:operation>
    ...
  </wsdl:binding>
  ...
  <wsp:Policy wsu:Id="PolicyID"> ... </wsp:Policy>
  ...
</wsdl:definitions>

Message policy subject

To associate a policy with a message, insert either a <wsp:Policy> element or a <wsp:PolicyReference> element as a sub-element of any of the following WSDL 1.1 elements:

  • wsdl:message
  • wsdl:portType/wsdl:operation/wsdl:input
  • wsdl:portType/wsdl:operation/wsdl:output
  • wsdl:portType/wsdl:operation/wsdl:fault
  • wsdl:binding/wsdl:operation/wsdl:input
  • wsdl:binding/wsdl:operation/wsdl:output
  • wsdl:binding/wsdl:operation/wsdl:fault

For example, you can associate a policy with a message in a binding as follows (using a policy reference):

<wsdl:definitions targetNamespace="http://tempuri.org/"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
    xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" ... >
  ...
  <wsdl:binding name="EndpointBinding" type="i0:IPingService">
    <wsdl:operation name="Ping">
      <soap:operation soapAction="http://xmlsoap.org/Ping" style="document"/>
      <wsdl:input name="PingRequest">
        <wsp:PolicyReference URI="#PolicyID"/>
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="PingResponse"> ... </wsdl:output>
    </wsdl:operation>
    ...
  </wsdl:binding>
  ...
  <wsp:Policy wsu:Id="PolicyID"> ... </wsp:Policy>
  ...
</wsdl:definitions>

5.2. Policy Expressions

Overview

In general, a wsp:Policy element is composed of multiple different policy settings (where individual policy settings are specified as policy assertions). Hence, the policy defined by a wsp:Policy element is really a composite object. The content of the wsp:Policy element is called a policy expression, where the policy expression consists of various logical combinations of the basic policy assertions. By tailoring the syntax of the policy expression, you can determine what combinations of policy assertions must be satisfied at runtime in order to satisfy the policy overall.

This section describes the syntax and semantics of policy expressions in detail.

Policy assertions

Policy assertions are the basic building blocks that can be combined in various ways to produce a policy. A policy assertion has two key characteristics: it adds a basic unit of functionality to the policy subject and it represents a boolean assertion to be evaluated at runtime. For example, consider the following policy assertion that requires a WS-Security username token to be propagated with request messages:

<sp:SupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
  <wsp:Policy>
    <sp:UsernameToken/>
  </wsp:Policy>
</sp:SupportingTokens>

When associated with an endpoint policy subject, this policy assertion has the following effects:

  • The Web service endpoint marshales/unmarshals the UsernameToken credentials.
  • At runtime, the policy assertion returns true, if UsernameToken credentials are provided (on the client side) or received in the incoming message (on the server side); otherwise the policy assertion returns false.

Note that if a policy assertion returns false, this does not necessarily result in an error. The net effect of a particular policy assertion depends on how it is inserted into a policy and on how it is combined with other policy assertions.

Policy alternatives

A policy is built up using policy assertions, which can additionally be qualified using the wsp:Optional attribute, and various nested combinations of the wsp:All and wsp:ExactlyOne elements. The net effect of composing these elements is to produce a range of acceptable policy alternatives. As long as one of these acceptable policy alternatives is satisfied, the overall policy is also satisified (evaluates to true).

wsp:All element

When a list of policy assertions is wrapped by the wsp:All element, all of the policy assertions in the list must evaluate to true. For example, consider the following combination of authentication and authorization policy assertions:

<wsp:Policy wsu:Id="AuthenticateAndAuthorizeWSSUsernameTokenPolicy">
  <wsp:All>
    <sp:SupportingTokens>
      <wsp:Policy>
        <sp:UsernameToken/>
      </wsp:Policy>
    </sp:SupportingTokens>
    <sp:SupportingTokens>
      <wsp:Policy>
        <sp:SamlToken/>
      </wsp:Policy>
    </sp:SupportingTokens>
  </wsp:All>
</wsp:Policy>

The preceding policy will be satisfied for a particular incoming request, if the following conditions both hold:

  • WS-Security UsernameToken credentials must be present; and
  • A SAML token must be present.
Note

The wsp:Policy element is semantically equivalent to wsp:All. Hence, if you removed the wsp:All element from the preceding example, you would obtain a semantically equivalent example

wsp:ExactlyOne element

When a list of policy assertions is wrapped by the wsp:ExactlyOne element, at least one of the policy assertions in the list must evaluate to true. The runtime goes through the list, evaluating policy assertions until it finds a policy assertion that returns true. At that point, the wsp:ExactlyOne expression is satisfied (returns true) and any remaining policy assertions from the list will not be evaluated. For example, consider the following combination of authentication policy assertions:

<wsp:Policy wsu:Id="AuthenticateUsernamePasswordPolicy">
  <wsp:ExactlyOne>
    <sp:SupportingTokens>
      <wsp:Policy>
        <sp:UsernameToken/>
      </wsp:Policy>
    </sp:SupportingTokens>
    <sp:SupportingTokens>
      <wsp:Policy>
        <sp:SamlToken/>
      </wsp:Policy>
    </sp:SupportingTokens>
  </wsp:ExactlyOne>
</wsp:Policy>

The preceding policy will be satisfied for a particular incoming request, if either of the following conditions hold:

  • WS-Security UsernameToken credentials are present; or
  • A SAML token is present.

Note, in particular, that if both credential types are present, the policy would be satisfied after evaluating one of the assertions, but no guarantees can be given as to which of the policy assertions actually gets evaluated.

The empty policy

A special case is the empty policy, an example of which is shown in Example 5.1, “The Empty Policy”.

Example 5.1. The Empty Policy

<wsp:Policy ... >
   <wsp:ExactlyOne>
      <wsp:All/>
   </wsp:ExactlyOne>
</wsp:Policy>

Where the empty policy alternative, <wsp:All/>, represents an alternative for which no policy assertions need be satisfied. In other words, it always returns true. When <wsp:All/> is available as an alternative, the overall policy can be satisified even when no policy assertions are true.

The null policy

A special case is the null policy, an example of which is shown in Example 5.2, “The Null Policy”.

Example 5.2. The Null Policy

<wsp:Policy ... >
   <wsp:ExactlyOne/>
</wsp:Policy>

Where the null policy alternative, <wsp:ExactlyOne/>, represents an alternative that is never satisfied. In other words, it always returns false.

Normal form

In practice, by nesting the <wsp:All> and <wsp:ExactlyOne> elements, you can produce fairly complex policy expressions, whose policy alternatives might be difficult to work out. To facilitate the comparison of policy expressions, the WS-Policy specification defines a canonical or normal form for policy expressions, such that you can read off the list of policy alternatives unambiguously. Every valid policy expression can be reduced to the normal form.

In general, a normal form policy expression conforms to the syntax shown in Example 5.3, “Normal Form Syntax”.

Example 5.3. Normal Form Syntax

<wsp:Policy ... >
   <wsp:ExactlyOne>
        <wsp:All> <Assertion .../> ... <Assertion .../> </wsp:All>
        <wsp:All> <Assertion .../> ... <Assertion .../> </wsp:All>
        ...
   </wsp:ExactlyOne>
</wsp:Policy>

Where each line of the form, <wsp:All>…​</wsp:All>, represents a valid policy alternative. If one of these policy alternatives is satisfied, the policy is satisfied overall.