%PDF- %PDF-
| Direktori : /backups/router/usr/local/lib/suricata/python/suricata/update/ |
| Current File : //backups/router/usr/local/lib/suricata/python/suricata/update/config.py |
# Copyright (C) 2017 Open Information Security Foundation
# Copyright (c) 2015-2017 Jason Ish
#
# You can copy, redistribute or modify this Program under the terms of
# the GNU General Public License version 2 as published by the Free
# Software Foundation.
#
# This program 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
# version 2 along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
import os.path
import logging
import yaml
import suricata.update.engine
from suricata.update.exceptions import ApplicationError
try:
from suricata.config import defaults
has_defaults = True
except:
has_defaults = False
logger = logging.getLogger()
DEFAULT_DATA_DIRECTORY = "/var/lib/suricata"
# Cache directory - relative to the data directory.
CACHE_DIRECTORY = os.path.join("update", "cache")
# Source directory - relative to the data directory.
SOURCE_DIRECTORY = os.path.join("update", "sources")
# Configuration keys.
DATA_DIRECTORY_KEY = "data-directory"
CACHE_DIRECTORY_KEY = "cache-directory"
IGNORE_KEY = "ignore"
DISABLE_CONF_KEY = "disable-conf"
ENABLE_CONF_KEY = "enable-conf"
MODIFY_CONF_KEY = "modify-conf"
DROP_CONF_KEY = "drop-conf"
LOCAL_CONF_KEY = "local"
OUTPUT_KEY = "output"
DIST_RULE_DIRECTORY_KEY = "dist-rule-directory"
if has_defaults:
DEFAULT_UPDATE_YAML_PATH = os.path.join(defaults.sysconfdir, "update.yaml")
else:
DEFAULT_UPDATE_YAML_PATH = "/etc/suricata/update.yaml"
DEFAULT_SURICATA_YAML_PATH = [
"/etc/suricata/suricata.yaml",
"/usr/local/etc/suricata/suricata.yaml",
"/etc/suricata/suricata-debian.yaml"
]
if has_defaults:
DEFAULT_DIST_RULE_PATH = [
defaults.datarulesdir,
"/etc/suricata/rules",
]
else:
DEFAULT_DIST_RULE_PATH = [
"/etc/suricata/rules",
]
DEFAULT_CONFIG = {
"sources": [],
LOCAL_CONF_KEY: [],
# The default file patterns to ignore.
"ignore": [
"*deleted.rules",
],
}
_args = None
_config = {}
# The filename the config was read from, if any.
filename = None
def has(key):
"""Return true if a configuration key exists."""
return key in _config
def set(key, value):
"""Set a configuration value."""
_config[key] = value
def get(key):
"""Get a configuration value."""
if key in _config:
return _config[key]
return None
def set_state_dir(directory):
_config[DATA_DIRECTORY_KEY] = directory
def get_state_dir():
"""Get the data directory. This is more of the Suricata state
directory than a specific Suricata-Update directory, and is used
as the root directory for Suricata-Update data.
"""
if os.getenv("DATA_DIRECTORY"):
return os.getenv("DATA_DIRECTORY")
if DATA_DIRECTORY_KEY in _config:
return _config[DATA_DIRECTORY_KEY]
return DEFAULT_DATA_DIRECTORY
def set_cache_dir(directory):
"""Set an alternate cache directory."""
_config[CACHE_DIRECTORY_KEY] = directory
def get_cache_dir():
"""Get the cache directory."""
if CACHE_DIRECTORY_KEY in _config:
return _config[CACHE_DIRECTORY_KEY]
return os.path.join(get_state_dir(), CACHE_DIRECTORY)
def get_output_dir():
"""Get the rule output directory."""
if OUTPUT_KEY in _config:
return _config[OUTPUT_KEY]
return os.path.join(get_state_dir(), "rules")
def args():
"""Return sthe parsed argument object."""
return _args
def get_arg(key):
key = key.replace("-", "_")
if hasattr(_args, key):
val = getattr(_args, key)
if val not in [[], None]:
return val
return None
def init(args):
global _args
global filename
_args = args
_config.update(DEFAULT_CONFIG)
if args.config:
logger.info("Loading %s", args.config)
with open(args.config, "rb") as fileobj:
config = yaml.safe_load(fileobj)
if config:
_config.update(config)
filename = args.config
elif os.path.exists(DEFAULT_UPDATE_YAML_PATH):
logger.info("Loading %s", DEFAULT_UPDATE_YAML_PATH)
with open(DEFAULT_UPDATE_YAML_PATH, "rb") as fileobj:
config = yaml.safe_load(fileobj)
if config:
_config.update(config)
filename = DEFAULT_UPDATE_YAML_PATH
# Apply command line arguments to the config.
for arg in vars(args):
if arg == "local":
for local in args.local:
logger.debug("Adding local ruleset to config: %s", local)
_config[LOCAL_CONF_KEY].append(local)
elif arg == "data_dir" and args.data_dir:
logger.debug("Setting data directory to %s", args.data_dir)
_config[DATA_DIRECTORY_KEY] = args.data_dir
elif getattr(args, arg) is not None:
key = arg.replace("_", "-")
val = getattr(args, arg)
logger.debug("Setting configuration value %s -> %s", key, val)
_config[key] = val
# Find and set the path to suricata if not provided.
if "suricata" in _config:
if not os.path.exists(_config["suricata"]):
raise ApplicationError(
"Configured path to suricata does not exist: %s" % (
_config["suricata"]))
else:
suricata_path = suricata.update.engine.get_path()
if not suricata_path:
logger.warning("No suricata application binary found on path.")
else:
_config["suricata"] = suricata_path
if "suricata" in _config:
build_info = suricata.update.engine.get_build_info(_config["suricata"])
# Set the first suricata.yaml to check for to the one in the
# --sysconfdir provided by build-info.
if not "suricata_conf" in _config and "sysconfdir" in build_info:
DEFAULT_SURICATA_YAML_PATH.insert(
0, os.path.join(
build_info["sysconfdir"], "suricata/suricata.yaml"))
# Amend the path to look for Suricata provided rules based on
# the build info. As we are inserting at the front, put the
# highest priority path last.
if "sysconfdir" in build_info:
DEFAULT_DIST_RULE_PATH.insert(
0, os.path.join(build_info["sysconfdir"], "suricata/rules"))
if "datarootdir" in build_info:
DEFAULT_DIST_RULE_PATH.insert(
0, os.path.join(build_info["datarootdir"], "suricata/rules"))
# Set the data-directory prefix to that of the --localstatedir
# found in the build-info.
if not DATA_DIRECTORY_KEY in _config and "localstatedir" in build_info:
data_directory = os.path.join(
build_info["localstatedir"], "lib/suricata")
logger.info("Using data-directory %s.", data_directory)
_config[DATA_DIRECTORY_KEY] = data_directory
# Fixup the default locations for Suricata-Update configuration files, but only if
# they exist, otherwise keep the defaults.
conf_search_path = ["/etc"]
if "sysconfdir" in build_info:
sysconfdir = build_info["sysconfdir"]
if not sysconfdir in conf_search_path:
conf_search_path.insert(0, sysconfdir)
configs = (
("disable-conf", "disable.conf"),
("enable-conf", "enable.conf"),
("drop-conf", "drop.conf"),
("modify-conf", "modify.conf"),
)
for key, filename in configs:
if getattr(args, key.replace("-", "_"), None) is not None:
continue
if _config.get(key) is not None:
continue
for conf_dir in conf_search_path:
config_path = os.path.join(conf_dir, "suricata", filename)
logger.debug("Looking for {}".format(config_path))
if os.path.exists(config_path):
logger.debug("Found {}".format(config_path))
logger.debug("Using {} for {}".format(config_path, key))
_config[key] = config_path
break
# If suricata-conf not provided on the command line or in the
# configuration file, look for it.
if not "suricata-conf" in _config:
for conf in DEFAULT_SURICATA_YAML_PATH:
if os.path.exists(conf):
logger.info("Using Suricata configuration %s" % (conf))
_config["suricata-conf"] = conf
break
if not DIST_RULE_DIRECTORY_KEY in _config:
for path in DEFAULT_DIST_RULE_PATH:
if os.path.exists(path):
logger.info("Using %s for Suricata provided rules.", path)
_config[DIST_RULE_DIRECTORY_KEY] = path
break