Skip to content

Commit 44f5c41

Browse files
orsiniumericwblukehindsLionelB5
authored
PEP-518 support: configure bandit via pyproject.toml (#401)
* parse config from toml * test toml config parsing * update docs * FIX pep8 "line too long" in tests * review * +extras * use setup.cfg for extras * fix setup.cfg * fix * Apply suggestions from code review Co-authored-by: Lionel Bersee <[email protected]> * Update doc/source/config.rst Co-authored-by: Lionel Bersee <[email protected]> * Update doc/source/config.rst Co-authored-by: Eric Brown <[email protected]> * actualize TOML config example in docs Co-authored-by: Eric Brown <[email protected]> Co-authored-by: Luke Hinds <[email protected]> Co-authored-by: Lionel Bersee <[email protected]>
1 parent d4faa78 commit 44f5c41

File tree

5 files changed

+123
-12
lines changed

5 files changed

+123
-12
lines changed

Diff for: bandit/core/config.py

+17-7
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,23 @@ def __init__(self, config_file=None):
3636
raise utils.ConfigError("Could not read config file.",
3737
config_file)
3838

39-
try:
40-
with f:
41-
self._config = yaml.safe_load(f)
42-
self.validate(config_file)
43-
except yaml.YAMLError as err:
44-
LOG.error(err)
45-
raise utils.ConfigError("Error parsing file.", config_file)
39+
if config_file.endswith('.toml'):
40+
import toml
41+
try:
42+
with f:
43+
self._config = toml.load(f)['tool']['bandit']
44+
except toml.TomlDecodeError as err:
45+
LOG.error(err)
46+
raise utils.ConfigError("Error parsing file.", config_file)
47+
else:
48+
try:
49+
with f:
50+
self._config = yaml.safe_load(f)
51+
except yaml.YAMLError as err:
52+
LOG.error(err)
53+
raise utils.ConfigError("Error parsing file.", config_file)
54+
55+
self.validate(config_file)
4656

4757
# valid config must be a dict
4858
if not isinstance(self._config, dict):

Diff for: doc/source/config.rst

+53
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,59 @@ several config files and pick from them using `-c`. If you only wish to control
3737
the specific tests that are to be run (and not their parameters) then using
3838
`-s` or `-t` on the command line may be more appropriate.
3939

40+
Also you can configure bandit via
41+
`pyproject.toml <https://www.python.org/dev/peps/pep-0518/>`_ file. In this
42+
case you would explicitly specify the path to configuration via `-c` too.
43+
For example:
44+
45+
.. code-block:: TOML
46+
47+
[tool.bandit]
48+
tests = ["B201", "B301"]
49+
skips = ["B101", "B601"]
50+
51+
[tool.bandit.any_other_function_with_shell_equals_true]
52+
no_shell = [
53+
"os.execl",
54+
"os.execle",
55+
"os.execlp",
56+
"os.execlpe",
57+
"os.execv",
58+
"os.execve",
59+
"os.execvp",
60+
"os.execvpe",
61+
"os.spawnl",
62+
"os.spawnle",
63+
"os.spawnlp",
64+
"os.spawnlpe",
65+
"os.spawnv",
66+
"os.spawnve",
67+
"os.spawnvp",
68+
"os.spawnvpe",
69+
"os.startfile"
70+
]
71+
shell = [
72+
"os.system",
73+
"os.popen",
74+
"os.popen2",
75+
"os.popen3",
76+
"os.popen4",
77+
"popen2.popen2",
78+
"popen2.popen3",
79+
"popen2.popen4",
80+
"popen2.Popen3",
81+
"popen2.Popen4",
82+
"commands.getoutput",
83+
"commands.getstatusoutput"
84+
]
85+
subprocess = [
86+
"subprocess.Popen",
87+
"subprocess.call",
88+
"subprocess.check_call",
89+
"subprocess.check_output"
90+
]
91+
92+
4093
Skipping Tests
4194
--------------
4295
The bandit config may contain optional lists of test IDs to either include

Diff for: setup.cfg

+7-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,13 @@ classifier =
2727
project_urls =
2828
Release notes = https://github.com/PyCQA/bandit/releases
2929

30-
[entry_points]
30+
[options.extras_require]
31+
yaml =
32+
PyYAML
33+
toml =
34+
toml
35+
36+
[options.entry_points]
3137
console_scripts =
3238
bandit = bandit.cli.main:main
3339
bandit-config-generator = bandit.cli.config_generator:main

Diff for: test-requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ hacking>=2.0.0 # Apache-2.0
77
stestr>=2.5.0 # Apache-2.0
88
testscenarios>=0.5.0 # Apache-2.0/BSD
99
testtools>=2.3.0 # MIT
10+
toml # MIT
1011
beautifulsoup4>=4.8.0 # MIT
1112
pylint==1.9.4 # GPLv2

Diff for: tests/unit/core/test_config.py

+45-4
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,16 @@
1616

1717

1818
class TempFile(fixtures.Fixture):
19-
def __init__(self, contents=None):
19+
def __init__(self, contents=None, suffix='.yaml'):
2020
super(TempFile, self).__init__()
2121
self.contents = contents
22+
self.suffix = suffix
2223

2324
def setUp(self):
2425
super(TempFile, self).setUp()
2526

26-
with tempfile.NamedTemporaryFile(mode='wt', delete=False) as f:
27+
with tempfile.NamedTemporaryFile(suffix=self.suffix, mode='wt',
28+
delete=False) as f:
2729
if self.contents:
2830
f.write(self.contents)
2931

@@ -112,7 +114,7 @@ def test_not_exist(self):
112114

113115

114116
class TestConfigCompat(testtools.TestCase):
115-
sample_yaml = textwrap.dedent("""
117+
sample = textwrap.dedent("""
116118
profiles:
117119
test_1:
118120
include:
@@ -157,10 +159,11 @@ class TestConfigCompat(testtools.TestCase):
157159
level: HIGH
158160
message: "{module} is considered insecure."
159161
""")
162+
suffix = '.yaml'
160163

161164
def setUp(self):
162165
super(TestConfigCompat, self).setUp()
163-
f = self.useFixture(TempFile(self.sample_yaml))
166+
f = self.useFixture(TempFile(self.sample, suffix=self.suffix))
164167
self.config = config.BanditConfig(f.name)
165168

166169
def test_converted_include(self):
@@ -252,3 +255,41 @@ def test_bad_yaml(self):
252255
self.config = config.BanditConfig(f.name)
253256
except utils.ConfigError as e:
254257
self.assertIn("Error parsing file.", e.message)
258+
259+
260+
class TestTomlConfig(TestConfigCompat):
261+
sample = textwrap.dedent("""
262+
[tool.bandit.profiles.test_1]
263+
include = [
264+
"any_other_function_with_shell_equals_true",
265+
"assert_used",
266+
]
267+
268+
[tool.bandit.profiles.test_2]
269+
include = ["blacklist_calls"]
270+
271+
[tool.bandit.profiles.test_3]
272+
include = ["blacklist_imports"]
273+
274+
[tool.bandit.profiles.test_4]
275+
exclude = ["assert_used"]
276+
277+
[tool.bandit.profiles.test_5]
278+
exclude = ["blacklist_calls", "blacklist_imports"]
279+
280+
[tool.bandit.profiles.test_6]
281+
include = ["blacklist_calls"]
282+
exclude = ["blacklist_imports"]
283+
284+
[[tool.bandit.blacklist_calls.bad_name_sets]]
285+
[tool.bandit.blacklist_calls.bad_name_sets.pickle]
286+
qualnames = ["pickle.loads"]
287+
message = "{func} library appears to be in use."
288+
289+
[[tool.bandit.blacklist_imports.bad_import_sets]]
290+
[tool.bandit.blacklist_imports.bad_import_sets.telnet]
291+
imports = ["telnetlib"]
292+
level = "HIGH"
293+
message = "{module} is considered insecure."
294+
""")
295+
suffix = '.toml'

0 commit comments

Comments
 (0)