On 07/16/2014 05:32 AM, Royce Lv wrote:
On 2014年07月12日 03:08, Crístian Viana wrote:
> Currently, every user with sudo permissions can perform any operation on
> any virtual machine.
>
> In order to add more security, Kimchi will only allow users listed in
> the VM
> metadata - along with those with sudo permissions - to be able to
> perform
> actions on it. A VM may contain a list of system users and groups
> associated with it. If a user is not listed to access a VM, they will
> not be
> able to see it or to perform any operation on it.
>
> Signed-off-by: Crístian Viana <vianac(a)linux.vnet.ibm.com>
> ---
> src/kimchi/control/base.py | 4 +++
> src/kimchi/model/vms.py | 63
> ++++++++++++++++++++++++++++++++++++++++++++--
> 2 files changed, 65 insertions(+), 2 deletions(-)
>
> diff --git a/src/kimchi/control/base.py b/src/kimchi/control/base.py
> index f8a5210..6022472 100644
> --- a/src/kimchi/control/base.py
> +++ b/src/kimchi/control/base.py
> @@ -118,6 +118,10 @@ class Resource(object):
> @cherrypy.expose
> def index(self):
> + authorized = getattr(self.model, model_fn(self,
> 'is_authorized'), None)
> + if authorized is not None and not authorized(*self.model_args):
> + raise cherrypy.HTTPError(403)
> +
> method = validate_method(('GET', 'DELETE', 'PUT'))
> try:
> return {'GET': self.get,
> diff --git a/src/kimchi/model/vms.py b/src/kimchi/model/vms.py
> index 17bda04..00dcd0f 100644
> --- a/src/kimchi/model/vms.py
> +++ b/src/kimchi/model/vms.py
> @@ -19,16 +19,19 @@
> from lxml.builder import E
> import lxml.etree as ET
> +import grp
> import os
> import time
> import uuid
> from xml.etree import ElementTree
> +import cherrypy
> import libvirt
> from cherrypy.process.plugins import BackgroundTask
> from kimchi import vnc
> from kimchi import xmlutils
> +from kimchi.auth import USER_NAME, USER_SUDO
> from kimchi.config import READONLY_POOL_TYPE
> from kimchi.exception import InvalidOperation, InvalidParameter
> from kimchi.exception import NotFoundError, OperationFailed
> @@ -232,8 +235,8 @@ class VMsModel(object):
> @staticmethod
> def get_vms(conn):
> - conn = conn.get()
> - names = [dom.name().decode('utf-8') for dom in
> conn.listAllDomains(0)]
> + libvirtconn = conn.get()
> + names = [dom.name().decode('utf-8') for dom in
> libvirtconn.listAllDomains(0) if
> VMModel._vm_is_authorized(dom.name(), conn)]
Filtering resources here can work, while I suggest using filter
resources in controller to be more generic, cover all resources will
filter logic.
In model all resources report a 'users' information in its
data()--means the valid user to view this resource:
vm--{'users':["kimchi_user_1", "root"]}
In controller, base.py:
def filter_data():
user_name = cherrypy.session.get(USER_NAME, None)
data = []
for res in resources:
if all(key in res.data and res.data[key] == val and user_name
in data["user"]
for key, val in fields_filter.iteritems()):
data.append(res.data)
return data
Good suggestion, Royce!
It makes the logic simpler and easier to use
> return sorted(names, key=unicode.lower)
> @@ -526,6 +529,62 @@ class VMModel(object):
> kimchi_log.error('Error trying to delete vm screenshot
> from '
> 'database due error: %s', e.message)
> + @staticmethod
> + def _vm_get_access_users(name, conn):
> + dom = conn.get().lookupByName(name)
> + metadata = get_metadata_node(dom, 'access')
> + if metadata == '':
> + return []
> +
> + users_xml = ET.fromstring(metadata).find('user')
> + return [] if users_xml is None else [ users_xml.text ]
> +
> + @staticmethod
> + def _vm_get_access_groups(name, conn):
> + dom = conn.get().lookupByName(name)
> + metadata = get_metadata_node(dom, 'access')
> + if metadata == '':
> + return []
> +
> + groups_xml = ET.fromstring(metadata).find('group')
> + return [] if groups_xml is None else [ groups_xml.text ]
> +
> + @staticmethod
> + def _vm_is_authorized(name, conn):
> + try:
> + user_name = cherrypy.session.get(USER_NAME, None)
> + user_sudo = cherrypy.session.get(USER_SUDO, False)
> + except AttributeError:
> + return False
> +
> + if user_sudo:
> + return True
> +
> + dom = conn.get().lookupByName(name)
> + metadata = get_metadata_node(dom, 'access')
> +
> + if user_name is None or metadata == '':
> + return True
> +
> + users = VMModel._vm_get_access_users(name, conn)
> + groups = VMModel._vm_get_access_groups(name, conn)
> +
> + users_in_groups = set()
> + for vm_g in groups:
> + try:
> + for u in grp.getgrnam(vm_g).gr_mem:
> + users_in_groups.add(u)
> + except KeyError:
> + kimchi_log.warning("group '%s' is listed as
> authorized by VM '%s' but it doesn't exist"
> + % (vm_g, name))
> +
> + if user_name in users or user_name in users_in_groups:
> + return True
> +
> + return False
> +
> + def is_authorized(self, name):
> + return VMModel._vm_is_authorized(name, self.conn)
> class VMScreenshotModel(object):
> def __init__(self, **kargs):
_______________________________________________
Kimchi-devel mailing list
Kimchi-devel(a)ovirt.org
http://lists.ovirt.org/mailman/listinfo/kimchi-devel