曾与蒿藜同雨露,한때 잡초와 쑥과 함께 비와 이슬을 나누던 곳이 이제는 소나무와 삼나무와 함께 서리와 눈을 견뎌내고 있다.终随松柏到冰霜.かつては雑草やヨモギと共に雨や露を分かち合っていたが、今では松やヒノキと共に霜や雪に耐えている。曾与蒿藜同雨露,Once sharing rain and dew with weeds and wormwood, now enduring frost and snow with pines and cypresses.终随松柏到冰霜.曾与蒿藜同雨露한때 잡초와 쑥과 함께 비와 이슬을 나누던 곳이 이제는 소나무와 삼나무와 함께 서리와 눈을 견뎌내고 있다.,终随松柏到冰霜.譖セ荳手珍阯懷酔髮ィ髴イ�檎サ磯囂譚セ譟丞芦蜀ー髴�曾与蒿藜同雨露,鏇句笌钂胯棞鍚岄洦闇诧紝缁堥殢鏉炬煆鍒板啺闇�终随松柏到冰霜.曾与蒿藜同雨露,한때 잡초와 쑥과 함께 비와 이슬을 나누던 곳이 이제는 소나무와 삼나무와 함께 서리와 눈을 견뎌내고 있다.终随松柏到冰霜.曾与蒿藜同雨露,终随松柏到冰霜.
import os
import pwd
import grp
import re
import subprocess
import tempfile
from stat import S_IRUSR, S_IRGRP
class NoSuchUser(Exception):
def __init__(self, user):
message = 'No such user (%s)' % user
Exception.__init__(self, 'No such user (%s)' % (user,))
class NoSuchGroup(Exception):
def __init__(self, group):
message = 'No such group (%s)' % group
Exception.__init__(self, message)
class UnableToReadFile(Exception):
def __init__(self):
Exception.__init__(self, 'Cannot read sudoers file')
class UnableToWriteFile(Exception):
def __init__(self):
Exception.__init__(self, 'Cannot modify sudoers file')
ALIAS_LVECTL_CMDS = [ "/bin/ps", "/bin/grep", "/sbin/service", "/usr/bin/getcontrolpaneluserspackages",
"/usr/sbin/lvectl", "/usr/local/directadmin/plugins/new_lvemanager/admin/GetDomains" ]
ALIAS_SELECTOR_CMDS = [ "/usr/bin/cl-selector", "/usr/bin/piniset", "/usr/sbin/lveps", "/usr/bin/selectorctl" ]
DEFAULTS_REQUIRETTY = 'Defaults:%s !requiretty'
# Patterns for group
GROUP_LVECTL_SELECTOR = '%%%s ALL=NOPASSWD: LVECTL_CMDS, SELECTOR_CMDS'
GROUP_DEFAULTS_REQUIRETTY = 'Defaults:%%%s !requiretty'
class Clsudo(object):
"""
Adds CloudLinux users to sudoers file
"""
filepath = '/etc/sudoers'
temp_dir = '/etc'
temp_prefix = 'lve_sudoers_'
def add_user(user):
"""
Adds username to sudoers file
"""
Clsudo._check_user(user)
Clsudo._get_contents(user)
if not Clsudo.has_alias:
Clsudo.sudoers_list.append ( 'Cmnd_Alias LVECTL_CMDS = ' + ", ".join( ALIAS_LVECTL_CMDS ) )
if not Clsudo.has_selector_alias:
Clsudo.sudoers_list.append('Cmnd_Alias SELECTOR_CMDS = ' + ", ".join( ALIAS_SELECTOR_CMDS ))
if not Clsudo.has_rights:
Clsudo.sudoers_list.append('%s ALL=NOPASSWD: LVECTL_CMDS' % (user,))
if not Clsudo.has_selector_rights:
Clsudo.sudoers_list.append('%s ALL=NOPASSWD: SELECTOR_CMDS' % (user,))
if not Clsudo.has_action:
Clsudo.sudoers_list.append(DEFAULTS_REQUIRETTY % (user,))
Clsudo._write_contents()
add_user = staticmethod(add_user)
def add_cagefs_user(user):
"""
Adds username to sudoers file
"""
Clsudo._check_user(user)
Clsudo._get_contents(user)
if not Clsudo.has_cagefs_alias:
Clsudo.sudoers_list.append('Cmnd_Alias CAGEFS_CMDS = /usr/sbin/cagefsctl, '
'/bin/ps, /bin/grep, /sbin/service')
if not Clsudo.has_cagefs_rights:
Clsudo.sudoers_list.append('%s ALL=NOPASSWD: CAGEFS_CMDS' % (user,))
if not Clsudo.has_action:
Clsudo.sudoers_list.append(DEFAULTS_REQUIRETTY % (user,))
Clsudo._write_contents()
add_cagefs_user = staticmethod(add_cagefs_user)
def add_lvemanager_group(group_name):
"""
Adds group to sudoers file, grants access to LVE Manager
"""
Clsudo._check_group(group_name)
Clsudo._get_contents_group(group_name)
if not Clsudo.has_alias:
Clsudo.sudoers_list.append ( 'Cmnd_Alias LVECTL_CMDS = ' + ", ".join( ALIAS_LVECTL_CMDS ) )
if not Clsudo.has_selector_alias:
Clsudo.sudoers_list.append('Cmnd_Alias SELECTOR_CMDS = ' + ", ".join( ALIAS_SELECTOR_CMDS ))
if not Clsudo.has_action:
Clsudo.sudoers_list.append(GROUP_LVECTL_SELECTOR % (group_name,))
if not Clsudo.has_group_action:
Clsudo.sudoers_list.append(GROUP_DEFAULTS_REQUIRETTY % (group_name,))
# writes file
Clsudo._write_contents()
add_lvemanager_group = staticmethod(add_lvemanager_group)
def remove_user(user):
"""
Removes username from sudoers file
"""
try:
f = open(Clsudo.filepath)
Clsudo.sudoers_list = f.read().splitlines()
f.close()
idx = 0
removed = False
while idx < len(Clsudo.sudoers_list):
line = Clsudo.sudoers_list[idx]
if (('%s ALL=NOPASSWD:' % (user,)) in line) or ((DEFAULTS_REQUIRETTY % (user,))in line):
Clsudo.sudoers_list.remove(line)
removed = True
continue
idx += 1
if removed:
Clsudo._write_contents()
except (IOError, OSError):
raise UnableToReadFile()
remove_user = staticmethod(remove_user)
def update_user(user):
"""
updates username in sudoers file
"""
# Check user presence in system
Clsudo._check_user(user)
Clsudo._get_contents(user)
cmnd_dict = {"Cmnd_Alias LVECTL_CMDS":ALIAS_LVECTL_CMDS, "Cmnd_Alias SELECTOR_CMDS": ALIAS_SELECTOR_CMDS}
is_sudoer_change = 0
for idx in range(len(Clsudo.sudoers_list)):
comand_string = Clsudo.sudoers_list[idx]
for aliase_key, aliase_list in cmnd_dict.iteritems():
if aliase_key in comand_string:
comand_string = comand_string.replace(aliase_key,"").strip()
cmnd_list = comand_string.split(",")
for aliase_cmnd_item in aliase_list:
if aliase_cmnd_item not in cmnd_list:
is_sudoer_change = 1
Clsudo.sudoers_list[idx] = "%s = %s" % (aliase_key, ", ".join(aliase_list))
break
if(is_sudoer_change == 1):
Clsudo._write_contents()
update_user = staticmethod(update_user)
def _check_user(user):
"""
Checks passwd database for username presence
@param user: string
"""
try:
pwd.getpwnam(user)
except KeyError:
raise NoSuchUser(user)
_check_user = staticmethod(_check_user)
def _check_group(group_name):
"""
Checks grp database for group_name presence
@param group_name: string
"""
try:
grp.getgrnam(group_name)
except KeyError:
raise NoSuchGroup(group_name)
_check_group = staticmethod(_check_group)
def _get_contents(user):
"""
Reads file into list of strings
@param filename: string
"""
# Clear all status flags
Clsudo.has_action = False
Clsudo.has_group_action = False
Clsudo.has_alias = False
Clsudo.has_rights = False
Clsudo.has_selector_alias = False
Clsudo.has_selector_rights = False
Clsudo.has_cagefs_alias = False
Clsudo.has_cagefs_rights = False
require_tty_pattern = re.compile(r'Defaults:\s*%s\s*!requiretty' % user)
try:
i = open(Clsudo.filepath)
Clsudo.sudoers_list = i.read().splitlines()
i.close()
for idx in range(len(Clsudo.sudoers_list)):
if "Cmnd_Alias LVECTL_CMDS" in Clsudo.sudoers_list[idx]:
Clsudo.has_alias = True
continue
if "Cmnd_Alias CAGEFS_CMDS" in Clsudo.sudoers_list[idx]:
Clsudo.has_cagefs_alias = True
continue
if ("%s ALL=NOPASSWD: LVECTL_CMDS" % (user,)
in Clsudo.sudoers_list[idx]):
Clsudo.has_rights = True
continue
if "%s ALL=NOPASSWD: CAGEFS_CMDS" % (user,) in Clsudo.sudoers_list[idx]:
Clsudo.has_cagefs_rights = True
continue
if "requiretty" in Clsudo.sudoers_list[idx]:
pattern_match = require_tty_pattern.search(
Clsudo.sudoers_list[idx])
if pattern_match:
Clsudo.has_action = True
continue
if "Cmnd_Alias SELECTOR_CMDS" in Clsudo.sudoers_list[idx]:
if 'piniset' not in Clsudo.sudoers_list[idx]:
Clsudo.sudoers_list[idx] = Clsudo.sudoers_list[idx].replace(
'/usr/bin/cl-selector',
'/usr/bin/cl-selector, /usr/bin/piniset')
if 'lveps' not in Clsudo.sudoers_list[idx]:
Clsudo.sudoers_list[idx] = Clsudo.sudoers_list[idx].replace(
'/usr/bin/cl-selector, /usr/bin/piniset',
'/usr/bin/cl-selector, /usr/bin/piniset, /usr/sbin/lveps')
Clsudo.has_selector_alias = True
continue
if ("%s ALL=NOPASSWD: SELECTOR_CMDS" % (user,)
in Clsudo.sudoers_list[idx]):
Clsudo.has_selector_rights = True
continue
except (IOError, OSError):
raise UnableToReadFile()
_get_contents = staticmethod(_get_contents)
def _get_contents_group(group_name):
"""
Reads file into list of strings
@param group_name: string
"""
# Clear all status flags
Clsudo.has_action = False
Clsudo.has_group_action = False
Clsudo.has_alias = False
Clsudo.has_rights = False
Clsudo.has_selector_alias = False
Clsudo.has_selector_rights = False
Clsudo.has_cagefs_alias = False
Clsudo.has_cagefs_rights = False
group_prefix = "%%%s" % group_name
group_action = "Defaults:%%%s" % group_name
group_pattern = re.compile(r'%s\s*ALL=NOPASSWD:\s*LVECTL_CMDS,\s*SELECTOR_CMDS' % (group_name,))
try:
i = open(Clsudo.filepath)
Clsudo.sudoers_list = i.read().splitlines()
i.close()
for idx in range(len(Clsudo.sudoers_list)):
if "Cmnd_Alias SELECTOR_CMDS" in Clsudo.sudoers_list[idx]:
if 'piniset' not in Clsudo.sudoers_list[idx]:
Clsudo.sudoers_list[idx] = Clsudo.sudoers_list[idx].replace(
'/usr/bin/cl-selector',
'/usr/bin/cl-selector, /usr/bin/piniset')
if 'lveps' not in Clsudo.sudoers_list[idx]:
Clsudo.sudoers_list[idx] = Clsudo.sudoers_list[idx].replace(
'/usr/bin/cl-selector, /usr/bin/piniset',
'/usr/bin/cl-selector, /usr/bin/piniset, /usr/sbin/lveps')
Clsudo.has_selector_alias = True
continue
if "Cmnd_Alias LVECTL_CMDS" in Clsudo.sudoers_list[idx]:
Clsudo.has_alias = True
continue
if "Cmnd_Alias CAGEFS_CMDS" in Clsudo.sudoers_list[idx]:
Clsudo.has_cagefs_alias = True
continue
if Clsudo.sudoers_list[idx].startswith(group_prefix):
pattern_match = group_pattern.search(Clsudo.sudoers_list[idx])
if pattern_match:
Clsudo.has_action = True
if Clsudo.sudoers_list[idx].startswith(group_action):
Clsudo.has_group_action = True
if Clsudo.sudoers_list[idx].startswith(group_action):
Clsudo.has_group_action = True
except (IOError, OSError):
raise UnableToReadFile()
_get_contents_group = staticmethod(_get_contents_group)
def _write_contents():
"""
Writes data to temporary file then checks it and rewrites sudoers file
"""
try:
fd, temp_path = tempfile.mkstemp(
prefix=Clsudo.temp_prefix, dir=Clsudo.temp_dir)
fo = os.fdopen(fd, 'w')
fo.write('\n'.join(Clsudo.sudoers_list) + '\n')
fo.close()
mask = S_IRUSR | S_IRGRP
os.chmod(temp_path, mask)
if not Clsudo._is_file_valid(temp_path):
raise IOError
except (IOError, OSError):
try:
if os.path.exists(temp_path):
os.unlink(temp_path)
except:
pass
raise UnableToWriteFile()
try:
os.rename(temp_path, Clsudo.filepath)
except OSError:
raise UnableToWriteFile()
_write_contents = staticmethod(_write_contents)
def _is_file_valid(filename):
cmd = [
'/usr/sbin/visudo',
'-c',
'-f', filename
]
rv = subprocess.Popen(
cmd,
stdin=open('/dev/null'),
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
close_fds=True)
rt = rv.communicate()
if rv.returncode != 0:
return False
return True
_is_file_valid = staticmethod(_is_file_valid)