55Rretrieves Dependabot issues, analyses issues, generates graphs, and generates
66HTML page with Vulnerability report. Is is also possible to compare two
77repositories.
8+
9+ # Usage:
10+ usage: vulnerability_report.py [-h] [-v] --organization ORGANIZATION
11+ --repository REPOSITORY [-r] [-g] [-p]
12+ [-c COMPARISON [COMPARISON ...]]
13+
14+ Vulnerability report tool
15+
16+ options:
17+ -h, --help show this help message and exit
18+ -v, --verbose make it verbose
19+ --organization ORGANIZATION
20+ GitHub organization.
21+ --repository REPOSITORY
22+ GitHub repository.
23+ -r, --retrieve-issues
24+ Retrieve issues
25+ -g, --generate-graphs
26+ Generate graphs with vulnerabilities info
27+ -p, --generate-page Generate page with vulnerabilities info
28+ -c, --comparison COMPARISON [COMPARISON ...]
29+ Compare two or more repositories and generate
30+ comparison report. Multiple JSON files with Dependabot
31+ alerts needs to be provided
832"""
933
10- from argparse import ArgumentParser
34+ from argparse import ArgumentParser , Namespace
35+ import json
36+
37+ from typing import Any
38+
39+ type DependabotAlert = dict [str , Any ]
40+ type DependabotAlerts = list [DependabotAlert ]
1141
1242
1343def create_argument_parser () -> ArgumentParser :
@@ -46,35 +76,107 @@ def create_argument_parser() -> ArgumentParser:
4676 parser .add_argument (
4777 "-r" ,
4878 "--retrieve-issues" ,
49- default = True ,
79+ action = "store_true" ,
80+ default = False ,
5081 help = "Retrieve issues" ,
5182 )
5283
5384 parser .add_argument (
5485 "-g" ,
5586 "--generate-graphs" ,
56- default = True ,
87+ action = "store_true" ,
88+ default = False ,
5789 help = "Generate graphs with vulnerabilities info" ,
5890 )
5991
6092 parser .add_argument (
6193 "-p" ,
6294 "--generate-page" ,
63- default = True ,
95+ action = "store_true" ,
96+ default = False ,
6497 help = "Generate page with vulnerabilities info" ,
6598 )
6699
67100 parser .add_argument (
68101 "-c" ,
69102 "--comparison" ,
70- default = False ,
71- help = "Compare two repositories and generate comparison report. "
72- "Need to be used with --data1 and --data2 options" ,
103+ required = False ,
104+ nargs = "+" ,
105+ default = [],
106+ help = "Compare two or more repositories and generate comparison report. "
107+ "Multiple JSON files with Dependabot alerts needs to be provided" ,
73108 )
74109
75110 return parser
76111
77112
113+ def dependabot_file_name (args : Namespace ) -> str :
114+ """Construct file name containing Dependabot alerts."""
115+ return f"{ args .organization } __{ args .repository } .json"
116+
117+
118+ def load_dependabot_file (filename : str ) -> Any :
119+ """Load JSON file containing Dependabot alerts."""
120+ with open (filename , "r" ) as fin :
121+ return json .load (fin )
122+
123+
124+ def has_attribute_with_value (item : DependabotAlert , attribute : str , value : str ) -> bool :
125+ """Check if dictionary has attribute with given value."""
126+ return bool (item [attribute ] == value )
127+
128+
129+ def has_deep_attribute_with_value (
130+ item : DependabotAlert , selector : str , attribute : str , value : str
131+ ) -> bool :
132+ """Check if dictionary has deep attribute with given value."""
133+ return bool (item [selector ][attribute ] == value )
134+
135+
136+ def count_attribute_with_value (
137+ items : DependabotAlerts , attribute : str , value : str
138+ ) -> int :
139+ """Count all attributes with given value."""
140+ cnt : int = 0
141+ for item in items :
142+ if has_attribute_with_value (item , attribute , value ):
143+ cnt += 1
144+ return cnt
145+
146+
147+ def count_deep_attribute_with_value (
148+ items : DependabotAlerts , selector : str , attribute : str , value : str
149+ ) -> int :
150+ """Count all deep attributes with given value."""
151+ cnt : int = 0
152+ for item in items :
153+ if has_deep_attribute_with_value (item , selector , attribute , value ):
154+ cnt += 1
155+ return cnt
156+
157+
158+ def opened_cves (source_data : DependabotAlerts ) -> int :
159+ """Compute how many CVEs are opened."""
160+ return count_attribute_with_value (source_data , "state" , "open" )
161+
162+
163+ def fixed_cves (source_data : DependabotAlerts ) -> int :
164+ """Compute how many CVEs has been fixed opened."""
165+ return count_attribute_with_value (source_data , "state" , "fixed" )
166+
167+
168+ def with_severity (severity : str , source_data : DependabotAlerts ) -> int :
169+ """Count number of CVE having specified severity."""
170+ return count_deep_attribute_with_value (
171+ source_data , "security_advisory" , "severity" , severity
172+ )
173+
174+
175+ def process_dependabot_file (dependabot_file : str , prefix : str ) -> dict [str , Any ]:
176+ """Read Dependabot alerts and prepare statistic info."""
177+ return {}
178+
179+
78180def main () -> int :
79181 """
80182 CLI entry point that retrieves Dependabot issues and produces Vulnerability report.
@@ -94,8 +196,9 @@ def main() -> int:
94196 """
95197 parser = create_argument_parser ()
96198 args = parser .parse_args ()
97-
98- print (args )
199+ dependabot_file = dependabot_file_name (args )
200+ prefix = args .repository
201+ process_dependabot_file (dependabot_file , prefix )
99202 return 0
100203
101204
0 commit comments