Actually default to /etc/ rather than just claim

Previously, we were claiming to default to
/etc/bandit/bandit.yaml for config location, but we were
neither installing a config there, nor trying to use it at
run time.

This makes use of appdirs for locations to use platform
declared config locations.  This also tries to install
the bandit.yaml in /etc/bandit.yaml. (Or on a local
pip install: /usr/local/etc/bandit/bandit.yaml)

The searched paths are also added to the README to help
avoid ambiguity.

Change-Id: I29a9ff738ebb402a069b9750d26e4c94f85e861a
Closes-Bug: #1475510
Signed-off-by: Dave Walker (Daviey) <email@daviey.com>
This commit is contained in:
Dave Walker (Daviey) 2015-07-19 21:41:50 +01:00
parent 0a612ac3b8
commit 80c7798e51
5 changed files with 109 additions and 38 deletions

View File

@ -76,8 +76,8 @@ Usage::
max number of code lines to display for each issue
identified
-c CONFIG_FILE, --configfile CONFIG_FILE
test config file, defaults to /etc/bandit/bandit.yaml,
or./bandit.yaml if not given
if omitted default locations are checked. Check
documentation for searched paths
-p PROFILE, --profile PROFILE
test set profile in config to use (defaults to all
tests)
@ -107,14 +107,21 @@ The Bandit config file is used to set several things, including:
- other - plugins directory, included file types, shell display
colors, etc.
Bandit requires a config file. Bandit will use bandit.yaml in the following
preference order:
Bandit requires a config file which can be specified on the command line via
-c/--configfile. If this is not provided Bandit will search for a default
config file (bandit.yaml) in the following preference order:
- Bandit config file specified with ``-c`` command line option
- bandit.yaml file from current working directory
- bandit.yaml file from ``~/.config/bandit/``
- bandit.yaml file in ``config/`` directory of the Bandit package
GNU/Linux:
- ./bandit.yaml
- ~/.config/bandit/bandit.yaml
- /etc/bandit/bandit.yaml
- /usr/local/etc/bandit/bandit.yaml
Mac OSX:
- ./bandit.yaml
- /Users/${USER}/Library/Application Support/bandit/bandit.yaml
- /Library/Application Support/bandit/bandit.yaml
- /usr/local/etc/bandit/bandit.yaml
Exclusions
----------

65
bandit/bandit.py Executable file → Normal file
View File

@ -20,9 +20,13 @@ import logging
import os
import sys
from bandit.core import manager as b_manager
from appdirs import site_config_dir
from appdirs import user_config_dir
default_test_config = 'bandit.yaml'
from bandit.core import manager as b_manager
from bandit.core import utils
BASE_CONFIG = '/bandit.yaml'
def _init_logger(debug=False, log_format=None):
@ -55,10 +59,34 @@ def _init_extensions():
return ext_loader.MANAGER
def _find_config():
# prefer config file in the following order:
# 1) current directory, 2) user home directory, 3) bundled config
config_dirs = (['.'] + [user_config_dir("bandit")] +
site_config_dir("bandit", multipath=True).split(':'))
config_locations = [s + BASE_CONFIG for s in config_dirs]
# pip on Mac installs to the following path, but appdirs expects to
# follow Mac's BPFileSystem spec which doesn't include this path so
# we'll insert it. Issue raised as http://git.io/vOreU
mac_pip_cfg_path = "/usr/local/etc/bandit/bandit.yaml"
if mac_pip_cfg_path not in config_locations:
config_locations.append(mac_pip_cfg_path)
for config_file in config_locations:
if os.path.isfile(config_file):
return config_file # Found a valid config
else:
# Failed to find any config, raise an error.
raise utils.NoConfigFileFound(config_locations)
def main():
# bring our logging stuff up as early as possible
debug = ('-d' in sys.argv or '--debug' in sys.argv)
logger = _init_logger(debug)
# By default path would be /etx/xdg/bandit, we want system paths
os.environ['XDG_CONFIG_DIRS'] = '/etc:/usr/local/etc'
extension_mgr = _init_extensions()
# now do normal startup
@ -87,8 +115,8 @@ def main():
parser.add_argument(
'-c', '--configfile', dest='config_file',
action='store', default=None, type=str,
help=('test config file, defaults to /etc/bandit/bandit.yaml, or'
'./bandit.yaml if not given')
help=('if omitted default locations are checked. '
'Check documentation for searched paths')
)
parser.add_argument(
'-p', '--profile', dest='profile',
@ -135,30 +163,11 @@ def main():
args = parser.parse_args()
config_file = args.config_file
if not config_file:
home_config = None
# attempt to get the home directory from environment
home_dir = os.environ.get('HOME')
if home_dir:
home_config = "%s/.config/bandit/%s" % (home_dir,
default_test_config)
installed_config = str(os.path.dirname(os.path.realpath(__file__)) +
'/config/%s' % default_test_config)
# prefer config file in the following order:
# 1) current directory, 2) user home directory, 3) bundled config
config_paths = [default_test_config, home_config, installed_config]
for path in config_paths:
if path and os.access(path, os.R_OK):
config_file = path
break
if not config_file:
logger.error("no config found, tried:\n%s", '\t'.join(config_paths))
sys.exit(2)
try:
config_file = _find_config()
except utils.NoConfigFileFound as e:
logger.error(e)
sys.exit(2)
b_mgr = b_manager.BanditManager(config_file, args.agg_type,
args.debug, profile_name=args.profile,

View File

@ -181,6 +181,13 @@ class InvalidModulePath(Exception):
pass
class NoConfigFileFound(Exception):
def __init__(self, config_locations):
message = ("no config found - tried: " +
", ".join(config_locations))
super(NoConfigFileFound, self).__init__(message)
def get_module_qualname_from_path(path):
'''Get the module's qualified name by analysis of the path.

View File

@ -96,10 +96,9 @@ bandit.plugins =
try_except_pass = bandit.plugins.try_except_pass:try_except_pass
[files]
package_data =
bandit = config/bandit.yaml
data_files =
bandit =
etc/bandit/ = bandit/config/bandit.yaml
share/bandit/wordlist/ = wordlist/default-passwords
[build_sphinx]

49
tests/test_config.py Normal file
View File

@ -0,0 +1,49 @@
import fixtures
import logging
import mock
import os
import unittest
from appdirs import site_config_dir
from appdirs import user_config_dir
from bandit import bandit
from bandit.core import utils
BASE_CONFIG = '/bandit.yaml'
class ConfigTests(fixtures.TestWithFixtures):
def is_current_config(self, arg):
return arg == self.current_config
def setUp(self):
super(ConfigTests, self).setUp()
self.useFixture(fixtures.EnvironmentVariable('XDG_CONFIG_DIRS', '/etc:/usr/local/etc'))
# Mock os.path.isfile with one that selectively returns
# True if location being considered is the present one.
patcher = mock.patch('os.path.isfile', side_effect=self.is_current_config)
self.mocked_isfile = patcher.start()
self.addCleanup(patcher.stop)
def test_find_configs(self):
#TODO(Daviey): Mock user_config_dir to make input deterministic
# and test multi-platform locations.
config_dirs = (['.'] + [user_config_dir("bandit")] +
site_config_dir("bandit", multipath=True).split(':'))
config_locations = [s + BASE_CONFIG for s in config_dirs]
# check that at least 3 location paths were generated
self.assertLess(3, len(config_locations))
# Iterate through found locations
for c in config_locations:
self.current_config = c
ret = bandit._find_config()
self.assertEquals(self.current_config, ret)
def test_cannot_find_configs(self):
self.current_config = "/invalid/file"
with self.assertRaises(utils.NoConfigFileFound):
bandit._find_config()