Thursday, January 29, 2015

Reset WSO2 ESB Admin password

During my current WSO2 ESB project the supplied admin password of the Admin Console didn't work anymore and I needed a way to reset the admin password.
After googling I came out at the following URI: https://docs.wso2.com/display/Carbon401/Changing+User+Passwords+in+the+Carbon+Database
This tutorial used the default h2 database, which was different to the MySql database we used, so I needed to tweak it a little bit to work.

The initial go failed already because I didn't have Ant installed, which is a pre-requisite.

Pre-requisites
* Ant is installed
* WSO2 ESB server is stopped
* The 'mysql-connector-java-5.1.27-bin.jar' is available in the WSO2ESB/repository/components/lib
   folder

Actions to be taken
- Navigate to the WSO2ESB/bin folder
- Execute the 'chpasswd.sh' command:
  ./chpasswd.sh --db-url "jdbc:mysql://<server-name>:3306/wso2users" --db-driver "com.mysql.jdbc.Driver" --db-username <user> --db-password <password>
- Next you will get a prompt in which you can change your admin password.

Have fun with it!!

Thursday, January 15, 2015

How to configure the WSO2 SAP Adapter for sending and receiving iDocs?

WSO2 ESB comes with a variety of adapters to connect to all sorts of different systems. One of these adapters is the SAP adapter.
The WSO2 SAP adapter has full iDOC and experimental BAPI support. It used the SAP JCO library as underlying framework to communicate with SAP.
Installing the adapter couldn’t be easier. Its shipped with WSO2 ESB and the WSO2 ESB documentation website describes the installation procedure from the WSO2 perspective.
The installation procedure however does not guide you on how to find the settings you need in SAP.
So, let’s start off with some SAP adapter knowledge. I’ll refer to the WSO2 ESB SAP adapter as ‘SA’ in the following guide.
The SA is capable to be used as a Client as well as a Server. To setup the SA as client to a SAP system you’ll need to setup a client-side configuration fle. This file should be named [SAP-GWHOST].dest and must be placed in the [WSO2_HOME]/repository/conf/sap folder. This folder does not exist per default so make sure you create it and provide enough access rights for the WSO2 user to read the files within it.
To setup the WSO2 as an idoc server you must create a configuration file named [SAP-GWHOST].server.
Let’s first handle the client configuration file. There might be some differences based on your SAP system but the following settings should cover a lot of installations. The screenshots are based on SAP ECC version 6.0
In the examples below the SAP gateway is known as SAPSYS01.
The configuration of the SAPSYS01.dest (remember this is the “using WSO2 ESB as a SAP client” configuration) has the following content:
jco.client.client=900
jco.client.user=spremote
jco.client.passwd=FILL_IN_YOUR_PASSWORD_HERE
jco.client.lang=en
jco.client.ashost=SAPSYS01
jco.client.mshost=SAPSYS01
jco.client.gwhost=SAPSYS01
jco.client.gwserv=3300
jco.client.sysnr=00
jco.client.idle_timeout=300
jco.client.logon=0
jco.client.msserv=3600
jco.client.trace=0
jco.client.getsso2=0
jco.client.r3name=QCR
Ok, lets open up some screens in the SAP system. Assuming an experienced SAP engineer will be doing this you could either go through the SAP Easy Access menu or directly open up the appropriate transaction screen.
Open the System Gateway Monitor (SMGW) and use the top-menu named Goto – Parameters and Display as shown below.
Menu-Parameters-display-small
The following screen will show:
GatewayMonitor-params-small
Use the highlighted values from the Gateway Monitor Values for the jco.client.gwhost andjco.client.gwserv respectively.
Please be aware that you can substituted the service name (sapgw00 in the screenshot) to its corresponding port number (“sapgw00“ corresponds to portnumber 3300). Please see the last paragraph at Communication Connections of the R/3 System for more information.
Now, open transaction /NSMMS which will show the following screen:
ERD-SAP-Servers-Monitor-small
The highlighted values are to be used for respectively jco.client.msserv and jco.client.mshost
To find the SAP Server you’ll need to open transaction /NSSM51 which shows the following screen:
ERD-SAP-Servers
Use this highlighted value as jco.client.ashost
Then you’ll need to open transaction RZ11 and select the parameter name “SAP SYSTEM” and press Display which will show you the following screen:
ProfileParamterAttribs
Use the “Current value” as value for jco.client.sysnr
OK So far so good, we have already a bunch of values of our client configuration, but we’re not there yet.
Open the System status to get some additional values. Do that through the top menu, select System and then Status which will show the following screen:
System-Status
Use the values shown Client value for jco.client.client, user for jco.client.user, and Language for jco.client.lang
Based on the username shown here make sure to fill in the password for this useraccount injco.client.passwd
To find the R/3 name parameter value you’ll need to open transaction /NSMMS and then use the topmenu Goto -> Parameters -> Display which will show the following screen:
ListOfMessageServerParameters
Here you need to use the server service name and strip off the “sapms” part which in the screenshot case will leave you with ERD as jco.client.r3name
There are still some settings left. These are jco.client.getsso2jco.client.logon andjco.client.idle_timeout and jco.client.trace
The jco.client.getsso2 value can be left as value 0. It indicates whether a Single-Sign On ticket should be requested from SAP. That will not be used in this setup.
The jco.client.logon can also be left 0. It enables or disabled the logon check when a connection is opened to SAP.
The jco.client.idle_timeout can be left default to value 300. This setting allows connections to stay open for a specified amount of time. It is beneficial to leave this rather lengthy as that saves the connection setup overhead upon sending data to SAP.
The last setting is jco.client.trace can be used to switch on SAP JCO tracing. Trace files will be stored in WSO2_HOME and will be called jco_XXXXX.trc where XXXXX is a unique number to indicate the request.

Once all connection settings from the above paragraphs have been found and configured in the server and dest files then you might still run into issues.
One of which is a common issue where the following error appears:
Connect to message server host failed
Connection parameters: TYPE=B DEST=SAPSYS01 MSHOST=SAPSYS01 MSSERV=3600 R3NAME=ERD GROUP=PUBLIC PCS=1
ERROR Group PUBLIC not found
TIME Fri Jan 24 15:48:53 2014
This issue indicates that the user (Called “SPREMOTE” in the above configuration steps) is not assigned to the public user-role.
To fix this open up transaction /NSMLG where you must select the “PUBLIC” logon group. Then go to the top menu, choose Goto and User list as show here.
Menu-Userlist
CCMS-Global User List
If there is no public logon group then you should create one.
This can be done using the Create new assignment button in the CCMS:Maintain Logon Groups screen above.
As can be seen in the screenshot below; fill in PUBLIC as logon group name and click Copy to create the group.
CreateAssignment-User

Receiving IDOCs
Ok, so lets start off with setting up WSO2 as an IDOC server so that you can receive IDOC within WSO2. Assuming you read and executed the previous post you should now have the SAPSYS01.dest and SAPSYS01.server files. To setup WSO2 as an IDOC server you need only the SAPSYS01.server configuration file in [WSO2_HOME]/repository/conf/sap.
Make sure that your axis2.xml (which is located in [WSO2_HOME]/repository/conf/axis2) has the SAPTransportListener named idoc and the SAPTransportSender named idoc uncommented/enabled.
Please create a proxy service. Use the Custom proxy type and give it contents similar to the following:
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns=http://ws.apache.org/ns/synapse name="SAPAdapterProxy"
transports="idoc" statistics="enable" trace="enable" startOnLoad="true">
<target>
<inSequence>
<log level="full"/>
<drop />
</inSequence>
<outSequence>
<log level="full"/>
<send/>
</outSequence>
</target>
<parameter name="transport.sap.enableTIDHandler">enabled</parameter>
<parameter name="transport.sap.serverName">SAPSYS01</parameter>

<description/>
</proxy>
The magical parts are in bold.
First tell WSO2 to start listening with an idoc transport listener by setting the transports attribute value to “idoc”.
Then to configure the TransportListener you must set the two parameters which are highlighted at the bottom of the proxy. The first being the transactionHandler which needs to be enabled and the second needs tob e the servername of the SAP server you have a configuration setup for. In our case that is the SAPSYS01.server configuration file or SAPSYS01 SAP system name.
When you deploy this proxy then you should see a message in the log indicating that WSO2 is listening for incoming IDOCs.
TID: [0] [ESB] [2014-02-04 11:28:44,474] [localhost-startStop-1] DEBUG {org.wso2.carbon.transports.sap.idoc.IDocEndpoint} - Engaging the default TID handler for : SAPSYS01 {org.wso2.carbon.transports.sap.idoc.IDocEndpoint}

TID: [0] [ESB] [2014-02-04 11:28:44,481] [localhost-startStop-1] INFO {org.wso2.carbon.transports.sap.idoc.IDocEndpoint} - IDoc server started with server name : SAPSYS01 and program ID : JCOSERVER01 {org.wso2.carbon.transports.sap.idoc.IDocEndpoint}
Within your SAP system you should be able to see that an RFC connection to WSO2 is alive.
When you now send an iDOC over the new RFC connection to the registered programID (which is JCOSERVER01 as can be seen from the logstatements above) it will end up in the WSO2 proxy and the log-mediator will show you the IDOC received from SAP.
When you dont get the IDOC in the proxy then fiddle around a bit with the unicode setting in SAP. Experience showed me that enabling or disabling that at the SAP side fixes the connection and the IDOC is received properly.

Sending IDOCs
Sending IDOCs is actually rather easier than receiving them. To send IDOCs to SAP you need to have the SAPSYS01.dest configuration file setup. Please see my previous post for more details.
Lets create a custom proxy again with the following content:
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns=http://ws.apache.org/ns/synapse name="SAPSenderProxy"
transports="http" startOnLoad="true" trace="enable" statistics="enable">
<description/>
<target>
<inSequence>
<log level="full"/>
<send>
<endpoint name="sapidocendpoint">
<address uri="idoc:/SAPSYS01"/>
</endpoint>
</send>
</inSequence>
<outSequence/>
</target>
<parameter name="serviceType">proxy</parameter>
</proxy>
This proxy has been configured as an ordinary one where you send your data to it over the HTTP transport. The special part is in the address of the send-mediator’s endpoint. You must configure it to use the idoc transport and set the hostname-part of the URI to your SAP systems name.
You should now be up and running with your IDOC connections.

Monday, January 12, 2015

How to configure a VFS transport within WSO2 ESB?

In this tutorial I will show you the variety of options to configure a VFS transport.

What is VFS? 
Virtual File System (VFS) is an abstraction layer on top of a more concrete file system. The purpose of a VFS is to allow client applications to access different types of concrete file systems in a uniform way. 

1) Local file system
    a Windows
    b Linux 
2) FTP 
3) SFTP 
4) CIFS - SMB 

The most used VFS options are:

1a. Local file system - Windows
<proxy xmlns="http://ws.apache.org/ns/synapse" name="ProxyWinFile" transports="vfs" statistics="disable" trace="disable" startOnLoad="true">
   <target>
      <inSequence>         
         <log level="custom">            
            <property name="LOG" value="=====Win File=======Win File=====Win File====="/>         
         </log>      
      </inSequence>
      <outSequence>         
         <send>            
            <endpoint>               
               <address uri="vfs:file:///D:/SPs/tmp/out"/>            
            </endpoint>         
         </send>      
      </outSequence>
   </target>
   <parameter name="transport.vfs.ActionAfterProcess">MOVE</parameter>
   <parameter name="transport.PollInterval">20</parameter>
   <parameter name="transport.vfs.FileURI">file:///D:/SPs/tmp/in</parameter>
   <parameter name="transport.vfs.MoveAfterProcess">file:///D:/SPs/tmp/process</parameter>
   <parameter name="transport.vfs.MoveAfterFailure">file:///D:/SPs/tmp/fail</parameter>
   <parameter name="transport.vfs.FileNamePattern">.*\.xml</parameter>
   <parameter name="transport.vfs.ContentType">text/xml</parameter>
   <parameter name="transport.vfs.ActionAfterFailure">MOVE</parameter>
   <parameter name="transport.vfs.MoveTimestampFormat">yyyyMMdd_HHmmss_</parameter>
   <description></description>
</proxy>  

1b. Local file system - Linux
<proxy xmlns="http://ws.apache.org/ns/synapse" name="ProxyFile" transports="vfs" statistics="disable" trace="disable" startOnLoad="true">
   <target>
      <inSequence>
         <log level="custom">
            <property name="LOG" value="=====File=======File=====File====="/>
         </log>
      </inSequence>
      <outSequence>
         <send>
            <endpoint>
               <address uri="vfs:file:///home/user/file/out"/>
            </endpoint>
         </send>
      </outSequence>
   </target>
   <parameter name="transport.PollInterval">20</parameter>
   <parameter name="transport.vfs.ActionAfterProcess">MOVE</parameter>
   <parameter name="transport.vfs.MoveAfterProcess">file:///home/user/file/process</parameter>
   <parameter name="transport.vfs.FileURI">file:///home/user/file/in</parameter>
   <parameter name="transport.vfs.MoveAfterFailure">file:///home/user/file/fail</parameter>
   <parameter name="transport.vfs.FileNamePattern">.*\.xml</parameter>
   <parameter name="transport.vfs.ContentType">text/xml</parameter>
   <parameter name="transport.vfs.ActionAfterFailure">MOVE</parameter>
   <parameter name="transport.vfs.MoveTimestampFormat">yyyyMMdd_HHmmss_</parameter>
   <description></description>
</proxy> 
 

2. FTP Proxy configuration
<proxy name="ProxyFTP" transports="vfs" startOnLoad="true" trace="disable">
      <description/>
      <target>
         <inSequence>
            <log level="custom">
               <property name="LOG" value="=====FTP=====FTP=====FTP====="/>
            </log>
         </inSequence>
         <outSequence>
            <send>
               <endpoint>
                  <address uri="vfs:ftp://acb:abc123@10.100.0.5/esbtest/out"/>
               </endpoint>
            </send>
         </outSequence>
      </target>
      <parameter name="transport.vfs.ActionAfterProcess">MOVE</parameter>
      <parameter name="transport.PollInterval">5</parameter>
      <parameter name="transport.vfs.MoveAfterProcess">vfs:ftp://acb:abc123@10.100.0.5/esbtest/process</parameter>
      <parameter name="transport.vfs.FileURI">vfs:ftp://acb:abc123@10.100.0.5/esbtest/in?vfs.passive=true</parameter>
      <parameter name="transport.vfs.MoveAfterFailure">vfs:ftp://acb:abc123@10.100.0.5/esbtest/fail</parameter>
      <parameter name="transport.vfs.FileNamePattern">.*.xml</parameter>
      <parameter name="transport.vfs.ContentType">text/xml</parameter>
      <parameter name="transport.vfs.ActionAfterFailure">MOVE</parameter>
      <parameter name="transport.vfs.MoveTimestampFormat">yyyyMMdd_HHmmss_</parameter>
</proxy>

3. SFTP Proxy configuration
<proxy name="ProxySFTP" transports="vfs" startOnLoad="true" trace="disable">
      <description/>
      <target>
         <inSequence>
            <log level="custom">
               <property name="LOG" value="=====FTPS=======FTPS=====FTPS====="/>
            </log>
         </inSequence>
         <outSequence>
            <send>
               <endpoint>
                  <address uri="vfs:sftp://abc:abc123@10.100.0.5/esbtest/out"/>
               </endpoint>
            </send>
         </outSequence>
      </target>
      <parameter name="transport.PollInterval">5</parameter>
      <parameter name="transport.vfs.ActionAfterProcess">MOVE</parameter>
      <parameter name="transport.vfs.MoveAfterProcess">vfs:sftp://abc:abc123@10.100.0.5/esbtest/process</parameter>
      <parameter name="transport.vfs.FileURI">vfs:sftp://abc:abc123@10.100.0.5/esbtest/in?vfs.passive=true</parameter>
      <parameter name="transport.vfs.MoveAfterFailure">vfs:sftp://abc:abc123@10.100.0.5/esbtest/fail</parameter>
      <parameter name="transport.vfs.FileNamePattern">.*.xml</parameter>
      <parameter name="transport.vfs.ContentType">text/xml</parameter>
      <parameter name="transport.vfs.ActionAfterFailure">MOVE</parameter>
      <parameter name="transport.vfs.MoveTimestampFormat">yyyyMMdd_HHmmss_</parameter>
</proxy>

4. CIFS - SMB Proxy configuration (Windows with domain)
<proxy name="ProxySMB" transports="vfs" startOnLoad="true" trace="disable">
      <description/>
      <target>
         <inSequence>
            <log level="custom">
               <property name="LOG" value="====SMB====SMB====SMB===="/>
            </log>
         </inSequence>
         <outSequence>
            <send>
               <endpoint>
                  <address uri="vfs:smb://devlab\user1:user123@10.200.3.187/test/out"/>
               </endpoint>
            </send>
         </outSequence>
      </target>
      <parameter name="transport.vfs.ActionAfterProcess">MOVE</parameter>
      <parameter name="transport.PollInterval">10</parameter>
      <parameter name="transport.vfs.MoveAfterProcess">smb://devlab\user1:user123@10.200.3.187/test/process</parameter>
      <parameter name="transport.vfs.FileURI">smb://devlab\user1:user123@10.200.3.187/test/in</parameter>
      <parameter name="transport.vfs.MoveAfterFailure">smb://devlab\user1:user123@10.200.3.187/test/fail</parameter>
      <parameter name="transport.vfs.Locking">false</parameter>
      <parameter name="transport.vfs.FileNamePattern">.*\.xml</parameter>
      <parameter name="transport.vfs.ContentType">text/xml</parameter>
      <parameter name="transport.vfs.ActionAfterFailure">MOVE</parameter>
      <parameter name="transport.vfs.MoveTimestampFormat">yyyyMMdd_HHmmss_</parameter>
</proxy> 
 

Tuesday, August 6, 2013

Taking reverse proxy functionality into account within your software architecture

Within the Java project I am currently working on we had to deal with lots of security related questions and challenges.

The project itself is a Java project created with the following stack:
- Spring MVC (Controller)
- Apache Wicket (frontend)
- Spring / Spring Data / Apache CXF (Business & Service Layer)
- Hibernate (Model)

The application itself is deployed within a high-available environment.

One of a list of system architectural decisions we made was to handle all of our SSL trafic not within the application servers itself (using apache mod_ssl), but instead move it to the load balancer which is placed within the DMZ and actual acting as a reverse proxy.

This design has several advantages, both technical and from a maintenance point of view:

  • The SSL certificates and private keys are centralized on the reverse proxy service which simplifies key management. Not every application server within your application server cluster has to be polluted with SSL code and logic. In this way the responsibility and maintenance of this PKI management stuff can most of the times also move from project to hosting provider of your application.
  • The proxy server can terminate the SSL handshake and traffic from the proxy server to the application server cluster can be done using plain HTTP. This will lead to an improved performance of your application logic.
  • Upgrades of application servers can be done more easily. Switching to a new application server only requires reconfiguring the reverse proxy server to point to the new application server.
  • Improved security of your total application landscape when using a reverse proxy within a DMZ.
The message what I want to address is that you have to look further than only your software architecture environment, and also take the total system architecture including DMZ into account!!!!

Thursday, November 1, 2012

Access to XmlStore files from within Ws-App java code


Today I needed to have access from within Java Ws-App code to an XML definition located within the XML Store.
Within a Cordys BPM those webservices are available and can be easily drag and dropped into your BPM, but if you need this within your java code it can be easily accomplished by executing a Soap request.

public class XmlStore
{
    final String NS_CASEMNGT_INST = "http://schemas.cordys.com/casemanagement/instanceadministration/1.0";

    public static int getXMLObject(String userDn, String key)
    {
        int retVal = 0;
        int response = 0;

        try
        {
            // Build up the request to send.
            String[] paramNames = { "key" };
            Object[] paramValues = { key };
            SOAPRequestObject sro = new SOAPRequestObject(NS_CASEMNGT_INST , "GetXMLObject", paramNames, 
                        paramValues);

            // Set the proxy user if passed on
            if (StringUtils.isSet(userDn))
            {
                sro.setUser(userDn);
            }

            // Send the actual request.
            response = sro.sendAndWait();

            // Find the response document
            retVal = XPathHelper.selectSingleNode(response, "//xs:old/*", Constants.xmi);
        }
        catch (Exception e)
        {
            throw new CustomException(e, Messages.ERROR_GETTING_FILE_FROM_XML_STORE, key);
        }
        return retVal;
    }

And in the calling function you have than something like this:
Int xmlstoreObject = XMLStore.getXMLObject(BSF.getUser(), "/nl/project/xmlstore/xmlfile.xml");

Don't forget in your calling code to clean-up the NOM element by using the 'Node.delete(node)' function.
Otherwise memory leaks can be easily introduced.