Wednesday 28 March 2012

Oracle Service Bus - Using WLST to secure proxy services

UPDATE: 11g users please see the end of this post!

 One of the requirements for automating deployment of all resources related to Oracle Service Bus 11g was to set group security policy for public facing proxy services. This would involve WLST/MBeans but the default deployment process makes setting security policy impossible. After some 'research' I determined that it was possible with the inclusion of some undocumented apis. In the servicebus implementation there is a Security Configuration MBean which one might 'guess' is used internally to manage access controls to proxy services. For some reason BEA/Oracle does not want us using this... but we have other ideas. When starting WLST make sure to include sb-kernel-impl.jar in the classpath as this holds the Security Configuration MBean. You will also need sb-security.jar. Once you've created an OSB session you can grab the the relevant MBean with the following code:
serviceSecurityConfigurationMBean = findService(String("ServiceSecurityConfiguration.").concat(sessionName), "com.bea.wli.sb.security.management.configuration.ServiceSecurityConfigurationMBean")
You also need to grab the authorizer you want to use. The following code can grab this for you in a variable (I'm guessing there is a more elegant solution to getting the MBean...):
working_directory = pwd()
serverConfig()
xacmlAuthorizer = cd("/SecurityConfiguration/DevelopmentDomain/Realms/myrealm/AuthenticationProviders/DefaultAuthenticator")
cd(working_directory)
The following method will set the provided proxyReference with the policy either for the Web-Service as a whole or a particular operation:
def applyWSSecurityPolicy(serviceSecurityConfigurationMBean, authorizer, proxyReference, policy, operation = None):
 policyHolder = serviceSecurityConfigurationMBean.newAccessControlPolicyHolderInstance(authorizer)
 policyHolder.setPolicyExpression(policy)
 
 if (not operation):
  policyScope = serviceSecurityConfigurationMBean.newDefaultMessagePolicyScope(proxyReference)  
 else:
  policyScope = serviceSecurityConfigurationMBean.newOperationMessagePolicyScope(proxyReference,operation)
    
 serviceSecurityConfigurationMBean.setAccessControlPolicy(policyScope,policyHolder)
An example:
applyWSSecurityPolicy(serviceSecurityConfigurationMBean, xacmlAuthorizer, ref, "Grp(Administrators)", "deleteAllUsers")
And the following method will do the same at the transport level:
def applyTransportSecurityPolicy(serviceSecurityConfigurationMBean, authorizer, proxyReference, policy):
 policyHolder = serviceSecurityConfigurationMBean.newAccessControlPolicyHolderInstance(authorizer)
 policyHolder.setPolicyExpression(policy)
 
 policyScope = serviceSecurityConfigurationMBean.newTransportPolicyScope(proxyReference)
 
 serviceSecurityConfigurationMBean.setAccessControlPolicy(policyScope,policyHolder)
An example:
applyTransportSecurityPolicy(serviceSecurityConfigurationMBean, xacmlAuthorizer, ref, "Grp(Administrators)")
Remember to activate the session when you're done using the sessionMBean.acxtivateSession method. 

UPDATE: I've just started our migration to 11g and fixed the issue. For some reason Oracle made the ServiceSecurityConfigurationMBean very difficult to find. You can 'obtain' it again with the following WLST:
from java.lang.reflect import Proxy
custom()
cd("com/bea")
security_mbean_ih = MBeanServerInvocationHandler(mbs,ObjectName("com.bea:Name=%s.%s,Type=%s" % (ServiceSecurityConfigurationMBean.NAME,session_name,ServiceSecurityConfigurationMBean.TYPE)))
serviceSecurityConfigurationMBean = Proxy.newProxyInstance(ServiceSecurityConfigurationMBean.getClassLoader(),jarray.array([ServiceSecurityConfigurationMBean],java.lang.Class),security_mbean_ih)  
You can then use serviceSecurityConfigurationMBean as normal.