Wednesday, July 17, 2013
OIM 11g R2 Delegated Administration Model - Sample implementation (Part I)
Tuesday, April 17, 2012
Retrieving and Setting HTTP Headers in BPEL
From a security/IDM perspective, I think this feature opens up the ability to create some interesting solutions whereby identity information is added to HTTP headers by OAM (or other SSO products) in the web tier and consumed by services in the app tier. It also makes it possible to pass identity data between services in HTTP headers and thereby ignore having to modify web service requests themselves.
I’ll only add as a warning to remember that end users have the capability to add whatever HTTP headers they want to the requests they make. So, solutions should be developed with this in mind. In particular, if you are going to create a solution that depends on BPEL consuming an HTTP header created by an OAM response, you need to take steps to either ensure that this header really came from OAM (by signing or encrypting it) or take steps to ensure that all requests to BPEL really did originate by coming through the web tier with OAM.
Monday, November 21, 2011
More on Oracle Secure Token Services (OSTS)
I wanted to follow this up by letting everyone know about a good case study on the OSTS written by Oracle's partner the PathMaker Group. The study is based on a deployement of the OSTS that they did with a customer a couple months ago.
http://www.oracle.com/us/products/middleware/identity-management/sts-wireless-telco-provider-525434.pdf
Thursday, November 17, 2011
OIM 11g OID (LDAP) Groups Request-Based Provisioning with custom approval – Part II
This is Part Two of the article describing a potential implementation of Request Based LDAP Group Membership provisioning. Part One can be accessed here.
Continuing with the implementation after disabling the default approval policies at the Request and Operation Levels, the next step is to configure OIM to enable the modification of a provisioned resource via a request. The datasets associated to the Create and Modify operations of the resource in questions (OID User in this case) have to be imported into MDS. The connector’s installer at the present time doesn’t do the import of the metadata files to enable request based operations for the connector; this has to be done after installation by running the corresponding MDS utilities available in OIM.
Importing Connector’s Data Sets into MDS
The files containing the definition of the data collected by the Provisioning operations are called data sets. For OID User, there are two DataSet XML files:
- ModifyResourceOID User.xml
- ProvisionResourceOID User.xml
The one that we will need is the ModifyResourceOID User.xml. Here is the data set below:
From this data set this is what we will need for our implementation:
‘OID User Groups’ will be used as the attribute name to construct the RequestBeneficiaryEntityAttribute as shown in the code snippet below:
If you see any required attributes in the data set, you will have to create a value for the RequestBeneficiaryEntityAttribute for that attribute reference in the data set. The OID Server is one of those attributes. Also for the insertion of Child table records here is the specific code fragment for that:
Notice that we have to use the actual Database Table field name which can be retrieved from the Form Definition. See below:
Uploading DataSets into MDS
In this section I describe the process to upload DataSet XML files into MDS for OIM to use in Request Based Provisioning. As most of you know Data Sets determine the Fields collected during the provisioning process and certain attributes of those fields that make them required, pre-populated or only visible to the approvers. We won’t get into the details of the structure of the data sets involved here but at least we will cover a simple procedure for importing them into MDS. MDS is the acronym for Meta Data Store. Many applications part of the Fusion Middleware family rely on MDS to store configuration or Application Metadata.
This implementation works with OID’s data sets so this is the procedure to import them into MDS:
- Create a directory inside
/ / called DataSet/file (i.e in my case the directory is /opt/fmw11g/Oracle_IDM1/DataSet/file where my Middleware Home is /opt/fmw11g and my OIM installation resides under Oracle_IDM1 directory). - Copy all the datasets from the connector’s binaries home into the directory you just created in the previous step.
- Switch to the bin directory inside the server directory under you OIM home directory (i.e. in my case /opt/fmw11g/Oracle_IDM1/server/bin).
- Modify the file weblogic.properties inside the directory mentioned above. Here is mine:

Wls_servername is the name of the managed server as you defined it in the WebLogic Domain.
Application_name is always ‘oim’.
Metadata_from_loc is the path to the directory created in the first step. Specify this path omitting the last directory in the path (‘file’) as shown in the figure. So if you have a directory /opt/fmw11g/Oracle_IDM1/DataSet/file then the path should be specified as /opt/fmw11g/Oracle_IDM1/DataSet.
- Set the OIM_ORACLE_HOME to your OIM installation Home (i.e. in my case this is what I did export OIM_ORACLE_HOME=/opt/fmw11g/Oracle_IDM1).Run the weblogicImportMetadata.bat|sh script. The script will ask the following:
- User name: weblogic (Do not use xelsysadm)
- Password:
- Server URL: t3://myOIMHost
:14000 # Provide the URL to your oim managed server and oim's port. You should get an output similar to the one described below:
Run the script PurgeCache.bat|sh. Before running the script you need to set WL_HOME and JAVA_HOME environment variables with your location of WebLogic Server installation directory and path to a valid Java JDK/JRE directory (i.e. WL_HOME=/opt/fmw11g/wlserver_10.3 and JAVA_HOME=/opt/fmw11g/jdk160_24 coming with my FMW installation). The output should be similar to the following:
In this case the user has to be xelsysadm instead of weblogic.
Configuring the Human Task (Custom Approval Process SOA Composite)
Now it is time to look in detail at the SOA Composite that will serve as an approval process for our entitlements (LDAP Groups). Look at the following set of pictures:
From the Composite.xml design view in JDeveloper, right click on the Green Human Task icon and select Edit.
Select the Participant block and the click the Edit button at the top of the screen. This brings the screen shown below:
Notice the Value Column of the participant selection table. It is a User whose Login ID is retrieved from the payload in this case: /task:task/task:ownerUser. This is populated in the early stages of the composite right after the corresponding approver is retrieved from the Entitlements_Staging Database table for the requested Entitlement identified by the field EntitlementID. This information is retrieved by the Database Adapter Web Service configured to execute a query against the Entitlements_Staging table part of the schema defined in our solution. For information on how to configure the Database Adapter task in a BPEL process, see the documentation for Fusion Middleware – SOA Suite.
Summary
In summary this post describes a potential approach to implement Request Based OID User Group Membership provisioning using a custom approval process.
The concepts shown in this post include:
- A description of OIM API’s to construct and submit requests to modify provisioned resource.
- A demonstration of the process of configuring Custom Approval Processes via Request Templates.
- A description of the OIM configuration required to disable the default Request and Operation level approvals.
- The steps necessary to customize the SOA composite to extract required Entitlement and Associated Approver information and how to set up the Participants of the Human Task used to Approve/Reject requests.
- The steps to import metadata required to enable request based provisioning for OID Resource Objects (Users and Groups).
For further details about configuration of OIM for Provisioning Processes, Process Forms, Access Policies and any details mentioned but not covered in detail in this post please access OIM Fusion Middleware Documentation from the Fusion Middleware 11g documentation.
Thursday, April 21, 2011
Developing Workflows to OIM 11g - the basics
OIM 11g release brought us the powerful world of Oracle BPEL based workflows: from this release on, Oracle BPEL is the workflow engine to be used by OIM in all sorts of requests and their related approval processes. While this integration makes OIM workflows way more powerful and flexible when compared to OIM 9.x, the development process is quite different. The idea for this article is to provide tips for making the development process more straightforward.
First let’s take a look in the main development steps for having a new workflow:
1. Generating basic workflow: OIM provides an utility that can be used to generate a JDeveloper project that contains a basic BPEL Workflow process:
‘ant -f new_project.xml -f new_project.xml’
The ‘new_project.xml’ is located at $OIM_HOME/server/workflows/new-workflow.
You have to provide the application name (which will become the JDeveloper Applciation Name), the project name (which will become the JDeveloper project in the application) and the process name (which needs to be unique across applications and will be the BPEL process name).
The command line will generate a JDeveloper application and you can copy it to wherever your JDeveloper is installed and start working on your customizations.
Monday, February 21, 2011
Non-Standard approaches to SOA Identity Propagation and Authentication
These approaches are non-standard both because they well… don’t utilize the large body of standards that exist for web service security and because they are outside of what would probably be considered best practices by most people in the industry.
Custom Security Headers
It is fairly common to see people develop services that require authentication through a custom security header.
Now, if your service will consume a token that is truly custom, which is to say outside the standard token types defined in the WSS specs, then this is a perfectly reasonable approach. A good example of this would be a service that can consume a web SSO token from Oracle Access Manager.
This approach is especially powerful if your service can consume the custom token plus one or more of the standard tokens. One example would be a service setup to consume the Oracle Access Manager cookie or a standard username token.
However, one mistake you often see people make is to hard code in a required custom security header that is in essence the same as one of the standard WSS authentication methods. Usually, it is a custom security header that just holds a username and password, which makes it equivalent to the WSS username token.
There are several reasons developers take this approach but they mostly center on not understanding the flexibility and value of the security functionality that is already built into the container that is running their service. For example, sometimes developers will say that they need a custom token since the container will only compare the username in username token to the UID attribute in the directory, which is simply not the case.
Even if custom handling of authentication is required, it is still better to utilize a standard token (with custom handling) over a custom token.
Another mistake you see people make is once they decide they need a custom token, they will just turn off security at the container level and process the token inside of their service. It is far better for custom authentication code to live inside of the container than in the service itself. Staying with the container for security will:
- Allow you to easily use your custom token with other services
- Allow you to switch to a standard authentication method down the road
- Keep you compatible with authorization and auditing done at the container level which you may want to keep even if you need to do custom authentication.
- Use of standard authentication tokens that are processed by the container’s out-of-the-box functionality.
- Use of standard authentication tokens that are processed by custom code in the container.
- Use of custom authentication tokens/headers that are processed by custom code in the container.
- Use of custom authentication tokens/headers that are processed by code in the service itself.
The second approach I’d like to discuss is specific to propagating an identity from a web app or service to a “downstream” service. The approach is simply to stick the user identity into the body of the request and consume it with custom code in the service. Now obviously, this approach is inherently insecure on its own, but it is an appropriate option in situations where the client of the service can be trusted. Usually this trust will be justified by the security that is present at the transport or network level.
Sticking a user identity into the body of the request is really analogous to use of the SAML bearer confirmation method which I discussed in my first post on this blog.
So, it is probably most useful to think of its appropriateness in the same terms. In the blog post on the bearer confirmation method I discussed some advantages that it had over just sticking the user identity into the request body. Now, I’d like to turn the table and look at some possible advantages putting the identity in the request body sometimes has over SAML with bearer and over creating a custom security header of a similar ilk.
Now, you are probably saying to yourself: Hold on Brian, you just laid out a hierarchy with using standards and container functionality at the top and custom approaches executed in the service code at the bottom.
Well that is true, but there is a reason that putting the identity in the request body and extracting it in the service should sometimes be considered. The main problem with SAML with the bearer confirmation method is a lack of support for it. This lack of support applies not only to server side WSS stacks but, perhaps even more importantly client side stacks. If you are creating a service that may be widely consumed and are operating in a very heterogeneous environment where client side developers maybe be using any number of different software packages for their development, then SAML with bearer may be the wrong choice for you. Likewise, it may be harder for consumers of your service to create a custom security header than to just stick the identity in the request body. Along similar lines, it may be easier to convey the format you want to use for the user identity in the WSDL if the identity is being put in the body.
The final consideration for whether propagating the identity in the request body is a good way to go centers on how many services you might have where such trusted identity propagation is deemed as acceptable. If you have a huge SOA infrastructure with tons of applications consuming tons of internal services then it probably makes sense to standardize on bearer or develop a custom security header and corresponding container plug-in to consume the header.
However, if you only have one service that fits this description and SAML with bearer isn’t supported by your stack, then it may be hard to justify the added effort of developing a custom token. In that case, just sticking the user identity in the request body may be the best way to go.
Monday, June 14, 2010
Oracle Service Bus, SOA Suite Human Workflow Web Services and SAML
A customer recently was looking for some guidance on how to apply SAML and OSB to SOA Suite Human Workflow Web Services. I'd never looked at those particular web-services, but applying SAML to OSB and SOA Suite in 11g is pretty straightforward - OWSM...right? Well...this really depends on the requirements and which particular services are being used. In this post, I'll explain a little bit about the identity propagation options for the Human Workflow Web Services, and layout two different approaches to deploying OSB and SAML to protect them.
Identity Propagation Options for Human Workflow Web Services
The customer that I'm working with was particularly interested in the TaskService and TaskQueryServices. After looking at the documentation, I started by pulling down the WSDL. Most of the WSDL and dependent schemas are XML representations of the Workflow Services, but there is one part that caught my attention:
<service name="TaskQueryService">
<port name="TaskQueryServicePortSAML" binding="tns:TaskQueryServiceSOAPBinding">
<soap:address location="http://192.168.56.102:18001/integration/services/TaskQueryService/TaskQueryService2/*"/>
</port>
<port name="TaskQueryServicePort" binding="tns:TaskQueryServiceSOAPBinding">
<soap:address location="http://192.168.56.102:18001/integration/services/TaskQueryService/TaskQueryService"/>
</port>
</service>
The service has two ports - TaskQueryServicePort and TaskQueryServicePortSAML. They both have the same binding, so they support the same messages, just two different ports. Digging a little deeper, I took a look at the WSDL on the SAML Port by going to http://192.168.56.102:18001/integration/services/TaskQueryService/TaskQueryService2?ORAWSDL and look what I found....OWSM policy!
<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:oralgp="http://schemas.oracle.com/ws/2006/01/loggingpolicy" xmlns="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="wss10_saml_token_service_policy" xmlns:orawsp="http://schemas.oracle.com/ws/2006/01/policy" orawsp:displayName="Wss10 SAML Token Service Policy" xmlns:orasp="http://schemas.oracle.com/ws/2006/01/securitypolicy" orawsp:description="This policy authenticates users using credentials provided in SAML tokens in the WS-Security SOAP header. The credentials in the SAML token are authenticated against a SAML login module. This policy can be applied to any SOAP-based endpoint. " orawsp:attachTo="binding.server" Name="oracle/wss10_saml_token_service_policy" orawsp:category="security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" orawsp:local-optimization="check-identity">
<orasp:wss10-saml-token orawsp:Silent="false" orawsp:name="WSSecurity SAML Token" orawsp:Enforced="true" orawsp:category="security/authentication">
<orasp:saml-token orasp:is-encrypted="false" orasp:is-signed="false" orasp:confirmation-type="sender-vouches" orasp:version="1.1"/>
</orasp:wss10-saml-token>
</wsp:Policy>
People know, that I'm not really a WS-Policy purist of really even much of a fan, so I really like the ?ORAWSDL "trick" to help figure our which OWSM policy is being applied. From looking at the ORAWSDL, we've learned that the SAML end-point is protected by the oracle/wss10_saml_token_service_policy. This is a simple WS-Security SAML 1.0 Sender Vouches policy. Putting OSB 11gR1 in front of this service should be a pretty simple application of the OWSM/OSB integration. This is the one of the two approaches I'll explain in a little bit.
If there are two ports, and the 2nd port supports SAML for identity propagation, what does the 1st port use? The answer is a proprietary token. Before everyone goes BOOOOOOO, if you look at the services that are exposed through this end-point, they are synchronous, single-party, RPC style services. If all the requests are made over SSL, then there is no real advantage or requirement for message level security. I suspect, that this proprietary token was at some point an HTTP Cookie, and was probably just passed around in the HTTP transport header...also a well established (read: WebSSO) practice. I was at a different customer a few weeks back and we came to a very similar recommendation to use a transport token instead of message level security and SAML. Every environment is different, but this other way of doing identity propagation is reasonable for this situation. The token itself has been SOAP-a-sized (made SOAP friendly?) by being passed in a com:workflowContext element in all of the messages. Here's a sample:

This is an example of the authenticate call that returns the token for a user authenticated by their username and password. The really interesting part is what's commented out in the com:credential element - onBehalfOfUser. That's right - the proprietary token has impersonation built it. This actually goes beyond what is available in the SAML based identity propagation. The second solution will show how to use SAML with the proprietary token including the onBehalfOf functionality.
Solution 1 - OSB proxy calling Human Workflow Web Service as Business Service using SAML
Once you figure out what's going on with the Human Workflow Web Services, fronting it with OSB 11g and OWSM is pretty straight forward. The basic idea is that you're going to create a business service from the SAML Port, and then configure OSB to use OWSM when calling the business service. One of the nice things about OWSM is that picking the corresponding client policy for a service policy is pretty straight forward.

The only thing you really need to consider is are you going to set-up OSB as an active intermediary or as a pass-through. In either case, you create a proxy-service based on the business service, and configure the OWSM policy oracle/wss10_saml_token_service_policy. This policy uses a SAML Sender-Vouches, but there is no message protection. This means that the message itself is not signed. Notice, looking back at the policy, the assertion itself isn't signed or encrypted either, so we'll need to do something at the transport/network level to ensure that the request is authentic. If there is a trusted network between OSB and SOA suite, then you may not need anything else. You can use WebLogic's Connection Filters as an additional software firewall. If this is not sufficient, then you can set-up 2-way SSL between OSB and SOA Suite to ensure that the request is valid. OSB still uses Service Key Providers to determine the Certificate to use for making 2-way SSL calls, even if OWSM message level policies are applied. Why not just change the policy protecting the services to require that the message or assertion is signed? These end-points are not proper JAX-WS Web Services running in WebLogic Server...there are just servlets, so there is no simply way to change the policies. I think the best approach here is to use 2-way SSL.
Solution 2 - OSB Proxy calling Human Workflow Web Service using Proprietary Token
But Josh, I thought this was doing to be about using SAML? It is. OSB can still expose an endpoint protected by a SAML policy, but the call to Human Workflow Web Service is going to be done using the existing token identity propagation mechanism. The trick is that the proxy pipeline is going to make a Java callout to get the token and add it into the message. The key to the whole solution is the getWorkflowContextForAuthenticatedUser method. This call will return the token for the user. But what if OSB and SOA Suite are running on two separate domains? So this is a remote call, but the OSB and SOA suite domains have to be trusted. The simplest is to just set-up Global Trust. This means that the two domains will trust eachother's signed Principals. There are a few more subtle points that can best be explained by showing the Java callout code and the pipeline.
First, let's look at the pipeline. Conceptually, we have to make the Java callout, get the token, and then add the token to the request in the com:token element of the message. It's pretty simple, and there are far betten XPath people than I, but this is how I did it.
- Assign $body//com:onBehalfOfUser/text() to a variable - we'll talk more about this in a second.
- Make the Java Callout. The most important point is that the call requires a Service Account of type passthrough. This makes sure that the caller's identity is passed down so we know who the user that we're requesting a token for. We're passing in the onBehalfOfUser from above as a parameter. This method returns the token as a String.
- Assign $body/child::node() to the variable operationName. This is the child node of the body...which is the operation request. The com:workflowContext needs to be added to the first child of this element.
- Insert the following as the first child of operationNode
<com:workflowContext>
<com:credential>
<com:identityContext>jazn.com</com:identityContext>
</com:credential>
<com:token/>
<com:locale>en_US</com:locale>
<com:timeZone>US/Eastern</com:timeZone>
</com:workflowContext> - Replace ./com:workflowContext/com:token in operationNode with $token - the value returned from the Java callout
- Replace child::node() in $body with opertaionNode
This is the complete pipeline:
Now the Java callout. The code itself is actually pretty simple, but there was some tricky stuff with classloading. I started off trying to load the Client Jar Files into OSB directly, but was getting some very wierd ClassNotFoundExceptions with weblogic.jndi.WLInitialContextFactory. I decided after some fiddling that I was just going to load the bpm-services.jar
from the system classpath. This means modifying the setDomainEnv.sh to add the jar at start-up. This works really well, except that since the jar contains EJBs, they workflow services don't get deployed on the server. This is fine since for this customer OSB and SOA Suite are two separate domains. I'm sure there is a different way to fix the classloading but I was under a deadline, so this is the best for now.
Now that we have the set-up out of the way, this is the code for the callout
public static String getToken(final String runAsUser) throws Exception {
System.out.println("RunAsUser="+runAsUser);
Subject theUser = weblogic.security.Security.getCurrentSubject();
System.out.println("The User IS="+theUser);
if (theUser==null || theUser.toString().trim().equals("Subject:")) {
System.out.println("No user....");
return "";
} else {
System.out.println("'"+theUser.toString().trim()+"'");
}
System.out.println("Calling to get token for "+theUser+" from t3://localhost:8001");
Object token = weblogic.security.Security.runAs(theUser, new PrivilegedAction() {
@Override
public String run() {
try {
Class clientFactoryClass = ClassLoader.getSystemClassLoader().loadClass("oracle.bpel.services.workflow.client.WorkflowServiceClientFactory");
Method factoryMethod = clientFactoryClass.getMethod("getWorkflowServiceClient", new Class [] {String.class, oracle.bpel.services.workflow.client.config.WorkflowServicesClientConfigurationType.class, Logger.class});
WorkflowServicesClientConfigurationType wscct =
new WorkflowServicesClientConfigurationType();
Listservers = wscct.getServer();
ServerType server = new ServerType();
server.setDefault(true);
server.setName("default");
servers.add(server);
RemoteClientType rct = new RemoteClientType();
rct.setServerURL("t3://localhost:18001");
rct.setInitialContextFactory("weblogic.jndi.WLInitialContextFactory");
rct.setParticipateInClientTransaction(false);
server.setRemoteClient(rct);
IWorkflowServiceClient client =
(IWorkflowServiceClient)factoryMethod.invoke(clientFactoryClass, new Object[] { WorkflowServiceClientFactory.REMOTE_CLIENT, wscct, null});
ITaskQueryService tqs = client.getTaskQueryService();
IWorkflowContext wfContext = tqs.getWorkflowContextForAuthenticatedUser();
if (runAsUser==null) {
return wfContext.getToken();
} else {
IWorkflowContext onBehalfOfCtx = tqs.authenticateOnBehalfOf(wfContext, runAsUser);
return onBehalfOfCtx.getToken();
}
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
});
System.out.println("The token is "+token);
return (String)token;
}
The code itself is really pretty simple. You do need to pull the Subject using the always handy weblogic.security.Security.getCurrentSubject() call, and then invoke the PriviledgedAction. This is required so that when the client running inside of OSB makes the call to SOA Suite, the user's identity is passed, and a token for that user is returned. Again, you have to make sure that you've configured the Java callout with the passthrough service account. Finally, we check if a runAsUser (onBehaldOfUser) is passed, and if it is then instead of returning the token based upon the user's identity in SAML, you get a token onBehalf of the passed in user. In my testing, using the OOTB SAML capabilities, the information in the com:workflowContext was not processed, including the onBehalfOfUser information, so without a username and password, I think using the token based approach is the only way to leverage this functionality with SAML.
Summary
In laying out the two approaches, the simpler OOTB approach will work if you don't need the onBehalfOfUser functionality and you can secure the link between OSB and SOA Suite either at the network or transport level using 2-way SSL. The more complicated approach has the restriction of SOA Suite and OSB being in separate domains, but does have the advantage of supporting onBehalfOf. I would also make sure that for this approacj, there is transport or network security between the OSB and SOA suite since the token (though encrypted) could be replayed. There could be performace issues with the constant creation of the com:workflowContext objects, so its not hard to imagine that the Java callout is extended to use Coherence for caching of Subjects to tokens.
All and all a very good first "real test" for my new "huggable server" - multiple SOA and OSB domains + IDE + Browser without breaking a sweat. I can't but help feel that this solution can be improved, or somehow simplified. Is all of the complexity of the custom approach warranted? What do you think?
References
Edward Biedmond's Blog
Friday, May 14, 2010
Dynamic OWSM Policy and Policy Overrides for WLS, OSB and SOA Suite
I've been spending a lot of time lately working on OSB and OWSM. As people probably know, 11gR1 OSB is released, and you can now use OWSM to secure both proxy and business services.. You have been able for a while to use OWSM for WLS JAX-WS services and of course you can use it to secure SOA Suite composites and BPEL processes. I really like, and customers really like, the idea of being able to centrally manage WS-Security policy from one place. I also like the fact that there is now a single web-services stack across all of these products that OOTB interoperates with eachother. If you want to know why this is a real improvement, I refer you to the OSB to WLS + SAML post. Also, OWSM has native WS-Security Kerberos Token profile...and I have gotten it to work very nicely with WCF (a post for another time).
Given all this, I've been sharpening my pencil on how to write custom assertions (policies) in OWSM 11g. As people will recall, I did an OES+OWSM custom assertion at OOW 2009, and to be honest, that was really the last time I looked at it. My recollection from that time, and my recent experience was that it was a little challenging. Writing the custom assertions is very similar to writing the custom SSPI plugins. Its the type of thing that you don't do that often, and when you do, once you can get the build script going and some decent samples, its not too bad. So, my contribution to this effort can be found at https://owsm-11g-custom-assertions.samplecode.oracle.com/wiki/. In addition to the OES+OWSM assertion from last year, I added a new project called OWSMAC - OWSM Annotations Compiler. What I tried to do was look at what was challenging in working with the custom assertions and try to make it really, really simple.
These are a few of things that OWSMAC does:
- Automatically generate policy and assertion XML
- Simplified XPath processing
- Dynamic Reloading - no need to reboot the server after each little change
- Consistent and predictable lifecycle
- Programmatic selection of policy and overrides
I'm putting the cart before the horse here, as I've not really fully documented or "javadoc-ed" the project, but I have been able to solve a pretty interesting use case that a couple of customers have been interested in, so I wanted to share it now. I suggest that people join the project for updates on OWSMAC.
Dynamic Policy Selection
The scenario is that from an intermediary (likely OSB or SOA Suite composite) the request to the business service/reference requires message level security, but the specifics of the actual policy depend on some state - information in the message, or the location (network) of the destination or different targets have different security requirements - some partners want SAML and others want Username and Password. WS-SecurityPolicy once again is not sufficient or particularly helpful. You need to be able to determine the policy dynamically. I've done this through one of the samples in OWSMAC - DynamicClientPolicy
package owsmac.test;
import java.util.Map;
import javax.xml.soap.SOAPMessage;
import oracle.wsm.common.sdk.IContext;
import owsmac.annotations.Assertion;
import owsmac.annotations.AttachTo;
import owsmac.annotations.Category;
import owsmac.annotations.CustomMethod;
import owsmac.annotations.Executor;
import owsmac.annotations.MessageContextPropertyValue;
import owsmac.annotations.PolicyNameValue;
import oracle.wsm.security.util.SecurityConstants.ClientConstants;
import javax.xml.ws.BindingProvider;
import oracle.wsm.common.sdk.ISOAPBindingMessageContext;
import oracle.wsm.policyengine.IExecutionContext;
import owsmac.annotations.DestroyMethod;
import owsmac.annotations.ExecutionContext;
import owsmac.annotations.FaultMethod;
import owsmac.annotations.InitMethod;
import owsmac.annotations.PolicyPropertyValue;
import owsmac.annotations.Property;
@Assertion(displayName = "A dynamic client policy", customType = Assertion.CustomType.policy, category = Category.security, attachTo = AttachTo.binding_client)
@Executor(category = Category.security_authentication)
public class DynamicClientPolicy {
@PolicyNameValue()
public String selectedPolicy;
@PolicyPropertyValue(name="csf-key",policyNameValue="selectedPolicy")
//@MessageContextPropertyValue(name = ClientConstants.WSS_CSF_KEY)
public String csfKey;
@MessageContextPropertyValue(name = "javax.xml.ws.service.endpoint.address")
public String address;
@MessageContextPropertyValue(name = BindingProvider.USERNAME_PROPERTY)
public String samlUsername;
@MessageContextPropertyValue(name = "oracle.wsm.subject.precedence")
public String useSubjectPrecedence;
@Property(value = "localhost:389")
public static String LDAP_SERVER;
public static @ExecutionContext
IExecutionContext eCtx;
@InitMethod
public static void init() {
System.out.println("In Init: "+eCtx.getAllProperties());
System.out.println("In Init: The LDAP Server is "+LDAP_SERVER);
}
@DestroyMethod()
public static void destroy() {
System.out.println("Destroyed Dynamic Client Policy");
}
@FaultMethod()
public boolean onFault(IContext context) throws Exception {
ISOAPBindingMessageContext soapContext = (ISOAPBindingMessageContext)context;
SOAPMessage message = soapContext.getFault();
return true;
}
@CustomMethod(extendsPolicyNameValue="selectedPolicy")
public boolean selectPolicy(IContext context) throws Exception {
this.getPolicyFromContext(context);
return true;
}
/**
* This is where the custom logic goes for selecting the policy
* @param content
*/
private void getPolicyFromContext(IContext context) {
System.out.println("In the getContext.....");
Map<String,Object> properties = context.getAllProperties();
for (String property: properties.keySet()) {
Object value = properties.get(property);
System.out.println(property+"=>"+value);
}
System.out.println("The address is "+this.address);
if (this.address!=null && address.indexOf("UNT")!=-1) {
this.selectedPolicy = "oracle/wss_username_token_client_policy";
this.csfKey = "josh.creds";
} else {
this.selectedPolicy = "oracle/wss_saml_token_bearer_over_ssl_client_policy";
this.samlUsername = "foobar";
this.useSubjectPrecedence = "false";
}
System.out.println("The selected policy is "+this.selectedPolicy+" and user="+this.samlUsername);
}
}
The whole idea of OWSMAC is to allow people to use POJOs to build the assertions and let everything else happen "magically". I'll draw your attention to the selectPolicy method. This method has the @CustomMethod annotation with extendsPolicyNameValue. This basically means call this method, and when your done go invoke the policy stored in the field referenced in extendsPolicyNameValue. So, in this method, you can set the name of the policy and then also set additional policy overrides or programmatic overrides (these being the same as the properties for JAX-WS clients).
In the sample, we're just looking at the address (endpointURI) and then either invoking UNT - specifying the csf-key of the user or calling SAML and specifying the name of the user to include in the SAML assertion. In the SAML case, there is also something interesting going on - we're using 11gR1 PS SAML Identity Switching. Notice in order to this we're basically setting two properties - BindingProvider.USERNAME_PROPERTY and oracle.wsm.subject.precedence. The former is the name of the user (which doesn't have to exist in the user directory) and the latter is a flag that tells OWSM not to use the identity in the subject for the SAML assertion. Now, in order to perform identity switching, you need to grant a permission. The documentation is not particularly clear. The permission you need to grant is oracle.wsm.security.WSIdentityPermission resource=<composite name> assert. In the text box, you enter resource=<appname> not <appname>.
This is the simple composite that illustrates the scenario.
The references are to WLS web-services protected by OWSM service policies.
The policy file that gets generated by OWSMAC is then uploaded into EM to create a custom policy.
And then attach the policy to the references to the SAML and UNT services. You can also attach the same policy in OSB
Summary
In an ideal world, there would be no need to this type of programmatic extension of the core policy model. The standards would be precise and comprehensive and all of the OOTB policies would never need to be changed. But with our experience with SSPI and the WLS core security model, there are always occasions where customer requirements fall into that 20%, so its good to know that there are ways to simply extend the core product functionality. I like the simplicity of OWSM and the binding of configuration and policy is broadly very useful. Invariably there will be scenarios like the one above, where more dynamic behavior is required. My plan going forward it to continue to use the annotations model with the OWSMAC samples to illustrate how to execute these types of scenarios. I'm looking for additional samples to prove out or ideally some help developing and shaping the project, for everyone's benefit. Who's with me?
References
Creating Custom Assertions
Friday, October 16, 2009
JAVA Key Stores for SOA Security
I see too many people building out SOA development and test environments that utilize a single key store for all the components in their environment. Even worse, I see lots of people utilizing the same key and certificate pair for every component in their environment. If your environment is a dev/test environment built on Oracle products, this is likely the ever-popular “orakey” pair.
I believe that it is important to utilize separate keystores and key-certificate pairs for the client, service, and any intermediary components where keys and certificates are required in your development and test environments.
Taking the short cut of having components share keystores and even key-certificate pairs will only burn you down the road as you move forward with the development of your services and applications. Sharing keys and keystores can mask potential issues that will appear when you try to setup real keystores as you approach production. Further, sharing keys and keystores can actually make it more difficult to diagnose and solve certain issues that can occur during the build out and configuration of an environment.
I will now walk you though the simple steps of creating properly configured client “Alice” and service “Bob” keystores using the Oracle CertGen and ImportPrivateKey utilities. Following these steps you can have proper test keystores ready to go in a matter of minutes.
1) Create client (Alice) key-certificate pair signed by the demo CA cert "CertGenCA"
>> java utils.CertGen -certfile AliceCert -keyfile AliceKey -keyfilepass password
2) Create service (Bob) key-certificate pair signed by the demo CA cert "CertGenCA"
>> java utils.CertGen -certfile BobCert -keyfile BobKey -keyfilepass password
3) Create client (Alice) keystore with client key-certificate pair
>> java utils.ImportPrivateKey -certfile AliceCert.der -keyfile AliceKey.der -keyfilepass password -keystore Alice.jks -storepass password -alias alice -keypass password
4) Create service (Bob) keystore with client key-certificate pair
>> java utils.ImportPrivateKey -certfile BobCert.der -keyfile BobKey.der -keyfilepass password -keystore bob.jks -storepass password -alias bob -keypass password
5) Now add the root CA to both stores
>> keytool -importcert -file CertGenCA.der -keystore Alice.jks
>> keytool -importcert -file CertGenCA.der -keystore bob.jks
6) Add bob's public cert to Alice's store. This is needed to configure the recipient alias on the client
>> keytool -importcert -file BobCert.der -alias bob -keystore Alice.jks
7) Use and prosper!
Thursday, October 15, 2009
What is SOA Security?
Part of the success of this blog has been that its pretty much "manifesto-free", so I'll try to stay focused - the often overlooked area of SOA security is design time governance. Most services are not exposed on the public network. The security for the services at runtime is provided by simply being on the intranet, behind the firewall. We've discussed this before around the use of SAML Bearer confirmation method. The bigger issue is how to ensure that people are selecting the right services to use from the UDDI registry, and only those which they (either the developer of the application) is authorized to use. I think the notion of design time SOA security (often called SOA governance) is nicely discussed here, by Bob Rhubart.
There are some things about services and how they are composed and reused in SOA that need to be managed. How much design time governance (i.e. restrictions) obviously varies from environment to environment. I worked with one customer - that I saw again at OOW a few days ago - who pointed me to the the trustcom project. This is a project being looked at by European government agencies, and "frictionless commerce" with SOA. It is pretty dense stuff, but basically consider the concept of creating a virtual organization to go a perform a business (BPEL) process. A BPEL process has roles, so essentially you want to do is select a service provider for each role and then very easily swap providers in and out if for example, the provider is not meeting their SLAs. So when composing this process, you want to make sure that you're always using the "right" provider. So to do this, you need to look them up in the repository of which contains many, many service providers. So, the UDDI registry or repository needs to restrict access to only the members of the Virtual Organization and their services. There are obviously runtime implications to this model as well, but it does illustrate some of the interesting design time decisions around SOA Security (Governance)
Wednesday, October 14, 2009
Update on samplecode.oracle.com
OES SSPI Providers
The thinking is to use this project for WLS SSPI plug-ins that we use that are OES specific. The two I have in mind are:
- OESBPELAuditor - the ability to audit changes to the OES policies are store them in XML, such that a BPEL process could consume the changes
- OESAdjuductor - the previously mentioned adjudicator that makes integrating the OES WLS-SM more straight forward, but only apply OES decisions to OES resources and XACML decisions to WLS resources.
Seems likely that OWSM custom steps and assertions could also make a home in the soa-security sub category. As always, I'm open to suggestions, and I'm sure that this will evolve over time. Most of security is a configuration and administration problem, but there are occasions when some coding is required, and now by using samplecode.oracle.com, there is a vehicle to get this information out.
Tuesday, October 13, 2009
Oracle Service Bus: Pass-Through vs. Active Security
However, the fact is, the security functionality in OSB supports this use case exactly and with minimal effort.
The processing of message level security headers can be handled in two distinct ways in OSB: Pass-Through and Active Intermediary modes.
As an active intermediary, OSB processes the security headers in the SOAP request and enforces security policies on the messages. Additionally, in this mode, OSB can add new security headers (including new authentication tokens) to the request that is forwarded on to the service. I’ll leave further discussion for other posts.
In pass-through mode, OSB leaves the SOAP message untouched and simply routes the request on to its destination service. This means that all security headers in the original request are preserved in the request sent on to the destination service. So if a SAML assertion is sent in the original request through OSB, it will be part of the request being sent on to the service.
Pass-through mode is great when OSB is being inserted into a working infrastructure (maybe for the purpose of SLA management) where the web services already have security in place and no identity transformation is required as requests move from the clients through OSB and on to the services themselves.
Monday, October 12, 2009
OOW Initial Impressions
I forget how BIG Oracle is sometimes. OOW is a massive production, like an invasion of the Moscone center. It took me many minutes inside of the Oracle Demo grounds to find FMW, then IDM, then the people I was looking for to prep for my session tomorrow.
Once inside, some good discussions about a few use cases. I'll put this one out to the blog - in the OES, OWSM integration "Where should the policies for authorization, and specifically the policy defining the XPath of the attributes OES needs for authorization be managed?" For the presentation, I have them in OES policy, but I think there is a reasonable argument for them being defined inside of the OWSM policy. My thinking is that the encryption and signing policy (i.e. what parts of the body should be signed) are managed there...why not something like "Authorization XPath". Its obviously not as flexible....OES can determine on a per use or per role basis which attributes are required, but sometimes simpler is better, and maybe just having XPath defined in OWSM makes more sense. I'm on the fence...push me over.
Lunch with the boss, who even though I've worked for him for many years, I rarely get to see him face-to-face. Sushi across the street from Moscone is always good.
Also, at Hasan Rizvi's keynote, he made mention of a "standards based security platform for all of FMW" which is code for OPSS....solid mention.
Vikas and I finally huddled up and reviewed the demo/presentation for tomorrow. I'm excited, I think it all has come together quite nicely. Hopefully, I'll see some of you there tomorrow afternoon.
Saturday, October 10, 2009
OES OWSM 11g Custom Assertion Finally Done
So, this is an update of the OES-OWSM Custom step that was part of my OOW 2008 presentation. In doing the "migration" to 11g, I think I learned a number of things that I'll share over the coming weeks.
OES Adjudication Provider
I was frustrated by the complexity of securing an 11g SOA domain with OES. It seemed like the biggest issue was writing OES policies for the WLS resources. In both scenarios, I just wanted to call the OES API, and securing the WLS resources was just a consequence of the fact that ASIAuthorizer plugged into the SSPI framework, and that the Adjudicator couldn't tell the difference between OES and WLS resources. Well, for the OOW demo, I created an OES Adjudicator that only enforces the decision from the ASI or XACML authorizer depending on the resource. This greatly simplifies the deployment, because there are no OES policies for WLS resources. It took me a while to build it, but I think ultimately this is a reasonable solution for POC environments. It might be better in a production environment to author some basic policies for WLS resources in the ASI authorizer. My concern is that the overhead of going through two authorizers might not be worth the simplicity.
Authorization based on SAML Attributes
I extended the existing custom step to be able to resolve XPath queries from either the body or the header of the SOAP:Envelope. This opens up the possibility of not just doing authorization based on the content of the SOAP message, but also the headers. SAML Attribute's are part of the SAML Assertion, and that's available in the WS-Security header. This gives a concrete implementation of the attribute based authorization and federated authorization use cases discussed in this post. The implementation uses the SAML capabilities of OWSM 11g. They key capability here is the ability of the OWSM client side policy to generate a SAML Assertion based on the attributes of the user in the WLS LDAP. OWSM made this whole use case really very simple.
Writing an 11g OWSM Custom Assertion
I definitely picked-up some best practices from engineering, especially on how to get an OWSM custom Assertion into a policy that can be deployed to protect at WLS Web Service. In 11g environments, in makes sense to use OWSM to protect but composite web services as well at WLS web services. The reason is that you can get centralized policy management and avoid a lot of interoperability headaches. OWSM 11g and WLS 11g webservices stacks do work well together, but having the same stack for both producer and consumer greatly simplifies the process.
Like I said, there are more details to follow. Many of which I'll discuss/demonstrate at my OOW Session (2nd shameless plug), but all of which I will share on this blog in good time. For those who were awaiting the OES-OWSM 11g custom step and are not California Angels fans, feel free to contact me and I'll see what I can do about getting the step available ASAP. For Angel's fans and other who can wait, I get this information out as quickly as I can.
If anyone wants to meet up at OOW, I'm happy to accommodate, just ping me and let me know. Also, I'll try to post some updates from the conference.
Safe Travels
Wednesday, October 7, 2009
Fat Client and SOA - A case for SAML Sender Vouches and STS
There are a number of questions that drive the solution in a case like this:
- What directory/data source will users be authenticating to? A local source or a remote source?
- Are those same directories/data sources readily available to the consuming services?
In the cases where the directory and the services are in the same security domain, and the directory is "readily available", there is no need for something elaborate. I think using the native authentication of the directory (say LDAP) and then passing the users identity to the services as something simple (HTTP Header or WS-Security UsernameToken (no password)) would probably work. Applications can just take the username (or dn) from the request and callback to the directory to get additional information. One last thing, you need to have some mitigation strategy for avoiding people spoofing DNs (adding a DN that isn't there's to the request). The simplest way to is to do the requests over 2-way SSL. Package the certificate with the application and there you go. BTW, the CSF function of OPSS is a nice approach for this user case - relies on Java Security to ensure that only authorized applications can have access to the credential (password for decrypting the private key).
The harder use case is more of a federated model - example, the user needs to authenticate locally, but the services are in another security domain. In this model, if there is additional information that the services need about the user, they need to be passed in some form. I think that SAML-Sender Vouches works nicely here. So, the application authenticates locally and then gets a SAML Assertion, signed by the issuer. The SAML Assertion could/should contain additional information needed by the service - groups/roles/attributes etc. The SAML Assertion is added to the message and the message is signed.
This is actual a good use case for an STS. Basically, the STS is taking username and password in and returning a SAML Assertion for the service. Think of it as a standards based authentication service, where the standard is WS-Trust. The stand-alone application can just be configured to point to the local STS and the application is done - no need to specify support for LDAP, RDBMS...that's left to the local deployment.
The reality is that you could actually solve the first scenario with SAML/STS it may just be overkill, but starting with this architecture does provide much more flexible business models. For example, some customers of the service want to authenticate locally, while others want to authenticate centrally. Not a problem. Its simply a matter of configuration. In the fully federated case, the centralized service trust the local authentication and can avoid the headache of password management. That issue can be pushed out to local directories - at least that's the vision.








