The branch, master has been updated via 16eaf7fd52e gp: Cleanup some unused code via ab2cda79280 gp: Ensure centrify crontab user policy performs proper cleanup via 8cc706c1025 gp: Ensure script user policy performs proper cleanup via b278f15890a gp: Ensure smb.conf policy preforms proper cleanup via a330ad7b2cc gp: Ensure MOTD policy preforms proper cleanup via 8bdb1b65332 gp: Ensure Issue policy preforms proper cleanup via 8a24829093e gp: Ensure Messages policy preforms proper cleanup via 03d796c6778 gp: Ensure Firefox policy preforms proper cleanup via 8f59ce543a8 gp: Add a misc applier, to assist some gp exts via 6ac22de7493 gp: Ensure Firewalld preforms proper cleanup via 7db3b63e769 gp: Test modifying centrify crontab user policy enforces changes via 70d3601fc64 gp: Test modifying script user policy enforces changes via 5c2dc0cce46 gp: Test modifying smb.conf policy enforces changes via c5571718006 gp: Test modifying Issue policy enforces changes via ae752b8c0b3 gp: Test modifying Messages policy enforces changes via ef0c54d7c24 gp: Test modifying MOTD policy enforces changes via 32a70df7e4e gp: Test modifying firefox policy enforces changes via b49d150db9a gp: Test modifying firewalld policy enforces changes via 217beca6e9d gp: Ensure Firewalld tests don't flop from 5571ce9619d dsdb: Use samdb_system_container_dn() in pdb_samba_dsdb_*()
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 16eaf7fd52e91ed8cfb39ac98e6d9bf470bfc358 Author: David Mulder <dmul...@samba.org> Date: Tue Jan 10 10:07:33 2023 -0700 gp: Cleanup some unused code Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Autobuild-User(master): Andrew Bartlett <abart...@samba.org> Autobuild-Date(master): Mon Jul 31 10:55:26 UTC 2023 on atb-devel-224 commit ab2cda79280e3a3ce4b806f96a5896d2a463b5ea Author: David Mulder <dmul...@samba.org> Date: Tue Jul 25 13:23:10 2023 -0600 gp: Ensure centrify crontab user policy performs proper cleanup This resolves cleanup issues for user and group centrify compatible policies. It also ensures the crontab policies use functions from the scripts policy, to avoid code duplication and simplify cleanup. Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 8cc706c1025ec521f7f878bba8a48e6d66750fe0 Author: David Mulder <dmul...@samba.org> Date: Tue Jan 10 13:21:49 2023 -0700 gp: Ensure script user policy performs proper cleanup This resolves cleanup issues for scripts user policy. Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit b278f15890a3625f2b1663ea543e032ef411fac1 Author: David Mulder <dmul...@samba.org> Date: Tue Jan 10 09:57:21 2023 -0700 gp: Ensure smb.conf policy preforms proper cleanup Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit a330ad7b2cc163f34eb2d379e6ef98e7e449d477 Author: David Mulder <dmul...@samba.org> Date: Mon Jan 9 17:19:44 2023 -0700 gp: Ensure MOTD policy preforms proper cleanup Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 8bdb1b65332342da4d28af3b9d9fbcfca15a869e Author: David Mulder <dmul...@samba.org> Date: Mon Jan 9 17:12:53 2023 -0700 gp: Ensure Issue policy preforms proper cleanup Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 8a24829093ef234a5044fab1e9f9992a41e29be1 Author: David Mulder <dmul...@samba.org> Date: Mon Jan 9 16:33:59 2023 -0700 gp: Ensure Messages policy preforms proper cleanup Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 03d796c6778e1499b0a753ffd371d0437c9a27f8 Author: David Mulder <dmul...@samba.org> Date: Mon Jan 9 15:20:57 2023 -0700 gp: Ensure Firefox policy preforms proper cleanup Now uses gp_misc_applier to ensure old settings are properly cleaned up. Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 8f59ce543a88607ca244c1982238f4d01e173a4c Author: David Mulder <dmul...@samba.org> Date: Mon Jan 9 15:19:48 2023 -0700 gp: Add a misc applier, to assist some gp exts Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 6ac22de74938862b489e29090f4e6ec17c643dd8 Author: David Mulder <dmul...@samba.org> Date: Fri Jan 6 14:48:12 2023 -0700 gp: Ensure Firewalld preforms proper cleanup Now uses gp_applier to ensure old settings are properly cleaned up. Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 7db3b63e769baa7d485e12556351bf4533987c8e Author: David Mulder <dmul...@samba.org> Date: Tue Jul 25 13:48:25 2023 -0600 gp: Test modifying centrify crontab user policy enforces changes Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 70d3601fc648813b05ed2ec08da4c78229023763 Author: David Mulder <dmul...@samba.org> Date: Tue Jul 25 13:41:06 2023 -0600 gp: Test modifying script user policy enforces changes Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 5c2dc0cce4670091856885df26fd4e64fa4ba2d6 Author: David Mulder <dmul...@samba.org> Date: Fri Feb 10 14:12:03 2023 -0700 gp: Test modifying smb.conf policy enforces changes Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit c55717180062afd5a5af1fc07adb11b428609af0 Author: David Mulder <dmul...@samba.org> Date: Fri Feb 10 13:55:13 2023 -0700 gp: Test modifying Issue policy enforces changes Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit ae752b8c0b3fb5abc292bd9f040dea1b187510f1 Author: David Mulder <dmul...@samba.org> Date: Tue Jul 25 12:52:11 2023 -0600 gp: Test modifying Messages policy enforces changes Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit ef0c54d7c2408c4c51678419173c064844671651 Author: David Mulder <dmul...@samba.org> Date: Fri Feb 10 13:04:16 2023 -0700 gp: Test modifying MOTD policy enforces changes Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 32a70df7e4efac12573e3a4cbf5a15a7c6d4a151 Author: David Mulder <dmul...@samba.org> Date: Thu Feb 9 15:27:00 2023 -0700 gp: Test modifying firefox policy enforces changes Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit b49d150db9aca415f8473f785291c4c87300416e Author: David Mulder <dmul...@samba.org> Date: Fri Jan 13 11:15:50 2023 -0700 gp: Test modifying firewalld policy enforces changes Ensure that modifying the firewalld policy and re-applying will enforce the correct policy. Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 217beca6e9dc68db774e79ade59b4f7d4c3791b7 Author: David Mulder <dmul...@samba.org> Date: Fri Jan 6 14:49:19 2023 -0700 gp: Ensure Firewalld tests don't flop This test was failing depending on the system it was run on, since the result depends on whether firewalld python bindings were installed. This wasn't failing in CI (and so there is no flopping test marked), but does fail on some local systems. Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> ----------------------------------------------------------------------- Summary of changes: python/samba/gp/gp_centrify_crontab_ext.py | 75 +++---- python/samba/gp/gp_firefox_ext.py | 139 ++++++++---- python/samba/gp/gp_firewalld_ext.py | 74 ++++--- python/samba/gp/gp_msgs_ext.py | 74 ++++--- python/samba/gp/gp_scripts_ext.py | 64 +++--- python/samba/gp/gp_smb_conf_ext.py | 77 ++++--- python/samba/gp/gpclass.py | 27 +++ python/samba/gp/vgp_files_ext.py | 1 - python/samba/gp/vgp_issue_ext.py | 47 +++-- python/samba/gp/vgp_motd_ext.py | 47 +++-- python/samba/gp/vgp_startup_scripts_ext.py | 1 - python/samba/tests/bin/firewall-cmd | 12 +- python/samba/tests/gpo.py | 329 ++++++++++++++++++++++++++--- 13 files changed, 686 insertions(+), 281 deletions(-) Changeset truncated at 500 lines: diff --git a/python/samba/gp/gp_centrify_crontab_ext.py b/python/samba/gp/gp_centrify_crontab_ext.py index e8ffd8bec9f..e532416d224 100644 --- a/python/samba/gp/gp_centrify_crontab_ext.py +++ b/python/samba/gp/gp_centrify_crontab_ext.py @@ -16,9 +16,11 @@ import os, re from subprocess import Popen, PIPE -from samba.gp.gpclass import gp_pol_ext, drop_privileges, gp_file_applier -from hashlib import blake2b +from samba.gp.gpclass import gp_pol_ext, drop_privileges, gp_file_applier, \ + gp_misc_applier from tempfile import NamedTemporaryFile +from samba.gp.gp_scripts_ext import fetch_crontab, install_crontab, \ + install_user_crontab intro = ''' ### autogenerated by samba @@ -92,73 +94,44 @@ class gp_centrify_crontab_ext(gp_pol_ext, gp_file_applier): 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 +class gp_user_centrify_crontab_ext(gp_centrify_crontab_ext, gp_misc_applier): + def unapply(self, guid, attribute, entry): + others, entries = fetch_crontab(self.username) + if entry in entries: + entries.remove(entry) + install_user_crontab(self.username, others, entries) + self.cache_remove_attribute(guid, attribute) -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) + def apply(self, guid, attribute, entry): + old_val = self.cache_get_attribute_value(guid, attribute) + others, entries = fetch_crontab(self.username) + if not old_val or entry not in entries: + entries.append(entry) + install_user_crontab(self.username, others, entries) + self.cache_add_attribute(guid, attribute, entry) -class gp_user_centrify_crontab_ext(gp_centrify_crontab_ext): def process_group_policy(self, deleted_gpo_list, changed_gpo_list): 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() + self.unapply(guid, attribute, entry) 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 + attrs = [] 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() + attribute = self.generate_attribute(e.data) + attrs.append(attribute) + self.apply(gpo.name, attribute, e.data) + self.clean(gpo.name, keep=attrs) def rsop(self, gpo): return super().rsop(gpo, target='USER') diff --git a/python/samba/gp/gp_firefox_ext.py b/python/samba/gp/gp_firefox_ext.py index 06ae31d7afb..a623314d411 100644 --- a/python/samba/gp/gp_firefox_ext.py +++ b/python/samba/gp/gp_firefox_ext.py @@ -16,7 +16,7 @@ import os import json -from samba.gp.gpclass import gp_pol_ext +from samba.gp.gpclass import gp_pol_ext, gp_misc_applier from samba.dcerpc import misc from samba.common import get_string from samba.gp.util.logging import log @@ -29,8 +29,8 @@ def parse_entry_data(e): return e.data == 1 return e.data -def convert_pol_to_json(policies, section, entries): - result = policies['policies'] +def convert_pol_to_json(section, entries): + result = {} index_map = {} for e in entries: if not e.keyname.startswith(section): @@ -81,79 +81,121 @@ def convert_pol_to_json(policies, section, entries): current[e.valuename] = parse_entry_data(e) else: result[e.valuename] = parse_entry_data(e) - return {'policies': result} + return result -class gp_firefox_ext(gp_pol_ext): - __firefox_installdir1 = '/usr/lib64/firefox/distribution' - __firefox_installdir2 = '/etc/firefox/policies' - __destfile1 = os.path.join(__firefox_installdir1, 'policies.json') - __destfile2 = os.path.join(__firefox_installdir2, 'policies.json') +class gp_firefox_ext(gp_pol_ext, gp_misc_applier): + firefox_installdir = '/etc/firefox/policies' + destfile = os.path.join(firefox_installdir, 'policies.json') def __str__(self): return 'Mozilla/Firefox' def set_machine_policy(self, policies): try: - os.makedirs(self.__firefox_installdir1, exist_ok=True) - with open(self.__destfile1, 'w') as f: + os.makedirs(self.firefox_installdir, exist_ok=True) + with open(self.destfile, 'w') as f: json.dump(policies, f) - log.debug('Wrote Firefox preferences', self.__destfile1) + log.debug('Wrote Firefox preferences', self.destfile) except PermissionError: log.debug('Failed to write Firefox preferences', - self.__destfile1) - - try: - os.makedirs(self.__firefox_installdir2, exist_ok=True) - with open(self.__destfile2, 'w') as f: - json.dump(policies, f) - log.debug('Wrote Firefox preferences', self.__destfile2) - except PermissionError: - log.debug('Failed to write Firefox preferences', - self.__destfile2) + self.destfile) def get_machine_policy(self): - if os.path.exists(self.__destfile2): - with open(self.__destfile2, 'r') as r: - policies = json.load(r) - log.debug('Read Firefox preferences', self.__destfile2) - elif os.path.exists(self.__destfile1): - with open(self.__destfile1, 'r') as r: + if os.path.exists(self.destfile): + with open(self.destfile, 'r') as r: policies = json.load(r) - log.debug('Read Firefox preferences', self.__destfile1) + log.debug('Read Firefox preferences', self.destfile) else: policies = {'policies': {}} return policies + def parse_value(self, value): + data = super().parse_value(value) + for k, v in data.items(): + try: + data[k] = json.loads(v) + except json.decoder.JSONDecodeError: + pass + return data + + def unapply_policy(self, guid, policy, applied_val, val): + def set_val(policies, policy, val): + if val is None: + del policies[policy] + else: + policies[policy] = val + current = self.get_machine_policy() + if policy in current['policies'].keys(): + if applied_val is not None: + # Only restore policy if unmodified + if current['policies'][policy] == applied_val: + set_val(current['policies'], policy, val) + else: + set_val(current['policies'], policy, val) + self.set_machine_policy(current) + + def unapply(self, guid, policy, val): + cache = self.parse_value(val) + if policy == 'policies.json': + current = self.get_machine_policy() + for attr in current['policies'].keys(): + val = cache['old_val']['policies'][attr] \ + if attr in cache['old_val']['policies'] else None + self.unapply_policy(guid, attr, None, val) + else: + self.unapply_policy(guid, policy, + cache['new_val'] if 'new_val' in cache else None, + cache['old_val']) + self.cache_remove_attribute(guid, policy) + + def apply(self, guid, policy, val): + # If the policy has changed, unapply, then apply new policy + data = self.cache_get_attribute_value(guid, policy) + if data is not None: + self.unapply(guid, policy, data) + + current = self.get_machine_policy() + before = None + if policy in current['policies'].keys(): + before = current['policies'][policy] + + # Apply the policy and log the changes + new_value = self.generate_value(old_val=json.dumps(before), + new_val=json.dumps(val)) + current['policies'][policy] = val + self.set_machine_policy(current) + self.cache_add_attribute(guid, policy, get_string(new_value)) + def process_group_policy(self, deleted_gpo_list, changed_gpo_list, policy_dir=None): if policy_dir is not None: - self.__firefox_installdir2 = policy_dir - self.__destfile2 = os.path.join(policy_dir, 'policies.json') + self.firefox_installdir = policy_dir + self.destfile = os.path.join(policy_dir, 'policies.json') for guid, settings in deleted_gpo_list: - self.gp_db.set_guid(guid) if str(self) in settings: - for attribute, policies in settings[str(self)].items(): - self.set_machine_policy(json.loads(policies)) - self.gp_db.delete(str(self), attribute) - self.gp_db.commit() + for policy, val in settings[str(self)].items(): + self.unapply(guid, policy, val) for gpo in changed_gpo_list: if gpo.file_sys_path: - section = 'Software\\Policies\\Mozilla\\Firefox' - self.gp_db.set_guid(gpo.name) pol_file = 'MACHINE/Registry.pol' + section = 'Software\\Policies\\Mozilla\\Firefox' path = os.path.join(gpo.file_sys_path, pol_file) pol_conf = self.parse(path) if not pol_conf: continue - policies = self.get_machine_policy() - self.gp_db.store(str(self), 'policies.json', - json.dumps(policies)) - policies = convert_pol_to_json(policies, section, - pol_conf.entries) - self.set_machine_policy(policies) - self.gp_db.commit() + # Unapply the old cache entry, if present + data = self.cache_get_attribute_value(gpo.name, 'policies.json') + if data is not None: + self.unapply(gpo.name, 'policies.json', data) + + policies = convert_pol_to_json(section, pol_conf.entries) + for policy, val in policies.items(): + self.apply(gpo.name, policy, val) + + # cleanup removed policies + self.clean(gpo.name, keep=policies.keys()) def rsop(self, gpo): output = {} @@ -168,3 +210,10 @@ class gp_firefox_ext(gp_pol_ext): if e.keyname.startswith(section): output['%s\\%s' % (e.keyname, e.valuename)] = e.data return output + +class gp_firefox_old_ext(gp_firefox_ext): + firefox_installdir = '/usr/lib64/firefox/distribution' + destfile = os.path.join(firefox_installdir, 'policies.json') + + def __str__(self): + return 'Mozilla/Firefox (old profile directory)' diff --git a/python/samba/gp/gp_firewalld_ext.py b/python/samba/gp/gp_firewalld_ext.py index dd80d94c9cf..5e125b0fe46 100644 --- a/python/samba/gp/gp_firewalld_ext.py +++ b/python/samba/gp/gp_firewalld_ext.py @@ -16,10 +16,9 @@ import os from subprocess import Popen, PIPE -from hashlib import blake2b from shutil import which import json -from samba.gp.gpclass import gp_pol_ext +from samba.gp.gpclass import gp_pol_ext, gp_applier from samba.gp.util.logging import log def firewall_cmd(*args): @@ -41,16 +40,19 @@ def rule_segment_parse(name, rule_segment): return '%s %s ' % (name, ' '.join(['%s=%s' % (k, v) for k, v in rule_segment.items()])) -class gp_firewalld_ext(gp_pol_ext): +class gp_firewalld_ext(gp_pol_ext, gp_applier): def __str__(self): return 'Security/Firewalld' - def apply_zone(self, zone): + def apply_zone(self, guid, zone): + zone_attrs = [] ret = firewall_cmd('--permanent', '--new-zone=%s' % zone)[0] if ret != 0: log.error('Failed to add new zone', zone) else: - self.gp_db.store(str(self), 'zone:%s' % zone, zone) + attribute = 'zone:%s' % zone + self.cache_add_attribute(guid, attribute, zone) + zone_attrs.append(attribute) # Default to matching the interface(s) for the default zone ret, out = firewall_cmd('--list-interfaces') if ret != 0: @@ -60,8 +62,10 @@ class gp_firewalld_ext(gp_pol_ext): '--add-interface=%s' % interface.decode()) if ret != 0: log.error('Failed to set interfaces for zone', zone) + return zone_attrs - def apply_rules(self, rule_dict): + def apply_rules(self, guid, rule_dict): + rule_attrs = [] for zone, rules in rule_dict.items(): for rule in rules: if 'rule' in rule: @@ -88,50 +92,60 @@ class gp_firewalld_ext(gp_pol_ext): if ret != 0: log.error('Failed to add firewall rule', rule_parsed) else: - rhash = blake2b(rule_parsed.encode()).hexdigest() - self.gp_db.store(str(self), 'rule:%s:%s' % (zone, rhash), - rule_parsed) + rhash = self.generate_value_hash(rule_parsed) + attribute = 'rule:%s:%s' % (zone, rhash) + self.cache_add_attribute(guid, attribute, rule_parsed) + rule_attrs.append(attribute) + return rule_attrs + + def unapply(self, guid, attribute, value): + if attribute.startswith('zone'): + ret = firewall_cmd('--permanent', + '--delete-zone=%s' % value)[0] + if ret != 0: + log.error('Failed to remove zone', value) + else: + self.cache_remove_attribute(guid, attribute) + elif attribute.startswith('rule'): + _, zone, _ = attribute.split(':') + ret = firewall_cmd('--permanent', '--zone=%s' % zone, + '--remove-rich-rule', value)[0] + if ret != 0: + log.error('Failed to remove firewall rule', value) + else: + self.cache_remove_attribute(guid, attribute) + + def apply(self, applier_func, *args): + return applier_func(*args) def process_group_policy(self, deleted_gpo_list, changed_gpo_list): for guid, settings in deleted_gpo_list: - self.gp_db.set_guid(guid) if str(self) in settings: for attribute, value in settings[str(self)].items(): - if attribute.startswith('zone'): - ret = firewall_cmd('--permanent', - '--delete-zone=%s' % value)[0] - if ret != 0: - log.error('Failed to remove zone', value) - else: - self.gp_db.delete(str(self), attribute) - elif attribute.startswith('rule'): - _, zone, _ = attribute.split(':') - ret = firewall_cmd('--permanent', '--zone=%s' % zone, - '--remove-rich-rule', value)[0] - if ret != 0: - log.error('Failed to remove firewall rule', value) - else: - self.gp_db.delete(str(self), attribute) - self.gp_db.commit() + self.unapply(guid, attribute, value) for gpo in changed_gpo_list: if gpo.file_sys_path: section = 'Software\\Policies\\Samba\\Unix Settings\\Firewalld' - 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 + attrs = [] for e in pol_conf.entries: if e.keyname.startswith(section): if e.keyname.endswith('Rules'): - self.apply_rules(json.loads(e.data)) + attrs.extend(self.apply(self.apply_rules, gpo.name, + json.loads(e.data))) elif e.keyname.endswith('Zones'): if e.valuename == '**delvals.': continue - self.apply_zone(e.data) - self.gp_db.commit() + attrs.extend(self.apply(self.apply_zone, gpo.name, + e.data)) + + # Cleanup all old zones and rules from this GPO + self.clean(gpo.name, keep=attrs) def rsop(self, gpo): output = {} diff --git a/python/samba/gp/gp_msgs_ext.py b/python/samba/gp/gp_msgs_ext.py index 267c7456ad1..f1a13323c4d 100644 --- a/python/samba/gp/gp_msgs_ext.py +++ b/python/samba/gp/gp_msgs_ext.py @@ -15,57 +15,65 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import os -from samba.gp.gpclass import gp_pol_ext +from samba.gp.gpclass import gp_pol_ext, gp_misc_applier + +class gp_msgs_ext(gp_pol_ext, gp_misc_applier): + def unapply(self, guid, cdir, attribute, value): + if attribute not in ['motd', 'issue']: + raise ValueError('"%s" is not a message attribute' % attribute) + data = self.parse_value(value) + mfile = os.path.join(cdir, attribute) + current = open(mfile, 'r').read() if os.path.exists(mfile) else '' + # Only overwrite the msg if it hasn't been modified. It may have been + # modified by another GPO. + if 'new_val' not in data or current.strip() == data['new_val'].strip(): + msg = data['old_val'] + with open(mfile, 'w') as w: + if msg: + w.write(msg) + else: + w.truncate() + self.cache_remove_attribute(guid, attribute) + + def apply(self, guid, cdir, entries): + section_name = 'Software\\Policies\\Samba\\Unix Settings\\Messages' + for e in entries: + if e.keyname == section_name and e.data.strip(): + if e.valuename not in ['motd', 'issue']: + raise ValueError('"%s" is not a message attribute' % \ + e.valuename) + mfile = os.path.join(cdir, e.valuename) + if os.path.exists(mfile): + old_val = open(mfile, 'r').read() + else: + old_val = '' + # If policy is already applied, skip application + if old_val.strip() == e.data.strip(): + return + with open(mfile, 'w') as w: + w.write(e.data) + data = self.generate_value(old_val=old_val, new_val=e.data) + self.cache_add_attribute(guid, e.valuename, data) -class gp_msgs_ext(gp_pol_ext): def __str__(self): return 'Unix Settings/Messages' -- Samba Shared Repository