Friday, July 26, 2019

Extendable System Monitor on webMethods

System Connectivity Monitoring

There could be hundreds of systems integrated in a big company, and it's a challenge for administrator to check system health of each one. This tool is designed to monitor system connectivities and send out notification once it's down.
You could download it from git hub, https://github.com/dingago/HxSystemMonitorAdapter. The code is verified on webMethods 9.9.
It provides a summary page to view current status of all systems.
To monitor the systems automatically, there are only 2 things you need to do:
  1. Configure connections to associate with system you want to monitor. Different system would be represented by different kind of connection, which is easily to be extended.
  2. Configure service HxSystemMonitorAdapter.connection:pingAll as scheduler service, so it would check connection activity periodically.

Extend The Adapter to Monitor Your Own System

By default, it contains some build-in connections such as:
  • RemoteServerConnection, to monitor another Integration Server via webMethods remote server management
  • BrokerConnection, to monitor Broker via webMethods messaging
  • UniversalMessagingConnection, to monitor Universal Messaging via webMethods messaging
But you could always develop customized connection to monitor your own system following the instructions below:
  1. Develop a connection factory class which extends abstract class hx.systemMonitorAdapter.SystemMonitorAdapterConnectionFactory, and you need to define the fields how to configure the connection in it.
  2. Develop a connection class which extends abstract class hx.systemMonitorAdapter.SystemMonitorAdapterConnection, and you need to write some code to check the connectivity in method initializeConnection, just make sure throw a ResourceException when connectivity is inactive.
  3. Export these class as a jar file and place it under <Package_Dir>/code/jars.
  4. Create a new XML file under <Package_Dir>/config to provide some metadata of your connection, including:
    1. factoryClass, the class name of your connection factory
    2. displayName, the display name of your connection
    3. description, a brief description of your connection
    4. helpUrl, optional, the url of html page contains some help information of your connection
    5. field, the field name in your connection factory class and corresponding display name on GUI
You could reference required class from <Package_Dir>/code/jars/system-monitor-adapter.jar.

Getting Notification When System Is Down

This tool contains a customized IS event(HxSystemMonitorAdapter.event:SystemMonitorEvent), which would be published when a system is detected down. So you may want to subscribe this event by invoking service pub.event:addSubscriber. Event type is "Hx System Monitor Event" for subscribing.

Thursday, June 27, 2019

How to configure secured external LDAP as directory service on MWS

Overview

In this article, I will show you how to setup a secured LDAP server, and how to configure it as a directory service on My webMethods Server.

Configure External LDAP

Prepare Apache Directory Service

Install and start Apache DS according to online document https://directory.apache.org/apacheds/basic-ug/1.3-installing-and-starting.html. After you start the Apache DS, it is listening port 10636 for secured request by default.

Prepare Apache Directory Studio

Install Apache Directory Studio according to online document https://directory.apache.org/studio/downloads.html. After you start the Apache Directory Studio, switch to LDAP perspective and create a secured connection as below.


Remember to trust certificate if you see a dialog.

Replace Apache DS Certificate

Because the default certificate can't be recognized correctly, so we need to replace it by using an external key store file described here https://directory.apache.org/apacheds/basic-ug/3.3-enabling-ssl.html#in-case-you-want-to-use-an-external-keystore.

Prepare LDAP User

Save the content below as file with name xiaowei.ldif.

# File xiaowei.ldif

dn: cn=Xiaowei Wang,ou=users,ou=system
objectclass: inetOrgPerson
objectclass: organizationalPerson
objectclass: person
objectclass: top
cn: Xiaowei Wang
sn: Wang
uid: xiaowei
givenName: Xiaowei
mail: dingago@gmail.com
userpassword: xiaowei

Right click on the connection you just created and click "Import" -> "LDIF Import" -> "Browse..." to select the file xiaowei.ldif, then click "Finish" to import. Now you're supposed to see a new entry under users.

Configure MWS

Prepare Certificates

We need to export Apache DS certificate first. One easy way to do that is to use command "openssl s_client -showcerts -connect hostname:port". You will need to replace hostname with host name or IP address of the server Apache DS is running on, and replace port to port number which listener is listening for secured request(for example 10636).
This command will print the certificate chain, so you could copy anything between "-----BEGIN CERTIFICATE-----" and "-----END CERTIFICATE-----" and save them into individual file. Remember to copy these two lines as well.

Import Certificates to Trust Store

Now we need to import these certificates into MWS' trust store if they're self-signed.
According to document <Administering_My_webMethods_Server> (I'm looking at version 9.9), MWS is using trust store file located at <SAG_Dir>/jvm/jvm/jre/lib/security/cacerts. But that's not true. What you need to look at is MWS' custom_wrapper.conf, which is located under <SAG_Dir>/profiles/MWS_default/configuration in my environment. It could be different based on different version or different instance name.
Find the property "set.JAVA_TRUSTSTORE" in custom_wrapper.conf file, and this is the trust store MWS is using. You could either import these certificates into current trust store, or create your own trust store file and change the property value to point to your trust store.
To import into current trust store, if the file is sagdemoca.jks, then the password to import certificate is "manage".
To use your own trust store which password is not "manage", you will have to also change the property "set.JAVA_TRUSTSTORE_PASSWORD" as well. To generate encrypted password, change directory to <SAG_Dir>/common/lib and run the command below "java -cp wm-caf-common.jar;ext/log4j.jar com.webmethods.caf.common.CipherUtil your_password".

Configure Directory Service

Now start your MWS, and once it's ready login as Administrator then navigate to "Administration" -> "My webMethods" -> "Directory Service". Click "Create New Directory Service" and choose Directory Type "LDAP" then click "Next".
In my case, I have the Connection Information as below:

Provider URL : ldaps://localhost:10636
Base DN : ou=system
Security Principal : uid=admin,ou=system
Security Credentials : secret

And User Attributes as below, you could see it's matching the LDAP entry.

Once this Directory Service is created, you should be good to search LDAP user on MWS.


Thursday, June 20, 2019

Enhanced DSP on webMethods

DSP

DSP (Dynamic Server Pages) is a powerful tool for developer to build dynamic web pages on webMethods Integration Server. Actually every single page you see on Administrator UI is a DSP page. It contains a set of pre-defined tags, to allow you to invoke a service or display a value in pipeline.

What Is Wrong with DSP

Firstly, the number of tags DSP supports seems not changing, since we have more and more new features on Integration Server. It looks like nobody still maintains it.
Secondly, there is an obvious mistake for ifvar tag. In any "Dynamic Server Pages and Output Templates Developer’s Guide" it says the match option is to match a regex pattern. But that's not true, it's trying to match a glob pattern.

Enhanced DSP

The DSP is not as open as other components on Integration Server. Which means it's not easy to change how it works. What kind of tags are supported is hard-code defined in class com.wm.util.template.TemplateTokenizer based on tag name. And how do these tags work is defined in individual class under package com.wm.util.template. To enhance DSP, the only option I have is to replace the class. I prefer to use javassist to avoid changing on original jar files, but only add new jar file to override the behaviors.
I developed a sample project to:
  1. Add a customized argument on ifvar tag, to support regex pattern.
  2. Add a customized tag to support reading global variables.
Of course you could do a lot more than that. You could download it from GitHub, https://github.com/dingago/HxEnhancedDSP. The code is verified on webMethods 9.9.

What Does It Look Like

<HTML>
<BODY>
%invoke TestEnhancedDSP:getValue%
value = %value value%
<br>
pattern = ^test.*$
<br>
%ifvar value matches('^test.*$')%
regular matches = true
%else%
regular matches = false
%endif%
<br>
%ifvar value regexmatches('^test.*$')%
regex matches = true
%else%
regex matches = false
%endif%
%endinvoke%
</BODY>
</HTML>


<HTML>
<BODY>
Global variable "demoServer" = %gv demoServer%
</BODY>
</HTML>


Wednesday, June 12, 2019

Missing links on webMethods Administrator UI

Missing Links

There are a set of links at top right if you login Administrator UI. For example you can click Help link to view build-in documents based on what page you're viewing.
But in some of versions or some of pages, these links are missing.

Top.dsp

The reason is there is a missing %end% tag in DSP page "top.dsp" under WmRoot package. On version 9.9 this issue occurs between line 156 to 180.

156      %invoke wm.server.query:getLicenseSettings%
157      %ifvar keyExpired%
158      <TD width=100% class="keymessage">
159        <center>
160          <A  class="keymessage" HREF="settings-license-edit.dsp" TARGET="body">
161            License Key is Expired or Invalid.
162          </A>
163        </center>
164      </TD>
165      %else%
166      %ifvar keyExpiresIn%167      <TD width=100% class="keymessage">
168        <center>
169          &nbsp;
170          <A class="keymessage" HREF="settings-license-edit.dsp" TARGET="body">
171      %ifvar keyExpiresIn equals('0')%
172            License Key expires today.
173      %else%
174            License Key expires in about %value keyExpiresIn% days
175      %endif%
176          </A>
177        </center>
178      </TD>
179      %endif%
180      %endinvoke%

There is an obvious %end% tag missing for line 157, so what we need to do to fix it is to insert a new line like below.

156      %invoke wm.server.query:getLicenseSettings%
157      %ifvar keyExpired%
158      <TD width=100% class="keymessage">
159        <center>
160          <A  class="keymessage" HREF="settings-license-edit.dsp" TARGET="body">
161            License Key is Expired or Invalid.
162          </A>
163        </center>
164      </TD>
165      %else%
166      %ifvar keyExpiresIn%167      <TD width=100% class="keymessage">
168        <center>
169          &nbsp;
170          <A class="keymessage" HREF="settings-license-edit.dsp" TARGET="body">
171      %ifvar keyExpiresIn equals('0')%
172            License Key expires today.
173      %else%
174            License Key expires in about %value keyExpiresIn% days
175      %endif%
176          </A>
177        </center>
178      </TD>
179      %endif%
         %endif%
180      %endinvoke%

Saturday, June 8, 2019

Enhanced Central User Management on webMethods

Central User Management

By configuring Central User Management on Integration Server, we could authenticate user by not only IS local users, but also MWS users. Because MWS is capable to integrate with other directory services such as LDAP and AD, so it's definitely a better idea to reuse what you already have instead of create them once again.

Central User Management on IS

Usually what we did with central user is, to assign proper ACLs and make sure that user has correct permission. But actually we could do a lot of more. We could:
  • Create, read, update, delete, search user
  • Create, delete, search, list role
  • Create, delete, search, list group
  • Add user/group to group, remove user/group from group
  • Add user/group/role to role, remove user/group/role from role
  • Find members of group/role
I developed an IS package with a set of Java services to achieve them. You could download it from GitHub, https://github.com/dingago/HxEnhancedUserManagement. The code is verified on webMethods 9.9.

With Great Power Comes Great Responsibility

It also bring some extra risks to have such capability. Without proper ACL, everybody on IS, even with minimum permission, could create new user on MWS with administrator permission, and then grant himself/herself a higher authority with the created new user. Be Careful!

Wednesday, June 5, 2019

Introducing a non-invasive instance synchronization solution on webMethods

Instance Synchronization

Are you a webMethods administrator? How many Integration Server instances are you maintaining? How do you synchronize changing in a cluster, for example an extended setting?
I believe you usually have to make the change manually on all the nodes, and that's definitely boring and risky.

Cluster Dispatcher

I designed and built a tool Cluster Dispatcher to easily synchronize instance status. This is how it works. For specific service that might change instance status we will need to register it as a Service Dispatch task. When that specific service is invoked, Cluster Dispatcher would remote invoke the same service with the same inputs on other nodes. So whatever you did on one instance, you did for all. You could download this package form GitHub,https://github.com/dingago/HxClusterDispatcher. The code is verified on webMethods 9.9.

Features

Non-Invasive

You don't have to do any change for your service, or to invoke any service explicitly. It works if you register it as a Service Dispatch task.

Traceable

You could check the dispatching status by configuring logging service, so you know exactly what happened.

Two Dispatch Modes

Mode Lax will try to dispatch the service invocation on as many nodes as possible. Mode Strict will try to reverse the change if it's failed on any other nodes. 

Rollback

An optional rollback service is supported, which would be invoked on any successful nodes to reverse the change in mode Strict.

Self-Checking

Self-check if Cluster Dispatcher is configured correctly and ready to serve.

Management GUI Included

DSP pages are included to manage Cluster Dispatcher easily.

Friday, May 31, 2019

An easy way to hide Java code on webMethods

Why

Sometimes when you release a package on webMethods, you probably don't want to expose the detail  of your Java service, so somebody else could not modify your code, or you just don't want them to know how genius you are. Well, there is an easy way to hide your Java code just like what they did for Wm* packages.

How

If you take a look into the folder which holds your Java service, you would see a file named "java.frag". It's actually an XML file which contains unreadable weird string. That weird string would be base64 decoded back to Java code exactly the same as what you would see in Designer. You could try to decode it on some free web site, for example https://www.base64decode.org.

What

To hide the Java code, you will need to remove all java.frag files when releasing the package. When you try to archive the package on IS Administrator UI, select "All except specified by filter:" and type "*.frag" as the filter value. Now your genius idea would be a secret.

But

Unfortunately, the secret won't be kept too long. Once somebody export your package to local, then they could decompile class file to find out what you're hiding. There is another way to hide Java code even after exporting the package, but that's another story.

Extendable System Monitor on webMethods

System Connectivity Monitoring There could be hundreds of systems integrated in a big company, and it's a challenge for administrator...