Esempio n. 1
0
    def __init__(self, configuration_directory, install_directory, log_directory, capture_network_interfaces,
                 download_suricata_archive=True, stdout=True, verbose=False):
        """
        Install Suricata
        
        :param configuration_directory: Path to the configuration directory (E.G /etc/dynamite/suricata)
        :param install_directory: Path to the install directory (E.G /opt/dynamite/suricata/)
        :param log_directory: Path to the log directory (E.G /var/log/dynamite/suricata/)
        :param capture_network_interfaces: A list of network interfaces to capture on (E.G ["mon0", "mon1"])
        :param download_suricata_archive: If True, download the Suricata archive from a mirror
        :param stdout: Print the output to console
        :param verbose: Include detailed debug messages
        """

        self.configuration_directory = configuration_directory
        self.install_directory = install_directory
        self.log_directory = log_directory
        self.capture_network_interfaces = capture_network_interfaces
        self.download_suricata_archive = download_suricata_archive
        self.stdout = stdout
        self.verbose = verbose
        install.BaseInstallManager.__init__(self, 'suricata', verbose=self.verbose, stdout=stdout)

        utilities.create_dynamite_environment_file()
        if download_suricata_archive:
            try:
                self.logger.info("Attempting to download Suricata archive.")
                self.download_from_mirror(const.SURICATA_MIRRORS, const.SURICATA_ARCHIVE_NAME, stdout=stdout,
                                          verbose=verbose)
            except general_exceptions.DownloadError as e:
                self.logger.error("Failed to download Suricata archive.")
                self.logger.debug("Failed to download Suricata archive, threw: {}.".format(e))
                raise suricata_exceptions.InstallSuricataError("Failed to download Suricata archive.")
        try:
            self.logger.info("Attempting to extract Suricata archive ({}).".format(const.SURICATA_ARCHIVE_NAME))
            self.extract_archive(os.path.join(const.INSTALL_CACHE, const.SURICATA_ARCHIVE_NAME))
            self.logger.info("Extraction completed.")
        except general_exceptions.ArchiveExtractionError as e:
            self.logger.error("Failed to extract Suricata archive.")
            self.logger.debug("Failed to extract Suricata archive, threw: {}.".format(e))
            raise suricata_exceptions.InstallSuricataError("Failed to extract Suricata archive")
        try:
            self.install_dependencies(stdout=stdout, verbose=verbose)
        except (general_exceptions.InvalidOsPackageManagerDetectedError,
                general_exceptions.OsPackageManagerRefreshError):
            raise suricata_exceptions.InstallSuricataError("One or more OS dependencies failed to install.")
        if not self.validate_capture_network_interfaces(self.capture_network_interfaces):
            self.logger.error(
                "One or more defined network interfaces is invalid: {}".format(capture_network_interfaces))
            raise suricata_exceptions.InstallSuricataError(
                "One or more defined network interfaces is invalid: {}".format(capture_network_interfaces))
Esempio n. 2
0
    def _copy_suricata_files_and_directories(self):
        self.logger.info('Creating Suricata installation, configuration, and logging directories.')
        try:
            utilities.makedirs(self.install_directory, exist_ok=True)
            utilities.makedirs(self.configuration_directory, exist_ok=True)
            utilities.makedirs(self.log_directory, exist_ok=True)
        except Exception as e:
            self.logger.error('Failed to create required directory structure.')
            self.logger.debug("Failed to create required directory structure; {}".format(e))
            raise suricata_exceptions.InstallSuricataError(
                "Failed to create required directory structure; {}".format(e))
        try:
            utilities.makedirs(os.path.join(self.configuration_directory, 'rules'), exist_ok=True)
        except Exception as e:
            self.logger.error('Unable to re-create Suricata rules directory.')
            self.logger.debug('Unable to re-create Suricata rules directory: {}'.format(e))
        try:
            shutil.copy(os.path.join(const.DEFAULT_CONFIGS, 'suricata', 'suricata.yaml'),
                        os.path.join(self.configuration_directory, 'suricata.yaml'))
        except Exception as e:
            self.logger.error("General error while attempting to copy {} to {}.".format(
                os.path.join(const.DEFAULT_CONFIGS, 'suricata', 'suricata.yaml'), self.configuration_directory))

            self.logger.debug("General error while attempting to copy {} to {}; {}".format(
                os.path.join(const.DEFAULT_CONFIGS, 'suricata', 'suricata.yaml'), self.configuration_directory, e))

            raise suricata_exceptions.InstallSuricataError(
                "General error while attempting to copy {} to {}; {}".format(
                    os.path.join(const.DEFAULT_CONFIGS, 'suricata', 'suricata.yaml'), self.configuration_directory, e))
        try:
            utilities.copytree(os.path.join(const.INSTALL_CACHE, const.SURICATA_DIRECTORY_NAME, 'rules'),
                               os.path.join(self.configuration_directory, 'rules'))
        except Exception as e:
            self.logger.error("General error while attempting to copy {} to {}.".format(
                os.path.join(const.INSTALL_CACHE, const.SURICATA_DIRECTORY_NAME, 'rules'),
                os.path.join(self.configuration_directory, 'rules')))

            self.logger.debug("General error while attempting to copy {} to {}; {}".format(
                os.path.join(const.INSTALL_CACHE, const.SURICATA_DIRECTORY_NAME, 'rules'),
                os.path.join(self.configuration_directory, 'rules'), e))

            raise suricata_exceptions.InstallSuricataError(
                "General error while attempting to copy {} to {}; {}".format(
                    os.path.join(const.INSTALL_CACHE, const.SURICATA_DIRECTORY_NAME, 'rules'),
                    os.path.join(self.configuration_directory, 'rules'), e))
Esempio n. 3
0
 def setup_suricata(self):
     """
     Setup Suricata IDS with AF_PACKET support
     """
     env_file = os.path.join(const.CONFIG_PATH, 'environment')
     self._copy_suricata_files_and_directories()
     self._configure_and_compile_suricata()
     try:
         with open(env_file) as env_f:
             if 'SURICATA_HOME' not in env_f.read():
                 self.logger.info('Updating Suricata default home path [{}]'.format(self.install_directory))
                 subprocess.call('echo SURICATA_HOME="{}" >> {}'.format(self.install_directory, env_file),
                                 shell=True)
             if 'SURICATA_CONFIG' not in env_f.read():
                 self.logger.info('Updating Suricata default config path [{}]'.format(self.configuration_directory))
                 subprocess.call('echo SURICATA_CONFIG="{}" >> {}'.format(
                     self.configuration_directory, env_file), shell=True)
     except IOError:
         self.logger.error("Failed to open {} for reading.".format(env_file))
         raise suricata_exceptions.InstallSuricataError(
             "Failed to open {} for reading.".format(env_file))
     except Exception as e:
         self.logger.error("General error while creating environment variables in {}.".format(env_file))
         self.logger.debug("General error while creating environment variables in {}; {}".format(env_file, e))
         raise suricata_exceptions.InstallSuricataError(
             "General error while creating environment variables in {}; {}".format(env_file, e))
     try:
         config = suricata_configs.ConfigManager(self.configuration_directory)
     except suricata_exceptions.ReadsSuricataConfigError:
         self.logger.error("Failed to read Suricata configuration.")
         raise suricata_exceptions.InstallSuricataError("Failed to read Suricata configuration.")
     config.af_packet_interfaces = []
     for interface in self.capture_network_interfaces:
         config.add_afpacket_interface(interface, threads='auto', cluster_id=99)
     try:
         config.write_config()
     except suricata_exceptions.WriteSuricataConfigError:
         self.logger.error("Failed to write Suricata configuration.")
         suricata_exceptions.InstallSuricataError("Could not write Suricata configurations.")
     try:
         sysctl = systemctl.SystemCtl()
     except general_exceptions.CallProcessError:
         raise suricata_exceptions.InstallSuricataError("Could not find systemctl.")
     self.logger.info("Installing Suricata systemd Service.")
     if not sysctl.install_and_enable(os.path.join(const.DEFAULT_CONFIGS, 'systemd', 'suricata.service')):
         raise suricata_exceptions.InstallSuricataError("Failed to install Suricata systemd service.")
Esempio n. 4
0
 def _configure_and_compile_suricata(self):
     if self.configuration_directory.endswith('/'):
         suricata_config_parent = '/'.join(
             self.configuration_directory.split('/')[:-2])
     else:
         suricata_config_parent = '/'.join(
             self.configuration_directory.split('/')[:-1])
     self.logger.info(
         'Compiling Suricata from source. This can take up to 5 to 10 minutes.'
     )
     if self.stdout:
         utilities.print_coffee_art()
     time.sleep(1)
     self.logger.info('Configuring Suricata.')
     if self.verbose:
         suricata_config_p = subprocess.Popen(
             './configure --prefix={} --sysconfdir={} --localstatedir=/var/dynamite/suricata'
             .format(self.install_directory, suricata_config_parent),
             shell=True,
             cwd=os.path.join(const.INSTALL_CACHE,
                              const.SURICATA_DIRECTORY_NAME))
     else:
         suricata_config_p = subprocess.Popen(
             './configure --prefix={} --sysconfdir={} --localstatedir=/var/dynamite/suricata'
             .format(self.install_directory, suricata_config_parent),
             shell=True,
             cwd=os.path.join(const.INSTALL_CACHE,
                              const.SURICATA_DIRECTORY_NAME),
             stdout=subprocess.PIPE,
             stderr=subprocess.PIPE)
     try:
         suricata_config_p.communicate()
     except Exception as e:
         self.logger.error(
             "General error occurred while configuring Suricata.")
         self.logger.debug(
             "General error occurred while configuring Suricata; {}".format(
                 e))
         raise suricata_exceptions.InstallSuricataError(
             "General error occurred while configuring Suricata; {}".format(
                 e))
     if suricata_config_p.returncode != 0:
         self.logger.error(
             "Zeek configuration process returned non-zero; exit-code: {}".
             format(suricata_config_p.returncode))
         raise suricata_exceptions.InstallSuricataError(
             "Suricata configuration process returned non-zero; exit-code: {}"
             .format(suricata_config_p.returncode))
     time.sleep(1)
     self.logger.info("Compiling Suricata.")
     if utilities.get_cpu_core_count() > 1:
         parallel_threads = utilities.get_cpu_core_count() - 1
     else:
         parallel_threads = 1
     if self.verbose:
         compile_suricata_process = subprocess.Popen(
             'make -j {}; make install; make install-conf'.format(
                 parallel_threads),
             shell=True,
             cwd=os.path.join(const.INSTALL_CACHE,
                              const.SURICATA_DIRECTORY_NAME))
         try:
             compile_suricata_process.communicate()
         except Exception as e:
             self.logger.error(
                 "General error occurred while compiling Suricata.")
             self.logger.debug(
                 "General error occurred while compiling Suricata; {}".
                 format(e))
             raise suricata_exceptions.InstallSuricataError(
                 "General error occurred while compiling Suricata; {}".
                 format(e))
         compile_suricata_return_code = compile_suricata_process.returncode
     else:
         compile_suricata_process = subprocess.Popen(
             'make -j {}; make install; make install-conf'.format(
                 parallel_threads),
             shell=True,
             cwd=os.path.join(const.INSTALL_CACHE,
                              const.SURICATA_DIRECTORY_NAME),
             stdout=subprocess.PIPE,
             stderr=subprocess.PIPE)
         try:
             compile_suricata_return_code = utilities.run_subprocess_with_status(
                 compile_suricata_process, expected_lines=935)
         except Exception as e:
             self.logger.error(
                 "General error occurred while compiling Suricata.")
             self.logger.debug(
                 "General error occurred while compiling Suricata; {}".
                 format(e))
             raise suricata_exceptions.InstallSuricataError(
                 "General error occurred while compiling Suricata; {}".
                 format(e))
     if compile_suricata_return_code != 0:
         self.logger.error(
             "Failed to compile Suricata from source; error code: {}; run with --verbose flag for more info."
             .format(compile_suricata_return_code))
         raise suricata_exceptions.InstallSuricataError(
             "Suricata compilation process returned non-zero; exit-code: {}"
             .format(compile_suricata_return_code))
Esempio n. 5
0
    def setup_suricata_rules(self):
        """
        Installs Oinkmaster, sets up rules, and disables unneeded rule sets.
        """
        self.logger.info("Installing Suricata Rules (via Oinkmaster).")
        oink_installer = rules_install.InstallManager(
            download_oinkmaster_archive=True,
            stdout=self.stdout,
            verbose=self.verbose,
            install_directory=os.path.join(self.install_directory,
                                           'oinkmaster'))
        try:
            oink_installer.setup_oinkmaster()
        except oinkmaster_exceptions.InstallOinkmasterError as e:
            self.logger.error("Unable to install Oinkmaster dependency.")
            self.logger.debug(
                "Unable to install Oinkmaster dependency; {}".format(e))
            raise suricata_exceptions.InstallSuricataError(
                "Unable to install Oinkmaster dependency.")

        try:
            self.logger.info("Updating Suricata Rules (via Oinkmaster)")
            rules_install.update_suricata_rules()
        except oinkmaster_exceptions.UpdateSuricataRulesError as e:
            self.logger.error("Unable to update Suricata rule-sets.")
            self.logger.debug(
                "Unable to update Suricata rule-sets; {}".format(e))
            raise suricata_exceptions.InstallSuricataError(
                "Unable to update Suricata rule-sets.")
        try:
            config = suricata_configs.ConfigManager(
                self.configuration_directory)
        except suricata_exceptions.ReadsSuricataConfigError:
            self.logger.error("Failed to read Suricata configuration.")
            raise suricata_exceptions.InstallSuricataError(
                "Failed to read Suricata configuration.")
        config.default_log_directory = self.log_directory
        config.suricata_log_output_file = os.path.join(self.log_directory,
                                                       'suricata.log')
        config.default_rules_directory = os.path.join(
            self.configuration_directory, 'rules')
        config.reference_config_file = os.path.join(
            self.configuration_directory, 'reference.config')
        config.classification_file = os.path.join(self.configuration_directory,
                                                  'rules',
                                                  'classification.config')

        # Disable Unneeded Suricata rules
        try:
            self.logger.debug("Disabling Suricata Rule: 'http-events.rules'")
            config.disable_rule('http-events.rules')

            self.logger.debug("Disabling Suricata Rule: 'smtp-events.rules'")
            config.disable_rule('smtp-events.rules')

            self.logger.debug("Disabling Suricata Rule: 'dns-events.rules'")
            config.disable_rule('dns-events.rules')

            self.logger.debug("Disabling Suricata Rule: 'tls-events.rules'")
            config.disable_rule('tls-events.rules')

            self.logger.debug("Disabling Suricata Rule: 'drop.rules'")
            config.disable_rule('drop.rules')

            self.logger.debug("Disabling Suricata Rule: 'emerging-p2p.rules'")
            config.disable_rule('emerging-p2p.rules')

            self.logger.debug("Disabling Suricata Rule: 'emerging-pop3.rules'")
            config.disable_rule('emerging-pop3.rules')

            self.logger.debug(
                "Disabling Suricata Rule: 'emerging-telnet.rules'")
            config.disable_rule('emerging-telnet.rules')

            self.logger.debug("Disabling Suricata Rule: 'http-events.rules'")
            config.disable_rule('emerging-tftp.rules')

            self.logger.debug("Disabling Suricata Rule: 'emerging-voip.rules'")
            config.disable_rule('emerging-voip.rules')

        except suricata_exceptions.SuricataRuleNotFoundError:
            self.logger.error('Could not disable one or more Suricata rules.')
            raise suricata_exceptions.InstallSuricataError(
                "Could not disable one or more Suricata rules.")
        try:
            config.write_config()
        except suricata_exceptions.WriteSuricataConfigError:
            self.logger.error('Could not write Suricata configurations.')
            suricata_exceptions.InstallSuricataError(
                "Could not write Suricata configurations.")