2828from grp import getgrnam
2929from pathlib import Path
3030from pwd import getpwnam
31+ from subprocess import run , CalledProcessError
32+ from tempfile import NamedTemporaryFile
3133from typing import Optional
3234
3335try :
3436 import intelmq_api
3537except ImportError :
3638 intelmq_api = None
3739
40+ try :
41+ import intelmq_manager
42+ except ImportError :
43+ intelmq_manager = None
44+
3845from termstyle import red
3946from intelmq import (CONFIG_DIR , DEFAULT_LOGGING_PATH , ROOT_DIR , VAR_RUN_PATH ,
4047 VAR_STATE_PATH , BOTS_FILE , STATE_FILE_PATH )
4148from intelmq .bin .intelmqctl import IntelMQController
4249
4350
44- MANAGER_CONFIG_DIR = Path (CONFIG_DIR ) / 'manager/'
4551FILE_OUTPUT_PATH = Path (VAR_STATE_PATH ) / 'file-output/'
52+ ETC_INTELMQ = Path ('/etc/intelmq/' )
53+ ETC_INTELMQ_MANAGER = ETC_INTELMQ / 'manager/'
54+ WEBSERVER_CONFIG_DIR = None # "cache" for the webserver configuration directory
55+ NOTE_WEBSERVER_RELOAD = False # if the webserver needs to be reloaded
4656
4757
4858def basic_checks (skip_ownership ):
@@ -77,7 +87,7 @@ def create_directory(directory: str, octal_mode: int):
7787 directory .chmod (octal_mode )
7888
7989
80- def change_owner (file : str , owner = None , group = None , log : bool = True ):
90+ def change_owner (file : str , owner : Optional [ str ] = None , group : Optional [ str ] = None , log : bool = True ):
8191 if owner and Path (file ).owner () != owner :
8292 if log :
8393 print (f'Fixing owner of { file !s} .' )
@@ -96,8 +106,39 @@ def find_webserver_user():
96106 except KeyError :
97107 pass
98108 else :
99- print (f'Detected webserver username { candidate !r} .' )
109+ print (f'Detected Apache username { candidate !r} .' )
100110 return candidate
111+ else :
112+ sys .exit (red ("Unable to detect Apache user name. "
113+ "Please re-run this program and give the Apache user name with '--webserver-user'." ))
114+
115+
116+ def find_webserver_configuration_directory ():
117+ global WEBSERVER_CONFIG_DIR
118+ if WEBSERVER_CONFIG_DIR :
119+ return WEBSERVER_CONFIG_DIR
120+ webserver_configuration_dir_candidates = (Path ('/etc/apache2/conf-available/' ),
121+ Path ('/etc/apache2/conf.d/' ),
122+ Path ('/etc/httpd/conf.d/' ))
123+ for webserver_configuration_dir_candidate in webserver_configuration_dir_candidates :
124+ if webserver_configuration_dir_candidate .exists ():
125+ print (f'Detected Apache configuration directory { webserver_configuration_dir_candidate !s} .' )
126+ WEBSERVER_CONFIG_DIR = webserver_configuration_dir_candidate
127+ webserver_configuration_dir_candidate .as_posix
128+ return webserver_configuration_dir_candidate
129+ else :
130+ sys .exit (red ("Unable to detect Apache configuration directory. "
131+ "Please re-run this program and give the Apache configuration directory with '--webserver-configuration-directory'." ))
132+
133+
134+ def debian_activate_apache_config (config_name : str ):
135+ if 'available' not in WEBSERVER_CONFIG_DIR .as_posix ():
136+ return # not a Debian system
137+ available = WEBSERVER_CONFIG_DIR / config_name
138+ enabled = Path (WEBSERVER_CONFIG_DIR .as_posix ().replace ('available' , 'enabled' )) / config_name
139+ if not enabled .exists ():
140+ enabled .symlink_to (available )
141+ print ('Created symbolic link {enabled!s} pointing to {available!s}.' )
101142
102143
103144def intelmqsetup_core (ownership = True , state_file = STATE_FILE_PATH ):
@@ -140,23 +181,109 @@ def intelmqsetup_core(ownership=True, state_file=STATE_FILE_PATH):
140181
141182
142183def intelmqsetup_api (ownership : bool = True , webserver_user : Optional [str ] = None ):
184+ intelmq_group = getgrnam ('intelmq' )
185+ webserver_user = webserver_user or find_webserver_user ()
186+
187+ create_directory (ETC_INTELMQ , 0o40775 )
143188 if ownership :
144189 change_owner (CONFIG_DIR , group = 'intelmq' )
190+ change_owner (ETC_INTELMQ , owner = 'intelmq' , group = 'intelmq' )
145191
146192 # Manager configuration directory
147- create_directory (MANAGER_CONFIG_DIR , 0o40775 )
193+ create_directory (ETC_INTELMQ_MANAGER , 0o40775 )
148194 if ownership :
149- change_owner (MANAGER_CONFIG_DIR , group = 'intelmq' )
195+ change_owner (ETC_INTELMQ_MANAGER , group = 'intelmq' )
196+
197+ base = Path (pkg_resources .resource_filename ('intelmq_api' , '' )).parent
198+ api_config = base / 'etc/intelmq/api-config.json'
199+ etc_intelmq_config = ETC_INTELMQ / 'api-config.json'
200+ api_sudoers = base / 'etc/intelmq/api-sudoers.conf'
201+ etc_sudoers_api = Path ('/etc/sudoers.d/01_intelmq-api' ) # same path as used in the packages
202+ api_manager_positions = base / 'etc/intelmq/manager/positions.conf'
203+ etc_intelmq_manager_positions = ETC_INTELMQ_MANAGER / 'positions.conf'
204+
205+ if not base .as_posix ().startswith ('/usr/' ):
206+ # Paths differ in editable installations
207+ print (red ("Detected an editable (egg-link) pip-installation of 'intelmq-api'. Some feature of this program may not work." ))
208+
209+ if api_config .exists () and not etc_intelmq_config .exists ():
210+ shutil .copy (api_config , etc_intelmq_config )
211+ print (f'Copied { api_config !s} to { ETC_INTELMQ !s} .' )
212+ elif not api_config .exists () and not etc_intelmq_config .exists ():
213+ print (red (f'Unable to install api-config.json: Neither { api_config !s} nor { etc_intelmq_config !s} exists.' ))
214+ if api_sudoers .exists () and not etc_sudoers_api .exists ():
215+ with open (api_sudoers ) as sudoers :
216+ original_sudoers = sudoers .read ()
217+ sudoers = original_sudoers .replace ('www-data' , webserver_user )
218+ with NamedTemporaryFile (mode = 'w' ) as tmp_file :
219+ tmp_file .write (sudoers )
220+ tmp_file .flush ()
221+ try :
222+ run (('visudo' , '-c' , tmp_file .name ))
223+ except CalledProcessError :
224+ sys .exit (red ('Fatal error: Validation of adapted sudoers-file failed. Please report this bug.' ))
225+ change_owner (tmp_file .name , owner = 'root' , group = 'root' , log = False )
226+ Path (tmp_file .name ).chmod (0o440 )
227+ shutil .copy (tmp_file .name , etc_sudoers_api )
228+ print (f'Copied { api_sudoers !s} to { etc_sudoers_api !s} .' )
229+ elif not api_sudoers .exists () and not etc_sudoers_api .exists ():
230+ print (red (f'Unable to install api-sudoers.conf: Neither { api_sudoers !s} nor { etc_sudoers_api !s} exists.' ))
231+ if api_manager_positions .exists () and not etc_intelmq_manager_positions .exists ():
232+ shutil .copy (api_manager_positions , etc_intelmq_manager_positions )
233+ print (f'Copied { api_manager_positions !s} to { etc_intelmq_manager_positions !s} .' )
234+ etc_intelmq_manager_positions .chmod (0o664 )
235+ change_owner (etc_intelmq_manager_positions , owner = 'intelmq' , group = 'intelmq' , log = False )
236+ elif not api_manager_positions .exists () and not etc_intelmq_manager_positions .exists ():
237+ print (red (f'Unable to install positions.conf: Neither { api_manager_positions !s} nor { etc_intelmq_manager_positions !s} exists.' ))
150238
151- intelmq_group = getgrnam ('intelmq' )
152- webserver_user = webserver_user or find_webserver_user ()
153239 if webserver_user not in intelmq_group .gr_mem :
154240 sys .exit (red (f"Webserver user { webserver_user } is not a member of the 'intelmq' group. "
155241 f"Please add it with: 'usermod -aG intelmq { webserver_user } '." ))
156242
243+
244+ def intelmqsetup_api_webserver_configuration (webserver_configuration_directory : Optional [str ] = None ):
245+ webserver_configuration_dir = webserver_configuration_directory or find_webserver_configuration_directory ()
246+ api_config = Path (pkg_resources .resource_filename ('intelmq_api' , '' )).parent / 'etc/intelmq/api-apache.conf'
247+ apache_api_config = webserver_configuration_dir / 'api-apache.conf'
248+ if api_config .exists () and not apache_api_config .exists ():
249+ shutil .copy (api_config , apache_api_config )
250+ print (f'Copied { api_config !s} to { ETC_INTELMQ !s} .' )
251+ debian_activate_apache_config ('api-apache.conf' )
252+
253+ global NOTE_WEBSERVER_RELOAD
254+ NOTE_WEBSERVER_RELOAD = True
255+ elif not api_config .exists () and not apache_api_config .exists ():
256+ print (red (f'Unable to install webserver configuration api-config.conf: Neither { api_config !s} nor { apache_api_config !s} exists.' ))
257+
157258 print ('Setup of intelmq-api successful.' )
158259
159260
261+ def intelmqsetup_manager_webserver_configuration (webserver_configuration_directory : Optional [str ] = None ):
262+ html_dir = Path (pkg_resources .resource_filename ('intelmq_manager' , '' )).parent / '/usr/share/intelmq-manager/html'
263+ html_dir_destination = Path ('/usr/share/intelmq-manager/html' )
264+
265+ if not html_dir_destination .as_posix ().startswith ('/usr/' ):
266+ # Paths differ in editable installations
267+ print (red ("Detected an editable (egg-link) pip-installation of intelmq-manager. Some feature of this program may not work." ))
268+
269+ webserver_configuration_dir = webserver_configuration_directory or find_webserver_configuration_directory ()
270+ manager_config = Path (pkg_resources .resource_filename ('intelmq_manager' , '' )).parent / 'etc/intelmq/manager-apache.conf'
271+ apache_manager_config = webserver_configuration_dir / 'manager-apache.conf'
272+ if manager_config .exists () and not apache_manager_config .exists ():
273+ shutil .copy (manager_config , apache_manager_config )
274+ print (f'Copied { manager_config !s} to { apache_manager_config !s} .' )
275+ debian_activate_apache_config ('manager-apache.conf' )
276+
277+ global NOTE_WEBSERVER_RELOAD
278+ NOTE_WEBSERVER_RELOAD = True
279+ elif not manager_config .exists () and not apache_manager_config .exists ():
280+ print (red (f'Unable to install webserver configuration manager-config.conf: Neither { manager_config !s} nor { apache_manager_config !s} exists.' ))
281+
282+ if html_dir .exists ():
283+ shutil .copy (html_dir , '/' )
284+ print (f'Copied { html_dir !s} to { html_dir_destination !s} .' )
285+
286+
160287def main ():
161288 parser = argparse .ArgumentParser ("Set's up directories and example "
162289 "configurations for IntelMQ." )
@@ -167,15 +294,34 @@ def main():
167294 default = STATE_FILE_PATH )
168295 parser .add_argument ('--webserver-user' ,
169296 help = 'The webserver to use instead of auto-detection.' )
297+ parser .add_argument ('--webserver-configuration-directory' ,
298+ help = 'The webserver configuration directory to use instead of auto-detection.' )
299+ parser .add_argument ('--skip-api' ,
300+ help = 'Skip set-up of intelmq-api.' ,
301+ action = 'store_true' )
170302 args = parser .parse_args ()
171303
172304 basic_checks (skip_ownership = args .skip_ownership )
173305 intelmqsetup_core (ownership = not args .skip_ownership ,
174306 state_file = args .state_file )
175- if intelmq_api :
307+ if intelmq_api and not args . skip_api :
176308 print ('Running setup for intelmq-api.' )
177309 intelmqsetup_api (ownership = not args .skip_ownership ,
178310 webserver_user = args .webserver_user )
311+ print ('Running webserver setup for intelmq-api.' )
312+ intelmqsetup_api_webserver_configuration (webserver_configuration_directory = args .webserver_configuration_directory )
313+ else :
314+ print ('Skipping set-up of intelmq-api.' )
315+ if intelmq_manager and not args .skip_api :
316+ print ('Running webserver setup for intelmq-manager.' )
317+ intelmqsetup_manager_webserver_configuration (webserver_configuration_directory = args .webserver_configuration_directory )
318+ else :
319+ print ('Skipping set-up of intelmq-manager.' )
320+
321+ if NOTE_WEBSERVER_RELOAD :
322+ print ('Reload the webserver to make the changes effective.' )
323+
324+ print ("'intelmqsetup' completed." )
179325
180326
181327if __name__ == '__main__' :
0 commit comments