def on_init(self): self.authentication = Authentication()
class IdentityManagementService(BaseIdentityManagementService): """ Stores identities of users and resources, including bindings of internal identities to external identities. Also stores metadata such as a user profile. """ def on_init(self): self.authentication = Authentication() def create_actor_identity(self, actor_identity=None): # Persist ActorIdentity object and return object _id as OOI id actor_id, version = self.clients.resource_registry.create(actor_identity) return actor_id def update_actor_identity(self, actor_identity=None): # Overwrite ActorIdentity object self.clients.resource_registry.update(actor_identity) def read_actor_identity(self, actor_id=''): # Read ActorIdentity object with _id matching passed user id actor_identity = self.clients.resource_registry.read(actor_id) return actor_identity def delete_actor_identity(self, actor_id=''): # Delete specified ActorIdentity object self.clients.resource_registry.delete(actor_id) def find_actor_identity_by_name(self, name=''): """Return the ActorIdentity object whose name attribute matches the passed value. @param name str @retval user_info ActorIdentity @throws NotFound failed to find ActorIdentity @throws Inconsistent Multiple ActorIdentity objects matched name """ objects, matches = self.clients.resource_registry.find_resources(RT.ActorIdentity, None, name, id_only=False) if not objects: raise NotFound("ActorIdentity with name %s does not exist" % name) if len(objects) > 1: raise Inconsistent("Multiple ActorIdentity objects with name %s exist" % name) return objects[0] def register_user_credentials(self, actor_id='', credentials=None): # Create UserCredentials object credentials_obj_id, version = self.clients.resource_registry.create(credentials) # Create association with user identity object res = self.clients.resource_registry.create_association(actor_id, PRED.hasCredentials, credentials_obj_id) def unregister_user_credentials(self, actor_id='', credentials_name=''): # Read UserCredentials objects, matches = self.clients.resource_registry.find_resources(RT.UserCredentials, None, credentials_name, id_only=False) if not objects or len(objects) == 0: raise NotFound("UserCredentials %s does not exist" % credentials_name) if len(objects) > 1: raise Conflict("Multiple UserCredentials objects found for subject %s" % credentials_name) user_credentials_id = objects[0]._id # Find and break association with ActorIdentity assocs = self.clients.resource_registry.find_associations(actor_id, PRED.hasCredentials, user_credentials_id) if not assocs or len(assocs) == 0: raise NotFound("ActorIdentity to UserCredentials association for user id %s to credential %s does not exist" % (actor_id, credentials_name)) association_id = assocs[0]._id self.clients.resource_registry.delete_association(association_id) # Delete the UserCredentials self.clients.resource_registry.delete(user_credentials_id) def create_user_info(self, actor_id="", user_info=None): # Ensure UserInfo association does not already exist objects, assocs = self.clients.resource_registry.find_objects(actor_id, PRED.hasInfo, RT.UserInfo) if objects: raise Conflict("UserInfo already exists for user id %s" % (actor_id)) # Create UserInfo object user_info_id, version = self.clients.resource_registry.create(user_info) # Create association with user identity object self.clients.resource_registry.create_association(actor_id, PRED.hasInfo, user_info_id) return user_info_id def update_user_info(self, user_info=None): # Overwrite UserInfo object self.clients.resource_registry.update(user_info) def read_user_info(self, user_info_id=''): # Read UserInfo object with _id matching passed user id user_info = self.clients.resource_registry.read(user_info_id) return user_info def delete_user_info(self, user_info_id='', actor_identity_id=''): # Read UserInfo user_info = self.clients.resource_registry.read(user_info_id) if not user_info: raise NotFound("UserInfo %s does not exist" % user_info_id) # Find and break association with ActorIdentity if not actor_identity_id: subjects, assocs = self.clients.resource_registry.find_subjects(RT.ActorIdentity, PRED.hasInfo, user_info_id) if not assocs: raise NotFound("ActorIdentity to UserInfo association for user info id %s does not exist" % user_info_id) actor_identity_id = subjects[0]._id assocs = self.clients.resource_registry.find_associations(actor_identity_id, PRED.hasInfo, user_info_id) if not assocs: raise NotFound("ActorIdentity to UserInfo association for user info id %s does not exist" % user_info_id) association_id = assocs[0]._id self.clients.resource_registry.delete_association(association_id) # Delete the UserInfo self.clients.resource_registry.delete(user_info_id) def find_user_info_by_email(self, user_email=''): #return self.clients.resource_registry.find_resources_ext(restype=RT.UserInfo, attr_name="contact.email", attr_value=user_email, id_only=False) user_infos, _ = self.clients.resource_registry.find_resources_ext(RT.UserInfo, attr_name="contact.email", attr_value=user_email) if len(user_infos) > 1: log.warn("More than one UserInfo found for email '%s': %s" % (user_email, [ui._id for ui in user_infos])) if user_infos: return user_infos[0] return None def find_user_info_by_id(self, actor_id=''): # Look up UserInfo via association with ActorIdentity objects, assocs = self.clients.resource_registry.find_objects(actor_id, PRED.hasInfo, RT.UserInfo) if not objects: raise NotFound("UserInfo for user id %s does not exist" % actor_id) user_info = objects[0] return user_info def find_user_info_by_name(self, name=''): objects, matches = self.clients.resource_registry.find_resources(RT.UserInfo, None, name, id_only=False) if not objects: raise NotFound("UserInfo with name %s does not exist" % name) if len(objects) > 1: raise Inconsistent("Multiple UserInfo objects with name %s exist" % name) return objects[0] def find_user_info_by_subject(self, subject=''): # Find UserCredentials objects, matches = self.clients.resource_registry.find_resources(RT.UserCredentials, None, subject, id_only=False) if not objects: raise NotFound("UserCredentials with subject %s does not exist" % subject) if len(objects) > 1: raise Inconsistent("Multiple UserCredentials with subject %s exist" % subject) user_credentials_id = objects[0]._id subjects, assocs = self.clients.resource_registry.find_subjects(RT.ActorIdentity, PRED.hasCredentials, user_credentials_id) if not subjects or len(subjects) == 0: raise NotFound("ActorIdentity to UserCredentials association for subject %s does not exist" % subject) if len(subjects) > 1: raise Inconsistent("Multiple ActorIdentity to UserCredentials associations for subject %s exist" % subject) actor_identity_id = subjects[0]._id # Look up UserInfo via association with ActorIdentity objects, assocs = self.clients.resource_registry.find_objects(actor_identity_id, PRED.hasInfo, RT.UserInfo) if not objects: raise NotFound("UserInfo for subject %s does not exist" % subject) if len(objects) > 1: raise Inconsistent("Multiple UserInfos for subject %s exist" % subject) user_info = objects[0] return user_info def signon(self, certificate='', ignore_date_range=False): log.debug("Signon with certificate:\n%s" % certificate) # Check the certificate is currently valid if not ignore_date_range: if not self.authentication.is_certificate_within_date_range(certificate): raise BadRequest("Certificate expired or not yet valid") # Extract subject line attributes = self.authentication.decode_certificate_string(certificate) subject = attributes["subject"] valid_until_str = attributes["not_valid_after"] log.debug("Signon request for subject %s with string valid_until %s" % (subject, valid_until_str)) valid_until_tuple = time.strptime(valid_until_str, "%b %d %H:%M:%S %Y %Z") valid_until = str(int(time.mktime(valid_until_tuple)) * 1000) # Look for matching UserCredentials object objects, assocs = self.clients.resource_registry.find_resources(RT.UserCredentials, None, subject, True) if len(objects) > 1: raise Conflict("More than one UserCredentials object was found for subject %s" % subject) if len(objects) == 1: log.debug("Signon known subject %s" % (subject)) # Known user, get ActorIdentity object user_credentials_id = objects[0] subjects, assocs = self.clients.resource_registry.find_subjects(RT.ActorIdentity, PRED.hasCredentials, user_credentials_id) if len(subjects) == 0: raise Conflict("ActorIdentity object with subject %s was previously created but is not associated with a ActorIdentity object" % subject) actor_id = subjects[0]._id # Find associated UserInfo registered = True try: self.find_user_info_by_id(actor_id) except NotFound: registered = False log.debug("Signon returning actor_id, valid_until, registered: %s, %s, %s" % (actor_id, valid_until, str(registered))) return actor_id, valid_until, registered else: log.debug("Signon new subject %s" % (subject)) # New user. Create ActorIdentity and UserCredentials actor_name = "Identity for %s" % subject actor_identity = IonObject("ActorIdentity", name=actor_name) actor_id = self.create_actor_identity(actor_identity) user_credentials = IonObject("UserCredentials", name=subject, description="Default credentials for %s" % subject) self.register_user_credentials(actor_id, user_credentials) log.debug("Signon returning actor_id, valid_until, registered: %s, %s, False" % (actor_id, valid_until)) return actor_id, valid_until, False def get_user_info_extension(self, user_info_id='', org_id=''): """Returns an UserInfoExtension object containing additional related information @param user_info_id str @param org_id str - An optional org id that the user is interested in filtering against. @retval user_info UserInfoExtension @throws BadRequest A parameter is missing @throws NotFound An object with the specified actor_id does not exist """ if not user_info_id: raise BadRequest("The user_info_id parameter is empty") #THis is a hack to get the UI going. It would be preferable to get the actor id from the extended resource #container below, but their would need to be a guarantee of order of field processing in order #to ensure that the actor identity has been found BEFORE the negotiation methods are called - and probably #some elegant way to indicate the field and sub field; ie actor_identity._id actors, _ = self.clients.resource_registry.find_subjects(subject_type=RT.ActorIdentity, predicate=PRED.hasInfo, object=user_info_id, id_only=True) actor_id = actors[0] if len(actors) > 0 else '' extended_resource_handler = ExtendedResourceContainer(self) extended_user = extended_resource_handler.create_extended_resource_container( extended_resource_type=OT.UserInfoExtension, resource_id=user_info_id, computed_resource_type=OT.ComputedAttributes, user_id=user_info_id, org_id=org_id, actor_id=actor_id) #If the org_id is not provided then skip looking for Org related roles. if extended_user: #Did not setup a dependency to org_management service to avoid a potential circular bootstrap issue # since this method should never be called until the system is fully running try: org_client = OrgManagementServiceProcessClient(process=self) roles = org_client.find_all_roles_by_user(extended_user.actor_identity._id) extended_user.roles = list() for org_name in roles: for role in roles[org_name]: flattened_role = copy.copy(role.__dict__) del flattened_role['type_'] #Have to do this to appease the message validators for ION objects flattened_role['org_name'] = org_name #Nothing like forcing a value into the dict to appease the UI code extended_user.roles.append(flattened_role) except Exception, e: raise NotFound('Could not retrieve UserRoles for User Info id: %s - %s' % (user_info_id, e.message)) #filter notification requests that are retired extended_user.subscriptions = [nr for nr in extended_user.subscriptions if nr.temporal_bounds.end_datetime == ''] #filter owned resources that are retired nr_removed = [] for rsrc in extended_user.owned_resources: #remove all the Notifications if rsrc.type_ != OT.NotificationRequest: nr_removed.append(rsrc) extended_user.owned_resources = [rsrc for rsrc in nr_removed if rsrc.lcstate != 'DELETED'] #now append the active NotificationRequests extended_user.owned_resources.extend(extended_user.subscriptions) from ion.util.extresource import strip_resource_extension strip_resource_extension(extended_user) return extended_user
class IdentityManagementService(BaseIdentityManagementService): """ A resource registry that stores identities of users and resources, including bindings of internal identities to external identities. Also stores metadata such as a user profile.a A resource registry that stores identities of users and resources, including bindings of internal identities to external identities. Also stores metadata such as a user profile.a """ def on_init(self): self.authentication = Authentication() def create_user_identity(self, user_identity=None): # Persist UserIdentity object and return object _id as OOI id user_id, version = self.clients.resource_registry.create(user_identity) return user_id def update_user_identity(self, user_identity=None): # Overwrite UserIdentity object self.clients.resource_registry.update(user_identity) def read_user_identity(self, user_id=""): # Read UserIdentity object with _id matching passed user id user_identity = self.clients.resource_registry.read(user_id) if not user_identity: raise NotFound("UserIdentity %s does not exist" % user_id) return user_identity def delete_user_identity(self, user_id=""): # Read and delete specified UserIdentity object user_identity = self.clients.resource_registry.read(user_id) if not user_identity: raise NotFound("UserIdentity %s does not exist" % user_id) self.clients.resource_registry.delete(user_id) def register_user_credentials(self, user_id="", credentials=None): # Create UserCredentials object credentials_obj_id, version = self.clients.resource_registry.create(credentials) # Create association with user identity object res = self.clients.resource_registry.create_association(user_id, AT.hasCredentials, credentials_obj_id) def unregister_user_credentials(self, user_id="", credentials_name=""): # Read UserCredentials objects, matches = self.clients.resource_registry.find_resources( RT.UserCredentials, None, credentials_name, False ) if not objects or len(objects) == 0: raise NotFound("UserCredentials %s does not exist" % credentials_name) if len(objects) > 1: raise Conflict("Multiple UserCredentials objects found for subject %s" % credentials_name) user_credentials_id = objects[0]._id # Find and break association with UserIdentity assocs = self.clients.resource_registry.find_associations(user_id, AT.hasCredentials, user_credentials_id) if not assocs or len(assocs) == 0: raise NotFound( "UserIdentity to UserCredentials association for user id %s to credential %s does not exist" % (user_id, credentials_name) ) association_id = assocs[0]._id self.clients.resource_registry.delete_association(association_id) # Delete the UserCredentials self.clients.resource_registry.delete(user_credentials_id) def create_user_info(self, user_id="", user_info=None): # Ensure UserInfo association does not already exist objects, assocs = self.clients.resource_registry.find_objects(user_id, AT.hasInfo, RT.UserInfo) if objects: raise Conflict("UserInfo already exists for user id %s" % (user_id)) # Create UserInfo object user_info_id, version = self.clients.resource_registry.create(user_info) log.warn("user_info_id: %s" % user_info_id) # Create association with user identity object self.clients.resource_registry.create_association(user_id, AT.hasInfo, user_info_id) return user_info_id def update_user_info(self, user_info=None): # Overwrite UserInfo object self.clients.resource_registry.update(user_info) def read_user_info(self, user_info_id=""): # Read UserInfo object with _id matching passed user id user_info = self.clients.resource_registry.read(user_info_id) if not user_info: raise NotFound("UserInfo %s does not exist" % user_info_id) return user_info def delete_user_info(self, user_info_id=""): # Read UserInfo user_info = self.clients.resource_registry.read(user_info_id) if not user_info: raise NotFound("UserInfo %s does not exist" % user_info_id) # Find and break association with UserIdentity subjects, assocs = self.clients.resource_registry.find_subjects(RT.UserIdentity, AT.hasInfo, user_info_id) if not assocs: raise NotFound("UserIdentity to UserInfo association for user info id %s does not exist" % user_info_id) user_identity_id = subjects[0]._id assocs = self.clients.resource_registry.find_associations(user_identity_id, AT.hasInfo, user_info_id) if not assocs: raise NotFound("UserIdentity to UserInfo association for user info id %s does not exist" % user_info_id) association_id = assocs[0]._id self.clients.resource_registry.delete_association(association_id) # Delete the UserInfo self.clients.resource_registry.delete(user_info_id) def find_user_info_by_id(self, user_id=""): # Look up UserInfo via association with UserIdentity objects, assocs = self.clients.resource_registry.find_objects(user_id, AT.hasInfo, RT.UserInfo) if not objects: raise NotFound("UserInfo for user id %s does not exist" % user_id) user_info = objects[0] return user_info def find_user_info_by_name(self, name=""): objects, matches = self.clients.resource_registry.find_resources(RT.UserInfo, None, name, False) if not objects: raise NotFound("UserInfo with name %s does not exist" % name) if len(objects) > 1: raise Inconsistent("Multiple UserInfos with name %s exist" % name) return objects[0] def find_user_info_by_subject(self, subject=""): # Find UserCredentials objects, matches = self.clients.resource_registry.find_resources(RT.UserCredentials, None, subject, False) if not objects: raise NotFound("UserCredentials with subject %s does not exist" % subject) if len(objects) > 1: raise Inconsistent("Multiple UserCredentials with subject %s exist" % subject) user_credentials_id = objects[0]._id subjects, assocs = self.clients.resource_registry.find_subjects( RT.UserIdentity, AT.hasCredentials, user_credentials_id ) if not subjects or len(subjects) == 0: raise NotFound("UserIdentity to UserCredentials association for subject %s does not exist" % subject) if len(subjects) > 1: raise Inconsistent("Multiple UserIdentity to UserCredentials associations for subject %s exist" % subject) user_identity_id = subjects[0]._id # Look up UserInfo via association with UserIdentity objects, assocs = self.clients.resource_registry.find_objects(user_identity_id, AT.hasInfo, RT.UserInfo) if not objects: raise NotFound("UserInfo for subject %s does not exist" % subject) if len(objects) > 1: raise Inconsistent("Multiple UserInfos for subject %s exist" % subject) user_info = objects[0] return user_info def signon(self, certificate="", ignore_date_range=False): # Check the certificate is currently valid if not ignore_date_range: if not self.authentication.is_certificate_within_date_range(certificate): raise BadRequest("Certificate expired or not yet valid") # Extract subject line attributes = self.authentication.decode_certificate(certificate) subject = attributes["subject"] valid_until = attributes["not_valid_after"] # Look for matching UserCredentials object objects, assocs = self.clients.resource_registry.find_resources(RT.UserCredentials, None, subject, True) if len(objects) > 1: raise Conflict("More than one UserCredentials object was found for subject %s" % subject) if len(assocs) > 1: raise Conflict("More than one UserIdentity object is associated with subject %s" % subject) if len(objects) == 1: # Known user, get UserIdentity object user_credentials_id = objects[0] log.warn("objects: %s" % str(objects)) log.warn("user_credentials_id: %s" % user_credentials_id) subjects, assocs = self.clients.resource_registry.find_subjects( RT.UserIdentity, AT.hasCredentials, user_credentials_id ) if len(subjects) == 0: raise Conflict( "UserIdentity object with subject %s was previously created but is not associated with a UserIdentity object" % subject ) user_id = subjects[0]._id log.warn("subjects: %s" % str(subjects)) log.warn("user_id: %s" % user_id) # Find associated UserInfo registered = True try: self.find_user_info_by_id(user_id) except NotFound: registered = False return user_id, valid_until, registered else: # New user. Create UserIdentity and UserCredentials user_identity = IonObject("UserIdentity", {"name": subject}) user_id = self.create_user_identity(user_identity) user_credentials = IonObject("UserCredentials", {"name": subject}) self.register_user_credentials(user_id, user_credentials) return user_id, valid_until, False def create_resource_identity(self, resource_identity=None): # Persist ResourceIdentity object and return object _id as OOI id resource_identity_id, version = self.clients.resource_registry.create(resource_identity) return resource_identity_id def update_resource_identity(self, resource_identity=None): # Overwrite ResourceIdentity object self.clients.resource_registry.update(resource_identity) def read_resource_identity(self, resource_identity_id=""): # Read ResourceIdentity object with _id matching passed user id return self.clients.resource_registry.read(resource_identity_id) def delete_resource_identity(self, resource_identity_id=""): # Read and delete specified ResourceIdentity object resource_identity = self.clients.resource_registry.read(resource_identity_id) self.clients.resource_registry.delete(resource_identity_id)
class IdentityManagementService(BaseIdentityManagementService): """ A resource registry that stores identities of users and resources, including bindings of internal identities to external identities. Also stores metadata such as a user profile.a A resource registry that stores identities of users and resources, including bindings of internal identities to external identities. Also stores metadata such as a user profile.a """ def on_init(self): self.authentication = Authentication() def create_actor_identity(self, actor_identity=None): # Persist ActorIdentity object and return object _id as OOI id user_id, version = self.clients.resource_registry.create(actor_identity) return user_id def update_actor_identity(self, actor_identity=None): # Overwrite ActorIdentity object self.clients.resource_registry.update(actor_identity) def read_actor_identity(self, user_id=''): # Read ActorIdentity object with _id matching passed user id actor_identity = self.clients.resource_registry.read(user_id) if not actor_identity: raise NotFound("ActorIdentity %s does not exist" % user_id) return actor_identity def delete_actor_identity(self, user_id=''): # Read and delete specified ActorIdentity object actor_identity = self.clients.resource_registry.read(user_id) if not actor_identity: raise NotFound("ActorIdentity %s does not exist" % user_id) self.clients.resource_registry.delete(user_id) def find_actor_identity_by_name(self, name=''): """Return the ActorIdentity object whose name attribute matches the passed value. @param name str @retval user_info ActorIdentity @throws NotFound failed to find ActorIdentity @throws Inconsistent Multiple ActorIdentity objects matched name """ objects, matches = self.clients.resource_registry.find_resources(RT.ActorIdentity, None, name, False) if not objects: raise NotFound("ActorIdentity with name %s does not exist" % name) if len(objects) > 1: raise Inconsistent("Multiple ActorIdentity objects with name %s exist" % name) return objects[0] def register_user_credentials(self, user_id='', credentials=None): # Create UserCredentials object credentials_obj_id, version = self.clients.resource_registry.create(credentials) # Create association with user identity object res = self.clients.resource_registry.create_association(user_id, PRED.hasCredentials, credentials_obj_id) def unregister_user_credentials(self, user_id='', credentials_name=''): # Read UserCredentials objects, matches = self.clients.resource_registry.find_resources(RT.UserCredentials, None, credentials_name, False) if not objects or len(objects) == 0: raise NotFound("UserCredentials %s does not exist" % credentials_name) if len(objects) > 1: raise Conflict("Multiple UserCredentials objects found for subject %s" % credentials_name) user_credentials_id = objects[0]._id # Find and break association with ActorIdentity assocs = self.clients.resource_registry.find_associations(user_id, PRED.hasCredentials, user_credentials_id) if not assocs or len(assocs) == 0: raise NotFound("ActorIdentity to UserCredentials association for user id %s to credential %s does not exist" % (user_id,credentials_name)) association_id = assocs[0]._id self.clients.resource_registry.delete_association(association_id) # Delete the UserCredentials self.clients.resource_registry.delete(user_credentials_id) def create_user_info(self, user_id="", user_info=None): # Ensure UserInfo association does not already exist objects, assocs = self.clients.resource_registry.find_objects(user_id, PRED.hasInfo, RT.UserInfo) if objects: raise Conflict("UserInfo already exists for user id %s" % (user_id)) # Create UserInfo object user_info_id, version = self.clients.resource_registry.create(user_info) # Create association with user identity object self.clients.resource_registry.create_association(user_id, PRED.hasInfo, user_info_id) return user_info_id def update_user_info(self, user_info=None): # Overwrite UserInfo object self.clients.resource_registry.update(user_info) def read_user_info(self, user_info_id=''): # Read UserInfo object with _id matching passed user id user_info = self.clients.resource_registry.read(user_info_id) if not user_info: raise NotFound("UserInfo %s does not exist" % user_info_id) return user_info def delete_user_info(self, user_info_id=''): # Read UserInfo user_info = self.clients.resource_registry.read(user_info_id) if not user_info: raise NotFound("UserInfo %s does not exist" % user_info_id) # Find and break association with ActorIdentity subjects, assocs = self.clients.resource_registry.find_subjects(RT.ActorIdentity, PRED.hasInfo, user_info_id) if not assocs: raise NotFound("ActorIdentity to UserInfo association for user info id %s does not exist" % user_info_id) actor_identity_id = subjects[0]._id assocs = self.clients.resource_registry.find_associations(actor_identity_id, PRED.hasInfo, user_info_id) if not assocs: raise NotFound("ActorIdentity to UserInfo association for user info id %s does not exist" % user_info_id) association_id = assocs[0]._id self.clients.resource_registry.delete_association(association_id) # Delete the UserInfo self.clients.resource_registry.delete(user_info_id) def find_user_info_by_id(self, user_id=''): # Look up UserInfo via association with ActorIdentity objects, assocs = self.clients.resource_registry.find_objects(user_id, PRED.hasInfo, RT.UserInfo) if not objects: raise NotFound("UserInfo for user id %s does not exist" % user_id) user_info = objects[0] return user_info def find_user_info_by_name(self, name=''): objects, matches = self.clients.resource_registry.find_resources(RT.UserInfo, None, name, False) if not objects: raise NotFound("UserInfo with name %s does not exist" % name) if len(objects) > 1: raise Inconsistent("Multiple UserInfo objects with name %s exist" % name) return objects[0] def find_user_info_by_subject(self, subject=''): # Find UserCredentials objects, matches = self.clients.resource_registry.find_resources(RT.UserCredentials, None, subject, False) if not objects: raise NotFound("UserCredentials with subject %s does not exist" % subject) if len(objects) > 1: raise Inconsistent("Multiple UserCredentials with subject %s exist" % subject) user_credentials_id = objects[0]._id subjects, assocs = self.clients.resource_registry.find_subjects(RT.ActorIdentity, PRED.hasCredentials, user_credentials_id) if not subjects or len(subjects) == 0: raise NotFound("ActorIdentity to UserCredentials association for subject %s does not exist" % subject) if len(subjects) > 1: raise Inconsistent("Multiple ActorIdentity to UserCredentials associations for subject %s exist" % subject) actor_identity_id = subjects[0]._id # Look up UserInfo via association with ActorIdentity objects, assocs = self.clients.resource_registry.find_objects(actor_identity_id, PRED.hasInfo, RT.UserInfo) if not objects: raise NotFound("UserInfo for subject %s does not exist" % subject) if len(objects) > 1: raise Inconsistent("Multiple UserInfos for subject %s exist" % subject) user_info = objects[0] return user_info def signon(self, certificate='', ignore_date_range=False): log.debug("Signon with certificate:\n%s" % certificate) # Check the certificate is currently valid if not ignore_date_range: if not self.authentication.is_certificate_within_date_range(certificate): raise BadRequest("Certificate expired or not yet valid") # Extract subject line attributes = self.authentication.decode_certificate(certificate) subject = attributes["subject"] valid_until_str = attributes["not_valid_after"] log.debug("Signon request for subject %s with string valid_until %s" % (subject, valid_until_str)) valid_until_tuple = time.strptime(valid_until_str, "%b %d %H:%M:%S %Y %Z") valid_until = str(int(time.mktime(valid_until_tuple)) * 1000) # Look for matching UserCredentials object objects, assocs = self.clients.resource_registry.find_resources(RT.UserCredentials, None, subject, True) if len(objects) > 1: raise Conflict("More than one UserCredentials object was found for subject %s" % subject) if len(assocs) > 1: raise Conflict("More than one ActorIdentity object is associated with subject %s" % subject) if len(objects) == 1: log.debug("Signon known subject %s" % (subject)) # Known user, get ActorIdentity object user_credentials_id = objects[0] subjects, assocs = self.clients.resource_registry.find_subjects(RT.ActorIdentity, PRED.hasCredentials, user_credentials_id) if len(subjects) == 0: raise Conflict("ActorIdentity object with subject %s was previously created but is not associated with a ActorIdentity object" % subject) user_id = subjects[0]._id # Find associated UserInfo registered = True try: self.find_user_info_by_id(user_id) except NotFound: registered = False log.debug("Signon returning user_id, valid_until, registered: %s, %s, %s" % (user_id, valid_until, str(registered))) return user_id, valid_until, registered else: log.debug("Signon new subject %s" % (subject)) # New user. Create ActorIdentity and UserCredentials actor_identity = IonObject("ActorIdentity", {"name": subject}) user_id = self.create_actor_identity(actor_identity) user_credentials = IonObject("UserCredentials", {"name": subject}) self.register_user_credentials(user_id, user_credentials) log.debug("Signon returning user_id, valid_until, registered: %s, %s, False" % (user_id, valid_until)) return user_id, valid_until, False def create_resource_identity(self, resource_identity=None): # Persist ResourceIdentity object and return object _id as OOI id resource_identity_id, version = self.clients.resource_registry.create(resource_identity) return resource_identity_id def update_resource_identity(self, resource_identity=None): # Overwrite ResourceIdentity object self.clients.resource_registry.update(resource_identity) def read_resource_identity(self, resource_identity_id=''): # Read ResourceIdentity object with _id matching passed user id return self.clients.resource_registry.read(resource_identity_id) def delete_resource_identity(self, resource_identity_id=''): # Read and delete specified ResourceIdentity object resource_identity = self.clients.resource_registry.read(resource_identity_id) self.clients.resource_registry.delete(resource_identity_id)
class IdentityManagementService(BaseIdentityManagementService): """ A resource registry that stores identities of users and resources, including bindings of internal identities to external identities. Also stores metadata such as a user profile.a A resource registry that stores identities of users and resources, including bindings of internal identities to external identities. Also stores metadata such as a user profile.a """ def on_init(self): self.authentication = Authentication() def create_actor_identity(self, actor_identity=None): # Persist ActorIdentity object and return object _id as OOI id user_id, version = self.clients.resource_registry.create(actor_identity) return user_id def update_actor_identity(self, actor_identity=None): # Overwrite ActorIdentity object self.clients.resource_registry.update(actor_identity) def read_actor_identity(self, user_id=""): # Read ActorIdentity object with _id matching passed user id actor_identity = self.clients.resource_registry.read(user_id) if not actor_identity: raise NotFound("ActorIdentity %s does not exist" % user_id) return actor_identity def delete_actor_identity(self, user_id=""): # Read and delete specified ActorIdentity object actor_identity = self.clients.resource_registry.read(user_id) if not actor_identity: raise NotFound("ActorIdentity %s does not exist" % user_id) self.clients.resource_registry.delete(user_id) def find_actor_identity_by_name(self, name=""): """Return the ActorIdentity object whose name attribute matches the passed value. @param name str @retval user_info ActorIdentity @throws NotFound failed to find ActorIdentity @throws Inconsistent Multiple ActorIdentity objects matched name """ objects, matches = self.clients.resource_registry.find_resources(RT.ActorIdentity, None, name, False) if not objects: raise NotFound("ActorIdentity with name %s does not exist" % name) if len(objects) > 1: raise Inconsistent("Multiple ActorIdentity objects with name %s exist" % name) return objects[0] def register_user_credentials(self, user_id="", credentials=None): # Create UserCredentials object credentials_obj_id, version = self.clients.resource_registry.create(credentials) # Create association with user identity object res = self.clients.resource_registry.create_association(user_id, PRED.hasCredentials, credentials_obj_id) def unregister_user_credentials(self, user_id="", credentials_name=""): # Read UserCredentials objects, matches = self.clients.resource_registry.find_resources( RT.UserCredentials, None, credentials_name, False ) if not objects or len(objects) == 0: raise NotFound("UserCredentials %s does not exist" % credentials_name) if len(objects) > 1: raise Conflict("Multiple UserCredentials objects found for subject %s" % credentials_name) user_credentials_id = objects[0]._id # Find and break association with ActorIdentity assocs = self.clients.resource_registry.find_associations(user_id, PRED.hasCredentials, user_credentials_id) if not assocs or len(assocs) == 0: raise NotFound( "ActorIdentity to UserCredentials association for user id %s to credential %s does not exist" % (user_id, credentials_name) ) association_id = assocs[0]._id self.clients.resource_registry.delete_association(association_id) # Delete the UserCredentials self.clients.resource_registry.delete(user_credentials_id) def create_user_info(self, user_id="", user_info=None): # Ensure UserInfo association does not already exist objects, assocs = self.clients.resource_registry.find_objects(user_id, PRED.hasInfo, RT.UserInfo) if objects: raise Conflict("UserInfo already exists for user id %s" % (user_id)) # Create UserInfo object user_info_id, version = self.clients.resource_registry.create(user_info) # Create association with user identity object self.clients.resource_registry.create_association(user_id, PRED.hasInfo, user_info_id) return user_info_id def update_user_info(self, user_info=None): # Overwrite UserInfo object self.clients.resource_registry.update(user_info) def read_user_info(self, user_info_id=""): # Read UserInfo object with _id matching passed user id user_info = self.clients.resource_registry.read(user_info_id) if not user_info: raise NotFound("UserInfo %s does not exist" % user_info_id) return user_info def delete_user_info(self, user_info_id=""): # Read UserInfo user_info = self.clients.resource_registry.read(user_info_id) if not user_info: raise NotFound("UserInfo %s does not exist" % user_info_id) # Find and break association with ActorIdentity subjects, assocs = self.clients.resource_registry.find_subjects(RT.ActorIdentity, PRED.hasInfo, user_info_id) if not assocs: raise NotFound("ActorIdentity to UserInfo association for user info id %s does not exist" % user_info_id) actor_identity_id = subjects[0]._id assocs = self.clients.resource_registry.find_associations(actor_identity_id, PRED.hasInfo, user_info_id) if not assocs: raise NotFound("ActorIdentity to UserInfo association for user info id %s does not exist" % user_info_id) association_id = assocs[0]._id self.clients.resource_registry.delete_association(association_id) # Delete the UserInfo self.clients.resource_registry.delete(user_info_id) def find_user_info_by_id(self, user_id=""): # Look up UserInfo via association with ActorIdentity objects, assocs = self.clients.resource_registry.find_objects(user_id, PRED.hasInfo, RT.UserInfo) if not objects: raise NotFound("UserInfo for user id %s does not exist" % user_id) user_info = objects[0] return user_info def find_user_info_by_name(self, name=""): objects, matches = self.clients.resource_registry.find_resources(RT.UserInfo, None, name, False) if not objects: raise NotFound("UserInfo with name %s does not exist" % name) if len(objects) > 1: raise Inconsistent("Multiple UserInfo objects with name %s exist" % name) return objects[0] def find_user_info_by_subject(self, subject=""): # Find UserCredentials objects, matches = self.clients.resource_registry.find_resources(RT.UserCredentials, None, subject, False) if not objects: raise NotFound("UserCredentials with subject %s does not exist" % subject) if len(objects) > 1: raise Inconsistent("Multiple UserCredentials with subject %s exist" % subject) user_credentials_id = objects[0]._id subjects, assocs = self.clients.resource_registry.find_subjects( RT.ActorIdentity, PRED.hasCredentials, user_credentials_id ) if not subjects or len(subjects) == 0: raise NotFound("ActorIdentity to UserCredentials association for subject %s does not exist" % subject) if len(subjects) > 1: raise Inconsistent("Multiple ActorIdentity to UserCredentials associations for subject %s exist" % subject) actor_identity_id = subjects[0]._id # Look up UserInfo via association with ActorIdentity objects, assocs = self.clients.resource_registry.find_objects(actor_identity_id, PRED.hasInfo, RT.UserInfo) if not objects: raise NotFound("UserInfo for subject %s does not exist" % subject) if len(objects) > 1: raise Inconsistent("Multiple UserInfos for subject %s exist" % subject) user_info = objects[0] return user_info def signon(self, certificate="", ignore_date_range=False): log.debug("Signon with certificate:\n%s" % certificate) # Check the certificate is currently valid if not ignore_date_range: if not self.authentication.is_certificate_within_date_range(certificate): raise BadRequest("Certificate expired or not yet valid") # Extract subject line attributes = self.authentication.decode_certificate_string(certificate) subject = attributes["subject"] valid_until_str = attributes["not_valid_after"] log.debug("Signon request for subject %s with string valid_until %s" % (subject, valid_until_str)) valid_until_tuple = time.strptime(valid_until_str, "%b %d %H:%M:%S %Y %Z") valid_until = str(int(time.mktime(valid_until_tuple)) * 1000) # Look for matching UserCredentials object objects, assocs = self.clients.resource_registry.find_resources(RT.UserCredentials, None, subject, True) if len(objects) > 1: raise Conflict("More than one UserCredentials object was found for subject %s" % subject) if len(assocs) > 1: raise Conflict("More than one ActorIdentity object is associated with subject %s" % subject) if len(objects) == 1: log.debug("Signon known subject %s" % (subject)) # Known user, get ActorIdentity object user_credentials_id = objects[0] subjects, assocs = self.clients.resource_registry.find_subjects( RT.ActorIdentity, PRED.hasCredentials, user_credentials_id ) if len(subjects) == 0: raise Conflict( "ActorIdentity object with subject %s was previously created but is not associated with a ActorIdentity object" % subject ) user_id = subjects[0]._id # Find associated UserInfo registered = True try: self.find_user_info_by_id(user_id) except NotFound: registered = False log.debug( "Signon returning user_id, valid_until, registered: %s, %s, %s" % (user_id, valid_until, str(registered)) ) return user_id, valid_until, registered else: log.debug("Signon new subject %s" % (subject)) # New user. Create ActorIdentity and UserCredentials actor_identity = IonObject("ActorIdentity", {"name": subject}) user_id = self.create_actor_identity(actor_identity) user_credentials = IonObject("UserCredentials", {"name": subject}) self.register_user_credentials(user_id, user_credentials) log.debug("Signon returning user_id, valid_until, registered: %s, %s, False" % (user_id, valid_until)) return user_id, valid_until, False def get_actor_identity_extension(self, user_id="", org_id="", ext_associations=None, ext_exclude=None): """Returns an ActorIdentityExtension object containing additional related information @param user_id str @param org_id str @param ext_associations dict @param ext_exclude list @retval actor_identity ActorIdentityExtension @throws BadRequest A parameter is missing @throws NotFound An object with the specified user_id does not exist """ if not user_id: raise BadRequest("The user_id parameter is empty") extended_resource_handler = ExtendedResourceContainer(self) extended_user = extended_resource_handler.create_extended_resource_container( OT.ActorIdentityExtension, user_id, None, ext_associations, ext_exclude ) # If the org_id is not provided then skip looking for Org related roles. if org_id: # Did not setup a dependency to org_management service to avoid a potential circular bootstrap issue # since this method should never be called until the system is fully running try: org_client = OrgManagementServiceProcessClient(process=self) roles = org_client.find_org_roles_by_user(org_id, user_id) extended_user.roles = roles except Exception, e: # If this information is not available yet, them just move on and caller can retry later pass return extended_user
def test_authentication(self): private_key = """ -----BEGIN RSA PRIVATE KEY----- MIICXQIBAAKBgQDELieVJmWlcD1qfumxhraYailqB9Wd9emCLtSDPRRNAbSvOrTd +YVHvdC6xMG1JykFRUld4oWcHW7VGDVeiERAlUnfeJ/gK5/UkfUlJWqEOL7Hks9B lN7ls+1E94lGdDZ4hFl56k/rC7ERt8Z88ogZACirXEW6QG3C+dhO2XA3ZwIDAQAB AoGARyIBIjiY9KK88idwbvlMrfkYaSTMFQl8kMKQNcHo4X8z17GusSnvZLLzwzTi k9/OJOYZkxw2nAOkE0pC17MLI8inO9gljv3jfdbpJ07iOkDHQ8AUEBRyJKdkG1BP Xx1uCVnxocihni66w0VPM50X66LQsB2Tujei7PI1e3l4rckCQQDzsdzXykNGwrr5 j7XMKWAwrzCRKciBhnk0JDwxDKE7fV7f+KpbgBd3sfgOzSg+or33tpRXHOia284i K+TpuB6NAkEAzhYXuoNWbDNGy3Bjh7wBg7rdaldFCUft4LPFfj8HnS4bzsUybhm7 SrrESyr8FJbNKmCVn0fIa82yjfAofZk6wwJABet0KenH6JgiYp2TFPqMU6Jt05jo Pf0+RH382FQuNnu9KkOoH8Dk0QuJsxJYv+zEIJhW0ibpn5lnUH0welz2oQJBAJRu /yo8XKvUBuKSkW17MVAS8FUehD/aCfB1KwLyHObOBgNYryjz6Z06hhVp4WRm9WDX bgzqI+XZowhueIt2KQcCQQDNQIhcZduGlG9n//w+MmZ2NuRzW8nANTgS9Ds759vJ qBkRbsUcWgYKXN4RIqpc1Gjbsb4ltyprCOM35s5v8Ggc -----END RSA PRIVATE KEY----- """ certificate_crt = """ -----BEGIN CERTIFICATE----- MIICPzCCAagCCQCRkPH0fJqEzzANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJB VTELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVNhbiBEaWVnbzEOMAwGA1UEChMFT09J Q0kxETAPBgNVBAMTCFRoZSBEdWRlMREwDwYJKoZIhvcNAQkBFgJOQTAeFw0xMzAx MTAwMTM2NTlaFw0xNDAxMTAwMTM2NTlaMGQxCzAJBgNVBAYTAkFVMQswCQYDVQQI EwJDQTESMBAGA1UEBxMJU2FuIERpZWdvMQ4wDAYDVQQKEwVPT0lDSTERMA8GA1UE AxMIVGhlIER1ZGUxETAPBgkqhkiG9w0BCQEWAk5BMIGfMA0GCSqGSIb3DQEBAQUA A4GNADCBiQKBgQDELieVJmWlcD1qfumxhraYailqB9Wd9emCLtSDPRRNAbSvOrTd +YVHvdC6xMG1JykFRUld4oWcHW7VGDVeiERAlUnfeJ/gK5/UkfUlJWqEOL7Hks9B lN7ls+1E94lGdDZ4hFl56k/rC7ERt8Z88ogZACirXEW6QG3C+dhO2XA3ZwIDAQAB MA0GCSqGSIb3DQEBBQUAA4GBAAerq2XzxvcRZ8mskIKTjf/C+B4t2fiCp1lF/ca4 7FxJqmOLvoSJm0eVM0kt67WWy+IeCijctVv1BNhs/FpzaAWKAGjcR36QYpjhjqKs uCCjrh18zMGpSfKGCoEXb9xKp45UrREqpcbWGYdf3NabKeZSfTXUcxocLh7dtgSS hEct -----END CERTIFICATE----- """ certificate_csr = """ -----BEGIN CERTIFICATE REQUEST----- MIIBuTCCASICAQAwZDELMAkGA1UEBhMCQVUxCzAJBgNVBAgTAkNBMRIwEAYDVQQH EwlTYW4gRGllZ28xDjAMBgNVBAoTBU9PSUNJMREwDwYDVQQDEwhUaGUgRHVkZTER MA8GCSqGSIb3DQEJARYCTkEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMQu J5UmZaVwPWp+6bGGtphqKWoH1Z316YIu1IM9FE0BtK86tN35hUe90LrEwbUnKQVF SV3ihZwdbtUYNV6IRECVSd94n+Arn9SR9SUlaoQ4vseSz0GU3uWz7UT3iUZ0NniE WXnqT+sLsRG3xnzyiBkAKKtcRbpAbcL52E7ZcDdnAgMBAAGgFTATBgkqhkiG9w0B CQcxBhMEcGFzczANBgkqhkiG9w0BAQUFAAOBgQBmjsWSCpEv0O76KUv/XArsm9QM 7B6xKxpivLFWh8cOgTdQDhucokoLDQ2NLgVYGgmxy+DSswatFSwK+KEe5Zdafri8 WY8o9L2q/6JOlxJk4vC2pgtEVxomMW1nVH2oepIkT3xLbBVCSVGZcRiY7joueR/J fLCIe24piwAfVhpMcQ== -----END CERTIFICATE REQUEST----- """ message = "the dude abides" a = Authentication() certificate = certificate_crt a.add_to_white_list(certificate) status = a.authentication_enabled() self.assertTrue(status == True or status == False) signed_hex = a.sign_message_hex(message, private_key) v, ok = a.verify_message_hex(message, certificate, signed_hex) self.assertEqual(v, "Valid") self.assertEqual(ok, "OK") signed = a.sign_message(message, private_key) v, ok = a.verify_message(message, certificate, signed) self.assertEqual(v, "Valid") self.assertEqual(ok, "OK") decoded_cert = a.decode_certificate_string(certificate) self.assertEqual(decoded_cert['subject_items']['CN'], "The Dude")
class IdentityManagementService(BaseIdentityManagementService): """ A resource registry that stores identities of users and resources, including bindings of internal identities to external identities. Also stores metadata such as a user profile.a A resource registry that stores identities of users and resources, including bindings of internal identities to external identities. Also stores metadata such as a user profile.a """ def on_init(self): self.authentication = Authentication() def create_actor_identity(self, actor_identity=None): # Persist ActorIdentity object and return object _id as OOI id actor_id, version = self.clients.resource_registry.create( actor_identity) return actor_id def update_actor_identity(self, actor_identity=None): # Overwrite ActorIdentity object self.clients.resource_registry.update(actor_identity) def read_actor_identity(self, actor_id=''): # Read ActorIdentity object with _id matching passed user id actor_identity = self.clients.resource_registry.read(actor_id) return actor_identity def delete_actor_identity(self, actor_id=''): # Delete specified ActorIdentity object self.clients.resource_registry.delete(actor_id) def find_actor_identity_by_name(self, name=''): """Return the ActorIdentity object whose name attribute matches the passed value. @param name str @retval user_info ActorIdentity @throws NotFound failed to find ActorIdentity @throws Inconsistent Multiple ActorIdentity objects matched name """ objects, matches = self.clients.resource_registry.find_resources( RT.ActorIdentity, None, name, id_only=False) if not objects: raise NotFound("ActorIdentity with name %s does not exist" % name) if len(objects) > 1: raise Inconsistent( "Multiple ActorIdentity objects with name %s exist" % name) return objects[0] def register_user_credentials(self, actor_id='', credentials=None): # Create UserCredentials object credentials_obj_id, version = self.clients.resource_registry.create( credentials) # Create association with user identity object res = self.clients.resource_registry.create_association( actor_id, PRED.hasCredentials, credentials_obj_id) def unregister_user_credentials(self, actor_id='', credentials_name=''): # Read UserCredentials objects, matches = self.clients.resource_registry.find_resources( RT.UserCredentials, None, credentials_name, id_only=False) if not objects or len(objects) == 0: raise NotFound("UserCredentials %s does not exist" % credentials_name) if len(objects) > 1: raise Conflict( "Multiple UserCredentials objects found for subject %s" % credentials_name) user_credentials_id = objects[0]._id # Find and break association with ActorIdentity assocs = self.clients.resource_registry.find_associations( actor_id, PRED.hasCredentials, user_credentials_id) if not assocs or len(assocs) == 0: raise NotFound( "ActorIdentity to UserCredentials association for user id %s to credential %s does not exist" % (actor_id, credentials_name)) association_id = assocs[0]._id self.clients.resource_registry.delete_association(association_id) # Delete the UserCredentials self.clients.resource_registry.delete(user_credentials_id) def create_user_info(self, actor_id="", user_info=None): # Ensure UserInfo association does not already exist objects, assocs = self.clients.resource_registry.find_objects( actor_id, PRED.hasInfo, RT.UserInfo) if objects: raise Conflict("UserInfo already exists for user id %s" % (actor_id)) # Create UserInfo object user_info_id, version = self.clients.resource_registry.create( user_info) # Create association with user identity object self.clients.resource_registry.create_association( actor_id, PRED.hasInfo, user_info_id) return user_info_id def update_user_info(self, user_info=None): # Overwrite UserInfo object self.clients.resource_registry.update(user_info) def read_user_info(self, user_info_id=''): # Read UserInfo object with _id matching passed user id user_info = self.clients.resource_registry.read(user_info_id) return user_info def delete_user_info(self, user_info_id='', actor_identity_id=''): # Read UserInfo user_info = self.clients.resource_registry.read(user_info_id) if not user_info: raise NotFound("UserInfo %s does not exist" % user_info_id) # Find and break association with ActorIdentity if not actor_identity_id: subjects, assocs = self.clients.resource_registry.find_subjects( RT.ActorIdentity, PRED.hasInfo, user_info_id) if not assocs: raise NotFound( "ActorIdentity to UserInfo association for user info id %s does not exist" % user_info_id) actor_identity_id = subjects[0]._id assocs = self.clients.resource_registry.find_associations( actor_identity_id, PRED.hasInfo, user_info_id) if not assocs: raise NotFound( "ActorIdentity to UserInfo association for user info id %s does not exist" % user_info_id) association_id = assocs[0]._id self.clients.resource_registry.delete_association(association_id) # Delete the UserInfo self.clients.resource_registry.delete(user_info_id) def find_user_info_by_email(self, user_email=''): #return self.clients.resource_registry.find_resources_ext(restype=RT.UserInfo, attr_name="contact.email", attr_value=user_email, id_only=False) user_infos, _ = self.clients.resource_registry.find_resources_ext( RT.UserInfo, attr_name="contact.email", attr_value=user_email) if len(user_infos) > 1: log.warn("More than one UserInfo found for email '%s': %s" % (user_email, [ui._id for ui in user_infos])) if user_infos: return user_infos[0] return None def find_user_info_by_id(self, actor_id=''): # Look up UserInfo via association with ActorIdentity objects, assocs = self.clients.resource_registry.find_objects( actor_id, PRED.hasInfo, RT.UserInfo) if not objects: raise NotFound("UserInfo for user id %s does not exist" % actor_id) user_info = objects[0] return user_info def find_user_info_by_name(self, name=''): objects, matches = self.clients.resource_registry.find_resources( RT.UserInfo, None, name, id_only=False) if not objects: raise NotFound("UserInfo with name %s does not exist" % name) if len(objects) > 1: raise Inconsistent("Multiple UserInfo objects with name %s exist" % name) return objects[0] def find_user_info_by_subject(self, subject=''): # Find UserCredentials objects, matches = self.clients.resource_registry.find_resources( RT.UserCredentials, None, subject, id_only=False) if not objects: raise NotFound("UserCredentials with subject %s does not exist" % subject) if len(objects) > 1: raise Inconsistent( "Multiple UserCredentials with subject %s exist" % subject) user_credentials_id = objects[0]._id subjects, assocs = self.clients.resource_registry.find_subjects( RT.ActorIdentity, PRED.hasCredentials, user_credentials_id) if not subjects or len(subjects) == 0: raise NotFound( "ActorIdentity to UserCredentials association for subject %s does not exist" % subject) if len(subjects) > 1: raise Inconsistent( "Multiple ActorIdentity to UserCredentials associations for subject %s exist" % subject) actor_identity_id = subjects[0]._id # Look up UserInfo via association with ActorIdentity objects, assocs = self.clients.resource_registry.find_objects( actor_identity_id, PRED.hasInfo, RT.UserInfo) if not objects: raise NotFound("UserInfo for subject %s does not exist" % subject) if len(objects) > 1: raise Inconsistent("Multiple UserInfos for subject %s exist" % subject) user_info = objects[0] return user_info def signon(self, certificate='', ignore_date_range=False): log.debug("Signon with certificate:\n%s" % certificate) # Check the certificate is currently valid if not ignore_date_range: if not self.authentication.is_certificate_within_date_range( certificate): raise BadRequest("Certificate expired or not yet valid") # Extract subject line attributes = self.authentication.decode_certificate_string(certificate) subject = attributes["subject"] valid_until_str = attributes["not_valid_after"] log.debug("Signon request for subject %s with string valid_until %s" % (subject, valid_until_str)) valid_until_tuple = time.strptime(valid_until_str, "%b %d %H:%M:%S %Y %Z") valid_until = str(int(time.mktime(valid_until_tuple)) * 1000) # Look for matching UserCredentials object objects, assocs = self.clients.resource_registry.find_resources( RT.UserCredentials, None, subject, True) if len(objects) > 1: raise Conflict( "More than one UserCredentials object was found for subject %s" % subject) if len(objects) == 1: log.debug("Signon known subject %s" % (subject)) # Known user, get ActorIdentity object user_credentials_id = objects[0] subjects, assocs = self.clients.resource_registry.find_subjects( RT.ActorIdentity, PRED.hasCredentials, user_credentials_id) if len(subjects) == 0: raise Conflict( "ActorIdentity object with subject %s was previously created but is not associated with a ActorIdentity object" % subject) actor_id = subjects[0]._id # Find associated UserInfo registered = True try: self.find_user_info_by_id(actor_id) except NotFound: registered = False log.debug( "Signon returning actor_id, valid_until, registered: %s, %s, %s" % (actor_id, valid_until, str(registered))) return actor_id, valid_until, registered else: log.debug("Signon new subject %s" % (subject)) # New user. Create ActorIdentity and UserCredentials actor_name = "Identity for %s" % subject actor_identity = IonObject("ActorIdentity", name=actor_name) actor_id = self.create_actor_identity(actor_identity) user_credentials = IonObject( "UserCredentials", name=subject, description="Default credentials for %s" % subject) self.register_user_credentials(actor_id, user_credentials) log.debug( "Signon returning actor_id, valid_until, registered: %s, %s, False" % (actor_id, valid_until)) return actor_id, valid_until, False def get_user_info_extension(self, user_info_id='', org_id=''): """Returns an UserInfoExtension object containing additional related information @param user_info_id str @param org_id str - An optional org id that the user is interested in filtering against. @retval user_info UserInfoExtension @throws BadRequest A parameter is missing @throws NotFound An object with the specified actor_id does not exist """ if not user_info_id: raise BadRequest("The user_info_id parameter is empty") #THis is a hack to get the UI going. It would be preferable to get the actor id from the extended resource #container below, but their would need to be a guarantee of order of field processing in order #to ensure that the actor identity has been found BEFORE the negotiation methods are called - and probably #some elegant way to indicate the field and sub field; ie actor_identity._id actors, _ = self.clients.resource_registry.find_subjects( subject_type=RT.ActorIdentity, predicate=PRED.hasInfo, object=user_info_id, id_only=True) actor_id = actors[0] if len(actors) > 0 else '' extended_resource_handler = ExtendedResourceContainer(self) extended_user = extended_resource_handler.create_extended_resource_container( extended_resource_type=OT.UserInfoExtension, resource_id=user_info_id, computed_resource_type=OT.ComputedAttributes, user_id=user_info_id, org_id=org_id, actor_id=actor_id) #If the org_id is not provided then skip looking for Org related roles. if extended_user: #Did not setup a dependency to org_management service to avoid a potential circular bootstrap issue # since this method should never be called until the system is fully running try: org_client = OrgManagementServiceProcessClient(process=self) roles = org_client.find_all_roles_by_user( extended_user.actor_identity._id) extended_user.roles = list() for org_name in roles: for role in roles[org_name]: flattened_role = copy.copy(role.__dict__) del flattened_role[ 'type_'] #Have to do this to appease the message validators for ION objects flattened_role[ 'org_name'] = org_name #Nothing like forcing a value into the dict to appease the UI code extended_user.roles.append(flattened_role) except Exception, e: raise NotFound( 'Could not retrieve UserRoles for User Info id: %s - %s' % (user_info_id, e.message)) #filter notification requests that are retired extended_user.subscriptions = [ nr for nr in extended_user.subscriptions if nr.temporal_bounds.end_datetime == '' ] #filter owned resources that are retired nr_removed = [] for rsrc in extended_user.owned_resources: #remove all the Notifications if rsrc.type_ != OT.NotificationRequest: nr_removed.append(rsrc) extended_user.owned_resources = [ rsrc for rsrc in nr_removed if rsrc.lcstate != 'DELETED' ] #now append the active NotificationRequests extended_user.owned_resources.extend(extended_user.subscriptions) from ion.util.extresource import strip_resource_extension strip_resource_extension(extended_user) return extended_user
class IdentityManagementService(BaseIdentityManagementService): """ A resource registry that stores identities of users and resources, including bindings of internal identities to external identities. Also stores metadata such as a user profile.a A resource registry that stores identities of users and resources, including bindings of internal identities to external identities. Also stores metadata such as a user profile.a """ def on_init(self): self.authentication = Authentication() def create_actor_identity(self, actor_identity=None): # Persist ActorIdentity object and return object _id as OOI id actor_id, version = self.clients.resource_registry.create(actor_identity) return actor_id def update_actor_identity(self, actor_identity=None): # Overwrite ActorIdentity object self.clients.resource_registry.update(actor_identity) def read_actor_identity(self, actor_id=''): # Read ActorIdentity object with _id matching passed user id actor_identity = self.clients.resource_registry.read(actor_id) return actor_identity def delete_actor_identity(self, actor_id=''): # Delete specified ActorIdentity object self.clients.resource_registry.delete(actor_id) def find_actor_identity_by_name(self, name=''): """Return the ActorIdentity object whose name attribute matches the passed value. @param name str @retval user_info ActorIdentity @throws NotFound failed to find ActorIdentity @throws Inconsistent Multiple ActorIdentity objects matched name """ objects, matches = self.clients.resource_registry.find_resources(RT.ActorIdentity, None, name, id_only=False) if not objects: raise NotFound("ActorIdentity with name %s does not exist" % name) if len(objects) > 1: raise Inconsistent("Multiple ActorIdentity objects with name %s exist" % name) return objects[0] def register_user_credentials(self, actor_id='', credentials=None): # Create UserCredentials object credentials_obj_id, version = self.clients.resource_registry.create(credentials) # Create association with user identity object res = self.clients.resource_registry.create_association(actor_id, PRED.hasCredentials, credentials_obj_id) def unregister_user_credentials(self, actor_id='', credentials_name=''): # Read UserCredentials objects, matches = self.clients.resource_registry.find_resources(RT.UserCredentials, None, credentials_name, id_only=False) if not objects or len(objects) == 0: raise NotFound("UserCredentials %s does not exist" % credentials_name) if len(objects) > 1: raise Conflict("Multiple UserCredentials objects found for subject %s" % credentials_name) user_credentials_id = objects[0]._id # Find and break association with ActorIdentity assocs = self.clients.resource_registry.find_associations(actor_id, PRED.hasCredentials, user_credentials_id) if not assocs or len(assocs) == 0: raise NotFound("ActorIdentity to UserCredentials association for user id %s to credential %s does not exist" % (actor_id, credentials_name)) association_id = assocs[0]._id self.clients.resource_registry.delete_association(association_id) # Delete the UserCredentials self.clients.resource_registry.delete(user_credentials_id) def create_user_info(self, actor_id="", user_info=None): # Ensure UserInfo association does not already exist objects, assocs = self.clients.resource_registry.find_objects(actor_id, PRED.hasInfo, RT.UserInfo) if objects: raise Conflict("UserInfo already exists for user id %s" % (actor_id)) # Create UserInfo object user_info_id, version = self.clients.resource_registry.create(user_info) # Create association with user identity object self.clients.resource_registry.create_association(actor_id, PRED.hasInfo, user_info_id) return user_info_id def update_user_info(self, user_info=None): # Overwrite UserInfo object self.clients.resource_registry.update(user_info) def read_user_info(self, user_info_id=''): # Read UserInfo object with _id matching passed user id user_info = self.clients.resource_registry.read(user_info_id) return user_info def delete_user_info(self, user_info_id='', actor_identity_id=''): # Read UserInfo user_info = self.clients.resource_registry.read(user_info_id) if not user_info: raise NotFound("UserInfo %s does not exist" % user_info_id) # Find and break association with ActorIdentity if not actor_identity_id: subjects, assocs = self.clients.resource_registry.find_subjects(RT.ActorIdentity, PRED.hasInfo, user_info_id) if not assocs: raise NotFound("ActorIdentity to UserInfo association for user info id %s does not exist" % user_info_id) actor_identity_id = subjects[0]._id assocs = self.clients.resource_registry.find_associations(actor_identity_id, PRED.hasInfo, user_info_id) if not assocs: raise NotFound("ActorIdentity to UserInfo association for user info id %s does not exist" % user_info_id) association_id = assocs[0]._id self.clients.resource_registry.delete_association(association_id) # Delete the UserInfo self.clients.resource_registry.delete(user_info_id) def find_user_info_by_email(self, user_email=''): #return self.clients.resource_registry.find_resources_ext(restype=RT.UserInfo, attr_name="contact.email", attr_value=user_email, id_only=False) user_infos, _ = self.clients.resource_registry.find_resources_ext(RT.UserInfo, attr_name="contact.email", attr_value=user_email) if len(user_infos) > 1: log.warn("More than one UserInfo found for email '%s': %s" % (user_email, [ui._id for ui in user_infos])) if user_infos: return user_infos[0] return None def find_user_info_by_id(self, actor_id=''): # Look up UserInfo via association with ActorIdentity objects, assocs = self.clients.resource_registry.find_objects(actor_id, PRED.hasInfo, RT.UserInfo) if not objects: raise NotFound("UserInfo for user id %s does not exist" % actor_id) user_info = objects[0] return user_info def find_user_info_by_name(self, name=''): objects, matches = self.clients.resource_registry.find_resources(RT.UserInfo, None, name, id_only=False) if not objects: raise NotFound("UserInfo with name %s does not exist" % name) if len(objects) > 1: raise Inconsistent("Multiple UserInfo objects with name %s exist" % name) return objects[0] def find_user_info_by_subject(self, subject=''): # Find UserCredentials objects, matches = self.clients.resource_registry.find_resources(RT.UserCredentials, None, subject, id_only=False) if not objects: raise NotFound("UserCredentials with subject %s does not exist" % subject) if len(objects) > 1: raise Inconsistent("Multiple UserCredentials with subject %s exist" % subject) user_credentials_id = objects[0]._id subjects, assocs = self.clients.resource_registry.find_subjects(RT.ActorIdentity, PRED.hasCredentials, user_credentials_id) if not subjects or len(subjects) == 0: raise NotFound("ActorIdentity to UserCredentials association for subject %s does not exist" % subject) if len(subjects) > 1: raise Inconsistent("Multiple ActorIdentity to UserCredentials associations for subject %s exist" % subject) actor_identity_id = subjects[0]._id # Look up UserInfo via association with ActorIdentity objects, assocs = self.clients.resource_registry.find_objects(actor_identity_id, PRED.hasInfo, RT.UserInfo) if not objects: raise NotFound("UserInfo for subject %s does not exist" % subject) if len(objects) > 1: raise Inconsistent("Multiple UserInfos for subject %s exist" % subject) user_info = objects[0] return user_info def signon(self, certificate='', ignore_date_range=False): log.debug("Signon with certificate:\n%s" % certificate) # Check the certificate is currently valid if not ignore_date_range: if not self.authentication.is_certificate_within_date_range(certificate): raise BadRequest("Certificate expired or not yet valid") # Extract subject line attributes = self.authentication.decode_certificate_string(certificate) subject = attributes["subject"] valid_until_str = attributes["not_valid_after"] log.debug("Signon request for subject %s with string valid_until %s" % (subject, valid_until_str)) valid_until_tuple = time.strptime(valid_until_str, "%b %d %H:%M:%S %Y %Z") valid_until = str(int(time.mktime(valid_until_tuple)) * 1000) # Look for matching UserCredentials object objects, assocs = self.clients.resource_registry.find_resources(RT.UserCredentials, None, subject, True) if len(objects) > 1: raise Conflict("More than one UserCredentials object was found for subject %s" % subject) if len(objects) == 1: log.debug("Signon known subject %s" % (subject)) # Known user, get ActorIdentity object user_credentials_id = objects[0] subjects, assocs = self.clients.resource_registry.find_subjects(RT.ActorIdentity, PRED.hasCredentials, user_credentials_id) if len(subjects) == 0: raise Conflict("ActorIdentity object with subject %s was previously created but is not associated with a ActorIdentity object" % subject) actor_id = subjects[0]._id # Find associated UserInfo registered = True try: self.find_user_info_by_id(actor_id) except NotFound: registered = False log.debug("Signon returning actor_id, valid_until, registered: %s, %s, %s" % (actor_id, valid_until, str(registered))) return actor_id, valid_until, registered else: log.debug("Signon new subject %s" % (subject)) # New user. Create ActorIdentity and UserCredentials actor_name = "Identity for %s" % subject actor_identity = IonObject("ActorIdentity", name=actor_name) actor_id = self.create_actor_identity(actor_identity) user_credentials = IonObject("UserCredentials", name=subject, description="Default credentials for %s" % subject) self.register_user_credentials(actor_id, user_credentials) log.debug("Signon returning actor_id, valid_until, registered: %s, %s, False" % (actor_id, valid_until)) return actor_id, valid_until, False def get_user_info_extension(self, user_info_id='', user_id=''): """Returns an UserInfoExtension object containing additional related information @param user_info_id str @retval user_info UserInfoExtension @throws BadRequest A parameter is missing @throws NotFound An object with the specified actor_id does not exist """ if not user_info_id: raise BadRequest("The user_info_id parameter is empty") extended_resource_handler = ExtendedResourceContainer(self) extended_user = extended_resource_handler.create_extended_resource_container( extended_resource_type=OT.UserInfoExtension, resource_id=user_info_id, user_id=user_id) #If the org_id is not provided then skip looking for Org related roles. if extended_user: #Did not setup a dependency to org_management service to avoid a potential circular bootstrap issue # since this method should never be called until the system is fully running try: org_client = OrgManagementServiceProcessClient(process=self) roles = org_client.find_all_roles_by_user(extended_user.actor_identity._id) extended_user.roles = list() for org_name in roles: for role in roles[org_name]: flattened_role = copy.copy(role.__dict__) del flattened_role['type_'] #Have to do this to appease the message validators for ION objects flattened_role['org_name'] = org_name #Nothing like forcing a value into the dict to appease the UI code extended_user.roles.append(flattened_role) except Exception, e: raise NotFound('Could not retrieve UserRoles for User Info id: %s - %s' % (user_info_id, e.message)) #set the notifications for this user # retrieve the set of open negotaions for this user #filer out the accepted/rejected negotiations extended_user.open_negotiations = [] extended_user.closed_negotiations = [] if hasattr(extended_user, 'actor_identity'): negotiations, _ = self.clients.resource_registry.find_objects(extended_user.actor_identity, PRED.hasNegotiation, RT.Negotiation, id_only=False) for negotiation in negotiations: if negotiation.negotiation_status == NegotiationStatusEnum.OPEN: extended_user.open_negotiations.append(negotiation) elif negotiation.negotiation_status == NegotiationStatusEnum.ACCEPTED or \ negotiation.negotiation_status == NegotiationStatusEnum.REJECTED: extended_user.closed_negotiations.append(negotiation) # replace list of lists with single list replacement_owned_resources = [] for inner_list in extended_user.owned_resources: if inner_list: for actual_data_product in inner_list: if actual_data_product: replacement_owned_resources.append(actual_data_product) extended_user.owned_resources = replacement_owned_resources return extended_user