From 17ba8120ed61f58d927164d67408399becac27bb Mon Sep 17 00:00:00 2001 From: David Mulder Date: Fri, 29 Apr 2022 15:21:33 -0600 Subject: [PATCH] gpo: Add Centrify Compatible Crontab Extensions Signed-off-by: David Mulder Reviewed-by: Jeremy Allison Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Tue May 10 20:05:48 UTC 2022 on sn-devel-184 --- python/samba/gp_centrify_crontab_ext.py | 136 +++++++++++++++++++++++- selftest/knownfail.d/gpo | 2 - source4/scripting/bin/samba-gpupdate | 4 + 3 files changed, 136 insertions(+), 6 deletions(-) delete mode 100644 selftest/knownfail.d/gpo diff --git a/python/samba/gp_centrify_crontab_ext.py b/python/samba/gp_centrify_crontab_ext.py index 835d4680d6e..eace6a973cd 100644 --- a/python/samba/gp_centrify_crontab_ext.py +++ b/python/samba/gp_centrify_crontab_ext.py @@ -14,19 +14,147 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from samba.gpclass import gp_pol_ext +import os, re +from subprocess import Popen, PIPE +from samba.gpclass import gp_pol_ext, drop_privileges +from hashlib import blake2b +from tempfile import NamedTemporaryFile + +intro = ''' +### autogenerated by samba +# +# This file is generated by the gp_centrify_crontab_ext Group Policy +# Client Side Extension. To modify the contents of this file, +# modify the appropriate Group Policy objects which apply +# to this machine. DO NOT MODIFY THIS FILE DIRECTLY. +# + +''' +end = ''' +### autogenerated by samba ### +''' class gp_centrify_crontab_ext(gp_pol_ext): - def process_group_policy(self, deleted_gpo_list, changed_gpo_list, cdir=None): - pass + def __str__(self): + return 'Centrify/CrontabEntries' + + def process_group_policy(self, deleted_gpo_list, changed_gpo_list, + cdir=None): + for guid, settings in deleted_gpo_list: + self.gp_db.set_guid(guid) + if str(self) in settings: + for attribute, script in settings[str(self)].items(): + if os.path.exists(script): + os.unlink(script) + self.gp_db.delete(str(self), attribute) + self.gp_db.commit() + + for gpo in changed_gpo_list: + if gpo.file_sys_path: + section = \ + 'Software\\Policies\\Centrify\\UnixSettings\\CrontabEntries' + self.gp_db.set_guid(gpo.name) + pol_file = 'MACHINE/Registry.pol' + path = os.path.join(gpo.file_sys_path, pol_file) + pol_conf = self.parse(path) + if not pol_conf: + continue + for e in pol_conf.entries: + if e.keyname == section and e.data.strip(): + cron_dir = '/etc/cron.d' if not cdir else cdir + attribute = blake2b(e.data.encode()).hexdigest() + old_val = self.gp_db.retrieve(str(self), attribute) + if not old_val: + with NamedTemporaryFile(prefix='gp_', mode="w+", + delete=False, dir=cron_dir) as f: + contents = '%s\n%s\n%s' % (intro, e.data, end) + f.write(contents) + self.gp_db.store(str(self), attribute, f.name) + self.gp_db.commit() def rsop(self, gpo, target='MACHINE'): output = {} + section = 'Software\\Policies\\Centrify\\UnixSettings\\CrontabEntries' + pol_file = '%s/Registry.pol' % target + if gpo.file_sys_path: + path = os.path.join(gpo.file_sys_path, pol_file) + pol_conf = self.parse(path) + if not pol_conf: + return output + for e in pol_conf.entries: + if e.keyname == section and e.data.strip(): + if str(self) not in output.keys(): + output[str(self)] = [] + output[str(self)].append(e.data) return output +def fetch_crontab(username): + p = Popen(['crontab', '-l', '-u', username], stdout=PIPE, stderr=PIPE) + out, err = p.communicate() + if p.returncode != 0: + raise RuntimeError('Failed to read the crontab: %s' % err) + m = re.findall('%s(.*)%s' % (intro, end), out.decode(), re.DOTALL) + if len(m) == 1: + entries = m[0].strip().split('\n') + else: + entries = [] + m = re.findall('(.*)%s.*%s(.*)' % (intro, end), out.decode(), re.DOTALL) + if len(m) == 1: + others = '\n'.join([l.strip() for l in m[0]]) + else: + others = out.decode() + return others, entries + +def install_crontab(fname, username): + p = Popen(['crontab', fname, '-u', username], stdout=PIPE, stderr=PIPE) + _, err = p.communicate() + if p.returncode != 0: + raise RuntimeError('Failed to install crontab: %s' % err) + class gp_user_centrify_crontab_ext(gp_centrify_crontab_ext): def process_group_policy(self, deleted_gpo_list, changed_gpo_list): - pass + for guid, settings in deleted_gpo_list: + self.gp_db.set_guid(guid) + if str(self) in settings: + others, entries = fetch_crontab(self.username) + for attribute, entry in settings[str(self)].items(): + if entry in entries: + entries.remove(entry) + self.gp_db.delete(str(self), attribute) + with NamedTemporaryFile() as f: + if len(entries) > 0: + f.write('\n'.join([others, intro, + '\n'.join(entries), end]).encode()) + else: + f.write(others.encode()) + f.flush() + install_crontab(f.name, self.username) + self.gp_db.commit() + + for gpo in changed_gpo_list: + if gpo.file_sys_path: + section = \ + 'Software\\Policies\\Centrify\\UnixSettings\\CrontabEntries' + self.gp_db.set_guid(gpo.name) + pol_file = 'USER/Registry.pol' + path = os.path.join(gpo.file_sys_path, pol_file) + pol_conf = drop_privileges('root', self.parse, path) + if not pol_conf: + continue + for e in pol_conf.entries: + if e.keyname == section and e.data.strip(): + attribute = blake2b(e.data.encode()).hexdigest() + old_val = self.gp_db.retrieve(str(self), attribute) + others, entries = fetch_crontab(self.username) + if not old_val or e.data not in entries: + entries.append(e.data) + with NamedTemporaryFile() as f: + f.write('\n'.join([others, intro, + '\n'.join(entries), end]).encode()) + f.flush() + install_crontab(f.name, self.username) + self.gp_db.store(str(self), attribute, e.data) + self.gp_db.commit() def rsop(self, gpo): return super().rsop(gpo, target='USER') diff --git a/selftest/knownfail.d/gpo b/selftest/knownfail.d/gpo deleted file mode 100644 index 14ae00bb270..00000000000 --- a/selftest/knownfail.d/gpo +++ /dev/null @@ -1,2 +0,0 @@ -samba.tests.gpo.samba.tests.gpo.GPOTests.test_gp_centrify_crontab_ext -samba.tests.gpo.samba.tests.gpo.GPOTests.test_gp_user_centrify_crontab_ext diff --git a/source4/scripting/bin/samba-gpupdate b/source4/scripting/bin/samba-gpupdate index b4c2ca9b445..079ae485f10 100755 --- a/source4/scripting/bin/samba-gpupdate +++ b/source4/scripting/bin/samba-gpupdate @@ -50,6 +50,8 @@ from samba.gp_firefox_ext import gp_firefox_ext from samba.gp_chromium_ext import gp_chromium_ext, gp_chrome_ext from samba.gp_firewalld_ext import gp_firewalld_ext from samba.gp_centrify_sudoers_ext import gp_centrify_sudoers_ext +from samba.gp_centrify_crontab_ext import gp_centrify_crontab_ext, \ + gp_user_centrify_crontab_ext from samba.credentials import Credentials from samba.gp.util.logging import logger_init @@ -103,6 +105,7 @@ if __name__ == "__main__": gp_extensions.append(gp_sudoers_ext) gp_extensions.append(vgp_sudoers_ext) gp_extensions.append(gp_centrify_sudoers_ext) + gp_extensions.append(gp_centrify_crontab_ext) gp_extensions.append(gp_smb_conf_ext) gp_extensions.append(gp_msgs_ext) gp_extensions.append(vgp_symlink_ext) @@ -121,6 +124,7 @@ if __name__ == "__main__": gp_extensions.extend(machine_exts) elif opts.target == 'User': gp_extensions.append(gp_user_scripts_ext) + gp_extensions.append(gp_user_centrify_crontab_ext) gp_extensions.extend(user_exts) if opts.rsop: -- 2.34.1