4 Implementing Advanced Features in Custom Assertions

The Java API Reference for Oracle Web Services Manager specifies packages, interfaces, and methods you use to implement advanced features in custom assertions. This chapter describes how to use the API to implement some common features. This chapter describes the use of APIs, and exception handling. It includes the following sections:

4.1 Inputting Parameters to Custom Assertions

You can input parameters to custom assertions using the following interfaces and methods:

  • IAssertionBindings

  • IConfig

  • IPropertySet

  • getBindings

  • getConfigs

  • getPropertySets

  • getPropertyByName

  • getValue

To input parameters to custom assertions, perform the following steps:

  1. Specify parameters as properties inside your custom assertion. In this example, the orawsp:PropertySet with the name valid_ips defines a group of properties. The orawsp:Property element defines a single property. orawsp:Value defines a list of valid values for the property.

    
    <orawsp:PropertySet orawsp:name="valid_ips">
        <orawsp:Property orawsp:name="valid_ips" orawsp:type="string"
     orawsp:contentType="constant">
         <orawsp:Value>140.87.6.143,10.178.93.107</orawsp:Value>
         </orawsp:Property>
     </orawsp:PropertySet>
    
  2. Access the parameters inside the custom executor for the corresponding policy. For example, the following code in the execute method of custom assertion's executor class accesses the property valid_ips:

    IAssertionBindings bindings =
     ((SimpleAssertion)(this.assertion)).getBindings();
    IConfig config = bindings.getConfigs().get(0);
    IPropertySet propertyset = config.getPropertySets().get(0);   
    String valid_ips = propertyset.getPropertyByName("valid_ips").getValue();
    

4.2 Accessing Oracle WSM Context Properties

Oracle WSM context properties are accessed using the IMessageContext interface.

You access parameters to custom assertions using the following interfaces and methods:

  • IMessageContext

  • getServiceURL

  • getProperty

  • getAllProperty

To access Oracle WSM context properties, perform the following steps:

  1. To access Oracle WSM context properties inside the custom assertion executor, use the IMessageContext interface. For example:

    
    IMessageContext messagecontext = (IMessageContext) context;         
    messagecontext.getServiceURL();
    
  2. To access the value of a specific property inside the custom assertion executor, use the IMessageContext interface. For example:

    messagecontext.getProperty("<property name>");

  3. To access all the properties that are used during execution from inside the custom assertion executor, use the IMessageContext interface. For example:

    msgContextProperties = messagecontext.getAllProperties();

4.3 Accessing Request, Response, and Fault Message Objects

The Oracle WSM custom security assertion has three stages: request, response, and fault.

  • The request stage occurs when a client has made a request and that request is in the process of being delivered to its destination.

  • The response stage occurs after the destination has processed the message and is in the process of returning a response.

  • The fault stage occurs in the event of a fault.

The contextual information (such as stages and messages) is passed using context properties and can be obtained by the IMessageContext interface. The following interfaces and methods are used to access context properties:

  • IMessageContext

  • getStage

  • getRequestMessage

  • getResponseMessage

To access request, response and fault messages, and stages, perform the following:

  1. To access the stage, use the following code within the custom assertion executor:

    IMessageContext.STAGE stage = ((IMessageContext) iContext).getStage();
               if (stage == IMessageContext.STAGE.request) {
                         //handle request
                }
                
                if (stage == IMessageContext.STAGE.response) {
                       //handle response
                }
                
                if (stage == IMessageContext.STAGE.fault) {
                    //handle fault conditions
                }
    
  2. To retrieve the SOAP request message, use the same context oracle.wsm.common.sdk.IMessageContext, as shown in the following example:

    oracle.wsm.common.sdk.SOAPBindingMessageContext soapMsgCtxt=
     (oracle.wsm.common.sdk.SOAPBindingMessageContext) context;
    javax.xml.soap.SOAPMessage soapMessage = soapMsgCtxt.getRequestMessage();
    
  3. To retrieve the SOAP response message, use the same context oracle.wsm.common.sdk.IMessageContext, as shown in the following example:

    oracle.wsm.common.sdk.SOAPBindingMessageContext soapMsgCtxt=
     (oracle.wsm.common.sdk.SOAPBindingMessageContext) context;
    javax.xml.soap.SOAPMessage soapMessage = soapMsgCtxt.getResponseMessage ();
    

4.4 Accessing Parts of a Message Using XPath

You can access parts of a SOAP message using XPath expression inside your custom policy executor.

In the following SOAP message example, the node arg0 has the value john:

         <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
           <S:Header/>
             <S:Body>
               <ns2:echo xmlns:ns2="http://project1/">
                <arg0>john</arg0>
               </ns2:echo>
             </S:Body>
         </S:Envelope>

In XPath, there are seven types of nodes: element, attribute, text, namespace, processing-instruction, comment, and document nodes. XPath uses path expressions to select nodes in an XML document. Table 4-1 describes some examples of XPath expressions.

Table 4-1 Examples of XPath Expressions

Expression Description

/S:Envelope

Selects from the root element S:Envelope.

/S:Envelope/S:Body

Selects all S:Body elements that are children of S:Envelope

//S:Body

Selects all S:Body elements no matter where they are in a document


For example, to access the value of the node arg0, the XPath expression for arg0 in the above SOAP message is defined as:

//xpath expression that will be used to identify the node arg0
     String xpathStr = "/S:Envelope/S:Body/ns2:echo/arg0";
 

Define the namespaces for any namespace referenced by the XPath expression and add them to the namespace context. For example:

     final DefaultNamespaceContext nsContext = new DefaultNamespaceContext();
     nsContext.addEntry("S", "http://schemas.xmlsoap.org/soap/envelope/");
     nsContext.addEntry("ns2", "http://project1/");
              
     XPathFactory xpathFact = XPathFactory.newInstance();
     XPath xpath = xpathFact.newXPath();
     xpath.setNamespaceContext(nsContext);

Retrieve the value of node using the evaluate method. For example:

     //This will return node arg0 from SOAP message, here soapElement is  
// org.w3c.dom.Elemet  representation of SOAP message
     org.w3c.dom.Node inputNode = (Node)xpath.evaluate(xpathStr, soapElement,
 XPathConstants.NODE);

4.5 Accessing Certificates Used by Container for SSL

To retrieve certificates for SSL, perform the following steps:

  1. Retrieve SOAP response message using the same context oracle.wsm.common.sdk.IMessageContext, as shown in the following example:

    oracle.wsm.common.sdk.SOAPBindingMessageContext soapMsgCtxt=
     (oracle.wsm.common.sdk.SOAPBindingMessageContext) context;
                 
    
  2. Use the HttpServletRequest interface to retrieve the servlet request information.

    javax.servlet.http.HttpServletRequest request =
     (javax.servlet.http.HttpServletRequest)
     soapMsgCtxt.getTransportObject(ITransportContext.HTTP_SERVLETREQUEST_OBJ_
    NAME);
    
  3. Access the attributes of an X.509 certificate. For example:

    X509Certificate[] certificates = (X509Certificate[])
     request.getAttribute(oracle.wsm.security.util.SecurityConstants.SSL_PEER_
    CERTIFICATES);
    

Note:

To use the javax.servlet.http.HttpServletRequest interface, the following JAR file must be included in the classpath: modules/javax.servlet_1.0.0.0_2-5.jar.

4.6 Accessing Transport Properties

To access transport objects such as HTTP requests and responses, perform the following:

  1. Retrieve SOAP response message using the same context oracle.wsm.common.sdk.IMessageContext, as shown in the following example:

    oracle.wsm.common.sdk.SOAPBindingMessageContext soapMsgCtxt=
     (oracle.wsm.common.sdk.SOAPBindingMessageContext) context;
    
  2. Use the HttpServletRequest interface to retrieve servlet request information of the HTTP servlets, as shown in the following example:

        //to retrieve http servlet request object
         HttpServletRequest request = (HttpServletRequest) soapMsgCtxt
                .getTransportObject(ITransportContext.HTTP_SERVLETREQUEST_OBJ_
    NAME);
    
  3. Use the HttpServletRequest interface to retrieve servlet response information of the HTTP servlets, as shown in the following example:

        //to retrieve http servlet response object
         HttpServletResponse response = (HttpServletResponse) soapMsgCtxt
               .getTransportObject(ITransportContext.HTTP_SERVLETRESPONSE_OBJ_
    NAME);
    

Note:

To use the javax.servlet.http.HttpServletRequest interface, the following JAR file must be included in the classpath: modules/javax.servlet_1.0.0.0_2-5.jar.

4.7 Accessing CSF Keys

You can use credential store framework (CSF) to manage the credentials securely, and store, retrieve, and maintain credentials.

To configure and use CSF, perform the following steps:

  1. Configure CSF in jps-config.xml.

    For details on configuring credential store using WLST, see "Configuring the Credential Store Using WLST" in Securing WebLogic Web Services for Oracle WebLogic Server.

  2. You can add, update, or retrieve CSF keys from CSF inside your custom assertion executor. Example 4-1 and Example 4-2 provide sample codes that can be used to access CSF keys from credential store.

    Example 4-1 Accessing CSF Keys

       final String mapName = "oracle.wsm.security";
       final csfKey = "user.credentials";
       final oracle.security.jps.service.credstore.PasswordCredential userCreds =
     getCredentialsFromCSF(mapName, csfKey);
     
              if (userCreds != null) {
                    System.out.println("name:"+ userCreds.getName());
                    System.out.println("name:"+ new String(userCreds.getPassword()));
                                      }
        
    

    Example 4-2 getCredentialsFromCSF method

    private static oracle.security.jps.service.credstore.PasswordCredential 
    getCredentialsFromCSF(
            final String mapName, final String csfKey) {
            oracle.security.jps.service.credstore.PasswordCredential
            passwordCredential = null;
            try {
                if (csfKey != null) {
                final oracle.security.jps.service.credstore.CredentialStore credStore
                = getCredStore();
                if (credStore != null) {
                passwordCredential = (oracle.security.jps.service.credstore.PasswordCredential)  java.security.AccessController
                .doPrivileged(new
    java.security.PrivilegedExceptionAction<oracle.security.jps.service.credstore.
    Credential>() { 
                 public
     oracle.security.jps.service.credstore.Credential run() throws Exception {
                  return (credStore .getCredential(mapName, csfKey));
                                }
                            });
                    } else {
                        // failure obtaining csf credentials
                    }
                }
            } catch (final java.security.PrivilegedActionException ex) {
                //handle excpetion
            } catch (final oracle.security.jps.JpsException jpse) {
                //handle excpetion
            }
            return passwordCredential;
        }
     
     
        private static oracle.security.jps.service.credstore.CredentialStore
     getCredStore() throws oracle.security.jps.JpsException {
            oracle.security.jps.service.credstore.CredentialStore csfStore;
            oracle.security.jps.service.credstore.CredentialStore appCsfStore = null;
            oracle.security.jps.service.credstore.CredentialStore systemCsfStore =
     null;
     
            final oracle.security.jps.internal.api.runtime.ServerContextFactory
     factory = (oracle.security.jps.internal.api.runtime.ServerContextFactory)
     oracle.security.jps.JpsContextFactory
                .getContextFactory();
     
            final oracle.security.jps.JpsContext jpsCtxSystemDefault =
     factory.getContext(oracle.security.jps.internal.api.runtime.ServerContextFactory.S
    cope.SYSTEM);
     
            final oracle.security.jps.JpsContext jpsCtxAppDefault = factory
                .getContext(oracle.security.jps.internal.api.runtime.ServerContextFactory.Scope.AP
    PLICATION);
     
            appCsfStore = (jpsCtxAppDefault != null) ? jpsCtxAppDefault
                .getServiceInstance(oracle.security.jps.service.credstore.CredentialStore.class) :
     null;
     
            if (appCsfStore == null) {
                systemCsfStore = jpsCtxSystemDefault
                    .getServiceInstance(oracle.security.jps.service.credstore.CredentialStore.class);
                csfStore = systemCsfStore;
            } else {
                //use Credential Store defined in app-level jps-config.xml
                csfStore = appCsfStore;
            }
            return csfStore;
        }
    

Note:

The following JAR files must be included in the classpath: oracle.jps_11.1.1/jps-api.jar, oracle.jps_11.1.1/jps-unsupported-api.jar.

You must provide the necessary permissions to the custom policy executor in the system-jazn-data.xml file. For example,

   <grant>
            <grantee>
                <codesource>
                    <url>file:{location of custom policy executor jar}</url>
                </codesource>
            </grantee>
            <permissions>
                <permission>
                    <class>oracle.security.jps.service.credstore.CredentialAccessPermission</class>
                    <name>context=SYSTEM,mapName=*,keyName=*</name>
                    <actions>*</actions>
                </permission>
               </permissions>
        </grant>
 

4.8 Handling Exceptions in Custom Assertions

Any exceptions during the execution of custom assertions must be handled by the WSMException in the custom assertion executor.

IResult execute(IContext mcontext) throws WSMException

This method must always return a non-null IResult object. The status field indicates success or failure or other state. The IResult.getFault() method is used to return the detailed cause for failure and returns null in case of success.

As shown in the following example, exceptions arising from within the execute method of custom assertion executor should first be wrapped in WSMException, the execution status should be set to IResult.FAILED, and the generateFault method throws the WSMException.

IResult execute(IContext mcontext) throws WSMException {
   IResult result = new Result();
   try {
      ....
      .....
 
   } catch (Exception e) {
      WSMException wsmException = new WSMException(e);
      result.setStatus(IResult.FAILED);
      generateFault(wsmException);
   }
}