mirror of https://github.com/fail2ban/fail2ban
actions support IPv6 now:
- introduced "conditional" sections, see for example `[Init?family=inet6]`; - iptables-common and other iptables config(s) made IPv6 capable; - several small code optimizations; * all test cases passed (py3.x compatible);pull/1414/head
parent
75028585c0
commit
504e5ba6f2
|
@ -6,6 +6,9 @@
|
|||
# used in all iptables based actions by default.
|
||||
#
|
||||
# The user can override the defaults in iptables-common.local
|
||||
#
|
||||
# Modified: Alexander Koeppe <format_c@online.de>, Serg G. Brester <serg.brester@sebres.de>
|
||||
# made config file IPv6 capable (see new section Init?family=inet6)
|
||||
|
||||
[INCLUDES]
|
||||
|
||||
|
@ -13,6 +16,7 @@ after = iptables-blocktype.local
|
|||
iptables-common.local
|
||||
# iptables-blocktype.local is obsolete
|
||||
|
||||
|
||||
[Init]
|
||||
|
||||
# Option: chain
|
||||
|
@ -62,3 +66,19 @@ lockingopt = -w
|
|||
# Notes.: Actual command to be executed, including common to all calls options
|
||||
# Values: STRING
|
||||
iptables = iptables <lockingopt>
|
||||
|
||||
|
||||
[Init?family=inet6]
|
||||
|
||||
# Option: blocktype (ipv6)
|
||||
# Note: This is what the action does with rules. This can be any jump target
|
||||
# as per the iptables man page (section 8). Common values are DROP
|
||||
# REJECT, REJECT --reject-with icmp6-port-unreachable
|
||||
# Values: STRING
|
||||
blocktype = REJECT --reject-with icmp6-port-unreachable
|
||||
|
||||
# Option: iptables (ipv6)
|
||||
# Notes.: Actual command to be executed, including common to all calls options
|
||||
# Values: STRING
|
||||
iptables = ip6tables <lockingopt>
|
||||
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
#
|
||||
# If you are running on an older kernel you make need to patch in external
|
||||
# modules which probably won't be protocol version 6.
|
||||
#
|
||||
# Modified: Alexander Koeppe <format_c@online.de>, Serg G. Brester <serg.brester@sebres.de>
|
||||
# made config file IPv6 capable (see new section Init?family=inet6)
|
||||
|
||||
[INCLUDES]
|
||||
|
||||
|
@ -23,16 +26,16 @@ before = iptables-common.conf
|
|||
# Notes.: command executed once at the start of Fail2Ban.
|
||||
# Values: CMD
|
||||
#
|
||||
actionstart = ipset create f2b-<name> hash:ip timeout <bantime>
|
||||
<iptables> -I <chain> -m set --match-set f2b-<name> src -j <blocktype>
|
||||
actionstart = ipset create <ipmset> hash:ip timeout <bantime><familyopt>
|
||||
<iptables> -I <chain> -m set --match-set <ipmset> src -j <blocktype>
|
||||
|
||||
# Option: actionstop
|
||||
# Notes.: command executed once at the end of Fail2Ban
|
||||
# Values: CMD
|
||||
#
|
||||
actionstop = <iptables> -D <chain> -m set --match-set f2b-<name> src -j <blocktype>
|
||||
ipset flush f2b-<name>
|
||||
ipset destroy f2b-<name>
|
||||
actionstop = <iptables> -D <chain> -m set --match-set <ipmset> src -j <blocktype>
|
||||
ipset flush <ipmset>
|
||||
ipset destroy <ipmset>
|
||||
|
||||
# Option: actionban
|
||||
# Notes.: command executed when banning an IP. Take care that the
|
||||
|
@ -40,7 +43,7 @@ actionstop = <iptables> -D <chain> -m set --match-set f2b-<name> src -j <blockty
|
|||
# Tags: See jail.conf(5) man page
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = ipset add f2b-<name> <ip> timeout <bantime> -exist
|
||||
actionban = ipset add <ipmset> <ip> timeout <bantime> -exist
|
||||
|
||||
# Option: actionunban
|
||||
# Notes.: command executed when unbanning an IP. Take care that the
|
||||
|
@ -48,7 +51,7 @@ actionban = ipset add f2b-<name> <ip> timeout <bantime> -exist
|
|||
# Tags: See jail.conf(5) man page
|
||||
# Values: CMD
|
||||
#
|
||||
actionunban = ipset del f2b-<name> <ip> -exist
|
||||
actionunban = ipset del <ipmset> <ip> -exist
|
||||
|
||||
[Init]
|
||||
|
||||
|
@ -57,3 +60,12 @@ actionunban = ipset del f2b-<name> <ip> -exist
|
|||
# Values: [ NUM ] Default: 600
|
||||
#
|
||||
bantime = 600
|
||||
|
||||
ipmset = f2b-<name>
|
||||
familyopt =
|
||||
|
||||
|
||||
[Init?family=inet6]
|
||||
|
||||
ipmset = f2b-<name>6
|
||||
familyopt = <sp>family inet6
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
#
|
||||
# If you are running on an older kernel you make need to patch in external
|
||||
# modules.
|
||||
#
|
||||
# Modified: Alexander Koeppe <format_c@online.de>, Serg G. Brester <serg.brester@sebres.de>
|
||||
# made config file IPv6 capable (see new section Init?family=inet6)
|
||||
|
||||
[INCLUDES]
|
||||
|
||||
|
@ -23,16 +26,16 @@ before = iptables-common.conf
|
|||
# Notes.: command executed once at the start of Fail2Ban.
|
||||
# Values: CMD
|
||||
#
|
||||
actionstart = ipset create f2b-<name> hash:ip timeout <bantime>
|
||||
<iptables> -I <chain> -p <protocol> -m multiport --dports <port> -m set --match-set f2b-<name> src -j <blocktype>
|
||||
actionstart = ipset create <ipmset> hash:ip timeout <bantime><familyopt>
|
||||
<iptables> -I <chain> -p <protocol> -m multiport --dports <port> -m set --match-set <ipmset> src -j <blocktype>
|
||||
|
||||
# Option: actionstop
|
||||
# Notes.: command executed once at the end of Fail2Ban
|
||||
# Values: CMD
|
||||
#
|
||||
actionstop = <iptables> -D <chain> -p <protocol> -m multiport --dports <port> -m set --match-set f2b-<name> src -j <blocktype>
|
||||
ipset flush f2b-<name>
|
||||
ipset destroy f2b-<name>
|
||||
actionstop = <iptables> -D <chain> -p <protocol> -m multiport --dports <port> -m set --match-set <ipmset> src -j <blocktype>
|
||||
ipset flush <ipmset>
|
||||
ipset destroy <ipmset>
|
||||
|
||||
# Option: actionban
|
||||
# Notes.: command executed when banning an IP. Take care that the
|
||||
|
@ -40,7 +43,7 @@ actionstop = <iptables> -D <chain> -p <protocol> -m multiport --dports <port> -m
|
|||
# Tags: See jail.conf(5) man page
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = ipset add f2b-<name> <ip> timeout <bantime> -exist
|
||||
actionban = ipset add <ipmset> <ip> timeout <bantime> -exist
|
||||
|
||||
# Option: actionunban
|
||||
# Notes.: command executed when unbanning an IP. Take care that the
|
||||
|
@ -48,7 +51,7 @@ actionban = ipset add f2b-<name> <ip> timeout <bantime> -exist
|
|||
# Tags: See jail.conf(5) man page
|
||||
# Values: CMD
|
||||
#
|
||||
actionunban = ipset del f2b-<name> <ip> -exist
|
||||
actionunban = ipset del <ipmset> <ip> -exist
|
||||
|
||||
[Init]
|
||||
|
||||
|
@ -57,3 +60,12 @@ actionunban = ipset del f2b-<name> <ip> -exist
|
|||
# Values: [ NUM ] Default: 600
|
||||
#
|
||||
bantime = 600
|
||||
|
||||
ipmset = f2b-<name>
|
||||
familyopt =
|
||||
|
||||
|
||||
[Init?family=inet6]
|
||||
|
||||
ipmset = f2b-<name>6
|
||||
familyopt = <sp>family inet6
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
#
|
||||
# Author: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
|
||||
#
|
||||
#
|
||||
# Modified: Alexander Koeppe <format_c@online.de>, Serg G. Brester <serg.brester@sebres.de>
|
||||
# made config file IPv6 capable
|
||||
|
||||
[INCLUDES]
|
||||
|
||||
|
@ -22,30 +23,30 @@ before = iptables-common.conf
|
|||
# iptables-persistent package).
|
||||
#
|
||||
# Explanation of the rule below:
|
||||
# Check if any packets coming from an IP on the f2b-<name>
|
||||
# Check if any packets coming from an IP on the <iptname>
|
||||
# list have been seen in the last 3600 seconds. If yes, update the
|
||||
# timestamp for this IP and drop the packet. If not, let the packet
|
||||
# through.
|
||||
#
|
||||
# Fail2ban inserts blacklisted hosts into the f2b-<name> list
|
||||
# Fail2ban inserts blacklisted hosts into the <iptname> list
|
||||
# and removes them from the list after some time, according to its
|
||||
# own rules. The 3600 second timeout is independent and acts as a
|
||||
# safeguard in case the fail2ban process dies unexpectedly. The
|
||||
# shorter of the two timeouts actually matters.
|
||||
actionstart = if [ `id -u` -eq 0 ];then <iptables> -I <chain> -m recent --update --seconds 3600 --name f2b-<name> -j <blocktype>;fi
|
||||
actionstart = if [ `id -u` -eq 0 ];then <iptables> -I <chain> -m recent --update --seconds 3600 --name <iptname> -j <blocktype>;fi
|
||||
|
||||
# Option: actionstop
|
||||
# Notes.: command executed once at the end of Fail2Ban
|
||||
# Values: CMD
|
||||
#
|
||||
actionstop = echo / > /proc/net/xt_recent/f2b-<name>
|
||||
if [ `id -u` -eq 0 ];then <iptables> -D <chain> -m recent --update --seconds 3600 --name f2b-<name> -j <blocktype>;fi
|
||||
actionstop = echo / > /proc/net/xt_recent/<iptname>
|
||||
if [ `id -u` -eq 0 ];then <iptables> -D <chain> -m recent --update --seconds 3600 --name <iptname> -j <blocktype>;fi
|
||||
|
||||
# Option: actioncheck
|
||||
# Notes.: command executed once before each actionban command
|
||||
# Values: CMD
|
||||
#
|
||||
actioncheck = test -e /proc/net/xt_recent/f2b-<name>
|
||||
actioncheck = test -e /proc/net/xt_recent/<iptname>
|
||||
|
||||
# Option: actionban
|
||||
# Notes.: command executed when banning an IP. Take care that the
|
||||
|
@ -53,7 +54,7 @@ actioncheck = test -e /proc/net/xt_recent/f2b-<name>
|
|||
# Tags: See jail.conf(5) man page
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = echo +<ip> > /proc/net/xt_recent/f2b-<name>
|
||||
actionban = echo +<ip> > /proc/net/xt_recent/<iptname>
|
||||
|
||||
# Option: actionunban
|
||||
# Notes.: command executed when unbanning an IP. Take care that the
|
||||
|
@ -61,7 +62,12 @@ actionban = echo +<ip> > /proc/net/xt_recent/f2b-<name>
|
|||
# Tags: See jail.conf(5) man page
|
||||
# Values: CMD
|
||||
#
|
||||
actionunban = echo -<ip> > /proc/net/xt_recent/f2b-<name>
|
||||
actionunban = echo -<ip> > /proc/net/xt_recent/<iptname>
|
||||
|
||||
[Init]
|
||||
|
||||
iptname = f2b-<name>
|
||||
|
||||
[Init?family=inet6]
|
||||
|
||||
iptname = f2b-<name>6
|
||||
|
|
|
@ -25,6 +25,7 @@ __copyright__ = 'Copyright (c) 2007 Yaroslav Halchenko'
|
|||
__license__ = 'GPL'
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from ..helpers import getLogger
|
||||
|
||||
|
@ -99,6 +100,8 @@ after = 1.conf
|
|||
|
||||
SECTION_NAME = "INCLUDES"
|
||||
|
||||
CONDITIONAL_RE = re.compile(r"^(\w+)(\?.+)$")
|
||||
|
||||
if sys.version_info >= (3,2):
|
||||
# overload constructor only for fancy new Python3's
|
||||
def __init__(self, share_config=None, *args, **kwargs):
|
||||
|
@ -225,21 +228,31 @@ after = 1.conf
|
|||
# merge defaults and all sections to self:
|
||||
alld.update(cfg.get_defaults())
|
||||
for n, s in cfg.get_sections().iteritems():
|
||||
if isinstance(s, dict):
|
||||
s2 = alls.get(n)
|
||||
if isinstance(s2, dict):
|
||||
# save previous known values, for possible using in local interpolations later:
|
||||
sk = {}
|
||||
for k, v in s2.iteritems():
|
||||
if not k.startswith('known/') and k != '__name__':
|
||||
sk['known/'+k] = v
|
||||
s2.update(sk)
|
||||
# merge section
|
||||
s2.update(s)
|
||||
else:
|
||||
alls[n] = s.copy()
|
||||
curalls = alls
|
||||
# conditional sections
|
||||
cond = SafeConfigParserWithIncludes.CONDITIONAL_RE.match(n)
|
||||
if cond:
|
||||
n, cond = cond.groups()
|
||||
s = s.copy()
|
||||
try:
|
||||
del(s['__name__'])
|
||||
except KeyError:
|
||||
pass
|
||||
for k in s.keys():
|
||||
v = s.pop(k)
|
||||
s[k + cond] = v
|
||||
s2 = alls.get(n)
|
||||
if isinstance(s2, dict):
|
||||
# save previous known values, for possible using in local interpolations later:
|
||||
sk = {}
|
||||
for k, v in s2.iteritems():
|
||||
if not k.startswith('known/') and k != '__name__':
|
||||
sk['known/'+k] = v
|
||||
s2.update(sk)
|
||||
# merge section
|
||||
s2.update(s)
|
||||
else:
|
||||
alls[n] = s
|
||||
alls[n] = s.copy()
|
||||
|
||||
return ret
|
||||
|
||||
|
@ -254,9 +267,12 @@ after = 1.conf
|
|||
|
||||
def merge_section(self, section, options, pref='known/'):
|
||||
alls = self.get_sections()
|
||||
if pref == '':
|
||||
alls[section].update(options)
|
||||
return
|
||||
sk = {}
|
||||
for k, v in options.iteritems():
|
||||
if pref == '' or (not k.startswith(pref) and k != '__name__'):
|
||||
if not k.startswith(pref) and k != '__name__':
|
||||
sk[pref+k] = v
|
||||
alls[section].update(sk)
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ import time
|
|||
from abc import ABCMeta
|
||||
from collections import MutableMapping
|
||||
|
||||
from .ipdns import asip
|
||||
from .utils import Utils
|
||||
from ..helpers import getLogger
|
||||
|
||||
|
@ -41,6 +42,11 @@ logSys = getLogger(__name__)
|
|||
# Create a lock for running system commands
|
||||
_cmd_lock = threading.Lock()
|
||||
|
||||
# Todo: make it configurable resp. automatically set, ex.: `[ -f /proc/net/if_inet6 ] && echo 'yes' || echo 'no'`:
|
||||
allowed_ipv6 = True
|
||||
|
||||
# compiled RE for tag name (replacement name)
|
||||
TAG_CRE = re.compile(r'<([^ <>]+)>')
|
||||
|
||||
class CallingMap(MutableMapping):
|
||||
"""A Mapping type which returns the result of callable values.
|
||||
|
@ -256,14 +262,18 @@ class CommandAction(ActionBase):
|
|||
Replace the tags in the action command with actions properties
|
||||
and executes the resulting command.
|
||||
"""
|
||||
if (self._properties and
|
||||
not self.substituteRecursiveTags(self._properties)):
|
||||
self._logSys.error(
|
||||
"properties contain self referencing definitions "
|
||||
"and cannot be resolved")
|
||||
raise RuntimeError("Error starting action")
|
||||
startCmd = self.replaceTag(self.actionstart, self._properties)
|
||||
if not self.executeCmd(startCmd, self.timeout):
|
||||
# check valid tags in properties (raises ValueError if self recursion, etc.):
|
||||
if self._properties:
|
||||
self.substituteRecursiveTags(self._properties)
|
||||
# common (resp. ipv4):
|
||||
startCmd = self.replaceTag('<actionstart>', self._properties, conditional='family=inet4')
|
||||
res = self.executeCmd(startCmd, self.timeout)
|
||||
# start ipv6 actions if available:
|
||||
if allowed_ipv6:
|
||||
startCmd6 = self.replaceTag('<actionstart>', self._properties, conditional='family=inet6')
|
||||
if startCmd6 != startCmd:
|
||||
res &= self.executeCmd(startCmd6, self.timeout)
|
||||
if not res:
|
||||
raise RuntimeError("Error starting action")
|
||||
|
||||
@property
|
||||
|
@ -289,7 +299,7 @@ class CommandAction(ActionBase):
|
|||
Dictionary which includes information in relation to
|
||||
the ban.
|
||||
"""
|
||||
if not self._processCmd(self.actionban, aInfo):
|
||||
if not self._processCmd('<actionban>', aInfo):
|
||||
raise RuntimeError("Error banning %(ip)s" % aInfo)
|
||||
|
||||
@property
|
||||
|
@ -315,7 +325,7 @@ class CommandAction(ActionBase):
|
|||
Dictionary which includes information in relation to
|
||||
the ban.
|
||||
"""
|
||||
if not self._processCmd(self.actionunban, aInfo):
|
||||
if not self._processCmd('<actionunban>', aInfo):
|
||||
raise RuntimeError("Error unbanning %(ip)s" % aInfo)
|
||||
|
||||
@property
|
||||
|
@ -350,12 +360,19 @@ class CommandAction(ActionBase):
|
|||
Replaces the tags in the action command with actions properties
|
||||
and executes the resulting command.
|
||||
"""
|
||||
stopCmd = self.replaceTag(self.actionstop, self._properties)
|
||||
if not self.executeCmd(stopCmd, self.timeout):
|
||||
# common (resp. ipv4):
|
||||
stopCmd = self.replaceTag('<actionstop>', self._properties, conditional='family=inet4')
|
||||
res = self.executeCmd(stopCmd, self.timeout)
|
||||
# ipv6 actions if available:
|
||||
if allowed_ipv6:
|
||||
stopCmd6 = self.replaceTag('<actionstop>', self._properties, conditional='family=inet6')
|
||||
if stopCmd6 != stopCmd:
|
||||
res &= self.executeCmd(stopCmd6, self.timeout)
|
||||
if not res:
|
||||
raise RuntimeError("Error stopping action")
|
||||
|
||||
@classmethod
|
||||
def substituteRecursiveTags(cls, tags):
|
||||
def substituteRecursiveTags(cls, tags, conditional=''):
|
||||
"""Sort out tag definitions within other tags.
|
||||
Since v.0.9.2 supports embedded interpolation (see test cases for examples).
|
||||
|
||||
|
@ -374,7 +391,7 @@ class CommandAction(ActionBase):
|
|||
Dictionary of tags(keys) and their values, with tags
|
||||
within the values recursively replaced.
|
||||
"""
|
||||
t = re.compile(r'<([^ <>]+)>')
|
||||
t = TAG_CRE
|
||||
# repeat substitution while embedded-recursive (repFlag is True)
|
||||
while True:
|
||||
repFlag = False
|
||||
|
@ -394,14 +411,21 @@ class CommandAction(ActionBase):
|
|||
if found_tag == tag or found_tag in done:
|
||||
# recursive definitions are bad
|
||||
#logSys.log(5, 'recursion fail tag: %s value: %s' % (tag, value) )
|
||||
return False
|
||||
if found_tag in cls._escapedTags or not found_tag in tags:
|
||||
raise ValueError(
|
||||
"properties contain self referencing definitions "
|
||||
"and cannot be resolved, fail tag: %s value: %s" % (tag, value))
|
||||
repl = None
|
||||
if found_tag not in cls._escapedTags:
|
||||
repl = tags.get(found_tag + '?' + conditional)
|
||||
if repl is None:
|
||||
repl = tags.get(found_tag)
|
||||
if repl is None:
|
||||
# Escaped or missing tags - just continue on searching after end of match
|
||||
# Missing tags are ok - cInfo can contain aInfo elements like <HOST> and valid shell
|
||||
# constructs like <STDIN>.
|
||||
m = t.search(value, m.end())
|
||||
continue
|
||||
value = value.replace('<%s>' % found_tag , tags[found_tag])
|
||||
value = value.replace('<%s>' % found_tag, repl)
|
||||
#logSys.log(5, 'value now: %s' % value)
|
||||
done.append(found_tag)
|
||||
m = t.search(value, m.start())
|
||||
|
@ -443,7 +467,7 @@ class CommandAction(ActionBase):
|
|||
return value
|
||||
|
||||
@classmethod
|
||||
def replaceTag(cls, query, aInfo):
|
||||
def replaceTag(cls, query, aInfo, conditional=''):
|
||||
"""Replaces tags in `query` with property values.
|
||||
|
||||
Parameters
|
||||
|
@ -459,7 +483,7 @@ class CommandAction(ActionBase):
|
|||
`query` string with tags replaced.
|
||||
"""
|
||||
string = query
|
||||
aInfo = cls.substituteRecursiveTags(aInfo)
|
||||
aInfo = cls.substituteRecursiveTags(aInfo, conditional)
|
||||
for tag in aInfo:
|
||||
if "<%s>" % tag in query:
|
||||
value = str(aInfo[tag]) # assure string
|
||||
|
@ -469,10 +493,10 @@ class CommandAction(ActionBase):
|
|||
value = cls.escapeTag(value)
|
||||
string = string.replace('<' + tag + '>', value)
|
||||
# New line
|
||||
string = string.replace("<br>", '\n')
|
||||
string = reduce(lambda s, kv: s.replace(*kv), (("<br>", '\n'), ("<sp>", " ")), string)
|
||||
return string
|
||||
|
||||
def _processCmd(self, cmd, aInfo = None):
|
||||
def _processCmd(self, cmd, aInfo=None, conditional=''):
|
||||
"""Executes a command with preliminary checks and substitutions.
|
||||
|
||||
Before executing any commands, executes the "check" command first
|
||||
|
@ -496,7 +520,17 @@ class CommandAction(ActionBase):
|
|||
self._logSys.debug("Nothing to do")
|
||||
return True
|
||||
|
||||
checkCmd = self.replaceTag(self.actioncheck, self._properties)
|
||||
if conditional == '':
|
||||
conditional = 'family=inet4'
|
||||
if allowed_ipv6:
|
||||
try:
|
||||
ip = aInfo["ip"]
|
||||
if ip and asip(ip).isIPv6:
|
||||
conditional = 'family=inet6'
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
checkCmd = self.replaceTag('<actioncheck>', self._properties, conditional=conditional)
|
||||
if not self.executeCmd(checkCmd, self.timeout):
|
||||
self._logSys.error(
|
||||
"Invariant check failed. Trying to restore a sane environment")
|
||||
|
@ -506,15 +540,15 @@ class CommandAction(ActionBase):
|
|||
self._logSys.critical("Unable to restore environment")
|
||||
return False
|
||||
|
||||
# Replace static fields
|
||||
realCmd = self.replaceTag(cmd, self._properties, conditional=conditional)
|
||||
|
||||
# Replace tags
|
||||
if not aInfo is None:
|
||||
realCmd = self.replaceTag(cmd, aInfo)
|
||||
if aInfo is not None:
|
||||
realCmd = self.replaceTag(realCmd, aInfo, conditional=conditional)
|
||||
else:
|
||||
realCmd = cmd
|
||||
|
||||
# Replace static fields
|
||||
realCmd = self.replaceTag(realCmd, self._properties)
|
||||
|
||||
return self.executeCmd(realCmd, self.timeout)
|
||||
|
||||
@staticmethod
|
||||
|
|
|
@ -54,12 +54,17 @@ class CommandActionTest(LogCaptureTestCase):
|
|||
'xyz': "890 <ABC>",
|
||||
}
|
||||
# Recursion is bad
|
||||
self.assertFalse(CommandAction.substituteRecursiveTags({'A': '<A>'}))
|
||||
self.assertFalse(CommandAction.substituteRecursiveTags({'A': '<B>', 'B': '<A>'}))
|
||||
self.assertFalse(CommandAction.substituteRecursiveTags({'A': '<B>', 'B': '<C>', 'C': '<A>'}))
|
||||
self.assertRaises(ValueError,
|
||||
lambda: CommandAction.substituteRecursiveTags({'A': '<A>'}))
|
||||
self.assertRaises(ValueError,
|
||||
lambda: CommandAction.substituteRecursiveTags({'A': '<B>', 'B': '<A>'}))
|
||||
self.assertRaises(ValueError,
|
||||
lambda: CommandAction.substituteRecursiveTags({'A': '<B>', 'B': '<C>', 'C': '<A>'}))
|
||||
# Unresolveable substition
|
||||
self.assertFalse(CommandAction.substituteRecursiveTags({'A': 'to=<B> fromip=<IP>', 'C': '<B>', 'B': '<C>', 'D': ''}))
|
||||
self.assertFalse(CommandAction.substituteRecursiveTags({'failregex': 'to=<honeypot> fromip=<IP>', 'sweet': '<honeypot>', 'honeypot': '<sweet>', 'ignoreregex': ''}))
|
||||
self.assertRaises(ValueError,
|
||||
lambda: CommandAction.substituteRecursiveTags({'A': 'to=<B> fromip=<IP>', 'C': '<B>', 'B': '<C>', 'D': ''}))
|
||||
self.assertRaises(ValueError,
|
||||
lambda: CommandAction.substituteRecursiveTags({'failregex': 'to=<honeypot> fromip=<IP>', 'sweet': '<honeypot>', 'honeypot': '<sweet>', 'ignoreregex': ''}))
|
||||
# missing tags are ok
|
||||
self.assertEqual(CommandAction.substituteRecursiveTags({'A': '<C>'}), {'A': '<C>'})
|
||||
self.assertEqual(CommandAction.substituteRecursiveTags({'A': '<C> <D> <X>','X':'fun'}), {'A': '<C> <D> fun', 'X':'fun'})
|
||||
|
@ -127,6 +132,7 @@ class CommandActionTest(LogCaptureTestCase):
|
|||
CallingMap(matches=lambda: str(10))),
|
||||
"09 10 11")
|
||||
|
||||
def testReplaceNoTag(self):
|
||||
# As tag not present, therefore callable should not be called
|
||||
# Will raise ValueError if it is
|
||||
self.assertEqual(
|
||||
|
|
|
@ -1416,7 +1416,6 @@ class DNSUtilsNetworkTests(unittest.TestCase):
|
|||
self.assertNotEqual(ip4[0], None)
|
||||
self.assertTrue(ip4[0] is not None)
|
||||
self.assertFalse(ip4[0] is None)
|
||||
self.assertLess(None, ip4[0])
|
||||
self.assertLess(ip4[0], ip4[1])
|
||||
self.assertLess(ip4[1], ip4[2])
|
||||
self.assertEqual(sorted(reversed(ip4)), ip4)
|
||||
|
@ -1424,7 +1423,6 @@ class DNSUtilsNetworkTests(unittest.TestCase):
|
|||
self.assertNotEqual(ip6[0], None)
|
||||
self.assertTrue(ip6[0] is not None)
|
||||
self.assertFalse(ip6[0] is None)
|
||||
self.assertLess(None, ip6[0])
|
||||
self.assertLess(ip6[0], ip6[1])
|
||||
self.assertLess(ip6[1], ip6[2])
|
||||
self.assertEqual(sorted(reversed(ip6)), ip6)
|
||||
|
|
Loading…
Reference in New Issue