First of all, what is the use case and how is it different from doing authorization at the SOAP level with something like the to be built OWSM+OES integration? A couple distinctions:
- Authorization at the SOAP endpoint level is for the user/subject invoking the end-point. A callout from inside of BPEL could be for any user.
- Authorization at the SOAP endpoint results in a YES/NO decision. In the NO case, users are denied access. A callout from inside BPEL may result in something else...like a message being routed differently or elements being restricted
- Authorizations at the SOAP endpoint level are typically concerned with what is going into the message, not what is going out. A callout from inside of BPEL can affect messages in/and out - SOAP endpoing can also, its just not typically done.
So this begs the question, is OES here just a rules engine? Why not use the built in rules engine in BPEL? Good questions, strawman Josh. I think the difference is that rules in the rules engine are configured by developers. Policies in OES can be centrally managed and span multiple applications/domains/organizations. They can be changed and applied in the application without making any code changes, and allows developers to focus on building true business logic, not security logic.
One more thought, before the details. I probably could have just called OES with WebServices SM as a service using SOAP, but in all of our testing SOAP does not perform nearly as well as in-process. Besides, in process in the context of SOA composite can allow us to write very context rich policies that perform very nicely. Enough of the set-up, here's the approach.
Once you've got the SOA domain configured (see my previous 3 part epic), you're doing to make a Java callout from inside of the BPEL process to OES. I found developing inside of a Java callout very cumbersome, so really all that the Java callout does is pass in 2 DOM Node instances - one for input and one for output. There was a lesson learned here - you don't need to set the variable from inside the embedded Java - just get the variable and update in place.
The Nodes are variables from inside of the BPEL process, so this sets up an interesting pattern - XML in (data) - apply some policy - XML out (data). This is just another variation of the data-security...much simpler in many respects because the data is already there - given to me by BPEL. Thing of this as a Post query data security...for some small set of managable records, apply security policy about which ones and which data from those elements should be included.
Now from inside of the OES Facade (the class that gets called from the BPEL to process the Node) instantiate a handle to the OES API (I used the JavaAPIExample that ships with the Java SM) and start making authorization decisions...oh wait. What if I don't have an identity or what if the users are part of the messages, and I want to do authorization on their behalf? SSPI to the rescue again - just use the UsernameIdentityAsserter...also in the examples directory of the java-sm. The UsernameIdentityAsserter will basically just authenticate you with a clear text token. Standard Disclaimer here: You need to make sure that if you are going to configure this IdentityAsserter, that there are other controls, otherwise anyone who knows a username could impersonate that user.
Ok, now that we have the AuthenticIdentity, start doing authorization. You have the Node, and it can be passed as a dynamic attribute to OES for policy evaluation. Alternatively, you could jut pull information out of the DOM and pass it to OES. I think there is also a generic pattern here (I'm too jet lagged to say more but the idea is that the XML document is passed in and then you do an authorization query where the resources in OES miminc the schema in XML to determine what parts of the document that the user can see). I think there are a lot of interesting approaches here.
One more, and really I think the coolest part of the integration is the use of Service Interfaces to retrieve additional data for authorization. I spent a lot of time on this approach because Service Interfaces are very common inside of BPEL, and I felt like it would avoid a lot of the class loading issues that some time arise with attribute retrievers. On the other-hand, I needed a way that performed, that is I didn't want to go fetch a bunch of additional data that was not going to evaluated by the policy. I wanted the policy to come back and say - "Hey can you go fetch the user'd data of birth...I need that." OES has a way to do that, in the form of a special response - MissingAttributeResponse. It tells you which attribute was not there. This only works if you don't include sys_defined() around the attributes in the OES policy.
GRANT (//priv/edit, //role/Editor, //app/policy/book) if book_still_in_print=true;
If you make an isAccessedAllowed call, the result will come back as false, but with a response that includes a MissingAttributeResponse for book_still_in_print. So, now how to get this information. The ServiceInterface for an application module can be accessed from inside the server using JNDI. When you received the response, grab the InitialContext and lookup the Service (you should be able to find it based on the @PortableWebService annotation on the ServiceImpl). Look at that! All of the methods of the ServiceInterface available to add data to a decision. Definitely simpler than configuring them externally from an AttributeRetriever. Normally, I frown on applications have their own connections to Policy Information Point, but this is an exceptional case - the data is already presumably there from inside the composite.
This may turn out to be a very specialized use case - post query data security from inside a BPEL process - and not a general purpose SOA security use case like OES+OWSM or even OES+BPEL in some other scenario (I'll always take requests), but I feel after watching this thing in action, I have very impressed with how easy it was to write policy to do very powerful things from inside a BPEL. I like the idea of an explicit callout instead of embedding the OES API inside of a custom XSLT transform - more transparency at a business/process level as to what is going on, but I'm sure there are some scenarios where XSLT calling OES makes sense.