/*
* DO NOT REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2013 ForgeRock Inc. All rights reserved.
*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the License). You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://forgerock.org/license/CDDLv1.0.html
* See the License for the specific language governing
* permission and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* Header Notice in each file and include the License file
* at http://forgerock.org/license/CDDLv1.0.html
* If applicable, add the following below the CDDL Header,
* with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*/
package org.forgerock.openicf.connectors.rsaauthenticationmanager;
import com.rsa.admin.AddPrincipalsCommand;
import com.rsa.admin.DeletePrincipalsCommand;
import com.rsa.admin.GetPrincipalGroupsCommand;
import com.rsa.admin.LinkGroupPrincipalsCommand;
import com.rsa.admin.SearchGroupsCommand;
import com.rsa.admin.SearchPrincipalsCommand;
import com.rsa.admin.SearchSecurityDomainCommand;
import com.rsa.admin.UnlinkGroupPrincipalsCommand;
import com.rsa.admin.UpdatePrincipalCommand;
import com.rsa.admin.data.AttributeDTO;
import com.rsa.admin.data.GroupDTO;
import com.rsa.admin.data.ModificationDTO;
import com.rsa.admin.data.PrincipalDTO;
import com.rsa.admin.data.SecurityDomainDTO;
import com.rsa.admin.data.UpdatePrincipalDTO;
import com.rsa.authmgr.admin.agentmgt.SearchAgentsCommand;
import com.rsa.authmgr.admin.agentmgt.data.AgentConstants;
import com.rsa.authmgr.admin.agentmgt.data.ListAgentDTO;
import com.rsa.authmgr.admin.principalmgt.AddAMPrincipalCommand;
import com.rsa.authmgr.admin.principalmgt.LookupAMPrincipalCommand;
import com.rsa.authmgr.admin.principalmgt.UpdateAMPrincipalCommand;
import com.rsa.authmgr.admin.principalmgt.data.AMPrincipalDTO;
import com.rsa.authmgr.admin.tokenmgt.EnableTokensCommand;
import com.rsa.authmgr.admin.tokenmgt.LinkTokensWithPrincipalCommand;
import com.rsa.authmgr.admin.tokenmgt.ListTokensByPrincipalCommand;
import com.rsa.authmgr.admin.tokenmgt.LookupTokenCommand;
import com.rsa.authmgr.admin.tokenmgt.LookupTokenEmergencyAccessCommand;
import com.rsa.authmgr.admin.tokenmgt.ResynchronizeTokenCommand;
import com.rsa.authmgr.admin.tokenmgt.UnlinkTokensFromPrincipalsCommand;
import com.rsa.authmgr.admin.tokenmgt.UpdateTokenCommand;
import com.rsa.authmgr.admin.tokenmgt.UpdateTokenEmergencyAccessCommand;
import com.rsa.authmgr.admin.tokenmgt.data.ListTokenDTO;
import com.rsa.authmgr.admin.tokenmgt.data.TokenDTO;
import com.rsa.authmgr.admin.tokenmgt.data.TokenEmergencyAccessDTO;
import com.rsa.authmgr.common.AdminResource;
import com.rsa.command.CommandException;
import com.rsa.command.exception.ConcurrentUpdateException;
import com.rsa.command.exception.DataNotFoundException;
import com.rsa.command.exception.DuplicateDataException;
import com.rsa.command.exception.InsufficientPrivilegeException;
import com.rsa.command.exception.InvalidArgumentException;
import com.rsa.command.exception.ObjectInUseException;
import com.rsa.common.search.Filter;
import com.rsa.authmgr.admin.tokenmgt.GenerateOneTimeTokenCodeSetCommand;
import com.rsa.authmgr.admin.tokenmgt.SearchTokensCommand;
import com.rsa.command.ClientSession;
import com.rsa.command.CommandTargetPolicy;
import com.rsa.common.SystemException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.List;
import java.util.Map;
import org.identityconnectors.common.logging.Log;
import org.identityconnectors.common.security.GuardedString;
import org.identityconnectors.framework.common.exceptions.ConnectorException;
import org.identityconnectors.framework.common.exceptions.UnknownUidException;
import org.identityconnectors.framework.common.objects.Attribute;
import org.identityconnectors.framework.common.objects.AttributeBuilder;
import org.identityconnectors.framework.common.objects.AttributesAccessor;
import org.identityconnectors.framework.common.objects.ConnectorObjectBuilder;
import org.identityconnectors.framework.common.objects.ObjectClass;
import org.identityconnectors.framework.common.objects.OperationOptions;
import org.identityconnectors.framework.common.objects.ResultsHandler;
import org.identityconnectors.framework.common.objects.Uid;
import org.identityconnectors.framework.common.objects.filter.FilterTranslator;
import org.identityconnectors.framework.spi.Configuration;
import org.identityconnectors.framework.spi.ConnectorClass;
import org.identityconnectors.framework.spi.operations.CreateOp;
import org.identityconnectors.framework.spi.operations.DeleteOp;
import org.identityconnectors.framework.spi.operations.SchemaOp;
import org.identityconnectors.framework.spi.operations.SearchOp;
import org.identityconnectors.framework.spi.operations.TestOp;
import org.identityconnectors.framework.spi.operations.UpdateOp;
import org.identityconnectors.framework.common.objects.Schema;
import org.identityconnectors.framework.common.objects.SchemaBuilder;
import org.identityconnectors.framework.common.objects.AttributeInfo;
import org.identityconnectors.framework.common.objects.AttributeInfoBuilder;
import org.identityconnectors.framework.common.objects.OperationalAttributeInfos;
import org.identityconnectors.framework.common.objects.Name;
import org.identityconnectors.framework.spi.PoolableConnector;
/**
* Main implementation of the RSA AM 8 Connector Connector.
* <p>
* The RSA Authentication Manager 8 connector has the following setup
* prerequisites:
* <br/>
* <ul>
* <li> The following JAR dependencies must be present in classpath:
* <ul>
* <li>ws-constants-1.0.jar</li>
* <li>commons-io-2.2-1.0.jar</li>
* <li>ognl-1.0.jar</li>
* <li>commons-logging-1.1.1-1.0.jar</li>
* <li>commons-httpclient-1.0.jar</li>
* <li>commons-logging-1.0.jar</li>
* <li>log4j-1.2.12rsa-1-1.0.jar</li>
* <li>axis-saaj-1.0.jar</li>
* <li>connector-framework-1.1.0.0-SNAPSHOT-javadoc-1.0.jar</li>
* <li>am-client-1.0.jar</li>
* <li>axis-jaxrpc-1.0.jar</li>
* <li>iScreen-1-1-0rsa-2-1.0.jar</li>
* <li>iScreen-ognl-1-1-0rsa-2-1.0.jar</li>
* <li>aopalliance-1.0.jar</li>
* <li>xercesImpl-1.0.jar</li>
* <li>dependencies.txt
* <li>spring-beans-1.0.jar</li>
* <li>spring-aop-1.0.jar</li>
* <li>connector-framework-internal-1.1.0.0-SNAPSHOT-1.0.jar</li>
* <li>spring-context-1.0.jar</li></li>
* <li>iScreen-ognl-1.0.jar</li>
* <li>spring-expression-1.0.jar</li>
* <li>jdom-1.0-1.0.jar</li>
* <li>commons-beanutils-1.0.jar</li>
* <li>commons-lang-1.0.jar</li>
* <li>clu-common-1.0.jar</li>
* <li>commons-discovery-0.2-1.0.jar</li>
* <li>wlfullclient-1.0.jar</li>
* <li>spring-asm-1.0.jar</li>
* <li>connector-framework-1.1.0.0-SNAPSHOT-1.0.jar</li>
* <li>axis-1.0.jar</li>
* <li>commons-codec-1.0.jar</li>
* <li>log4j-1.0.jar</li>
* <li>iScreen-1.0.jar</li>
* <li>ognl-2.6.7-1.0.jar</li>
* <li>commons-beanutils-1.8.3-1.0.jar</li>
* <li>commons-discovery-1.0.jar</li>
* <li>spring-web-1.0.jar</li>
* <li>spring-context-support-1.0.jar</li>
* <li>wsdl4j-1.0.jar</li>
* <li>test-contract-1.3-1.0.jar</li>
* <li>testng-5.7-jdk15-1.0.jar</li>
* <li>commons-lang-2.2-1.0.jar</li>
* <li>ims-systemfields-4.3.0.0.0-1.0.jar</li>
* <li>axis-1.3-1.0.jar</li>
* <li>cryptoj-5.0-1.0.jar</li>
* <li>connector-framework-1.1.0.0-SNAPSHOT-tests-1.0.jar</li>
* <li>ws-extras-1.0.jar</li>
* <li>spring-core-1.0.jar</li>
* </ul>
* </li>
* <br/>
* <li>The root certificate of the RSA server must be added to the local keystore (using keytool).
* The local keystore may reside in JAVA_HOME/jre/lib/security for example.</li>
* <br/>
* <li>The RSA Authentication Manager 8 connector uses the RSA COmmand Client server, which
* requires credentials. These command client credentials can be retrieved from the RSA
* server by running "rsautil manage-secrets --action list" for the server's
* RSA_HOME/utils directory.</li>
* <br/>
* <li>The connector requires a RSA Authentication manager 8 service account to perform
* it operation. This special account must have User Manager role in RSA. The relevant
* credentials can be set using the 'UserMgrPrincipal' and 'UserMgrPwd' Connector
* configuration properties. The 'UserMgrPrincipal' defaults to "openicf".</li>
* </ul>
* </p>
*
* @author Alex Babeanu (ababeanu@nulli.com)
* www.nulli.com - Identity Solution Architects
*
* @version 1.1
* @since 1.0
*/
@ConnectorClass(
displayNameKey = "RSAAuthenticationManager8.connector.display",
configurationClass = RSAAuthenticationManager8Configuration.class)
public class RSAAuthenticationManager8Connector implements
PoolableConnector
, CreateOp
, DeleteOp
, SearchOp<Filter>
, TestOp
, UpdateOp
, SchemaOp
{
/**
* Setup logging for the {@link RSAAuthenticationManager8Connector}.
*/
private static final Log logger = Log.getLog(RSAAuthenticationManager8Connector.class);
/**
* Place holder for the Connection created in the init method.
*/
private RSAAuthenticationManager8Connection connection;
/**
* Gets the Connection context for this connector.
*
* @return The current RSA Connection
*/
public RSAAuthenticationManager8Connection getConnection() {
return connection;
}
/**
* Place holder for the {@link Configuration}passed into the init() method
* {@link org.forgerock.openicf.connectors.rsaauthenticationmanager.RSAAuthenticationManager8Connector#init(org.identityconnectors.framework.spi.Configuration)}.
*/
private RSAAuthenticationManager8Configuration configuration;
/**
* Gets the Configuration context for this connector.
*
* @return The current {@link Configuration}
*/
public Configuration getConfiguration() {
return this.configuration;
}
/**
* The RSA User Principal this connector instance modifies.
*/
// private PrincipalDTO UserPrincipal;
/**
* Flag used internally to identify full user searches.
*/
private Boolean searchAll = false;
/**
* Callback method to receive the {@link Configuration}.
*
* @param configuration the new {@link Configuration}
* @see org.identityconnectors.framework.spi.Connector#init(org.identityconnectors.framework.spi.Configuration)
*/
public void init(final Configuration configuration) {
this.configuration = (RSAAuthenticationManager8Configuration) configuration;
this.connection = new RSAAuthenticationManager8Connection(this.configuration);
}
/**
* Disposes of the {@link RSAAuthenticationManager8Connector}'s resources.
*
* @see org.identityconnectors.framework.spi.Connector#dispose()
*/
public void dispose() {
//configuration = null;
if (connection != null) {
connection.dispose();
connection = null;
}
configuration = null;
}
/******************
* SPI Operations
******************/
/**
* {@inheritDoc}
*/
public Uid create(final ObjectClass objectClass, final Set<Attribute> createAttributes, final OperationOptions options) {
String Uid = null;
String LoginID = null;
logger.info("Creating object of ObjectClass:" + objectClass.getDisplayNameKey());
logger.info("Creation contains {0} attributes", createAttributes.size());
// Extract attributes and create User and Account in IMS and AM
if (objectClass.is("__ACCOUNT__")) {
logger.info("Creating User Account...");
// Read attributes from input
logger.info("Reading Creation attributes...");
AttributesAccessor aa = new AttributesAccessor(createAttributes);
// Operational Attribs
GuardedString Password = aa.getPassword();
/* Server side settings can allow for null password
* if (Password == null) {
throw new IllegalArgumentException("The Password attribute cannot be null.");
}*/
Boolean Enabled = aa.getEnabled(true);
// Getting UserID
//String UserId = aa.findString(PrincipalDTO.LOGINUID);
Uid CreateUid = aa.getUid();
String UserId;
if (CreateUid == null)
// If no UID attribute provided, use the Name
UserId = aa.getName().getNameValue();
else {
UserId = aa.getUid().getUidValue();
if ((UserId == null) || (UserId.isEmpty()))
UserId = aa.getName().getNameValue();
}
// Other attribs
String First = aa.findString(PrincipalDTO.FIRST_NAME);
String Last = aa.findString(PrincipalDTO.LAST_NAME);
String Descr = aa.findString(PrincipalDTO.DESCRIPTION);
String MiddleName = aa.findString(PrincipalDTO.MIDDLE_NAME);
String EmpNb = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_EMPLOYEE_NB);
String Email = aa.findString(PrincipalDTO.EMAIL);
Boolean AdminRole = aa.findBoolean(PrincipalDTO.ADMINISTRATOR_FLAG);
if (AdminRole == null)
AdminRole = Boolean.FALSE;
// AM extension attribs
String DefShell = aa.findString(AdminResource.DEFAULTSHELL);
Boolean ShellAllowed = Boolean.FALSE;
if (DefShell != null) {
// Default shell value provided, need an AM account.
ShellAllowed = aa.findBoolean(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_SHELL_ALLOWED);
if (ShellAllowed == null)
// No Default Shell Allowed value provided, assume TRUE since a Shell value is provided.
ShellAllowed = Boolean.TRUE;
// Else use whatever Shell Allowed value is provided
}
// Uncomment to enable
/*
String WinPwd = aa.findString(configuration.ATTR_WIN_PWD);
*/
// Uncomment if the Security Domain needs to be passed as parameter to create
// Currently determined at Connection time
// String SDGuid = aa.findString(PrincipalDTO.SECURITY_DOMAIN);
// Create is a 2-step process: 1) create the IMS user and 2) create the AM Account
// 1- Create IMS User
PrincipalDTO principal = new PrincipalDTO();
principal.setUserID(UserId);
principal.setFirstName(First);
principal.setLastName(Last);
principal.setPassword(RSAAuthenticationManager8Utils.getPlainPassword(Password));
principal.setEnabled(Enabled);
principal.setCanBeImpersonated(false);
principal.setTrustToImpersonate(false);
principal.setSecurityDomainGuid(this.connection.getDomain().getGuid());
principal.setIdentitySourceGuid(this.connection.getIdSource().getGuid());
// require user to change password at next login
principal.setPasswordExpired(true);
principal.setDescription(Descr);
principal.setMiddleName(MiddleName);
principal.setEmail(Email);
principal.setAdminRole(AdminRole);
// Add custom Attributes
ArrayList<AttributeDTO> attrs = new ArrayList<AttributeDTO> ();
// DATA Attribs
// Employee Number
AttributeDTO attr = new AttributeDTO();
attr.setName(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_EMPLOYEE_NB);
String[] EmpNbs = {EmpNb};
attr.setValues(EmpNbs);
attrs.add(attr);
// Allowed to create pin
attr = new AttributeDTO();
attr.setName(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_ALLOWED_TO_CREATE_PIN);
Boolean[] AllowPin = {aa.findBoolean(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_ALLOWED_TO_CREATE_PIN)};
attr.setValues(AllowPin);
attrs.add(attr);
// Required to create pin
attr = new AttributeDTO();
attr.setName(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_REQUIRED_TO_CREATE_PIN);
Boolean[] ReqPin = {aa.findBoolean(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_REQUIRED_TO_CREATE_PIN)};
attr.setValues(ReqPin);
attrs.add(attr);
// the start date
Calendar cal = Calendar.getInstance();
Date now = cal.getTime();
// Date Formatter
SimpleDateFormat sdf = new SimpleDateFormat(RSAAuthenticationManager8Configuration.DATE_FORMAT);
Date startDt = null;
Date endDt = null;
// the account end date - 1 Year validity
// Uncomment to set a 1 year validity for the account
//cal.add(Calendar.YEAR, 1);
//Date expire = cal.getTime();
// Temp Start Date
String TmpStartDtStr = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TEMP_START_DATE);
if (TmpStartDtStr != null) {
try {
startDt = sdf.parse(TmpStartDtStr);
} catch (ParseException e) {
logger.error("Invalid date format for {0}. Expected format: {1}. Provided date: {2}"
, RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TEMP_START_DATE
, RSAAuthenticationManager8Configuration.DATE_FORMAT
, TmpStartDtStr);
throw new IllegalArgumentException("Invalid Date Format");
}
}
if (startDt ==null)
principal.setAccountStartDate(now);
else
principal.setAccountStartDate(startDt);
// Temp End Date
String TmpEndDtStr = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TEMP_END_DATE);
if (TmpEndDtStr != null) {
try {
endDt = sdf.parse(TmpEndDtStr);
} catch (ParseException e) {
logger.error("Invalid date format for {0}. Expected format: {1}. Provided date: {2}"
, RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TEMP_END_DATE
, RSAAuthenticationManager8Configuration.DATE_FORMAT
, TmpEndDtStr);
throw new IllegalArgumentException("Invalid Date Format");
}
}
if (endDt != null) {
principal.setAccountExpireDate(endDt);
// If an End Date is supplied, it is a Temp user
attr = new AttributeDTO();
attr.setName(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TEMPUSER);
String[] TempUser = {"true"};
attr.setValues(TempUser);
attrs.add(attr);
}
// Temp User Start Hour
attr = new AttributeDTO();
attr.setName(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TEMP_START_HOUR);
String[] TempStartHr = {aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TEMP_START_HOUR)};
attr.setValues(TempStartHr);
attrs.add(attr);
// Temp User End Hour
attr = new AttributeDTO();
attr.setName(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TEMP_END_HOUR);
String[] TempEndHr = {aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TEMP_END_HOUR)};
attr.setValues(TempEndHr);
attrs.add(attr);
// Secret Word
attr = new AttributeDTO();
attr.setName(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_SECRET_WORD);
String[] Secret = {aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_SECRET_WORD)};
attr.setValues(Secret);
attrs.add(attr);
principal.setAttributes(attrs.toArray(new AttributeDTO[attrs.size()]));
// Prepare Create command
AddPrincipalsCommand cmd = new AddPrincipalsCommand();
cmd.setPrincipals(new PrincipalDTO[] { principal });
logger.info("Creating User Principal...");
//PrincipalDTO User = new PrincipalDTO();
try {
ClientSession ses = connection.newSession();
cmd.execute(ses);
connection.sessionLogout(ses);
// only one user was created, there should be one GUID result
Uid = cmd.getGuids()[0];
//User = cmd.getPrincipals()[0];
principal.setGuid(Uid);
LoginID = principal.getUserID();
logger.info("User Principal created with GUID: {0} .", Uid);
} catch (DuplicateDataException e) {
logger.error("Duplicate user ERROR: " + e.getMessage() + " key: " +e.getMessageKey());
throw new ConnectorException("Create Principal failure.", e);
} catch (ObjectInUseException e) {
// Shouldn't happen on Create, only on Delete
} catch (DataNotFoundException e) {
// Shouldn't happen on create, but on find/delete
} catch (InvalidArgumentException e) {
logger.error("Invalid Argument ERROR: " + e.getMessage() + " key: " +e.getMessageKey());
throw new ConnectorException("Create Principal failure.", e);
} catch (InsufficientPrivilegeException e) {
logger.error("Insufficient Privileges to create Principal (User may already Exist): " + e.getMessage() + " User ID: " + configuration.getCmdclientUser());
throw new ConnectorException("Create Principal failure. (User may already Exist)", e);
} catch (CommandException e) {
logger.error("An exception was thrown by the RSA command: " + e.getMessage() + " key: " +e.getMessageKey() + " cause: " + e.getCause());
throw new ConnectorException("Create Principal failure.", e);
}
// 2- Create AM Account with the new UID
// This is an add-on to the IMS principal in case any of the following attributes are used/required
// Uncomment if required...
/* */
if ((Uid != null) && (ShellAllowed)) {
logger.info("Creating AM Principal...");
AMPrincipalDTO AMprincipal = new AMPrincipalDTO();
AMprincipal.setGuid(Uid);
AMprincipal.setDefaultShell(DefShell);
AMprincipal.setDefaultUserIdShellAllowed(ShellAllowed);
//AMprincipal.setStaticPassword(RSAAuthenticationManager8Utils.getPlainPassword(Password));
AMprincipal.setStaticPasswordSet(false);
//AMprincipal.setWindowsPassword(WinPwd);
// Perform Account Creation
AddAMPrincipalCommand AMcmd = new AddAMPrincipalCommand(AMprincipal);
try {
ClientSession ses = connection.newSession();
AMcmd.execute(ses);
connection.sessionLogout(ses);
logger.info("AM Principal created.");
} catch (CommandException e) {
logger.error("An exception was thrown by the RSA AM command: " + e.getMessage() + " key: " +
e.getMessageKey() + " cause: " + e.getCause());
throw new ConnectorException("Create AM Principal failure.", e);
}
}
/* */
// ACTION Attributes
// Group Actions
List<Object> Groups = aa.findList(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_GROUPS);
ArrayList<String> GroupsList = new ArrayList<String>();
// Process Group List
if ((Uid != null) && (Groups != null)) {
if (!(Groups.isEmpty())) {
// Convert List<Object> to List<String>
for (Object grpobj : Groups) {
GroupsList.add(grpobj.toString());
}
logger.info("Linking user {0} to {1} groups...", principal.getUserID(), Groups.size());
linkGroups2User(GroupsList.toArray(new String[GroupsList.size()]), principal);
//processGroups (User, GroupsList);
}
}
// Token Actions
ArrayList<String> assignTokenList = new ArrayList<String>();
// Token 1
String token1 = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN1_SN);
if (token1 != null)
if (!(token1.isEmpty()))
assignTokenList.add(token1);
// Token 2
String token2 = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN2_SN);
if (token2 != null)
if (!(token2.isEmpty()))
assignTokenList.add(token2);
// Token 3
String token3 = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN3_SN);
if (token3 != null)
if (!(token3.isEmpty()))
assignTokenList.add(token3);
if (assignTokenList.size() > 0) {
logger.info ("Assigning tokens to new user...");
AssignTokens2User(assignTokenList, Uid);
logger.info ("{0} tokens succesfully assigned", assignTokenList.size());
}
}
// UNSUPPORTED Object Class
else {
logger.error("The RSA connector doesn't support Create for objectClass: {0}",
objectClass.getDisplayNameKey());
throw new UnsupportedOperationException("Connector doesn't support Create for objectClass: " +
objectClass.getDisplayNameKey());
}
return new Uid(LoginID);
//return new Uid(Uid);
}
/**
* {@inheritDoc}
*/
// TODO
public void delete(final ObjectClass objectClass, final Uid uid,
final OperationOptions options) {
//throw new UnsupportedOperationException();
if (objectClass.is("__ACCOUNT__")) {
String UserId = uid.getUidValue();
logger.info("Deleting User with ID: " + UserId + "...");
// Lookup user in RSA to fetch the user's GUID
PrincipalDTO user;
try {
user = lookupUser(UserId);
} catch (Exception e) {
logger.error("The User Principal with ID: " + UserId + " doesn't exist on the resource.");
throw new UnknownUidException ("Unknown UID", e);
}
DeletePrincipalsCommand cmd = new DeletePrincipalsCommand();
cmd.setGuids(new String[] { user.getGuid() });
cmd.setIdentitySourceGuid(this.connection.getIdSource().getGuid());
try {
ClientSession ses = connection.newSession();
cmd.execute(ses);
connection.sessionLogout(ses);
logger.info("User Deleted.");
} catch (ObjectInUseException e) {
logger.error("The User Principal object of user: " + UserId + " is currently in use and can't be deleted.");
throw new RuntimeException ("User Principal Delete Failure", e);
} catch (InvalidArgumentException e) {
logger.error("Invalid Argument: " + UserId + ".");
throw new RuntimeException ("Invalid UID", e);
} catch (DataNotFoundException e) {
logger.error("The User Principal with ID: " + UserId + " doesn't exist on the resource.");
throw new UnknownUidException ("Unknown UID", e);
} catch (InsufficientPrivilegeException e) {
logger.error("Insufficient privileges to delete user with ID: " + UserId + ".");
throw new RuntimeException ("Insufficient privileges.", e);
} catch (CommandException e) {
logger.error("An error occured while deleting the User Principal with ID: " + UserId + ".");
throw new RuntimeException ("An exception occurred...", e);
}
}
// UNSUPPORTED Object Class
else {
logger.error("The RSA connector doesn't support Delete for objectClass: {0}",
objectClass.getDisplayNameKey());
throw new UnsupportedOperationException("Connector doesn't support Delete for objectClass: " +
objectClass.getDisplayNameKey());
}
}
// SEARCH
/**
* {@inheritDoc}
*/
public FilterTranslator<Filter> createFilterTranslator(ObjectClass objectClass,
OperationOptions options) {
//throw new UnsupportedOperationException();
if (ObjectClass.ACCOUNT.equals(objectClass)) {
return (FilterTranslator<Filter>) new RSAAuthenticationManager8FilterTranslator();
}
else {
return new RSAAuthenticationManager8TokenFilterTranslator();
}
}
/**
* {@inheritDoc}
*/
public void executeQuery(ObjectClass objectClass, Filter query, ResultsHandler handler, OperationOptions options) {
//throw new UnsupportedOperationException();
// If no query, then fetch all objects
if (query == null) {
query = Filter.empty();
}
if (query.checkEmpty()) {
logger.info("Searching RSA with an empty filter...");
searchAll = true;
} else {
logger.info("Searching for RSA {0} matching query: {1} ", objectClass.getObjectClassValue(), query.toString());
}
// Search for ACCOUNTS
if (ObjectClass.ACCOUNT.equals(objectClass)) {
// Execute search of users matching the provided filter
PrincipalDTO[] results;
SearchPrincipalsCommand cmd = new SearchPrincipalsCommand();
// For paginated search, use:
//SearchPrincipalsIterativeCommand cmd = new SearchPrincipalsIterativeCommand();
// Search size limit default
cmd.setLimit(RSAAuthenticationManager8Configuration.SEARCH_LIMIT_DEFAULT);
// Get Search size limit from options, if any, and override the limit
Map<String, Object> TokenOpts = options.getOptions();
if (TokenOpts != null) {
if (TokenOpts.get(RSAAuthenticationManager8Configuration.SEARCH_LIMIT_NAME) != null) {
int limit = (Integer) TokenOpts.get(RSAAuthenticationManager8Configuration.SEARCH_LIMIT_NAME);
logger.info("Performing Search with Search Page Size limit of: " + limit);
cmd.setLimit(limit);
}
}
cmd.setIdentitySourceGuid(this.connection.getIdSource().getGuid());
cmd.setSecurityDomainGuid(this.connection.getDomain().getGuid());
cmd.setAttributeMask(new String[]{"ALL_INTRINSIC_ATTRIBUTES", "CORE_ATTRIBUTES", "SYSTEM_ATTRIBUTES", "ALL_EXTENDED_ATTRIBUTES"});
cmd.setFilter(query);
cmd.setSearchSubDomains(true);
try {
ClientSession ses = connection.newSession();
cmd.execute(ses);
connection.sessionLogout(ses);
results = cmd.getPrincipals();
for (PrincipalDTO principal : results) {
if (!(searchAll)) {
logger.info("Building results for user {0}.", principal.getUserID());
}
buildUser(principal, handler);
}
} catch (CommandException e) {
logger.error("An error occured during search. Cause : " + e.getCause() + " Msg: " + e.getMessage());
throw new RuntimeException("An error occured during Search.", e);
}
searchAll = false;
// ---- TOKENS - Emergency Access data
} else if (RSAAuthenticationManager8Configuration.TOKEN_OBJECTCLASS.equals(objectClass.getObjectClassValue())) {
// TOKEN Search: fetches the Emergency Access data of a given Token
// and generates new 1-time TokenCodes for the lost token.
// Used mainly to retrieve the tokenCodes once a Token has been lost
// Token search parameter: "serialNumber", ie: ListTokenDTO.FILTER_SERIAL_NO
logger.info("Fetching tokenCodes with filter: {0} ", query);
if (query.checkEmpty()) {
throw new IllegalArgumentException("Searching for tokens with an empty filter is not supported. Please specify a Token serialNumber .");
}
// Get the token's GUID
SearchTokensCommand TokenSrchCmd = new SearchTokensCommand();
TokenSrchCmd.setFilter(query);
TokenSrchCmd.setAssigned(true); // look for assigned tokens
TokenSrchCmd.setLimit(1); // Only fetch 1 token
ListTokenDTO[] listTokens = null;
try {
ClientSession ses = connection.newSession();
TokenSrchCmd.execute(ses);
connection.sessionLogout(ses);
// Retrieve only the first and only result
listTokens = TokenSrchCmd.getListSecurIDTokens();
} catch (Exception e) {
logger.error("Failed to fetch token with filter:" + query.toString());
throw new RuntimeException("Token Lookup failure.", e);
}
ListTokenDTO listToken = null;
if (listTokens.length > 0) {
listToken = listTokens[0];
} else {
logger.warn("No Tokens were found with the given filter...");
}
String TokenGuid = null;
if (listToken != null) {
TokenGuid = listToken.getGuid();
}
// Fetch the token's Emergency Access attributes
String serial = "";
String isLost = "";
String eaAccessCode = "";
String fixedTokenCode = "";
String nbUnusedCodes = "";
ArrayList<String> tokenCodes = null;
if (TokenGuid != null) {
LookupTokenEmergencyAccessCommand TokenEAcmd = new LookupTokenEmergencyAccessCommand();
TokenEAcmd.setGuid(TokenGuid);
try {
ClientSession ses = connection.newSession();
TokenEAcmd.execute(ses);
connection.sessionLogout(ses);
logger.info("Succesfully retrieved the token's Emergency Acces info.");
} catch (CommandException e) {
logger.error("Token " + TokenGuid + " Emergency Access data Lookup failure:" + e.getCause() + " - " + e.getMessage()
+ " - " + e.getMessageKey());
throw new RuntimeException("Token " + TokenGuid + " Emergency Access data Lookup failure.", e);
}
// Generate TokenCodes for the fetched token
TokenEmergencyAccessDTO tokenEA = TokenEAcmd.getTokenEmergencyAccess();
if (tokenEA != null) {
// Is the token lost?
isLost = String.valueOf(tokenEA.isTokenLost());
logger.info("Token is lost ? Answer: " + isLost);
if (tokenEA.isTokenLost()) {
// First clear any unused TokenCodes from the token, then generate
// a new set of TokenCodes.
// 1. Clear tokencodes:
tokenEA.setClearUnusedCodes(true);
// Update the Token's EA record:
UpdateTokenEmergencyAccessCommand lostUpdCmd = new UpdateTokenEmergencyAccessCommand();
lostUpdCmd.setTokenEmergencyAccessDTO(tokenEA);
logger.info("Clearing the unused TokenCodes of Token {0} with SN: {1}", TokenGuid, tokenEA.getSerialNumber());
try {
ClientSession ses = connection.newSession();
lostUpdCmd.execute(ses);
connection.sessionLogout(ses);
logger.info("TokenCodes succesfully cleared.");
} catch (CommandException e) {
logger.error("Token " + tokenEA.getSerialNumber() + " Emergency Access data Update failure:" + e.getCause() + " - " + e.getMessage()
+ " - " + e.getMessageKey());
throw new RuntimeException("Token " + tokenEA.getSerialNumber() + " Emergency Access data Update failure.", e);
}
// 2. Read the new EA Token data to get the latest Token version
// for optimistic locking
LookupTokenEmergencyAccessCommand TokenEAcmd3 = new LookupTokenEmergencyAccessCommand();
TokenEAcmd3.setGuid(TokenGuid);
try {
ClientSession ses = connection.newSession();
TokenEAcmd.execute(ses);
connection.sessionLogout(ses);
logger.info("Succesfully retrieved the Updated Token's Emergency Acces info.");
} catch (CommandException e) {
logger.error("Token " + TokenGuid + " Emergency Access data Lookup failure:" + e.getCause() + " - " + e.getMessage()
+ " - " + e.getMessageKey());
throw new RuntimeException("Token " + TokenGuid + " Emergency Access data Lookup failure.", e);
}
TokenEmergencyAccessDTO tokenEA2 = TokenEAcmd.getTokenEmergencyAccess();
// Generate tokencodes for this lost token:
logger.info("Generating {0} new TokenCodes for this token...", RSAAuthenticationManager8Configuration.NB_EA_TOKENCODES);
GenerateOneTimeTokenCodeSetCommand tokenCodeGenCmd = new GenerateOneTimeTokenCodeSetCommand();
tokenCodeGenCmd.setTokenGuid(TokenGuid);
tokenCodeGenCmd.setSetSize(RSAAuthenticationManager8Configuration.NB_EA_TOKENCODES);
String[] ottAry = null;
try {
ClientSession ses = connection.newSession();
tokenCodeGenCmd.execute(ses);
connection.sessionLogout(ses);
ottAry = tokenCodeGenCmd.getOtts();
// DEBUG - Log the generated codes, comment-out for production
/* for (int i = 0; i < ottAry.length; i++) {
logger.info(ottAry[i]);
} */
} catch (CommandException ex) {
logger.error("An error occured while generating EA TokenCodes for token.");
throw new RuntimeException("TokenCodes generation error - ", ex);
} catch (SystemException ex) {
logger.error("An unexpected error occured while generating EA TokenCodes for token.");
throw new RuntimeException("TokenCodes generation error - ", ex);
}
if (ottAry != null) {
logger.info("Succesfully Generated {0} TokenCodes.", ottAry.length);
// set new TokenCodes onto lost token
tokenEA2.setOneTimeTokencodeSet(ottAry);
// Update the Token's EA record with the new codes:
UpdateTokenEmergencyAccessCommand lostUpdCdCmd = new UpdateTokenEmergencyAccessCommand();
lostUpdCdCmd.setTokenEmergencyAccessDTO(tokenEA2);
logger.info("Setting the TokenCodes on Token {0} with SN: {1}", TokenGuid, tokenEA2.getSerialNumber());
try {
ClientSession ses = connection.newSession();
lostUpdCdCmd.execute(ses);
connection.sessionLogout(ses);
logger.info("Token Lost status succesfully updated.");
} catch (CommandException e) {
logger.error("Token " + tokenEA2.getSerialNumber() + " Emergency Access data Update failure:" + e.getCause() + " - " + e.getMessage()
+ " - " + e.getMessageKey());
throw new RuntimeException("Token " + tokenEA2.getSerialNumber() + " Emergency Access data Update failure.", e);
}
// Convert to ArrayList
tokenCodes = new ArrayList<String>(Arrays.asList(ottAry));
} else {
logger.warn("No TokenCodes retrieved for the given token.");
}
}
// Fetch the updated TokenEA record once again to get the latest
// post-update EA data and return the Other EA Token attributes
LookupTokenEmergencyAccessCommand TokenEAcmd2 = new LookupTokenEmergencyAccessCommand();
TokenEAcmd2.setGuid(TokenGuid);
try {
ClientSession ses = connection.newSession();
TokenEAcmd.execute(ses);
connection.sessionLogout(ses);
logger.info("Succesfully retrieved the Updated Token's Emergency Acces info.");
} catch (CommandException e) {
logger.error("Token " + TokenGuid + " Emergency Access data Lookup failure:" + e.getCause() + " - " + e.getMessage()
+ " - " + e.getMessageKey());
throw new RuntimeException("Token " + TokenGuid + " Emergency Access data Lookup failure.", e);
}
TokenEmergencyAccessDTO tokenEAupd = TokenEAcmd.getTokenEmergencyAccess();
serial = tokenEAupd.getSerialNumber();
eaAccessCode = tokenEAupd.getEmergencyAccessTokenCode();
fixedTokenCode = tokenEAupd.getTemporaryFixedTokencode();
nbUnusedCodes = String.valueOf(tokenEAupd.getNumUnusedCodes());
} else {
logger.warn("Couldn't fetch any Emergency Access (EA) data for the given Token search filter.");
}
}
// Build result handler
ConnectorObjectBuilder builder = new ConnectorObjectBuilder();
builder.setObjectClass(new ObjectClass(RSAAuthenticationManager8Configuration.TOKEN_OBJECTCLASS));
// Create the result multi-valued attribute
if (tokenCodes == null) {
tokenCodes = new ArrayList<String>();
}
// These can't be null or blank in the Connector Object
if (TokenGuid == null) {
TokenGuid = "NotFound";
serial = "NotFound";
}
builder.setUid(serial);
builder.setName(serial);
builder.addAttribute(AttributeBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TEMP_TOKEN_CODES,
tokenCodes));
builder.addAttribute(AttributeBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_EA_ACCESS_CODE, eaAccessCode));
builder.addAttribute(AttributeBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TEMP_FIXED_TOKENCODE, fixedTokenCode));
builder.addAttribute(AttributeBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_IS_LOST, isLost));
builder.addAttribute(AttributeBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_NB_UNUSED_TOKENCODES, nbUnusedCodes));
//Build and call handler for the principal
handler.handle(builder.build());
} else {
// Unsupported Object Class
// TODO - Add support for GROUP and TOKEN ObjClasses
throw new IllegalArgumentException("Unsupported objectclass '" + objectClass.getObjectClassValue() + "'");
}
}
/**
* Result Builder class to handle the results of a search against RSA. This handler handles 1 search result, and is
* called by the framework for every row in the query resultset.
* Calls the ICF 'handle' callback.
*
* @param RSAUser a RSA User Principal as returned by an RSA Search command.
* @param handler The OpenICF Handler to handle these results.
*/
protected void buildUser(PrincipalDTO RSAUser, ResultsHandler handler) {
// Get all attributes
AttributeDTO[] Attribs = extractAttributes(RSAUser);
int sz = Attribs.length;
if (!(searchAll))
logger.info("The RSA Principal has {0} attributes.", sz);
// Instantiate builder
ConnectorObjectBuilder builder = new ConnectorObjectBuilder();
builder.setObjectClass(ObjectClass.ACCOUNT);
// Get Principal UID and set it
builder.setUid(RSAUser.getUserID());
builder.setName(RSAUser.getUserID());
//loop through all attributes
for (AttributeDTO attr : Attribs) {
String name = attr.getName();
Object[] values = attr.getValues();
if (!(searchAll))
logger.info("Attrib: {0} = {1}", name, Arrays.toString(values));
// Skip LoginID since already set
if (!(name.equalsIgnoreCase(PrincipalDTO.LOGINUID)))
builder.addAttribute(AttributeBuilder.build(name, values));
// Uncomment to only return Enabled Principals
//builder.addAttribute(AttributeBuilder.buildEnabled(true));
}
if (!(searchAll)) {
// do not retrieve extra attributes on search all
// Groups
logger.info("Searching for groups...");
GroupDTO[] groups = getUserGroups(RSAUser.getGuid(), RSAUser.getUserID());
if (groups != null) {
if (groups.length > 0) {
logger.info("Found {0} groups.", groups.length);
ArrayList<String> grpNames = new ArrayList<String>();
for (GroupDTO grp : groups) {
grpNames.add(grp.getName());
}
builder.addAttribute(AttributeBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_GROUPS,
grpNames));
}
}
// Default shell
logger.info("Fetching the current AM Principal of user {0}...", RSAUser.getUserID());
LookupAMPrincipalCommand lookupAMCmd = new LookupAMPrincipalCommand();
lookupAMCmd.setGuid(RSAUser.getGuid());
AMPrincipalDTO currAMprincipal = null;
try {
ClientSession ses = connection.newSession();
lookupAMCmd.execute(ses);
connection.sessionLogout(ses);
currAMprincipal = lookupAMCmd.getAmp();
} catch (CommandException e) {
logger.warn("Failed to fetch the AM principal of user:" + RSAUser.getUserID() + " - " + e.getMessage()
+ " - " + e.getMessageKey() + "-" + e.getCause());
}
if (currAMprincipal != null) {
builder.addAttribute(AttributeBuilder.build(AdminResource.DEFAULTSHELL, currAMprincipal.getDefaultShell()));
}
}
//Build and call handler for the principal
handler.handle(builder.build());
}
// End-SEARCH
/**
* {@inheritDoc}
*/
// TODO
public void test() {
logger.info("Performing Connector Test");
this.connection.test();
String defCommandTgt = null;
defCommandTgt = CommandTargetPolicy.getDefaultCommandTarget().toString();
logger.info("Using default command target for this thread: {0}",defCommandTgt);
/*try {
this.lookupSecurityDomain(this.configuration.getSecurityDomain());
} catch (Exception ex) {
logger.error("Connection Test Failed: {0}", ex.getMessage());
throw new RuntimeException("Connection Test Failed", ex);
}*/
}
/**
* {@inheritDoc}
*/
// TODO
public Uid update(ObjectClass objectClass, Uid uid, Set<Attribute> replaceAttributes, OperationOptions options) {
//throw new UnsupportedOperationException();
Iterator rai = replaceAttributes.iterator();
while (rai.hasNext()) {
Attribute attr = (Attribute)rai.next();
try {
logger.info("Inbound Replace Attribute: {0} = {1}",attr.getName(), attr.getValue());
} catch (Exception e) {
logger.error("failed to log Attribute name/value: " + e.getMessage());
}
}
// Look for requested User
PrincipalDTO user;
try {
logger.info("Looking for user: " + uid.getUidValue() + "...");
user = lookupUser(uid.getUidValue());
logger.info("Found user.");
// this.UserPrincipal = user;
} catch (Exception e) {
logger.error("Couldn't find the requested user to update. Error: " + e.getMessage() + " - " + e.getCause());
throw new UnknownUidException("Unable to update user: " + uid.getUidValue(), e);
}
/* */// DEBUG
AttributeDTO[] attribs = user.getAttributes();
logger.info("attribs length = " + attribs.length);
for (AttributeDTO attrib : attribs)
logger.info("Attrib Name = {0} - Value = {1}", attrib.getName(), attrib.getValues()[0]);
// END-DEBUG */
// Read Update Attributes
AttributesAccessor aa = new AttributesAccessor(replaceAttributes);
// USER ACCOUNT
if (objectClass.is("__ACCOUNT__")) {
HashMap<String, Object> AttribMap = new HashMap<String, Object>();
// Operation Attributes
if (aa.getPassword() != null) AttribMap.put(PrincipalDTO.PASSWORD, aa.getPassword());
//AttribMap.put(PrincipalDTO.LOGINUID, uid.getUidValue());
// Flag indicating whether the principal is enabled or not
AttribMap.put(PrincipalDTO.ENABLE_FLAG, aa.getEnabled(true));
// Flag indicating whether principal is locked out of the system.
// Maintained by system, do not update
//AttribMap.put(PrincipalDTO.LOCKOUT_FLAG, aa.findBoolean(PrincipalDTO.LOCKOUT_FLAG));
// Other Attributes
if (aa.findString(PrincipalDTO.FIRST_NAME) != null) AttribMap.put(PrincipalDTO.FIRST_NAME, aa.findString(PrincipalDTO.FIRST_NAME));
if (aa.findString(PrincipalDTO.LAST_NAME) != null) AttribMap.put(PrincipalDTO.LAST_NAME, aa.findString(PrincipalDTO.LAST_NAME));
if (aa.findString(PrincipalDTO.DESCRIPTION) != null) AttribMap.put(PrincipalDTO.DESCRIPTION, aa.findString(PrincipalDTO.DESCRIPTION));
if (aa.findString(PrincipalDTO.MIDDLE_NAME) != null) AttribMap.put(PrincipalDTO.MIDDLE_NAME, aa.findString(PrincipalDTO.MIDDLE_NAME));
if (aa.findString(PrincipalDTO.EMAIL) != null) AttribMap.put(PrincipalDTO.EMAIL, aa.findString(PrincipalDTO.EMAIL));
// Flag indicating principal has administrative roles.
// Maintained by system, do not update.
//AttribMap.put(PrincipalDTO.ADMINISTRATOR_FLAG, aa.findBoolean(PrincipalDTO.ADMINISTRATOR_FLAG));
// Date Format for all dates:
SimpleDateFormat sdf = new SimpleDateFormat(RSAAuthenticationManager8Configuration.DATE_FORMAT);
Date d;
// Date principal's account will expire.
String endDt = aa.findString(PrincipalDTO.EXPIRATION_DATE);
if ((endDt==null) || (endDt.isEmpty())) {
// Try to find the temp end date
endDt = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TEMP_END_DATE);
}
if (endDt != null) {
try {
d = sdf.parse(endDt);
} catch (ParseException e) {
logger.error("Invalid date format for EXPIRATION_DATE. Expected format {0}, found {1} ",
RSAAuthenticationManager8Configuration.DATE_FORMAT,
endDt);
throw new IllegalArgumentException("Invalid Date Format");
}
AttribMap.put(PrincipalDTO.EXPIRATION_DATE, d);
}
// Principal's Start Date
String startDt = aa.findString(PrincipalDTO.START_DATE);
if ((startDt==null) || (startDt.isEmpty())) {
// Try to find the temp end date
startDt = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TEMP_START_DATE);
}
if (startDt != null) {
try {
d = sdf.parse(startDt);
} catch (ParseException e) {
logger.error("Invalid date format for START_DATE. Expected format {0}, found {1} ",
RSAAuthenticationManager8Configuration.DATE_FORMAT,
startDt);
throw new IllegalArgumentException("Invalid Date Format");
}
AttribMap.put(PrincipalDTO.START_DATE, d);
}
// Date principal will no longer be locked out of the system.
// Unsupported--
/*
try {
d = sdf.parse(aa.findString(PrincipalDTO.EXPIRE_LOCKOUT_DATE));
} catch (ParseException e) {
logger.error ("Invalid date format for EXPIRE_LOCKOUT_DATE. Expected format: " + this.configuration.DATE_FORMAT);
throw new ConnectorException ("Invalid Date Format");
}
AttribMap.put(PrincipalDTO.EXPIRE_LOCKOUT_DATE, d);
*/
// Flag indicating if principal can be impersonated.
Boolean impers = aa.findBoolean(PrincipalDTO.IMPERSONATABLE_FLAG);
if (impers != null)
AttribMap.put(PrincipalDTO.IMPERSONATABLE_FLAG, impers);
// Flag indicating if principal can impersonate others.
impers = aa.findBoolean(PrincipalDTO.IMPERSONATOR_FLAG);
if (impers != null)
AttribMap.put(PrincipalDTO.IMPERSONATOR_FLAG, impers);
// Extended/Custom attribs
if (aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_EMPLOYEE_NB) != null) AttribMap.put(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_EMPLOYEE_NB, aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_EMPLOYEE_NB));
//AttribMap.put(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_ALLOWED_TO_CREATE_PIN, aa.findBoolean(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_ALLOWED_TO_CREATE_PIN));
//AttribMap.put(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_REQUIRED_TO_CREATE_PIN, aa.findBoolean(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_REQUIRED_TO_CREATE_PIN));
//AttribMap.put(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_SECRET_WORD, aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_SECRET_WORD));
// Initialize RSA Update Command
logger.info("Setting ID Source...");
UpdatePrincipalCommand cmd = new UpdatePrincipalCommand();
cmd.setIdentitySourceGuid(user.getIdentitySourceGuid());
// Instantiate RSA Update Object
UpdatePrincipalDTO updateDTO = new UpdatePrincipalDTO();
updateDTO.setGuid(user.getGuid());
// copy the rowVersion to satisfy optimistic locking requirements
updateDTO.setRowVersion(user.getRowVersion());
// Modifications:
List<ModificationDTO> mods = new ArrayList<ModificationDTO>();
ModificationDTO mod = new ModificationDTO();
// User's current attributes:
AttributeDTO[] currAttribs = extractAttributes(user);
// Handle attributes
for (Map.Entry<String, Object> entry : AttribMap.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
// call private method for attribute handling
mod = handleAttribute(key, value, currAttribs);
try {
logger.info("Adding Update Attribute: " + mod.getOperation() + " - " + mod.getName() + " - " +
mod.getValues()[0]);
mods.add(mod);
} catch (NullPointerException npe) {
if (mod.getOperation() == ModificationDTO.REMOVE_ATTRIBUTE)
mods.add(mod);
else
logger.warn("Mod for Attribute: " + key + " is null, skipping.");
}
}
// set the requested updates into the UpdatePrincipalDTO
updateDTO.setModifications(mods.toArray(new ModificationDTO[mods.size()]));
cmd.setPrincipalModification(updateDTO);
// perform the update
try {
ClientSession ses = connection.newSession();
cmd.execute(ses);
connection.sessionLogout(ses);
logger.info("User Principal Updated.");
} catch (CommandException e) {
logger.error("User Principal Update Failure, message: " + e.getMessage() + " Key: " +
e.getMessageKey() + " Cause: " + e.getCauses());
throw new ConnectorException("Update Principal failure.", e);
}
// TODO - Update Default Shell
String DefShell = aa.findString(AdminResource.DEFAULTSHELL);
Boolean ShellAllowed = Boolean.FALSE;
if ((DefShell != null) && (!(DefShell.isEmpty()))) {
// Default shell value provided, need an AM account.
ShellAllowed = aa.findBoolean(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_SHELL_ALLOWED);
if (ShellAllowed == null)
// No Default Shell Allowed value provided, assume TRUE since a Shell value is provided.
ShellAllowed = Boolean.TRUE;
// Else use whatever Shell Allowed value is provided
// Fetch the current AMPrincipal to ensure the update AMPrincipalDTO object
// has the right row version for optimistic locking
logger.info("Fetching the current AM Principal of user {0}...", user.getUserID());
LookupAMPrincipalCommand lookupAMCmd = new LookupAMPrincipalCommand();
lookupAMCmd.setGuid(user.getGuid());
AMPrincipalDTO currAMprincipal = null;
try {
ClientSession ses = connection.newSession();
lookupAMCmd.execute(ses);
connection.sessionLogout(ses);
currAMprincipal = lookupAMCmd.getAmp();
} catch (CommandException e) {
logger.warn("Failed to fetch the AM principal of user:" + user.getUserID() + " - " + e.getMessage()
+ " - " + e.getMessageKey() + "-" + e.getCause());
currAMprincipal = new AMPrincipalDTO();
}
logger.info("Updating Default Shell on AM Principal...");
//AMPrincipalDTO AMprincipal = new AMPrincipalDTO();
//currAMprincipal.setGuid(user.getGuid());
currAMprincipal.setDefaultShell(DefShell);
currAMprincipal.setDefaultUserIdShellAllowed(ShellAllowed);
//currAMprincipal.setRowVersion(user.getRowVersion());
//AMprincipal.setStaticPassword(RSAAuthenticationManager8Utils.getPlainPassword(Password));
//AMprincipal.setStaticPasswordSet(false);
//AMprincipal.setWindowsPassword(WinPwd);
// Perform Account Creation
UpdateAMPrincipalCommand AMUpdcmd = new UpdateAMPrincipalCommand(currAMprincipal);
try {
ClientSession ses = connection.newSession();
AMUpdcmd.execute(ses);
connection.sessionLogout(ses);
logger.info("AM Principal Updated.");
} catch (CommandException e) {
logger.error("An exception was thrown by the RSA AM command: " + e.getMessage() + " key: " +
e.getMessageKey() + " cause: " + e.getCause());
throw new ConnectorException("Update AM Principal failure.", e);
}
}
// Update Groups
List<Object> Groups = aa.findList(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_GROUPS);
ArrayList<String> GroupsList = new ArrayList<String>();
// Process Group List
if (Groups != null) {
if (!(Groups.isEmpty())) {
logger.info("Processing user {0}'s {1} groups...", user.getUserID(), Groups.size());
// Convert List<Object> to List<String>
for( Object grpobj : Groups ) {
GroupsList.add( grpobj.toString() );
}
//linkGroups2User(GroupsList.toArray(new String[GroupsList.size()]), user);
processGroups (user, GroupsList);
}
}
// Update Tokens
/* */
// Token Action Lists
// Tokens to assign:
ArrayList<String> assignTokenList = new ArrayList<String>();
// Tokens to unassign:
ArrayList<String> unassignTokenList = new ArrayList<String>();
// Tokens to Disable
ArrayList<String> disableTokenList = new ArrayList<String>();
// Tokens to Enable
ArrayList<String> enableTokenList = new ArrayList<String>();
// Assign new Tokens
// If a SN is provided, then assign the token
String Serial1 = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN1_SN);
if (Serial1 != null)
if (!(Serial1.isEmpty()))
assignTokenList.add(Serial1);
String Serial2 = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN2_SN);
if (Serial2 != null)
if (!(Serial2.isEmpty()))
assignTokenList.add(Serial2);
String Serial3 = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN3_SN);
if (Serial3 != null)
if (!(Serial1.isEmpty()))
assignTokenList.add(Serial3);
// Assign Tokens in bulk
logger.info("Assigning {0} tokens to user {1}...", assignTokenList.size(), user.getUserID());
AssignTokens2User(assignTokenList, user.getGuid());
// Get the User's currently assigned Tokens
// The array is sorted by ascending Serial Number
TokenDTO[] tokens = getUserTokens(user.getGuid());
TokenDTO Token1 = null;
TokenDTO Token2 = null;
TokenDTO Token3 = null;
int n = tokens.length;
logger.info("User has {0} tokens", n);
if(n== 3) {
Token1 = tokens[0];
Token2 = tokens[1];
Token3 = tokens[2];
} else if (n == 2) {
Token1 = tokens[0];
Token2 = tokens[1];
} else if (n == 1) {
Token1 = tokens[0];
}
// Resynchronize the tokens
// Token #1
//Boolean sync1 = aa.findBoolean(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN1_RESYNC);
Boolean sync1 = Boolean.valueOf(aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN1_RESYNC));
String seq11 = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN1_FIRST_SEQ);
String seq12 = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN1_NEXT_SEQ);
resyncToken (sync1, Token2, seq11, seq12, 1);
// Token #2
Boolean sync2 = Boolean.valueOf(aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN2_RESYNC));
String seq21 = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN2_FIRST_SEQ);
String seq22 = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN2_NEXT_SEQ);
resyncToken (sync2, Token2, seq21, seq22, 2);
// Token #3
Boolean sync3 = Boolean.valueOf(aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN3_RESYNC));
String seq31 = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN3_FIRST_SEQ);
String seq32 = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN3_NEXT_SEQ);
resyncToken (sync3, Token3, seq31, seq32, 3);
// Disable tokens
// Token #1
String token1DisableStr = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN1_DISABLED);
if ((token1DisableStr != null) && (!(token1DisableStr.isEmpty()))) {
if (Token1 == null) {
logger.error("Token Disable/Enable requested but the user doesn't have a Token 1.");
throw new IllegalArgumentException ("Token Disable/Enable requested but the user doesn't have a Token 1.");
} else if (Boolean.valueOf(token1DisableStr))
disableTokenList.add(Token1.getId());
else
enableTokenList.add(Token1.getId());
}
// Token #2
String token2DisableStr = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN2_DISABLED);
if ((token2DisableStr != null) && (!(token2DisableStr.isEmpty()))) {
if (Token2 == null) {
logger.error("Token Disable/Enable requested but the user doesn't have a Token 2.");
throw new IllegalArgumentException ("Token Disable/Enable requested but the user doesn't have a Token 2.");
}
Boolean doDisable = Boolean.valueOf(token2DisableStr);
if (doDisable) {
disableTokenList.add(Token2.getId());
}
else {
enableTokenList.add(Token2.getId());
}
}
// Token #3
String token3DisableStr = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN3_DISABLED);
if ((token3DisableStr != null) && (!(token3DisableStr.isEmpty()))) {
if (Token3 == null) {
logger.error("Token Disable/Enable requested but the user doesn't have a Token 3.");
throw new IllegalArgumentException ("Token Disable/Enable requested but the user doesn't have a Token 3.");
} else if (Boolean.valueOf(token3DisableStr)){
disableTokenList.add(Token3.getId());
}
else {
enableTokenList.add(Token3.getId());
}
}
// Perform disable/enable in bulk
if (disableTokenList.size() > 0) {
logger.info("Disabling {0} token(s)", disableTokenList.size());
EnableTokens(disableTokenList.toArray(new String[disableTokenList.size()]), false);
}
if (enableTokenList.size() > 0) {
logger.info("Enabling {0} token(s)", enableTokenList.size());
EnableTokens(enableTokenList.toArray(new String[enableTokenList.size()]), true);
}
// Lost Tokens
// Token #1
String token1LostStr = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN1_LOST);
processLostToken(token1LostStr, Token1, 1);
// Token #2
String token2LostStr = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN2_LOST);
processLostToken(token2LostStr, Token2, 2);
// Token #1
String token3LostStr = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN3_LOST);
processLostToken(token3LostStr, Token3, 3);
// Unassign Tokens
// Token #1
String doRevokeToken1 = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN1_UNASSIGN);
if ((doRevokeToken1 != null) && (!(doRevokeToken1.isEmpty()))) {
if (Boolean.valueOf(doRevokeToken1)) {
// Revoke the token
if (Token1 != null) {
unassignTokenList.add(Token1.getSerialNumber());
} else {
logger.error("Token revocation requested but the user doesn't have a Token 1.");
throw new IllegalArgumentException ("Token revocation requested but the user doesn't have a Token 1.");
}
}
}
// Token #2
String doRevokeToken2 = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN2_UNASSIGN);
if ((doRevokeToken2 != null) && (!(doRevokeToken2.isEmpty()))) {
if (Boolean.valueOf(doRevokeToken2)) {
// Revoke the token
if (Token2 != null) {
unassignTokenList.add(Token2.getSerialNumber());
} else {
logger.error("Token revocation requested but the user doesn't have a Token 2.");
throw new IllegalArgumentException ("Token revocation requested but the user doesn't have a Token 2.");
}
}
}
// Token #3
String doRevokeToken3 = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN3_UNASSIGN);
if ((doRevokeToken3 != null) && (!(doRevokeToken3.isEmpty()))) {
if (Boolean.valueOf(doRevokeToken3)) {
// Revoke the token
if (Token3 != null) {
unassignTokenList.add(Token3.getSerialNumber());
} else {
logger.error("Token revocation requested but the user doesn't have a Token 3.");
throw new IllegalArgumentException ("Token revocation requested but the user doesn't have a Token 3.");
}
}
}
if (unassignTokenList.size() > 0)
RevokeTokens(unassignTokenList);
// Update Pin
// Token #1
String token1PinMode = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN1_NEW_PIN_MODE);
String token1ClearPin = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN1_CLEAR_PIN);
String token1Pin = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN1_PIN);
logger.info("token1PinMode: {0}, token1Pin: {1}, token1ClearPin: {2}", token1PinMode, token1Pin, token1ClearPin);
updateTokenPin(Token1,token1PinMode,token1Pin,token1ClearPin,1);
// Token #2
String token2PinMode = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN2_NEW_PIN_MODE);
String token2ClearPin = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN2_CLEAR_PIN);
String token2Pin = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN2_PIN);
logger.info("token2PinMode: {0},token2Pin: {1}, token2ClearPin: {2}", token2PinMode, token2Pin, token2ClearPin);
updateTokenPin(Token2,token2PinMode,token2Pin,token2ClearPin,2);
// Token #3
String token3PinMode = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN3_NEW_PIN_MODE);
String token3ClearPin = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN3_CLEAR_PIN);
String token3Pin = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN3_PIN);
logger.info("token3PinMode: {0}, token3Pin: {1}, token3ClearPin: {2}", token3PinMode, token3Pin, token3ClearPin);
updateTokenPin(Token3,token3PinMode,token3Pin,token3ClearPin,3);
/* */
// TOKEN
} else if (objectClass.is(RSAAuthenticationManager8Configuration.TOKEN_OBJECTCLASS)) {
// Get Token List
List<String> TokenSNs = aa.findStringList(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN_SN_LIST);
// Get Token operation
Map<String,Object> TokenOpts = options.getOptions();
// Only 1 option is expected, only read the first one.
Integer action = (Integer) TokenOpts.entrySet().iterator().next().getValue();
// Perform operation
switch (action) {
case 1:
// RSAAuthenticationManager8Configuration.TOKEN_OP_OPTION_ASSIGN - Assign tokens
logger.info("Assigning Tokens to user {0}...", uid.getUidValue());
AssignTokens2User(TokenSNs, user.getGuid());
logger.info("Tokens succesfully assigned.");
break;
case 2:
// RSAAuthenticationManager8Configuration.TOKEN_OP_OPTION_REVOKE - Revoke tokens
logger.info("Revoking Tokens...");
RevokeTokens(TokenSNs);
logger.info("Tokens succesfully revoked.");
break;
case 3:
// RSAAuthenticationManager8Configuration.TOKEN_OP_OPTION_DISABLE - disable tokens
logger.info("Disabling Tokens");
EnableTokens(TokenSerials2GUIDs(TokenSNs), false);
logger.info("Tokens succesfully disabled.");
break;
case 4:
// RSAAuthenticationManager8Configuration.TOKEN_OP_OPTION_ENABLE - enable tokens
logger.info("Enabling Tokens");
EnableTokens(TokenSerials2GUIDs(TokenSNs), true);
logger.info("Tokens succesfully enabled.");
break;
default:
logger.warn("The requested Token operation: {0} is not supported. Ignoring.", action);
break;
}
// GROUP
} else if (objectClass.is("__GROUP__")) {
// Get Group Name
String GroupName = aa.findString(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_GROUP_NAME);
// Get Group operation
Map<String,Object> GroupOpts = options.getOptions();
// Only 1 option is expected, only read the first one.
Integer action = (Integer) GroupOpts.entrySet().iterator().next().getValue();
// Perform operation
switch (action) {
case 1:
// RSAAuthenticationManager8Configuration.GROUP_OP_OPTION_LINK - Link Group
logger.info("Linking Group {0} to user {1}...", GroupName, uid.getUidValue());
linkGroups2User (new String[] {GroupName}, user);
break;
case 2:
// RSAAuthenticationManager8Configuration.GROUP_OP_OPTION_UNLINK - Unlink Group
logger.info("Unlinking Group {0} from user {1}...", GroupName, uid.getUidValue());
unlinkGroupsFromUser(new String[] {GroupName}, user);
break;
default:
logger.warn("The requested Group operation: {0} is not supported. Ignoring.", action);
break;
}
// UNSUPPORTED Object Class
} else {
logger.error("The RSA connector doesn't support Update of objectClass: {0}",
objectClass.getDisplayNameKey());
throw new UnsupportedOperationException("Connector doesn't support Update of objectClass: " +
objectClass.getDisplayNameKey());
}
return uid;
}
/**
*
* {@inheritDoc}
* @see SchemaOp#schema()
*/
public Schema schema() {
if (configuration == null) {
throw new IllegalStateException("Configuration object has not been set.");
}
logger.info("Building Schema configuration...");
// Create Schema
SchemaBuilder schemaBuilder = new SchemaBuilder(getClass());
Set<AttributeInfo> attributes = new HashSet<AttributeInfo>();
//USER Objects
logger.info("USER attributes...");
// Mandatory Attribute NAME
AttributeInfoBuilder nmeBuilder = new AttributeInfoBuilder();
nmeBuilder.setCreateable(true);
nmeBuilder.setUpdateable(true);
nmeBuilder.setName(Name.NAME);
attributes.add(nmeBuilder.build());
// Mandatory Attribute UID
AttributeInfoBuilder uidBuilder = new AttributeInfoBuilder();
uidBuilder.setCreateable(true);
uidBuilder.setUpdateable(true);
uidBuilder.setName(Uid.NAME);
attributes.add(uidBuilder.build());
//Add all RSA User Principal attributes
attributes.add(AttributeInfoBuilder.build(PrincipalDTO.EMAIL));
attributes.add(AttributeInfoBuilder.build(PrincipalDTO.FIRST_NAME));
attributes.add(AttributeInfoBuilder.build(PrincipalDTO.LAST_NAME));
attributes.add(AttributeInfoBuilder.build(PrincipalDTO.MIDDLE_NAME));
attributes.add(AttributeInfoBuilder.build(PrincipalDTO.CERTDN));
attributes.add(AttributeInfoBuilder.build(PrincipalDTO.DESCRIPTION));
attributes.add(AttributeInfoBuilder.build(PrincipalDTO.ADMINISTRATOR_FLAG));
attributes.add(AttributeInfoBuilder.build(PrincipalDTO.EXPIRATION_DATE));
attributes.add(AttributeInfoBuilder.build(PrincipalDTO.IMPERSONATABLE_FLAG));
attributes.add(AttributeInfoBuilder.build(PrincipalDTO.IMPERSONATOR_FLAG));
attributes.add(AttributeInfoBuilder.build(PrincipalDTO.LAST_UPDATED_BY));
attributes.add(AttributeInfoBuilder.build(PrincipalDTO.LAST_UPDATED_ON));
attributes.add(AttributeInfoBuilder.build(PrincipalDTO.LOCKOUT_FLAG));
attributes.add(AttributeInfoBuilder.build(PrincipalDTO.START_DATE));
attributes.add(AttributeInfoBuilder.build(AdminResource.DEFAULTSHELL));
// Custom:
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_EMPLOYEE_NB));
// Groups is multivalued:
AttributeInfoBuilder grpBuilder = new AttributeInfoBuilder();
grpBuilder.setCreateable(true);
grpBuilder.setUpdateable(true);
grpBuilder.setMultiValued(true);
grpBuilder.setName(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_GROUPS);
attributes.add(grpBuilder.build());
/* not supported yet:
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_ALLOWED_TO_CREATE_PIN));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_REQUIRED_TO_CREATE_PIN));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TEMPUSER));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TEMP_START_DATE ));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TEMP_START_HOUR));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TEMP_END_DATE));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TEMP_END_HOUR));
*/
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_SECRET_WORD ));
// Token Custom Attribs:
// Token 1
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN1_SN ));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN1_PIN ));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN1_RESYNC ));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN1_FIRST_SEQ));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN1_NEXT_SEQ));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN1_DISABLED));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN1_LOST));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN1_NEW_PIN_MODE));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN1_CLEAR_PIN ));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN1_UNASSIGN));
// Token 2
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN2_SN));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN2_PIN ));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN2_RESYNC));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN2_FIRST_SEQ));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN2_NEXT_SEQ));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN2_DISABLED));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN2_LOST ));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN2_NEW_PIN_MODE));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN2_CLEAR_PIN ));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN2_UNASSIGN ));
// Token 3
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN3_SN));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN3_PIN ));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN3_RESYNC));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN3_FIRST_SEQ));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN3_NEXT_SEQ ));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN3_DISABLED));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN3_LOST));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN3_NEW_PIN_MODE));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN3_CLEAR_PIN));
attributes.add(AttributeInfoBuilder.build(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN3_UNASSIGN));
// Operational attributes?
attributes.add(OperationalAttributeInfos.PASSWORD);
attributes.add(OperationalAttributeInfos.ENABLE);
// Build Schema
schemaBuilder.defineObjectClass(ObjectClass.ACCOUNT_NAME, attributes);
// TOKEN objects
logger.info("TOKEN Attributes...");
attributes = new HashSet<AttributeInfo>();
AttributeInfoBuilder aib = new AttributeInfoBuilder();
AttributeInfoBuilder TokenNmeBuilder = new AttributeInfoBuilder();
TokenNmeBuilder.setCreateable(true);
TokenNmeBuilder.setUpdateable(true);
TokenNmeBuilder.setName(Name.NAME);
attributes.add(TokenNmeBuilder.build());
// Mandatory Attribute UID
AttributeInfoBuilder TokenUidBuilder = new AttributeInfoBuilder();
TokenUidBuilder.setCreateable(true);
TokenUidBuilder.setUpdateable(true);
TokenUidBuilder.setName(Uid.NAME);
attributes.add(TokenUidBuilder.build());
// Token List
aib.setMultiValued(true);
aib.setName(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TOKEN_SN_LIST);
attributes.add(aib.build());
// Temp Token List
aib.setMultiValued(true);
aib.setName(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TEMP_TOKEN_CODES);
attributes.add(aib.build());
// Temp Token List
aib.setMultiValued(false);
aib.setName(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_EA_ACCESS_CODE);
attributes.add(aib.build());
aib.setName(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_IS_LOST);
attributes.add(aib.build());
aib.setName(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_NB_UNUSED_TOKENCODES);
attributes.add(aib.build());
aib.setName(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_TEMP_FIXED_TOKENCODE);
attributes.add(aib.build());
schemaBuilder.defineObjectClass(RSAAuthenticationManager8Configuration.TOKEN_OBJECTCLASS, attributes);
// GROUP objects
logger.info("GROUP Attributes...");
attributes = new HashSet<AttributeInfo>();
aib = new AttributeInfoBuilder();
AttributeInfoBuilder GroupNmeBuilder = new AttributeInfoBuilder();
GroupNmeBuilder.setCreateable(true);
GroupNmeBuilder.setUpdateable(true);
GroupNmeBuilder.setName(Name.NAME);
attributes.add(GroupNmeBuilder.build());
// Mandatory Attribute UID
AttributeInfoBuilder GroupUidBuilder = new AttributeInfoBuilder();
GroupUidBuilder.setCreateable(true);
GroupUidBuilder.setUpdateable(true);
GroupUidBuilder.setName(Uid.NAME);
attributes.add(GroupUidBuilder.build());
// Group Name
aib.setName(RSAAuthenticationManager8Configuration.CUSTOM_ATTR_GROUP_NAME);
attributes.add(aib.build());
schemaBuilder.defineObjectClass(ObjectClass.GROUP_NAME, attributes);
return schemaBuilder.build();
}
/**
* {@inheritDoc}
* @see PoolableConnector#checkAlive()
*/
@Override
public void checkAlive() {
logger.info("Checking Connection");
if (this.connection.getDomain() == null) {
logger.info("Connection has no cached realm domain");
throw new RuntimeException (" Pool has no current RSA Connection");
}
if (this.connection.getIdSource() == null){
logger.info("Connection has no cached realm idSource");
throw new RuntimeException (" Pool has no current RSA Connection");
}
//String sessionId = null;
try {
//sessionId = this.connection.getRSASession().getSessionId();
//logger.info("Found session with ID: {0}.", sessionId);
// this.lookupSecurityDomain(this.configuration.getSecurityDomain());
/* check if session alive by querying session with a command
GetSessionCommand cmd = new GetSessionCommand();
cmd.setSessionId(sessionId);
cmd.execute();
SessionDTO session = cmd.getSession();
if (session == null) throw new RuntimeException (" RSA Connection is dead:" + sessionId);
logger.info("The session with ID: {0} is still alive.", sessionId);
logger.info("Session Command Response ID: {0}", session.getId());
logger.info("Session Max Inactivity: {0}", session.getMaxInactivity());
logger.info("Session Max Time To Live: {0}", session.getMaxTimeToLive());
logger.info("Session Creation Time: {0}", session.getCreationTime());
logger.info("Session Client IP: {0}", session.getClientIP());
*/
// as checkalive, query self to see if there is proper response
SearchPrincipalsCommand cmd = new SearchPrincipalsCommand();
cmd.setLimit(RSAAuthenticationManager8Configuration.SEARCH_LIMIT_DEFAULT);
cmd.setIdentitySourceGuid(this.connection.getIdSource().getGuid());
cmd.setSecurityDomainGuid(this.connection.getDomain().getGuid());
cmd.setAttributeMask(new String[]{"CORE_ATTRIBUTES"});
cmd.setFilter(Filter.equal(PrincipalDTO.LOGINUID, configuration.getUserMgrPrincipal()));
cmd.setSearchSubDomains(true);
ClientSession ses = connection.newSession();
logger.info("Performing search for {0}", configuration.getUserMgrPrincipal());
cmd.execute(ses);
connection.sessionLogout(ses);
int numResults = cmd.getPrincipals().length;
logger.info("The connection is still alive. found {0} result", numResults);
} catch (Exception e) {
logger.warn("The connection is not alive: " + e.getMessage());
throw new RuntimeException (" RSA Connection is dead.", e);
}
}
/**
* PRIVATE METHODS
*/
/**
* Update the token's pin mode and/or clears its pin.
*
* @param token A TokenDTO object encapsulating the token to update.
* @param pinMode a String representation of a boolean to determine the new pin mode
* @param pin A string representation of the new pin to set
* @param clear a String representation of a boolean to determine whether to clear the pin or not
* @param tokenNb the token number
*/
private void updateTokenPin (TokenDTO token, String pinMode, String pin, String clear, int tokenNb) {
if (token != null) {
logger.info("Updating token PIN for token {0}, pinMode: {1}, clear: {2}, tokenNb: {3}", token.getSerialNumber(), pinMode, clear, tokenNb);
// Must first fetch the Token object, which includes row versions and all
// Else update may fail on optimistic lock
logger.info("Fetching Token...");
LookupTokenCommand TokCmd = new LookupTokenCommand();
TokCmd.setGuid(token.getId());
try {
ClientSession ses = connection.newSession();
TokCmd.execute(ses);
connection.sessionLogout(ses);
logger.info("token succefully retrieved.");
} catch (CommandException e) {
logger.error ("An error occured while searching for Token with serial: " + token.getSerialNumber());
throw new RuntimeException ("Token search failure.", e);
}
TokenDTO currToken = TokCmd.getToken();
Boolean updated = false;
if ((pinMode != null) && (!(pinMode.isEmpty()))) {
// Set New Pin mode
currToken.setNewPinMode(Boolean.valueOf(pinMode));
updated = true;
logger.info("Set New Pin Mode: {0}.", Boolean.valueOf(pinMode));
}
if ((clear != null) && (!(clear.isEmpty()))) {
// Set Pin is Set
currToken.setPinIsSet(Boolean.valueOf(clear));
updated = true;
logger.info("Set Clear Pin Flag: {0}.", Boolean.valueOf(clear));
}
if ((pin != null) && (!(pin.isEmpty()))) {
// Set New Pin
currToken.setPin(pin);
updated = true;
logger.info("Setting Pin : {0}.", pin);
}
if (updated) {
// Perform the update
logger.info("Updating PIN for token {0}.", tokenNb);
UpdateTokenCommand cmd2 = new UpdateTokenCommand();
cmd2.setToken(currToken);
try {
ClientSession ses = connection.newSession();
cmd2.execute(ses);
connection.sessionLogout(ses);
logger.info("PIN data succesfully updated.");
} catch (ObjectInUseException e) {
logger.error("Can't update the PIN because Token {0} is in use.", tokenNb);
throw new RuntimeException("Token in use, can't update.", e);
} catch (DuplicateDataException e) {
logger.error("Can't update the PIN because of duplicate data on Token {0}.", tokenNb);
throw new RuntimeException("Duplicate Token data, can't update.", e);
} catch (InvalidArgumentException e) {
logger.error("Invalid data passed for Token {0}.", tokenNb);
throw new RuntimeException("Invalid data, can't update.", e);
} catch (DataNotFoundException e) {
logger.error("Can't update the PIN because the supplied Token {0} with serial {1} doesn't exist.",
tokenNb, token.getSerialNumber());
throw new RuntimeException("Token doesn't exist, can't update.", e);
} catch (ConcurrentUpdateException e) {
logger.error("Can't update the PIN because Token {0} is being updated concurrently.", tokenNb);
throw new RuntimeException("Concurrent update, can't proceed.", e);
} catch (InsufficientPrivilegeException e) {
logger.error("Insuficient privileges to update the PIN of Token {0}.", tokenNb);
throw new RuntimeException("Insufficient privileges, can't update.", e);
} catch (CommandException e) {
logger.error("An error occured while updating Token {0}.", tokenNb);
throw new RuntimeException("Token update error.", e);
}
}
}
}
/**
* Resynchronizes the given Token.
*
* @param isSync a boolean specifying whether a resync is requested.
* @param token a TokenDTO object encapsulating the token to resync.
* @param seq1 The First sequence used in token resync.
* @param seq2 The Next sequence used in token resync
* @param tokenNb The token number
*/
private void resyncToken (Boolean isSync, TokenDTO token, String seq1, String seq2, int tokenNb) {
if ((isSync != null) && (isSync)) {
// Need first and next sequences to resync the token.
if ((seq1 == null) || (seq1.isEmpty())) {
logger.error("Token Resync requested but the Token {0}'s FIRST SEQUENCE is not provided.", tokenNb);
throw new IllegalArgumentException("Token " + Integer.toString(tokenNb) +
" Resync requested but the Token's First SEQUENCE is not provided.");
}
if ((seq2 == null) || (seq2.isEmpty())) {
logger.error("Token Resync requested but the Token {0}'s NEXT SEQUENCE is not provided.", tokenNb);
throw new IllegalArgumentException("Token " + Integer.toString(tokenNb) +
" Resync requested but the Token's NEXT SEQUENCE is not provided.");
}
if (token == null) {
logger.error("Token Resync requested but the user doesn't have a Token {0}.", tokenNb);
throw new IllegalArgumentException("Token Resync requested but the user doesn't have a Token" +
Integer.toString(tokenNb));
}
// Resync Tokens
logger.info("Resync-in Token {0} with SN: {1}", tokenNb, token.getSerialNumber());
ResynchronizeTokenCommand sync3Cmd = new ResynchronizeTokenCommand(token.getSerialNumber(), seq1, seq2);
try {
ClientSession ses = connection.newSession();
sync3Cmd.execute(ses);
connection.sessionLogout(ses);
logger.info("Succesfully Resync-ed Token {0}...", tokenNb);
} catch (CommandException e) {
logger.error("Token " + Integer.toString(tokenNb) + " Resync failure:" + e.getCause() + " - " +
e.getMessage() + " - " + e.getMessageKey());
throw new RuntimeException("Token " + Integer.toString(tokenNb) + " Resync failure.", e);
}
}
}
/**
* Processes the Lost status of a given Token.
* This method will not generate Temporary TokenCodes, the SearchOp of the
* __TOKEN__ objectclass will do this instead.
*
* @param isLost a STring representation of a boolean - true if the token is in fact lost.
* @param token the TokenDTO object encapsulating the Token
* @param tokenNb the token number
*/
private void processLostToken (String isLost, TokenDTO token, int tokenNb) {
if (token == null) {
logger.info("Ignoring null token {2}", tokenNb);
} else {
logger.info("Processing Lost Token, token serial = {0}, isLost= {1}. tokenNb={2}", token.getSerialNumber(), isLost, tokenNb);
if ((isLost != null) && (!(isLost.isEmpty()))) {
if (token == null) {
logger.error("Token Lost operation was requested but the user doesn't have a Token {0}.", tokenNb);
throw new IllegalArgumentException("Token Lost operation requested but the user doesn't have a Token " + tokenNb);
}
// Fetch The Token's Emergency Access object
logger.info("Looking for Token {0}'s Emergency Access data..", tokenNb);
LookupTokenEmergencyAccessCommand lostLookupCmd = new LookupTokenEmergencyAccessCommand();
lostLookupCmd.setGuid(token.getId());
try {
ClientSession ses = connection.newSession();
lostLookupCmd.execute(ses);
connection.sessionLogout(ses);
} catch (CommandException e) {
logger.error("Token " + Integer.toString(tokenNb) + " Emergency Access data Lookup failure:" + e.getCause() + " - " + e.getMessage() +
" - " + e.getMessageKey());
throw new RuntimeException("Token " + Integer.toString(tokenNb) + " Emergency Access data Lookup failure.", e);
}
TokenEmergencyAccessDTO tokenEA = lostLookupCmd.getTokenEmergencyAccess();
// Set the token lost flag
Boolean islost = Boolean.valueOf(isLost);
tokenEA.setTokenLost(islost);
if (islost) {
// Set Lost mode: Disable EA and mark token as not lost
// after a successful authentication with the original token
// Temp TokenCodes are generated in SearchOp for the __TOKEN__
// Object class. The RSA SDK doesn't allow for the retrieval
// of the TokenCodes once they are created.
tokenEA.setLostMode(TokenEmergencyAccessDTO.DISABLE_EA_ON_AUTH);
// EA Mode: one-time tokencode
tokenEA.setEaMode(2);
}
// Update the Emergency Data for this token
UpdateTokenEmergencyAccessCommand lostUpdCmd = new UpdateTokenEmergencyAccessCommand ();
lostUpdCmd.setTokenEmergencyAccessDTO(tokenEA);
logger.info("Updating the lost status of Token {0} with SN: {1} to {2}", tokenNb, token.getSerialNumber(), isLost);
try {
ClientSession ses = connection.newSession();
lostUpdCmd.execute(ses);
connection.sessionLogout(ses);
logger.info("Token Lost status succesfully updated.");
} catch (CommandException e) {
logger.error("Token " + Integer.toString(tokenNb) + " Emergency Access data Update failure:" + e.getCause() + " - " + e.getMessage() +
" - " + e.getMessageKey());
throw new RuntimeException("Token " + Integer.toString(tokenNb) + " Emergency Access data Update failure.", e);
}
// Get Emergency TokenCodes for this lost token
// GenerateEmergencyAccessCodeCommand
}
}
}
/**
* Fetches a user's tokens and returns them.
* @param UserGuid The RSA GUID of the user who's tokens to fetch.
* @return array of ListTokenDTO objects for the tokens assigned to the
* given principal; an empty array is returned if principal has no
* assigned tokens
*/
private TokenDTO[] getUserTokens (String UserGuid) {
// Fetch the user's tokens
ArrayList<TokenDTO> tokens = new ArrayList<TokenDTO> ();
ListTokensByPrincipalCommand cmd = new ListTokensByPrincipalCommand(UserGuid);
ListTokenDTO[] tokensList = null;
try {
ClientSession ses = connection.newSession();
cmd.execute(ses);
connection.sessionLogout(ses);
tokensList = cmd.getTokenDTOs();
} catch (DataNotFoundException dne) {
logger.warn("No tokens found for User with GUID {0}.", UserGuid);
} catch (CommandException e) {
logger.error("An error occured while looking for the user tokens");
throw new RuntimeException ("User token lookup error", e);
}
// Sort the Token List
tokensList = sortTokens (tokensList);
// Convert ListTokens into TokenDTO's. ListTokenDTO is not sufficient to update the Token, so we must first
// lookup the full token record.
if (tokensList != null) {
if (tokensList.length > 0) {
for (ListTokenDTO lstToken : tokensList) {
LookupTokenCommand LookupCmd = new LookupTokenCommand();
LookupCmd.setGuid(lstToken.getGuid());
try {
ClientSession ses = connection.newSession();
LookupCmd.execute(ses);
connection.sessionLogout(ses);
} catch (CommandException e) {
logger.error("An error occured while converting list tokens into tokens...");
throw new RuntimeException("User token convertion error", e);
}
tokens.add(LookupCmd.getToken());
} // End-for
} // end-if
} // end-if
return tokens.toArray(new TokenDTO[tokens.size()]);
}
/**
* Sorts an array of ListTokens on their serial numbers
*
* @param tokensList An array of ListTokenDTO objects
* @return a sorted array of ListTokenDTO objects. The Tokens with the lowest Serial Number will be first.
*/
private ListTokenDTO[] sortTokens (ListTokenDTO[] tokensList) {
// Sort the Tokens List by Serial Number
if (tokensList.length > 1) {
// First convert to ArrayList
ArrayList<ListTokenDTO> tokensAryList = new ArrayList<ListTokenDTO>(Arrays.asList(tokensList));
if (!(searchAll))
logger.info("Sorting tokens...");
Collections.sort(tokensAryList, new TokenSerialComparable());
// Convert back to Array
tokensList = tokensAryList.toArray(new ListTokenDTO[tokensAryList.size()]);
}
return tokensList;
}
/**
* Unassign the specified tokens.
*
* @param TokenSerials an Array of Strings storing the Serial Numbers of the Tokens to Un-assign from
* their respective users.
*/
private void RevokeTokens (List<String> TokenSerials ) {
// Convert Serial#'s to GUIDs.
String[] TokensAry = TokenSerials2GUIDs (TokenSerials);
if (TokensAry.length > 0) {
logger.info("Unassigning {0} Tokens...", TokensAry.length);
UnlinkTokensFromPrincipalsCommand UnlinkCmd = new UnlinkTokensFromPrincipalsCommand ();
UnlinkCmd.setTokenGuids(TokensAry);
try
{
ClientSession ses = connection.newSession();
UnlinkCmd.execute(ses);
connection.sessionLogout(ses);
logger.info("Succuesfully unassigned {0} Tokens...", TokensAry.length);
} catch (CommandException e) {
logger.error("An error occured while Un-assigning the tokens given tokens.");
throw new RuntimeException ("Can't unaassign tokens.", e);
}
}
}
/**
* Assign a set of tokens to a user.
*
* @param TokenSerials an Array of Strings storing the Serial Numbers of the Tokens to assign to the user.
* @param UserGuid The GUID of the user. This is not the user's Login ID but the RSA GUID for that user.
* @throws IllegalArgumentException If the provided Serial Number(s) don't match any tokens.
* @throws RuntimeException If the Assign command fails.
*/
private void AssignTokens2User (List<String> TokenSerials, String UserGuid) {
// Convert Serial#'s to GUIDs.
String[] TokensAry = TokenSerials2GUIDs (TokenSerials);
if (TokensAry.length > 0) {
// Enable the tokens
EnableTokens(TokensAry, true);
// Link tokens
LinkTokensWithPrincipalCommand cmd2 = new LinkTokensWithPrincipalCommand(TokensAry, UserGuid);
try {
ClientSession ses = connection.newSession();
cmd2.execute(ses);
connection.sessionLogout(ses);
logger.info("Succesfully assigned {0} tokens to the user.", TokensAry.length);
} catch (CommandException e) {
logger.error("An error occured while assigning the tokens to user {0}.", UserGuid);
throw new RuntimeException ("Can't assign tokens.", e);
}
} else {
// Empty tokens array
logger.warn("No tokens were found to assign, no action was performed.");
}
}
/**
* Converts an input list of Token serial numbers into an array of their corresponding GUIDs read from RSA AM.
*
* @param TokenSerials the list of Token Serial Numbers to convert.
* @return an Array of Strings.
*/
private String[] TokenSerials2GUIDs (List<String> TokenSerials) {
// Array of Token GUIDs to process
ArrayList<String> tokens = new ArrayList<String> ();
// Loop through all provided Token SN's
for (String TokenSN : TokenSerials) {
// First fetch the Token matching the given Serial Number.
TokenDTO token = null;
LookupTokenCommand cmd = new LookupTokenCommand();
cmd.setSerialNumber(TokenSN);
try {
ClientSession ses = connection.newSession();
cmd.execute(ses);
connection.sessionLogout(ses);
token = cmd.getToken();
} catch (CommandException e) {
logger.error("The provided Token Serial Number {0} doesn't match any tokens, or an error occured while fetching the token.", TokenSN);
throw new IllegalArgumentException ("Can't fetch token.", e);
}
if (token != null) {
// Get the Token's GUID
String TokenGUID = token.getId();
// Add token GUID to Array of GUIDs to assign to user
tokens.add(TokenGUID);
} // End if
} // End for
// Convert to Array
return tokens.toArray(new String[tokens.size()]);
}
/**
* Enables a set of Tokens
*
* @param tokens an array of Strings containing the GUIDS of the tokens to enable or disable.
*/
private void EnableTokens (String[] tokens, Boolean enable) {
logger.info("Processing enablement/disablement of {0} Tokens with status = {1}...", tokens.length, Boolean.toString(enable));
EnableTokensCommand EnableCmd = new EnableTokensCommand();
EnableCmd.setTokenGuids(tokens);
EnableCmd.setEnable(enable);
try {
ClientSession ses = connection.newSession();
EnableCmd.execute(ses);
connection.sessionLogout(ses);
logger.info("{0} Tokens processed succesfully.", tokens.length);
} catch (CommandException e) {
logger.error("An error occured while processing the Enablement of the tokens.");
throw new RuntimeException ("Can't process the given tokens.", e);
}
}
/**
* Lookup a security domain by name Searches all levels of the security
* domains hierachy
* @throws Exception
*/
private SecurityDomainDTO lookupSecurityDomain(String name) throws Exception {
SearchSecurityDomainCommand cmd = new SearchSecurityDomainCommand();
cmd.setFilter(Filter.equal(SecurityDomainDTO.NAME_ATTRIBUTE, name));
cmd.setLimit(1);
// in order to search all levels we set searchbase to "*"
cmd.setSearchBase("*");
cmd.setSearchScope(SecurityDomainDTO.SEARCH_SCOPE_SUB);
logger.info("Looking up Security Domain {0}", name);
try {
ClientSession ses = connection.newSession();
cmd.execute(ses);
connection.sessionLogout(ses);
} catch (CommandException e) {
logger.error("An error occured while looking up Domain {0}: {1}", name, e.getMessage());
throw new RuntimeException ("An error occured while looking up Domain", e);
}
if (cmd.getSecurityDomains().length == 0) {
throw new Exception("Could not find security domain " + name);
}
return cmd.getSecurityDomains()[0];
}
/**
* Lookup an agent by name.
*
* @param name the agent name to lookup
* @return the GUID of the agent
* @throws Exception
*/
private ListAgentDTO lookupAgent(String name) throws Exception {
SearchAgentsCommand cmd = new SearchAgentsCommand();
cmd.setFilter(Filter.equal(AgentConstants.FILTER_HOSTNAME, name));
cmd.setLimit(1);
cmd.setSearchBase(connection.getIdSource().getGuid());
// the scope flags are part of the SecurityDomainDTO
cmd.setSearchScope(SecurityDomainDTO.SEARCH_SCOPE_SUB);
ClientSession ses = connection.newSession();
cmd.execute(ses);
connection.sessionLogout(ses);
if (cmd.getAgents().length < 1) {
throw new Exception("ERROR: Unable to find agent " + name + ".");
}
return cmd.getAgents()[0];
}
/**
* Lookup a user by login UID.
*
* @param userId the user login UID
* @return the user record.
* @throws Exception
*/
private PrincipalDTO lookupUser(String userId) throws Exception {
SearchPrincipalsCommand cmd = new SearchPrincipalsCommand();
// create a filter with the login UID equal condition
cmd.setFilter(Filter.equal(PrincipalDTO.LOGINUID, userId));
cmd.setSystemFilter(Filter.empty());
cmd.setLimit(1);
cmd.setIdentitySourceGuid(connection.getIdSource().getGuid());
cmd.setSecurityDomainGuid(connection.getDomain().getGuid());
cmd.setGroupGuid(null);
cmd.setOnlyRegistered(true);
cmd.setSearchSubDomains(true);
cmd.setAttributeMask(new String[]{"ALL_INTRINSIC_ATTRIBUTES", "CORE_ATTRIBUTES", "SYSTEM_ATTRIBUTES", "ALL_EXTENDED_ATTRIBUTES"}); //"ALL_ATTRIBUTES"
ClientSession ses = connection.newSession();
cmd.execute(ses);
connection.sessionLogout(ses);
if (cmd.getPrincipals().length < 1) {
throw new UnknownUidException("Unable to find user " + userId + ".");
}
return cmd.getPrincipals()[0];
}
/**
* Processes the Principal's given attribute name/value to create a RSA Modification DTO row as follows:
* <ul>
* <li> Replace all of the current values of that attribute in the target object with the provided values of that attribute.</li>
* <li> If the target object does not currently contain an attribute that the input set contains,
* then add this attribute (along with the provided values) to the target object.</li>
* <li> If the value of an attribute in the input set is null, then remove that attribute from the target
* object entirely </li>
* </ul>
*
* @param AttribName
* @param AttribVal
* @return
*/
private ModificationDTO handleAttribute (String AttribName, Object AttribVal, AttributeDTO[] UserAttribs) {
ModificationDTO ModRow = new ModificationDTO();
logger.info("\n Handing attribute : " + AttribName + " with value: " + AttribVal);
// Do NOT remove these attributes:
String[] doNotRemove = new String[] {
PrincipalDTO.PASSWORD, PrincipalDTO.LOGINUID, PrincipalDTO.ADMINISTRATOR_FLAG };
if (AttribVal == null) {
// Remove Attribute from target entry except the above
if (!(Arrays.asList(doNotRemove).contains(AttribName))) {
ModRow.setOperation(ModificationDTO.REMOVE_ATTRIBUTE);
ModRow.setName(AttribName);
}
} else {
// Check if attribute exists on target entry
Boolean found = false;
// Search for attribute
for (int i = 0; i < UserAttribs.length; i++) {
if (UserAttribs[i].getName().equals(AttribName)) {
// found attribute
found = true;
break;
}
}
if (AttribName == PrincipalDTO.PASSWORD) {
// Special case for pwd: decrypt the Guarded String
AttribVal = RSAAuthenticationManager8Utils.getPlainPassword((GuardedString) AttribVal);
}
if (found) {
// Found: Replace attribute value
ModRow.setOperation(ModificationDTO.REPLACE_ATTRIBUTE);
ModRow.setName(AttribName);
ModRow.setValues(new Object[] { AttribVal });
} else {
// Not found: add the attribute
ModRow.setOperation(ModificationDTO.ADD_ATTRIBUTE);
ModRow.setName(AttribName);
ModRow.setValues(new Object[] { AttribVal });
} // end Found
} // end attrib == null
return ModRow;
}
/**
* The RSA SDK doesn't provide a convenience method to extract all attributes from a Principal DTO object. The
* Principal's attributes must be read one by one by their authenticationors.
* This methods extracts all of a User Principal's attributes and stores them into an array of AttributeDTO's.
*
* @param User the Principal's DTO object
* @return and array of AttributeDTO encapsulating the user's attributes.
*/
private AttributeDTO[] extractAttributes (PrincipalDTO User) {
// Extended attributes:
AttributeDTO[] attribs = User.getAttributes();
logger.info("====== Extracting Attribs - attribs size = {0}", attribs.length);
ArrayList<AttributeDTO> AttribList = new ArrayList<AttributeDTO>(Arrays.asList(attribs));
logger.info("====== Attribs List size = {0}", AttribList.size());
// Core Attributes:
AttributeDTO loginAttr = new AttributeDTO();
loginAttr.setName(PrincipalDTO.LOGINUID);
String[] id = { User.getUserID() };
loginAttr.setValues(id);
AttribList.add(loginAttr);
AttributeDTO emailAttr = new AttributeDTO();
emailAttr.setName(PrincipalDTO.EMAIL);
String[] email = { User.getEmail() };
emailAttr.setValues(email);
AttribList.add(emailAttr);
AttributeDTO fnameAttr = new AttributeDTO();
fnameAttr.setName(PrincipalDTO.FIRST_NAME);
String[] fname = { User.getFirstName() };
fnameAttr.setValues(fname);
AttribList.add(fnameAttr);
AttributeDTO lnameAttr = new AttributeDTO();
lnameAttr.setName(PrincipalDTO.LAST_NAME);
String[] lname = { User.getLastName() };
lnameAttr.setValues(lname);
AttribList.add(lnameAttr);
AttributeDTO mnameAttr = new AttributeDTO();
mnameAttr.setName(PrincipalDTO.MIDDLE_NAME);
String[] mname = { User.getMiddleName() };
mnameAttr.setValues(mname);
AttribList.add(mnameAttr);
AttributeDTO certdnAttr = new AttributeDTO();
certdnAttr.setName(PrincipalDTO.CERTDN);
String[] cdn = { User.getCertificateDN() };
certdnAttr.setValues(cdn);
AttribList.add(certdnAttr);
// System Attributes:
AttributeDTO descrAttr = new AttributeDTO();
descrAttr.setName(PrincipalDTO.DESCRIPTION);
String[] descr = { User.getDescription() };
descrAttr.setValues(descr);
AttribList.add(descrAttr);
AttributeDTO adminAttr = new AttributeDTO();
adminAttr.setName(PrincipalDTO.ADMINISTRATOR_FLAG);
Boolean[] admin = { User.isAdminRole() };
adminAttr.setValues(admin);
AttribList.add(adminAttr);
AttributeDTO enbAttr = new AttributeDTO();
enbAttr.setName(PrincipalDTO.ENABLE_FLAG);
Boolean[] enb = { User.isEnabled() };
enbAttr.setValues(enb);
AttribList.add(enbAttr);
// Date Format for dates
DateFormat df = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
AttributeDTO expDtAttr = new AttributeDTO();
expDtAttr.setName(PrincipalDTO.EXPIRATION_DATE);
Date expDt = User.getAccountExpireDate();
if (expDt != null) {
String[] expDtStr = { df.format(expDt) };
expDtAttr.setValues(expDtStr);
AttribList.add(expDtAttr);
}
AttributeDTO impAttr = new AttributeDTO();
impAttr.setName(PrincipalDTO.IMPERSONATABLE_FLAG);
Boolean[] imp = { User.isCanBeImpersonated() };
impAttr.setValues(imp);
AttribList.add(impAttr);
AttributeDTO trustAttr = new AttributeDTO();
trustAttr.setName(PrincipalDTO.IMPERSONATOR_FLAG);
Boolean[] trust = { User.isTrustToImpersonate() };
trustAttr.setValues(trust);
AttribList.add(trustAttr);
AttributeDTO adminFlagAttr = new AttributeDTO();
adminFlagAttr.setName(PrincipalDTO.ADMINISTRATOR_FLAG);
Boolean[] adminFlag = { User.isAdminRole() };
adminFlagAttr.setValues(adminFlag);
AttribList.add(trustAttr);
AttributeDTO modAttr = new AttributeDTO();
modAttr.setName(PrincipalDTO.LAST_UPDATED_BY);
String[] mod = { User.getLastModifiedBy() };
modAttr.setValues(mod);
AttribList.add(modAttr);
AttributeDTO modDtAttr = new AttributeDTO();
modDtAttr.setName(PrincipalDTO.LAST_UPDATED_ON);
Date modDt = User.getLastModifiedOn();
if (modDt != null) {
String[] modDtStr = { df.format(modDt) };
modDtAttr.setValues(modDtStr);
AttribList.add(modDtAttr);
}
AttributeDTO lockAttr = new AttributeDTO();
lockAttr.setName(PrincipalDTO.LOCKOUT_FLAG);
Boolean[] lock = { User.isLockoutStatus() };
lockAttr.setValues(lock);
AttribList.add(lockAttr);
AttributeDTO startAttr = new AttributeDTO();
startAttr.setName(PrincipalDTO.START_DATE);
Date start = User.getAccountStartDate();
if (start != null) {
String[] startStr = { df.format(start) };
startAttr.setValues(startStr);
AttribList.add(startAttr);
}
// Extended Attributes
/* *
AttributeDTO[] extendedAttrs = User.getAttributes();
if (!(searchAll))
logger.info("Extracted {0} extended attributes. Adding...", extendedAttrs.length);
for (AttributeDTO extendedAttr : extendedAttrs) {
AttribList.add(extendedAttr);
}
/* */
// User's Token Attributes
// TokenDTO[] tokens = getUserTokens(User.getGuid());
// Fetch the user's tokens
//ArrayList<TokenDTO> tokens = new ArrayList<TokenDTO> ();
if (!(searchAll))
logger.info("Fetching {0}'s assigned tokens...", User.getUserID());
ListTokensByPrincipalCommand cmd = new ListTokensByPrincipalCommand(User.getGuid());
ListTokenDTO[] tokensList = null;
try {
ClientSession ses = connection.newSession();
cmd.execute(ses);
connection.sessionLogout(ses);
tokensList = cmd.getTokenDTOs();
if (!(searchAll))
logger.info("Found {0} tokens.",tokensList.length);
} catch (DataNotFoundException dne) {
logger.warn("No tokens found for User with GUID {0}.", User.getGuid());
} catch (CommandException e) {
logger.error("An error occured while looking for the user tokens");
throw new RuntimeException("User token lookup error", e);
}
if (tokensList != null) {
// Sort the tokens by serial numbers
/* */
tokensList = sortTokens (tokensList);
/* */
// Process results
for (int i = 0; i < tokensList.length; i++) {
ListTokenDTO token = tokensList[i];
// Build custom attribute name using the array index as token identifier
String TokenPrefix = "token";
// Serial #
//logger.info("---- Token serial #: {0}",token.getSerialNumber());
String serial = new StringBuffer(TokenPrefix).append(Integer.toString(i+1)).append("SerialNumber").toString();
AttributeDTO serialAttr = new AttributeDTO();
serialAttr.setName(serial);
String[] sn = { token.getSerialNumber() };
serialAttr.setValues(sn);
AttribList.add(serialAttr);
// Token Lost
//logger.info("---- Token Lost #: {0}",token.getTokenLost());
String lost = new StringBuffer(TokenPrefix).append(Integer.toString(i+1)).append("Lost").toString();
AttributeDTO lostAttr = new AttributeDTO();
lostAttr.setName(lost);
String[] tokenLost = { Boolean.toString(token.getTokenLost()) };
lostAttr.setValues(tokenLost);
AttribList.add(lostAttr);
// New Pin Mode
//logger.info("---- Token New Pin Mode #: {0}",token.getNewPinMode());
String newPinMode = new StringBuffer(TokenPrefix).append(Integer.toString(i+1)).append("NewPinMode").toString();
AttributeDTO newPinModeAttr = new AttributeDTO();
newPinModeAttr.setName(newPinMode);
String[] newPinModeAry = { Boolean.toString(token.getNewPinMode()) };
newPinModeAttr.setValues(newPinModeAry);
AttribList.add(newPinModeAttr);
// Disabled?
//logger.info("---- Token disabled #: {0}",token.getEnable());
String disabled = new StringBuffer(TokenPrefix).append(Integer.toString(i+1)).append("Disabled").toString();
AttributeDTO disabledAttr = new AttributeDTO();
disabledAttr.setName(disabled);
Boolean disable = !(token.getEnable()); // Return a DISABLED flag
String[] disabledAry = { Boolean.toString(disable) };
disabledAttr.setValues(disabledAry);
AttribList.add(disabledAttr);
} // End-for
} // End-if TokenList
return AttribList.toArray(new AttributeDTO[AttribList.size()]);
}
/**
* Lookup a group by name.
*
* @param name the name of the group to lookup
* @return the GUID of the group
* @throws Exception
*/
private GroupDTO lookupGroup(String name) {
SearchGroupsCommand cmd = new SearchGroupsCommand();
cmd.setFilter(Filter.equal(GroupDTO.NAME, name));
cmd.setSystemFilter(Filter.empty());
cmd.setLimit(1);
cmd.setIdentitySourceGuid(this.connection.getIdSource().getGuid());
cmd.setSecurityDomainGuid(this.connection.getDomain().getGuid());
cmd.setSearchSubDomains(true);
cmd.setGroupGuid(null);
try {
ClientSession ses = connection.newSession();
cmd.execute(ses);
connection.sessionLogout(ses);
} catch (DataNotFoundException e) {
logger.error ("Unable to find group {0}.", name);
throw new RuntimeException ("Unable to find group.", e);
} catch (InvalidArgumentException e) {
logger.error ("The provide group name: {0} is invalid.", name);
throw new RuntimeException ("Invalid group name.", e);
} catch (InsufficientPrivilegeException e) {
logger.error ("Insufficient privileges to find group {0}.", name);
throw new RuntimeException ("Insufficient privileges.", e);
} catch (CommandException e) {
logger.error ("An error occured while looking for group {0}.", name);
throw new RuntimeException ("Unable to find group.", e);
}
if (cmd.getGroups().length < 1) {
throw new UnknownUidException("Unable to find group " + name + ".");
}
return cmd.getGroups()[0];
}
/**
* Fetch all of a RSA Principal's groups.
*
* @param userGUID the user Principal's GUID
* @param userID The user princpal's loging ID
* @return an Array of GroupDTO objects encapsulating the user's groups
*/
private GroupDTO[] getUserGroups (String userGUID, String userID) {
GroupDTO[] groups;
if (!(searchAll))
logger.info("Fetching the list of groups user {0} in Security Domain {1} is a member of..."
, userID, this.connection.getIdSource().getGuid());
GetPrincipalGroupsCommand cmd = new GetPrincipalGroupsCommand();
//GetUserGroupsCommand cmd = new GetUserGroupsCommand();
cmd.setGuid(userGUID);
cmd.setIdentitySourceGuid(this.connection.getIdSource().getGuid());
//cmd.setSecurityDomainID(this.connection.getDomain().getGuid());
try {
ClientSession ses = connection.newSession();
cmd.execute(ses);
connection.sessionLogout(ses);
groups = cmd.getGroups();
if (!(searchAll))
logger.info("Succesfully retrieved {0}'s {1} groups.", userID, groups.length);
} catch (InvalidArgumentException e) {
logger.error("The provided parameters are invalid or data is missing. " + e.getCause() + "\n" + e.getMessage()
+ "\n" + e.getMessageKey());
throw new RuntimeException("Invalid parameters.", e);
} catch (InsufficientPrivilegeException e) {
logger.error("Insufficient privileges to search user {1}'s groups.", userID);
throw new RuntimeException("Insufficient privileges.", e);
} catch (DataNotFoundException e) {
logger.error("Unable to find user {0}.", userID);
throw new RuntimeException("Unable to find user.", e);
} catch (CommandException e) {
logger.error("An error occured while searching for {0}'s groups.", userID);
throw new RuntimeException("Unable to search for the user's groups.", e);
}
return groups;
}
/**
* Processes a set of groups for a given user: makes the user a member of the groups which names
* are provided. I.e., Links the user to those groups he's not already linked to, unlinks the user from the groups
* not listed.
*
* @param user The user's Principal object.
* @param GroupNames The list of group names to link to the user to.
*/
private void processGroups (PrincipalDTO user, ArrayList<String> GroupNames) {
// Get the list of groups the user is currently a member of:
GroupDTO[] groups = getUserGroups(user.getGuid(), user.getUserID());
// CReate List of current User gorups
ArrayList<String> currGrpNames = new ArrayList<String>();
for (GroupDTO grp : groups) {
currGrpNames.add(grp.getName());
}
if ((GroupNames == null) || (GroupNames.isEmpty())) {
// If the user has no current groups: do nothing.
if (currGrpNames.size() > 0) {
// No group names supplied: Remove all current memberships
logger.info("Unlinking {0} groups from fo user {1}...", currGrpNames.size(), user.getUserID());
unlinkGroupsFromUser(currGrpNames.toArray(new String[currGrpNames.size()]), user);
}
} else if (currGrpNames.size() > 0) {
// Some group names were provided, AND the user has current memberships.
// Compare the user's current group membership to the desired/provided list.
// Groups to add:
ArrayList<String> AddGroups = new ArrayList<String>();
for (String name : GroupNames) {
if (!(currGrpNames.contains(name)))
AddGroups.add(name);
}
// Groups to remove:
ArrayList<String> DelGroups = new ArrayList<String>();
for (String name : currGrpNames) {
if (!(GroupNames.contains(name)))
DelGroups.add(name);
}
if (!(AddGroups.isEmpty())) {
// Add groups
logger.info("Linking {0} groups to user {1}...", AddGroups.size(), user.getUserID());
linkGroups2User(AddGroups.toArray(new String[AddGroups.size()]), user);
}
if (!(DelGroups.isEmpty())) {
// Remove groups
logger.info("Unlinking {0} groups from fo user {1}...", DelGroups.size(), user.getUserID());
unlinkGroupsFromUser(DelGroups.toArray(new String[DelGroups.size()]), user);
}
} else {
// The user currently has no groups AND Group names were supplied: add them all:
logger.info("Linking {0} groups to user {1}...", GroupNames.size(), user.getUserID());
linkGroups2User(GroupNames.toArray(new String[GroupNames.size()]), user);
}
}
/**
* Transforms an array of Group names into an array of Group GUIDs by looking the group object up in RSA.
*
* @param GrpNames An array of Group Name Strings
* @return An Array of GUID Strings
*/
private String[] groupNames2Guids (String[] GrpNames) {
// Build array of Group Guids from the array or Group Names
ArrayList<String> GroupGuidsList = new ArrayList<String> ();
for (String GroupName : GrpNames) {
GroupDTO group = lookupGroup(GroupName);
GroupGuidsList.add(group.getGuid());
}
return GroupGuidsList.toArray(new String[GroupGuidsList.size()]);
}
/**
* Links a RSA group to a user.
*
* @param GroupNames The list of RSA Group names to link.
* @param user The User Principal object.
*/
private void linkGroups2User (String [] GroupNames, PrincipalDTO user) {
LinkGroupPrincipalsCommand cmd = new LinkGroupPrincipalsCommand();
// Build array of Group Guids from the array or Group Names
String[] GroupGuids = groupNames2Guids (GroupNames);
// Parameters
cmd.setGroupGuids(GroupGuids);
String[] users = { user.getGuid() };
cmd.setPrincipalGuids(users);
logger.info("Principal set {0}.", cmd.getPrincipalGuids()[0]);
cmd.setIdentitySourceGuid(this.connection.getIdSource().getGuid());
// Run command
try {
ClientSession ses = connection.newSession();
cmd.execute(ses);
connection.sessionLogout(ses);
logger.info(" {0} Group(s) succesfully linked.", GroupGuids.length);
} catch (InvalidArgumentException e) {
logger.error ("The provided group names or UserID {0} is invalid.", user.getUserID());
throw new RuntimeException ("Invalid Parameters.", e);
} catch (InsufficientPrivilegeException e) {
logger.error ("Insufficient privileges to link groups to user {0}.", user.getUserID());
throw new RuntimeException ("Insufficient privileges.", e);
} catch (DataNotFoundException e) {
logger.error ("Unable to find groups or user {1}.", user.getUserID());
throw new RuntimeException ("Unable to find group or user.", e);
} catch (DuplicateDataException e) {
logger.error ("Groups already linked to user {0}.", user.getUserID());
throw new RuntimeException ("Group already linked to user.", e);
} catch (CommandException e) {
logger.error ("An error occured while linking to user {0}.", user.getUserID());
throw new RuntimeException ("Unable to link group.", e);
}
}
/**
* Unlink a set of Groups from as User
*
* @param GroupNames The list of group names of the RSA group to unlink
* @param user The User's Principal object
*/
private void unlinkGroupsFromUser (String[] GroupNames, PrincipalDTO user){
UnlinkGroupPrincipalsCommand UnlinkCmd = new UnlinkGroupPrincipalsCommand();
// Build array of Group Guids from the array or Group Names
String[] GroupGuids = groupNames2Guids (GroupNames);
// Perform opration
UnlinkCmd.setGroupGuids(GroupGuids);
UnlinkCmd.setPrincipalGuids(new String[] { user.getGuid() });
UnlinkCmd.setIdentitySourceGuid(this.connection.getIdSource().getGuid());
try {
ClientSession ses = connection.newSession();
UnlinkCmd.execute(ses);
connection.sessionLogout(ses);
logger.info("Group succesfully unlinked {0} groups.", GroupGuids.length);
} catch (InvalidArgumentException e) {
logger.error ("The provided group(s)or UserID {0} is invalid.", user.getUserID());
throw new RuntimeException ("Invalid group or user name.", e);
} catch (InsufficientPrivilegeException e) {
logger.error ("Insufficient privileges to unlink groups from user {0}.", user.getUserID());
throw new RuntimeException ("Insufficient privileges.", e);
} catch (DataNotFoundException e) {
logger.error ("Unable to find groups or user {0s}.", user.getUserID());
throw new RuntimeException ("Unable to find group or user.", e);
} catch (CommandException e) {
logger.error ("An error occured while unlinking groups from user {0}.", user.getUserID());
throw new RuntimeException ("Unable to unlink groups.", e);
}
}
/**
* Embedded classes
*/
/**
* Implements the comparable interface to compare RSA Tokens against each other based on their Serial Numbers.
* Used for sorting tokens.
*/
public class TokenSerialComparable implements Comparator<ListTokenDTO>{
@Override
public int compare(ListTokenDTO token1, ListTokenDTO token2) {
return token1.getSerialNumber().compareTo(token2.getSerialNumber());
}
}
}