Friday, June 18, 2010

Securing WebLogic WebServices with Oracle Entitlements Server and Oracle Web Services Manager

In a way this post is actuall an update on a few previous posts. The first is an update on the custom assertions for OWSM. I've been making some changes, and now the latest revision - revision 41 - is pretty solid. I've also published the JavaDoc and will continue to add more documentation as time permits. The second is on the OES and OWSM custom assertion from OOW2009. This is really the focus of this post...how to use this assertion to secure the services with OES and OWSM, but its is worth noting that the new version of this assertion, does use the OWSMAC framework. It definately greatly simplifed the development effort. For people who are interested in the new custom assertion, here's a link to the code.

Overview


This solution uses OES 10gR3CP4 protecting a JAX-WS webservice running inside of WLS 10.3.2 (11gR1SP). The domain is a JRF domain, which means that I can use OWSM to protect the web-service. I installed and configured the WLS SM and used the config tool to create a scoped application - scoped in this case means that I'm going to use the entitlementsadministration GUI - apps and orgs. I created in Eclipse the worlds simplest Web Service and deployed it. The webservice is nothing more than a "helloWorld". Once deployed, I could use the WLS admin console to define the policies for web-service.



Notice that I applied two policies...and authentication policy using oracle/wss10_saml_token_service_policy, and then the custom policy owsmac/owsmac_oes_AuthorizationPolicy. NOTE: The oracle/wss10_saml_token_service_policy has no message protection and has to be used in a production environment in conjunction with network or transport security. You'll see why when you look at the sample messages.

Why use OES Custom Assertion for OWSM?


Since the endpoint that we're protecing in a JAX-WS webservice, it is protected by the WLS SM by default. As we discussed previously, the container first checks the access controls policy for the URL and then the WebService. With OWSM in the picture, the sequence is:

  • URL Authorization Check - the resource is type=>url<, application=sample_service, contextPath=/sample_service, uri=/Service1Service, httpMethod=GET. You can do authorization only on the URL of the endpoint. Nothing in the body
  • Call OWSM - calls OES Custom Assertion - we'll discuss more in a second what you can do
  • WebServices Authorization Check - the resource is type=>webservices<, application=sample_service, contextPath=/sample_service, webService=Service1Port, method=hello, signature={java.lang.String}. Notice you have a lot more information like the Port and the operation as well as the signature of the method. Also, if you use attribute retriever in OES, you should be able to access a lot of the relevent appContext elements. The list is pretty expansive.


This means that without doing any custom work, you get two cracks at the request, and with OES in place and the WLS SM, there is quite a bit you can do. So why use the OES OWSM custom assertion? These are the additional use cases I've come up with:

  • You don't want to use OES to secure the WLS resources - when I did this solution last year at OOW, I installed the WLS SM, but also had the DefaultAuthorizer and used the OES Adjudicator to pull the two together. In this case, OES won't get called for URL and Webservices resource types
  • Policy Based access to SOAP:Body and SOAP:Env - If you use OOTB WLS SM to secure web-services, then you have to code a custom attribute retriever to operate on the SOAP Message. This means that if there are changes, then you'll need to re-code. The approach of having the XPath defined in the OES policy allows for changes to be made w/o coding
  • You want to update the message - In the updated version of the OES Custom Assertion, you can write policy that updates the values. What is the use case for this - outbound datamasking at the perimeter. For example, you can't control what the web service is going to return, but you want to make sure that the contents don't expose any PII. You can write a policy that will mask it.
  • You want to do authorization on the response - This is related to the previous point, but it allows you to do one more authorization check based upon the information in the response. This makes sense if the authorization cannot be determined until after invoking the operation. These really only makes sense in read operations, since the authorization failure is happending "presumably" after the transaction has been committed.

If you have any of the use cases above, read on and I'll explain a little more about the policies in OES.

Modelling the Policies for the OES Custom Assertion


The OES custom assertion works with 4 actions - request_lookup, execute_request, response_lookup, and execute_response. They are performed in that order. All of the magic happens in the responses (i.e. report_as function in the constraints). The values of the report_as in the lookup phases are assumed to be XPath queries that should be performed. The resulting values are then sent down in the execute phase. If the user is granted access, any report_as values returned that reference the attributes passed in are assumed to be updates which the OWSM assertion then applies.


For example, the constraint report_as("hello_out","*****") in the execute_response method will replace the value of the hello_out attribute (defined as the XPath in the response_lookup privilege) with ****.

I used the Vordel SOAP Box to test, including the creation of the unsigned SAML assertion required by the oracle/wss10_saml_token_service_policy. Basically, the policies allow any requests except if the hello in message is abc or if the response is Hello abcd - which means that the input of abcd will cause authorization to fail. Otherwise, the response is masked with ****. I also DENY any requests is the authentication method in the SAML assertion is urn:oasis:names:tc:SAML:1.0:am:unspecified. The XPath can be used on either the header of the body of the SOAP message.



I've included below the export from PolicyIX. It shows all of the authorization policies in detail.


Reference: Policy Export For Sample Application



<?xml version="1.0" encoding="UTF-8"?>
<xb:policy_propagation xmlns:xb="http://policypropagation.ales.com/xmlbean">
<xb:policy_propagation_data_v2>
<xb:scopes>
<xb:application_entry value="RootOrg!defaultOrg!sample_service" boundSSM="oes10gR3cp4wlsssm">
<xb:admin_roles>
<xb:admin_role_entry value="AppAdmin" isPrimary="true" description="Primary Application Admin Role of current Application">
<xb:admin_role_privileges>
<xb:admin_role_privilege_entry object="action" action="adminmanage"/>
<xb:admin_role_privilege_entry object="authorizationPolicy" action="adminmanage"/>
<xb:admin_role_privilege_entry object="authorizationPolicyReport" action="adminmanage"/>
<xb:admin_role_privilege_entry object="directory" action="adminview"/>
<xb:admin_role_privilege_entry object="extension" action="adminmanage"/>
<xb:admin_role_privilege_entry object="group" action="adminview"/>
<xb:admin_role_privilege_entry object="policyDistribution" action="adminmanage"/>
<xb:admin_role_privilege_entry object="policySimulator" action="adminmanage"/>
<xb:admin_role_privilege_entry object="resource" action="adminmanage"/>
<xb:admin_role_privilege_entry object="role" action="adminmanage"/>
<xb:admin_role_privilege_entry object="rolePolicy" action="adminmanage"/>
<xb:admin_role_privilege_entry object="rolePolicyReport" action="adminmanage"/>
<xb:admin_role_privilege_entry object="user" action="adminview"/>
</xb:admin_role_privileges>
</xb:admin_role_entry>
</xb:admin_roles>
<xb:resources>
<xb:resource_entry value="//resources/SOAPMessage" isVirtualResoureAllowed="true"/>
<xb:resource_entry value="//resources/SOAPMessage/Service1Service" isVirtualResoureAllowed="true"/>
<xb:resource_entry value="//resources/SOAPMessage/Service1Service/Service1Port" isVirtualResoureAllowed="true"/>
<xb:resource_entry value="//resources/SOAPMessage/Service1Service/Service1Port/hello" isVirtualResoureAllowed="true"/>
<xb:resource_entry value="//resources/url" isVirtualResoureAllowed="true"/>
<xb:resource_entry value="//resources/webservices" isVirtualResoureAllowed="true"/>
</xb:resources>
<xb:actions>
<xb:action_entry value="any"/>
<xb:action_entry value="execute_request"/>
<xb:action_entry value="execute_response"/>
<xb:action_entry value="request_lookup"/>
<xb:action_entry value="response_lookup"/>
</xb:actions>
<xb:dynamic_attributes>
<xb:dynamic_attribute_entry name="auth_method" type="string"/>
<xb:dynamic_attribute_entry name="hello_in" type="string"/>
<xb:dynamic_attribute_entry name="hello_out" type="string"/>
</xb:dynamic_attributes>
<xb:roles>
<xb:role_entry value="Anonymous" parent=""/>
</xb:roles>
<xb:policies>
<xb:membership_rule_entry>
<xb:policy_effect value="grant"/>
<xb:policy_roles>
<xb:policy_role_entry value="Anonymous"/>
</xb:policy_roles>
<xb:policy_resources>
<xb:policy_resource_entry value="//resources/url"/>
</xb:policy_resources>
<xb:policy_subjects>
<xb:policy_group_entry name="allusers" directory="defaultUsers" scope="RootOrg!defaultOrg"/>
</xb:policy_subjects>
</xb:membership_rule_entry>
<xb:authorization_policy_entry>
<xb:policy_effect value="deny"/>
<xb:policy_actions>
<xb:policy_action_entry value="execute_response"/>
</xb:policy_actions>
<xb:policy_resources>
<xb:policy_resource_entry value="//resources/SOAPMessage/Service1Service/Service1Port/hello"/>
</xb:policy_resources>
<xb:policy_subjects>
<xb:policy_group_entry name="allusers" directory="defaultUsers" scope="RootOrg!defaultOrg"/>
</xb:policy_subjects>
<xb:policy_constraint value="sys_defined ( hello_out ) and hello_out = &quot;Hello abcd&quot;"/>
</xb:authorization_policy_entry>
<xb:authorization_policy_entry>
<xb:policy_effect value="deny"/>
<xb:policy_actions>
<xb:policy_action_entry value="execute_request"/>
</xb:policy_actions>
<xb:policy_resources>
<xb:policy_resource_entry value="//resources/SOAPMessage/Service1Service/Service1Port/hello"/>
</xb:policy_resources>
<xb:policy_subjects>
<xb:policy_group_entry name="allusers" directory="defaultUsers" scope="RootOrg!defaultOrg"/>
</xb:policy_subjects>
<xb:policy_constraint value="sys_defined ( hello_in ) and hello_in = &quot;abc&quot;"/>
</xb:authorization_policy_entry>
<xb:authorization_policy_entry>
<xb:policy_effect value="deny"/>
<xb:policy_actions>
<xb:policy_action_entry value="execute_request"/>
</xb:policy_actions>
<xb:policy_resources>
<xb:policy_resource_entry value="//resources/SOAPMessage/Service1Service/Service1Port/hello"/>
</xb:policy_resources>
<xb:policy_subjects>
<xb:policy_group_entry name="allusers" directory="defaultUsers" scope="RootOrg!defaultOrg"/>
</xb:policy_subjects>
<xb:policy_constraint value="sys_defined ( auth_method ) and auth_method = &quot;urn:oasis:names:tc:SAML:1.0:am:unspecified&quot;"/>
</xb:authorization_policy_entry>
<xb:authorization_policy_entry>
<xb:policy_effect value="grant"/>
<xb:policy_actions>
<xb:policy_action_entry value="response_lookup"/>
</xb:policy_actions>
<xb:policy_resources>
<xb:policy_resource_entry value="//resources/SOAPMessage/Service1Service/Service1Port/hello"/>
</xb:policy_resources>
<xb:policy_subjects>
<xb:policy_group_entry name="allusers" directory="defaultUsers" scope="RootOrg!defaultOrg"/>
</xb:policy_subjects>
<xb:policy_constraint value="report_as ( &quot;hello_out&quot; , &quot;body:.//tns:helloResponse/return&quot; )"/>
</xb:authorization_policy_entry>
<xb:authorization_policy_entry>
<xb:policy_effect value="grant"/>
<xb:policy_actions>
<xb:policy_action_entry value="any"/>
</xb:policy_actions>
<xb:policy_resources>
<xb:policy_resource_entry value="//resources/url"/>
</xb:policy_resources>
<xb:policy_subjects>
<xb:policy_group_entry name="allusers" directory="defaultUsers" scope="RootOrg!defaultOrg"/>
</xb:policy_subjects>
</xb:authorization_policy_entry>
<xb:authorization_policy_entry>
<xb:policy_effect value="grant"/>
<xb:policy_actions>
<xb:policy_action_entry value="request_lookup"/>
</xb:policy_actions>
<xb:policy_resources>
<xb:policy_resource_entry value="//resources/SOAPMessage/Service1Service/Service1Port/hello"/>
</xb:policy_resources>
<xb:policy_subjects>
<xb:policy_group_entry name="allusers" directory="defaultUsers" scope="RootOrg!defaultOrg"/>
</xb:policy_subjects>
<xb:policy_constraint value="report_as ( &quot;hello_in&quot; , &quot;body:.//tns:hello/arg0&quot; )"/>
</xb:authorization_policy_entry>
<xb:authorization_policy_entry>
<xb:policy_effect value="grant"/>
<xb:policy_actions>
<xb:policy_action_entry value="request_lookup"/>
</xb:policy_actions>
<xb:policy_resources>
<xb:policy_resource_entry value="//resources/SOAPMessage/Service1Service/Service1Port/hello"/>
</xb:policy_resources>
<xb:policy_subjects>
<xb:policy_group_entry name="allusers" directory="defaultUsers" scope="RootOrg!defaultOrg"/>
</xb:policy_subjects>
<xb:policy_constraint value="report_as ( &quot;auth_method&quot; , &quot;header:.//saml:AuthenticationStatement/@AuthenticationMethod&quot; )"/>
</xb:authorization_policy_entry>
<xb:authorization_policy_entry>
<xb:policy_effect value="grant"/>
<xb:policy_actions>
<xb:policy_action_entry value="execute_request"/>
</xb:policy_actions>
<xb:policy_resources>
<xb:policy_resource_entry value="//resources/SOAPMessage/Service1Service/Service1Port/hello"/>
</xb:policy_resources>
<xb:policy_subjects>
<xb:policy_group_entry name="allusers" directory="defaultUsers" scope="RootOrg!defaultOrg"/>
</xb:policy_subjects>
<xb:policy_constraint value="sys_defined ( hello_in ) and report_as ( &quot;hello_in&quot; , &quot;*****&quot; )"/>
</xb:authorization_policy_entry>
<xb:authorization_policy_entry>
<xb:policy_effect value="grant"/>
<xb:policy_actions>
<xb:policy_action_entry value="execute_response"/>
</xb:policy_actions>
<xb:policy_resources>
<xb:policy_resource_entry value="//resources/SOAPMessage"/>
</xb:policy_resources>
<xb:policy_subjects>
<xb:policy_group_entry name="allusers" directory="defaultUsers" scope="RootOrg!defaultOrg"/>
</xb:policy_subjects>
</xb:authorization_policy_entry>
<xb:authorization_policy_entry>
<xb:policy_effect value="grant"/>
<xb:policy_actions>
<xb:policy_action_entry value="any"/>
</xb:policy_actions>
<xb:policy_resources>
<xb:policy_resource_entry value="//resources/webservices"/>
</xb:policy_resources>
<xb:policy_subjects>
<xb:policy_group_entry name="allusers" directory="defaultUsers" scope="RootOrg!defaultOrg"/>
</xb:policy_subjects>
</xb:authorization_policy_entry>
</xb:policies>
</xb:application_entry>
</xb:scopes>
<xb:security_configuration_data>
<xb:scms>
<xb:scm_entry name="adminconfig">
<xb:ssms>
<xb:ssm_entry name="asiadmin"/>
<xb:ssm_entry name="oes10gR3cp4wlsssm"/>
</xb:ssms>
</xb:scm_entry>
</xb:scms>
</xb:security_configuration_data>
</xb:policy_propagation_data_v2>
</xb:policy_propagation>

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.