Merge pull request #185 from yarikoptic/_tent/jail.conf

"Debian-style" jail.conf -- lean and nice (Fixes #156) + more testing.
pull/190/merge
Yaroslav Halchenko 2013-04-24 12:10:18 -07:00
commit bddbf1e398
6 changed files with 418 additions and 179 deletions

View File

@ -1,22 +1,31 @@
# Fail2Ban jail specifications file # Fail2Ban jail specifications file
# #
# WARNING: heavily refactored in 0.9.0 release. Please review and
# customize settings for your setup.
#
# Comments: use '#' for comment lines and ';' for inline comments # Comments: use '#' for comment lines and ';' for inline comments
# #
# Changes: in most of the cases you should not modify this # Changes: in most of the cases you should not modify this
# file, but provide customizations in jail.local file, e.g.: # file, but provide customizations in jail.local file,
# or separate .conf files under jail.d/ directory, e.g.:
# #
# [DEFAULT] # [DEFAULT]
# bantime = 3600 # bantime = 3600
# #
# [ssh-iptables] # [sshd]
# enabled = true # enabled = true
# #
# See jail.conf(5) man page for more information
# The DEFAULT allows a global definition of the options. They can be overridden # The DEFAULT allows a global definition of the options. They can be overridden
# in each jail afterwards. # in each jail afterwards.
[DEFAULT] [DEFAULT]
#
# MISCELLANEOUS OPTIONS
#
# "ignoreip" can be an IP address, a CIDR mask or a DNS host. Fail2ban will not # "ignoreip" can be an IP address, a CIDR mask or a DNS host. Fail2ban will not
# ban a host which matches an address in this list. Several addresses can be # ban a host which matches an address in this list. Several addresses can be
# defined using space separator. # defined using space separator.
@ -30,7 +39,7 @@ bantime = 600
findtime = 600 findtime = 600
# "maxretry" is the number of failures before a host get banned. # "maxretry" is the number of failures before a host get banned.
maxretry = 3 maxretry = 5
# "backend" specifies the backend used to get files modification. # "backend" specifies the backend used to get files modification.
# Available options are "pyinotify", "gamin", "polling" and "auto". # Available options are "pyinotify", "gamin", "polling" and "auto".
@ -62,46 +71,122 @@ usedns = warn
# auto: will use the system locale setting # auto: will use the system locale setting
logencoding = auto logencoding = auto
# "enabled" enables the jails.
# By default all jails are disabled, and it should stay this way.
# Enable only relevant to your setup jails in your .local or jail.d/*.conf
#
# true: jail will be enabled and log files will get monitored for changes
# false: jail is not enabled
enabled = false
# This jail corresponds to the standard configuration in Fail2ban 0.6.
# The mail-whois action send a notification e-mail with a whois request
# in the body.
[ssh-iptables] # "filter" defines the filter to use by the jail.
# By default jails have names matching their filter name
#
filter = %(__name__)s
enabled = false
#
# ACTIONS
#
# Some options used for actions
# Destination email address used solely for the interpolations in
# jail.{conf,local} configuration files.
destemail = root@localhost
# E-mail action. Since 0.8.1 Fail2Ban uses sendmail MTA for the
# mailing. Change mta configuration parameter to mail if you want to
# revert to conventional 'mail'.
mta = sendmail
# Default protocol
protocol = tcp
# Specify chain where jumps would need to be added in iptables-* actions
chain = INPUT
# Ports to be banned
# Usually should be overridden in a particular jail
port = 0:65535
#
# Action shortcuts. To be used to define action parameter
# Default banning action (e.g. iptables, iptables-new,
# iptables-multiport, shorewall, etc) It is used to define
# action_* variables. Can be overridden globally or per
# section within jail.local file
banaction = iptables-multiport
# The simplest action to take: ban only
action_ = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
# ban & send an e-mail with whois report to the destemail.
action_mw = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
%(mta)s-whois[name=%(__name__)s, dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"]
# ban & send an e-mail with whois report and relevant log lines
# to the destemail.
action_mwl = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
%(mta)s-whois-lines[name=%(__name__)s, dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s"]
# Choose default action. To change, just override value of 'action' with the
# interpolation to the chosen action shortcut (e.g. action_mw, action_mwl, etc) in jail.local
# globally (section [DEFAULT]) or per specific section
action = %(action_)s
#
# JAILS
#
#
# SSH servers
#
[sshd]
port = ssh
logpath = /var/log/auth.log
/var/log/sshd.log
[sshd-ddos]
port = ssh
logpath = /var/log/auth.log
/var/log/sshd.log
[dropbear]
port = ssh
filter = sshd filter = sshd
action = iptables[name=SSH, port=ssh, protocol=tcp] logpath = /var/log/dropbear
sendmail-whois[name=SSH, dest=you@example.com, sender=fail2ban@example.com]
logpath = /var/log/sshd.log
maxretry = 5
[proftpd-iptables]
enabled = false # Generic filter for PAM. Has to be used with action which bans all
filter = proftpd # ports such as iptables-allports, shorewall
action = iptables[name=ProFTPD, port=ftp, protocol=tcp]
sendmail-whois[name=ProFTPD, dest=you@example.com]
logpath = /var/log/proftpd/proftpd.log
maxretry = 6
# This jail forces the backend to "polling". [pam-generic]
[sasl-iptables] # pam-generic filter can be customized to monitor specific subset of 'tty's
banaction = iptables-allports
logpath = /var/log/auth.log
enabled = false [xinetd-fail]
filter = sasl
backend = polling banaction = iptables-multiport-log
action = iptables[name=sasl, port=smtp, protocol=tcp] logpath = /var/log/daemon.log
sendmail-whois[name=sasl, dest=you@example.com] maxretry = 2
logpath = /var/log/mail.log
# .. custom jails
# Here we use TCP-Wrappers instead of Netfilter/Iptables. "ignoreregex" is # Here we use TCP-Wrappers instead of Netfilter/Iptables. "ignoreregex" is
# used to avoid banning the user "myuser". # used to avoid banning the user "myuser".
[ssh-tcpwrapper] [sshd-tcpwrapper]
enabled = false
filter = sshd filter = sshd
action = hostsdeny action = hostsdeny
sendmail-whois[name=SSH, dest=you@example.com] sendmail-whois[name=SSH, dest=you@example.com]
@ -111,127 +196,74 @@ logpath = /var/log/sshd.log
# Here we use blackhole routes for not requiring any additional kernel support # Here we use blackhole routes for not requiring any additional kernel support
# to store large volumes of banned IPs # to store large volumes of banned IPs
[ssh-route] [sshd-route]
enabled = false
filter = sshd filter = sshd
action = route action = route
logpath = /var/log/sshd.log logpath = /var/log/sshd.log
maxretry = 5
# Here we use a combination of Netfilter/Iptables and IPsets # Here we use a combination of Netfilter/Iptables and IPsets
# for storing large volumes of banned IPs # for storing large volumes of banned IPs
# #
# IPset comes in two versions. See ipset -V for which one to use # IPset comes in two versions. See ipset -V for which one to use
# requires the ipset package and kernel support. # requires the ipset package and kernel support.
[ssh-iptables-ipset4] [sshd-iptables-ipset4]
enabled = false
filter = sshd filter = sshd
action = iptables-ipset-proto4[name=SSH, port=ssh, protocol=tcp] action = iptables-ipset-proto4[name=SSH, port=ssh, protocol=tcp]
logpath = /var/log/sshd.log logpath = /var/log/sshd.log
maxretry = 5
[ssh-iptables-ipset6] [sshd-iptables-ipset6]
enabled = false
filter = sshd filter = sshd
action = iptables-ipset-proto6[name=SSH, port=ssh, protocol=tcp, bantime=600] action = iptables-ipset-proto6[name=SSH, port=ssh, protocol=tcp, bantime=600]
logpath = /var/log/sshd.log logpath = /var/log/sshd.log
maxretry = 5
# This jail demonstrates the use of wildcards in "logpath". # This jail uses ipfw, the standard firewall on FreeBSD. The "ignoreip"
# Moreover, it is possible to give other files on a new line. # option is overridden in this jail. Moreover, the action "mail-whois" defines
# the variable "name" which contains a comma using "". The characters '' are
# valid too.
[apache-tcpwrapper] [sshd-ipfw]
enabled = false filter = sshd
filter = apache-auth action = ipfw[localhost=192.168.0.1]
action = hostsdeny sendmail-whois[name="SSH,IPFW", dest=you@example.com]
logpath = /var/log/auth.log
ignoreip = 168.192.0.1
#
# HTTP servers
#
[apache-auth]
port = http,https
logpath = /var/log/apache*/*error.log logpath = /var/log/apache*/*error.log
/home/www/myhomepage/error.log
maxretry = 6
# The hosts.deny path can be defined with the "file" argument if it is
# not in /etc.
[postfix-tcpwrapper]
enabled = false
filter = postfix
action = hostsdeny[file=/not/a/standard/path/hosts.deny]
sendmail[name=Postfix, dest=you@example.com]
logpath = /var/log/postfix.log
bantime = 300
# Do not ban anybody. Just report information about the remote host.
# A notification is sent at most every 600 seconds (bantime).
[vsftpd-notification]
enabled = false
filter = vsftpd
action = sendmail-whois[name=VSFTPD, dest=you@example.com]
logpath = /var/log/vsftpd.log
maxretry = 5
bantime = 1800
# Same as above but with banning the IP address.
[vsftpd-iptables]
enabled = false
filter = vsftpd
action = iptables[name=VSFTPD, port=ftp, protocol=tcp]
sendmail-whois[name=VSFTPD, dest=you@example.com]
logpath = /var/log/vsftpd.log
maxretry = 5
bantime = 1800
# Ban hosts which agent identifies spammer robots crawling the web # Ban hosts which agent identifies spammer robots crawling the web
# for email addresses. The mail outputs are buffered. # for email addresses. The mail outputs are buffered.
[apache-badbots] [apache-badbots]
enabled = false port = http,https
filter = apache-badbots logpath = /var/log/apache*/*access.log
action = iptables-multiport[name=BadBots, port="http,https"] /var/www/*/logs/access_log
sendmail-buffered[name=BadBots, lines=5, dest=you@example.com]
logpath = /var/www/*/logs/access_log
bantime = 172800 bantime = 172800
maxretry = 1 maxretry = 1
# Use shorewall instead of iptables. [apache-noscript]
[apache-shorewall] port = http,https
logpath = /var/log/apache*/*error.log
maxretry = 6
enabled = false [apache-overflows]
filter = apache-noscript
action = shorewall
sendmail[name=Postfix, dest=you@example.com]
logpath = /var/log/apache2/error_log
# Monitor roundcube server port = http,https
logpath = /var/log/apache*/*error.log
[roundcube-iptables] maxretry = 2
enabled = false
filter = roundcube-auth
action = iptables[name=RoundCube, port="http,https"]
logpath = /var/log/roundcube/userlogins
# Monitor SOGo groupware server
[sogo-iptables]
enabled = false
filter = sogo-auth
port = http, https
# without proxy this would be:
# port = 20000
action = iptables[name=SOGo, port="http,https"]
logpath = /var/log/sogo/sogo.log
# Ban attackers that try to use PHP's URL-fopen() functionality # Ban attackers that try to use PHP's URL-fopen() functionality
# through GET/POST variables. - Experimental, with more than a year # through GET/POST variables. - Experimental, with more than a year
@ -239,53 +271,145 @@ logpath = /var/log/sogo/sogo.log
[php-url-fopen] [php-url-fopen]
enabled = false
port = http,https port = http,https
filter = php-url-fopen
logpath = /var/www/*/logs/access_log logpath = /var/www/*/logs/access_log
maxretry = 1
# A simple PHP-fastcgi jail which works with lighttpd. # A simple PHP-fastcgi jail which works with lighttpd.
# If you run a lighttpd server, then you probably will # If you run a lighttpd server, then you probably will
# find these kinds of messages in your error_log: # find these kinds of messages in your error_log:
# ALERT tried to register forbidden variable GLOBALS # ALERT tried to register forbidden variable GLOBALS
# through GET variables (attacker '1.2.3.4', file '/var/www/default/htdocs/index.php') # through GET variables (attacker '1.2.3.4', file '/var/www/default/htdocs/index.php')
# This jail would block the IP 1.2.3.4.
[lighttpd-fastcgi] [lighttpd-fastcgi]
enabled = false
port = http,https port = http,https
filter = lighttpd-fastcgi
# adapt the following two items as needed
logpath = /var/log/lighttpd/error.log logpath = /var/log/lighttpd/error.log
maxretry = 2
# Same as above for mod_auth # Same as above for mod_auth
# It catches wrong authentications # It catches wrong authentifications
[lighttpd-auth] [lighttpd-auth]
enabled = false
port = http,https port = http,https
filter = lighttpd-auth
# adapt the following two items as needed
logpath = /var/log/lighttpd/error.log logpath = /var/log/lighttpd/error.log
maxretry = 2
# This jail uses ipfw, the standard firewall on FreeBSD. The "ignoreip" [roundcube-auth]
# option is overridden in this jail. Moreover, the action "mail-whois" defines
# the variable "name" which contains a comma using "". The characters '' are
# valid too.
[ssh-ipfw] port = http,https
logpath = /var/log/roundcube/userlogins
enabled = false [sogo-auth]
filter = sshd
action = ipfw[localhost=192.168.0.1] port = http,https
sendmail-whois[name="SSH,IPFW", dest=you@example.com] # without proxy this would be:
# port = 20000
logpath = /var/log/sogo/sogo.log
# ... custom jails
[apache-tcpwrapper]
filter = apache-auth
action = hostsdeny
logpath = /var/log/apache*/*error.log
maxretry = 6
#
# FTP servers
#
[proftpd]
port = ftp,ftp-data,ftps,ftps-data
logpath = /var/log/proftpd/proftpd.log
[pure-ftpd]
port = ftp,ftp-data,ftps,ftps-data
logpath = /var/log/auth.log logpath = /var/log/auth.log
ignoreip = 168.192.0.1 maxretry = 6
[vsftpd]
port = ftp,ftp-data,ftps,ftps-data
logpath = /var/log/vsftpd.log
# or overwrite it in jails.local to be
# logpath = /var/log/auth.log
# if you want to rely on PAM failed login attempts
# vsftpd's failregex should match both of those formats
# Do not ban anybody. Just report information about the remote host.
# A notification is sent at most every 600 seconds (bantime).
[vsftpd-notification]
filter = vsftpd
action = sendmail-whois[name=VSFTPD, dest=you@example.com]
logpath = /var/log/vsftpd.log
maxretry = 5
bantime = 1800
[wuftpd]
port = ftp,ftp-data,ftps,ftps-data
logpath = /var/log/syslog
maxretry = 6
#
# Mail servers
#
[courier-smtp]
port = smtp,ssmtp
logpath = /var/log/mail.log
[postfix]
port = smtp,ssmtp
logpath = /var/log/mail.log
# The hosts.deny path can be defined with the "file" argument if it is
# not in /etc.
[postfix-tcpwrapper]
filter = postfix
action = hostsdeny[file=/not/a/standard/path/hosts.deny]
sendmail[name=Postfix, dest=you@example.com]
logpath = /var/log/postfix.log
bantime = 300
#
# Mail servers authenticators: might be used for smtp,ftp,imap servers, so
# all relevant ports get banned
#
[courier-auth]
port = smtp,ssmtp,imap2,imap3,imaps,pop3,pop3s
logpath = /var/log/mail.log
[sasl]
port = smtp,ssmtp,imap2,imap3,imaps,pop3,pop3s
# You might consider monitoring /var/log/mail.warn instead if you are
# running postfix since it would provide the same log lines at the
# "warn" level but overall at the smaller filesize.
logpath = /var/log/mail.log
[dovecot]
port = smtp,ssmtp,imap2,imap3,imaps,pop3,pop3s
logpath = /var/log/mail.log
#
# DNS servers
#
# These jails block attacks against named (bind9). By default, logging is off # These jails block attacks against named (bind9). By default, logging is off
# with bind9 installation. You will need something like this: # with bind9 installation. You will need something like this:
@ -314,65 +438,55 @@ ignoreip = 168.192.0.1
# #
# [named-refused-udp] # [named-refused-udp]
# #
# enabled = false
# filter = named-refused # filter = named-refused
# action = iptables-multiport[name=Named, port="domain,953", protocol=udp] # port = domain,953
# sendmail-whois[name=Named, dest=you@example.com] # protocol = udp
# logpath = /var/log/named/security.log # logpath = /var/log/named/security.log
# ignoreip = 168.192.0.1 # ignoreip = 168.192.0.1
# This jail blocks TCP traffic for DNS requests. # This jail blocks TCP traffic for DNS requests.
[named-refused-tcp] [named-refused]
enabled = false
filter = named-refused filter = named-refused
action = iptables-multiport[name=Named, port="domain,953", protocol=tcp] port = domain,953
sendmail-whois[name=Named, dest=you@example.com]
logpath = /var/log/named/security.log logpath = /var/log/named/security.log
ignoreip = 168.192.0.1 ignoreip = 168.192.0.1
#
# Miscelaneous
#
# Multiple jails, 1 per protocol, are necessary ATM: # Multiple jails, 1 per protocol, are necessary ATM:
# see https://github.com/fail2ban/fail2ban/issues/37 # see https://github.com/fail2ban/fail2ban/issues/37
[asterisk-tcp] [asterisk-tcp]
enabled = false
filter = asterisk filter = asterisk
action = iptables-multiport[name=asterisk-tcp, port="5060,5061", protocol=tcp] port = 5060,5061
sendmail-whois[name=Asterisk, dest=you@example.com, sender=fail2ban@example.com] protocol = tcp
logpath = /var/log/asterisk/messages logpath = /var/log/asterisk/messages
maxretry = 10 maxretry = 10
[asterisk-udp] [asterisk-udp]
enabled = false
filter = asterisk filter = asterisk
action = iptables-multiport[name=asterisk-udp, port="5060,5061", protocol=udp] port = 5060,5061
sendmail-whois[name=Asterisk, dest=you@example.com, sender=fail2ban@example.com] protocol = udp
logpath = /var/log/asterisk/messages logpath = /var/log/asterisk/messages
maxretry = 10 maxretry = 10
# To log wrong MySQL access attempts add to /etc/my.cnf: # To log wrong MySQL access attempts add to /etc/my.cnf:
# log-error=/var/log/mysqld.log # log-error=/var/log/mysqld.log
# log-warning = 2 # log-warning = 2
[mysqld-iptables] [mysqld-auth]
enabled = false port = 3306
filter = mysqld-auth
action = iptables[name=mysql, port=3306, protocol=tcp]
sendmail-whois[name=MySQL, dest=root, sender=fail2ban@example.com]
logpath = /var/log/mysqld.log logpath = /var/log/mysqld.log
maxretry = 5
[guacamole-iptables] [guacamole]
enabled = false port = http,https
filter = guacamole
action = iptables-multiport[name=Guacmole, port="http,https"]
sendmail-whois[name=Guacamole, dest=root, sender=fail2ban@example.com]
logpath = /var/log/tomcat*/catalina.out logpath = /var/log/tomcat*/catalina.out
maxretry = 5
# Jail for more extended banning of persistent abusers # Jail for more extended banning of persistent abusers
# !!! WARNING !!! # !!! WARNING !!!
@ -381,8 +495,6 @@ maxretry = 5
# an infinite loop constantly feeding itself with non-informative lines # an infinite loop constantly feeding itself with non-informative lines
[recidive] [recidive]
enabled = false
filter = recidive
logpath = /var/log/fail2ban.log logpath = /var/log/fail2ban.log
action = iptables-allports[name=recidive] action = iptables-allports[name=recidive]
sendmail-whois-lines[name=recidive, logpath=/var/log/fail2ban.log] sendmail-whois-lines[name=recidive, logpath=/var/log/fail2ban.log]

View File

@ -28,15 +28,45 @@ __copyright__ = 'Copyright (c) 2007 Yaroslav Halchenko'
__license__ = 'GPL' __license__ = 'GPL'
import logging, os, sys import logging, os, sys
if sys.version_info >= (3,2): # pragma: no cover if sys.version_info >= (3,2): # pragma: no cover
# SafeConfigParser deprecitated from python 3.2 (renamed ConfigParser)
from configparser import ConfigParser as SafeConfigParser # SafeConfigParser deprecated from Python 3.2 (renamed to ConfigParser)
from configparser import ConfigParser as SafeConfigParser, \
BasicInterpolation
# And interpolation of __name__ was simply removed, thus we need to
# decorate default interpolator to handle it
class BasicInterpolationWithName(BasicInterpolation):
"""Decorator to bring __name__ interpolation back.
Original handling of __name__ was removed because of
functional deficiencies: http://bugs.python.org/issue10489
commit v3.2a4-105-g61f2761
Author: Lukasz Langa <lukasz@langa.pl>
Date: Sun Nov 21 13:41:35 2010 +0000
Issue #10489: removed broken `__name__` support from configparser
But should be fine to reincarnate for our use case
"""
def _interpolate_some(self, parser, option, accum, rest, section, map,
depth):
if section and not (__name__ in map):
map = map.copy() # just to be safe
map['__name__'] = section
return super(BasicInterpolationWithName, self)._interpolate_some(
parser, option, accum, rest, section, map, depth)
else: # pragma: no cover else: # pragma: no cover
from ConfigParser import SafeConfigParser from ConfigParser import SafeConfigParser
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger(__name__) logSys = logging.getLogger(__name__)
__all__ = ['SafeConfigParserWithIncludes']
class SafeConfigParserWithIncludes(SafeConfigParser): class SafeConfigParserWithIncludes(SafeConfigParser):
""" """
Class adds functionality to SafeConfigParser to handle included Class adds functionality to SafeConfigParser to handle included
@ -68,6 +98,14 @@ after = 1.conf
SECTION_NAME = "INCLUDES" SECTION_NAME = "INCLUDES"
if sys.version_info >= (3,2):
# overload constructor only for fancy new Python3's
def __init__(self, *args, **kwargs):
kwargs = kwargs.copy()
kwargs['interpolation'] = BasicInterpolationWithName()
super(SafeConfigParserWithIncludes, self).__init__(
*args, **kwargs)
#@staticmethod #@staticmethod
def getIncludes(resource, seen = []): def getIncludes(resource, seen = []):
""" """

View File

@ -54,7 +54,13 @@ class JailReader(ConfigReader):
return self.__name return self.__name
def read(self): def read(self):
return ConfigReader.read(self, "jail") out = ConfigReader.read(self, "jail")
# Before returning -- verify that requested section
# exists at all
if not (self.__name in self.sections()):
raise ValueError("Jail %r was not found among available"
% self.__name)
return out
def isEnabled(self): def isEnabled(self):
return self.__force_enable or self.__opts["enabled"] return self.__force_enable or self.__opts["enabled"]

View File

@ -21,12 +21,13 @@ __author__ = "Cyril Jaquier, Yaroslav Halchenko"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2011-2013 Yaroslav Halchenko" __copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2011-2013 Yaroslav Halchenko"
__license__ = "GPL" __license__ = "GPL"
import os, shutil, tempfile, unittest import os, shutil, sys, tempfile, unittest
from fail2ban.client.configreader import ConfigReader from fail2ban.client.configreader import ConfigReader
from fail2ban.client.jailreader import JailReader from fail2ban.client.jailreader import JailReader
from fail2ban.client.filterreader import FilterReader from fail2ban.client.filterreader import FilterReader
from fail2ban.client.jailsreader import JailsReader from fail2ban.client.jailsreader import JailsReader
from fail2ban.client.actionreader import ActionReader
from fail2ban.client.configurator import Configurator from fail2ban.client.configurator import Configurator
TEST_FILES_DIR = os.path.join(os.path.dirname(__file__), "files") TEST_FILES_DIR = os.path.join(os.path.dirname(__file__), "files")
@ -46,7 +47,7 @@ class ConfigReaderTest(unittest.TestCase):
"""Call after every test case.""" """Call after every test case."""
shutil.rmtree(self.d) shutil.rmtree(self.d)
def _write(self, fname, value): def _write(self, fname, value=None, content=None):
# verify if we don't need to create .d directory # verify if we don't need to create .d directory
if os.path.sep in fname: if os.path.sep in fname:
d = os.path.dirname(fname) d = os.path.dirname(fname)
@ -54,10 +55,13 @@ class ConfigReaderTest(unittest.TestCase):
if not os.path.exists(d_): if not os.path.exists(d_):
os.makedirs(d_) os.makedirs(d_)
f = open("%s/%s" % (self.d, fname), "w") f = open("%s/%s" % (self.d, fname), "w")
f.write(""" if value is not None:
f.write("""
[section] [section]
option = %s option = %s
""" % value) """ % value)
if content is not None:
f.write(content)
f.close() f.close()
def _remove(self, fname): def _remove(self, fname):
@ -104,15 +108,41 @@ option = %s
self._remove("c.local") self._remove("c.local")
self.assertEqual(self._getoption(), 1) self.assertEqual(self._getoption(), 1)
def testInterpolations(self):
self.assertFalse(self.c.read('i')) # nothing is there yet
self._write("i.conf", value=None, content="""
[DEFAULT]
b = a
zz = the%(__name__)s
[section]
y = 4%(b)s
e = 5${b}
z = %(__name__)s
[section2]
z = 3%(__name__)s
""")
self.assertTrue(self.c.read('i'))
self.assertEqual(self.c.sections(), ['section', 'section2'])
self.assertEqual(self.c.get('section', 'y'), '4a') # basic interpolation works
self.assertEqual(self.c.get('section', 'e'), '5${b}') # no extended interpolation
self.assertEqual(self.c.get('section', 'z'), 'section') # __name__ works
self.assertEqual(self.c.get('section', 'zz'), 'thesection') # __name__ works even 'delayed'
self.assertEqual(self.c.get('section2', 'z'), '3section2') # and differs per section ;)
class JailReaderTest(unittest.TestCase): class JailReaderTest(unittest.TestCase):
def testIncorrectJail(self):
jail = JailReader('XXXABSENTXXX', basedir=CONFIG_DIR)
self.assertRaises(ValueError, jail.read)
def testStockSSHJail(self): def testStockSSHJail(self):
jail = JailReader('ssh-iptables', basedir=CONFIG_DIR) # we are running tests from root project dir atm jail = JailReader('sshd', basedir=CONFIG_DIR) # we are running tests from root project dir atm
self.assertTrue(jail.read()) self.assertTrue(jail.read())
self.assertTrue(jail.getOptions()) self.assertTrue(jail.getOptions())
self.assertFalse(jail.isEnabled()) self.assertFalse(jail.isEnabled())
self.assertEqual(jail.getName(), 'ssh-iptables') self.assertEqual(jail.getName(), 'sshd')
def testSplitOption(self): def testSplitOption(self):
action = "mail-whois[name=SSH]" action = "mail-whois[name=SSH]"
@ -179,6 +209,59 @@ class JailsReaderTest(unittest.TestCase):
# commands to communicate to the server # commands to communicate to the server
self.assertEqual(comm_commands, []) self.assertEqual(comm_commands, [])
allFilters = set()
# All jails must have filter and action set
# TODO: evolve into a parametric test
for jail in jails.sections():
filterName = jails.get(jail, 'filter')
allFilters.add(filterName)
self.assertTrue(len(filterName))
# moreover we must have a file for it
# and it must be readable as a Filter
filterReader = FilterReader(filterName, jail, {})
filterReader.setBaseDir(CONFIG_DIR)
self.assertTrue(filterReader.read()) # opens fine
filterReader.getOptions({}) # reads fine
# test if filter has failregex set
self.assertTrue(filterReader._opts.get('failregex', '').strip())
actions = jails.get(jail, 'action')
self.assertTrue(len(actions.strip()))
# somewhat duplicating here what is done in JailsReader if
# the jail is enabled
for act in actions.split('\n'):
actName, actOpt = JailReader.extractOptions(act)
self.assertTrue(len(actName))
self.assertTrue(isinstance(actOpt, dict))
if actName == 'iptables-multiport':
self.assertTrue('port' in actOpt)
actionReader = ActionReader(
actName, jail, {}, basedir=CONFIG_DIR)
self.assertTrue(actionReader.read())
actionReader.getOptions({}) # populate _opts
cmds = actionReader.convert()
self.assertTrue(len(cmds))
# all must have some actionban
self.assertTrue(actionReader._opts.get('actionban', '').strip())
# Verify that all filters found under config/ have a jail
def get_all_confs(d):
from glob import glob
return set(
os.path.basename(x.replace('.conf', ''))
for x in glob(os.path.join(CONFIG_DIR, d, '*.conf')))
# TODO: provide jails for some additional filters
# ['gssftpd', 'qmail', 'apache-nohome', 'exim', 'dropbear', 'webmin-auth', 'cyrus-imap', 'sieve']
# self.assertEqual(get_all_confs('filter.d').difference(allFilters),
# set(['common']))
def testReadStockJailConfForceEnabled(self): def testReadStockJailConfForceEnabled(self):
# more of a smoke test to make sure that no obvious surprises # more of a smoke test to make sure that no obvious surprises
# on users' systems when enabling shipped jails # on users' systems when enabling shipped jails
@ -191,7 +274,7 @@ class JailsReaderTest(unittest.TestCase):
self.assertTrue(len(comm_commands)) self.assertTrue(len(comm_commands))
# and we know even some of them by heart # and we know even some of them by heart
for j in ['ssh-iptables', 'recidive']: for j in ['sshd', 'recidive']:
# by default we have 'auto' backend ATM # by default we have 'auto' backend ATM
self.assertTrue(['add', j, 'auto'] in comm_commands) self.assertTrue(['add', j, 'auto'] in comm_commands)
# and warn on useDNS # and warn on useDNS