Why We Need Policies
It’s all very well that we now have specifications such as WS-Security and WS- Attachments that prescribe how to handle tasks necessary for SOAP messaging, but those specifications don’t really answer the question of how we expose these functionalities to our Web service consuming clients. We have seen in previous chapters that a Web service request can contain a set of credentials that can be used by the requested service to determine whether to allow access. That’s great, but how do you know which credentials to include in the request message? Should you send along a Kerberos ticket, and if that doesn’t work, try a X.509 certificate, or maybe load the message down with every possible security token that you can assemble? Although a message loaded down with WS- Security-defined elements might be more secure, it's inefficient to perform the extra work of adding these security elements when the recipient doesn't require them and possibly can't even handle such a message.
At this point, I know that many of you have just developed—in your minds—some sort of service, which for fun you might have named MyInfoService, that can be called in advance of making a request to the service that you need to access, say MyDataService, in order to get the applicable policy requirements. MyInfoService might tell you which security tokens to send to MyDataService, which languages are supported, what the message encoding should be, and the like. After this neat epiphany, you might then start to think about the difficulties of late binding to such a service, the extra logic that will need to be built into the client to assemble the right information at run time to make the request to MyDataService. After thinking more about the costs of making an extra SOAP request to MyInfoService before calling MyDataService, you might begin to pine for the early-binding benefits of consuming a WSDL file at design time.
Limitations of Existing Description Mechanisms
As we discussed in Chapter 1, one of the major benefits of WSDL is that it lets us consume the description of a Web service at design time so that we know, at run time, how to interact with the service. Unfortunately, although WSDL is designed to describe items such as exposed Web methods, data types, and SOAP message elements, it has proven less useful when it comes to describing choices, preferences, and other requirements not tied directly to the messaging interface.
For example, WSDL can tell you that MyDataService expects a SOAP request message to have a body element, which contains a certain child element, which corresponds to an exposed Web method. It can also provide schema information for this element. Each exposed Web method will have this information, and there will be similar information about what will be returned should the methods execute successfully. WSDL can even tell you that certain header elements are required, such as those that might provide authentication information or otherwise identify the requester or a particular message. Unfortunately, WSDL alone can’t help us in the case of conditional requirements and other policy issues not directly related to either message transport or describing a SOAP message. Fortunately, WSDL does provide the extensibility to support the definition of policy requirements, as we will discuss shortly.
Defining Web Service Requirements
Up to this point, I have taken a somewhat compartmentalized approach to my discussion of Web service specifications and their related functionalities. This is in part for clarity’s sake but also because the modular design of these specifications enables us to treat them in this manner, implementing the ones that we feel are necessary for our application and simply forgetting the rest. However, when we get into real-world scenarios, things can and will get more complicated. It’s certainly not unanticipated that, in an enterprise Web service, we’ll be carrying out operations such as encrypting and signing SOAP messages, transmitting security tokens, and providing custom routing information. Of course, as I have pointed out, the real question when accessing Web services is not, “How do I do these things?” since the specifications tell us how, but rather, “Which of these must I specify for my request message to successfully return me my ‘Hello World?’” Or, “How can I tell the customers of my Web service what they need to do to get their ‘Hello World?’” Alternatively, how can customers tell my Web service about the messaging requirements of their client applications so that messages can also be received by the clients?
The answer is that we need a way for communicating the full breadth of what our Web service requires of its clients, which can be thought of as our Web service’s policy statement. The same goes for communicating the client’s requirements to the service. Since both parties in a Web service-based interaction need to be able to enforce their own policies and interpret other policy statements, it really makes more sense to discuss policy in terms of sender and receive rather than client and service.
The policy-related specifications, backed by IBM, Microsoft, BEA Systems, SAP and others, officially define policy as “the collection of all acceptable policy assertions for a specific domain” (WS-Policy Section 3.4). In this definition, an assertion is considered a requirement or preference of the service. The following are examples of some assertions that can be made by a Web service:
You must send either an X.509 certificate from you or else a Kerberos ticket, and Kerberos tickets are preferred.
You must encrypt your message header.
You must sign the message.
You must send requests only in either German or Dutch.
You can send messages encoded in either UTF-8 or ANSI_X3.4-1968.
In the rest of this chapter, I’ll discuss the specifications that describe how to declare such policies for our Web services. Like all of the specifications that I discuss in this book, a main goal of these specifications is to be modular, wherein each layer is broken down into a separate specification, which includes the policy specifications described next.
WS-Policy
This specification describes a framework for defining and communicating the expectations and requirements both for sending messages to and receiving messages from a Web service, and it defines the format of such requirements.
WS-PolicyAssertion
This specification defines a core set of Web service-policy assertions dealing mostly with messaging issues, encoding, and other requirements that fall outside WSDL.
WS-SecurityPolicy
This specification describes a set of policy assertions that defines the types of security features that a Web service has implemented and the type of security that’s required of an incoming request message. Although WS-SecurityPolicy is often considered a security specification, I discuss it in this chapter because it does define policy assertions regarding Web services security and leverages the WS-Policy framework for describing assertions.
WS-PolicyAttachment
This specification, in essence, ties everything together by defining how policy expressions are linked to WSDL and Universal Description, Discovery, and Integration (UDDI) as well as to other discoverability mechanisms.
Not only are the above specifications designed, to leverage one another, but they are also orthogonal to one another. This means that, for example, the security policy assertions defined in WS-SecurityPolicy can be taken advantage of in a framework other than the one described in WS-Policy or even just passed around in SOAP message headers. In subsequent sections, I will delve into what these specifications describe in a bit more detail, and we will see how WSE makes it work. I do cover UDDI-specific policy bindings in this book.
Web Services Policy Framework
As the highest level of these policy-related specifications, the WS-Policy specification describes the framework that can be used to combine various policy assertions, each one of them an XML node, into a single policy expression. Applications and services can then use this policy expression to determine the requirements for accessing a Web service provider, and a policy expression might apply to one or more Web methods supported by a Web service or even be used with multiple Web services across an entire domain. As such, multiple policy expressions can be combined into an overall policy document for an entire entity, such as a domain or a company.
Although they might sound complicated, policy expressions are simply hierarchical structures of XML nodes, in which these nodes are either policy assertions, policy operators, or other policy expressions. The structure of a policy expression conveys the ultimate requirements for accessing the service. For example, you can create a policy expression that says a valid request message must have property A, and if not, it must have properties B and C.
The following is an example of a simple policy expression that makes two security assertions:
In this statement, the two assertions are that a request message must include a valid X.509 certificate that can be used to identify the sender and that the message must be digitally signed using the Advanced Encryption Standard (AES) algorithm so that the recipient can determine whether the message has been tampered with. As you can see, a policy statement is simply an XML structure that combines one or more assertions using policy expressions.
Policy Operators
Much like logical or arithmetic operators, policy operators allow us to define relationships among multiple assertions in a policy expression. WS-Policy defines the following operators, which themselves can contain other nested operators.
All
This element dictates that all assertions or other expression elements that are child elements must be satisfied in order to access a Web service. In the following example, All indicates that an X.509 certificate must be included in the request and that the message must be encrypted and digitally signed:
ExactlyOne
This element dictates that only one of the requirements prescribed by the contained assertions is to be followed when the service is accessed. For example, the following policy expression states that the requesting application must provide only one of three types of security tokens for authentication:
Note that when the ExactlyOne operator is used, it overrides the Usage attribute value, which in this example is Required. When using the ExactlyOne operator, it’s helpful to also specify the optional Preference attribute on the contained assertions to give requesting applications an idea of which of these assertions are preferred. A higher Preference value is more preferable than a lower value.
OneOrMore
This element dictates that at least one of the requirements prescribed by the contained assertions must be followed when accessing the service. For example, the following policy expression states that the requesting application need provide only one of the three types of security tokens for authentication but can provide more if desired:
Like ExactlyOne, the OneOrMore operator benefits from having the Preference attribute specified on the contained assertions.
PolicyReference
Although not technically a policy operator, the PolicyReference element provides a means whereby one policy expression can be included, by reference, as an element in another. This element is treated as an All element with respect to the assertions and operators in the policy expression that references it. For a policy expression to be referenced, it must have a Uniform Resource Identifier (URI) assigned by the Id attribute or else a qualified name assigned to the Name attribute. The following is an example of a policy expression that references two other expressions, one by name and one by URI:
Policy Assertions
Assertions are the building blocks of a policy expression, and they describe the rules that an application must follow when making requests to a Web service. Policy assertions follow this general XML format:
General Messaging Assertions
The WS-PolicyAssertions specifications define a set of policy assertions that apply to the general messaging behaviors of SOAP-based Web services. All of these assertions follow the general format defined in WS-Policy and are defined next.
TextEncoding
If a Web service supports more than one character encoding or requires a nonstandard encoding, the TextEncoding assertion can be used to define such a policy, provided the XML specification supports the encoding. Of course, to maximize interoperability, the default encoding of UTF-8 should be used. The following sample is a policy expression that declares an option between two supported character encodings:
Language
If a Web service supports multiple languages for textual content or if English isn’t the standard, the Language assertion can be used to declare such policies. The following policy example declares that both English and German are supported:
SpecVersion
This assertion enables a Web service to specify which versions of a specification request messages must conform to, where a specification is referenced by its URI.
MessagePredicate
This assertion is used to ensure that request messages contain the necessary XML elements in order to comply with a Web service’s requirements. This assertion is particularly useful for declaring requirements for proprietary elements in the message header or body elements. The message predicate is selected using either XPath 1.0 or the message part selection functions defined in WS-Policy, which are used to select either the entire message body (wsp:Body) or a specified message header (wsp:Header). The selection language used is specified in the Dialect attribute; if this attribute is not specified, the default, XPath 1.0, is assumed. While the two message part functions are easier to use, XPath should be used to select specific parts of a body or header element. The WS-PolicyAssertions specification introduces nine new XPath functions for selecting parts of a SOAP message, which I won’t detail here. In the following assertion, an XPath expression, which uses the new GetHeader function, identifies messages with only one MyCustomHeader header element:
Note that the use of XPath expressions to select the message predicate is not supported by WSE 2.0.
Security Policy Assertions
While there is certainly a need for general messaging assertions, the drive to declare security requirements to enable interoperability with the WS-Security specification was certainly a major impetus behind the development of WS-Policy. Thus an entire specification, the WS-SecurityPolicy specification, is devoted to defining security assertions. These assertions, most of which are supported by WSE 2.0, are defined next.
SecurityToken
This assertion is used to declare which types of security tokens, defined in WS-Security, must be supplied in order to authenticate a requesting application. Usage of the security tokens listed in Table 6-1 can be specified by this assertion.
Table 6-1: Security Tokens with Defined Policy Assertions Qualified Name
Token Type
wsse:X509v3
X.509 Certificate
wsse:Kerberosv5TGT
Kerberos ticket-granting ticket (TGT)
wsse:Kerberosv5ST
Kerberos service ticket
wsse:UsernameToken
Username token
wsse:SAMLAssertion
SAML Assertion
wsse:XrMLLicense
XrML License
In this table, SAML refers to an XML-based security-assertion token.
WS-SecurityPolicy supports additional optional elements for specifying additional information about token requirements, including which certificate authorities and key distribution centers are acceptable and any token-specific information that makes it easier for requesting clients to present the correct token in the request message. For example, the following policy expression defines acceptable tokens as X.509 certificates from one of two different certificate authorities: a Kerberos TGT from the specified key distribution center or a username token with the specified username.
For more information about details and usage of security token assertions, refer to the WS-SecurityPolicy specification.
Integrity
When a Web service requires that incoming request messages be digitally signed to indicate whether they have been tampered with or modified, an Integrity assertion can be added to the policy expression. The following is an example of an assertion that the message header must be digitally signed with an X.509 certificate using the Secure Hash Algorithm (SHA) algorithm:
For more information about details and usage of integrity assertions, refer to the WS-SecurityPolicy specification.
Confidentiality
If the Web service requires that any parts of a request message be encrypted, this can be stated in the policy expression using a Confidentiality assertion. A Confidentiality assertion that declares that the EncryptedElement node in the message body must be encrypted using the service’s X.509 certificate and Triple-DES (Data Encryption Standard) specification might look like this:
Visibility
A request message to a Web service can be routed through one or more intermediate Web services. If any of these intermediaries need to be able to access part of the request message, a Visibility assertion can be made to prevent that portion of the message from being encrypted. The following example assertion requires that the message header not be encrypted:
SecurityHeader
This assertion specifies requirements of the format of the Security header element in a request message. The following example requires that child elements within the Security header be prefixed by the WS-Security XML namespace and that only encrypted elements specifically referenced in the Security header will be processed:
MessageAge
This assertion defines the maximum number of seconds a message has to travel from the sender to the receiver. The total travel time is determined by using the value of the Timestamp header, which makes it mandatory when this assertion is used. If the message transmission time exceeds the value of the Age attribute, the message is rejected. The following is an example of this assertion with an age of 30 minutes:
Obviously the smaller this value, the more important it becomes for the two endpoints to have their times synchronized. The means by which these machines synchronize their times is not addressed in any of the specifications addressed by this book. Rather, time synchronization is normally accomplished via some out-of-band mechanism like a phone call or use of a common time server.
Reliable Messaging Assertions
The WS-ReliableMessaging specification, which I described in Chapter 4, defines a set of policy assertions that are used when declaring the message reliability features that must be used when accessing a Web service endpoint. These assertions include the following:
Specification Version This assertion is used to declare the version of WS-ReliableMessaging to which a message must conform. This assertion is made by the SpecVersion element, as in the following:
Delivery Assurance This assertion is used by the Web service that is the ultimate recipient to declare message delivery behaviors when receiving messages from the service guaranteeing reliability. This assertion is made by the DeliveryAssurance element, where the Value attribute can be one of these values:
wsrm:AtMostOnce Messages are delivered only once.
wsrm:AtLeastOnce Messages are delivered at least once.
wsrm:ExactlyOnce Messages are delivered exactly once, which is equivalent to both of the previous assertions together.
wsrm:InOrder Messages are delivered in the order they were sent.
For example, the following assertions request that messages be delivered by the reliability service exactly once and in the order that they were sent:
Sequence Expiration This assertion declares the time at which a reliable messaging sequence is no longer valid. This assertion is made using the wsu:Expires element. The following assertion indicates that a sequence expires on December 31, 2005:
Inactivity Timeout This assertion declares the number of milliseconds before an inactive sequence expires. The Milliseconds attribute of the InactivityTimeout element is used to specify this inactivity period. The following assertion indicates that a sequence will expire if it is inactive for longer than 1 minute:
Retransmission Interval This assertion declares the number of milliseconds before an unacknowledged message is re-sent. The Milliseconds attribute of the BaseRetransmissionInterval element is used to specify this period. Another related assertion, ExponentialBackoff, is used to declare that a previously agreed upon algorithm is used when a new retransmission interval is negotiated. The following assertion indicates that a message must be re-sent if an acknowledgement has not been received within 1 minute and that the back- off algorithm should be used:
Acknowledgement Interval This assertion declares the number of milliseconds before an acknowledgement must be sent in a separate message. The Milliseconds attribute of the AcknowledgementInterval element is used to specify this period. The following assertion indicates that a stand-alone acknowledgement message must be sent if another message is not being returned to the sender within 1 minute:
Referencing Policy Expressions
Of course, it’s not enough that we can simply create policy expressions. Just as important are mechanisms for communicating policy expressions to other parties and for applying them against sent and received messages. In fitting with the Web service model promoted by WSDL, the best way to communicate policies are to make them discoverable and accessible to the parties who must access a Web service endpoint. We already have mechanisms defined for publishing Web service definitions, such as WSDL and UDDI. However, we need to be able to locate policy files and reference policy expressions from these description-and-discovery documents. The WS-PolicyAttachment specification provides mechanisms for including policy expressions within an XML document, such as a SOAP message header, or referencing them from an XML document, such as a WSDL file. By linking policies to WSDL, we can leverage the discoverability, description, and extensibility features of WSDL.
Before I discuss how to link policies to WSDL, I need to discuss some of the semantics for identifying policies. While policy expressions are the integral unit for declaring policies, when publishing multiple policy assertions, a service may want to store all policy assertions in a single document, even when these policies relate to multiple endpoints implemented by the service. WS-Policy provides a way to reference a single policy expression within an XML document containing multiple expressions using either a qualified name or a URI.
To reference a policy expression using a URI, the Id attribute must be supplied, as defined by the Web Service Security Addendum specification. This enables the policy expression to be referenced relative to a base URI plus the pound sign and the name assigned in the Id attribute. For example, you can reference the following policy expression in the http://example.com/policy namespace as http://example.com/policy#MySecurityPolicy:
⋮
⋮
The other mechanism for referencing a policy element involves assigning a qualified name to the policy expression, which is done using the Name attribute as defined by WS-Policy. When the Name attribute is used to specify policy expressions, an expression named MyTextEncodingPolicy in the http://example.com/policy namespace is referenced as p:MyTextEncodingPolicy, where xmlns:p=”http://example.com/policy”.
To hook up policy expressions to other XML documents, the WS-PolicyAttachment specification defines two mechanisms for referencing policy expressions. The first enables a policy expression to be referenced within any arbitrary XML element. This mechanism lets us add a PolicyURIs attribute to any XML element and reference the URI for a policy expression. Likewise, the PolicyRefs attribute can be added to any XML element to reference a policy expression by its fully qualified name. The following example element references these policy expressions that I have just discussed:
The other mechanism enables a policy expression to be assigned to an arbitrary Web service resource; such resources can be specified using the semantics of the WS-Addressing specification, which I discussed in Chapter 4. Known as a policy attachment, this XML policy structure is composed of the following elements:
A reference to the resource to which the policy statement applies, where this reference is based on WS-Addressing.
A policy expression either defined by a Policy element or referenced by a PolicyReference element.
Security information, defined using WS-Security, such as a digital signature.
In the following example, the PolicyAttachment element maps two policy expressions that reference Web services, wherein the security token policy is contained within the policy attachment document and the message age policy is referenced externally:
Policy Assertions and WSDL
Now that you have the means to define policies for particular Web service resources, you need to add this information to your WSDL files so that it can be publicly exposed to applications that consume your services. The ideal method for publishing a policy assertion for a given resource is to add it to the part of the WSDL file that defines the section of the Web service to which policy applies. However, when doing so, it is important to remember that policy assertions made on parent WSDL elements are enforced on child elements, which means that we must use care when applying policies at multiple, overlapping levels in a service definition because we may get unexpected results for the effective policy for a given WSDL element. For example, when a policy assertion, say a signature requirement, is defined at the message level of the service description, this policy will apply to all parts of the message. However, when a policy, such as confidentially requirement, is also defined for a single message part, the effective policy for that part of the message will include both the signature policy, defined for message, and the confidentiality policy, defined on the part. This can get even more complicated when you define a policy for the portType or operation elements to which the message belongs. In such cases, the effective policy for a message part is determined as the sum total of the policies defined for the portType, operation, message, and part elements.
To make things even less straight-forward, because of restrictions in WSDL 1.1, you aren’t able to add arbitrary XML, such as a PolicyAttachment element, to portType and message elements. Instead, WS-PolicyAttachment specifies that a required UsingPolicy element be added to the WSDL definition to indicate that policies are being defined. In addition, policy references are added to the appropriate elements in the WSDL document for the Web service functionalities for which policies are being defined. When consuming a policy annotated WSDL file, you must be able to retrieve the externally referenced policy files. For example, the following WSDL file includes policy information for the DocumentService Web service:
⋮
In this example, any requests to the GetDocument method must contain a X509-based security token, and all parts of the request message to the GetDocument Web method must conform to a signature policy referenced by the SignaturePolicy identifier. In addition, the body of the request message must conform to the encryption policy referenced by the EncryptionPolicy identifier. This makes the effective policy for the body of a request message to the GetDocument method the same as the following:
Securing Policy Expressions
As publicly exposed in XML documents, policy expressions and policy attachments are exposed to the same kinds of vulnerabilities as SOAP messages being transported using an unencrypted transport; therefore, policy expressions require the same kind of security considerations that are given to SOAP messages. For example, if I’m consuming a policy expression for a Web service, I need to be able to know that this policy expression has indeed been published from the Web service that I’m expecting and hasn’t been modified by any malicious parties. To ensure this, the Web service must digitally sign its policy expressions using a trusted security token (either a shared secret or a private key) as defined in WS-Security. In a similar manner, if I need to protect my Web service’s policies but also make them publicly available, I can encrypt parts of the policy expression using XML encryption as defined in WS-Security.
Because you can apply the features of WS-Security to a policy expression as you would a SOAP message, WS-Policy supports including the Security element, as defined by WS-Security, within a policy expression. When defined in this way, the Security element specifies the security features that are implemented in the policy expression. For example, the following policy expression includes a digital signature, which is defined in the Security element:
In this example, the NULL value of the URI attribute in the Reference element indicates that the entire expression will be included in the signature. However, the act of signing will change the Signature element and, thereby, the contents of the expression, so I specify the referenced XPath transformation to indicate that the digital signature doesn’t include the Signature element.
Policy Support in WSE
Version 2.0 of WSE includes the ability to declare and enforce WS-Policy– based restrictions on Web services that are enabled to use WSE. While WS- Policy implies that policy is something that applies only to inbound messages, WSE has been designed to apply WS-Policy functionality to outbound messages as well. This enables you to place the same type of policy restrictions on outbound messages to ensure that they will conform to the receivers’ published policy. And even better, WSE will attempt to automatically retrieve the necessary security tokens and do the work of signing and encrypting the message to bring it into compliance to the outbound policy. This means that a well planned use of policy with WSE can greatly reduce the amount of code that you need to write, and by using policy, you can change security requirements for your WSE-based application on the fly without having to modify and recompile your code.
In both inbound and outbound cases, policy enforcement is implemented by a set of policy input and output filters. The policy verification input filter ensures that incoming messages conform to policy assertions registered for the requested resource. If an incoming message does not conform to these requirements, a PolicyValidationException is thrown and a message containing a Fault element in the body is returned to the sender with an error message indicating that the request did not conform to the policy. Conversely, the WSE policy- enforcement output filter also ensures that all outgoing messages conform to any send policies defined for outbound messages. If the SoapContext object of an outbound message doesn’t already have the elements needed to conform to the send policy, this filter attempts to retrieve security tokens from a security token cache and sign or encrypt the message to bring it into conformance with the policy. If a send-policy violation is detected in an outbound message, a PolicyEnforcementException exception is thrown.
The policy documents used by WSE when testing messages for compliance are stored at the local computer in an XML policy cache file. While typically stored in the directory with the application, policy cache files can be stored in any directory to which the WSE runtime, under the ASP.NET worker process account, has access. The policy cache document is made up of one or more policy assertions, as specified by WS-Policy, and a mapping between policies and the resources against which the policies are being verified, wherein policies are mapped to resources using the Id policy attribute. The following is an example of a valid WSE policy cache document:
Version 2.0 of WSE implements support for both Confidentiality (encryption) and Integrity (signing) assertions out of the box. To use the policy filters to validate or enforce any other policy assertions defined by WS-PolicyAssertions or WS-SecurityPolicy, you will need to use the policy API implemented in the Microsoft.Web.Services.Security.Policy and Microsoft.Web.Services.Policy namespaces to write your own assertions handler. After writing the handler, you must then register it with the policy filters. As this is an advanced scenario, I won’t be covering it here. Instead, you should refer to the WSE 2.0 SDK documentation.
In theory, the WSE policy filters should be able to successfully parse any policy assertions that conform to the WS-Policy, WS-PolicyAssertions, and WS- SecurityPolicy specifications. However, to ensure that a policy cache document can be successfully parsed and interpreted by WSE, you should either use the WSE Settings Tool to create a basic policy cache document or possibly start with a WSE-generated document and add your own assertions and operators. In the next section, I will show how to use the WSE Settings Tool to generate a simple policy cache document.
In version 2.0, WSE doesn’t support any of the discovery mechanisms for policies described in WS-PolicyAttachment. To make policies visible to applications that consume your Web service, you must either send a copy of a policy document to your Web service’s consumers or present an accessible URL location from which the policy document can be accessed. An even better way to make policies discoverable would be to manually edit the WSDL file, following the rules prescribed in WS-PolicyAttachment that I discussed earlier. Then you must publish both the WSDL and the policy document file so that applications can access these discovery documents. When publishing a policy document, it would be nice to be able to digitally sign it, as is recommended by WS-Policy. However, in this release, WSE doesn’t provide an easy way to apply the WS- Security features to a policy cache document. Remember that as it stands today, WSDL consuming tools, such as the Visual Studio .NET Add Web Reference tool, will not be about to automatically consume these policy extensions to your WSDL files and be able to find the referenced policies,

No comments:
Post a Comment