Hello colleagues,
I’m currently working on the building the during provisioning cloud rule that generates email from firstName and lastName and populates Active Directory as a targeted app with it.
Its simplified logic is
“{firstName}.{lastName}[counter if its a duplicate]@{domain}”
But of course it varies a bit according to the parameters and I’m doing it with COUNTRY_SCHEMA map.
Here is the code snippet:
// Replaces diacritical marks and removes special chars
public String sanitizeString(String input) throws GeneralException {
log.info("Entering - sanitizeString()");
String result = input;
for (Object key : replaceMap.keySet()) {
result = result.replace(key.toString(), replaceMap.get(key).toString());
}
result = result.replaceAll("[^a-zA-Z0-9]", "");
log.info("Leaving - sanitizeString() with result: " + result);
return result;
}
// Parses the first part of LastName
public String processLastName(String lastName, boolean toKeepPrefix) throws GeneralException {
log.info("Entering - processLastName()");
lastName = lastName.trim();
if (lastName.contains(" ")) {
String[] parts = lastName.split(" ");
if (toKeepPrefix) {
log.info("Leaving - processLastName() with result: " + parts[0]);
return parts[0];
} else {
log.info("Leaving - processLastName() with result: " + String.join("", parts));
return String.join("", parts);
}
}
log.info("Leaving - processLastName() with result: " + lastName);
return lastName;
}
// Checks the existence of the generated email in the source app
public boolean isEmailUnique(String email) throws GeneralException {
log.info("Entering - isEmailUnique()");
List sourceIds = new ArrayList();
sourceIds.add(application.getId());
String attributeName = "mail";
String operation = "Equals";
List values = new ArrayList();
values.add(email);
int count = idn.attrSearchCountAccounts(sourceIds, attributeName, operation, values);
boolean result = count == 0;
log.info("Leaving - isEmailUnique() with result: " + result);
return result;
}
// Main function to generate email
public String generateEmail(String firstName, String lastName, String countryCode) throws GeneralException {
try {
log.info("Entering - generateEmail()");
log.info("Input Parameters for generateEmail: " + "firstName=" + firstName + " lastName=" + lastName + " countryCode=" + countryCode);
log.warn("generateEmail - current IDN: " + idn);
log.warn("generateEmail - current APPLICATION: " + application);
firstName = StringUtils.trimToNull(firstName);
lastName = StringUtils.trimToNull(lastName);
countryCode = StringUtils.trimToNull(countryCode);
if (firstName == null || lastName == null || countryCode == null) {
throw new GeneralException("Missing required attributes for email generation");
}
String schema = COUNTRY_SCHEMA.getOrDefault(countryCode, COUNTRY_SCHEMA.get("default"));
boolean toKeepPrefix = schema.contains("{lastNamePrefix}");
String lastNamePrefix = "";
if (toKeepPrefix) {
for (String prefix : LASTNAME_PREFIXES) {
if (lastName.toLowerCase().startsWith(prefix)) {
lastNamePrefix = prefix.replace(" ", "");
lastName = lastName.substring(prefix.length()).trim();
break;
}
}
} else {
for (String prefix : LASTNAME_PREFIXES) {
if (lastName.toLowerCase().startsWith(prefix)) {
lastName = lastName.substring(prefix.length()).trim();
break;
}
}
}
String firstLastName = processLastName(lastName, toKeepPrefix);
firstName = sanitizeString(firstName);
firstLastName = sanitizeString(firstLastName);
lastName = sanitizeString(lastName);
String firstCharFirstname = firstName.substring(0, 1);
String email = schema
.replace("{firstname}", firstName)
.replace("{firstCharFirstname}", firstCharFirstname)
.replace("{lastNamePrefix}", lastNamePrefix)
.replace("{firstLastName}", firstLastName)
.replace("{lastname}", lastName);
int counter = 1;
String baseEmail = email;
while (!isEmailUnique(email)) {
if (counter > 49) {
throw new GeneralException("Exceeded maximum number of email duplicates");
}
email = baseEmail.replace("@", counter + "@");
counter++;
}
log.info("Leaving - generateEmail() with the result: " + email.toLowerCase());
return email.toLowerCase();
} catch (Exception e) {
log.error("Error in generateEmail for user: " + identity.getDisplayName(), e);
throw new GeneralException("GenerateMail failed for user: " + identity.getDisplayName(), e);
}
}
return generateEmail(identity.getFirstname(), identity.getLastname(), identity.getStringAttribute("countryCode"));
and dealing the issue with the email duplication processing.
Despite the RDK built tests work out and result the expected value.
@Test
public void testUniqueLogic () throws GeneralException, EvalError {
Interpreter i = new Interpreter();
IdnRuleUtil idn = mock();
when(idn.attrSearchCountAccounts(any(), any(), any(), any())).thenReturn(1).thenReturn(0);
log.info("SOME OBJECT " + idn);
Application application = mock(Application.class);
when(application.getId()).thenReturn("12345");
Identity identity = mock(Identity.class);
when(identity.getFirstname()).thenReturn("Trox");
when(identity.getLastname()).thenReturn("Marmox");
when(identity.getStringAttribute("countryCode")).thenReturn("IT");
String result = "";
i.set("log", log);
i.set("idn", idn);
i.set("application", application);
i.set("identity", identity);
String source = RuleXmlUtils.readRuleSourceFromFilePath(RULE_FILENAME);
result = (String) i.eval(source);
assertNotNull(result);
assertEquals(result, "[email protected]");
log.info("Beanshell script returned: " + result);
}
My assumption that there is a mistake with isEmailUnique function because in the Sailpoint UI after the provisioning to AD I see an empty Email field in the corresponding AD account attributes.
I would really appreciate if u could guide me with debugging the code and share ur best practices to debug such kind of rules.
As far as i know since it’s cloud based rule, my only tools to test and debug it are RDK with UNIT tests or to write the similar Java Function and there were no bugs spotted as i said.
As you have noticed I was also trying to distribute the logs through the code to check the code execution flow but I’ve discovered that they are not visible because it’s a cloud Rule.
is there a way to check the logs in these Rules? Probably I need to change the logging level or sth else?
Thank u for you input in advance and any related advice.