Example #1
0
 def view(self, access_id):
     level = access.get(access_id)
     auditlog.log(auditlog.CODE_CONTENT_VIEW, target=level)
     level_includes = lambda have, want: (have & want) != 0 # This is needed because jinja is whining about the '&' in the conditional
     return render('access/view.html', {'level': level,
                                        'level_includes': level_includes,
                                        'acl_labels': acl.ACCESS_LEVEL_LABELS})
Example #2
0
 def getPasswordForResource(self, username, resource_id, include_history=False):
     """
     Looks up a password matching specified username @ specified resource name (e.g. hostname).
     
     :param username: The username associated with the password.
     :type username: str
     :param resource_id: The resource ID or name that we are looking up.
     :type resource_id: int or str
     :param include_history: Whether to include history (previous passwords) for this password.
     :type include_history: bool
     :return: The matching password, or None if none found.
     """
     try:
         try:
             resource_id = int(resource_id)
         except ValueError:
             resource = resources.get_by_name(resource_id, assert_single=True)
         else:
             resource = resources.get(resource_id)
         pw = passwords.get_for_resource(username=username, resource_id=resource.id, assert_exists=True)
         auditlog.log(auditlog.CODE_CONTENT_VIEW, target=pw)
         return pw.to_dict(decrypt=True, include_history=include_history)
     except exc.NoSuchEntity:
         log.info("Unable to find password matching user@resource: {0}@{1}".format(username, resource_id))
         raise
     except:
         log.exception("Unable to find password for resource.")
         raise RuntimeError("Unhandled error trying to lookup password for user@resource: {0}@{1}".format(username, resource_id))
Example #3
0
 def checkpassword(realm, username, password):
     auth_providers = get_configured_providers()
     try:
         for auth_provider in auth_providers:
             try:
                 auth_provider.authenticate(username, password)
             except exc.InsufficientPrivileges:
                 # Fail fast in this case; we don't want to continue on to try other authenticators.
                 raise _LoginFailed()
             except exc.AuthError:
                 # Swallow other auth errors so it goes onto next authenticator in the list.
                 pass
             except:
                 # Other exceptions needs to get logged at least.
                 log.exception("Unexpected error authenticating user using {0!r}".format(auth_provider))
             else:
                 log.info("Authentication succeeded for username {0} using provider {1}".format(username, auth_provider))
                 break
         else:
             log.debug("Authenticators exhausted; login failed.")
             raise _LoginFailed()
     except _LoginFailed:
         auditlog.log(auditlog.CODE_AUTH_FAILED, comment=username)
         return False
     else:
         # Resolve the user using the *current value* for auth_provider (as that is the one that passed the auth.
         user = auth_provider.resolve_user(username)
         
         log.debug("Setting up cherrypy session with username={0}, user_id={1}".format(username, user.id))    
         cherrypy.session['username'] = username # @UndefinedVariable
         cherrypy.session['user_id'] = user.id # @UndefinedVariable
         
         auditlog.log(auditlog.CODE_AUTH_LOGIN)
         return True
Example #4
0
 def process_add(self, **kwargs): # We don't specify the args explicitly since we are using wtforms here.
     form = GroupAddForm(request_params())
     if form.validate():
         group = groups.create(name=form.name.data)
         auditlog.log(auditlog.CODE_CONTENT_ADD, target=group)
         notify_entity_activity(group, 'created')
         raise cherrypy.HTTPRedirect('/group/list')
     else:
         return render("group/add.html", {'form': form})
Example #5
0
 def getResource(self, resource_id):
     try:
         resource_id = int(resource_id)
     except ValueError:
         resource = resources.get_by_name(resource_id, assert_single=True)
     else:
         resource = resources.get(resource_id)
     auditlog.log(auditlog.CODE_CONTENT_VIEW, target=resource)
     return resource.to_dict(decrypt=True, include_passwords=True)
Example #6
0
 def getGroup(self, group_id):
     try:
         group_id = int(group_id)
     except ValueError:
         group = groups.get_by_name(group_id)
     else:
         group = groups.get(group_id)
     auditlog.log(auditlog.CODE_CONTENT_VIEW, target=group)
     return group.to_dict(include_resources=True)
Example #7
0
    def process_login(self, **kwargs):
        form = LoginForm(request_params())

        # TODO: Refactor to combine with the ensconce.server:checkpassword method.  Lots of duplicate
        # logic here.  AT MINIMUM MAKE SURE THAT ANY CHANGES HERE ARE REFLECTED THERE
        
        # This is a "flow-control" exception. ... You'll see. :)        
        class _LoginFailed(Exception):
            pass
        
        try:
            if not form.validate():
                raise _LoginFailed()
        
            username = form.username.data
            password = form.password.data
            
            for auth_provider in get_configured_providers():
                try:
                    auth_provider.authenticate(username, password)
                except exc.InsufficientPrivileges:
                    form.username.errors.append(ValidationError("Insufficient privileges to log in."))
                    # Fail fast in this case; we don't want to continue on to try other authenticators.
                    raise _LoginFailed()
                except exc.AuthError:
                    # Swallow other auth errors so it goes onto next authenticator in the list.
                    pass
                except:
                    # Other exceptions needs to get logged at least.
                    log.exception("Unexpected error authenticating user using {0!r}".format(auth_provider))
                else:
                    log.info("Authentication succeeded for username {0} using provider {1}".format(username, auth_provider))
                    break
            else:
                log.debug("Authenticators exhausted; login failed.")
                form.password.errors.append(ValidationError("Invalid username/password."))
                raise _LoginFailed()
            
        except _LoginFailed:
            auditlog.log(auditlog.CODE_AUTH_FAILED, comment=username)
            return render("login.html", {'auth_provider': config['auth.provider'], 'form': form})
        else:
            
            # Resolve the user using the *current value* for auth_provider (as that is the one that passed the auth.
            user = auth_provider.resolve_user(username)
            
            log.debug("Setting up cherrypy session with username={0}, user_id={1}".format(username, user.id))    
            cherrypy.session['username'] = username # @UndefinedVariable
            cherrypy.session['user_id'] = user.id # @UndefinedVariable
            
            auditlog.log(auditlog.CODE_AUTH_LOGIN)
            
            if form.redirect.data:
                raise cherrypy.HTTPRedirect(form.redirect.data)
            else:
                raise cherrypy.HTTPRedirect("/")
Example #8
0
 def view(self, group_id):
     try:
         group_id = int(group_id)
     except ValueError:
         group = groups.get_by_name(group_id)
     else:
         group = groups.get(group_id)
         
     auditlog.log(auditlog.CODE_CONTENT_VIEW, target=group)
     return render("group/view.html", {'group': group})
Example #9
0
 def view(self, resource_id):
     try:
         resource_id = int(resource_id)
     except ValueError:
         resource = resources.get_by_name(resource_id, assert_single=True)
     else:
         resource = resources.get(resource_id)
     
     auditlog.log(auditlog.CODE_CONTENT_VIEW, target=resource)
     return render('resource/view.html', {'resource': resource})
Example #10
0
 def getPassword(self, password_id, include_history=False):
     """
     Get the specified password record (decrypted) and optionally password history.
     
     :param password_id: The ID of password to lookup.
     :type password_id: int
     :param include_history: Whether to include history (previous passwords) for this password.
     :type include_history: bool
     """
     pw = passwords.get(password_id)
     auditlog.log(auditlog.CODE_CONTENT_VIEW, target=pw)
     return pw.to_dict(decrypt=True, include_history=include_history)
Example #11
0
 def deleteResource(self, resource_id):
     """
     Delete a resource (resource must be empty or error will be thrown).
     
     :param resource_id: The numeric ID of resource (cannot use resource name here).
     :type resource_id: int
     :return: The deleted resource object.
     :rtype: dict
     """
     r = resources.delete(resource_id)
     auditlog.log(auditlog.CODE_CONTENT_DEL, target=r)
     return r.to_dict(decrypt=False)
Example #12
0
 def process_add(self, **kwargs):
     form = OperatorAddForm(request_params())
     form.access_id.choices = [(l.id, l.description) for l in access.list()]
     if form.validate():
         operator = operators.create(username=form.username.data,
                                     password=form.password.data,
                                     access_id=form.access_id.data)
         auditlog.log(auditlog.CODE_CONTENT_ADD, target=operator)
         notify_entity_activity(operator, 'created')
         raise cherrypy.HTTPRedirect('/user/list')
     else:
         return render('user/add.html', {'form': form })
Example #13
0
 def reveal(self, password_id, _=None):
     """
     (AJAX) Returns the specified password.  (This is a separate action for the purposes of auditing.)
     
     (jquery will pass an additional _ arg for no-caching purposes.)
     """
     pw = passwords.get(password_id)
     if not pw:
         raise ValueError("Invalid password specified: {0}".format(password_id))
     
     auditlog.log(auditlog.CODE_CONTENT_VIEW, target=pw)
     return pw.password_decrypted
Example #14
0
 def deletePassword(self, password_id):
     """
     Delete a password (and all password history).
     
     :param password_id: The numeric ID of password.
     :type password_id: int
     :return: The deleted password object.
     :rtype: dict
     """
     pw = passwords.delete(password_id)
     auditlog.log(auditlog.CODE_CONTENT_DEL, target=pw)
     return pw.to_dict(decrypt=False)
Example #15
0
 def createGroup(self, name):
     """
     Create a new group with specified name.
     
     :param name: The new group name.
     :type name: str
     
     :return: The created group object.
     :rtype: dict
     """
     group = groups.create(name)
     auditlog.log(auditlog.CODE_CONTENT_ADD, target=group)
     return group.to_dict()
Example #16
0
 def process_add(self, **kwargs):
     form = PasswordAddForm(request_params())
     if form.validate():
         pw = passwords.create(username=form.username.data,
                               resource_id=form.resource_id.data,
                               password=form.password_decrypted.data,
                               description=form.description.data,
                               tags=form.tags.data)
         auditlog.log(auditlog.CODE_CONTENT_ADD, target=pw)
         notify_entity_activity(pw, 'created')
         raise cherrypy.HTTPRedirect('/resource/view/%d' % pw.resource_id)
     else:
         return render('password/add.html', {'form': form})
Example #17
0
 def process_edit(self, **kwargs):
     """
     Updates a group (changes name).
     """
     form = GroupEditForm(request_params())
     if form.validate():
         (group, modified) = groups.modify(form.group_id.data, name=form.name.data)
     
         auditlog.log(auditlog.CODE_CONTENT_MOD, target=group, attributes_modified=modified)
         notify_entity_activity(group, 'updated')
         raise cherrypy.HTTPRedirect('/group/list')
     else:
         return render('group/edit.html', {'form': form})
Example #18
0
 def deleteGroup(self, group_id):
     """
     Delete a group (group must be empty or error will be thrown).
     
     :param group_id: The numeric ID of group (cannot use group name here).
     :type group_id: int
     :return: The deleted group object.
     :rtype: dict
     """
     g = groups.delete(group_id)
     auditlog.log(auditlog.CODE_CONTENT_DEL, target=g)
     return g.to_dict()
     
Example #19
0
 def process_add(self, **kwargs):
     form = AccessAddForm(request_params())
     if form.validate():
         level_mask = 0
         for i in form.levels.data:
             level_mask |= int(i)
 
         level = access.create(level_mask, form.description.data)
         auditlog.log(auditlog.CODE_CONTENT_ADD, target=level)
         notify_entity_activity(level, 'created')
         raise cherrypy.HTTPRedirect('/access/list')
     else:
         return render('access/add.html', {'form': form})
Example #20
0
 def process_merge(self, **kwargs):
     form = MergeForm(request_params())
     group_tuples = [(g.id, g.name) for g in groups.list()]
     form.from_group_id.choices = [(0, '[From Group]')] + group_tuples
     form.to_group_id.choices = [(0, '[To Group]')] + group_tuples
     if form.validate():
         log.info("Passed validation, somehow.")
         (moved_resources, from_group, to_group) = groups.merge(form.from_group_id.data, form.to_group_id.data)
         for r in moved_resources:
             auditlog.log(auditlog.CODE_CONTENT_MOD, target=r, attributes_modified=['group_id'])
         auditlog.log(auditlog.CODE_CONTENT_DEL, target=from_group)
         raise cherrypy.HTTPRedirect('/group/view/{0}'.format(to_group.id))
     else:
         return render("group/merge.html", {'form': form})
Example #21
0
 def tagsearch(self, tags):
     """
     Perform a search for specified tags (only).
     
     :param tags: A list of tags to search for (and).
     :type tags: list
     :returns: A dict like {'resources': [r1,r2,...], 'passwords': [p1,p2,...]}
     :rtype: dict
     """
     results = search.tagsearch(tags)
     auditlog.log(auditlog.CODE_SEARCH, comment=repr(tags))
     return {
         'resources':    [r.to_dict(decrypt=False) for r in results.resource_matches],
         'passwords':    [r.to_dict(decrypt=False) for r in results.password_matches],
     }
Example #22
0
 def process_add(self, **kwargs):
     form = ResourceAddForm(request_params())
     form.group_ids.choices = [(g.id, g.label) for g in groups.list()]
     if form.validate():
         resource = resources.create(name=form.name.data,
                                     group_ids=form.group_ids.data,
                                     addr=form.addr.data,
                                     description=form.description.data, 
                                     notes=form.notes_decrypted.data,
                                     tags=form.tags.data) # XXX: process
         auditlog.log(auditlog.CODE_CONTENT_ADD, target=resource)
         notify_entity_activity(resource, 'created')
         raise cherrypy.HTTPRedirect('/resource/view/{0}'.format(resource.id))
     else:
         return render('resource/add.html', {'form': form })
Example #23
0
 def process_edit(self, **kwargs):
     form = PasswordEditForm(request_params())
     if form.validate():
         (pw, modified) = passwords.modify(form.password_id.data, 
                                           username=form.username.data, 
                                           password=form.password_decrypted.data, 
                                           description=form.description.data,
                                           tags=form.tags.data)
 
         auditlog.log(auditlog.CODE_CONTENT_MOD, target=pw,
                      attributes_modified=modified)
         notify_entity_activity(pw, 'updated')
         raise cherrypy.HTTPRedirect('/resource/view/{0}'.format(pw.resource_id))
     else:
         log.warning("Form failed validation: {0}".format(form.errors))
         return render('password/edit.html', {'form': form})
Example #24
0
    def modifyGroup(self, group_id, name):
        """
        Modify (rename) a group.

        :param group_id: The ID of group to modify.
        :type group_id: int
        
        :keyword name: The new name of the group.
        :type name: str
        
        :return: The updated group object.
        :rtype: dict
        """
        (group, modified) = groups.modify(group_id, name=name)
        auditlog.log(auditlog.CODE_CONTENT_MOD, target=group, attributes_modified=modified)
        return group.to_dict()
Example #25
0
 def search(self, searchstr):
     """
     Perform a search for specified search string.
     
     :param searchstr: A string to match (exactly).
     :type searchstr: str
     :returns: A dict like {'resources': [r1,r2,...], 'groups': [g1,g2,...], 'passwords': [p1,p2,...]}
     :rtype: dict
     """
     results = search.search(searchstr)
     auditlog.log(auditlog.CODE_SEARCH, comment=searchstr)
     return {
         'resources':    [r.to_dict(decrypt=False) for r in results.resource_matches],
         'groups':       [r.to_dict() for r in results.group_matches],
         'passwords':    [r.to_dict(decrypt=False) for r in results.password_matches],
     }
Example #26
0
 def process_edit(self, **kwargs):
     form = ResourceEditForm(request_params())
     form.group_ids.choices = [(g.id, g.label) for g in groups.list()]
     if form.validate():
         (resource, modified) = resources.modify(form.resource_id.data,
                                                 name=form.name.data,
                                                 addr=form.addr.data,
                                                 group_ids=form.group_ids.data,
                                                 notes=form.notes_decrypted.data,
                                                 description=form.description.data,
                                                 tags=form.tags.data) # XXX: process
         auditlog.log(auditlog.CODE_CONTENT_MOD, target=resource, attributes_modified=modified)
         notify_entity_activity(resource, 'updated')
         raise cherrypy.HTTPRedirect('/resource/view/{0}'.format(resource.id))
     else:
         log.warning("Form validation failed.")
         log.warning(form.errors)
         return render('resource/edit.html', {'form': form})
Example #27
0
 def process_edit(self, **kwargs):
     log.debug("params = %r" % request_params())
     form = OperatorEditForm(request_params())
     form.access_id.choices = [(l.id, l.description) for l in access.list()]
     if form.validate():
         params = dict(operator_id=form.operator_id.data,
                       username=form.username.data,
                       access_id=form.access_id.data)
         
         # If password is blank, let's just not change it.
         if form.password.data:
             params['password'] = form.password.data
             
         (operator, modified) = operators.modify(**params)
         auditlog.log(auditlog.CODE_CONTENT_MOD, target=operator, attributes_modified=modified)
         notify_entity_activity(operator, 'updated')
         raise cherrypy.HTTPRedirect('/user/list')
     else:
         return render('user/edit.html', {'form': form, 'externally_managed': operator.externally_managed})
Example #28
0
 def createResource(self, group_ids, name, addr=None, description=None, notes=None):
     """
     Creates a new resource, adding to specified groups.
     
     :param group_ids: The group IDs associated with this password.
     :type group_ids: list
     
     :keyword name:
     :keyword addr:
     :keyword description:
     :keyword notes: The notes field (will be encrypted).
     
     :return: The created resource object.
     :rtype: dict
     """
     resource = resources.create(name=name, group_ids=group_ids, addr=addr,
                                 description=description, notes=notes)
     auditlog.log(auditlog.CODE_CONTENT_ADD, target=resource)
     return resource.to_dict()
Example #29
0
 def createPassword(self, resource_id, username, password, description=None, expire_months=None):
     """
     Creates a new password for specified resource.
     
     :param resource_id: The resource with which to associate this password.
     :type resource_id: int
     
     :keyword: username:
     :keyword: password:
     :keyword: description:
     :keyword: expire_months:
     
     :return: The created password object.
     :rtype: dict    
     """
     pw = passwords.create(username, resource_id=resource_id, description=description, 
                           password=password, expire_months=expire_months)
     auditlog.log(auditlog.CODE_CONTENT_ADD, target=pw)
     return pw.to_dict()
Example #30
0
 def modifyPassword(self, password_id, **kwargs):
     """
     Modify an existing password.
     
     This method requires keyword arguments and so only works with JSON-RPC2 protocol.
     
     :param password_id: The ID of the password to modify.
     :type password_id: int
     
     :keyword username:
     :keyword password:
     :keyword description:
     
     :return: The modified password object.
     :rtype: dict
     """
     (pw, modified) = passwords.modify(password_id, **kwargs)
     auditlog.log(auditlog.CODE_CONTENT_MOD, target=pw, attributes_modified=modified)
     return pw.to_dict()