Chapter 10. Defining and applying policy

This chapter covers

  • SCA policy in general
  • Implementation policy
  • Interaction policy

Policies in Tuscany and SCA are used to control those aspects of your application that tend to be orthogonal to your component implementations, for example, logging and monitoring or security concerns such as authentication, integrity, and confidentiality. These types of functions are often referred to as qualities of service and can significantly complicate an application if you implement them inside your business logic.

In an enterprise, it’s better to define policies once and then apply them consistently across all of the components that need them. That’s why SCA describes a policy framework that allows intents and policy sets to be defined and associated with component implementations and the bindings that connect them. Using policy sets and intents, you don’t have to use APIs to achieve quality of service (QoS) behavior; you just mark up the composite application.

You’ve already learned in previous chapters that components built using Tuscany and SCA are independent of some of the complexities you normally associate with enterprise application development. You’ve seen how bindings can be added to component services and references without changing the component implementation itself. Tuscany and SCA treat the configuration of policies in the same way by allowing you to define and configure policies independently of the implementations and bindings to which they’re attached.

We’ll start our description of policy in SCA and Tuscany with an overview of how policy fits into the SCA domain concept. We’ll then look at how the Tuscany runtime applies policy configuration to the running application, where the rubber hits the road, as it were.

To bring policy into focus we’ll look at how an implementation policy, which enables message logging, can be applied to an SCA component implementation. We’ll also look at an interaction policy that enables simple authorization between the Payment and CreditCardPayment components from the travel sample. The interaction sample takes up quite a bit of space in this chapter because it shows how intents and policy sets are applied to both the reference and service sides of the interaction. We’ll finish the chapter with some discussion of the more advanced features of the policy framework and a quick review of the limited policies that Tuscany currently supports.

10.1. An overview of policy within an SCA domain

The SCA policy framework is defined in the SCA Policy Framework Specification (http://www.osoa.org/download/attachments/35/SCA_Policy_Framework_V100.pdf). The foundations of SCA’s approach to supporting policy are the policy intents and policy sets that SCA defines.

A policy intent, as you might have guessed by the name, is a statement of intent. For example, say you want to have all of the messages that arrive at a component logged for debugging purposes. You could associate the intent logging with your component implementation. This doesn’t say how logging will be performed. It just says that you want logging performed.

To implement the logging feature you’ll have to define a policy set that satisfies the logging intent. A policy set describes the technical details involved in logging messages, for example, what details to log and where the log messages should be written.

The approach of having policy intents defined separately from policy sets allows a great deal of flexibility when constructing and deploying SCA applications. The component developer can use intents to describe QoS requirements abstractly without needing to understand the mechanisms used to provide the QoS features. At the deployment stage, enterprise policy sets ensure that intents are satisfied in accordance with local policy, for example, by using whatever technical infrastructure is most appropriate in the local enterprise environment.

All SCA intents and policy sets are provided in configuration files with the name definitions.xml. There can be multiple definitions.xml files spread across application contributions and Tuscany extensions. Figure 10.1 shows how policy sets and intents within one or more definitions.xml files can be associated with component implementations, references, and services.

Figure 10.1. An SCA component with intents and/or policy sets attached to enforce quality of service. The intents and policy sets are read in from one or more definitions.xml files.

As illustrated in the figure, SCA provides the ability to describe intents and policy sets in an SCA domain. The SCA domain isn’t shown explicitly, but all of the items shown have been contributed to a single SCA domain. The figure shows that intents and policy sets can be associated with implementations, what SCA not surprisingly calls implementation policies. This allows you to control the quality of service provided by the component implementation either at the level of the whole implementation or at the level of individual operations. In our logging example, every message entering or leaving the implementation, or operation, can be treated consistently in terms of what information is recorded about the message.

Figure 10.1 also shows that intents and policy sets can be associated with component references and services, what SCA calls interaction policies. This allows policy to be associated with the individual bindings that are configured for component services and references. In this way the protocol stack of a binding can be configured to ensure that appropriate QoS behavior is achieved.

As can be seen from the figure, intents and policy sets are described inside XML files with the name definitions.xml. A definitions.xml file can either appear inside a contribution or be packaged with a Tuscany extension such as an implementation or binding type. The latter approach is used in those cases where the intents or policy sets are provided as a feature of the extension in question. For example, the Tuscany binding.ws extension ships with a definitions.xml file that includes intents for selecting SOAP versions called SOAP.1_1 and SOAP.1_2.

The contents of all of the definitions.xml files present in a domain, whether they come from extensions or from contributions, are aggregated and made available across the domain. When configuring an application there’s no need to worry about the precise location of a definitions.xml file, just that it’s available within the domain.

With this brief overview, we can look at how to use intents and policy sets to enable QoS features. We’ll start at the end by describing what impact policy has on the Tuscany runtime before looking at how to use intents and policies.

10.2. The policy runtime

We have quite a few ways of configuring policy in an SCA composite application. The flexibility provided is useful, but it does make the policy framework seem a little complicated at first sight. The objective, though, is quite straightforward. Our aim is to add Java code to bindings or component implementations in order to enable QoS features.

Before we look in more detail at the policy model, this section takes a bottom-up approach by looking at how Tuscany allows policy code to be added to the runtime in the form of policy interceptors. This should answer any nagging doubt about how a policy configuration leads to something actually happening in the running application. With this knowledge, some of the mystery will be removed, and in section 10.3 we’ll continue to look at the various ways policy intents and policy sets can be used.

10.2.1. Policy interceptors

The Tuscany framework is designed to allow policy-related Java code to be added easily. Between each binding and implementation, on both service and reference ends of an SCA wire, the Tuscany framework creates chains of interceptors, one for each service operation. Each interceptor in the chain operates on incoming and outgoing messages. The processing performed depends on the interceptor in question; for example, a databinding interceptor might transform the contents of the message from one data format to another. A policy interceptor, on the other hand, might encrypt or decrypt a message.

Figure 10.2 gives an abstract view of some of the runtime artifacts that are created by Tuscany when you create a wire between two SCA components.

Figure 10.2. A high-level view of how the Tuscany runtime uses message interceptors strung out along a chain to allow policy function to be plugged in. There’s an interceptor chain for each operation within each component service and reference.

In figure 10.2, ComponentA has a reference called ReferenceA, which is wired to ServiceB of ComponentB. The reference and service have a compatible binding, the type of which isn’t specified here because this mechanism is the same regardless of which binding you choose.

Within the reference and service are three rows, or chains, of interceptors. A chain is built for each operation that the interface of ReferenceA and ServiceB provides. In this case the interface has three operations: operation1, operation2, and operation3.

A message for operation2 sent from ComponentA, via ReferenceA, passes along the middle chain of three interceptors. First, it’s processed by the implementation policy interceptors. Next, it’s processed by any other interceptors that happen to be on the chain; for example, interceptors are used here to perform databinding transformations. Finally, the message is processed by the interaction policy interceptors before being passed on to the reference binding that transports the message, using some protocol, to the service binding.

At the service side the process is reversed. The message passes from the binding into the middle of the three chains that were constructed to process messages for operation2. First, the message passes through the interaction policy interceptor before carrying on through any other interceptors on the chain. Finally, it’s processed by the implementation policy interceptor and is passed on to operation2 in the implementation of ComponentB.

With this chain of interceptors, it’s not hard to see how policy functions such as logging or encryption could be implemented and added to a running application using a Tuscany interceptor.

10.2.2. The interceptor interface

Each interceptor on the chain has to be able to do two things. It has to process a message and then pass the message on to the next interceptor. To achieve this, each interceptor implements a simple Tuscany-provided interface called Interceptor.

public interface Interceptor extends Invoker {
void setNext(Invoker next);
Invoker getNext();
}

You can see that the Interceptor interface allows interceptors to be linked together into a chain of interceptors. The Tuscany framework adds the next interceptor in the chain by calling setNext() on the last interceptor in the chain. The Invoker base class provides the interface that passes the message along the chain and is equally straightforward:

public interface Invoker {
Message invoke(Message msg);
}

The Message type here is a Tuscany interface that represents messages in a general way as they pass between the binding and the component implementation. We’ll provide a more general discussion of these two interfaces, and interceptor chains, in chapter 13.

A simple example of an interceptor is the logging implementation policy interceptor we’ve already mentioned. The following code shows a simplified version of the Tuscany logging policy interceptor that uses JDK logging to print out information about messages that are passing into or out of component implementations.

Listing 10.1. A simplified version of the JDKLoggingPolicyInterceptor

In this much-reduced version of the JDKLoggingPolicyInterceptor, all of the setup code has been omitted, and the invoke method prints out only the name of the operation and no details of the message that’s passing through. When the interceptor is added as an implementation interceptor at reference or service ends of the wire, the operation name is printed for each message that’s sent. You can see the full implementation in the Tuscany source policy-logging module.

The purpose of showing you this isn’t to provide an in-depth tutorial of policy interceptor construction but to show you that, at the end of the day, a policy interceptor is acting on messages passing between bindings and component implementations.

Now that you know a bit about how policy is implemented using an interceptor, let’s look at some examples of how a policy interceptor is configured using policy intents and policy sets.

10.3. Using intents and policy sets for implementation policy

In this first example we’ll use the Trip component from the travel-booking application and look at how to configure the logging implementation policy. You can find this example in the Tuscany SCA Tours trip-policy contribution. You can run it with the policy launcher from launchers/policy. This launcher pulls in the following contributions as well: common, payment-java-policy, and policy-client. Figure 10.3 shows what the Trip component looks like.

Figure 10.3. The Trip component providing Search and Book services. Messages flow from the service bindings to the implementation, as shown by the solid lines with arrows.

The Trip component in the trip-policy contribution provides two services, Search and Book, which allow you to search for prepackaged trips and then book one. Because we’re going to configure an implementation policy in this case, the policy will apply to the component implementation regardless of which service is being called. Let’s look at the composite description first.

10.3.1. Adding implementation intents to the composite file

Let’s start by adding a policy intent to the description of the Trip component that appears in a trip.composite file:

<component name="TripComponent">
<implementation.java class="com.tuscanyscatours.trip.impl.TripImpl"
requires="tuscany:logging"/>
<service name="Search"/>
<service name="Book"/>
</component>

The important piece of configuration here, as far as policy is concerned, is the attribute on the implementation.java element, which reads

requires="tuscany:logging"

This tells the Tuscany runtime that the intention is to log messages passing into and out of the implementation. You may be wondering how we know that that’s what this means. The string logging isn’t all that descriptive. As you learned in the overview, each intent is described in a definitions.xml file. In this case the definitions.xml is provided by the Tuscany developers inside the Tuscany source policy-logging extension module and is as follows:

<definitions xmlns="http://www.osoa.org/xmlns/sca/1.0"
targetNamespace="http://tuscany.apache.org/xmlns/sca/1.0"
xmlns:sca="http://www.osoa.org/xmlns/sca/1.0"
xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.0">

<intent name="logging"
constrains="sca:implementation.java
sca:implementation.spring">
<description>
All messages to and from this implementation must be logged
</description>
</intent>
</definitions>

First, note that intents aren’t intrinsically meaningful. The human-readable description here is the only thing that tells us what this intent means.

Second, note that the intent specifically describes what sort of elements in the composite file it can be applied to. In this case the constrains attribute says that the logging intent can be used with both implementation.java and implementation.spring.

It’s worth pointing out here that the requires attribute that allows you to add intents to the SCA composite application can be added to pretty much any element in the composite file. The constrains attribute doesn’t stop you from adding intents in the wrong place; it just tells the Tuscany runtime in which cases it should take notice of the intents. It’s also the case that child elements in the composite file inherit intents that are specified on their parent elements; we’ll cover more on this later in the chapter.

You’ve seen how the intent is defined. Let’s now look at how the runtime interprets the intent and how it chooses a policy set that satisfies the intent.

10.3.2. Choosing a policy set to satisfy the intent

Intents don’t do much in isolation. The Tuscany runtime needs to find a policy set that satisfies the intent in order to achieve the effect that’s intended. In this example the intention is to log any message passing into and out of an implementation, so we’ll need a policy set that tells the Tuscany runtime to do this.

Policy sets are specified in definitions.xml files. In this case a definitions.xml file is provided with the TuscanySCATours trip-policy contribution with the following contents:

<definitions xmlns="http://www.osoa.org/xmlns/sca/1.0"
targetNamespace="http://tuscany.apache.org/xmlns/sca/1.0"
xmlns:sca="http://www.osoa.org/xmlns/sca/1.0"
xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.0"
xmlns:scatours="http://scatours">

<policySet name="JDKLoggingPolicy"
provides="tuscany:logging"
appliesTo="sca:implementation.java">
<tuscany:jdkLogger name="myLogger">
<logLevel>FINER</logLevel>
</tuscany:jdkLogger>
</policySet>
</definitions>

This describes a policy set called JDKLoggingPolicy. The job of this policy set is to configure the Tuscany runtime to apply the implementation logging policy to the implementations of individual components.

How does Tuscany know which component implementations to apply this policy to? You can see that this policy set has an attribute called provides. This attribute describes which intents are satisfied by this policy set. In this case it’s the tuscany: logging intent we’ve already described. There’s also an appliesTo attribute, which tells the runtime which bindings or implementation types this policy set can work with. In this case this policy set is configured to work only with implementation.java. Given these two pieces of information, the Tuscany runtime can find the component implementations that have the logging intent applied to them, and from these, which ones this policy set is able to work with.

The policy configuration information is provided inside the policy set. Several types of information can appear here, as described later in this chapter, but for now you can see the tuscany:jdkLogger element. The Tuscany policy-logging extension reads this element and creates an internal model to represent the JDK logging policy. It’s configured by the logLevel element, which describes how much detail should be logged.

At runtime, Tuscany uses the internal model of the JDK logging policy to create a JDKLoggingPolicyInterceptor for the Trip component implementation. JDKLoggingPolicyInterceptor is included in the Tuscany distribution in the policy-logging module. The result is shown in figure 10.4.

Figure 10.4. The result of applying the logging policy to the Trip component implementation is that the Tuscany runtime creates a JDKLoggingPolicyInterceptor. The chains aren’t shown here, but the diagram indicates that the interceptor is applied to all operations of all services provided by the implementation of the Trip component.

The result of the policy configuration, through intents and policy sets, is the addition of the JDKLoggingPolicyInterceptor to incoming messages. We’ve already described how interceptors work. We’re not showing the individual chains here, but this implementation policy interceptor will process all the messages coming into the implementation regardless of which operation of which service they’re targeted at.

The operation of the JDKLoggingPolicyInterceptor causes log statements to be written out with varying levels of detail, depending on the logLevel configuration in the policy set. The operation of this policy, and the interceptor that does the real work, seems somewhat orthogonal to the real operation of the component implementation. This is intentional. The SCA Policy Framework is designed to allow these types of features to be added and configured in your composite application independently of the component implementations.

In this example we’ve focused on the Trip component, which doesn’t define any explicit references. When references are defined by an implementation, any implementation intents and policy sets will be applied to the reference as well. If you want to control the way that policy interceptors are applied to individual services or references, you’ll need to use an interaction policy.

10.4. Using intents and policy sets for interaction policy

Interaction policy is often the first type of policy we’re asked about. This often happens because people new to SCA and Tuscany want to connect to or provide a service with some kind of security enabled. Interaction policy can be applied to both reference and service bindings. Regardless of whether the service or reference is connected to an SCA or non-SCA service, policy can be used to configure the operation of the service or reference’s binding.

Each binding will interpret the policy configuration in a way that’s appropriate to the protocol that the binding uses. For example, a binding that uses HTTP, such as the Web Services binding, may implement an authentication policy by passing basic authentication credentials in the HTTP header. Other bindings will likely use other authentication mechanisms.

To demonstrate how interaction intents and policy sets operate, we’ll use the Web Services binding basic authentication example. We’ll configure authentication between the TuscanySCATours Payment and CreditCardPayment components. These components are defined in the payment-java-policy and creditcard-payment-jaxb-policy contributions, respectively. Again, this example is run using the policy launcher. Figure 10.5 shows the message flow.

Figure 10.5. The Payment component is wired to the CreditCardPayment component, and the reference and service are configured to use the Web Services binding. Messages flow through the reference and service, as shown by the solid line with the arrow.

As with implementation policy intents, interaction policy intents can be added just about anywhere in the composite file. The SCA rules for the inheritance of policy information ensure that the Web Services binding is configured in the correct way.

This will be quite a long section because we’ll use this Payment example to look at how interaction intents can be added into the application’s composite file or into the service and reference definitions within a Java component implementation. We’ll also look at how policy sets are defined to satisfy the intents on the service and reference sides of this example. We’ll finish up by giving a brief overview of how the runtime is configured based on the intent and policy set provided. Let’s start enabling authentication between the Payment and CreditCardPayment components by adding intents to the credit card composite file.

10.4.1. Adding interaction intents to the composite file

We’ll start by configuring the service on the CreditCardPayment component with the authentication intent. The contents of the creditcard.composite file in the credit-card-payment-jaxb contribution that contains the CreditCardPayment component definition are shown in the following listing.

Listing 10.2. The credit card composite application

Listing 10.2 shows that the authentication intent has been added directly to the <binding.ws/> element using the requires attribute . This means that any message arriving at the CreditCardPayment service over the Web Services binding requires authentication.

Note that the default binding, <binding.sca/>, has no policy annotations, and so messages arriving over this binding don’t require authentication. This sounds a little lax, so you could add authentication to the default binding in the same way it was added to the Web Services binding.

To make life a little easier and to prevent you from having to add intents on every binding, SCA allows intents and policy sets to be added at the service, component, and even the composite level. For example, if you want all bindings of the CreditCardPayment service to require that incoming messages are authenticated, you could write the following:

<service name="CreditCardPayment" requires="authentication">
<interface.wsdl .../>
<binding.ws uri="http://localhost:8082/CreditCardPayment"/>
<binding.sca/>
</service>

This literally means that the service requires authentication and implies that all bindings of the service inherit the authentication intent. You can go further and say that all services and references of a component require authentication. To do this you’d configure the authentication intent at the component level, as follows:

<component name="CreditCardPayment" requires="authentication">
<service name="CreditCardPayment">
<interface.wsdl .../>
<binding.ws uri="http://localhost:8082/CreditCardPayment"/>
<binding.sca/>
</service>
</component>

If you want every service and reference of every component in your composite application to required authentication, then you’d move the authentication intent up one more level, as follows:

  <composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
targetNamespace="http://tuscanyscatours.com/"
name="creditcard"
requires="authentication">
<component name="CreditCardPayment">
<service name="CreditCardPayment">
<interface.wsdl .../>
<binding.ws uri="http://localhost:8082/CreditCardPayment"/>
<binding.sca/>
</service>
</component>
</composite>

In all of these examples, the Tuscany runtime ensures that the service and reference bindings are configured with the intents specified in parent elements. This mechanism applies to implementations as well, so when you configured the component and the composite in the last two snippets, the authentication intents would have potentially been added to the implementation as well.

But if you remember from section 10.3.1, intents are configured in the definitions.xml file with information about which elements they apply to. Authentication is an inbuilt intent that’s defined in the following way in the Tuscany policy-security extension module’s definitions.xml file:

<intent name="authentication"
constrains="sca:binding"/>

You can see that the authentication intent applies only to bindings. Even when this intent is defined at the component or composite level, it’ll only be attached to service and reference bindings and won’t be attached to implementations.

Defining intents using the requires attribute associated with elements in the composite file isn’t the only way to add policy intents. Let’s look next at how intents can be defined in a component implementation.

10.4.2. Adding interaction intents to the component implementation

In our payment example the Payment component’s creditCardPayment reference also needs to be configured for authentication to match the expectations of the CreditCardPayment service you’ve configured. In this case you’ll add the intent directly to the Payment component’s Java implementation.

SCA provides the @Requires annotation to allow application developers to attach one or more intents directly to a Java implementation. See section 2 of the SCA Java Common Annotations and APIs specification for general information about SCA policy Java annotations (http://www.osoa.org/download/attachments/35/SCA_JavaAnnotationsAndAPIs_V100.pdf). Currently intents and policy sets can only be added directly to components with a Java implementation. Other implementation types aren’t supported in the same way, and policy configuration for non-Java implementation types must be carried out by adding intents and policy sets to the composite file.

We’re using a Java implementation in our example, and the code to add authentication to the creditCardPayment reference is shown here.

Listing 10.3. Defining intents in the Java implementation

Note that the namespace-qualified authentication intent has been added directly to the creditCardPayment reference using the @Requires annotation . Because there’s no standard way of representing a QName as a string, SCA has adopted the syntax used by javax.xml.namespace.QName, where the namespace is declared inside curly braces in front of the qualified name.

The policy intent can be specified for various scopes, including Java interfaces, Java implementation classes, business methods, or fields. But method or field-level intents override class or interface-level intents. The intents defined via Java annotations can’t be overridden by the same intents that might be defined later during assembly in the composite file. SCA follows the same inheritance rules to apply intent annotations as specified in section 2.1 of the common annotation specification, JSR 250 (http://jcp.org/en/jsr/detail?id=250).

If you look at the SCA Policy Framework specification, you’ll also see that some specific annotations are described, such as @Authentication. Tuscany doesn’t support these specific policy annotations yet and instead relies on the @Requires style, which achieves the same effect.

Adding authentication directly to the Payment component’s implementation has the same effect as if we’d added the authentication intent to the component definition in the composite file in the following way:

<component name="Payment">
<implementation.java class="com.tuscanyscatours.payment.impl.PaymentImpl"/>
<service name="Payment">
<binding.sca/>
<binding.ws uri="http://localhost:8081/Payment"/>
</service>
<reference name="customerRegistry" target="CustomerRegistry"/>
<reference name="creditCardPayment" requires="authentication">
<binding.ws uri="http://localhost:8082/CreditCardPayment"/>
</reference>
<reference name="emailGateway" target="EmailGateway"/>
<property name="transactionFee">0.02</property>
</component>

Note how requires="authentication" has been added to the creditCardPayment reference.

You may be wondering why SCA supports so many different ways of specifying policy configuration. It’s all about flexibility and choice. If you’re a component implementer who knows that a service will require authentication, then you can describe that intention by adding configuration to the implementation itself. The Tuscany runtime will then raise errors if this intent isn’t satisfied at runtime.

If, on the other hand, you want to leave it up to the application assembler to configure whether each service must only accept authenticated messages, then you’re free to do this.

We’ve made our intentions clear in our example now, but, as you know from section 10.3, when we discussed implementation policy, adding intents doesn’t provide enough information to tell the Tuscany runtime how to implement the policy. For that we’ll need policy sets.

10.4.3. Choosing a policy set to satisfy the intent at the service

As we described in section 10.3, policy sets tell the Tuscany runtime how to realize the intents that are attached to the composite application. In our authentication example we’re going to exploit the basic authentication policy defined in Tuscany, which can be applied to the Web Services binding. You’ll define a policy set in your CreditCardPayment module’s definitions.xml file from the creditcard-payment-jaxb-policy contribution, as shown here.

Listing 10.4. The CreditCardPayment definitions.xml file

First, you’ll define the policy set and give it the name BasicAuthenticationPolicySet. The attributes of the policy set say that it provides policy for the authentication intent and that it can be applied only to the SCA Web Services binding . This restriction is applied because what follows causes the Tuscany runtime to run code that will work only with the Web Services binding.

If you had attached the authentication intent to the CreditCardPayment component, then, as previously described, the result would be that the authentication intent would be added to the SCA default binding as well as the Web Services binding. In this case, the Web Services binding authentication would be handled by the Basic-AuthenticationPolicySet shown here. The authentication function of the default binding would not be handled by this policy set because of the appliesTo restriction ; that is, it doesn’t apply to binding.sca. You’d have to define an extra policy set that tells the Tuscany runtime how to handle authentication over the default SCA binding.

Looking inside the policy set you see the <tuscany:basicAuthentication> element . By their nature SCA policy sets are extensible, and this basic authentication element is a Tuscany-specific element that configures the Web Services binding for basic authentication.

On the service side the presence of this type of policy causes a basic authentication message interceptor to be introduced and also causes the Web Services binding to extract the basic authentication credentials from the incoming message and make them available for the interceptor to process. In the default implementation that Tuscany ships with, all that the interceptor does is compare the incoming credentials with the username and password specified in the policy set. The following listing shows the code for the BasicAuthenticationServicePolicyInterceptor’s invoke method. This can be found in the Tuscany policy-security module.

Listing 10.5. BasicAuthenticationServicePolicyInterceptor invoke
public Message invoke(Message msg) {
Subject subject = SecurityUtil.getSubject(msg);
BasicAuthenticationPrincipal principal =
SecurityUtil.getPrincipal(subject,
BasicAuthenticationPrincipal.class);
boolean authenticated = false;

if (principal != null){

System.out.println("Authenticating user: " +
principal.getName());

if (policySet != null) {
for (Object policyObject : policySet.getPolicies()){
if (policyObject instanceof BasicAuthenticationPolicy){
BasicAuthenticationPolicy policy =
(BasicAuthenticationPolicy)policyObject;
if (policy.getUserName().equals(principal.getName())){
if (policy.getPassword().equals(principal.getPassword())){
authenticated = true;
}
}
}
}

}
}

if (authenticated == false){
throw new ServiceRuntimeException("User: " +
principal.getName() +
" cannot be authenticated");
}

return getNext().invoke(msg);
}

The invoke method retrieves the policy subject from the incoming message, retrieves the principal from the subject, and then compares the name and password in the principal with the name and password provided in the policy set.

This policy isn’t exactly what you’d call a production-quality policy and is severely restricted in the amount of flexibility that it allows for managing authenticated users. But it does demonstrate the approach, and it would be easy to extend or replace the interceptor in order to call out to some more proficient security provider such as an LDAP-based registry.

For our example to work properly, you’ll need to have a policy set that will provide an implementation for the authentication intent that’s attached to the creditCardPayment reference of the Payment component.

10.4.4. Choosing a policy set to satisfy the intent at the reference

In this example you’re running the Payment and CreditCardPayment components in separate composites on separate nodes. This means that you’ll need to define a separate definitions.xml file for the Payment component. This is because the two composites are effectively running in separate domains. But the policy set is identical to the policy set we provided for the CreditCardComponent.

<policySet name="BasicAuthenticationPolicySet"
provides="authentication"
appliesTo="sca:binding.ws">
<tuscany:basicAuthentication>
<tuscany:userName>myname</tuscany:userName>
<tuscany:password>mypassword</tuscany:password>
</tuscany:basicAuthentication>
</policySet>

At the reference side this causes the Tuscany runtime to add an interceptor to the message flow for the creditCardPayment reference. This interceptor takes the username and password from the policy set and adds it to the message passing along the chain. The presence of this policy set also configures the Web Services binding to take the credentials from the message and add them to the HTTP header of the outgoing message. The following snippet shows that the BasicAuthenticationReferencePolicyInterceptor invoke method is simplistic:

public Message invoke(Message msg) {
Subject subject = SecurityUtil.getSubject(msg);
BasicAuthenticationPrincipal principal =
SecurityUtil.getPrincipal(subject,
BasicAuthenticationPrincipal.class);

if (principal == null &&
policy.getUserName() != null &&
!policy.getUserName().equals("")) {
principal = new BasicAuthenticationPrincipal(policy.getUserName(),
policy.getPassword());
subject.getPrincipals().add(principal);
}
return getNext().invoke(msg);
}

The code first looks to see if any principal information has been placed on the message by the implementation. This could be the case when the implementation is operating within an existing security context. Assuming that no principal information is found, a principal is constructed based on the information contained in the policy set.

The reference side of the basic authentication policy is more useful than the service side in real applications because it allows you to talk to non-SCA web services that exploit basic authentication.

10.4.5. Running the payment example with authentication enabled

You’ve added the authentication intent at both the CreditCardPayment reference and service, and you’ve added policy sets to describe what the Tuscany runtime should do to implement these intents. Now you can run the sample, using the payment-java-policy launcher, and see the effect of this configuration.

In this case the launcher runs two nodes in effectively separate domains. The first node is configured with the creditcard-payment-jaxb-policy contribution that contains the following files:

creditcard-payment-jaxb-policy/
META-INF/
sca-contribution.xml
com.tuscanyscatours.payment.creditcard/
CreditCardPayment.java
com.tuscanyscatours.payment.creditcard.impl/
CreditCardPaymentImpl.java
creditcard.composite
CreditCardPayment.wsdl
definitions.xml

The layout and contents of this contribution should be familiar to you by now. The sca-contribution.xml file describes the contribution, and the creditcard.composite file describes the composite application, which, in this case, has the CreditCardPayment component in it. The Java and WSDL files describe the component service interface and the component implementation. The important file that’s packaged with this contribution as far as policy is concerned is the definitions.xml file that describes the basic authentication policy we’ve already looked at.

The second node starts two contributions: the policy-client contribution and the payment-java-policy contribution. The payment-client contribution adds a client component to call the Payment component so that it in turn will call the CreditCardPayment component. Of most interest is the Payment contribution, which contains the following files:

payment-java-policy/
META-INF/
sca-contribution.xml
com.tuscanyscatours.payment/
Payment.java
com.tuscanyscatours.payment.impl/
PaymentImpl.java
payment.composite
Payment.wsdl
CreditCardPayment.wsdl
definitions.xml

Again, everything is pretty much as you’d expect to find it (we’ve omitted some of the Java files here to keep the listing short), but notice that there’s another definitions.xml file. This again holds the definition of the basic authentication, but this time the policy will be applied to the reference.

Figure 10.6 shows the components and the effects of the policy configuration in enabling message authentication between the Payment and CreditCardPayment components.

Figure 10.6. The result of applying the authentication policy to the Payment and CreditCardPayment components is that the Tuscany runtime creates a basic authentication interceptor in both reference and service chains and configures the Web Services binding to use the HTTP header to pass basic authentication credentials.

If you were to look at the HTTP message that passed between the reference and service Web Services bindings in this case, you’d see something like the message shown in the following listing.

Listing 10.6. The credit card authorization message with basic authentication enabled

The important line is the line in the HTTP header that starts with Authorization , which has been added by virtue of the intent and policy set configuration. We should point out that you wouldn’t want to send credit card details without encrypting them using just basic authentication. You’d want to have the content encrypted using a confidentiality intent. But this is just a sample so that you can see the effect of adding intents.

Now if you were to disable the reference-side policy by removing the authentication intent from the reference, for example, the sample would fail with an error because the service side still expects messages to contain credentials.

We’ve spent a lot of time looking at how to add intents and then define policy sets for interaction policies, in this section, and implementation policies, in the previous section. Such policies allow you to configure the QoS provided by the component services you build. Interaction policy also allows you to configure QoS when communicating with other SCA or non-SCA services.

Now that you have the basics, let’s take a quick look at some of the other features that the policy framework specification includes.

10.5. Other features of the SCA Policy Framework

Now that we’ve walked through how intents and policy sets are used in general, you should be aware of a few other features.

We’ll look at some of the flexibility you have if you’re using intents. Profile intents can be used to group other intents together. Qualified intents can be used to structure your intent’s namespace, and finally the definitions.xml file can be used to define the default intents provided by SCA bindings.

We’ll start by looking at how policy sets can be attached directly to the composite application without first associating intents with the composite application. This is useful if the person assembling the application wants to be explicit about which policy sets should be used.

10.5.1. Dealing with policy sets directly

In the previous sections, where we discussed implementation and interaction policy, we started by adding intents to the composite application and then defined policy sets that were linked to the abstract intents using the provides attribute. This use of abstract intents is useful when you want to separate the role of the person who sets the QoS intention from that of the person who configures policy implementation in your particular environment. But the use of intents isn’t mandatory, and you can use policy sets directly in both the composite file and in Java implementations.

In the composite file a policy set is attached directly to an element using the policySets attribute. In our previous payment example we could have configured the CreditCardPayment reference in the composite file in the following way:

<component name="Payment">
<implementation.java
class="com.tuscanyscatours.payment.impl.PaymentImpl" />
<service name="Payment">
<binding.sca/>
<binding.ws uri="http://localhost:8081/Payment"/>
</service>
<reference name="customerRegistry" target="CustomerRegistry"/>
<reference name="creditCardPayment"
policySets="BasicAuthenticationPolicySet">
<binding.ws uri="http://localhost:8082/CreditCardPayment"/>
</reference>
<reference name="emailGateway" target="EmailGateway"/>
<property name="transactionFee">0.02</property>
</component>

Note that the creditCardPayment reference now has a policySets attribute, which references the BasicAuthenticationPolicySet policy set directly.

This equivalent approach can be taken in this component’s Java implementation. SCA provides the @PolicySets annotation to allow Java developers to specify policy sets. A policy name is a string in the form of a qualified name (QName). As we said previously, SCA has adopted the syntax used by javax.xml.namespace.QName where the namespace is declared inside curly braces in front of the qualified name, for example:

@PolicySets("{http://www.osoa.org/xmlns/sca/
1.0}BasicAuthenticationPolicySet")

@PolicySets can be specified for two or more policy set names using a comma-separated list, for example:

@PolicySets({"{http://www.osoa.org/xmlns/sca/1.0}FirstPolicySet",
"{http://www.osoa.org/xmlns/sca/1.0}SecondPolicySet"})

@PolicySets can be specified for various scopes in the implementation including Java interfaces, Java classes, methods, or fields. The method or field-level policy sets override the class or interface ones. SCA follows the same inheritance rules to apply policy set annotations as specified by the Common Annotations for Java Specification, JSR 250. Policy sets must satisfy intents expressed for the implementation when both are present.

10.5.2. Profile intents

Intents can be used to collect other intents. This makes it easier for the assembler to configure combinations of intents. For example, if you wanted to configure a reference or service with a combination of intents that include integrity and confidentiality, you could define a profile intent as follows:

<sca:intent name="messageProtection"
constrains="sca:binding"
requires="confidentiality integrity">
<sca:description>
Protect messages from unauthorized reading or modification
</sca:description>
</sca:intent>

When a profile intent is used, the Tuscany runtime will automatically replace the profile intent with the individual intents that it requires, and processing will continue, as we’ve already described.

10.5.3. Intent qualification

The SCA Policy Framework Specification provides a way to group intents, where an intent can be further qualified to add more detail to the description of the QoS that’s required. A good example of this is the SOAP intent that can be used to control the version of SOAP that the Web Services binding uses. The SCA Web Services Binding Specification defines the following intents:

<sca:intent name="SOAP" constrains="sca:binding.ws">
<sca:description>
Communication through this binding requires SOAP
</sca:description>
</sca:intent>

<sca:intent name="SOAP.1_1">
<sca:description>
Communication through this binding requires SOAP 1.1
</sca:description>
</sca:intent>

<sca:intent name="SOAP.1_2">
<sca:description>
Communication through this binding requires SOAP 1.2
</sca:description>
</sca:intent>

This simplifies the definition of the group of intents. The main or qualifiable intent, SOAP, defines what elements this intent constrains. The qualified intents, SOAP.1_1 and SOAP.1_2, serve to extend the SOAP intent to provide further fidelity of configuration.

10.5.4. Default intents

A definitions.xml file can contain information about what intents an extension supports by default. The <bindingType> and <implementationType> elements support this configuration. For example, the Web Services binding, which is described in chapter 7, has a definitions.xml file with the following configuration:

<sca:bindingType type="sca:binding.ws"
mayProvide="SOAP SOAP.1_1 SOAP.1_2 MTOM"
alwaysProvides=""/>

This says that the binding.ws extension can optionally be configured with the SOAP, SOAP.1_1, SOAP.1_2, or MTOM intents, and it’ll know what to do with them without your having to provide a policy set. These intents are configured as mayProvide because they can optionally be attached to binding.ws in the composite file.

If there are intents that an extension provides regardless of how the composite application is configured, they’d appear in the alwaysProvides attribute.

We’ve covered a good deal of ground now and explained how you can attach policy to various parts of your composite application. Let’s now take a short tour of the policies that Tuscany currently supports.

10.6. Tuscany intents and policy sets

Intents and policies in Tuscany have been developed as required by the Tuscany community. There aren’t that many so far, and it’s no surprise that intents and policies have been created first for popular bindings, such as the Web Services binding.

Table 10.1 provides an index of some of the more useful intents and policies that Tuscany currently supports. To understand how to use these in detail, look at the examples referenced in the description text.

Table 10.1. Summary of useful intents and policies in Tuscany

Intent

Policy

Description

binding.ws    
SOAP Provided by binding.ws Qualified interaction intent that can be used to configure the Web Services binding to use either the SOAP.1_1 or SOAP.1_2 protocol.
MTOM Provided by binding.ws Interaction intent that tells the Web Services binding to pass binary data using the Axis2 MTOM support.
authentication <tuscany:
basicAuthentication/>
Interaction intent/policy that tells the Web Services binding to use HTTP-based basic authentication. See payment-java-policy and creditcard-payment-jaxb-policy.
authentication
integrity
confidentiality
<tuscany:wsConfigParam> Interaction intent/policy that can be used to set Axis2 configuration parameters. See sample/helloworld-ws-reference-secure, where it’s used to set Inflow and OutflowSecurity parameters.
authentication
integrity
confidentiality
<wsp:Policy/> Interaction intent/policy that uses WS policy to configure Axis Rampart. See sample/helloworld-ws-reference-secure.
binding.jms    
priority <tuscany:jmsHeader/> Interaction intent/policy used to demonstrate the use of policy as an alternative to more direct configuration of the binding.
deliveryMode <tuscany:jmsHeader/> Interaction intent/policy used to demonstrate the use of policy as an alternative to more direct configuration of the binding.
binding.http    
authentication <tuscany:
authenticationConfiguration/>
Interaction intent/policy used to configure an HTTP endpoint to request expect HTTP basic authentication. See samples/store-secure.
confidentiality <tuscany:confidentiality> Interaction intent/policy used to configure an HTTP endpoint to use an HTTP transport. See samples/store-secure.
General    
tuscany:logging <tuscany:jdkLogger> Logs messages passing into or out of an implementation.

In general, the intents will already be defined in definitions.xml files shipped with Tuscany extensions, such as binding.ws. To satisfy the intents, you’ll need to build a policy set inside a definitions.xml file included in one of your application’s contributions. Table 10.1 lists the policy elements you can use to build a policy set. Where the table says that the policy is provided by an extension, this means that it’s a default intent and there’s no need to define a policy set.

If the policy is an interaction policy such as authorization or integrity, the Tuscany runtime will apply it before the implementation is called. Therefore, interaction policies are invisible to the implementation. Any processing required by the policy is performed by the Tuscany runtime within the reference or service code without implementation involvement.

At the time of writing, only Java implementations support the inclusion of annotations for policy intents and policy sets. You can’t associate intents and policy sets directly with Spring applications, BPEL processes, or scripts. You can, though, associate implementation intents and policies with the implementation element in the composite file.

Because we have relatively few policies implemented at present, as described in table 10.1, it’s likely that the precise QoS configuration you require isn’t already supported, and so we encourage you to look at the existing policy extensions and improve them for your own needs and even better consider contributing any improvements to the Tuscany project.

10.7. Summary

Supporting quality of service in an application is one of those things that we all know we have to do. We also know that having to code this kind of functionality in each component implementation we build doesn’t lead to happiness. We complicate our business logic and repeat code that others are probably better qualified to construct.

The Tuscany and SCA Policy Framework provides a structured way of defining and building the QoS functions required by our SCA applications. The Policy Framework allows us to do this independently of the component implementations we build. This has a number of important benefits. Our business logic isn’t mixed up with QoS code. The QoS features can be developed at an enterprise level and can be applied consistently across many components and applications. Finally, it supports the clear separation of roles between the business logic developers and those responsible for assembling and deploying SCA applications in the enterprise environment.

You’ve now had good look at the policy framework and the ways in which you can use intents and policy sets to configure your applications. This brings this section on using the detailed features of Apache Tuscany to a close. We’re going to move on now and look at how to deploy the applications you build.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.224.135