Commit 7368822f authored by Alain Takoudjou's avatar Alain Takoudjou

Merge branch 'tap-nobridge' into 'master'

Tap nobridge



See merge request !2
parents 0f48ce37 b8d90b26
...@@ -272,6 +272,33 @@ class SlapTool(BaseTool): ...@@ -272,6 +272,33 @@ class SlapTool(BaseTool):
self._getSlapPartitionByPackingList(_assertACI(computer_partition.getObject()))) self._getSlapPartitionByPackingList(_assertACI(computer_partition.getObject())))
return xml_marshaller.xml_marshaller.dumps(slap_computer) return xml_marshaller.xml_marshaller.dumps(slap_computer)
@UnrestrictedMethod
def _getHostingSubscriptionIpList(self, computer_id, computer_partition_id):
software_instance = self._getSoftwareInstanceForComputerPartition(
computer_id, computer_partition_id)
if software_instance is None or \
software_instance.getSlapState() == 'destroy_requested':
return xml_marshaller.xml_marshaller.dumps([])
# Search hosting subscription
hosting = software_instance.getSpecialiseValue()
while hosting and hosting.getPortalType() != "Hosting Subscription":
hosting = hosting.getSpecialiseValue()
ip_address_list = []
for instance in hosting.getSpecialiseRelatedValueList(
portal_type="Software Instance"):
computer_partition = instance.getAggregateValue(portal_type="Computer Partition")
if not computer_partition:
continue
for internet_protocol_address in computer_partition.contentValues(
portal_type='Internet Protocol Address'):
ip_address_list.append(
(internet_protocol_address.getNetworkInterface('').decode("UTF-8"),
internet_protocol_address.getIpAddress().decode("UTF-8"))
)
return xml_marshaller.xml_marshaller.dumps(ip_address_list)
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
'getFullComputerInformation') 'getFullComputerInformation')
def getFullComputerInformation(self, computer_id): def getFullComputerInformation(self, computer_id):
...@@ -298,6 +325,28 @@ class SlapTool(BaseTool): ...@@ -298,6 +325,28 @@ class SlapTool(BaseTool):
else: else:
return result return result
security.declareProtected(Permissions.AccessContentsInformation,
'getHostingSubscriptionIpList')
def getHostingSubscriptionIpList(self, computer_id, computer_partition_id):
"""
Search and return all Computer Partition IP address related to one
Hosting Subscription
"""
result = self._getHostingSubscriptionIpList(computer_id,
computer_partition_id)
if self.REQUEST.response.getStatus() == 200:
# Keep in cache server for 7 days
self.REQUEST.response.setHeader('Cache-Control',
'public, max-age=1, stale-if-error=604800')
self.REQUEST.response.setHeader('Vary',
'REMOTE_USER')
self.REQUEST.response.setHeader('Last-Modified', rfc1123_date(DateTime()))
self.REQUEST.response.setBody(result)
return self.REQUEST.response
else:
return result
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
'getComputerPartitionCertificate') 'getComputerPartitionCertificate')
def getComputerPartitionCertificate(self, computer_id, computer_partition_id): def getComputerPartitionCertificate(self, computer_id, computer_partition_id):
......
...@@ -40,6 +40,7 @@ import time ...@@ -40,6 +40,7 @@ import time
import traceback import traceback
import warnings import warnings
import logging import logging
import json
if sys.version_info < (2, 6): if sys.version_info < (2, 6):
warnings.warn('Used python version (%s) is old and has problems with' warnings.warn('Used python version (%s) is old and has problems with'
...@@ -56,9 +57,10 @@ from slapos.grid.svcbackend import (launchSupervisord, ...@@ -56,9 +57,10 @@ from slapos.grid.svcbackend import (launchSupervisord,
createSupervisordConfiguration, createSupervisordConfiguration,
_getSupervisordConfigurationDirectory, _getSupervisordConfigurationDirectory,
_getSupervisordSocketPath) _getSupervisordSocketPath)
from slapos.grid.utils import (md5digest, dropPrivileges, SlapPopen) from slapos.grid.utils import (md5digest, dropPrivileges, SlapPopen, updateFile)
from slapos.human import human2bytes from slapos.human import human2bytes
import slapos.slap import slapos.slap
from netaddr import valid_ipv4, valid_ipv6
# XXX: should be moved to SLAP library # XXX: should be moved to SLAP library
...@@ -166,6 +168,22 @@ def merged_options(args, configp): ...@@ -166,6 +168,22 @@ def merged_options(args, configp):
url.strip() for url in options.get( url.strip() for url in options.get(
"upload-to-binary-cache-url-blacklist", "").split('\n') if url] "upload-to-binary-cache-url-blacklist", "").split('\n') if url]
options['firewall'] = {}
if configp.has_section('firewall'):
options['firewall'] = dict(configp.items('firewall'))
options['firewall']["authorized_sources"] = [
source.strip() for source in options['firewall'].get(
"authorized_sources", "").split('\n') if source]
options['firewall']['firewall_cmd'] = options['firewall'].get(
"firewall_cmd", "firewall-cmd")
options['firewall']['firewall_executable'] = options['firewall'].get(
"firewall_executable", "")
options['firewall']['dbus_executable'] = options['firewall'].get(
"dbus_executable", "")
options['firewall']['reload_config_cmd'] = options['firewall'].get(
"reload_config_cmd",
"slapos node restart firewall")
return options return options
...@@ -240,7 +258,8 @@ def create_slapgrid_object(options, logger): ...@@ -240,7 +258,8 @@ def create_slapgrid_object(options, logger):
software_min_free_space=software_min_free_space, software_min_free_space=software_min_free_space,
instance_min_free_space=instance_min_free_space, instance_min_free_space=instance_min_free_space,
instance_storage_home=op.get('instance_storage_home'), instance_storage_home=op.get('instance_storage_home'),
ipv4_global_network=op.get('ipv4_global_network')) ipv4_global_network=op.get('ipv4_global_network'),
firewall_conf=op.get('firewall'))
def check_required_only_partitions(existing, required): def check_required_only_partitions(existing, required):
...@@ -298,6 +317,7 @@ class Slapgrid(object): ...@@ -298,6 +317,7 @@ class Slapgrid(object):
instance_min_free_space=None, instance_min_free_space=None,
instance_storage_home=None, instance_storage_home=None,
ipv4_global_network=None, ipv4_global_network=None,
firewall_conf={},
): ):
"""Makes easy initialisation of class parameters""" """Makes easy initialisation of class parameters"""
# Parses arguments # Parses arguments
...@@ -359,6 +379,8 @@ class Slapgrid(object): ...@@ -359,6 +379,8 @@ class Slapgrid(object):
self.ipv4_global_network = ipv4_global_network self.ipv4_global_network = ipv4_global_network
else: else:
self.ipv4_global_network= "" self.ipv4_global_network= ""
self.firewall_conf = firewall_conf
def _getWatchdogLine(self): def _getWatchdogLine(self):
invocation_list = [WATCHDOG_PATH] invocation_list = [WATCHDOG_PATH]
...@@ -370,6 +392,93 @@ class Slapgrid(object): ...@@ -370,6 +392,93 @@ class Slapgrid(object):
invocation_list.append("--instance-root '%s'" % self.instance_root) invocation_list.append("--instance-root '%s'" % self.instance_root)
return ' '.join(invocation_list) return ' '.join(invocation_list)
def _generateFirewallSupervisorConf(self):
"""If firewall section is defined in slapos configuration, generate
supervisor configuration entry for firewall process.
"""
supervisord_conf_folder_path = os.path.join(self.instance_root,
'etc', 'supervisord.conf.d')
supervisord_firewall_conf = os.path.join(supervisord_conf_folder_path,
'firewall.conf')
if not self.firewall_conf or not self.firewall_conf.get('firewall_executable') \
or self.firewall_conf.get('testing', False):
if os.path.exists(supervisord_firewall_conf):
os.unlink(supervisord_firewall_conf)
return
supervisord_firewall_program_conf = """\
[program:firewall]
directory=/opt/slapos
command=%(firewall_executable)s
process_name=firewall
priority=5
autostart=true
autorestart=true
startsecs=0
startretries=0
exitcodes=0
stopsignal=TERM
stopwaitsecs=60
user=0
group=0
serverurl=AUTO
redirect_stderr=true
stdout_logfile=%(log_file)s
stdout_logfile_maxbytes=100KB
stdout_logfile_backups=1
stderr_logfile=%(log_file)s
stderr_logfile_maxbytes=100KB
stderr_logfile_backups=1
""" % {'firewall_executable': self.firewall_conf['firewall_executable'],
'log_file': self.firewall_conf.get('log_file', '/var/log/firewall.log')}
if not os.path.exists(supervisord_conf_folder_path):
os.makedirs(supervisord_conf_folder_path)
updateFile(supervisord_firewall_conf, supervisord_firewall_program_conf)
def _generateDbusSupervisorConf(self):
"""If dbus command is defined in slapos configuration, generate
supervisor configuration entry for dbus daemon.
"""
supervisord_conf_folder_path = os.path.join(self.instance_root,
'etc', 'supervisord.conf.d')
supervisord_dbus_conf = os.path.join(supervisord_conf_folder_path,
'dbus.conf')
if not self.firewall_conf or not self.firewall_conf.get('dbus_executable') \
or self.firewall_conf.get('testing', False):
if os.path.exists(supervisord_dbus_conf):
os.unlink(supervisord_dbus_conf)
return
supervisord_dbus_program_conf = """\
[program:dbus]
directory=/opt/slapos
command=%(dbus_executable)s
process_name=dbus
priority=1
autostart=true
autorestart=true
startsecs=0
startretries=0
exitcodes=0
stopsignal=TERM
stopwaitsecs=60
user=0
group=0
serverurl=AUTO
redirect_stderr=true
stdout_logfile=%(dbus_log_file)s
stdout_logfile_maxbytes=100KB
stdout_logfile_backups=1
stderr_logfile=%(dbus_log_file)s
stderr_logfile_maxbytes=100KB
stderr_logfile_backups=1
""" % {'dbus_executable': self.firewall_conf['dbus_executable'],
'dbus_log_file': self.firewall_conf.get('dbus_log_file', '/var/log/dbus.log')}
if not os.path.exists(supervisord_conf_folder_path):
os.makedirs(supervisord_conf_folder_path)
updateFile(supervisord_dbus_conf, supervisord_dbus_program_conf)
def checkEnvironmentAndCreateStructure(self): def checkEnvironmentAndCreateStructure(self):
"""Checks for software_root and instance_root existence, then creates """Checks for software_root and instance_root existence, then creates
needed files and directories. needed files and directories.
...@@ -379,6 +488,8 @@ class Slapgrid(object): ...@@ -379,6 +488,8 @@ class Slapgrid(object):
raise OSError('%s does not exist.' % self.software_root) raise OSError('%s does not exist.' % self.software_root)
createSupervisordConfiguration(self.instance_root, self._getWatchdogLine()) createSupervisordConfiguration(self.instance_root, self._getWatchdogLine())
self._generateFirewallSupervisorConf()
self._generateDbusSupervisorConf()
def _launchSupervisord(self): def _launchSupervisord(self):
if not self.forbid_supervisord_automatic_launch: if not self.forbid_supervisord_automatic_launch:
...@@ -543,6 +654,168 @@ class Slapgrid(object): ...@@ -543,6 +654,168 @@ class Slapgrid(object):
if not promise_present: if not promise_present:
self.logger.info("No promise.") self.logger.info("No promise.")
def _checkAddFirewallRules(self, partition_id, command_list, add=True):
"""
"""
instance_path = os.path.join(self.instance_root, partition_id)
firewall_rules = os.path.join(instance_path, '.slapos-firewalld-rules')
json_list = []
reload_rules = False
if os.path.exists(firewall_rules):
with open(firewall_rules, 'r') as frules:
rules_list = json.loads(frules.read())
for command in rules_list:
skip_check = False
if add:
for i in range(0, len(command_list)):
new_cmd = command_list[i]
if command == new_cmd:
json_list.append(command_list.pop(i))
skip_check = True
break
# Only if add==True, do not try to remove the rule
if skip_check:
continue
# Check if this rule exists in iptables
check_cmd = command.replace('--add-rule', '--query-rule')
process = subprocess.Popen(check_cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True)
check_result = process.communicate()[0]
self.logger.debug('%s: %s' % (check_cmd, check_result))
if check_result.strip() == 'yes':
reload_rules = True
command = command.replace('--add-rule', '--remove-rule')
self.logger.debug(command)
cmd_process = subprocess.Popen(command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True)
result = cmd_process.communicate()[0]
if cmd_process.returncode == 1:
raise Exception("Failed to remove firewalld rule %s. \n%s" % (
command, result))
if add:
for i in range(0, len(command_list)):
reload_rules = True
command = command_list.pop()
self.logger.debug(command)
cmd_process = subprocess.Popen(command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True)
result = cmd_process.communicate()[0]
if cmd_process.returncode == 1:
raise Exception("Failed to add firewalld rule %s. \n%s" % (
command, result))
json_list.append(command)
if reload_rules:
# Apply changes: reload configuration
# XXX - need to check firewalld reload instead of restart
self.logger.info("Reloading firewall configuration...")
reload_cmd = self.firewall_conf['reload_config_cmd']
reload_process = subprocess.Popen(reload_cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True)
result = reload_process.communicate()[0]
if reload_process.returncode == 1:
self.logger.error('FirewallD Reload: %s' % result)
raise Exception("Failed to load firewalld rules with command %s" % reload_cmd)
with open(firewall_rules, 'w') as frules:
frules.write(json.dumps(json_list))
def _getFirewallRules(self, ip, ip_list, ip_type='ipv4'):
"""
"""
if ip_type not in ['ipv4', 'ipv6', 'eb']:
raise NotImplementedError("firewall-cmd has not rules with tables %s." % ip_type)
fw_cmd = self.firewall_conf['firewall_cmd']
command = '%s --permanent --direct --add-rule %s filter' % (fw_cmd, ip_type)
cmd_list = []
for other_ip in ip_list:
# Configure INPUT rules
cmd_list.append('%s INPUT 0 -s %s -d %s -j ACCEPT' % (command,
other_ip, ip))
# Configure FORWARD rules
cmd_list.append('%s FORWARD 0 -s %s -d %s -j ACCEPT' % (command,
other_ip, ip))
# Drop all other requests
cmd_list.append('%s INPUT 1000 -d %s -j DROP' % (command, ip))
cmd_list.append('%s FORWARD 1000 -d %s -j DROP' % (command, ip))
cmd_list.append('%s INPUT 900 -d %s -m state --state ESTABLISHED,RELATED -j DROP' % (
command, ip))
cmd_list.append('%s FORWARD 900 -d %s -m state --state ESTABLISHED,RELATED -j DROP' % (
command, ip))
return cmd_list
def _setupComputerPartitionFirewall(self, computer_partition, ip_list, authorized_ip_list, drop_entries=False):
"""
Using linux iptables, limit access to IP of this partition to all
others partitions of the same Hosting Subscription
"""
ipv4_list = []
ipv6_list = []
authorized_ipv4_list = []
authorized_ipv6_list = []
for net_ip in ip_list:
iface, ip = (net_ip[0], net_ip[1])
if not iface.startswith('route_'):
continue
if valid_ipv4(ip):
ipv4_list.append(ip)
elif valid_ipv6(ip):
ipv6_list.append(ip)
for iface, ip in authorized_ip_list:
if valid_ipv4(ip):
if not ip in ipv4_list:
authorized_ipv4_list.append(ip)
elif valid_ipv6(ip):
if not ip in ipv6_list:
authorized_ipv6_list.append(ip)
filter_dict = getattr(computer_partition, '_filter_dict', None)
extra_list = []
if filter_dict is not None:
extra_list = filter_dict.get('authorized_sources', '').split(' ')
extra_list.extend(self.firewall_conf.get('authorized_sources', []))
for ip in extra_list:
if not ip:
continue
the_ip = ip.split('/')[0]
if valid_ipv4(the_ip):
authorized_ipv4_list.append(ip)
elif valid_ipv6(the_ip):
authorized_ipv6_list.append(ip)
if not drop_entries:
self.logger.info("Configuring firewall...")
add_rules = True
else:
add_rules = False
self.logger.info("Removing firewall configuration...")
for ip in ipv4_list:
cmd_list = self._getFirewallRules(ip,
authorized_ipv4_list,
ip_type='ipv4')
self._checkAddFirewallRules(computer_partition.getId(), cmd_list,
add=add_rules)
def processComputerPartition(self, computer_partition): def processComputerPartition(self, computer_partition):
""" """
Process a Computer Partition, depending on its state Process a Computer Partition, depending on its state
...@@ -677,10 +950,20 @@ class Slapgrid(object): ...@@ -677,10 +950,20 @@ class Slapgrid(object):
# self.logger.info(' Instance type: %s' % computer_partition.getType()) # self.logger.info(' Instance type: %s' % computer_partition.getType())
self.logger.info(' Instance status: %s' % computer_partition_state) self.logger.info(' Instance status: %s' % computer_partition_state)
partition_ip_list = full_hosting_ip_list = []
if self.firewall_conf:
partition_ip_list = parameter_dict['ip_list'] + parameter_dict.get(
'full_ip_list', [])
full_hosting_ip_list = computer_partition.getFullHostingIpAddressList()
if computer_partition_state == COMPUTER_PARTITION_STARTED_STATE: if computer_partition_state == COMPUTER_PARTITION_STARTED_STATE:
local_partition.install() local_partition.install()
computer_partition.available() computer_partition.available()
local_partition.start() local_partition.start()
if self.firewall_conf:
self._setupComputerPartitionFirewall(computer_partition,
partition_ip_list,
full_hosting_ip_list)
self._checkPromises(computer_partition) self._checkPromises(computer_partition)
computer_partition.started() computer_partition.started()
elif computer_partition_state == COMPUTER_PARTITION_STOPPED_STATE: elif computer_partition_state == COMPUTER_PARTITION_STOPPED_STATE:
...@@ -689,12 +972,21 @@ class Slapgrid(object): ...@@ -689,12 +972,21 @@ class Slapgrid(object):
# propagate the state to children if any. # propagate the state to children if any.
local_partition.install() local_partition.install()
computer_partition.available() computer_partition.available()
if self.firewall_conf:
self._setupComputerPartitionFirewall(computer_partition,
partition_ip_list,
full_hosting_ip_list)
finally: finally:
# Instance has to be stopped even if buildout/reporting is wrong. # Instance has to be stopped even if buildout/reporting is wrong.
local_partition.stop() local_partition.stop()
computer_partition.stopped() computer_partition.stopped()
elif computer_partition_state == COMPUTER_PARTITION_DESTROYED_STATE: elif computer_partition_state == COMPUTER_PARTITION_DESTROYED_STATE:
local_partition.stop() local_partition.stop()
if self.firewall_conf:
self._setupComputerPartitionFirewall(computer_partition,
partition_ip_list,
full_hosting_ip_list,
drop_entries=True)
try: try:
computer_partition.stopped() computer_partition.stopped()
except (SystemExit, KeyboardInterrupt): except (SystemExit, KeyboardInterrupt):
......
...@@ -331,6 +331,12 @@ class IComputerPartition(IBuildoutController, IRequester): ...@@ -331,6 +331,12 @@ class IComputerPartition(IBuildoutController, IRequester):
text -- message log of the status text -- message log of the status
""" """
def getFullHostingIpAddressList():
"""
Returns a dictionnary containing the latest status of the
computer partition.
"""
class IComputer(Interface): class IComputer(Interface):
""" """
Computer interface specification Computer interface specification
......
...@@ -607,6 +607,15 @@ class ComputerPartition(SlapRequester): ...@@ -607,6 +607,15 @@ class ComputerPartition(SlapRequester):
) )
return xml_marshaller.loads(xml) return xml_marshaller.loads(xml)
def getFullHostingIpAddressList(self):
xml = self._connection_helper.GET('getHostingSubscriptionIpList',
params={
'computer_id': self._computer_id,
'computer_partition_id': self._partition_id,
}
)
return xml_marshaller.loads(xml)
def _addIpv6Brackets(url): def _addIpv6Brackets(url):
# if master_url contains an ipv6 without bracket, add it # if master_url contains an ipv6 without bracket, add it
# Note that this is mostly to limit specific issues with # Note that this is mostly to limit specific issues with
......
...@@ -39,6 +39,7 @@ import textwrap ...@@ -39,6 +39,7 @@ import textwrap
import time import time
import unittest import unittest
import urlparse import urlparse
import json
import xml_marshaller import xml_marshaller
from mock import patch from mock import patch
...@@ -283,6 +284,11 @@ class ComputerForTest(object): ...@@ -283,6 +284,11 @@ class ComputerForTest(object):
self.software_amount = software_amount self.software_amount = software_amount
self.software_root = software_root self.software_root = software_root
self.instance_root = instance_root self.instance_root = instance_root
self.ip_address_list = [
('interface1', '10.0.8.3'),
('interface2', '10.0.8.4'),
('route_interface1', '10.10.8.4')
]
if not os.path.isdir(self.instance_root): if not os.path.isdir(self.instance_root):
os.mkdir(self.instance_root) os.mkdir(self.instance_root)
if not os.path.isdir(self.software_root): if not os.path.isdir(self.software_root):
...@@ -309,6 +315,12 @@ class ComputerForTest(object): ...@@ -309,6 +315,12 @@ class ComputerForTest(object):
'status_code': 200, 'status_code': 200,
'content': xml_marshaller.xml_marshaller.dumps(slap_computer) 'content': xml_marshaller.xml_marshaller.dumps(slap_computer)
} }
elif url.path == '/getHostingSubscriptionIpList':
ip_address_list = self.ip_address_list
return {
'status_code': 200,
'content': xml_marshaller.xml_marshaller.dumps(ip_address_list)
}
if req.method == 'POST' and 'computer_partition_id' in qs: if req.method == 'POST' and 'computer_partition_id' in qs:
instance = self.instance_list[int(qs['computer_partition_id'][0])] instance = self.instance_list[int(qs['computer_partition_id'][0])]
instance.sequence.append(url.path) instance.sequence.append(url.path)
...@@ -417,8 +429,11 @@ class InstanceForTest(object): ...@@ -417,8 +429,11 @@ class InstanceForTest(object):
self.partition_path = os.path.join(self.instance_root, self.name) self.partition_path = os.path.join(self.instance_root, self.name)
os.mkdir(self.partition_path, 0o750) os.mkdir(self.partition_path, 0o750)
self.timestamp = None self.timestamp = None
self.ip_list = [('interface0', '10.0.8.2')]
self.full_ip_list = [('route_interface0', '10.10.2.3', '10.10.0.1',
'255.0.0.0', '10.0.0.0')]
def getInstance(self, computer_id): def getInstance(self, computer_id, ):
""" """
Will return current requested state of instance Will return current requested state of instance
""" """
...@@ -427,9 +442,13 @@ class InstanceForTest(object): ...@@ -427,9 +442,13 @@ class InstanceForTest(object):
partition._requested_state = self.requested_state partition._requested_state = self.requested_state
if getattr(self, 'filter_dict', None): if getattr(self, 'filter_dict', None):
partition._filter_dict = self.filter_dict partition._filter_dict = self.filter_dict
partition._parameter_dict = {'ip_list': self.ip_list,
'full_ip_list': self.full_ip_list
}
if self.software is not None: if self.software is not None:
if self.timestamp is not None: if self.timestamp is not None:
partition._parameter_dict = {'timestamp': self.timestamp} partition._parameter_dict['timestamp'] = self.timestamp
return partition return partition
def getSoftwareRelease(self): def getSoftwareRelease(self):
...@@ -1952,3 +1971,190 @@ class TestSlapgridDestructionLock(MasterMixin, unittest.TestCase): ...@@ -1952,3 +1971,190 @@ class TestSlapgridDestructionLock(MasterMixin, unittest.TestCase):
self.grid.agregateAndSendUsage() self.grid.agregateAndSendUsage()
self.assertFalse(os.path.exists(dummy_instance_file_path)) self.assertFalse(os.path.exists(dummy_instance_file_path))
class TestSlapgridCPWithFirewall(MasterMixin, unittest.TestCase):
def setFirewallConfig(self, source_ip=""):
firewall_conf= dict(
authorized_sources=source_ip,
firewall_cmd='/bin/echo',
firewall_executable='/bin/echo "service firewall started"',
reload_config_cmd='/bin/echo "Config reloaded."',
log_file='fw-log.log',
testing=True,
)
self.grid.firewall_conf = firewall_conf
def checkRuleFromIpSource(self, ip, cmd_list):
# XXX - rules for one ip contain 2*len(ip_address_list) rules ACCEPT and 4 rules DROP
num_rules = len(self.ip_address_list) * 2 + 4
self.assertEqual(len(cmd_list), num_rules)
base_cmd = '%s --permanent --direct --add-rule ipv4 filter' % self.grid.firewall_conf['firewall_cmd']
# Check that there is DROP rule on INPUT
rule = '%s INPUT 1000 -d %s -j DROP' % (base_cmd, ip)
self.assertIn(rule, cmd_list)
# Check that there is DROP rule on FORWARD
rule = '%s FORWARD 1000 -d %s -j DROP' % (base_cmd, ip)
self.assertIn(rule, cmd_list)
# Check that there is DROP rule on INPUT, ESTABLISHED,RELATED
rule = '%s INPUT 900 -d %s -m state --state ESTABLISHED,RELATED -j DROP' % (base_cmd, ip)
self.assertIn(rule, cmd_list)
# Check that there is DROP rule on FORWARD, ESTABLISHED,RELATED
rule = '%s FORWARD 900 -d %s -m state --state ESTABLISHED,RELATED -j DROP' % (base_cmd, ip)
self.assertIn(rule, cmd_list)
# Check that there is INPUT ACCEPT on ip_list
for _, other_ip in self.ip_address_list:
rule = '%s INPUT 0 -s %s -d %s -j ACCEPT' % (base_cmd, other_ip, ip)
self.assertIn(rule, cmd_list)
# Check that there is FORWARD ACCEPT on ip_list
for _, other_ip in self.ip_address_list:
rule = '%s FORWARD 0 -s %s -d %s -j ACCEPT' % (base_cmd, other_ip, ip)
self.assertIn(rule, cmd_list)
def test_getFirewallRules(self):
computer = ComputerForTest(self.software_root, self.instance_root)
self.setFirewallConfig()
self.ip_address_list = computer.ip_address_list
ip = computer.instance_list[0].full_ip_list[0][1]
cmd_list = self.grid._getFirewallRules(ip,
[elt[1] for elt in self.ip_address_list],
ip_type='ipv4')
self.checkRuleFromIpSource(ip, cmd_list)
def test_checkAddFirewallRules(self):
computer = ComputerForTest(self.software_root, self.instance_root)
self.setFirewallConfig()
self.grid.firewall_conf['firewall_cmd'] = '/bin/echo "yes" #'
self.ip_address_list = computer.ip_address_list
instance = computer.instance_list[0]
ip = instance.full_ip_list[0][1]
name = computer.instance_list[0].name
cmd_list = self.grid._getFirewallRules(ip,
[elt[1] for elt in self.ip_address_list],
ip_type='ipv4')
self.grid._checkAddFirewallRules(name, cmd_list, add=True)
rules_path = os.path.join(instance.partition_path,
'.slapos-firewalld-rules')
with open(rules_path, 'r') as frules:
rules_list = json.loads(frules.read())
self.checkRuleFromIpSource(ip, rules_list)
# Remove all rules
self.grid._checkAddFirewallRules(name, cmd_list, add=False)
with open(rules_path, 'r') as frules:
rules_list = json.loads(frules.read())
self.assertEqual(rules_list, [])
# Add one more ip in the authorized list
self.ip_address_list.append(('interface1', '10.0.8.7'))
cmd_list = self.grid._getFirewallRules(ip,
[elt[1] for elt in self.ip_address_list],
ip_type='ipv4')
self.grid._checkAddFirewallRules(name, cmd_list, add=True)
with open(rules_path, 'r') as frules:
rules_list = json.loads(frules.read())
self.checkRuleFromIpSource(ip, rules_list)
def test_partition_no_firewall(self):
computer = ComputerForTest(self.software_root, self.instance_root)
with httmock.HTTMock(computer.request_handler):
instance = computer.instance_list[0]
self.assertEqual(self.grid.processComputerPartitionList(),
slapgrid.SLAPGRID_SUCCESS)
self.assertFalse(os.path.exists(os.path.join(
instance.partition_path,
'.slapos-firewalld-rules'
)))
def test_partition_firewall(self):
computer = ComputerForTest(self.software_root, self.instance_root)
self.setFirewallConfig()
with httmock.HTTMock(computer.request_handler):
instance = computer.instance_list[0]
self.assertEqual(self.grid.processComputerPartitionList(), slapgrid.SLAPGRID_SUCCESS)
self.assertTrue(os.path.exists(os.path.join(
instance.partition_path,
'.slapos-firewalld-rules'
)))
rules_path = os.path.join(instance.partition_path,
'.slapos-firewalld-rules')
self.ip_address_list = computer.ip_address_list
with open(rules_path, 'r') as frules:
rules_list = json.loads(frules.read())
self.assertEqual(len(rules_list), len(self.ip_address_list) * 2 + 4)
ip = instance.full_ip_list[0][1]
self.checkRuleFromIpSource(ip, rules_list)
def test_partition_firewall_ipsource(self):
computer = ComputerForTest(self.software_root, self.instance_root)
self.setFirewallConfig()
source_ip = ['10.0.8.10']
self.grid.firewall_conf['authorized_sources'] = source_ip
with httmock.HTTMock(computer.request_handler):
instance = computer.instance_list[0]
self.assertEqual(self.grid.processComputerPartitionList(), slapgrid.SLAPGRID_SUCCESS)
self.assertTrue(os.path.exists(os.path.join(
instance.partition_path,
'.slapos-firewalld-rules'
)))
rules_path = os.path.join(instance.partition_path,
'.slapos-firewalld-rules')
rules_list= []
self.ip_address_list = computer.ip_address_list + [('iface', ip)
for ip in source_ip]
ip = instance.full_ip_list[0][1]
base_cmd = '%s --permanent --direct --add-rule ipv4 filter' % self.grid.firewall_conf['firewall_cmd']
with open(rules_path, 'r') as frules:
rules_list = json.loads(frules.read())
self.assertEqual(len(rules_list), len(self.ip_address_list) * 2 + 4)
rule_input = '%s INPUT 0 -s %s -d %s -j ACCEPT' % (base_cmd, source_ip[0], ip)
self.assertIn(rule_input, rules_list)
rule_fwd = '%s FORWARD 0 -s %s -d %s -j ACCEPT' % (base_cmd, source_ip[0], ip)
self.assertIn(rule_fwd, rules_list)
self.checkRuleFromIpSource(ip, rules_list)
def test_partition_firewall_ip_parameter(self):
computer = ComputerForTest(self.software_root, self.instance_root)
self.setFirewallConfig()
source_ip = '10.0.8.10'
with httmock.HTTMock(computer.request_handler):
instance = computer.instance_list[0]
instance.filter_dict = {'authorized_sources': source_ip}
self.assertEqual(self.grid.processComputerPartitionList(), slapgrid.SLAPGRID_SUCCESS)
self.assertTrue(os.path.exists(os.path.join(
instance.partition_path,
'.slapos-firewalld-rules'
)))
rules_path = os.path.join(instance.partition_path,
'.slapos-firewalld-rules')
rules_list= []
self.ip_address_list = computer.ip_address_list + [('iface', ip)
for ip in source_ip.split(' ')]
ip = instance.full_ip_list[0][1]
base_cmd = '%s --permanent --direct --add-rule ipv4 filter' % self.grid.firewall_conf['firewall_cmd']
with open(rules_path, 'r') as frules:
rules_list = json.loads(frules.read())
self.assertEqual(len(rules_list), len(self.ip_address_list) * 2 + 4)
rule_input = '%s INPUT 0 -s %s -d %s -j ACCEPT' % (base_cmd, source_ip, ip)
self.assertIn(rule_input, rules_list)
rule_fwd = '%s FORWARD 0 -s %s -d %s -j ACCEPT' % (base_cmd, source_ip, ip)
self.assertIn(rule_fwd, rules_list)
self.checkRuleFromIpSource(ip, rules_list)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment