forked from fail2ban/fail2ban
-
Notifications
You must be signed in to change notification settings - Fork 0
/
setup.py
executable file
·336 lines (304 loc) · 10 KB
/
setup.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
#!/usr/bin/env python
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: t -*-
# vi: set ft=python sts=4 ts=4 sw=4 noet :
# This file is part of Fail2Ban.
#
# Fail2Ban is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Fail2Ban is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Fail2Ban; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
__author__ = "Cyril Jaquier, Steven Hiscocks, Yaroslav Halchenko"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2008-2016 Fail2Ban Contributors"
__license__ = "GPL"
import platform
try:
import setuptools
from setuptools import setup
from setuptools.command.install import install
from setuptools.command.install_scripts import install_scripts
except ImportError:
setuptools = None
from distutils.core import setup
# all versions
from distutils.command.build_py import build_py
from distutils.command.build_scripts import build_scripts
if setuptools is None:
from distutils.command.install import install
from distutils.command.install_scripts import install_scripts
try:
# python 3.x
from distutils.command.build_py import build_py_2to3
from distutils.command.build_scripts import build_scripts_2to3
_2to3 = True
except ImportError:
# python 2.x
_2to3 = False
import os
from os.path import isfile, join, isdir, realpath
import re
import sys
import warnings
from glob import glob
from fail2ban.setup import updatePyExec
source_dir = os.path.realpath(os.path.dirname(
# __file__ seems to be overwritten sometimes on some python versions (e.g. bug of 2.6 by running under cProfile, etc.):
sys.argv[0] if os.path.basename(sys.argv[0]) == 'setup.py' else __file__
))
with_tests = True
# Wrapper to install python binding (to current python version):
class install_scripts_f2b(install_scripts):
def get_outputs(self):
outputs = install_scripts.get_outputs(self)
# setup.py --dry-run install:
dry_run = not outputs
self.update_scripts(dry_run)
if dry_run:
#bindir = self.install_dir
bindir = self.build_dir
print('creating fail2ban-python binding -> %s (dry-run, real path can be different)' % (bindir,))
print('Copying content of %s to %s' % (self.build_dir, self.install_dir));
return outputs
fn = None
for fn in outputs:
if os.path.basename(fn) == 'fail2ban-server':
break
bindir = os.path.dirname(fn)
print('creating fail2ban-python binding -> %s' % (bindir,))
updatePyExec(bindir)
return outputs
def update_scripts(self, dry_run=False):
buildroot = os.path.dirname(self.build_dir)
install_dir = self.install_dir
try:
# remove root-base from install scripts path:
root = self.distribution.command_options['install']['root'][1]
if install_dir.startswith(root):
install_dir = install_dir[len(root):]
except: # pragma: no cover
print('WARNING: Cannot find root-base option, check the bin-path to fail2ban-scripts in "fail2ban.service".')
print('Creating %s/fail2ban.service (from fail2ban.service.in): @BINDIR@ -> %s' % (buildroot, install_dir))
with open(os.path.join(source_dir, 'files/fail2ban.service.in'), 'r') as fn:
lines = fn.readlines()
fn = None
if not dry_run:
fn = open(os.path.join(buildroot, 'fail2ban.service'), 'w')
try:
for ln in lines:
ln = re.sub(r'@BINDIR@', lambda v: install_dir, ln)
if dry_run:
sys.stdout.write(' | ' + ln)
continue
fn.write(ln)
finally:
if fn: fn.close()
if dry_run:
print(' `')
# Wrapper to specify fail2ban own options:
class install_command_f2b(install):
user_options = install.user_options + [
('disable-2to3', None, 'Specify to deactivate 2to3, e.g. if the install runs from fail2ban test-cases.'),
('without-tests', None, 'without tests files installation'),
]
def initialize_options(self):
self.disable_2to3 = None
self.without_tests = not with_tests
install.initialize_options(self)
def finalize_options(self):
global _2to3
## in the test cases 2to3 should be already done (fail2ban-2to3):
if self.disable_2to3:
_2to3 = False
if _2to3:
cmdclass = self.distribution.cmdclass
cmdclass['build_py'] = build_py_2to3
cmdclass['build_scripts'] = build_scripts_2to3
if self.without_tests:
self.distribution.scripts.remove('bin/fail2ban-testcases')
self.distribution.packages.remove('fail2ban.tests')
self.distribution.packages.remove('fail2ban.tests.action_d')
del self.distribution.package_data['fail2ban.tests']
install.finalize_options(self)
def run(self):
install.run(self)
# Update fail2ban-python env to current python version (where f2b-modules located/installed)
updatePyExec(os.path.join(source_dir, 'bin'))
if setuptools and "test" in sys.argv:
import logging
logSys = logging.getLogger("fail2ban")
hdlr = logging.StreamHandler(sys.stdout)
fmt = logging.Formatter("%(asctime)-15s %(message)s")
hdlr.setFormatter(fmt)
logSys.addHandler(hdlr)
if set(["-q", "--quiet"]) & set(sys.argv):
logSys.setLevel(logging.CRITICAL)
warnings.simplefilter("ignore")
sys.warnoptions.append("ignore")
elif set(["-v", "--verbose"]) & set(sys.argv):
logSys.setLevel(logging.DEBUG)
else:
logSys.setLevel(logging.INFO)
elif "test" in sys.argv:
print("python distribute required to execute fail2ban tests")
print("")
# if build without tests:
if "build" in sys.argv:
if "--without-tests" in sys.argv:
with_tests = False
sys.argv.remove("--without-tests")
longdesc = '''
Fail2Ban scans log files like /var/log/pwdfail or
/var/log/apache/error_log and bans IP that makes
too many password failures. It updates firewall rules
to reject the IP address or executes user defined
commands.'''
if setuptools:
setup_extra = {
'test_suite': "fail2ban.tests.utils.gatherTests",
'use_2to3': True,
}
else:
setup_extra = {}
data_files_extra = []
if os.path.exists('/var/run'):
# if we are on the system with /var/run -- we are to use it for having fail2ban/
# directory there for socket file etc.
# realpath is used to possibly resolve /var/run -> /run symlink
data_files_extra += [(realpath('/var/run/fail2ban'), '')]
# Installing documentation files only under Linux or other GNU/ systems
# (e.g. GNU/kFreeBSD), since others might have protective mechanisms forbidding
# installation there (see e.g. #1233)
platform_system = platform.system().lower()
doc_files = ['README.md', 'DEVELOP', 'FILTERS', 'doc/run-rootless.txt']
if platform_system in ('solaris', 'sunos'):
doc_files.append('README.Solaris')
if platform_system in ('linux', 'solaris', 'sunos') or platform_system.startswith('gnu'):
data_files_extra.append(
('/usr/share/doc/fail2ban', doc_files)
)
# Get version number, avoiding importing fail2ban.
# This is due to tests not functioning for python3 as 2to3 takes place later
exec(open(join("fail2ban", "version.py")).read())
setup(
name = "fail2ban",
version = version,
description = "Ban IPs that make too many password failures",
long_description = longdesc,
author = "Cyril Jaquier & Fail2Ban Contributors",
author_email = "[email protected]",
url = "http://www.fail2ban.org",
license = "GPL",
platforms = "Posix",
cmdclass = {
'build_py': build_py, 'build_scripts': build_scripts,
'install_scripts': install_scripts_f2b, 'install': install_command_f2b
},
scripts = [
'bin/fail2ban-client',
'bin/fail2ban-server',
'bin/fail2ban-regex',
# 'bin/fail2ban-python', -- link (binary), will be installed via install_scripts_f2b wrapper
] + [
'bin/fail2ban-testcases',
] if with_tests else [],
packages = [
'fail2ban',
'fail2ban.client',
'fail2ban.server',
] + [
'fail2ban.tests',
'fail2ban.tests.action_d',
] if with_tests else [],
package_data = {
'fail2ban.tests':
[ join(w[0], f).replace("fail2ban/tests/", "", 1)
for w in os.walk('fail2ban/tests/files')
for f in w[2]] +
[ join(w[0], f).replace("fail2ban/tests/", "", 1)
for w in os.walk('fail2ban/tests/config')
for f in w[2]] +
[ join(w[0], f).replace("fail2ban/tests/", "", 1)
for w in os.walk('fail2ban/tests/action_d')
for f in w[2]]
} if with_tests else {},
data_files = [
('/etc/fail2ban',
glob("config/*.conf")
),
('/etc/fail2ban/filter.d',
glob("config/filter.d/*.conf")
),
('/etc/fail2ban/filter.d/ignorecommands',
[p for p in glob("config/filter.d/ignorecommands/*") if isfile(p)]
),
('/etc/fail2ban/action.d',
glob("config/action.d/*.conf") +
glob("config/action.d/*.py")
),
('/etc/fail2ban/fail2ban.d',
''
),
('/etc/fail2ban/jail.d',
''
),
('/var/lib/fail2ban',
''
),
] + data_files_extra,
**setup_extra
)
# Do some checks after installation
# Search for obsolete files.
obsoleteFiles = []
elements = {
"/etc/":
[
"fail2ban.conf"
],
"/usr/bin/":
[
"fail2ban.py"
],
"/usr/lib/fail2ban/":
[
"version.py",
"protocol.py"
]
}
for directory in elements:
for f in elements[directory]:
path = join(directory, f)
if isfile(path):
obsoleteFiles.append(path)
if obsoleteFiles:
print("")
print("Obsolete files from previous Fail2Ban versions were found on "
"your system.")
print("Please delete them:")
print("")
for f in obsoleteFiles:
print("\t" + f)
print("")
if isdir("/usr/lib/fail2ban"):
print("")
print("Fail2ban is not installed under /usr/lib anymore. The new "
"location is under /usr/share. Please remove the directory "
"/usr/lib/fail2ban and everything under this directory.")
print("")
# Update config file
if sys.argv[1] == "install":
print("")
print("Please do not forget to update your configuration files.")
print("They are in \"/etc/fail2ban/\".")
print("")
print("You can also install systemd service-unit file from \"build/fail2ban.service\"")
print("resp. corresponding init script from \"files/*-initd\".")
print("")