Post Date: April 26, 2011
Posted By: Trey Kirk
It's often a requirement to determine if an ActiveDirectory account is inactive. In addition, it's just as often one may need to capture the 'Password Never Expires' flag as well. These, as well as several others attributes, are stored as a single value on the 'userAccountControl' attribute. This attribute is a bit-wise series of flags where '1' represents true and '0' represents false. To capture the values of the flags, one needs to use a Customization Rule. This rule should include the logic below. It is up to the reader to apply minute differences
/*
* Information on the userAccountControl attribute is represented as a collection of bitwise flags. That is,
* a user userAccountControl of 514 is better represented as: 00000001000000010, which simply means the
* 2nd and 10th bits are true (from right to left), and the other bits are false. Bit 2 is the flag indicating
* the account as being disabled. Bit 17 indicates the password never expires. A complete listing of all of the
* bitwise flags are found here: http://support.microsoft.com/kb/305144
*
* To determine which flags are enabled, we have to use the Java AND '&' operator which applies the given mask to
* a value and returns that same mask when the bit is found
*/
int DISABLED_MASK = 2;
int NEVER_EXPIRE_PASSWORD_MASK = 65536;
// If the ResourceObject is an account, do the following:
if(object.getObjectType().compareTo(Connector.TYPE_ACCOUNT) == 0) {
// fetches the schema value 'userAccountControl'. This is the literal value found on the account Schema
accountControl = object.get("userAccountControl");
// If the DISABLE_MASK is found, set disabled = 'Yes'
// ... set inactive = 'true'
//
// Change these values to those that make more sense to your environment, i.e.: disabled = 'true', enabled = 'No' / 'False'
if ( accountControl != null && accountControl instanceof Long) {
if ( (accountControl & DISABLED_MASK) == DISABLED_MASK){
object.put("disabled","Yes");
object.put("inactive","true");
} else
object.put("disabled","No");
// If the NEVER_EXPIRE_PASSWORD_MASK is found, flag 'neverExpirePassword'
if ( (accountControl & NEVER_EXPIRE_PASSWORD_MASK) == NEVER_EXPIRE_PASSWORD_MASK)
object.put("neverExpirePassword","Yes");
else
object.put("neverExpirePassword","No");
}
Additional Notes from Richard Craig:
- you need to add the following import for the rule to work:
import sailpoint.connector.Connector;
- you need to ensure the userAccountControl attribute is added to the application schema (by default it's not there) and that the attribute type is set to 'long'.
Some notes on this:
- you need to add the following import for the rule to work:
import sailpoint.connector.Connector;
- you need to ensure the userAccountControl attribute is added to the application schema (by default it's not there) and that the attribute type is set to 'long'.
Hi Richard,
Thanks for the help. But when i am running aggregation task for JDBC Connector(Human Resource) then I am getting below error. Please find the below customized rule which i am using in JDBC connector(Human Resource Application) to make application account status as Disabled.
Exception during aggregation. Reason: java.lang.RuntimeException: sailpoint.connector.ConnectorException: BeanShell script error: Parse error at line 34, column 11. Encountered: <EOF> BSF info: DisableAccountStatusRule at line: 0 column: columnNo
Thanks,
Gopal
Hi Gopal,
It looks like you still need to return the object at the end of your function (eg: return object;), and it's also hard to follow exactly, but it looks like you are also missing a } (you have "if object.getObjectType().compareTo(Connector.TYPE_ACCOUNT) == 0) {" but I don't see it close). ... I'm trying to do something similar with our ERP data, and even though I was able to get it to compile, and it is writing disabled and inactive as attributes on the accounts, it's not updating the Status as it's shown in the Identity Application Accounts lists (as you were originally asking).
Even a most simple rule, so as to eliminate the possibility of a logic mistake, was not changing the status in that list, ie:
object.put("disabled", "Yes");
object.put("inactive", true);
return object;
Cheers,
Tyler
I was able to get things working today, I had to switch to a Build Map Rule (so a connector rule, rather than aggregation rule), but at least on first run it appears to do what I want. The full rule:
import sailpoint.connector.Connector;
import sailpoint.connector.JDBCConnector;
import sailpoint.object.Schema;
import java.util.*;
import org.apache.commons.lang.StringUtils;
Map map = JDBCConnector.buildMapFromResultSet(result, schema);
if ( schema.getObjectType().compareTo(Connector.TYPE_ACCOUNT) == 0){
String accountStatus = map.get("ACCOUNTSTATUS");
//if account is locked, set IIQDisabled true
if ((accountStatus != null) &&
(accountStatus.equals("LOCKED"))) {
map.put("IIQDisabled", true);
} else {
map.put("IIQDisabled", false);
}
}
return map;
Thanks a lot Tyler. I will try the same.