Skip to content

Commit 1e1250a

Browse files
Make blint more usable as a library (#123)
* Deduplicate metadata export code. Signed-off-by: Caroline Russell <[email protected]> * Use CJD for io. Signed-off-by: Caroline Russell <[email protected]> * Refactor modules to be more usable as libraries. Signed-off-by: Caroline Russell <[email protected]> * Bump cjd. Signed-off-by: Caroline Russell <[email protected]> Move modules to lib. Signed-off-by: Caroline Russell <[email protected]> * Bump version. Signed-off-by: Caroline Russell <[email protected]> * Set defaults in parser. Signed-off-by: Caroline Russell <[email protected]> * Corrections. Signed-off-by: Caroline Russell <[email protected]> * Fix sbom_mode cmdline arg. Signed-off-by: Caroline Russell <[email protected]> * bint_options changed Signed-off-by: Aryan Rajoria <[email protected]> --------- Signed-off-by: Caroline Russell <[email protected]> Signed-off-by: Aryan Rajoria <[email protected]> Co-authored-by: Aryan Rajoria <[email protected]>
1 parent fae0647 commit 1e1250a

File tree

10 files changed

+724
-500
lines changed

10 files changed

+724
-500
lines changed

blint/cli.py

Lines changed: 40 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
# -*- coding: utf-8 -*-
33

44
import argparse
5-
import logging
65
import os
7-
import sys
86

9-
from blint.lib.analysis import AnalysisRunner, report
7+
from blint.lib.runners import run_default_mode, run_sbom_mode
8+
from blint.lib.runners import AnalysisRunner, run_default_mode, run_sbom_mode
9+
from blint.config import BlintOptions
1010
from blint.logger import LOG
1111
from blint.lib.sbom import generate
1212
from blint.lib.utils import gen_file_list
@@ -25,10 +25,23 @@ def build_args():
2525
"""
2626
Constructs command line arguments for the blint tool
2727
"""
28+
parser = build_parser()
29+
return parser.parse_args()
30+
31+
32+
def build_parser():
2833
parser = argparse.ArgumentParser(
2934
prog="blint",
3035
description="Binary linter and SBOM generator.",
3136
)
37+
parser.set_defaults(
38+
deep_mode=False,
39+
sbom_output="",
40+
stdout_mode=False,
41+
exports_prefix=[],
42+
src_dir_boms=[],
43+
sbom_mode=False
44+
)
3245
parser.add_argument(
3346
"-i",
3447
"--src",
@@ -82,14 +95,14 @@ def build_args():
8295
sbom_parser = subparsers.add_parser(
8396
"sbom", help="Command to generate SBOM for supported binaries."
8497
)
98+
sbom_parser.set_defaults(sbom_mode=True)
8599
sbom_parser.add_argument(
86100
"-i",
87101
"--src",
88102
dest="src_dir_image",
89103
action="extend",
90104
nargs="+",
91-
help="Source directories, container images or binary files. Defaults "
92-
"to current directory.",
105+
help="Source directories, container images or binary files. Defaults to current directory.",
93106
)
94107
sbom_parser.add_argument(
95108
"-o",
@@ -127,7 +140,8 @@ def build_args():
127140
nargs="+",
128141
help="Directories containing pre-build and build BOMs. Use to improve the precision.",
129142
)
130-
return parser.parse_args()
143+
144+
return parser
131145

132146

133147
def parse_input(src):
@@ -153,68 +167,40 @@ def parse_input(src):
153167
def handle_args():
154168
"""Handles the command-line arguments.
155169
156-
This function parses the command-line arguments and returns the parsed
157-
arguments, reports directory, and source directory.
170+
This function parses the command-line arguments and returns a BlintOptions object
158171
159172
Returns:
160-
tuple: A tuple containing the parsed arguments, reports directory, and
161-
source directory.
173+
BlintOptions: A class containing the parsed command-line arguments
162174
"""
163175
args = build_args()
164176
if not args.no_banner and args.subcommand_name != "sbom":
165177
print(BLINT_LOGO)
166-
if not args.src_dir_image:
167-
args.src_dir_image = [os.getcwd()]
168-
if not os.getenv("CI"):
169-
src_dirs = args.src_dir_image
170-
else:
171-
src_dirs = parse_input(args.src_dir_image)
172-
173-
# Create reports directory
174-
reports_dir = args.reports_dir
175-
176-
for src in src_dirs:
177-
if not os.path.exists(src):
178-
LOG.error(f"{src} is an invalid file or directory!")
179-
sys.exit(1)
180-
return args, reports_dir, src_dirs
178+
blint_options = BlintOptions(
179+
deep_mode=args.deep_mode,
180+
exports_prefix=args.exports_prefix,
181+
fuzzy=args.suggest_fuzzable,
182+
no_error=args.noerror,
183+
no_reviews=args.no_reviews,
184+
reports_dir=args.reports_dir,
185+
sbom_mode=args.sbom_mode,
186+
sbom_output=args.sbom_output,
187+
src_dir_boms=args.src_dir_boms,
188+
src_dir_image=args.src_dir_image,
189+
stdout_mode=args.stdout_mode
190+
)
191+
return blint_options
181192

182193

183194
def main():
184195
"""Main function of the blint tool"""
185-
args, reports_dir, src_dirs = handle_args()
196+
blint_options = handle_args()
186197

187198
# SBOM command
188-
if args.subcommand_name == "sbom":
189-
if args.stdout_mode:
190-
sbom_output = sys.stdout
191-
LOG.setLevel(logging.ERROR)
192-
else:
193-
if args.sbom_output:
194-
sbom_output = args.sbom_output
195-
if os.path.isdir(sbom_output):
196-
sbom_output = os.path.join(sbom_output, "bom-post-build.cdx.json")
197-
else:
198-
sbom_output = os.path.join(os.getcwd(), "bom-post-build.cdx.json")
199-
sbom_output_dir = os.path.dirname(sbom_output)
200-
if sbom_output_dir and not os.path.exists(sbom_output_dir):
201-
os.makedirs(sbom_output_dir)
202-
generate(src_dirs, sbom_output, args.deep_mode, args.exports_prefix, args.src_dir_boms)
199+
if blint_options.sbom_mode:
200+
run_sbom_mode(blint_options)
203201
# Default case
204202
else:
205-
if reports_dir and not os.path.exists(reports_dir):
206-
os.makedirs(reports_dir)
207-
files = gen_file_list(src_dirs)
208-
analyzer = AnalysisRunner()
209-
findings, reviews, fuzzables = analyzer.start(
210-
files, reports_dir, args.no_reviews, args.suggest_fuzzable
211-
)
212-
report(src_dirs, reports_dir, findings, reviews, files, fuzzables)
213-
214-
if os.getenv("CI") and not args.noerror:
215-
for f in findings:
216-
if f['severity'] == 'critical':
217-
sys.exit(1)
203+
run_default_mode(blint_options)
218204

219205

220206
if __name__ == "__main__":

blint/config.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# pylint: disable=too-many-lines
2+
import sys
3+
from dataclasses import dataclass, field
24
import os
35
import re
6+
from typing import List
7+
48

59
# Default ignore list
610
ignore_directories = [
@@ -1268,6 +1272,56 @@ def get_int_from_env(name, default):
12681272
return int(get_float_from_env(name, default))
12691273

12701274

1275+
@dataclass
1276+
class BlintOptions:
1277+
"""
1278+
A data class representing the command-line options for the blint tool.
1279+
1280+
Attributes:
1281+
deep_mode (bool): Flag indicating whether to perform deep analysis.
1282+
exports_prefix (list): Prefixes to determine exported symbols.
1283+
fuzzy (bool): Flag indicating whether to perform fuzzy analysis.
1284+
no_error (bool): Flag indicating whether to suppress error messages.
1285+
no_reviews (bool): Flag indicating whether to perform symbol reviews.
1286+
reports_dir (str): The path to the reports directory.
1287+
sbom_mode (bool): Flag indicating whether to perform SBOM analysis.
1288+
src_dir_image (list): A list of source directories.
1289+
sbom_output (str): The path to the output file.
1290+
deep_mode (bool): Flag indicating whether to perform deep analysis.
1291+
export_prefixes (list): Prefixes to determine exported symbols.
1292+
src_dir_boms (list): Directory containing pre-build and build sboms.
1293+
"""
1294+
deep_mode: bool = False
1295+
exports_prefix: List = field(default_factory=list)
1296+
fuzzy: bool = False
1297+
no_error: bool = False
1298+
no_reviews: bool = False
1299+
reports_dir: str = ""
1300+
sbom_mode: bool = False
1301+
sbom_output: str = ""
1302+
sbom_output_dir: str = ""
1303+
src_dir_boms: List = field(default_factory=list)
1304+
src_dir_image: List = field(default_factory=list)
1305+
stdout_mode: bool = False
1306+
1307+
def __post_init__(self):
1308+
if not self.src_dir_image and not (self.sbom_mode and self.src_dir_boms):
1309+
self.sources = [os.getcwd()]
1310+
if not self.reports_dir:
1311+
self.reports_dir = os.getcwd()
1312+
if self.sbom_mode:
1313+
if self.stdout_mode:
1314+
self.sbom_output = sys.stdout
1315+
elif not self.sbom_output:
1316+
self.sbom_output = os.path.join(self.reports_dir, "bom-post-build.cdx.json")
1317+
self.sbom_output_dir = os.path.join(self.reports_dir)
1318+
elif os.path.isdir(self.sbom_output):
1319+
self.sbom_output_dir = self.sbom_output
1320+
self.sbom_output = os.path.join(self.sbom_output, "bom-post-build.cdx.json")
1321+
else:
1322+
self.sbom_output_dir = os.path.dirname(self.sbom_output)
1323+
1324+
12711325
# PII related symbols
12721326
PII_WORDS = (
12731327
"FirstName",

0 commit comments

Comments
 (0)