bandit/bandit/bandit.py

166 lines
5.8 KiB
Python
Executable File

# -*- coding:utf-8 -*-
#
# Copyright 2014 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from __future__ import absolute_import
import argparse
import logging
import os
import sys
from bandit.core import extension_loader as ext_loader
from bandit.core import manager as b_manager
default_test_config = 'bandit.yaml'
def main():
extension_mgr = ext_loader.MANAGER
parser = argparse.ArgumentParser(
description='Bandit - a Python source code analyzer.'
)
parser.add_argument(
'targets', metavar='targets', type=str, nargs='+',
help='source file(s) or directory(s) to be tested'
)
parser.add_argument(
'-r', '--recursive', dest='recursive',
action='store_true', help='process files in subdirectories'
)
parser.add_argument(
'-a', '--aggregate', dest='agg_type',
action='store', default='file', type=str,
choices=['file', 'vuln'],
help='group results by vulnerability type or file it occurs in'
)
parser.add_argument(
'-n', '--number', dest='context_lines',
action='store', default=-1, type=int,
help='max number of code lines to display for each issue identified'
)
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')
)
parser.add_argument(
'-p', '--profile', dest='profile',
action='store', default=None, type=str,
help='test set profile in config to use (defaults to all tests)'
)
parser.add_argument(
'-l', '--level', dest='level', action='count',
default=1, help='results level filter'
)
parser.add_argument(
'-f', '--format', dest='output_format', action='store',
default='txt', help='specify output format',
choices=sorted(extension_mgr.formatter_names)
)
parser.add_argument(
'-o', '--output', dest='output_file', action='store',
default=None, help='write report to filename'
)
parser.add_argument(
'-v', '--verbose', dest='verbose', action='store_true',
help='show extra information like excluded and included files'
)
parser.add_argument(
'-d', '--debug', dest='debug', action='store_true',
help='turn on debug mode'
)
parser.set_defaults(debug=False)
parser.set_defaults(verbose=False)
parser.epilog = ('The following plugin suites were discovered and'
' loaded: [' +
', '.join(extension_mgr.plugin_names) + ']')
# setup work - parse arguments, and initialize BanditManager
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:
# no logger yet, so using print
print ("no config found, tried ...")
for path in config_paths:
if path:
print ("\t%s" % path)
sys.exit(2)
b_mgr = b_manager.BanditManager(config_file, args.agg_type,
args.debug, profile_name=args.profile,
verbose=args.verbose)
# we getLogger() here because BanditManager has configured it at this point
logger = logging.getLogger()
if args.output_format != "json":
logger.info("using config: %s", config_file)
logger.info("running on Python %d.%d.%d", sys.version_info.major,
sys.version_info.minor, sys.version_info.micro)
# check ability to write output file, if requested
if args.output_file is not None:
check_dest = b_mgr.check_output_destination(args.output_file)
if check_dest is not True:
logger.error(
'Problem with specified output destination\n\t%s: %s',
check_dest, args.output_file
)
sys.exit(2)
# initiate file discovery step within Bandit Manager
b_mgr.discover_files(args.targets, args.recursive)
# initiate execution of tests within Bandit Manager
b_mgr.run_tests()
if args.debug:
b_mgr.output_metaast()
# trigger output of results by Bandit Manager
b_mgr.output_results(args.context_lines, args.level - 1, args.output_file,
args.output_format)
# return an exit code of 1 if there are results, 0 otherwise
if b_mgr.results_count > 0:
sys.exit(1)
else:
sys.exit(0)
if __name__ == '__main__':
main()