mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
gp: Apply Firewalld Policy
Signed-off-by: David Mulder <dmulder@suse.com> Reviewed-by: Jeremy Allison <jra@samba.org> Autobuild-User(master): Jeremy Allison <jra@samba.org> Autobuild-Date(master): Mon Nov 1 21:16:43 UTC 2021 on sn-devel-184
This commit is contained in:
parent
cd73e41013
commit
5199eb1412
@ -14,12 +14,145 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import os
|
||||||
|
from subprocess import Popen, PIPE
|
||||||
|
from hashlib import blake2b
|
||||||
|
from shutil import which
|
||||||
|
import json
|
||||||
from samba.gpclass import gp_pol_ext
|
from samba.gpclass import gp_pol_ext
|
||||||
|
|
||||||
|
def firewall_cmd(*args):
|
||||||
|
fw_cmd = which('firewall-cmd')
|
||||||
|
if fw_cmd is not None:
|
||||||
|
cmd = [fw_cmd]
|
||||||
|
cmd.extend(list(args))
|
||||||
|
|
||||||
|
p = Popen(cmd, stdout=PIPE, stderr=PIPE)
|
||||||
|
stdoutdata, _ = p.communicate()
|
||||||
|
return p.returncode, stdoutdata
|
||||||
|
else:
|
||||||
|
return -1, 'firewall-cmd not found'
|
||||||
|
|
||||||
|
def rule_segment_parse(name, rule_segment):
|
||||||
|
if isinstance(rule_segment, str):
|
||||||
|
return ('%s=%s' % (name, rule_segment)) + ' '
|
||||||
|
else:
|
||||||
|
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):
|
||||||
|
def __str__(self):
|
||||||
|
return 'Security/Firewalld'
|
||||||
|
|
||||||
|
def apply_zone(self, zone):
|
||||||
|
ret = firewall_cmd('--permanent', '--new-zone=%s' % zone)[0]
|
||||||
|
if ret != 0:
|
||||||
|
self.logger.error('Failed to add new zone %s' % zone)
|
||||||
|
else:
|
||||||
|
self.gp_db.store(str(self), 'zone:%s' % zone, zone)
|
||||||
|
# Default to matching the interface(s) for the default zone
|
||||||
|
ret, out = firewall_cmd('--list-interfaces')
|
||||||
|
if ret != 0:
|
||||||
|
self.logger.error('Failed to set interfaces for zone: %s' % zone)
|
||||||
|
for interface in out.strip().split():
|
||||||
|
ret = firewall_cmd('--permanent', '--zone=%s' % zone,
|
||||||
|
'--add-interface=%s' % interface.decode())
|
||||||
|
if ret != 0:
|
||||||
|
self.logger.error('Failed to set interfaces for zone: %s' % \
|
||||||
|
zone)
|
||||||
|
|
||||||
|
def apply_rules(self, rule_dict):
|
||||||
|
for zone, rules in rule_dict.items():
|
||||||
|
for rule in rules:
|
||||||
|
if 'rule' in rule:
|
||||||
|
rule_parsed = rule_segment_parse('rule', rule['rule'])
|
||||||
|
else:
|
||||||
|
rule_parsed = 'rule '
|
||||||
|
for segment in ['source', 'destination', 'service', 'port',
|
||||||
|
'protocol', 'icmp-block', 'masquerade',
|
||||||
|
'icmp-type', 'forward-port', 'source-port',
|
||||||
|
'log', 'audit']:
|
||||||
|
names = [s for s in rule.keys() if s.startswith(segment)]
|
||||||
|
for name in names:
|
||||||
|
rule_parsed += rule_segment_parse(name, rule[name])
|
||||||
|
actions = set(['accept', 'reject', 'drop', 'mark'])
|
||||||
|
segments = set(rule.keys())
|
||||||
|
action = actions.intersection(segments)
|
||||||
|
if len(action) == 1:
|
||||||
|
rule_parsed += rule_segment_parse(list(action)[0],
|
||||||
|
rule[list(action)[0]])
|
||||||
|
else:
|
||||||
|
self.logger.error('Invalid firewall rule syntax')
|
||||||
|
ret = firewall_cmd('--permanent', '--zone=%s' % zone,
|
||||||
|
'--add-rich-rule', rule_parsed.strip())[0]
|
||||||
|
if ret != 0:
|
||||||
|
self.logger.error('Failed to add firewall rule: %s' % \
|
||||||
|
rule_parsed)
|
||||||
|
else:
|
||||||
|
rhash = blake2b(rule_parsed.encode()).hexdigest()
|
||||||
|
self.gp_db.store(str(self), 'rule:%s:%s' % (zone, rhash),
|
||||||
|
rule_parsed)
|
||||||
|
|
||||||
def process_group_policy(self, deleted_gpo_list, changed_gpo_list):
|
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:
|
||||||
|
for attribute, value in settings[str(self)].items():
|
||||||
|
if attribute.startswith('zone'):
|
||||||
|
ret = firewall_cmd('--permanent',
|
||||||
|
'--delete-zone=%s' % value)[0]
|
||||||
|
if ret != 0:
|
||||||
|
self.logger.error('Failed to remove zone: %s' % \
|
||||||
|
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:
|
||||||
|
self.logger.error('Failed to remove firewall'
|
||||||
|
' rule: %s' % value)
|
||||||
|
else:
|
||||||
|
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\\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
|
||||||
|
for e in pol_conf.entries:
|
||||||
|
if e.keyname.startswith(section):
|
||||||
|
if e.keyname.endswith('Rules'):
|
||||||
|
self.apply_rules(json.loads(e.data))
|
||||||
|
elif e.keyname.endswith('Zones'):
|
||||||
|
if e.valuename == '**delvals.':
|
||||||
|
continue
|
||||||
|
self.apply_zone(e.data)
|
||||||
|
self.gp_db.commit()
|
||||||
|
|
||||||
def rsop(self, gpo):
|
def rsop(self, gpo):
|
||||||
output = {}
|
output = {}
|
||||||
|
pol_file = 'MACHINE/Registry.pol'
|
||||||
|
section = 'Software\\Policies\\Samba\\Unix Settings\\Firewalld'
|
||||||
|
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.startswith(section):
|
||||||
|
if e.keyname.endswith('Zone'):
|
||||||
|
if 'Zones' not in output.keys():
|
||||||
|
output['Zones'] = []
|
||||||
|
output['Zones'].append(e.data)
|
||||||
|
elif e.keyname.endswith('Rules'):
|
||||||
|
if 'Rules' not in output.keys():
|
||||||
|
output['Rules'] = []
|
||||||
|
output['Rules'].append(json.loads(e.data))
|
||||||
return output
|
return output
|
||||||
|
@ -1 +0,0 @@
|
|||||||
^samba.tests.gpo.samba.tests.gpo.GPOTests.test_gp_firewalld_ext
|
|
@ -48,6 +48,7 @@ from samba.gp_gnome_settings_ext import gp_gnome_settings_ext
|
|||||||
from samba.gp_cert_auto_enroll_ext import gp_cert_auto_enroll_ext
|
from samba.gp_cert_auto_enroll_ext import gp_cert_auto_enroll_ext
|
||||||
from samba.gp_firefox_ext import gp_firefox_ext
|
from samba.gp_firefox_ext import gp_firefox_ext
|
||||||
from samba.gp_chromium_ext import gp_chromium_ext, gp_chrome_ext
|
from samba.gp_chromium_ext import gp_chromium_ext, gp_chrome_ext
|
||||||
|
from samba.gp_firewalld_ext import gp_firewalld_ext
|
||||||
from samba.credentials import Credentials
|
from samba.credentials import Credentials
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
@ -126,6 +127,7 @@ if __name__ == "__main__":
|
|||||||
gp_extensions.append(gp_firefox_ext)
|
gp_extensions.append(gp_firefox_ext)
|
||||||
gp_extensions.append(gp_chromium_ext)
|
gp_extensions.append(gp_chromium_ext)
|
||||||
gp_extensions.append(gp_chrome_ext)
|
gp_extensions.append(gp_chrome_ext)
|
||||||
|
gp_extensions.append(gp_firewalld_ext)
|
||||||
gp_extensions.extend(machine_exts)
|
gp_extensions.extend(machine_exts)
|
||||||
elif opts.target == 'User':
|
elif opts.target == 'User':
|
||||||
gp_extensions.append(gp_user_scripts_ext)
|
gp_extensions.append(gp_user_scripts_ext)
|
||||||
|
Loading…
Reference in New Issue
Block a user