Saturday, July 18, 2009

WS-SecureConversation

WebLogic 11g (10.3.1) has support for WS-SecureConversation. What is WS-SecureConversation? According to Wikipedia, not much more than a specification from IBM, MSFT and others. Recently, I've had a couple of customers asking about WS-SecureConversation and how WLS can support it so I wanted to take a little time to discuss what WS-SecureConversation is and explain how to configure WS-SecureConversation on WLS 11g.

WS-SecureConversation enables the creation of a SecurityContext between a web-service producer and consumer. The SecurityContext is essentially a shared key. The SecurityContext is created first, and then the message exchange begins. WS-SecureConversation uses the WS-Trust specification to establish the SecurityContext. One common approach is to use WS-Trust to communicate with a SecurityTokenService (STS). Another is for the consumer and the producer to negotiate the SecurityContext directly. In WebLogic Server, this process is called "bootstrapping". The difference among the policies is just how the two parties establish trust so that they can securely exchange the shared key. Often, the shared key for the security context is used to calculate DerivedKey. Using the concept of DerivedKeys it is common to have one key used for signing the message and another to encrypt the message.

The sample client illustrates how to configure a client application to use WS-SecureConversation. The details on the setting up the server are not obvious, so I'll cover them here.

You'll need a client public/private key-pair and a server public/private key-pair. For demos, I'll just use utils.CertGen and utils.ImportPrivateKey. You'll need both of them in their own java keystore, as well as the certificate in PEM format. Once the SecurityContext is established, messages will be secured with the DerivedKeys, but to establish the SecurityContext, X.509 certificates and either WS-Security or SSL is used to exchange the keys. This is why you need the keys.

In order to configure the server to use DerivedKeys and the SecurityContext, you need to configure a domain level webservice configuration, and set-up the appropriate certificates and credential-providers (DerivedKeys and SecureConversation). This can be very tedious manual process. Fortunately, there is a sample that has a WLST script that does it for you.

WL_HOME\samples\server\examples\src\examples\webservices\wsrm_security\configWss_Service.py

Run the script as follows:

java weblogic.WLST weblogic welcome1 localhost 7001 serverkeystore.jks serverkeystorepass serveralias serverkeypassword

You'll also need to create a CertPath provider, mark it as the default builder, and then configure both the client certificate and server certificates as trusted.

Finally, deploy a web-service protected by the bootstrapping policy, for example:

@Policy(uri = "policy:Wssp1.2-2007-Wssc1.3-Bootstrap-Wss1.1.xml")

This will sign the message with the DerivedKeys. If you want the body encrypted as well, use the following policies:

@Policies(
{@Policy(uri = "policy:Wssp1.2-2007-Wssc1.3-Bootstrap-Wss1.1.xml"),
@Policy(uri = "policy:Wssp1.2-2007-EncryptBody.xml")}
)

You'll need to modify the sample to use your generated stubs. Make sure that you use JAX-RPC web-service stub.

This is probably the first of a few posts of WS-SecureConversation. I'll definitely need to cover the topics of WS-SecureConversation and WS-Trust, WS-SecureConversation and WS-ReliableMessaging. If there are more topics of interest, let me know.

Friday, July 17, 2009

Oracle Open World 2009 - Identity Management Sessions

The list of sessions for Oracle OpenWorld 2009 is available.

I'll be presenting on Oracle Web Services Manager (OWSM) and securing FMW 11g. I was talking to Vikas last night (driving back from NJ) and the current thinking for the presentation/demo is:

MSFT .net client using Kerberos Token Profile invokes a BPEL process which in turn invokes JAX-WS WebService running on SOA Suite 11g. We'll probably use SAML (Sender vouches?) to get end-to-end identity propagation from BPEL to the final service.

I'm definately open for input/suggestions for what people would want to see. Also, I'm exceited about the opportunity to present as I'll get to continue to come-up to speed on OWSM 11g. Obviously, this will be a source for numerous postings here.

Stay tuned

Tuesday, July 14, 2009

SOA Perspective on Authorization

I'm blogging in two places, and some times I'm not sure which makes the most sense. Thanks to modern search technology, maybe it doesn't matter :)

I just finished a post on Authorization Pre-Caching. To avoid accusations of a "Remember When" cheesy sitcom, re-tread post, I'll add some more color on this use case in the broader context of SOA, and specifically OSB.

If you want to have a centralized authorization solution and it needs to be very very fast, SOAP is not a good choice. In my experience you're adding 10s of ms latency compared to a binary protocol like RMI. For general purpose services this may not matter, but for fast authorization/entitlement services this is a non starter. If you have to have a very fast binary protocol, consider building a custom transport.

This enables the very fast compact protocol that is required to meet extreme performance requirements, but instead of a proprietary or light-weight contained, it can be serviced by an enterprise class container that provides routing, SLA, reporting (insert OSB marketing here)

If said modern search technology brought you here, and you found a post on exposing security functionality with SOA, but you really wanted "How to Secure my SOA", try here - from last year's OOW

Thursday, July 9, 2009

OPSS Sample Application


Over the past few weeks, I'd been working with the development team on putting together a nice OPSS Sample Application

The README gives a lot of detail about what the application does and how to use it, so I wanted to spend a little time here to point out some of the ways that existing WLS secured applications can be enhanced with OPSS and also some of the finer points on the application itself.

OPSS provides some good simple user profile services. Admittedly not as elaborate as something like an OIM would provide, but probably cleaner and easier to implement then going through the MBeanReader interfaces of WLS. Also, unlike the MBean interfaces in WLS, there is more than just users and groups. There's user and group attributes. In the sample application this is all very nicely wired to the embedded LDAP that ships with WLS, but through simple configuration can be changed to work with an enterprise repository (LDAP).

If you look at the initialize method of the LdapIdStore class inside of the LdapDC project, you see the set-up of the JPSContextFactory, JPSContext, and IdentityStore instances. The IdentityStore is essentially a handle the the AuthenticationProvider configured in WLS. In the same project, you'll also find the LdapIdStoreView class. This class demonstrates how to get a handle to the UserManager and RoleManager classes. These classes give you access to the users and enterprise roles defined in the application. The FMW Security Guide has all of the details

In the sample application, there are three enterprise roles - basic user, premium user and ezshareadmin. Notice that the sample application also comes pre-configured with a list of users assigned to those roles. This was all done from JDeveloper and packages as part of the application. When the application is deployed, the information is published into WebLogic Server's authentication provider - the embedded LDAP. For building applications, this can simplify and speed testing. All of the user, group, policy information etc. is stored in the jazn-data.xml, and as I mentioned can be edited from inside of JDeveloper.


In general, I'm not a huge fan of the Java 2 security model, but I think that the way that the CredentialStoreFramework (CSF) uses it in this example is reasonable. Basically, all of the encryption/decryption of the files is done with a symmetric key. Any code that can gain access to that key can access the messages. By using Java 2 permissions model, and having to explicitly grant code access to the key, this restricts the access to only authorized code. This is very useful in centralized environments where many applications are hosted in a single server. In the sample application all of the code is granted access for simplicity, but could be further restricted depending on requirements. This model also breaks the cycle of having to have the password to something...for example, keys are stored in a Java Keystore require a cleartext password to get the private key, but then where do you store that password? Prompt for it at start-up? Java 2 security provides the answer.

I also like the way that the sample application implements accessing the credential store. All of the access is centralized through two methods in the CryptoUtil class. This class can be found in the ezShareModel project. The key thing is that it uses PriviledgedAction to access the store.


This greatly simplifies the configuration of the Java 2 permissions since only the CryptoUtil.class has to be granted access, regardless of whatever other code is in the call stack.

I personally think the coolest part of the sample application is the way that the encryption and decryption is integrated into the ADF View Object. I'm constantly getting questions about data security - mostly around authorization - but this is another key requirement - confidentiality of data on disk. This can be achieved using features of the database, but what this solution shows is a clever way to do it from the middleware. If you look at the BasicFilesView.xml and BasicFilesViewRowImpl.java also in the ezShareModel project, you'll see that the view is using a custom row implementation, and that implementation in-turn is using the CryptoUtil class for all of its encryption/decryption. Very nice!

People can definitely post their questions here about the sample application or maybe suggest some use cases for extending the application....maybe Web Services security...interesting SSO or authorization scenarios. Let me know.

Wednesday, July 1, 2009

OpenId SSO for WebLogic Server

With the launch of 11gR, there is a new way to share code samples within the Oracle community. Check out samplecode.oracle.com

To that end, I thought I'd make my community contribution in the form of an
IdentityAsserter that provides SSO to WLS using OpenId

There were a couple of reasons to do this, but the main one was to build a reasonable example of the ServletAuthenticationFilter. WLS uses it internally for the SPNEGO support, and SAML SSO support, but I'd never really had a need from a customer to use it until recently. The need here was OpenId. On the OpenId side, I used the OpenId4Java. If people look at the sample, I'm sure there is a lot more that can be done, and I've only done very cursory testing with the Personal Information Portal at Verisign Labs. Again, this is not exactly my focus, so apologies in advance for any issues there.

So, what is the ServletAuthenticationFilter? Well its really just a special type of IdentityAsserter. It's an IdentityAsserter that adds a Filter to every web application inside of WLS. The filter only gets called when the user is accessing a protected resource, but before regular authentication kicks-in. The key is that this happens before authentication. This allows the filter implementation to go do something, like challenge the user for a different type of credentials other than what WLS supports natively. Also, the ServletAuthenticationFilter has the notion of multi-part challenges, like those that are required to do SPNEGO or OpenId. There is an initial step, and then multiple continue steps, until the challenge is completed. There are a bunch of different interfaces, and it can be a little confusing, but here's my best explanation:

The Filter logic:
1. Is there an existing challenge context - normally stored in the HttpSession.
a. If there is, call continueChallengeIdentity
b. If there isn't, call assertChallengeIdentity
2. Check if the challengeContext.hasChallengeContextCompleted
a. If it has, get the Subject and call ServletAuthentication.runAs(subject,request) - this pushes the subject onto the WLS Stack
b. If it hasn't, get the ChallengeToken. Process the token, and return it to the user.

The Identity Asserter Logic:
1. Build the Basic Identity Asserter First - this is just the plain old IA that sets up a CallbackHandler. This is based on the token type that you're going to extract. In my example, I just extended the SimpleSampleIdentityAsserter, so really my tokens are just usernames.
2. Implementing the ServletAuthenticationFilter interface
a. All that this really does is just instantiate the filter...very simple.
3. Implementinf the ChallengeIdentityAsserterV2 interface
a. The assertChallengeIdentity is going to get called when the filter calls the AppChallengeContext.assertChallengeIdentity, so this is the intial call. In this method, you'll need to instantiate your implementation of the ProviderChallengeContext, and return it.
b. The continueChallengeIdentity method gets called when the filter calls AppChallengeContext.continueChallengeIdentity. This time you get passed the ProviderChallengeContext that you created in the assertChallengeContext.
c. When you finally have a valid user, you need to set the CallbackHandler on the ProviderChallengeContext. This is simple, since you're already inside of an IdentityAsserter. Basically, just call assertIdentity, get the CallbackHandler, mark the ProviderChallengeContext has completed and you're done.

So, by looking at the Filter and IdentityAsserter implementations, we can start to understand what the purposes of some of the other objects in the model. The ProviderChallengeContext is used to hold the start of the challenge. Its typically stored in the user's session, so you can just use instance variables inside of it to hold the state. One more thing about the sessions. The filters are instatiated just like other regular filters, which means that they are scoped to applications - configured globally, but all running inside of the application. The sessions that you get from the HttpServletRequest are tied to that application. If you want to pass information between apps, you'll need to do it on the URL.

The other implication, is that the methods on the IdentityAsserter take a ContextHandler, but the methods of the AppChallengeContext take an AppContext. Basically, under the covers the AppContext is wrapped/converted into a ContextHandler. This probably means that you'll need to build you own implementation of the AppContext to hold your data. This included the HttpServletRequest and HttpServletResponse objects.

That's basically it. The rest of the information is readily available in the product documentation. I encourage people to download and try the sample. As always, comments welcome.