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.

18 comments:

  1. Interesting article. I've included kernel-impl.jar in the classpath, but I can't find sb-security.jar. Where can I find this file?

    ReplyDelete
  2. On WLS/OSB 10.3 I have it under the wls binary directory osb_10.3/lib/sb-security.jar. I couldn't see this jar file in version 11g but I found the following under the osb directory:
    ./lib/modules/com.bea.alsb.security-offline.jar
    ./lib/modules/com.bea.alsb.security.api.jar
    ./lib/modules/com.bea.alsb.security-wls.jar
    ./lib/modules/com.bea.alsb.security.impl.jar

    I'm guessing the jar: ./lib/modules/com.bea.alsb.security.api.jar is probably what you're interested in. Let me know how you get on.

    ReplyDelete
  3. I believe I have all the necessary jars now. The following statement serviceSecurityConfigurationMBean = findService(String("ServiceSecurityConfiguration.").concat(sessionName), "com.bea.wli.sb.security.management.configuration.ServiceSecurityConfigurationMBean") returns None regardless of which tree i'm in.

    Which tree are you creating the MBean in? Do you mind sharing you src code?

    Thanks

    ReplyDelete
    Replies
    1. I have the same problem. Did you discovered the solution for this ?

      Delete
  4. How have you created a WLS session? I've got the following code:

    sessionMBean = findService(SessionManagementMBean.NAME, SessionManagementMBean.TYPE)
    sessionName = String("SessionImportScript-" + Long(System.currentTimeMillis()).toString())
    sessionMBean.createSession(sessionName)

    This might correspond to the correct MBean.

    I realized that I stated it was for 11g but I've actually only tried it on 10g. We're in the process of migrating to 11g at the moment so I'll have to come back to this in the near future as part of this migration.

    ReplyDelete
  5. Yes I create the session first.

    ReplyDelete
  6. I have a question... I need to add policy conditions (add a specific user) to a proxy service via WLST.. this works for that?

    thanks!

    ReplyDelete
  7. Yep, it uses the XACML format, so instead of using 'Grp(Administrators)' you would use 'Usr(JoeBloggs)'. E.g. from above:
    applyWSSecurityPolicy(serviceSecurityConfigurationMBean, xacmlAuthorizer, ref, "Usr(JoeBloggs)", "deleteAllUsers")

    ReplyDelete
  8. Thakns for answer me, but i having an error with this line:

    policyHolder = serviceSecurityConfigurationMBean.newAccessControlPolicyHolderInstance(authorizer)

    is throwing this exception : newAccessControlPolicyHolderInstance(): 1st arg can't be coerced to weblogic.management.security.authorization.PolicyEditorMBean

    seems like the parameter is expected is of a different type

    have any idea?

    regards! and thanks again

    ReplyDelete
  9. I think i solve it by passing by parameter a authorization provider and not a authentication provider

    atnr=cmo.getSecurityConfiguration().getDefaultRealm().lookupAuthorizer('XACMLAuthorizer')

    thanksss

    ReplyDelete
  10. OK we're in the process of shifting to OSB 11g and it appears Oracle have refactored the code so that some of the internal MBeans can't be accessed so easily (booo). You can still grab the MBean with:
    custom()
    securityMBean = cd("com.bea:Name=ServiceSecurityConfiguration.test,Type=com.bea.wli.sb.security.management.configuration.ServiceSecurityConfigurationMBean")

    But it's a bit more of a pain to play with operations. Will make an update and keep you posted.

    ReplyDelete
  11. Yes but im working with 10g,i have a new problem in my application when im creating a new policy scope (policyScope = serviceSecurityConfigurationMBean.newTransportPolicyScope(ref)) , that line of code. it's deleting users previously configured in the proxy service, is no way to get the current users configured in a proxy service to add users without deleting any user added previously ??

    ReplyDelete
  12. Hi Julian,

    I had done an all-or-nothing approach to this. My recommendation would be to change the line:
    policyHolder.setPolicyExpression(policy)
    to something like:
    policyHolder.setPolicyExpression(policy + policyHolder.getPolicyExpression())
    Although I'm not sure exactly what the concatenation of two policy strings would look like.

    ReplyDelete
  13. Thanks a lot for answer David, i tried to concat two expression but didn't work... when i activate the osb session i have the following error "[OSB Security:386801]An error ocurred while activating access control changes for proxy "null"." its to be seem is no possible concat two expressions.. anyway is deleting previously users too because is still creating a new policy scope for the proxy service... there is no way to obtain the users configured in the policy scope ??, i tried to find the reference for the MBean ServiceSecurityConfigurationMBean but i cant find it!

    thanks again

    regardss

    ReplyDelete
  14. Hi David,

    Any progress on the 11g migration of your code? I have started working on this today and would be eager to see where you are at with this. THanks.

    regards,

    Johnny

    ReplyDelete
  15. Hey guys,

    See the update above. Hope it helps. I couldn't figure out how to grab the MBean without going to the custom tree. If you have any ideas please let me know.

    Thanks,
    David

    ReplyDelete
  16. I try to implement the solution but with an exception. Any idee (ALSB (OSB) 10.3) ???


    exception below

    # we got the following exception
    # Unexpected error: com.bea.wli.config.session.SessionConflictException
    # No stack trace available.
    # Problem invoking WLST - Traceback (innermost last):
    # File "E:\PROJETS\RECURANT\EDF\linky\WLST\WORKING\Security\lib\security.py", line 246, in ?
    # File "E:\PROJETS\RECURANT\EDF\linky\WLST\WORKING\Security\lib\security.py", line 105, in accessControlSecurity1
    # com.bea.wli.config.session.SessionConflictException: Conflicts for session SessionScript1363339726764
    # ----------------------------------------------
    # [Non-Critical] Concurrent Modification Conflicts
    # NONE
    # [Critical] Resources with validation errors
    # 1 - ProxyService test/PS_TEST_bis CannotCommit
    # + CannotCommit [OSB Security:386836]Unnecessary proxy wide message access control policy found for service "test/PS_TEST_bis". Hint: The service is neither an active security
    # intermediary nor has custom authentication enabled. ServiceDiagnosticLocation[SECURITY_TAB]:DiagnosticLocation:
    #
    #
    # Usr(USER_A,USER_B,USER_C)
    #
    #
    #
    #
    # [Info] Informational messages
    # NONE
    #
    # at com.bea.wli.config.session.SessionManager.commitSessionUnlocked(SessionManager.java:358)
    # at com.bea.wli.config.session.SessionManager.commitSession(SessionManager.java:339)
    # at com.bea.wli.config.session.SessionManager.commitSession(SessionManager.java:297)
    # at com.bea.wli.config.session.SessionManager.commitSession(SessionManager.java:306)

    ReplyDelete
  17. start code :

    # connection
    print "\n\n\n***********************************************************************************************"
    connect( 'weblogic', 'weblogic', 't3://localhost:7001')
    domainRuntime()

    # create a session
    sessionName = String("SessionScript"+Long(System.currentTimeMillis()).toString())
    SessionMBean = findService( SessionManagementMBean.NAME ,SessionManagementMBean.TYPE)
    SessionMBean.createSession(sessionName)

    # get the ServiceSecurityConfigurationMBean
    serviceSecurityConfigurationMBean = findService(String("ServiceSecurityConfiguration.").concat(sessionName), "com.bea.wli.sb.security.management.configuration.ServiceSecurityConfigurationMBean")

    # get the XACMLAuthorizer
    working_directory=pwd()
    serverConfig()
    xacmlAuthorizer = cd('/SecurityConfiguration/%s/Realms/myrealm/Authorizers/XACMLAuthorizer' % domain_name )
    cd(working_directory)
    domainRuntime()

    # get service ref
    ConfigurationMBean = findService(String("ALSBConfiguration.").concat(sessionName), "com.bea.wli.sb.management.configuration.ALSBConfigurationMBean")
    bsQuery = ProxyServiceQuery()
    bsQuery.setPath("default/*")
    refs = ConfigurationMBean.getRefs(bsQuery)

    for ref in refs:

    print 'ref=%s'%ref

    # use the security Mbean to add : USER_A,USER_B,USER_C to the policy
    policyHolder = serviceSecurityConfigurationMBean.newAccessControlPolicyHolderInstance(xacmlAuthorizer)
    policyHolder.setPolicyExpression("Usr(USER_A,USER_B,USER_C)")
    policyScope = serviceSecurityConfigurationMBean.newDefaultMessagePolicyScope(ref)
    serviceSecurityConfigurationMBean.setAccessControlPolicy(policyScope,policyHolder)

    # print the service definition
    servConfMBean = findService( "%s.%s" % (ServiceConfigurationMBean.NAME, sessionName), ServiceConfigurationMBean.TYPE)
    serviceDefinition = servConfMBean.getServiceDefinition(ref)
    print serviceDefinition

    ReplyDelete