Tips & tricks for installing and running IBM products

    Binance referal code 10%

    Tom Bosmans  19 April 2021 15:44:39
    Use this referal code to get 10% commission on crypto orders, on binance.

    content-security-policy with nonce in ISAM/ISVA for junction cookie

    Tom Bosmans  16 March 2021 15:16:18


    I was trying to implement CSP in ISAM, specifically to add nonce protection for my client-side javascript code.
    This is specifically for Infomap authentication policies.

    The mechanism is as follows :
    - add a header that includes a nonce (a random value that is different for every page)
    - add the nonce to the script tags

    I implemented this by generating a random value in the mapping rule for the infomap.  I choose a 13 characters random string for no particular reason.  Ideally, you'd make sure the nonce is unique and you would also verify it's unique (server-side). 

    // generate a nonce
    var templateNonce = OAuthMappingExtUtils.generateRandomString(13);
    macros.put("@TEMPLATENONCE@", templateNonce);

    Then , in the html page for the Infomap, I add a header:

    templateContext.response.setHeader("Content-Security-Policy","default-src 'self'; script-src 'nonce-"+templateContext.macros["@TEMPLATENONCE@"]+"';");

    Every script tag then needs to include a nonce.

    script type="text/javascript" nonce="@TEMPLATENONCE@"


    To accomodate the piece of code that's added for the IV_JCT cookie, you can generate a sha256 hash value.

    SCRIPT type="text/javascript"
    document.cookie = "IV_JCT=%2Fmga; path=/; secure";

    The hash value for the piece of javascript code is the same for everyone using ISAM, so you could add it to all your WebSeal junctions (if they use -j).

    To generate it, you need to copy all the code (including comments, whitespace, tabs, carriage returns and what else) , put it in a file and generate the hash:

    cat test.js | openssl sha256 -binary | openssl base64


    Precede it with "sha256-" and add to the header:

    templateContext.response.setHeader("Content-Security-Policy","default-src 'self'; script-src 'nonce-"+templateContext.macros["@TEMPLATENONCE@"]+"' 'sha256-1ICPqU0KcyH0XeAruG+H5+h7JCqchnCGp1SD7g5JON8=';");

    JSON.stringify in ISAM

    Tom Bosmans  30 October 2020 14:32:19
    When using JSON.stringify, I get a lot these errors:

    Caused by: org.mozilla.javascript.EvaluatorException: Access to Java class "java.lang.reflect.Constructor" is prohibite

    This was driving me crazy, because it seemed to be very random.

    Now thinking about it a bit more, it occured to me that the reason for this is that JSON.stringify needs to operate on a javascript object.
    You don't always have a String object , though.  So if you try to do that on a string literal, it throws the error above.

    Sometimes you can resolve this by first using JSON.parse, but that does not always work either.

    The solution is simple:  just add an explicit cast to String to your string literal :


    Fedora 31 and Notes Client

    Tom Bosmans  26 March 2020 10:04:04
    My Notes client failed to start on my new Fedora Linux with an error "error while loading shared libraries: cannot open shared object file: No such file or directory "

    The shared library is however included in the /opt/ibm/notes/lib directory.

    So I just added that directory to the /etc/ configuration :


    Then , run

    sudo ldconfig

    I probably should have created a separate file to put into /etc/ , but the end result is the same.
    And it works fine now.  Not sure if I have now introduced other problems though :-)

    ISAM Do not use LACP Bonding on the management interface

    Tom Bosmans  15 October 2019 14:31:42
    The isam appliances allow you to use bonding or network aggregation (

    This is a good idea for the "data" interfaces, IF
    - you are using the hardware appliance
    - have only a single network you connect to (single subnet)
    - you have a need for higher total throughput
    - your network switch supports LACP (         802.3ad )

    It is also possible to setup Dynamic Link Aggregation (lacp) for the management interfaces - although you can use the interfaces on the hardware appliance for whatever you want them to do, the first 2 are marked on the box as "management" .  
    It sounded like a good idea to do this - create a bond between the first 2 interfaces (albeit a bit overkill, because there is no need for the higher throughput on the management interfaces).

    But it turns out, it can be a bad idea in recovery situations (depending on how close you are with your network team ).  

    To activate LACP , you first have to configure the bonding configuration on the appliance and then change the network ports on the switch you connect to from static ports to aggregate ports (terminology may vary).
    ISAM will then briefly disconnect and reconnect, with a working bonding interface.

    So far , so good.  

    The problem begins when you run into problems and want to reset the appliance (of you don't have problems, you just want to reset the appliance).

    The appliance then goes back to a default configuration, where the first interface tries to obtain an ip address over dhcp.

    This fails, because the switch is still configured for LACP , and not for a simple static port.  The appliance does not get an ip address.

    No worries, you can connect to the appliance using the serial console interface (a connector is included with the appliance).  You can then use putty or securecrt or some terminal program to open a serial connection to the appliance.

    Now for the problem :   the console interface does not provide possibility to configure bonding on the interfaces.  This means you cannot get the management interface up and running , so you cannot access the LMI.

    Note that this not have to be a huge problem, depending on your organization.  
    - you can activate/configure another interface as management interface, where you can connect to the LMI on
    - you can ask your network team to de-activate LACP on the switch
    - you could use a different type of bonding/link aggregation , that works with normal static ports (I have not investigated other modes in detail)

    But in large organizations, getting every part of it to do exactly what you want at the right time can be challenging .  The simpler solution is to not use bonding at all for the management interface, and keep the second management interface as a backup (unconfigured).  In case of failure of the first interface, you can activate the second interface using the serial console.

    ISAM SPNEGO configuration

    Tom Bosmans  11 September 2019 09:18:07
    SPNEGO challenge when reverse dns lookup does not match the requested hostname
    The challenge with SPNEGO or rather the Kerberos implementation on ISAM is that it depends on reverse DNS lookups (on the ip address) by default to verify that the hostname you want to connect to.
    This means that even though you have keytabs for the hostname you connect to, the SSO will fail if the reverse dns lookup returns another hostname for that IP address.

    Typically , you'll see errors in your log similar to this :

    483       2019-09-10-17:13:53.304+02:00I----- 0x30923082 webseald ERROR bst general amstli.c 2764 0x7f55c50de700 -- HPDST0130E   The security service function gss_accept_sec_context returned the error 'Request ticket server HTTP/ not found in keytab (ticket kvno 3)' (code 0x96c73a23/-1765328349).

    2 solutions exist.  The first one, changing DNS , is sometimes difficult to explain (because not all Kerberos implementations are equal , and SPNEGO works for other servers, the client may not understand why it's necessary).
    So there is a second solution, by using some of the newer kerberos parameters (NEW in Kerberos 1.10).
    So this may not be possible on your ISAM version !  I am using 9.0.6 in this case, which comes with Kerberos 1.12 .


    The old way to resolve this, is to make sure the reverse dns lookup for your ip address returns the hostname of your WebSeal proxy (the one users connect to).  In this way, you just need the 1 SPN in your keytab.

    Configuration with additional keytabs

    You need to have a keytab that contains the hostname for the url the user accesses, and the hostname for all backend servers (ie. what's in the reverse dns lookup and A records) as SPN.
    You can combine them in ISAM.

    Then , you can add these 2 parameters to the Defaults section in Kerberos configuration.  Rdns is false does not really seem to have a lot of effect, to be honest, but ignore_acceptor_hostname is the golden ticket here.

    ignore_acceptor_hostname = true
    rdns = false

    Image:ISAM SPNEGO configuration


    Virtual host junctions and federation on ISAM

    Tom Bosmans  9 August 2019 10:15:40
    I recently struggled with a setup of an OIDC federation setup on IBM Security Access Manager.

    Instead of using standard, transparant path junctions, I was now using Virttual Host Junctions.
    And I could not get the federation to work.

    After a while, the penny dropped , and I realised that the /mga junction is not avaiable in the Virtual host junction.  Which I should have realised from the beginning of course...

    So there's 2 options

    match-vhj-first and session sharing

    The "match-vhj-first " is set to yes by default, and this means that you cannot access the /mga junction (and hence cannot kick off the federation etc).  Set this parameter to "false", and the /mga junction is available in the Virtual Host Junction.
    For federation, you may get away with just that change, as long as you setup seperate federations per virtual host.

    See this older article by Philip Nye on the related topic of Context Based Access control:

    Single federation per Reverse Proxy instance and session sharing

    For the OIDC Federation, I opted for a slightly different approach though.  There is no real need to change the default "match-vhj-first" setting.  What is important in setting up Federations, is that the hostnames used are constant throughout the OIDC federation flow.  And by setting up a "master" federation partner, I can kick off federation on all virtual host junctions on the same reverse proxy - no need to change anything in the federation setup when adding a new virtual host junction.

    Webseal configuration

    In the Webseald.conf configuration file , I set fhe following parameters:

    match-vhj-first = yes

    domain = mydomain.tld

    shared-domain-cookie = yes
    tcp-session-cookie-name = PD-H-SESSION-ID-rp1
    ssl-session-cookie-name = PD-S-SESSION-ID-rp1

    This enables the sharing of the webseal session between the junctions (including virtual host junctions) within a reverse proxy (webseal).
    This is not necessary if you use DSC , and this does not work if you don't have a single "cookie domain" .


    Key here is to have a single OIDC Federation set up against the "base" webseal reverse proxy, eg. the ip address or hostname you used to setup the reverse proxy.

    The URLs to use in the Federation components (  redirectUriPrefix, providerId ) need to point to that base webseal reverse proxy.
    Make sure to not mix the hostnames here, because then the Federation will fail.

    If you enabled local-response-redirect, you can then use the following kickoff URL to start the Federation.

    local-response-redirect-uri = https://mywebseal.mydomain.tld/mga/sps/oidc/rp//kickoff/

    After a successful federation, thanks to the session sharing, you are also logged into your Virtual Host Junction.

    The only correct way to setup the ISAM RTE with basic users for the UserLookupHelper

    Tom Bosmans  2 August 2019 09:03:41
    I've been struggling a bit to get the UserLookupHelper work correctly in a custom authenticatiion mechanism I am building for Username / Password authentication.  I am using the ISAM "all-in-one" deployment pattern , that is becoming quite popular these days.  This basically consists of identical ISAM appliances that have all functions (reverse proxy, AAC, federation) and operate independently.  The environment provides high availability by adding identical appliances (typically using automation).  The identital appliances do share some resources, notably the High Volume database and the federated ldap repositories.
    This pattern also relies on using Basic users in Federated repositories.

    The problem I came across is that in this setup, the UserLookupHelper is very difficult to get to working correctly using the ISAM RTE.
    Recentlly a technote was published ( ) , but that only describes what is causing the problem, not the detailed steps to resolve or avoid it.

    I tried various workarounds, and a workaround that is suggested a lot is to use an LDAP connection to (1 of the) federated repositories.   While that may work for you, it is NOT what I want - I want to use ALL of the configured federated directories .

    In the end , I found that a simple recommendation in setting up ISAM can avoid all these problems, so I'll start with that


    In the "all-in-one" deployment pattern, with Basic users in remote ldap repositories, there is only 1 correct ISAM Runtime server setup : Local Policy Server/Remote LDAP Server (lmi / ssl) .

    When initially configuring the Runtime environment, select a local Policy server and a remote LDAP server pointing to your embedded ldap (instead of local Policy Server/local LDAP server).
    Configure the connection to your local embedded LDAP using:
    - hostname: your appliance's LMI hostname
    - port: 636
    - enable ssl

    Select a keystore that contains the CA certificates of ALL the federated repositories you want to connect to and also the CA for your embedded ldap.

    The embedded LDAP does not listen on port 636 on the localhost/loopback/ interface !

    You need to make 2 small modification afterwards to ldap.conf


    host =

    port = 389
    -> port = 636

    ssl-port = 636

    And under [bind-credentials], you must add the bind-dn and bind-pwd for a user that can read your embedded ldap (eg. the root user), like this :


    bind-dn = cn=root,secAuthority=Default

    bind-pwd = your-root-password-i-hope-it-is-not-passw0rd

    See the technote for the explanation.

    This setup will enable you to use :
    - UserName / Password AAC Authentication mechanism using the ISAM RTE
    - the UserLookupHelper connecting to ISAM RTE (and all the configured federated repositories with basic users)
    - the SCIM prerequisites

    Errors & what does not work

    UserLookupHelper does not work

    So your userlookuphelper does not work in your setup with Basic Users - it cannot contact the ISAM RTE or it cannot contact the federated repositories you defined.

    You MUST use the ISAM RTE way of initialisation, that is the only way that will work for Federated Repostitories with Basic users !
    You MUST have set the bind-dn and bind-pwd under [bind-credentials] in ldap.conf .

    Following snippet shows how to correctly initialize the UserLookupHelper, in this case for a username that is submitted in a form.

    var username = context.get(Scope.REQUEST, "urn:ibm:security:asf:request:parameter", "username");

    var userLookupHelper = new UserLookupHelper();

    // Use ISAM RTE with false

    // configure bind-dn and bind-pw in ldap.conf

    // need to have all certificates in the keystore that is used in ldap.conf (to ad and to rte)

    // set 636 as non-ssl port

    // MUST use false, because this is the only way Basic Users and Federated repositories will work

    // check here

    reportmsg("Init ... [" + username + "]",false);

    if( userLookupHelper.isReady() ) {

      IDMappingExtUtils.traceString("User Lookup Helper is ready for  ... [" + username + "]");

      var user = userLookupHelper.getUser(username);


    But this likely does not work for you.

    Enable tracing

    When you start working on your InfoMap with UserLookupHelper, you probably want to enable tracing .
    Go to "Secure Access Control" , "Global Settings" , "Runtime Parameters", and go the "Runtime Tracing" tab

    Image:The only correct way to setup the ISAM RTE with basic users for the UserLookupHelper
    Add this trace specification:


    The trace.log you can then view in "Monitor / Application Logs" (https://lmi/isam/application_logs)  
    Under access_control/runtime/trace.log

    Errors indication the problem

    If you use Basic users in LDAP directories that require SSL, and you have setup your ISAM with local Policy Server/local LDAP, you will likely see errors like this :
    The runtime trace shows that the connection uses :389:readwrite:5.

    Other errors may look like this:

    [7/31/19 11:48:41:962 CEST] 000000bd id=00000000                I getUser com.tivoli.pd.rgy.exception.DomainNotFoundRgyException: HPDAA0266E   The Security Access Manager domain Default does not exist.

    or another typical one:

    com.tivoli.pd.rgy.exception.ServerDownRgyException: HPDAA0278E   None of the configured LDAP servers of the appropriate type for the operation can be contacted.

    Manually configuring ISAM

    So how do I fix this ?
    The root cause information is correct in the technote, but it does not fully explain how to fix the problem.
    Changing the port is only part of the solution, because the embedded LDAP server listens on port 636 of the management interface of the appliance by default, not on localhost. The administrator can choose a port other than the default by modifying the advanced tuning parameter wga.rte.embedded.ldap.ssl.port. The advanced tuning parameters are accessed through Manage System Settings > Advanced Tuning Parameters. After you modify this advanced tuning parameter, you must restart the Security Access Manager runtime environment for the change to take effect.

    Update ldap.conf

    Go to "Secure Web Settings/Manage/Runtime Component" and navigate to "Manage/Configuration Files/ldap.conf"
    Set the host to the ip address or hostname of your LMI, it cannot be set to
    Set the port to the same value as ssl-port (by default, 636.  To change it, see the previous paragraph).


    host =

    port = 636

    ssl-port = 636

    ssl-keyfile = yourkeystore.kdb

    The keystore you set here must contain all the CA certificates for the federated ldap.  It's likely you have a value there already if you configured Federated Directories already.
    In the default setup, you can export the server certificate from the keystore embedded_ldap_keys , and import it as a CA in "yourkeystore.kdb" .

    Update the bind-credentials, with the username and password for a user that can access the embedded ldap (eg. cn=root)


    bind-dn = cn=root,secAuthority=Default

    bind-pwd = your-root-password-i-hope-it-is-not-passw0rd

    The ISAM runtime will restart after these changes.

    Update pd.conf

    Go to "Secure Web Settings/Manage/Runtime Component" and navigate to "Manage/Configuration Files/pd.conf"

    Edit the pdrte stanza.


    user-reg-type = ldap

    user-reg-server =

    user-reg-host =

    user-reg-hostport = 636

    Update user-reg-server with your lmi's hostname .  Note that you may have to add a hostrecord for your lmi !
    Update user-reg-host with your lmi's public ip address (in this example,
    Update user-reg-hostport to match the ssl port (default 636).

    In the ssl stanza, I enabled the TLS 1.1 and 1.2 versions.


    tls-v10-enable = no

    tls-v11-enable = yes

    tls-v12-enable = yes

    Update ivmgrd.conf

    Go to "Secure Web Settings/Manage/Runtime Component" and navigate to "Manage/Configuration Files/ivmgrd.conf"

    Enable ssl, and assign the keystore you used earlier.

    ssl-enabled = true

    ssl-keyfile = yourkeystore.kdb

    Update your reverse proxies

    The reverse proxies need to be instructed to connect over ssl.

    So for every reverse proxy, open the "Secure Web Settings"/"Reverse proxy" page, select the reverse proxies one by one and open the Configuration file (webseald.conf): "Manage/Configuration/Edit Configuration file"

    Find the [ldap] stanza and enable ssl :


    ssl-enabled = yes

    ssl-keyfile = yourkeystore.kdb

    ssl-keyfile-dn =

    The keystore you select here should contain the CA certificates for your embedded ldap , and the federated repositories.  
    Leave the ssl-keyfile-dn empty, unless you're using Mutual TLS.

    Restart the reverse proxy after these changes, and repeat for all your reverse proxies.

    If the reverse proxy fails to start, look in the msg__webseald-.log file (via Monitor/Reverse proxy log files) for errors indicating connection problems, for instance these:

    2019-08-01-14:43:48.521+02:00I----- 0x16B480C9 webseald ERROR rgy ira ira_handle.c 1489 0x7f95100a6840 -- HPDRG0201E   Error code 0x51 was received from the LDAP server. Error text: "Can't contact LDAP server".

    206       2019-08-01-14:43:48.525+02:00I----- 0x1354A0C0 webseald WARNING ivc general azn_maint.cpp 1136 0x7f94f1b8a700 -- HPDCO0192W   LDAP server has failed.

    Possible causes are missing ssl certificates , or errors in ip addresses and hostnames in your configuration.

    Look for messages like this: No trusted certificate found
    javax.naming.CommunicationException: simple bind failed: [Root exception is No trusted certificate

    Ansible configuration

    I've published Ansible playbook that performs all these tasks for you  
    It requires you have setup Ansible to work with ISAM (with the roles and the modules found here :

    Congratulations, now you should have a working environment

    You should now have a working environment :
    - you can use a standard pkmslogin to webseal with a basic user
    - the UserLookupHelper works correctly (init(false) or init()) and can locate basic users
    - the Username/Password mechanism can be configured
    - the SCIM setup can use the ISAM RTE

    A remark on Point of Contact configuration

    This setup is applicable if you have your ISAM appliance set to "Access Manager Credential" or "Access Manager Username and extended attributes".  It is not applicable for the External Users model (since you probably won't have basic users configured ).

    A remark LMI Configuration

    I noticed that if I set the LMI to only use TLSv1.2, the UserLookupHelper no longer works (or rather, that the ISAM RTE connection fails on an LMIRest call ).  So I re-enabled all TLS protocols for the LMI to resolve this.
    I need to get to the bottom of this, though .

    Alternative solution that will only work if your federated repositories do not use SSL

    If your federated repositories do not use SSL (which will never happen in real life, I hope), you can get away with a simpler change.   However, I do not recommend this

    So keep the runtime configured with local Policy Server and local LDAP.

    Open ldap.conf, and remove the ssl_keyfile parameter completely.  This will disable all SSL usage for your embedded ldap and for the federated repositories.

    Restart everything.

    Download the Brave browser and earn BAT tokens

    Tom Bosmans  27 April 2019 21:54:04
    The Brave browser promises better privacy ; and to directly pay the user for the ads you're looking at .
    The payout is in BAT (Basic Attention Tokens).

    I think this looks promising .

    Download the browser here :

    ISAM with VirtualBox and Vagrant for development

    Tom Bosmans  15 March 2019 13:36:28

    How to run ISAM on Virtual Box (and how to run it using Vagrant)

    The goal of this post is to get IBM Security Access Manager running on Virtual Box ( ), on my local machine.  This will allow me to test the Ansible playbooks I'm preparing locally before commiting them onto the Git repository.
    As a small addition, I have Vagrant , to quickly set up a new clean instance.  Vagrant does not really bring a whole lot of value in this case, because ISAM is a locked down appliance and Vagrant can't really do a lot.  

    Download the ISAM 9.0.6 ISO file

    Get the ISAM 9.0.6 (or whatever the most recent version is) from Passport Advantage.

    Setup Virtual Box

    Under File/Preferences/Network , create a new NAT network.
    You can just accept the defaults.

    Create new Virtual Machine

    Create a new virtual machine.  

    - Configure 2 NIC's, both configured with the Intel E1000 adapter
    Connect the first NIC to the NAT Network you prepared.
    Connect the second NIC to the Host-Only Network.

    - Configure Storage : create a new SCSI controller, with LSI Logic adapter
    Create a new disk, with a size of at least 8 GB (recommended is 100Gb)

    - Connect the CD/DVD to the ISO file you downloaded earlier with ISAM on it

    - Assign 2048 Mb of memory  

    - Disable Audio

    Advanced configuration for the Virtual Machine

    To run the ISAM appliance on Virtual Box, we need to trick it to think it's running on VMWare.

    Open a command prompt and navigate to the Virtual Box installation folder.
    Run the "list vms" command to get a list of your virtual machines.

    C:\Program Files\Oracle\VirtualBox>

    VBoxManage.exe list vms

    "isam905" {1c548e84-f7cd-4283-a36a-71843757d1af}

    Run the following command to “fake” Vmware .  Use the output of the previous command for the vm info.
    This is the "magic" command that makes everything work:

    VBoxManage setextradata "isam905" "VBoxInternal/Devices/pcbios/0/Config/DmiBIOSVendor"  "VMware Virtual Platform"

    These commands configure port forwarding for initial configuration:

    VBoxManage modifyvm "isam905" --natpf1 "guestssh,tcp,,2222,,22"

    VBoxManage modifyvm "isam905" --natpf1 "lmi,tcp,,4443,,443"

    Configure ISAM

    Start the vm and configure it.
    After initial booting from the dvd and installing the image, you must disconnect the dvd pointing to the iso file.

    Then reboot the machine again; and it should boot to the console .

    Access the LMI

    You can now access the LMI on

    The console is available by ssh on port 2222:

    ssh -p 2222 admin@

    Next steps

    I can now use Ansible to configure the ISAM vm, specifically :
    - perform first steps , activation etc.
    - configure the second interface on the Host Only adapter, so ISAM is accessible on a "normal" address as well (without port forwarding).

    Another thing I'm working on, is to use Vagrant to be able to rapidly start up a temporary ISAM appliance .