Skip to content

Commit

Permalink
ipatests: Mark firewalld commands as no-op on non-firewalld distros
Browse files Browse the repository at this point in the history
The FreeIPA integration tests strictly require Firewalld.
But not all the distros have such or any other high-level tool
for managing a firewall. Thus, to run integration tests on such systems
NoOpFirewall class has been added, which provides no-op firewalld
commands.

Fixes: https://pagure.io/freeipa/issue/8261
Signed-off-by: Stanislav Levin <slev@altlinux.org>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: François Cami <fcami@redhat.com>
  • Loading branch information
stanislavlevin authored and fcami committed Apr 8, 2020
1 parent 3985183 commit ba162b9
Showing 1 changed file with 158 additions and 3 deletions.
161 changes: 158 additions & 3 deletions ipatests/pytest_ipa/integration/firewall.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,115 @@

"""Firewall class for integration testing using firewalld"""

import abc

from ipapython import ipautil


class Firewall:
class FirewallBase(abc.ABC):
def __init__(self, host):
"""Initialize with host where firewall changes should be applied"""

@abc.abstractmethod
def run(self):
"""Enable and start firewall service"""

@abc.abstractmethod
def enable_service(self, service):
"""Enable firewall rules for service"""

@abc.abstractmethod
def disable_service(self, service):
"""Disable firewall rules for service"""

@abc.abstractmethod
def enable_services(self, services):
"""Enable firewall rules for list of services"""

@abc.abstractmethod
def disable_services(self, services):
"""Disable firewall rules for list of services"""

@abc.abstractmethod
def passthrough_rule(self, rule, ipv=None):
"""Generic method to get direct passthrough rules to
rule is an ip[6]tables rule without using the ip[6]tables command.
The rule will per default be added to the IPv4 and IPv6 firewall.
If there are IP version specific parts in the rule, please make sure
that ipv is adapted properly.
The rule is added to the direct sub chain of the chain that is used
in the rule"""

@abc.abstractmethod
def add_passthrough_rules(self, rules, ipv=None):
"""Add passthough rules to the end of the chain
rules is a list of ip[6]tables rules, where the first entry of each
rule is the chain. No --append/-A, --delete/-D should be added before
the chain name, beacuse these are added by the method.
If there are IP version specific parts in the rule, please make sure
that ipv is adapted properly.
"""

@abc.abstractmethod
def prepend_passthrough_rules(self, rules, ipv=None):
"""Insert passthough rules starting at position 1 as a block
rules is a list of ip[6]tables rules, where the first entry of each
rule is the chain. No --append/-A, --delete/-D should be added before
the chain name, beacuse these are added by the method.
If there are IP version specific parts in the rule, please make sure
that ipv is adapted properly.
"""

@abc.abstractmethod
def remove_passthrough_rules(self, rules, ipv=None):
"""Remove passthrough rules
rules is a list of ip[6]tables rules, where the first entry of each
rule is the chain. No --append/-A, --delete/-D should be added before
the chain name, beacuse these are added by the method.
If there are IP version specific parts in the rule, please make sure
that ipv is adapted properly.
"""


class NoOpFirewall(FirewallBase):
"""
no-op firewall is intended for platforms which haven't high level firewall
backend.
"""
def run(self):
pass

def enable_service(self, service):
pass

def disable_service(self, service):
pass

def enable_services(self, services):
pass

def disable_services(self, services):
pass

def passthrough_rule(self, rule, ipv=None):
pass

def add_passthrough_rules(self, rules, ipv=None):
pass

def prepend_passthrough_rules(self, rules, ipv=None):
pass

def remove_passthrough_rules(self, rules, ipv=None):
pass


class FirewallD(FirewallBase):
def __init__(self, host):
"""Initialize with host where firewall changes should be applied
Unmasks, enables and starts firewalld."""
"""Initialize with host where firewall changes should be applied"""
self.host = host

def run(self):
# Unmask firewalld service
self.host.run_command(["systemctl", "unmask", "firewalld"])
# Enable firewalld service
Expand Down Expand Up @@ -120,3 +221,57 @@ def remove_passthrough_rules(self, rules, ipv=None):
"""
for rule in rules:
self.passthrough_rule(["-D"] + rule, ipv)


class Firewall(FirewallBase):
"""
Depending on the ipaplatform proxy firewall tasks to the actual backend.
Current supported backends: firewalld and no-op firewall.
"""
def __init__(self, host):
"""Initialize with host where firewall changes should be applied"""
# break circular dependency
from .tasks import get_platform

self.host = host
platform = get_platform(host)

firewalls = {
'rhel': FirewallD,
'fedora': FirewallD,
'debian': FirewallD,
'ubuntu': FirewallD,
'altlinux': NoOpFirewall,
}
if platform not in firewalls:
raise ValueError(
"Platform {} doesn't support Firewall".format(platform))
self.firewall = firewalls[platform](self.host)
self.run()

def run(self):
self.firewall.run()

def enable_service(self, service):
self.firewall.enable_service(service)

def disable_service(self, service):
self.firewall.disable_service(service)

def enable_services(self, services):
self.firewall.enable_services(services)

def disable_services(self, services):
self.firewall.disable_services(services)

def passthrough_rule(self, rule, ipv=None):
self.firewall.passthrough_rule(rule, ipv)

def add_passthrough_rules(self, rules, ipv=None):
self.firewall.add_passthrough_rules(rules, ipv)

def prepend_passthrough_rules(self, rules, ipv=None):
self.firewall.prepend_passthrough_rules(rules, ipv)

def remove_passthrough_rules(self, rules, ipv=None):
self.firewall.remove_passthrough_rules(rules, ipv)

0 comments on commit ba162b9

Please sign in to comment.