Building an Infor Grid Lab – Part 5

To further build my Infor ION Grid laboratory for learning purposes, today I will install the Grid on the PostgreSQL database, on Windows.

Special note

I have a special appreciation for PostgreSQL. It is free/libre software. It is the successor of Postgres which is the successor of Ingres, two pioneering database systems in the heydays of Edgar F. Codd’s relational model. It originated at the University of California at Berkeley, a remarkable institution of computer science, near San Francisco where I live. And Ingres and Postgres were written by professor Michael Stonebraker, who is another recipient of the ACM Turing Award for his extensive contribution to database systems, and whom was my professor in the MIT Big Data course.


The Infor ION Grid bundled installer has built-in support for PostgreSQL (see part 4), but it is for your internal use only, not for production use. Anyhow, Infor M3 only supports EnterpriseDB Postgres Plus Advanced Server (see the announcement thing).

1. Install PostgreSQL

Download PostgreSQL for Windows:

Follow the installation wizard:

Verify it is started and listening:

2. Create the database

Create the Grid database, e.g. InforIONGrid, and verify the connection:

cd C:\Program Files\PostgreSQL\9.6\
createdb --username=postgres InforIONGrid
psql --username postgres -d InforIONGrid

Verify with a JDBC client such as SQuirreL (the Grid bundled installer ships with a PostgreSQL JDBC driver):


You can also verify with pgAdmin:

C:\Program Files\PostgreSQL\9.6\pgAdmin 4\bin\pgAdmin4.exe

3. Install the Grid

Now install the Grid as usual, select PostgreSQL support, enter Schema public:


The result is a Grid as usual, running on the PostgreSQL database:

Future work

  • Install Grid on Linux
  • Install Grid on a virtual private cloud
  • Install Grid session providers
  • Install GDBC
  • Install Grid applications
  • Grid pentesting
  • Proof-of-concept of Grid database on homomorphic encryption with CryptDB or Microsoft’s Always Encrypted SQL Server


That was an illustration of how to install the Infor ION Grid on PostgreSQL on Windows, for learning purposes. The installation is quite intuitive.

Special thanks to the Infor ION Grid team in Sweden for making the Grid available on PostgreSQL.

Related posts

Infor M3 open source platform announcement thing

Let’s talk about the Infor M3 open source platform announcement thing.


In 2015, Infor announced: “The latest Infor M3 solution now features an open source based Linux platform as a deployment choice to reduce total cost of ownership for customers.”

It is admirable to support open source software, so please join us in congratulating Infor.

What about free/libre software?

It would have been more admirable to support free/libre software. The open source movement and the free/libre software movement are related but distinct; freedom is more important than open source.

Supported platform

The following documentation, M3 Core 13.4 Installation Guides Red Hat Linux > M3 Core Installation Planning Guide – RHEL > Introduction and overview > Installation Scenarios > Recommendations, says M3 Core is now available as an option on “Red Hat Enterprise Linux as operating system and Postgres Plus Advanced Server as database […] If the M3 Database Server is installed on Red Hat Enterprise Linux, the Postgres Plus Advanced Server must be used.”

Red Hat Enterprise Linux

Red Hat Enterprise Linux is a commercial product. Its source code is open and provided at no cost, but it is not provided in compiled form. To use it, we have to either buy it or go through the difficult compilation and derivative processes.

As a side note, Red Hat has controversy in the community with their non-free/libre licensing and inclusion of binary blobs [1] and as such is not endorsed by the Free Software Foundation [2].

EnterpriseDB Postgres Plus Advanced Server

EnterpriseDB Postgres Plus Advanced Server is also a commercial product, even though based on the open source PostgreSQL, it is provided at cost, and its source code is not available:

Technical reason?

Besides understandably not being able to support every combination of platform, are there any technical reasons for M3 to HAVE TO use Red Hat Enterprise Linux and EnterpriseDB Postgres Plus Advanced Server, and not Fedora, CentOS, Debian, Ubuntu, Suse, PostgreSQL?

Business collaboration?

Does it have anything to do with Infor’s joint collaboration with Red Hat and EnterpriseDB for Infor LN?

Wasn’t there something similar with the Intentia and IBM alliance [3] [4], where Movex Workplace HAD TO use the Enterprise Edition of IBM WebSphere Application Server for no apparent technical reason?

What about the community?

Infor uses a lot of free/libre software on free/libre licenses such as BSD, GPL and Apache. For example, this is the (not cleaned-up) list of about 100 projects used by one of the components of M3, the Infor Grid:

antlr antlr-runtime aopalliance-repackaged asm asm-commons asm-tree bcmail-jdk16 bcprov-jdk16 commonj.sdo commons-daemon commons-fileupload commons-logging commons-math3 ctivation cxf-api cxf-rt-bindings-soap cxf-rt-bindings-xml cxf-rt-core cxf-rt-databinding-jaxb cxf-rt-databinding-xmlbeans cxf-rt-frontend-jaxws cxf-rt-frontend-simple cxf-rt-management cxf-rt-transports-http cxf-rt-ws-addr cxf-rt-ws-policy cxf-rt-ws-rm cxf-rt-ws-security decision-trees derbyclient drools-compiler drools-core ecj eclipselink ehcache-core geronimo-javamail_1.4_spec groovy-all hk2-api hk2-locator hk2-utils izpack-api izpack-tools jackson-core-asl jackson-jaxrs jackson-mapper-asl jackson-xc javassist javax-websocket-client-impl javax-websocket-server-impl javax.annotation-api javax.el javax.inject javax.persistence javax.servlet-api javax.servlet.jsp javax.servlet.jsp-api javax.servlet.jsp.jstl javax.websocket-api jcommander jersey-client jersey-common jersey-container-servlet jersey-container-servlet-core jersey-core jersey-guava jersey-json jersey-media-json-jackson jersey-media-multipart jersey-multipart jersey-server jersey-servlet jetty-annotations jetty-continuation jetty-http jetty-io jetty-jndi jetty-jsp jetty-plus jetty-schemas jetty-security jetty-server jetty-servlet jetty-servlets jetty-util jetty-webapp jetty-xml jna jna-platform joda-time jsr166 jt400_jdk16 knowledge-api knowledge-internal-api linked-binaries liquibase log-viewer mail maven-shared-utils mimepull mockito-all mvel2 neethi ojalgo ojdbc6 org.apache.taglibs.standard.glassfish org.eclipse.jdt.core osgi-resource-locator postgresql scripting-client slf4j-api slf4j-grid sqljdbc4 stax2-api stringtemplate tasks validation-api websocket-api websocket-client websocket-common websocket-server websocket-servlet windowsjnasecurity woodstox-core-asl wsdl4j wss4j xml-resolver xmlbeans xmlschema-core xmlsec

Does Infor contribute back to the free/libre software community? Individual Infor developers probably contribute to free/libre software with bug fixes and documentation (congratulations). But I have not seen Infor as a company officially sponsor events, fund projects, contribute code, or provide developers to free/libre software. I do not know that they do or that they do not. If you know, please leave me a comment.


It is admirable that Infor provides M3 based on an open source platform as an option, it illustrates Infor’s commitment to the cloud and open platforms. However, the narrative is not clear as the required “open source” platform actually requires commercial products, at cost, that have restrictive licenses, with closed source code, possibly due to a business collaboration. For-profit corporations can choose to be commercial, closed source, and collaborate with partners, to fund product development and to protect intellectual property, but then the narrative should be made clear. Is there a technical reason? Is Infor misappropriating “open source”? Is Infor giving back to the free/libre software community? What do you think? Let me know in the comments below.

Building an Infor Grid Lab – Part 4bis

Continuing from part 4 building an Infor ION Grid laboratory for my learning purposes, today I will do alternative installations using the IzPack console and unattended installation modes. Most probably, you will never need to know any of this, except if you maintain a large cloud environment.


The Grid bundled installer is available publicly as part of the Grid deliverable, but it is for internal use only, not for production use.

Console mode

The Grid installer uses IzPack for the installation wizard, which comes with a text console installation mode, to have a command line interface instead of the graphical user interface:

To use it, create the empty database as usual, start a command prompt as administrator, execute the following command, and answer the prompts:

java -jar installer-1.13.77.jar -console

Refer to the log file if needed. The result is the same as in part 4, with database tables, files and folders, Grid registry, administrative router, user interface, Windows Service, etc.

Unattended mode

Furthermore, IzPack has an unattended installation mode, for a silent install.

To use, create an empty file with the following command:

java -jar installer-1.13.77.jar -console -options-template

Open the resulting file in a text editor, set the desired property values, with the proper escaping where necessary (e.g. install.path=C:\\Infor\\InforIONGrid):

And execute the silent install with the following command, there will be no prompts:

java -jar installer-1.13.77.jar -console -options

The resulting Grid is the same as usual.

Future work

  • Install the Grid on Linux and PostgreSQL
  • Install Grid on a virtual private cloud
  • Install Grid session providers
  • Install GDBC
  • Install Grid applications
  • Penetration testing
  • Proof-of-concept of Grid database on homomorphic encryption with CryptDB or Microsoft’s Always Encrypted SQL Server


That was an illustration of alternative installations of the Infor ION Grid using the IzPack text console installation mode for a command line interface, and the unattended installation mode for a silent install. Most probably, you will never need to know any of this. It shows Infor’s commitment to transition, from graphical user interfaces and customer on-premise installations, to migrating products to a multi-tenant cloud, the new direction.

That’s it! Please like, comment, subscribe, share, participate.

Related posts

Developing H5 Client scripts – Part 1

The day came I have to develop a script for Infor M3 H5 Client with M3 API calls for a customer. This post will add to my previous post, to Scott’s three previous posts, and to Karin’s previous post.


Scripts for H5 Client are written in the JavaScript programming language (ECMAScript). Scripts for Infor Smart Office are written in the JScript.NET programming language. Programs for M3 are written in the Java programming language. Despite the similarities, the three languages are different. Smart Office scripts will NOT execute in H5 Client; you will have to re-write most of the code and be familiar with functional programming, jQuery, Deferred, Promises, etc.; it is like back in the days of IBrix.


Here is the M3 H5 Development Guide:


Here are some tips to convert a Smart Office script to an H5 Client script:

Example of a minimal script for Smart Office:

package MForms.JScript {
	class Test {
		public function Init(element: Object, args: Object, controller : Object, debug : Object) {
			debug.WriteLine('Hello, World!');

The equivalent script for H5 Client:

var Test = new function () {
	this.Init = function (scriptArgs) {
		console.log('Hello, World!');

Various ways to get a field and its value compared to norpe’s guide for Smart Office:

var controller = scriptArgs.controller;
var host = controller.ParentWindow;
ScriptUtil.FindChild($, 'WRCUNM')[0]
ScriptUtil.FindChild(host, 'WRCUNM')[0]

UPDATE 2017-06-06: According to the H5 Development Guide, the above is not the recommended API, but controller.GetContentElement().GetElement("WRCUNM") instead.

Example to call an M3 API in H5 script:

ScriptUtil.ApiRequest('/execute/CRS610MI/LstByNumber', result => console.log(result), (error, message) => console.log([error, message]))

UPDATE 2017-06-06: According to the H5 Development Guide, the above is not the recommended API, but MIService.Current.execute|executeRequest instead, but I get error ‘MIService is not defined’; perhaps I do not have the latest version of H5 Client.

Chrome Developer tools

Use the Google Chrome Developer tools:

Use it for the list of global variables, code completion, type reflection, console, dynamic execution, debugger, network monitor, DOM, styles:

Pause execution to introspect global variables:

UPDATE 2017-06-06: In the JavaScript console, you can get the current controller with getActiveController() or MainController.Current.Instances.host_X where X is the controller number.

Administrative tool

Use the administrative tool to import/export H5 scripts:

UPDATE 2017-06-06: To update a script, simply re-import it, click Yes to override, and refresh the M3 panel with Actions > Refresh-F5; there is no cache thus no need to add the version number in the script file name unlike Smart Office.


Attach the script to the panel as usual at Tools > Personalize > Scripts:

Select Actions > Refresh-F5 to load the script:

Use the JavaScript debugger statement in your script to pause execution and invoke the Chrome debugger:

Call M3 API, and refer to my previous post:


That was a quick look at how to develop scripts for Infor M3 H5 Client including calls to M3 API.

Thanks to Scott Campbell of Potato IT for the first look.

Please like, comment, subscribe, share, come author with us, or look at other ways to contribute.

Related documentation

Building an Infor Grid Lab – Part 2bis

I am learning how to install an Infor ION Grid laboratory from scratch without LifeCycle Manager (LCM). I had started in part 2 with a minimalist Grid. Today, I will add the Default Router, Developer Session Provider, Administrative Router, Configuration Manager, web user interface, and Grid Agent.


I am learning the guts of the Grid because I am curious by nature, because I want to do penetration testing, because I want to install M3 on Linux and PostgreSQL to promote free software (as in freedom), and I want to make a proof-of-concept of M3 (just the Grid for now) on a homomorphic encryption database such as CryptDB or Microsoft’s Always Encrypted SQL Server.

Learning process

To learn, I take any installed Grid as a reference, and I study its internals. I start from the Topology View, I select the Node of interest (e.g. Administrative Router), I look at the Properties to make note of the command that launches it, I look at the Threads to determine the Java class name, I look at the disassembled source code to assimilate what it does, I look at the LCM installation package to understand the Velocity scripts and Ant tasks (see my previous work on LCM), and I look at the public Infor documentation. Then, I try to reproduce the Grid in my laboratory with only the necessary and sufficient elements. Here are some screenshots while learning the Grid Administrative Router:

I must use this Chinese wall technique because as a consultant I do not have access to Infor Product Development, i.e. the developers do not respond to my questions, and they do not share their source code or internal documentation. I am known for having “crazy ideas”, supposedly pointless. I call it progress 😉 If we do not challenge the status quo, who will? Even if I had access to the internal details, I am not allowed to show proprietary information. The workaround is to put myself in the situation of a clean room, analogous to that of any customer that has access to the binaries and that can reverse engineer on their own. That is how I can share my results here. Nonetheless, congratulations to Infor for finally having made a lot of the documentation public; please encourage them as well. In that direction, please sign the petition so Infor makes their source code at least source-available or shared source, and so they cooperate more with developers.

1. Begin with minimal Grid

Follow part 2 to begin with a minimal Grid.

2. Additional JAR files

Get the following additional JAR files (I may need to clean up the list). These JAR files are packed with IzPack at Grid_Installer_11.\products\Infor_ION_Grid_11.1.13.0\components\installer-1.13.77.jar\resources\packs\ . More easily, I get them from my existing Grid installation of part 4. Then, put them somewhere, e.g. C:\Infor\Grid\resources\ :



Prepare a CLASSPATH environment variable with all the JAR files including the JDBC driver:

set CLASSPATH=drivers\sqljdbc42.jar;resources\bcmail-jdk16.jar;resources\bcprov-jdk16.jar;resources\commons-fileupload-1.2.2.jar;resources\grid-core.jar;resources\grid-jaxrs2-1.13.77.jar;resources\grid-webapp-1.13.77.jar;resources\grid.httpclient.jar;resources\grid.liquibase.jar;resources\hk2-api-2.2.0.jar;resources\hk2-locator-2.2.0.jar;resources\hk2-utils-2.2.0.jar;resources\jackson-core-asl-1.9.13.jar;resources\jackson-jaxrs-1.9.13.jar;resources\jackson-mapper-asl-1.9.13.jar;resources\javassist-3.18.1-GA.jar;resources\javax-websocket-client-impl-9.1.1.v20140108.jar;resources\javax-websocket-server-impl-9.1.1.v20140108.jar;resources\javax.annotation-api-1.2.jar;resources\javax.inject-2.2.0.jar;resources\javax.servlet-api.jar;resources\javax.websocket-api-1.0.jar;resources\;resources\jersey-client-2.7.jar;resources\jersey-common-2.7.jar;resources\jersey-container-servlet-core-2.7.jar;resources\jersey-guava-2.7.jar;resources\jersey-media-json-jackson-2.7.jar;resources\jersey-media-multipart-2.7.jar;resources\jersey-server-2.7.jar;resources\jetty-http-9.1.1.v20140108.jar;resources\jetty-io-9.1.1.v20140108.jar;resources\jetty-security-9.1.1.v20140108.jar;resources\jetty-server-9.1.1.v20140108.jar;resources\jetty-servlet-9.1.1.v20140108.jar;resources\jetty-servlets-9.1.1.v20140108.jar;resources\jetty-util-9.1.1.v20140108.jar;resources\jna-3.3.0-platform.jar;resources\jna-3.3.0.jar;resources\mimepull-1.9.3.jar;resources\validation-api-1.1.0.Final.jar;resources\websocket-api-9.1.1.v20140108.jar;resources\websocket-client-9.1.1.v20140108.jar;resources\websocket-common-9.1.1.v20140108.jar;resources\websocket-server-9.1.1.v20140108.jar;resources\websocket-servlet-9.1.1.v20140108.jar

4. Additional folders

Create the following additional folders, I leave them empty even though I could organize the JAR files accordingly:


And create file webStartResources\, even though empty.

5. Additional tables

Create the following additional database tables:

 PROPERTY_KEY varchar(128) NOT NULL,
 PROPERTY_VALUE varbinary(max) NULL,
 PROPERTY_SIZE numeric(10, 0) NOT NULL,
 SEQID numeric(5, 0) NOT NULL,
 TIMESTAMP numeric(20, 0) NOT NULL,
 GRID_NAME varchar(64) NOT NULL,
 HOST_NAME varchar(64) NOT NULL,
 VALID_CERT varchar(32) NOT NULL,
 MODIFIED_BY varchar(128) NULL,
 TIMESTAMP numeric(20, 0) NOT NULL,
 RUNNING varchar(32) NOT NULL,
 HTTP_PORT numeric(20, 0) NOT NULL

6. Default Router

The Default Router is what Grid clients will connect to by default to communicate with the Grid.

Add the following to <routers> in the runtime.xml in the GRIDCONF table:

<router name="Default Router" host="localhost" httpsPort="50000" httpPort="50001" />

Use this command to start the Default Router:

java -cp %CLASSPATH% com.lawson.grid.Startup -router "Default Router" -configDir C:\Infor\Grid\ -host localhost -logLevel ALL

7. Developer Session Provider

The Developer Session Provider will let us login with any user and password (e.g. grid-admin) and get a session.

Add the following to <runtime> in the runtime.xml in the GRIDCONF table:

<sessionProviders developer="true" />

8. Administrative Router

The administrative router is the server part of the Configuration Manager.

Add the following to <topology> in the topology.xml in the GRIDCONF table:

<administrativeRouter host="localhost" port="50005" webStartPort="50006" httpsPort="50007" />

Use this command to start the Administrative Router:

java -cp %CLASSPATH% com.lawson.grid.Startup -router "Administrative Router" -configDir C:\Infor\Grid\ -host localhost -logLevel ALL

9. Configuration Manager Client

The Configuration Manager Client is the user interface to manage the runtime.xml.

You can use the online client from the Grid Management Pages:

Or you can use this command to start the offline client:

java -cp %CLASSPATH% com.lawson.grid.config.client.ui.Launch

10. Web UI

Start the Grid web user interface by opening a browser to https://localhost:50000/grid/info.html , then select /grid/ui/ , then go to the Configuration Manager and login:

11. Start the Grid

To start the Grid:

  1. Start the Registry as shown previously in part 2:
  2. java -cp %CLASSPATH% com.lawson.grid.Startup -registry -configDir C:\Infor\Grid\ -host localhost -logLevel ALL
  3. Start the Default Router as shown above.
  4. Start the Administrative Router as shown above.

Now we can start the Configuration Manager Client and/or web UI as shown above and enjoy the Grid.


We now have a minimal Grid with the Configuration Manager and fewer error messages:

Optional – Grid Agent

Instead of starting the Grid manually piece by piece, we can let the Grid Agent start it all. The Grid Agent is used to start nodes programmatically (e.g. registry, routers, applications); there is one Grid Agent per host. The Windows Service Infor ION Grid Bootstrap uses the Grid Launcher and Grid Agent to launch everything in the Grid at startup: registry, routers, applications, etc.:

java -cp %CLASSPATH% com.lawson.grid.agent.GridAgent -configDir C:\Infor\Grid\ -logToConsole -logLevel ALL -host localhost

Note: The Grid Agent will attempt to create the database tables, but because we already have some tables, not all of them, it will stop. Delete all the tables from the Grid database; re-run the Grid Agent, it will create all the tables; re-import the GRIDCONF with runtime.xml and topology.xml; re-run the Grid Agent.

Note: To stop the Grid, if we simply close the Grid Agent command prompt to terminate the batch job, it will not terminate the Java processes. We must go in the Task Manager and end the three java.exe processes for the registry, default router, and administrative router:


I put the SQL and commands on my GitHub.

Future work

I hope to do the following soon:

  • Install Grid session providers
  • Install GDBC
  • Install Grid applications
  • Install the Grid on Linux and PostgreSQL
  • Penetration testing
  • Proof-of-concept of Grid database on homomorphic encryption with CryptDB or Microsoft’s Always Encrypted SQL Server


That was a continuation of part 2 of building an Infor Grid laboratory for learning purposes, beginning with a minimal Grid, and adding a Default Router, Developer Session Provider, Administrative Router, Configuration Manager, web user interface, and Grid Agent. I can probably polish some of it. I will continue in the next posts.

That’s it!

Please like, comment, subscribe, share, and come write the next idea.

Related posts

Building an Infor Grid Lab – Part 4

Continuing to learn Infor ION Grid and building a laboratory without LifeCycle Manager (LCM), today I will use the Grid bundled installer and spew screenshots of the intuitive and automated install.


The Grid bundled installer is available publicly as part of the Grid deliverable, but it is for internal use only, not for production use.

1. Database

Install a database server (DB2 AS/400, Apache Derby, Oracle, PostgreSQL, or SQL Server), and create a new database, e.g. InforIONGrid:

2. JAR file

Go to the Infor Product Download Center, find the M3 Core Infrastructure and Technology, download the Grid installer, unzip it, go to the components sub-folder, and execute the installer JAR file:

3. Next Next Next

Follow the wizard:

3. Result

Here is the resulting Grid, files and folders, web UI, admin UI, topology, registry, default router, administrative router, user and role mapping, Grid Bootstrap, database, Windows Service, processes, topology XML, and runtime XML:

User and Role Mappings:



Windows Service:

Infor ION Grid Bootstrap - InforIONGrid - localhost
LogOnAs=NT SERVICE\Infor ION Grid Bootstrap - InforIONGrid - localhost
JavaHome=C:\Program Files\Java\jdk1.8.0_111
JVMParameters=-Xmx512M -XX:MaxPermSize=512m
ApplicationParameters=-baseDir C:\Infor\InforIONGrid


<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<topology gridId="83144c68-5a16-4e6c-8280-b9102a477980" xmlns:xsi="" xsi:schemaLocation="" xmlns="">
        <host address="localhost" gridAgentPort="50003" name="localhost"/>
    <registry host="localhost" port="50004"/>
    <administrativeRouter externalAddress="localhost" host="localhost" httpsAuthType="client" httpsPort="50007" port="50005" webStartPort="50006"/>
    <!--5/9/17 12:45 PM-->
    <!--Created by installer-->


<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<runtime xmlns:xsi="" xsi:schemaLocation="" xmlns="">
    <sessionProviders developer="false"/>
        <router externalAddress="localhost" host="localhost" httpAuthenticationMethods="ntlm" httpPort="50001" httpsAuthType="client" httpsAuthenticationMethods="basic ntlm" httpsPort="50000" name="Default Router"/>
        <propertyOverrides nodeType="router">
            <property name="grid.jvm.maxHeapMB">256</property>
        <propertyOverrides nodeType="registry">
            <property name="grid.jvm.maxHeapMB">256</property>
            <property name="grid.jvm.maxHeapMB">512</property>
            <property name="">true</property>
            <propertyListMap name="grid.slf4j.mapping" strategy="merge">
            <propertyListMap name="grid.router.endpoints"/>
    <!--5/9/17 12:45 PM-->
    <!--Created by installer-->

Here is the folder structure (zoom in):

C:\Infor\InforIONGrid>tree /a /f
Folder PATH listing for volume Windows_OS
Volume serial number is 0E5A-3982
|   BootstrapWebUI-50002.url
|   pid
|       sqljdbc4-4.0.jar
|   \---InforIONGrid
|       |   AdminUI.cmd
|       |   ChangeDBPassword.cmd
|       |   ChangeJDK.cmd
|       |   OfflineConfigUI.cmd
|       |   StartAllHosts.cmd
|       |   StartHost.cmd
|       |   StopAllHosts.cmd
|       |   StopHost.cmd
|       |
|       +---config
|       |       binary.path
|       |
|       |
|       +---log
|       |   \---SYSTEM
|       |           grid-agent-1244.log
|       |           grid-agent-1772.log
|       |           grid-agent-4504.log
|       |           grid-agent-4600.log
|       |           grid-agent-4960.log
|       |           grid-agent-6808.log
|       |           grid-registry-3816.log
|       |           grid-registry-3872.log
|       |           grid-registry-4072.log
|       |           grid-registry-5040.log
|       |           grid-registry-6492.log
|       |           grid-registry-8832.log
|       |           grid-router-Administrative_Router-3220.log
|       |           grid-router-Administrative_Router-3908.log
|       |           grid-router-Administrative_Router-4776.log
|       |           grid-router-Administrative_Router-5020.log
|       |           grid-router-Administrative_Router-5320.log
|       |           grid-router-Administrative_Router-9504.log
|       |           grid-router-Default_Router-3052.log
|       |           grid-router-Default_Router-3832.log
|       |           grid-router-Default_Router-4824.log
|       |           grid-router-Default_Router-5152.log
|       |           grid-router-Default_Router-5340.log
|       |           grid-router-Default_Router-8508.log
|       |
|       \---secure
|               https.ks
|               https.ts
|               InforIONGrid.der
|               InforIONGrid.ks
|               server.key
|               server.ks
|       bootstrap-2516.log
|       bootstrap-2532.log
|       bootstrap-2544.log
|       bootstrap-2552.log
|       bootstrap-2568.log
|       bootstrap-2588.log
|       bootstrap-2732.log
|       bootstrap-8144.log
|       installation_20170509124513914.log
|       installation_20170518165426295.log
|       service-2516.log
|       service-2532.log
|       service-2544.log
|       service-2552.log
|       service-2568.log
|       service-2588.log
|       service-2732.log
|       service-8144.log
|       service_out-2516.log
|       service_out-2532.log
|       service_out-2544.log
|       service_out-2552.log
|       service_out-2568.log
|       service_out-2588.log
|       service_out-2732.log
|       service_out-8144.log
|   |   bootstrap-daemon-1.2.4.jar
|   |   commons-daemon-1.0.15.jar
|   |
|   +---1.13.77
|   |       bcmail-jdk16-1.45.jar
|   |       bcprov-jdk16-1.45.jar
|   |       bootstrap-core-1.13.77.jar
|   |       grid-core-1.13.77.jar
|   |       grid.commons-dbcp2-2.0.1.jar
|   |       grid.httpclient-4.2.6.jar
|   |       grid.liquibase-2.0.5.jar
|   |       jackson-core-asl-1.9.12.jar
|   |       jackson-mapper-asl-1.9.12.jar
|   |       javax.servlet-api-3.1.0.jar
|   |       jna-3.3.0-platform.jar
|   |       jna-3.3.0.jar
|   |       maven-shared-utils-0.4.jar
|   |       windowsjnasecurity-1.0.4.jar
|   |
|   +---amd64
|   |       service-wrapper-
|   |
|   \---x86
|           service-wrapper-
|   \---1.13.77
|       +---jaxrs1Resources
|       |       grid-jaxrs1-1.13.77.jar
|       |       jackson-core-asl-1.9.2.jar
|       |       jackson-jaxrs-1.9.2.jar
|       |       jackson-mapper-asl-1.9.2.jar
|       |       jackson-xc-1.9.2.jar
|       |       jersey-core-1.18.1.jar
|       |       jersey-json-1.18.1.jar
|       |       jersey-multipart-1.18.1.jar
|       |       jersey-server-1.18.1.jar
|       |       jersey-servlet-1.18.1.jar
|       |       mimepull-1.9.3.jar
|       |
|       +---jaxrs2Resources
|       |       aopalliance-repackaged-2.2.0.jar
|       |       grid-jaxrs2-1.13.77.jar
|       |       hk2-api-2.2.0.jar
|       |       hk2-locator-2.2.0.jar
|       |       hk2-utils-2.2.0.jar
|       |       jackson-core-asl-1.9.13.jar
|       |       jackson-jaxrs-1.9.13.jar
|       |       jackson-mapper-asl-1.9.13.jar
|       |       jackson-xc-1.9.13.jar
|       |       javassist-3.18.1-GA.jar
|       |       javax.annotation-api-1.2.jar
|       |       javax.inject-2.2.0.jar
|       |
|       |       jersey-client-2.7.jar
|       |       jersey-common-2.7.jar
|       |       jersey-container-servlet-2.7.jar
|       |       jersey-container-servlet-core-2.7.jar
|       |       jersey-guava-2.7.jar
|       |       jersey-media-json-jackson-2.7.jar
|       |       jersey-media-multipart-2.7.jar
|       |       jersey-server-2.7.jar
|       |       mimepull-1.9.3.jar
|       |       osgi-resource-locator-1.0.1.jar
|       |       validation-api-1.1.0.Final.jar
|       |
|       +---licenses
|       |   +---asm
|       |   |       license.txt
|       |   |
|       |   +---bcprov-jdk16
|       |   |       license.txt
|       |   |
|       |   +---core
|       |   |       license.html
|       |   |
|       |   +---cxf
|       |   |       license.txt
|       |   |
|       |   +---httpcore
|       |   |       license.txt
|       |   |
|       |   +---jetty-package
|       |   |       license.txt
|       |   |
|       |   +---jna
|       |   |       license.txt
|       |   |
|       |   +---jquery
|       |   |       license.txt
|       |   |
|       |   +---jquery-hashchange
|       |   |       license.txt
|       |   |
|       |   +---jsp-2.1-glassfish
|       |   |       license.txt
|       |   |
|       |   +---neethi
|       |   |       license.txt
|       |   |
|       |   +---servlet-api
|       |   |       license.txt
|       |   |
|       |   +---timepicker
|       |   |       license.txt
|       |   |
|       |   +---wsdl4j
|       |   |       license.txt
|       |   |
|       |   +---wstx-asl
|       |   |       license.txt
|       |   |
|       |   +---xml-resolver
|       |   |       license.txt
|       |   |
|       |   +---xmlbeans
|       |   |       license.txt
|       |   |
|       |   \---XmlSchema
|       |           license.txt
|       |
|       +---monitorResources
|       |       activation-1.1.jar
|       |       antlr-2.7.7.jar
|       |       antlr-3.3.jar
|       |       antlr-runtime-3.3.jar
|       |       commonj.sdo-2.1.1.jar
|       |       commons-math3-3.0.jar
|       |       decision-trees-1.0.2.jar
|       |       drools-compiler-5.4.0.Final.jar
|       |       drools-core-5.4.0.Final.jar
|       |       ecj-3.5.1.jar
|       |       eclipselink-2.5.1.jar
|       |       grid-monitor-1.13.77.jar
|       |       grid-monitor-impl-1.13.77.jar
|       |       grid-monitor-linux-1.13.77.jar
|       |       grid-monitor-wmi-1.13.77.jar
|       |       groovy-all-2.0.0.jar
|       |       javax.persistence-2.1.0.jar
|       |       joda-time-2.0.jar
|       |       jsr166-1.7.0.jar
|       |       knowledge-api-5.4.0.Final.jar
|       |       knowledge-internal-api-5.4.0.Final.jar
|       |       mail-1.4.jar
|       |       mvel2-2.1.0.drools16.jar
|       |       ojalgo-31.0.jar
|       |       stringtemplate-3.2.1.jar
|       |
|       +---resources
|       |       bcmail-jdk16-1.45.jar
|       |       bcprov-jdk16-1.45.jar
|       |       grid-core-1.13.77.jar
|       |       grid.commons-dbcp2-2.0.1.jar
|       |       grid.httpclient-4.2.6.jar
|       |       grid.liquibase-2.0.5.jar
|       |       javax.servlet-api-3.1.0.jar
|       |       jna-3.3.0-platform.jar
|       |       jna-3.3.0.jar
|       |       linked-binaries-1.13.77.jar
|       |       maven-shared-utils-0.4.jar
|       |
|       +---services
|       |   \---log
|       |           slf4j-api-1.7.5.jar
|       |           slf4j-grid-1.13.77.jar
|       |
|       +---tools
|       |   \---grid-cli
|       |           grid-cli-1.13.77.jar
|       |           jackson-core-asl-1.9.13.jar
|       |           jackson-mapper-asl-1.9.13.jar
|       |           jcommander-1.32.jar
|       |
|       +---webAppResources
|       |       asm-4.1.jar
|       |       asm-commons-4.1.jar
|       |       asm-tree-4.1.jar
|       |       commons-fileupload-1.2.2.jar
|       |       grid-webapp-1.13.77.jar
|       |       javax-websocket-client-impl-9.1.1.v20140108.jar
|       |       javax-websocket-server-impl-9.1.1.v20140108.jar
|       |       javax.annotation-api-1.2.jar
|       |       javax.el-3.0.0.jar
|       |       javax.servlet.jsp-2.3.2.jar
|       |       javax.servlet.jsp-api-2.3.1.jar
|       |       javax.servlet.jsp.jstl-1.2.0.v201105211821.jar
|       |       javax.websocket-api-1.0.jar
|       |       jetty-annotations-9.1.1.v20140108.jar
|       |       jetty-continuation-9.1.1.v20140108.jar
|       |       jetty-http-9.1.1.v20140108.jar
|       |       jetty-io-9.1.1.v20140108.jar
|       |       jetty-jndi-9.1.1.v20140108.jar
|       |       jetty-jsp-9.1.1.v20140108.jar
|       |       jetty-plus-9.1.1.v20140108.jar
|       |       jetty-schemas-3.1.M0.jar
|       |       jetty-security-9.1.1.v20140108.jar
|       |       jetty-server-9.1.1.v20140108.jar
|       |       jetty-servlet-9.1.1.v20140108.jar
|       |       jetty-servlets-9.1.1.v20140108.jar
|       |       jetty-util-9.1.1.v20140108.jar
|       |       jetty-webapp-9.1.1.v20140108.jar
|       |       jetty-xml-9.1.1.v20140108.jar
|       |       org.apache.taglibs.standard.glassfish-1.2.0.v201112081803.jar
|       |       org.eclipse.jdt.core-3.8.2.v20130121.jar
|       |       websocket-api-9.1.1.v20140108.jar
|       |       websocket-client-9.1.1.v20140108.jar
|       |       websocket-common-9.1.1.v20140108.jar
|       |       websocket-server-9.1.1.v20140108.jar
|       |       websocket-servlet-9.1.1.v20140108.jar
|       |
|       +---webServiceResources
|       |       asm-3.1.jar
|       |       commons-logging-1.1.1.jar
|       |       cxf-api-2.7.5.jar
|       |       cxf-rt-bindings-soap-2.7.5.jar
|       |       cxf-rt-bindings-xml-2.7.5.jar
|       |       cxf-rt-core-2.7.5.jar
|       |       cxf-rt-databinding-jaxb-2.7.5.jar
|       |       cxf-rt-databinding-xmlbeans-2.7.5.jar
|       |       cxf-rt-frontend-jaxws-2.7.5.jar
|       |       cxf-rt-frontend-simple-2.7.5.jar
|       |       cxf-rt-management-2.7.5.jar
|       |       cxf-rt-transports-http-2.7.5.jar
|       |       cxf-rt-ws-addr-2.7.5.jar
|       |       cxf-rt-ws-policy-2.7.5.jar
|       |       cxf-rt-ws-rm-2.7.5.jar
|       |       cxf-rt-ws-security-2.7.5.jar
|       |       ehcache-core-2.5.1.jar
|       |       geronimo-javamail_1.4_spec-1.7.1.jar
|       |       grid-ws-1.13.77.jar
|       |       neethi-3.0.2.jar
|       |       stax2-api-3.1.1.jar
|       |       woodstox-core-asl-4.2.0.jar
|       |       wsdl4j-1.6.3.jar
|       |       wss4j-1.6.10.jar
|       |       xml-resolver-1.2.jar
|       |       xmlbeans-2.6.0.jar
|       |       xmlschema-core-2.0.3.jar
|       |       xmlsec-1.5.4.jar
|       |
|       \---webStartResources
|               AppUI.jnlp
|               grid-core-1.13.77.jar.pack.gz
|               Infor48x48.png
|       client.ks
|       admin-ui.jar
|       application-deployer.jar
|       certificates.jar
|       change-db-password.jar
|       change-jdk.jar
|       grid-cli.jar
|       log-viewer.jar
|       scripting-client.jar
    |   uninstall.cmd
    |   uninstall.jar

Future work

Next, I may:

  • Installing a Grid silently with izpack XML
  • Generate secure\server.key with OpenSSL
  • Setup an Administrative Router
  • Setup a Grid Agent
  • Setup a Grid Launcher
  • Setup a Grid Bootstrap
  • Install session providers
  • Install applications
  • Install GDBC
  • Install the Grid on Linux and PostgreSQL


That was an illustration of the Infor ION Grid bundled installer which is internal only and intuitive.

Related posts

Building an Infor Grid Lab – Part 3

I am building an Infor ION Grid laboratory manually without LifeCycle Manager (LCM) for my learning purposes. In part 2, I had made the installation using cryptographic keys taken from an existing Grid installation. Today, I will create new keys.


The Grid uses TLS to ensure privacy, authentication, and integrity of communication within the Grid. That involves asymmetric cryptography, public/private key pairs, key exchange, digital certificates, digital signatures, symmetric keys, ciphers, etc.

Thankfully the Grid automates most of it. It uses the Java Cryptography Extension (JCE), the Bouncy Castle Crypto APIs, and 2048 bit RSA key pairs. The key material is unique to each installation.


The Infor Documentation Infocenter has an Infor ION Grid Security Administration Guide:


The Infor documentation that is publicly available covers the default cryptographic properties of the Grid such as algorithms, providers, cipher suites, block cipher modes of operation, hashing functions, padding, key length, paths, file names, etc.; the Internet covers cryptography in general; and I am not revealing any secrets; therefore, I am revealing no more information than what is already available publicly. Besides, revealing cryptographic properties does not reveal any secrets, therefore Infor is not revealing any secrets either. Besides, the default properties can be changed to suit our needs. The security of a cryptosystem depends not on the knowledge of its cryptographic properties, but on its implementation and on the security of the secret key material. Thus, it is important you keep your systems up-to-date, and keep your secret key material secure. In doubt, read Auguste Kerckhoffs’s principle, “il faut qu’il puisse sans inconvénient tomber entre les mains de l’ennemi” or Claude Shannon’s maxim, “we shall assume that the enemy knows the system being used.”

Key material

For a minimalist Grid installation, we need the following four files, they are unique to each installation:

For the Grid, we need these files, where the file names must match the Grid name, e.g. Grid:

  • Grid.ks: this is the Java keystore for the Grid. It contains the Grid’s public/private key pair, and the Grid self-signed certificate which will be the root certificate authority (CA) to sign other keys.
  • (optional): this is the clear text password for both keystore and private key.

For each host, we need these files, where the file names are server:

  • server.ks: this is the Java keystore for the host. It contains the host’s public/private key pair, and the host certificate signed by the Grid.
  • this is the clear text password for both keystore and private key.
  • server.key: this is a symmetric key, signed and encrypted, used to encrypt/decrypt protected Grid properties.

In a production environment, keep all these files secure.

Console tool

The Grid has a console tool that automatically creates the key material:

In addition to the console tool, I will show the equivalent command using the Java keytool, and I will inspect the result with KeyStore Explorer.

1. Create Grid material

Use this command to create new key material for the Grid (replace the parameter values with your values, and use a strong password):

java ^
 -cp resources\grid-core.jar;resources\bcprov-jdk16.jar;resources\bcmail-jdk16.jar ^ ^
 -create=gridcert ^
 -gridname Grid ^
 -gridpassword password123 ^
 -gridkeystore secure

It produces these two files:

  • Grid.der
  • Grid.ks

Note: Grid.der is the root CA that typically system administrators will push to the users computers, and then those computers will automatically trust the certificates of M3, Smart Office, etc.

Note: Unfortunately, the command does not automatically generate a strong password for this keystore, which leaves it vulnerable to user choice.

The Grid certificate has the following extensions:

  • Basic Constraints: Subject is a CA, Path Length Constraint: 1
  • Subject Key Identifier
  • Key Usage: Digital Signature, Certificate Signing
  • Extended Key Usage: TLS Web Server Authentication, Code Signing, TLS Web Client Authentication

Alternatively, instead of the console tool, we can use the Java keytool:

keytool ^
 -genkeypair ^
 -keyalg RSA ^
 -keysize 2048 ^
 -sigalg SHA256WITHRSA ^
 -dname cn=Grid ^
 -ext BasicConstraints=ca:true,pathlen:1 ^
 -ext KeyUsage=digitalSignature,keyCertSign ^
 -ext ExtendedkeyUsage=serverAuth,codeSigning,clientAuth ^
 -validity 90 ^
 -keypass password123 ^
 -keystore secure\Grid.ks ^
 -storepass password123

Then, we need to do some export/import to add the certificate as a separate entry:

keytool ^
 -exportcert ^
 -file secure\Grid.der ^
 -keystore secure\Grid.ks ^
 -storepass password123
keytool ^
 -changealias ^
 -alias mykey ^
 -destalias grid_key ^
 -keypass password123 ^
 -keystore secure\Grid.ks ^
 -storepass password123
keytool ^
 -noprompt ^
 -importcert ^
 -alias mykey ^
 -file secure\Grid.der ^
 -keypass password123 ^
 -keystore secure\Grid.ks ^
 -storepass password123
keytool ^
 -changealias ^
 -alias mykey ^
 -destalias grid_cert ^
 -keypass password123 ^
 -keystore secure\Grid.ks ^
 -storepass password123

2. Create host material

Use this command to create new key material for the host (replace the parameter values with your values, and add as many roles and addresses as needed for this host):

java ^
 -cp resources\grid-core.jar;resources\bcprov-jdk16.jar;resources\bcmail-jdk16.jar ^ ^
 -create=hostcert ^
 -gridname Grid ^
 -gridpassword password123 ^
 -hostname localhost ^
 -gridkeystore secure ^
 -hostkeystore secure ^
 -role grid-admin ^
 -address localhost ^
 -address ::1 ^
 -address ^
 -address ^

It produces these two files:

  • server.ks

Note: Fortunately, the command automatically generates a strong password for this keystore.

The host certificate has extensions for the role (e.g. grid-admin), for the host actor (SYSTEM), for the IP addresses and hostnames:

Alternatively, instead of the console tool, we can use the Java keytool. But it is tricky for we have to add the certificate extensions in hexadecimal. The IANA enterprise number for Lawson Software (Infor) is 10105. The OID names can be found in the OID repository. Note: Thomas Fanto registered child OID 238 for the Grid runtime information in 2009, but somehow the console tool uses child OID 237 instead, which is not reserved. Anyway, dump the OID values as hexadecimal (e.g. grid-admin is 677269642D61646D696E, and SYSTEM is 53595354454D). Prefix them with the ASN.1 UTF8String tag byte of 0x0C to encapsulate them as a UTF-8 String and with the byte length in HEX (e.g. grid-admin is 10 bytes long which is 0x0A, and SYSTEM is 6 bytes long which is 0x06). For the sequences, prefix them with the SEQUENCE tag byte of 0x30 and with the sequence byte length (e.g. 9+3+9+11+2*4 = 40 = 0x28).

keytool ^
 -genkey ^
 -alias localhost_key ^
 -keyalg RSA ^
 -keysize 2048 ^
 -sigalg SHA256WITHRSA ^
 -dname cn=localhost ^
 -ext ^
 -ext ^
 -ext ^
 -validity 90 ^
 -keypass password123 ^
 -keystore secure\server.ks ^
 -storepass password123

Then, we need to create a certificate signing request (CSR) for the host certificate, sign it with the Grid root CA, and import the resulting chain to the keystore:

keytool ^
 -certreq ^
 -alias localhost_key ^
 -keyalg SHA256WITHRSA ^
 -file secure\server.csr.txt ^
 -keystore secure\server.ks ^
 -storepass password123
keytool ^
 -gencert ^
 -infile secure\server.csr.txt ^
 -outfile secure\server.der ^
 -keystore secure\Grid.ks ^
 -storepass password123 ^
 -alias grid_key ^
 -ext BC=0
keytool ^
 -importcert ^
 -noprompt ^
 -trustcacerts ^
 -alias grid_key ^
 -file secure\Grid.der ^
 -keystore secure\server.ks ^
 -storepass password123
keytool ^
 -importcert ^
 -trustcacerts ^
 -alias localhost_key ^
 -file secure\server.der ^
 -keystore secure\server.ks ^
 -storepass password123

Then, save the keystore password with:

echo | set /p="password123" > secure\

3. Create symmetric material

Use this command to create new symmetric key material (replace the parameter values with your values):

java ^
 -cp resources\grid-core.jar;resources\bcprov-jdk16.jar;resources\bcmail-jdk16.jar ^ ^
 -create=symkey ^
 -gridname Grid ^
 -gridkeystore secure ^
 -gridpassword password123 ^
 -symkeypath secure ^
 -hostkeystore secure ^
 -hostname localhost

It produces this file:

  • server.key

It is used to encrypt/decrypt protected Grid properties such as passwords:

Alternatively, we can generate the server.key in Java by taking the Grid certificate’s distinguished name in ASN.1 DER encoded form, signing it with the Grid’s private key, and encrypting it with the host’s public key, but I am not allowed to show the source code for that, and I am struggling with replicating it with the OpenSSL RSA utility and AES encryption. So use the Grid command tool above to generate server.key.


We now have the new unique necessary and sufficient cryptographic key material for a minimalist Grid, and the Grid successfully validates it:

successfully initialized secret key
successfully initialized server keystore


I collected all the commands in my GitHub at keys.cmd.

Future work

Next time, I would like to:

  • Generate the symmetric key with OpenSSL
  • Continue researching security vulnerabilities
  • Use the new Grid installer
  • Setup an administrative router
  • Setup session providers
  • Install applications
  • Install the Grid on Linux and PostgreSQL


That was an illustration of how to manually create – for learning purposes – new cryptographic keys for a minimalist installation of the Infor ION Grid using the built-in tools, and alternatively using the Java keytool. I am learning so I probably missed a few things. Thankfully the Grid console tool automates most of it.

That’s it! Congratulations if you’ve made it so far.

Related posts