[Kimchi-devel] [PATCH V6] add a method to fix search permissions
Sheldon
shaohef at linux.vnet.ibm.com
Wed Jan 8 15:17:17 UTC 2014
On 01/08/2014 11:08 PM, shaohef at linux.vnet.ibm.com wrote:
> From: ShaoHe Feng <shaohef at linux.vnet.ibm.com>
>
> First will use setfacl to set the path search permission for user or
> group, if failed then set search permission for others on the path.
>
> Usage:
> check_path_permission("/tmp/need/to/fix/path", username)
> fix_path_permission("/tmp/need/to/fix/path", username)
>
> Signed-off-by: ShaoHe Feng <shaohef at linux.vnet.ibm.com>
> Signed-off-by: Aline Manera <alinefm at linux.vnet.ibm.com>
> Signed-off-by: Royce Lv <lvroyce at linux.vnet.ibm.com>
> ---
> Makefile.am | 1 +
> src/kimchi/utils.py | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 122 insertions(+), 1 deletion(-)
>
> diff --git a/Makefile.am b/Makefile.am
> index 04ad696..1f80e5f 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -46,6 +46,7 @@ PEP8_WHITELIST = \
> src/kimchi/cachebust.py \
> src/kimchi/config.py.in \
> src/kimchi/control/*.py \
> + src/kimchi/utils.py \
> src/kimchi/disks.py \
> src/kimchi/distroloader.py \
> src/kimchi/exception.py \
> diff --git a/src/kimchi/utils.py b/src/kimchi/utils.py
> index af245c6..62a412d 100644
> --- a/src/kimchi/utils.py
> +++ b/src/kimchi/utils.py
> @@ -18,11 +18,16 @@
> #
> # You should have received a copy of the GNU Lesser General Public
> # License along with this library; if not, write to the Free Software
> -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> #
>
> import cherrypy
> +import grp
> import os
> +import pwd
> +import re
> +import stat +import subprocess
> import urllib2
>
>
> @@ -34,6 +39,7 @@ from kimchi import config
>
> kimchi_log = cherrypy.log.error_log
>
> +
> def is_digit(value):
> if isinstance(value, int):
> return True
> @@ -96,3 +102,117 @@ def check_url_path(path):
> return False
>
> return True
> +
> +
> +def run_command(cmd):
> + try:
> + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
> + stderr=subprocess.PIPE)
> + out, error = proc.communicate()
> +
> + kimchi_log.debug("Run command '%s'", " ".join(cmd))
> + if out or error:
> + kimchi_log.debug("out:\n %s\nerror:\n %s", out, error)
> + except OSError as e:
> + kimchi_log.error("Failed to run command %s. %s", " ".join(cmd),
> + e.message)
> + return (None, None, None)
> + if proc.returncode != 0:
> + kimchi_log.debug("Cmd '%s' failed, error code: %s", cmd, error)
> + return (out, error, proc.returncode)
> +
> +
> +def name_uid(user):
> + return pwd.getpwnam(user).pw_uid
> +
> +
> +def get_group_ids(user):
> + gids = [g.gr_gid for g in grp.getgrall() if user in g.gr_mem]
> + gid = pwd.getpwnam(user).pw_gid
> + gids.append(grp.getgrgid(gid).gr_gid)
> + return gids
> +
> +
> +def get_groups(user):
> + gids = get_group_ids(user)
> + return [grp.getgrgid(gid).gr_name for gid in gids]
> +
> +
> +def run_setfacl_set_x(path, user="qemu"):
> + set_user = ["setfacl", "--modify", "user:%s:x" % user, path]
> + out, error, ret = run_command(set_user)
> + return ret == 0
> +
> +
> +def run_getfacl(path, user="qemu", groups=[]):
> + cmd = ["getfacl", path]
> + out, error, ret = run_command(cmd)
> + if out and ret == 0:
> + res = re.findall("user:%s:..x" % user, out)
> + if res:
> + return True
> + res = re.findall("(?<=group:)(.*)(?=:..x)",
> + out) if groups else []
> + return list(set(res) & set(groups)) != []
> + return False
> +
> +
> +def set_x_on_path(path, who="other"):
> + S_IXWHO = ((stat.S_IXUSR if who == "user" else None) or
> + (stat.S_IXGRP if who == "group" else None) or
> + stat.S_IXOTH)
> + mode = os.stat(path).st_mode | S_IXWHO
> + os.chmod(path, mode)
> + ret = os.stat(path).st_mode == mode
> + if not ret:
> + kimchi_log.debug("faild to set +x attribute on %s", path)
> + return ret
> +
> +
> +def get_x_on_path(path, uid, gids=[]):
> + try:
> + st = os.stat(path)
> + mode = st.st_mode
> + return ((uid == st.st_uid and mode & stat.S_IXUSR == stat.S_IXUSR) or
> + (st.st_gid in gids and mode & stat.S_IXGRP == stat.S_IXGRP) or
> + mode & stat.S_IXOTH == stat.S_IXOTH)
> + except OSError as e:
> + kimchi_log.error("faild to get attribute on %s as user id: %s. %s",
> + path, uid, e.message)
> + return False
> +
> +
> +def check_path_permission(path, user='qemu', groups=[]):
> + groups = groups if groups else get_groups(user)
> + gids = [grp.getgrnam(group).gr_gid for group in groups] if groups else []
> + path = os.path.abspath(path)
> + paths = path.split("/")
> + paths = paths[1:]
> + path = "/"
> + for p in paths:
> + path = os.path.join(path, p)
> + if not (get_x_on_path(path, name_uid(user), gids) or
> + run_getfacl(path, user, groups)):
> + return False
> + return True
> +
some duplicate codes in check_path_permission and fix_path_permission
not sure a decorator is necessary as follow:
But just two function need decorator, seems not necessary.
+def path_permission(func):
+ def _wrapper(path, user, groups, *args, **argkw):
+ groups = groups if groups else get_groups(user)
+ gids = [grp.getgrnam(group).gr_gid
+ for group in groups] if groups else []
+ uid = name_uid(user)
+ path = os.path.abspath(path)
+ paths = path.split("/")
+ paths = paths[1:]
+ path = "/"
+ for p in paths:
+ path = os.path.join(path, p)
+ if not func(path, user, groups, uid, gids):
+ return False
+ return True
+ return _wrapper
+
+
+ at path_permission
+def check_path_permission(path, user='qemu', groups=[], uid=None, gids=[]):
+ return (get_x_on_path(path, uid, gids) or
+ run_getfacl(path, user, groups))
+
+
+ at path_permission
+def fix_path_permission(path, user='qemu', groups=[], uid=None, gids=[]):
+ st = os.stat(path)
+ uid = name_uid(user)
+ who = 'user' if st.st_uid == uid else None
+ who = 'group' if not who and st.st_gid in gids else 'other'
+ return (get_x_on_path(path, uid, gids) or
+ run_getfacl(path, user, groups) or
+ run_setfacl_set_x(path, user) or
+ set_x_on_path(path, who))
> +
> +def fix_path_permission(path, user='qemu', groups=[]):
> + groups = groups if groups else get_groups(user)
> + gids = [grp.getgrnam(group).gr_gid for group in groups] if groups else []
> + path = os.path.abspath(path)
> + paths = path.split("/")
> + paths = paths[1:]
> + path = "/"
> + for p in paths:
> + path = os.path.join(path, p)
> + st = os.stat(path)
> + uid = name_uid(user)
> + who = 'user' if st.st_uid == uid else None
> + who = 'group' if not who and st.st_gid in gids else 'other'
> + if not (get_x_on_path(path, uid, gids) or
> + run_getfacl(path, user, groups) or
> + run_setfacl_set_x(path, user) or
> + set_x_on_path(path, who)):
> + return False
> + return True
--
Thanks and best regards!
Sheldon Feng(冯少合)<shaohef at linux.vnet.ibm.com>
IBM Linux Technology Center
More information about the Kimchi-devel
mailing list