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
예제 #6
0
    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")
 def on_init(self):
     self.authentication = Authentication()
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
예제 #9
0
    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='', 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