Intro
I thought I might save someone else the trouble of re-creating a respectable program using the Authentication Manager SDK for version 7.1 which can simply add and delete users to keep the local database in sync with an external database.
History Lesson
We had this problem licked under Authentication Manager v 6.1.2. In that version the sdk was TCL-based and for whatever reason, it seemed a whole lot simpler to understand the model and get working code. When we began to look at v 7.1 we saw we were confronted with a whole different animal that required new understanding and new skills to master.
The Details
Jython is Python plus Java. I really don’t know either language so I used a technique you might call programming by extrapolation. Here is the code. Not really understanding python I preserved as much as possible for fear of breaking something. I nevertheless had to be a little innovative and create a new function.
''' * Jython class demonstrating the Administration API * usage from a Jython script. * * Run this script in the utils directory of the Authentication Manager installation. * * Execute the command "rsautil jython AdminAPIDemos.py create <admin user name> <password>" * Execute the command "rsautil jython AdminAPIDemos.py assign <admin user name> <password>" * Execute the command "rsautil jython AdminAPIDemos.py update <admin user name> <password>" * Execute the command "rsautil jython AdminAPIDemos.py delete <admin user name> <password>" * * If you are executing this script in an environment other than the predefined * rsautil scripting tool you must make the CommandClientAppContext.xml file * available in the end of the classpath for this script. You must also configure * the necessary connection parameters in a properties file located in the process * working directory. See the provided samples for more information. ''' # imports from jarray import array import sys # DrJ required import # Not Workign! from org.python.modules import re from java.util.regex import * from java.lang import * from java.util import Calendar,Date from java.lang import String from org.springframework.beans import BeanUtils from com.rsa.admin import AddGroupCommand from com.rsa.admin import AddPrincipalsCommand from com.rsa.admin import DeleteGroupCommand from com.rsa.admin import DeletePrincipalsCommand from com.rsa.admin import LinkGroupPrincipalsCommand from com.rsa.admin import LinkAdminRolesPrincipalsCommand from com.rsa.admin import SearchAdminRolesCommand from com.rsa.admin import SearchGroupsCommand from com.rsa.admin import SearchPrincipalsCommand from com.rsa.admin import SearchRealmsCommand from com.rsa.admin import SearchSecurityDomainCommand from com.rsa.admin import UpdateGroupCommand from com.rsa.admin import UpdatePrincipalCommand from com.rsa.admin.data import AdminRoleDTOBase from com.rsa.admin.data import GroupDTO from com.rsa.admin.data import IdentitySourceDTO from com.rsa.admin.data import ModificationDTO from com.rsa.admin.data import PrincipalDTO from com.rsa.admin.data import RealmDTO from com.rsa.admin.data import SecurityDomainDTO from com.rsa.admin.data import UpdateGroupDTO from com.rsa.admin.data import UpdatePrincipalDTO from com.rsa.authmgr.admin.agentmgt import AddAgentCommand from com.rsa.authmgr.admin.agentmgt import DeleteAgentsCommand from com.rsa.authmgr.admin.agentmgt import LinkAgentsToGroupsCommand from com.rsa.authmgr.admin.agentmgt import SearchAgentsCommand from com.rsa.authmgr.admin.agentmgt import UpdateAgentCommand from com.rsa.authmgr.admin.agentmgt.data import AgentConstants from com.rsa.authmgr.admin.agentmgt.data import AgentDTO, ListAgentDTO from com.rsa.authmgr.admin.hostmgt.data import HostDTO from com.rsa.authmgr.admin.principalmgt import AddAMPrincipalCommand from com.rsa.authmgr.admin.principalmgt.data import AMPrincipalDTO from com.rsa.authmgr.admin.tokenmgt import GetNextAvailableTokenCommand from com.rsa.authmgr.admin.tokenmgt import LinkTokensWithPrincipalCommand from com.rsa.authn import SearchPasswordPoliciesCommand from com.rsa.authn import UpdatePasswordPolicyCommand from com.rsa.authn.data import PasswordPolicyDTO from com.rsa.command import ClientSession from com.rsa.command import CommandException from com.rsa.command import CommandTargetPolicy, ConnectionFactory from com.rsa.command.exception import DataNotFoundException, DuplicateDataException from com.rsa.common.search import Filter ''' * This class demonstrates the usage patterns of the * Authentication Manager 7.1 API. * * <p> * The first set of operations performed if the first * command line argument is equal to "create". * The sample creates a restricted agent, a group, and a user. * Links the user to the group and the group to the agent. * </p> * <p> * The second set of operations performed if the first * command line argument is equal to "delete". * Lookup the user, group and agent created above. * Delete the user, group and agent. * </p> * <p> * A third set of operations is performed if the first * command line argument is equal to "assign". * Lookup the user and assign the next available * SecurID token to the user. * Lookup the SuperAdminRole and assign it to the user. * </p> * <p> * A fourth set of operations performed if the first * command line argument is equal to "update". * Update the Agent, Group, and User objects. * </p> * <p> * A fifth set of operations performed if the first * command line argument is equal to "disable". * Lookup a password policy with a name that starts * with "Initial" and then disable the password history * for that policy. Use this to allow the sample to * perform multiple updates of the user password using * the same password for each update. * </p> * <p> * The APIs demonstrated include the use of the Filter * class to generate search expressions for use with * all search commands. * </p> ''' class AdminAPIDemos: ''' * We need to know these fairly static values throughout this sample. * Set the references to top level security domain (realm) and system * identity source to use later. * * @throws CommandException if something goes wrong ''' def __init__(self): searchRealmCmd = SearchRealmsCommand() searchRealmCmd.setFilter( Filter.equal( RealmDTO.NAME_ATTRIBUTE, "SystemDomain")) searchRealmCmd.execute() realms = searchRealmCmd.getRealms() if( len(realms) == 0 ): print "ERROR: Could not find realm SystemDomain" sys.exit( 2 ) self.domain = realms[0].getTopLevelSecurityDomain() self.idSource = realms[0].getIdentitySources()[0] ''' * Create an agent and set it to be restricted. * * @param: name the name of the agent to create * @param: addr the IP address for the agent * @param: alt array of alternate IP addresses * @return: the GUID of the agent just created * * @throws CommandException if something goes wrong ''' def createAgent(self, name, addr, alt): # need a HostDTO to be set host = HostDTO() host.setName(name) host.setPrimaryIpAddress(addr) host.setSecurityDomainGuid(self.domain.getGuid()) host.setNotes("Created by AM Demo code") # the agent to be created agent = AgentDTO() agent.setName(name) agent.setHost(host) agent.setPrimaryAddress(addr) agent.setAlternateAddresses(alt) agent.setSecurityDomainId(self.domain.getGuid()) agent.setAgentType(AgentConstants.STANDARD_AGENT) agent.setRestriction(1) # only allow activated groups agent.setEnabled(1) agent.setOfflineAuthDataRefreshRequired(0) agent.setNotes("Created by AM Demo code") cmd = AddAgentCommand(agent) try: cmd.execute() except DuplicateDataException: print "ERROR: Agent " + name + " already exists." sys.exit(2) # return the created agents GUID for further linking return cmd.getAgentGuid() ''' * Lookup an agent by name. * * @param: name the agent name to lookup * @return: the GUID of the agent * * @throws CommandException if something goes wrong ''' def lookupAgent(self, name): cmd = SearchAgentsCommand() cmd.setFilter(Filter.equal(AgentConstants.FILTER_HOSTNAME, name)) cmd.setLimit(1) cmd.setSearchBase(self.domain.getGuid()) # the scope flags are part of the SecurityDomainDTO cmd.setSearchScope(SecurityDomainDTO.SEARCH_SCOPE_ONE_LEVEL) cmd.execute() if (len(cmd.getAgents()) < 1): print "ERROR: Unable to find agent " + name + "." sys.exit(2) return cmd.getAgents()[0] ''' * Update an agent, assumes a previous lookup done by lookupAgent. * * @param agent the result of a previous lookup * * @throws CommandException if something goes wrong ''' def updateAgent(self, agent): cmd = UpdateAgentCommand() agentUpdate = AgentDTO() # copy the rowVersion to satisfy optimistic locking requirements BeanUtils.copyProperties(agent, agentUpdate) # ListAgentDTO does not include the SecurityDomainId # use the GUID of the security domain where agent was created agentUpdate.setSecurityDomainId(self.domain.getGuid()) # clear the node secret flag and modify some others agentUpdate.setSentNodeSecret(0) agentUpdate.setOfflineAuthDataRefreshRequired(1) agentUpdate.setIpProtected(1) agentUpdate.setEnabled(1) agentUpdate.setNotes("Modified by AM Demo code") # set the requested updates in the command cmd.setAgentDTO(agentUpdate) # perform the update cmd.execute() ''' * Delete an agent. * * @param: agentGuid the GUID of the agent to delete * * @throws CommandException if something goes wrong ''' def deleteAgent(self, agentGuid): cmd = DeleteAgentsCommand( [agentGuid] ) cmd.execute() ''' * Create an IMS user, needs to exist before an AM user can be * created. * * @param: userId the user's login UID * @param: password the user's password * @param: first the user's first name * @param: last the user's last name * * @return: the GUID of the user just created * * @throws CommandException if something goes wrong ''' def createUser(self, userId, password, first, last): cal = Calendar.getInstance() # the start date now = cal.getTime() # DrJ: add 50 years from now! cal.add(Calendar.YEAR, 50) # the account end date expire = cal.getTime() principal = PrincipalDTO() principal.setUserID( userId ) principal.setFirstName( first ) principal.setLastName( last ) # principal.setPassword( password ) principal.setEnabled(1) principal.setLockoutStatus(0) principal.setAccountStartDate(now) #principal.setAccountExpireDate(expire) #principal.setAccountExpireDate(0) principal.setAdminRole(0) principal.setCanBeImpersonated(0) principal.setTrustToImpersonate(0) principal.setSecurityDomainGuid( self.domain.getGuid() ) principal.setIdentitySourceGuid( self.idSource.getGuid() ) principal.setDescription("Created by DrJ utilities") cmd = AddPrincipalsCommand() cmd.setPrincipals( [principal] ) try: cmd.execute() except DuplicateDataException: print "ERROR: User " + userId + " already exists." sys.exit(2) # only one user was created, there should be one GUID result return cmd.getGuids()[0] ''' * Lookup a user by login UID. * * @param: userId the user login UID * * @return: the GUID of the user record. ''' def lookupUser(self, userId): cmd = SearchPrincipalsCommand() cmd.setFilter(Filter.equal(PrincipalDTO.LOGINUID, userId)) cmd.setSystemFilter(Filter.empty()) cmd.setLimit(1) cmd.setIdentitySourceGuid(self.idSource.getGuid()) cmd.setSecurityDomainGuid(self.domain.getGuid()) cmd.setGroupGuid(None) cmd.setOnlyRegistered(1) cmd.setSearchSubDomains(0) cmd.execute() if (len(cmd.getPrincipals()) < 1): print "ERROR: Unable to find user " + userId + "." sys.exit(2) return cmd.getPrincipals()[0] ''' * Update the user definition. * * @param user the principal object from a previous lookup ''' def updateUser(self, user): cmd = UpdatePrincipalCommand() cmd.setIdentitySourceGuid(user.getIdentitySourceGuid()) updateDTO = UpdatePrincipalDTO() updateDTO.setGuid(user.getGuid()) # copy the rowVersion to satisfy optimistic locking requirements updateDTO.setRowVersion(user.getRowVersion()) # collect all modifications here mods = [] # first change the email mod = ModificationDTO() mod.setOperation(ModificationDTO.REPLACE_ATTRIBUTE) mod.setName(PrincipalDTO.EMAIL) mod.setValues([ user.getUserID() + "@mycompany.com" ]) mods.append(mod) # add it to the list # also change the password mod = ModificationDTO() mod.setOperation(ModificationDTO.REPLACE_ATTRIBUTE) mod.setName(PrincipalDTO.PASSWORD) mod.setValues([ "MyNewPAssW0rD1!" ]) mods.append(mod) # add it to the list # change the middle name mod = ModificationDTO() mod.setOperation(ModificationDTO.REPLACE_ATTRIBUTE) mod.setName(PrincipalDTO.MIDDLE_NAME) mod.setValues([ "The Big Cahuna" ]) mods.append(mod) # add it to the list # make a note of this update in the description mod = ModificationDTO() mod.setOperation(ModificationDTO.REPLACE_ATTRIBUTE) mod.setName(PrincipalDTO.DESCRIPTION) mod.setValues([ "Modified by AM Demo code" ]) mods.append(mod) # add it to the list # set the requested updates into the UpdatePrincipalDTO updateDTO.setModifications(mods) cmd.setPrincipalModification(updateDTO) # perform the update cmd.execute() ''' * Delete a user. * * @param: userGuid the GUID of the user to delete * * @throws CommandException if something goes wrong ''' def deleteUser(self, userGuid): cmd = DeletePrincipalsCommand() cmd.setGuids( array( [userGuid], String ) ) cmd.setIdentitySourceGuid( self.idSource.getGuid() ) cmd.execute() ''' * Create an Authentication Manager user linked to the IMS user. * The user will have a limit of 3 bad passcodes, default shell * will be "/bin/sh", the static password will be "12345678" and * the Windows Password for offline authentication will be "Password123!". * * @param: guid the GUID of the IMS user * * @throws CommandException if something goes wrong ''' def createAMUser(self, guid): principal = AMPrincipalDTO() principal.setGuid(guid) principal.setBadPasscodes(3) principal.setDefaultShell("/bin/sh") principal.setDefaultUserIdShellAllowed(1) # these next three innocent-looking lines cost you a license! do not use them!! - DrJ #principal.setStaticPassword("12345678") #principal.setStaticPasswordSet(1) #principal.setWindowsPassword("Password123!") cmd = AddAMPrincipalCommand(principal) cmd.execute() ''' * Create a group to assign a user to. * * @param: name the name of the group to create * @return: the GUID of the group just created * * @throws CommandException if something goes wrong ''' def createGroup(self, name): group = GroupDTO() group.setName(name) group.setDescription("Created by AM Demo code") group.setSecurityDomainGuid(self.domain.getGuid()) group.setIdentitySourceGuid(self.idSource.getGuid()) cmd = AddGroupCommand() cmd.setGroup(group) try: cmd.execute() except DuplicateDataException: print "ERROR: Group " + name + " already exists." sys.exit(2) return cmd.getGuid() ''' * Lookup a group by name. * * @param: name the name of the group to lookup * @return: the GUID of the group * * @throws CommandException if something goes wrong ''' def lookupGroup(self, name): cmd = SearchGroupsCommand() cmd.setFilter(Filter.equal(GroupDTO.NAME, name)) cmd.setSystemFilter(Filter.empty()) cmd.setLimit(1) cmd.setIdentitySourceGuid(self.idSource.getGuid()) cmd.setSecurityDomainGuid(self.domain.getGuid()) cmd.setSearchSubDomains(0) cmd.setGroupGuid(None) cmd.execute() if (len(cmd.getGroups()) < 1): print "ERROR: Unable to find group " + name + "." sys.exit(2) return cmd.getGroups()[0] ''' * Update a group definition. * * @param group the current group object ''' def updateGroup(self, group): cmd = UpdateGroupCommand() cmd.setIdentitySourceGuid(group.getIdentitySourceGuid()) groupMod = UpdateGroupDTO() groupMod.setGuid(group.getGuid()) # copy the rowVersion to satisfy optimistic locking requirements groupMod.setRowVersion(group.getRowVersion()) # collect all modifications here mods = [] mod = ModificationDTO() mod.setOperation(ModificationDTO.REPLACE_ATTRIBUTE) mod.setName(GroupDTO.DESCRIPTION) mod.setValues([ "Modified by AM Demo code" ]) mods.append(mod) # set the requested updates into the UpdateGroupDTO groupMod.setModifications(mods) cmd.setGroupModification(groupMod) # perform the update cmd.execute() ''' * Delete a group. * * @param: groupGuid the GUID of the group to delete * * @throws CommandException if something goes wrong ''' def deleteGroup(self, groupGuid): cmd = DeleteGroupCommand() cmd.setGuids( [groupGuid] ) cmd.setIdentitySourceGuid( self.idSource.getGuid() ) cmd.execute() ''' * Assign the user to the specified group. * * @param: userGuid the GUID for the user to assign * @param: groupGuid the GUID for the group * * @throws CommandException if something goes wrong ''' def linkUserToGroup(self, userGuid, groupGuid): cmd = LinkGroupPrincipalsCommand() cmd.setGroupGuids( [groupGuid] ) cmd.setPrincipalGuids( [userGuid] ) cmd.setIdentitySourceGuid(self.idSource.getGuid()) cmd.execute() ''' * Assign the group to the restricted agent so users can authenticate. * * @param: agentGuid the GUID for the restricted agent * @param: groupGuid the GUID for the group to assign * * @throws CommandException if something goes wrong ''' def assignGroupToAgent(self, agentGuid, groupGuid): cmd = LinkAgentsToGroupsCommand() cmd.setGroupGuids( [groupGuid] ) cmd.setAgentGuids( [agentGuid] ) cmd.setIdentitySourceGuid(self.idSource.getGuid()) cmd.execute() ''' * Assign next available token to this user. * * @param: userGuid the GUID of the user to assign the token to * * @throws CommandException if something goes wrong ''' def assignNextAvailableTokenToUser(self, userGuid): cmd = GetNextAvailableTokenCommand() try: cmd.execute() except DataNotFoundException: print "ERROR: No tokens available" else: tokens = [cmd.getToken().getId()] cmd2 = LinkTokensWithPrincipalCommand(tokens, userGuid) cmd2.execute() print ("Assigned next available SecurID token to user jdoe") ''' * Lookup an admin role and return the GUID. * * @param name the name of the role to lookup * @return the GUID for the required role * * @throws CommandException if something goes wrong ''' def lookupAdminRole(self, name): cmd = SearchAdminRolesCommand() # set search filter to match the name cmd.setFilter(Filter.equal(AdminRoleDTOBase.NAME_ATTRIBUTE, name)) # we only expect one anyway cmd.setLimit(1) # set the domain GUID cmd.setSecurityDomainGuid(self.domain.getGuid()) cmd.execute() if (len(cmd.getAdminRoles()) < 1): print "ERROR: Unable to find admin role " + name + "." sys.exit(2) return cmd.getAdminRoles()[0].getGuid() ''' * Assign the given admin role to the principal provided. * * @param adminGuid the GUID for the administrator * @param roleGuid the GUID for the role to assign * * @throws CommandException if something goes wrong ''' def assignAdminRole(self, adminGuid, roleGuid): cmd = LinkAdminRolesPrincipalsCommand() cmd.setIgnoreDuplicateLink(1) cmd.setPrincipalGuids( [ adminGuid ] ) cmd.setAdminRoleGuids( [ roleGuid ] ) cmd.execute() print ("Assigned SuperAdminRole to user jdoe") ''' * Lookup a password policy by name and return the object. * * @param name the policy name * @return the object * * @throws CommandException if something goes wrong ''' def lookupPasswordPolicy(self, name): cmd = SearchPasswordPoliciesCommand() cmd.setRealmGuid(self.domain.getGuid()) # match the policy name cmd.setFilter(Filter.startsWith(PasswordPolicyDTO.NAME, name)) cmd.execute() if (len(cmd.getPolicies()) < 1): print ("ERROR: Unable to find password policy with name starting with " + name + ".") sys.exit(2) # we only expect one anyway return cmd.getPolicies()[0] ''' * Update the given password policy, currently it just disables * password history. * * @param policy the policy to update * * @throws CommandException if something goes wrong ''' def updatePasswordPolicy(self, policy): cmd = UpdatePasswordPolicyCommand() # disable password history policy.setHistorySize(0) cmd.setPasswordPolicy(policy) cmd.execute() ''' * Create a collection of related entities, user, agent, group, token. * * @param admin the administrator user name * @param password the administrator password * * @throws Exception if something goes wrong ''' def doCreate(self): # Create a hypothetical agent with four alternate addresses addr = "1.2.3.4" alt = [ "2.2.2.2", "3.3.3.3", "4.4.4.4", "5.5.5.5" ] # create a restricted agent agentGuid = self.createAgent("Demo Agent", addr, alt) print ("Created Demo Agent") # create a user group groupGuid = self.createGroup("Demo Agent Group") print ("Created Demo Agent Group") # assign the group to the restricted agent self.assignGroupToAgent(agentGuid, groupGuid) print ("Assigned Demo Agent Group to Demo Agent") # create a user and the AMPrincipal user record userGuid = self.createUser("jdoe", "Password123!", "John", "Doe") self.createAMUser(userGuid) print ("Created user jdoe") # link the user to the group self.linkUserToGroup(userGuid, groupGuid) print ("Added user jdoe to Demo Agent Group") ''' * add user by DrJ * * @param admin the administrator user name * @param password the administrator password * * @throws Exception if something goes wrong ''' def doAdd(self): # create a user and the AMPrincipal user record # loop over all users listed in addusers.txt f = open('addusers.txt','r') str = f.readline() while str: strs = str.rstrip() cols = strs.split(",") userid = cols[0] fname = cols[1] lname = cols[2] print userid # if user already exists we want to go continue with the list try: userGuid = self.createUser(userid, "*LK*", fname, lname) self.createAMUser(userGuid) print "Created user userid,fname,lname: ", userid,",",lname,",",fname,"\n" except: print "exception for user ",userid,"\n" str = f.readline() f.close() ''' * Assign the next available token to the user. * * @param admin the administrator user name * @param password the administrator password * * @throws Exception if something goes wrong ''' def doAssignNextToken(self): # lookup and then ... userGuid = self.lookupUser("jdoe").getGuid() # assign the next available token to this user self.assignNextAvailableTokenToUser(userGuid) # now that he has a token make him an admin roleGuid = self.lookupAdminRole("SuperAdminRole") self.assignAdminRole(userGuid, roleGuid) ''' * Delete the entities created by the doCreate method. * * @param admin the administrator user name * @param password the administrator password * * @throws Exception if something goes wrong ''' def doDelete(self): # lookup and then ... # loop over all users listed in delusers.txt f = open('delusers.txt','r') str = f.readline() while str: # format: userid,fname,lname . We just want the userid cols = str.split(",") userid = cols[0] print userid # if user doesn't exist we want to go continue with the list try: userGuid = self.lookupUser(userid).getGuid() # ... cleanup self.deleteUser(userGuid) print "Deleted user ",userid except: print "exception for user ",userid,"\n" str = f.readline() f.close() ''' * Update the various entities created by the doCreate method. * * @throws Exception if something goes wrong ''' def doUpdate(self): # lookup and then ... agent = self.lookupAgent("Demo Agent") group = self.lookupGroup("Demo Agent Group") user = self.lookupUser("jdoe") # ... update self.updateAgent(agent) print ("Updated Demo Agent") self.updateGroup(group) print ("Updated Demo Agent Group") self.updateUser(user) print ("Updated user jdoe") ''' * Disable password history limit on default password policy so * we can issue multiple updates for the user password. * * @throws Exception if something goes wrong ''' def doDisablePasswordHistory(self): # lookup and then ... policy = self.lookupPasswordPolicy("Initial") # ... update self.updatePasswordPolicy(policy) print ("Disabled password history") # Globals here ''' * Show usage message and exit. * * @param msg the error causing the exit ''' def usage(msg): print ("ERROR: " + msg) print ("Usage: APIDemos <create|delete> <admin username> <admin password>") sys.exit(1) ''' * Use from command line with three arguments. * * <p> * First argument: * create - to create the required entities * assign - to assign the next available token to the user * delete - to delete all created entities * </p> * <p> * Second argument is the administrator user name. * Third argument is the administrator password. * </p> * * @param args the command line arguments ''' if len(sys.argv) != 4: usage("Missing arguments") # skip script name args = sys.argv[1:] # establish a connected session with given credentials conn = ConnectionFactory.getConnection() session = conn.connect(args[1], args[2]) # make all commands execute using this target automatically CommandTargetPolicy.setDefaultCommandTarget(session) try: # create instance api = AdminAPIDemos() # call delusers before addusers print "Deleting users...\n" api.doDelete() print "Adding users...\n" api.doAdd() finally: # logout when done session.logout() |
I of course worked from their demo file, AdminAPIDemos.py, and kept the name for simplicity. I added a a doAdd routine and modified their doDelete function.
These modified functions expect external files to exist, addusers.txt and delusers.txt. The syntax of addusers.txt is:
loginname1,first_name,last_name loginname2,first_name,last_name ...
Delusers.txt has the same syntax.
The idea is that if you can create these files once per day with the new users/removed users from your corporate directory by some other means, then you have a way to use them as a basis for keeping your AM internal database in sync with your external enterprise directory, whatever it might be.
Other Notes
Initially I saw my users were set to expire after a year or so. The original code I borrwed from had lines like this:
cal = Calendar.getInstance() # the start date now = cal.getTime() cal.add(Calendar.YEAR, 1) # the account end date expire = cal.getTime() |
which caused this. I eventually found how to set a flag to create the account with unlimited validity.
I also introduced a very simple regex handling to break up the input lines. This caused the need for importing additional classes:
from java.util.regex import * from java.lang import * |
I could not get python regexes to work.
I also found these three innocent-looking lines were costing me a license unit for each added user:
principal.setStaticPassword("12345678") principal.setStaticPasswordSet(1) principal.setWindowsPassword("Password123!") |
So I commented them out as I did not need them.
That’s it!
Getting the SDK running cost me a few days but at least I’ve documented that as well in pretty good detail: Problems with Jython API for RSA Authentication Manager.
Conclusion
We’ve shared with the community an actual, working jython API for adding/removing users from an RSA Authentication Manager v 7.1 database.