Sunday, August 13, 2017

IGI v ISIM v ISAM v ITDI

I've been writing this blogs for many years now and I typically use it as a means of recording snippets of information that ideally I would like to refer back to and snippets of information that I think others would be interested in.

So, what are you guys interested in?

Well, the beauty of running a blog like this for so long is that I get to see which posts are popular and which are not! I get to see which products you guys are using and abusing. And I can tell you that the popularity of these IBM security products can be easily ranked. In reverse order (by popularity):

IBM Security Identity Governance & Intelligence (IGI) is the new kid on the block so it is understandable that not many people are interested in what I have to say about IGI. Maybe, over time, this will change. Fingers crossed!

IBM Security Access Manager (ISAM) has been around forever but it seems that nobody is interested anymore. That's probably a sign that organisations have shifted their focus elsewhere and that federated security (which ISAM handles really well) is the way forward and freebie tools that are SAML and OpenID:Connect ready are preferable?

IBM Security Identity Manager (ISIM) has been around forever too, but it has always been a heavyweight beast of a product that requires significant investment and therefore is used by huge organisations only. I don't know how many ISIM customers there are out there, but I'm guessing it is a dwindling list given that IGI is seen as the long-term replacement.

And then we come to IBM Tivoli Directory Integrator (ITDI). Of all the things I've ever blogged about, it seems that TDI generates the most interest - and by a country mile! As an example, the last time I mentioned TDI, it managed to gather more than 300 times as many page requests as everything to do with IGI put together! One single post!

TDI is still a tool I go to on a daily basis. It is truly wonderful and flexible and easy to get to grips with. Maybe I should focus more on TDI topics?

In any case, I'd be interested to hear from whomever out there reads the stuff that I write. What topics would you like me to cover? What products do you think deserve focus? Do you still find any of this information worthwhile?

I still hope there are plenty of you IBM Security specialists out there helping to deliver a smarter, more secure planet.

Monday, July 24, 2017

IGI Custom Reports - Best Practice Guide

A short and sweet "quick tip" update only, I'm afraid. Anyone looking to settle down to a long read will be sorely disappointed as my time is precious and this topic doesn't deserve lengthy discussion.

Creating custom reports in IBM Security Identity Governance and Intelligence (IGI) is a multi-step process:

  • Create a SQL query to extract data
  • Create a "Report" to structure the data according to your needs
  • Assign the "Report" to a user community


What happens if you need to update your report to include an additional data element, however? Unfortunately, IGI (as of v5.2.2) does not afford you with the luxury of updating your SQL query to grab the additional data element without deleting the report. What a pain.

My solution? Don't bother.

Well... I say don't bother. What I mean is that there is no need to update the SQL query in-situ.

A better approach might be to create a new SQL query with the additional data element, create a new report as required and associate the new report to the same user community as the old report. The old report can remain in the system although disassociating it from the user community would seem to be a reasonable final step to take.

When I create a custom report, I like to follow these steps:

  • Create a SQL query to extract data and add a version number to the name, i.e. "Stephen's Query v1.0"
  • Create a "Report" to structure the data according to my needs and add a version number to the name, i.e. "Stephen's Report v1.0"
  • Assign the "Report" to a user community, i.e. IGI Users Called Stephen


When I need to update the report, I follow these steps:

  • Create a SQL query to extract data and add a version number to the name, i.e. "Stephen's Query v1.1"
  • Create a "Report" to structure the data according to my needs and add a version number to the name, i.e. "Stephen's Report v1.1"
  • Assign the "Report" to a user community, i.e. IGI Users Called Stephen
  • De-assign the "Old Report" from the user community


Of course, an added benefit is that it is much easier to "roll-back" to the previous version of the report if necessary and I didn't have to delete anything.

NOTE: I would frequently prefix all my custom reports with some identifier which helps me differentiate custom reports from the pre-packaged reports. For example, when providing services to ACME Inc, I may prefix all my reports with ACME and I would NEVER customise a pre-packaged report, but rather create a new custom-version of the report instead.

Wednesday, April 05, 2017

IGI Report Building

IBM Security Identity Governance is undoubtedly a powerful tool. However, the documentation supplied with the tool could certainly do with some improvement and there is a desperate need for a lot more "technotes" to help deployment consultants get the best value out of the tool.

As an example, IGI ships with almost 100 canned reports but one important report that seems to be missing is a report listing all the orphan/unmatched accounts within the system.

Generating such a report should be a breeze using IGI's Report Designer module. But here comes another "however". The documentation doesn't really give you any kind of clue as to how the underlying database schema has been put together and therefore it is difficult to understand which tables, attributes and values should be used to construct such a report. It also doesn't help that in some cases, the naming convention used is somewhat confusing.

That said, here is how you might construct a simple Orphan Accounts report.

Step 1 - Create Query
Create a new query called "Orphan Accounts"  with the following as the SQL Query:

select
  t.name as APPNAME,
  pwdm.code as USERID,
  pwdm.name as FIRSTNAME,
  pwdm.surname as LASTNAME,
  pwdm.email as EMAIL,
  pwdm.dn as DN,
  pwdm.lastlogin as LASTLOGIN
from
  #pmschema#.pwdmanagement pwdm
  left join #pmschema#.target t on pwdm.pwdcfg=t.pwdcfg
where
  pwdm.state > 0

This query pulls out the Application Name, User ID, First & Last Names, Email Address, DN and Last Login Date/Time for those accounts that are in an orphan/unmatched state. The STATE attribute having a value greater than 0 means that the account has not been matched to an identity.

Make sure that you you select the "Query Column" link at the bottom of the screen and click on IMPORT in order to be left with the following:


Step 2 - Create Report
Now, create a new report called "Orphan Accounts" using the query that you have just created.

Reorder the columns as necessary within the Columns tab. Under Additional Data, ensure that report output formats are selected. In this case, CSV and XSLX are great options.


Under the Localization tab, ensure the column names are assigned appropriate business friendly names.

Step 3 - Report Assignment
The report has now been built, but it needs to be made available to a set of users. Within the Report Designer, navigate to Configure > Assignment > Report/Dashboard -> Entitlement and select the report you have just created.

Now assign the user community to the report. When clicking on Add, you will be presented by a list of default administrative IT Roles rather than Business Roles. If you want to assign the report to a particular Business Role (i.e. Application Manager), then click on Filter, select Type and select Business Role to see a list of roles.

Once the report has been assigned to your business role, you can now log in to the Service Centre as a user with that Business Role entitlement and you will see the "Orphan Accounts" report available for execution.

Summary
Hopefully a comprehensive definition of the schema will be documented and made available at some point in the near future. Meanwhile, hacking around the SQL Query definitions that are provided out of the box is probably going to be your best option for constructing your own reports.

Monday, February 27, 2017

IGI Default Entitlements

Those of you who have downloaded the latest (and greatest) version of IBM Security Identity Governance (v5.2.2) are no doubt having a wonderful time with the new interface and the new features.

But like every new software release, one or two things may not behave quite like you expected them to.

As an example, the rule embedded within the USER_MOVE Rule Flow suggests that the moveUser method will move a user to a new Organisational Unit and automatically assign all default entitlements assigned to that OU. At least, the comments explicitly state that this is to be expected:
// Move the user assigning the default entitlements of the new OU
UtilAction.moveUser(sql, userBean, orgUnitBean);

Unfortunately, the result of this operation is somewhat disappointing. The user does indeed move... but new default entitlements are not assigned.

Checking a v5.2.1 demo image that I have, though, reveals the following additional code which does actually meet our expectations:

// Assign default entitlements of OU
EntitlementBean entBeanDefault = new EntitlementBean(); 
entBeanDefault.setDefaultOption(true);

BeanList entsDefault = _OrgUnitAction.findEntitlementByOU(sql, false, entBeanDefault, null, orgUnitBean, null);
if (!entsDefault.isEmpty()) {
    for (int k = 0; k < entsDefault.size(); k++) {
        EntitlementBean role = (EntitlementBean) entsDefault.get(k);
        BeanList roles = JobRoleAction.find(sql, role);
        if(roles==null || roles.isEmpty() ) {
            throw new Exception("Role : " + role.getName() + " not found!");
        }
        UserAction.addRole(sql, userBean , orgUnitBean , roles , null, null, false, false);
    }
}

NOTE: The following will need adding to the Package Imports:
import com.engiweb.profilemanager.common.ruleengine.action.reorganize._OrgUnitAction
import com.engiweb.profilemanager.common.ruleengine.action.JobRoleAction

Tuesday, November 22, 2016

IGI Attribute Hierarchies

IBM Security Identity Governance & Intelligence (or IGI for short) has a very neat feature whereby hierarchies can be constructed using any attribute associated with an identity. Now, instead of identities being firmly placed within a rigid organizational hierarchy, additional hierarchies can be created to help model entitlements more accurately.

For example, it could be useful for everyone who reports to a specific manager to be automatically assigned a suite of entitlements. Additionally, we could find that rights should be assigned based on regional or office location.

Fundamentally, the assignment of this rights is somewhat akin to how IBM Security Identity Manager could be configured with dynamic roles - except IGI's approach is so much more powerful.

For example, let's consider identity records that contain the following attributes:
  • Country
  • City
  • Address

It could be interesting to model that hierarchy and "virtually" place identities in a hierarchy that might look like this:

World
- United Kingdom
- - Belfast
- - - 1 Main Street
- - London
- - - 2 High Street
- - - 3 Oxford Street
- - - 4 Piccadilly
- France
- - Paris
- - - 5 Rue de Provence

etc.

Modelling the hierarchy is simple. As an IGI administrator, one merely needs to navigate to Access Governance Core > Configure > Rules. In here, we can create a Rules Sequence called  LOCATION_HIERARCHY of type Hierarchy.

Now, within the Rules tab, we can select the rule class Hierarchy and rule flow LOCATION_HIERARCHY (ignoring the fact that the naming convention mismatch between sequence and flow is rather annoying).

Within the package imports section, we would place the following:

import com.engiweb.profilemanager.common.bean.UserBean
import com.crossideas.certification.common.bean.data.ResultBean
import com.engiweb.profilemanager.common.ruleengine.action.UtilAction
import java.util.ArrayList

global com.engiweb.pm.dao.db.DAO sql
global com.engiweb.logger.impl.Log4JImpl logger

This suite of imports exposing methods which we can now use. Our next step is to CREATE a Rules Package with the following code:

when
    userBean : UserBean(  )  
    resultBean : ResultBean(  )
then
/* Country>City>Office */
    String country = userBean.getCountry();
    String city = userBean.getLocality();
    String office = userBean.getAddress();

    if (country != null && city != null && office != null) {
        resultBean.setResultString("World;" + country + ";" + city + ";" + office); 
    } else {
        resultBean.setResultString("World"); 
    }

What does this code do? Well, it iterates over every identity in the platform and constructs a string of World;Country;City;Office which can be passed back to the core platform in order to construct a hierarchy. Give the package a "sensible" name (like Country>City>Office) and assign it to the LOCATION_HIERARCHY rule flow.

The next step is to Access Governance Core > Configure > Hierarchy in order to create a hierarchy that can use our rule flow. Under the Actions link, click on Add. Populate the blank form with the following details:

Name: Location Hierarchy
Configuration Type: Advanced
Rule: LOCATION_HIERARCHY
Value: Hierarchy
Separator Char: Semi-Colon (;)

Save the hierarchy, re-select it and under Actions, click on BUILD. Now the system will build an appropriate hierarchy which can be viewed under Access Governance Core > Manage > Groups.

So what can we do now?

Well... let's assume we want everyone in the United Kingdom to be assigned a role. Create and publish role called "United Kingdom Users". Now configure the role by updating the Org Units it is assigned to (ignoring the fact it is called Org Units which will no doubt be resolved in a future fix pack!). Add an "Org Unit" of type Location Hierarchy, navigate down through the hierarchy and find United Kingdom, click on OK and complete the following:

Default: Yes, and align users
Visibility Violation: No
Enabled: Yes
Hierarchy: Checked

That's it... every user under the United Kingdom hierarchy will automatically be assigned the United Kingdom Users role.

Tuesday, August 30, 2016

Javadoc Updates

It has been a while, but I've finally got round to uploading the latest Javadocs for IBM Security Identity Manager v7.0 and IBM Security Access Manager v9.0.

These can be found by following the links from here: https://www.stephen-swann.co.uk/links-and-tools/

Enjoy - if it's possible to enjoy Javadocs!

Wednesday, March 23, 2016

Property Changes In TDI - On The Fly

This week, I was asked if it was possible to update a TDI property while the TDI server was still running and, if so, how to go about doing it.

The reason for wanting to do so was akin to injecting a property into TDI at run-time so that it would "safely" shutdown an Assembly Line at a sensible point of processing. Now, there are many ways to address this actual requirement, but the fundamental question of how to inject a property into TDI is certainly something that can be explained easily.

tdisrvctl
The tdisrvctl command is a terrific command for communicating with a running TDI server. In order to communicate with the TDI server, you merely need to supply some key information, such as the Port Number that the TDI Server API is listening on, and some means to identify yourself using the TDI keystores. Finally, you supply an "operation" for the TDI Server to perform. Manipulating properties can be performed with the "prop" operation. In summary, tdisrvctl needs the following parameters:

  • -p {port}
  • -K {keystore}
  • -P {keystore password}
  • -T {trust store}
  • -W {trust store password}
  • -op prop


I set up a Project in TDI called propertyhandling, with an assemblyline called propertyhandling and a property in the propertyhandling properties file called status with a value of run.

In my AL, I created a conditional WHILE loop with this code:

if (system.getExternalProperty("status") == "run") {
      return true;
} else {
      return false;
}

I ran the AL and it trundles along nicely doing nothing but looping and consuming all available CPU. You got to love never-ending loops!

I then ran this command:

tdisrvctl.bat -p 1091 -T C:\TDISOL\testserver.jks -W server -K C:\TDISOL\serverapi\testadmin.jks -P administrator -op prop -c propertyhandling -o propertyhandling -g all

The -c, -o and -g options after the prop operation need a little explaining:

  • -c this is the Solution Name for my configuration, in this case propertyhandling
  • -o this is the name of the properties collection, in this case propertyhandling
  • -g this tells the TDI Server to return the property value for the property named, in this case all means return the values for all the properties in the properties file


When I run the command, the result I get on-screen is this:

--- propertyhandling ---

status=run

This is excellent news, I'm able to query the current properties held in this particular properties file. Swapping that -g argument for a -s argument means I can now manipulate the status property as such:

tdisrvctl.bat -p 1091 -T C:\TDISOL\testserver.jks -W server -K C:\TDISOL\serverapi\testadmin.jks -P administrator -op prop -c propertyhandling -o propertyhandling -s status=stop

The -s require a property/value pair to be supplied. In this case, -s is telling the TDI Server to set the value of property status to stop. When I run this command, I get this result:

CTGDJB070I The property status has been set and committed.

That looks positive and when I check whether my assemblyline is still running, I find that it has indeed come to an end - as expected. Thanks goodness, says my CPU!

Of course, there are a myriad of use cases for injecting properties at run time... safe shut-down of an assemblyline is just one.