Wednesday, October 27, 2010

Keystores and signing your SAML assertions

I've been working on a project recently that includes SOAP clients submitting messages via JMS and HTTP to Oracle Service Bus (OSB). OSB is supposed to validate the assertion, perhaps do some transformations on the SOAP, and then send the message off to some backend service. I'll probably talk about the last two thirds of the solution at some point in the future, but it's the first third that has raised a bunch of questions that other people probably have too.

Before I go into the details let me just remind you that the details here are specific to this customer's situation. I'm not advocating for, endorsing or otherwise suggesting that the info here is useful to YOUR situation. With that said...

The customer's architecture includes submitting the messages over a 2-way SSL channel and they want to use SAML 1.1 assertions with the Bearer confirmation method. Most people are probably more familiar with the Sender Vouches method in which the entity sending the SAML assertion (i.e. the SOAP client) is trusted by the receiving party - which means that every client needs a private key and the receiver needs to have the associated Certificate (or the issuer's Certificate).

In Bearer the sender of the message isn't necessarily the party that actually created the SAML Assertion; if they were then you could just use Sender Vouches and be done. In Bearer you're saying that the communication channel authenticates the caller; this also means that the party sending the message could get a SAML assertion from somewhere else and then just includes it in the SOAP message. There are a bunch of dangers in this sort of architecture, but you can mitigate most of them through appropriate architectural choices. What those dangers are and how you mitigate them is a subject for a separate post. There's a third confirmation method called Holder of Key which is, again, a great subject for another post.

In any case when you use the Bearer Confirmation Method you might want the assertion to be signed, especially if it comes from somewhere other than the client. So who has the private key? And what certificates do you need to put in the keystore?

When you install WebLogic the installer automatically creates a couple of keystores for you. Gerard Davison discusses this a bit in a blog post in the context of setting up SSL. We can use the same keystores for testing SOAP.

First here's the table (shamelessly copied) from Gerard's post:

Property Value
Trust store location wlserver_10.3/ server/lib/DemoTrust.jks
Trust store passwordDemoTrustKeyStorePassPhrase
Key store location wlserver_10.3/ server/lib/DemoIdentity.jks
Key store passwordDemoIdentityKeyStorePassPhrase
Private key passwordDemoIdentityPassPhrase

As you can see there are two JKS files - DemoTrust.jks and DemoIdentity.jks. Take a look at the contents of them by using keytool:

keytool -list -keystore DemoIdentity.jks -storepass DemoIdentityKeyStorePassPhrase
keytool -list -keystore DemoTrust.jks -storepass DemoTrustKeyStorePassPhrase

You'll find that DemoIdentity.jks contains a Private Key and DemoTrust.jks contains the associated Certificate (and a few others).


I'm a huge fan of automated unit test tools. I'll often invest literally tens of hours writing test drivers that will be thrown away when the project is done just so I can be sure that I haven't missed anything. More importantly I want to be 100% sure that we've got test coverage for all of the positive and negative cases we've thought of in the design phase.


So for my little SOAP tester in my test environment I can use the DemoIdentity.jks file to sign the SAML Assertion and as long as OSB is configured to use DemoTrust.jks it should accept my SAML Assertion.

In the real world you definitely won't be using the DemoTrust keystore. Instead you'll create another Key Store to be used on the OSB server and you'll probably put the Certificate of the SAML assertion generator in there (if it's a self-signed cert) or the Cert chain needed to verify the signature.

Hope this helps!

Monday, October 25, 2010

Quick tip: OVD – Providing namespace translation for DN attributes

Breaking off the ADF/OPSS series…

OVD (Oracle Virtual Directory) guru Mark Wilcox gave me this really helpful tip that it’s worth sharing. It can save you folks quite a bit of headache.

Scenario: you have configured an OVD authentication provider in WLS, but you cannot login with any user from OVD in WLS Console, even the user being a member of an Administrators group in the backend LDAP directory. When you try it, you end up with an “Authentication Denied” error. And if you login into WLS Console in the “normal” way (i.e., using weblogic user from Default Authenticator provider) you don’t see the OVD users memberships. These two problems are definitely related.

Solution: you need to change the LDAP adapter definition in OVD a bit. Connect to ODSM (Oracle Directory Services Manager), retrieve your adapter, click on the General tab and add uniquemeber as one of DN Attributes, as shown:

image

OVD translates all attributes listed as DN Attributes. Translation here means converting the backend repository (in this case OID) namespace into the adapter’s namespace. In this example, OID namespace is dc=us,dc=oracle,dc=com, while adapter’s is ou=oid,dc=us,dc=oracle,dc=com. Without the translation, uniquemembers of a group would end up being cn=<user>,dc=us,dc=oracle,dc=com. With the translation, they align nicely with the adapter’s namespace: cn=<user>,ou=oid,dc=us,dc=oracle,dc=com.

No need to restart anything. You should now be able to see users memberships as well as login in WLS Console with administrators users defined in the OVD authentication provider.

Note: this has been done in Oracle Identity Management 11g PS2.

Wednesday, October 20, 2010

Several ADF apps to one single OPSS policy stripe

In OPSS Artifacts Life Cycle in ADF Applications, I’ve explained how to change the default behavior for migration of authorization policies when deploying applications. Revisiting it, I’ve said that one can specify the MERGE value for jps.policystore.migration param-name in weblogic-application.xml and that is particularly useful in some deployments where more than one application have to share the same policy context (or policy stripe).

A real use case is when a customer wants to hide the concept of how a system is partitioned across ADF applications for security administrators. Most of the times, a security administrator is interested in the policies of the system as whole. This article explains how it can be done.
Before going further, some definitions:
  • Policy Store: repository of policies comprising one or more application policy stripes and code-based grants. There’s only one policy store per WLS domain.
  • Policy Stripe: set of application policies to which one or more applications bind to. One application binds to only one policy stripe.
Clarifying a little bit more, take the following system-jazn-data.xml snippet, the OOTB policy store in WLS domains. In such case, system-jazn-data.xml itself represents the policy store, while OrderEntry#V2.0 and OrderCapture#V2.0 are the policy stripes, defining an application-level scope for authorization policies. In default mode, OrderEntry application does not have access to application policies in OrderCapture#V2.0 policy stripe, and vice-versa.

<?xml version='1.0' encoding='utf-8'?>
<jazn-data>
<policy-store>
<applications>
<application>
<name>OrderEntry#V2.0</name>
<app-roles>
...
</app-roles>
<jazn-policy>
...
</jazn-policy>
</application>
<application>
<name>OrderCapture#V2.0</name>
<app-roles>
...
</app-roles>
<jazn-policy>
...
</jazn-policy>
</application>
</applications>
</policy-store>
</jazn-data>

When we develop an ADF application in JDeveloper and enables ADF security, the authorization policies you create go into a workspace-level jazn-data.xml under a stripe name that has the same name as the application itself, as show below. Let’s say our application is called OrderEntry. In jazn-data, we would have:

<?xml version='1.0' encoding='utf-8'?>
<jazn-data>
<policy-store>
<applications>
<application>
<name>OrderEntry</name>
<app-roles>
...
</app-roles>
<jazn-policy>
...
</jazn-policy>
</application>
</applications>
</policy-store>
</jazn-data>

Then if you do nothing and just deploy the application, the policies get migrated to the runtime policy store under an application policy stripe named OrderEntry#V2.0. For our mental sanity, the V2.0 comes from the Weblogic-Application-Version property in the MANIFEST.MF, but this is not the topic of this article.

Now what happens if we want to have OrderEntry and OrderCapture binding to the same policy stripe, say OrderMgmt? We need to add some properties to some deployment descriptors:

1) in weblogic-application.xml:

<application-param>
<param-name>jps.policystore.applicationid</param-name>
<param-value>OrderMgmt</param-value>
</application-param>

Such information is used only at deployment time. It basically tell the OPSS listeners to migrate application policies in jazn-data.xml to OrderMgmt policy stripe in the runtime policy store. In this scenario, the version number is not appended to the stripe name.

2) in web application’s web.xml:

<filter>
<filter-name>JpsFilter</filter-name>
<filter-class>oracle.security.jps.ee.http.JpsFilter</filter-class>
<init-param>
<param-name>enable.anonymous</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>remove.anonymous.role</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>application.name</param-name>
<param-value>OrderMgmt</param-value>
</init-param>
</filter>

Here I have added the init-param application.name to the JpsFilter definition. The param-value must match the value defined in weblogic-application.xml. This information is used only at runtime. It tells the JpsFilter where to bind to when looking for authorization policies. As the JpsFilter intercepts all requests for the Faces Servlet (javax.faces.webapp.FacesServlet), it establishes the policy store context for every request to an ADF artifact.

By repeating this very same configuration across your applications, you can bind any number of applications to the same policy stripe, i.e., the same authorization context and expose a single and consolidated view of your authorization policies to security administrators.