Skip to content
Snippets Groups Projects
Commit c2a59a7c authored by Sven Mäder's avatar Sven Mäder :speech_balloon:
Browse files

Remove dev versions of xymon home permissions check

parent 63961535
No related branches found
No related tags found
No related merge requests found
#!/usr/bin/env python3
import os
import sys
import pwd
import grp
import stat
import posix1e
import lib_path
import lib
import dphysldap
home_dirs = 0
users = {}
nis_homes = {}
nis_shares = {}
owner = []
permission = []
acl = []
bad_home_directory = []
no_ldap_user = []
bad_nis_map = []
no_nis_map = []
no_blocked = []
not_closed = []
not_open = []
class Home(object):
"""
Holds info about a home directory
"""
def __init__(self, name, path, st):
self.name = name
self.path = path
self.st = st
@property
def uid(self):
return self.st.st_uid
@property
def gid(self):
return self.st.st_gid
@property
def uname(self):
return pwd.getpwuid(self.uid).pw_name
@property
def gname(self):
return grp.getgrgid(self.gid).gr_name
@property
def filemode(self):
return stat.filemode(self.st.st_mode)
@property
def permission(self):
return ' '.join([self.filemode, self.path])
def __str__(self):
return ' '.join([self.filemode, self.uname, self.gname, self.path])
def search_ldap():
ldap = dphysldap.Ldap()
people = 'ou=people,dc=phys,dc=ethz,dc=ch'
auto_home = 'nisMapName=auto.home,ou=automount,dc=phys,dc=ethz,dc=ch'
ldap.search('(objectClass=posixAccount)', search_base=people, attributes=['uid', 'blocked', 'homeDirectory'])
ldap_users = ldap.response
for user in ldap_users:
uid = user['attributes']['uid'][0]
blocked = user['attributes']['blocked']
home_dir = user['attributes']['homeDirectory']
user_attrs = {}
user_attrs['homeDirectory'] = home_dir
if blocked:
user_attrs['blocked'] = blocked
else:
no_blocked.append(uid)
user_attrs['blocked'] = 'no'
users[uid] = user_attrs
ldap.search('(&(objectClass=nisObject)(cn=*)(nisMapEntry=phd-home*))',
search_base=auto_home, attributes=['cn', 'nisMapEntry'])
entries = ldap.response
for entry in entries:
cn = entry['attributes']['cn'][0]
nis_map = entry['attributes']['nisMapEntry']
nis_homes[cn] = nis_map
ldap.search('(&(objectClass=nisObject)(cn=*)(!(nisMapEntry=phd-home*)))',
search_base=auto_home, attributes=['cn', 'nisMapEntry'])
entries = ldap.response
for entry in entries:
cn = entry['attributes']['cn'][0]
nis_map = entry['attributes']['nisMapEntry']
nis_shares[cn] = nis_map
def check_homes(top):
global home_dirs
if not os.path.isdir(top):
return
for f in os.listdir(top):
pathname = os.path.join(top, f)
if not os.path.isdir(pathname):
continue
st = os.stat(pathname)
home = Home(f, pathname, st)
home_dirs += 1
if bad_owner(home):
owner.append(home)
if bad_permission(home):
permission.append(home)
if posix1e.has_extended(home.path):
acl.append(home)
if home.name in users:
if users[home.name]['homeDirectory'][6:] != home.name:
bad_home_directory.append(': '.join([home.name, users[home.name]['homeDirectory']]))
if users[home.name]['blocked'] == 'yes':
if home.st.st_mode & stat.S_IRWXU:
not_closed.append(home)
else:
if home.st.st_mode & stat.S_IRWXU != stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR:
not_open.append(home)
del users[home.name]
else:
no_ldap_user.append(home)
if home.name in nis_homes:
if nis_homes[home.name].split(':', maxsplit=1)[1] != home.path:
bad_nis_map.append(': '.join([home.name, nis_homes[home.name]]))
del nis_homes[home.name]
else:
no_nis_map.append(home)
def check_shares():
for user in list(users.keys()):
if user in nis_shares:
del nis_shares[user]
del users[user]
def bad_owner(home):
if home.name == home.uname and home.name == home.gname:
return False
return True
def bad_permission(home):
# d---------
if home.st.st_mode == stat.S_IFDIR:
return False
# drwx------
elif home.st.st_mode == stat.S_IFDIR | stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR:
return False
return True
def list_homes(homes):
for home in homes:
print(home)
if __name__ == '__main__':
arg_count = len(sys.argv) - 1
search_ldap()
print('statistics')
print('----------')
print('ldap users: ' + str(len(users)))
print('ldap nismaps (home): ' + str(len(nis_homes)))
print('ldap nismaps (share): ' + str(len(nis_shares)))
for i, arg in enumerate(sys.argv):
if i == 0:
continue
check_homes(arg)
check_shares()
print('home dirs: ' + str(home_dirs))
print('bad owner: ' + str(len(owner)))
print('bad permission: ' + str(len(permission)))
print('strange ldap users: ' + str(len(users)))
print('no blocked attr: ' + str(len(no_blocked)))
print('home not closed: ' + str(len(not_closed)))
print('home not open: ' + str(len(not_open)))
print('orphaned nis homes: ' + str(len(nis_homes)))
print('orphaned nis shares: ' + str(len(nis_shares)))
print('bad homeDirectory: ' + str(len(bad_home_directory)))
print('no user for home: ' + str(len(no_ldap_user)))
print('bad nismaps (home): ' + str(len(bad_nis_map)))
print('no nismap for home: ' + str(len(no_nis_map)))
print()
if no_blocked:
print('no blocked attr:')
print('----------------')
for home in no_blocked:
print(home)
print()
if owner:
print('bad owner or group:')
print('-------------------')
for home in owner:
print(home)
print()
if permission:
print('bad permission:')
print('---------------')
for home in permission:
print(home.permission)
print()
if acl:
print('bad acl:')
print('--------')
for home in acl:
extacl = posix1e.ACL(file=home.path)
print(home.path)
print(extacl)
print()
if users:
print('strange ldap users:')
print('-------------------')
for k, v in users.items():
print(''.join([k, ': ', 'blocked=', v['blocked'], ' ', 'homeDirectory=', v['homeDirectory']]))
print()
if not_closed:
print('home not closed:')
print('----------------')
for home in not_closed:
print(home)
print()
if not_open:
print('home not open:')
print('-------------')
for home in not_open:
print(home)
print()
if nis_homes:
print('orphaned nis homes:')
print('-------------------')
for k, v in nis_homes.items():
print(': '.join([k, v]))
print()
if nis_shares:
print('orphaned nis shares:')
print('--------------------')
for k, v in nis_shares.items():
print(': '.join([k, v]))
print()
if bad_home_directory:
print('bad homeDirectory:')
print('------------------')
for home in bad_home_directory:
print(home)
print()
if no_ldap_user:
print('no user for home:')
print('-----------------')
for home in no_ldap_user:
print(home)
print()
if bad_nis_map:
print('bad nismaps (home):')
print('-------------------')
for home in bad_nis_map:
print(home)
print()
if no_nis_map:
print('no nismap for home:')
print('-------------------')
for home in no_nis_map:
print(home)
print()
#!/usr/bin/env python3
import os
import sys
import pwd
import grp
import stat
import glob
import posix1e
import pyxymon as pymon
CHECK_NAME = 'permissions'
CHECK_VERSION = 2
LIFETIME = 30
home_dir = '/export/home1/*'
owner = []
permission = []
acl = []
class Home(object):
"""
Holds info about a home directory
"""
def __init__(self, name, path, st):
self.name = name
self.path = path
self.st = st
@property
def uid(self):
return self.st.st_uid
@property
def gid(self):
return self.st.st_gid
@property
def uname(self):
return pwd.getpwuid(self.uid).pw_name
@property
def gname(self):
return grp.getgrgid(self.gid).gr_name
@property
def filemode(self):
return stat.filemode(self.st.st_mode)
@property
def permission(self):
return ' '.join([self.filemode, self.path])
def __str__(self):
return ' '.join([self.filemode, self.uname, self.gname, self.path])
def check_homes(top):
if not os.path.isdir(top):
return
for f in os.listdir(top):
pathname = os.path.join(top, f)
if not os.path.isdir(pathname):
continue
st = os.stat(pathname)
home = Home(f, pathname, st)
if bad_owner(home):
owner.append(home)
if bad_permission(home):
permission.append(home)
if posix1e.has_extended(home.path):
acl.append(home)
def bad_owner(home):
if home.name == home.uname and home.name == home.gname:
return False
return True
def bad_permission(home):
# d---------
if home.st.st_mode == stat.S_IFDIR:
return False
# drwx------
elif home.st.st_mode == stat.S_IFDIR | stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR:
return False
return True
def list_homes(homes):
for home in homes:
print(home)
def run_check(xymon):
for path in glob.glob(home_dir):
check_homes(path)
if owner:
title = 'bad owner or group'
content = 'home must be owned by the respective user and the group his user-private-group<br/><br/>'
for home in owner:
content += ''.join([str(home), '<br/>'])
xymon.section(title, content)
xymon.color = pymon.STATUS_CRITICAL
if permission:
title = 'bad permissions'
content = 'home permission not <code>drwx------</code> (active user) or <code>d---------</code> (blocked user)<br/><br/>'
for home in permission:
content += ''.join([str(home.permission), '<br/>'])
xymon.section(title, content)
xymon.color = pymon.STATUS_CRITICAL
if acl:
title = 'bad acls'
content = 'home has posix.1e extended ACLs<br/>check acls using `getfacl`, which stands for `get fucking ACL`<br/><br/>'
for home in acl:
extacl = posix1e.ACL(file=home.path)
content += ''.join([home.path, '<br/>'])
content += ''.join([str(extacl), '<br/>'])
xymon.section(title, content)
xymon.color = pymon.STATUS_CRITICAL
def main():
"""Run xymon check"""
xymon = pymon.XymonClient(CHECK_NAME)
check_script = os.path.basename(__file__)
# The default criticity is set to 'pymon.STATUS_OK'
xymon.lifetime = LIFETIME
xymon.title('home ownership and permissions')
try:
run_check(xymon)
except Exception as e:
xymon.color = pymon.STATUS_WARNING
xymon.section('Exception', e)
xymon.footer(check_script, CHECK_VERSION)
xymon.send()
if __name__ == '__main__':
main()
sys.exit(0)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment