Beispiel #1
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))
Beispiel #2
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)
Beispiel #3
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})
Beispiel #4
0
def check_duplicate_username(form, field):    
    username = field.data
    existing = resource = None
    if hasattr(form, 'resource_id'):
        # It's being added
        resource = resources.get(form.resource_id.data)
        existing = resource.passwords.filter_by(username=username).first()
    elif hasattr(form, 'password_id'):
        # Lookup from pw_id
        pw = passwords.get(form.password_id.data)
        resource = pw.resource
        q = resource.passwords.filter_by(username=username)
        q = q.filter(Password.id != pw.id) # @UndefinedVariable
        existing = q.first()
    else:
        raise Exception("Unexpected condition.")
    
    if existing:
        raise ValidationError("Username \"{0}\" already exists for this resource \"{1}\".".format(username, resource.name))
Beispiel #5
0
 def delete(self, resource_id, redirect_to=None):
     resource = resources.get(resource_id)
     if cherrypy.request.method == 'POST':
         
         # First remove any passwords for this resource.
         for pw in resource.passwords:
             del_pw = passwords.delete(pw.id)
             auditlog.log(auditlog.CODE_CONTENT_DEL, target=del_pw)
     
         # Then remove the actual resource
         resource = resources.delete(resource_id)
         auditlog.log(auditlog.CODE_CONTENT_DEL, target=resource)
         notify_entity_activity(resource, 'deleted')
         if redirect_to:
             raise cherrypy.HTTPRedirect(redirect_to)
         else:
             raise cherrypy.HTTPRedirect('/resource/list')
     else:
         return render('resource/delete.html', {'resource': resource,
                                                'redirect_to': redirect_to})
Beispiel #6
0
 def from_structure(self, structure):
     """
     Populates the SQLAlchemy model from a python dictionary of the database structure.
     """
     session = meta.Session()
     
     try:
         for resource_s in structure['resources']:
             log.debug("Importing: {0!r}".format(resource_s))
             
             # First build up a list of group_ids for this resource that will correspond to groups
             # in *this* database.
             group_ids = []
             for gname in resource_s['groups']:
                 group = groups.get_by_name(gname, assert_exists=False)
                 if not group:
                     group = groups.create(gname)
                     log.info("Created group: {0!r}".format(group))
                 else:
                     log.info("Found existing group: {0!r}".format(group))
                     
                 group_ids.append(group.id)
             
             # First we should see if there is a match for the id and name; we can't rely on name alone since
             # there is no guarantee of name uniqueness (even with a group)
             resource = None
             resource_candidate = resources.get(resource_s['id'], assert_exists=False)
             if resource_candidate and resource_candidate.name == resource_s['name']:
                 resource = resource_candidate 
             else:
                 # If we find a matching resource (by name) and there is only one then we'll use that.
                 try:
                     resource = resources.get_by_name(resource_s['name'], assert_single=True, assert_exists=True)
                 except MultipleResultsFound:
                     log.info("Multiple resource matched name {0!r}, will create a new one.".format(resource_s['name']))
                 except exc.NoSuchEntity:
                     log.debug("No resource found matching name: {0!r}".format(resource_s['name']))
                     pass
                 
             resource_attribs = ('name', 'addr', 'description', 'notes', 'tags')
             resource_attribs_update = dict([(k,v) for (k,v) in resource_s.items() if k in resource_attribs])
             
             if resource:
                 (resource, modified) = resources.modify(resource.id, group_ids=group_ids, **resource_attribs_update)
                 # (yes, we are overwriting 'resource' var with new copy returned from this method)
                 log.info("Updating existing resource: {0!r} (modified: {1!r})".format(resource, modified))
                 if modified and modified != ['group_ids']:
                     if not self.force:
                         raise RuntimeError("Refusing to modify existing resource attributes {0!r} on {1!r} (use 'force' to override this).".format(modified, resource))
                     else:
                         log.warning("Overwriting resource attributes {0!r} on {1!r}".format(modified, resource))
             else:
                 # We will just assume that we need to create the resource.  Yes, it's possible it'll match an existing
                 # one, but better to build a merge tool than end up silently merging things that are not the same.
                 resource = resources.create(group_ids=group_ids, **resource_attribs_update)
                 log.info("Created new resource: {0!r}".format(resource))
             
             # Add the passwords
             for password_s in resource_s['passwords']:
                 
                 password_attribs = ('username', 'description', 'password', 'tags')
                 password_attribs_update = dict([(k,v) for (k,v) in password_s.items() if k in password_attribs])
             
                 # Look for a matching password.  We do know that this is unique.
                 password = passwords.get_for_resource(password_s['username'], password_s['resource_id'], assert_exists=False)
                 if password:
                     (password, modified) = passwords.modify(password_id=password.id, **password_attribs_update)
                     # (Yeah, we overwrite password object.)
                     log.info("Updating existing password: {0!r} (modified: {1!r})".format(password, modified))
                     
                     non_pw_modified = set(modified) - set(['password'])
                     if not modified:
                         log.debug("Password row not modified.")
                     else:
                         log.debug("Password modified: {0!r}".format(modified))
                      
                     # If anything changed other than password, we need to ensure that force=true
                     if non_pw_modified:
                         if not self.force:
                             raise RuntimeError("Refusing to modify existing password attributes {0!r} on {1!r} (use 'force' to override this).".format(non_pw_modified, password))
                         else:
                             log.warning("Overwriting password attributes {0!r} on {1!r}".format(non_pw_modified, password))
                 else:
                     password = passwords.create(resource_id=resource.id, **password_attribs_update)
                     log.info("Creating new password: {0!r}".format(password))
             
             
             # This probably isn't necessary as all the DAO methods should also flush session, but might as well.
             session.flush()
             
     except:
         session.rollback()
         raise
Beispiel #7
0
 def edit(self, resource_id):
     resource = resources.get(resource_id)
     log.debug("Resource matched: {0!r}".format(resource))
     form = ResourceEditForm(request_params(), obj=resource, resource_id=resource_id, group_ids=[g.id for g in resource.groups])
     form.group_ids.choices = [(g.id, g.label) for g in groups.list()]
     return render('resource/edit.html', {'form': form})