88#
99from pathlib import Path
1010
11- import yaml
11+ import saneyaml
1212from django .core .management .base import BaseCommand
1313from django .core .management .base import CommandError
1414from packageurl import PackageURL
1515
16- from vulnerabilities .models import PackageRelatedVulnerability
17- from vulnerabilities .models import Vulnerability
16+ from vulnerabilities .models import Package
1817
1918
2019class Command (BaseCommand ):
@@ -40,45 +39,100 @@ def export_data(self, git_path):
4039 """
4140 self .stdout .write (f"Exporting vulnerablecode data" )
4241
43- vulnerabilities = Vulnerability .objects .all ()
44- for vuln in vulnerabilities .iterator ():
45- vuln_data = {
46- "vulnerability_id" : vuln .vulnerability_id ,
47- "aliases" : [alias .alias for alias in vuln .get_aliases ],
48- "summary" : vuln .summary ,
49- "affected_purls" : vuln .get_affected_purls (),
50- "fixed_purl" : vuln .get_fixing_purls (),
51- "severities" : [severity for severity in vuln .severities .values ()],
52- "references" : [ref for ref in vuln .references .values ()],
53- "weaknesses" : [
54- "CWE-" + str (weakness ["cwe_id" ]) for weakness in vuln .weaknesses .values ()
55- ],
56- }
57-
58- relate_package = PackageRelatedVulnerability .objects .filter (
59- vulnerability_id = vuln .id
60- ).first ()
61- if relate_package :
62- purl = PackageURL .from_string (relate_package .package .purl )
63- write_vuln_data (git_path , purl .type , purl .name , vuln .vulnerability_id , vuln_data )
64- else :
65- print (
66- f"Can't create a vulnerability file without at least one purl related to it { vuln .id } "
67- )
68-
69-
70- def write_vuln_data (git_path , ecosystem , package , vuln_id , vuln_data ):
42+ for purl in Package .objects .paginated ():
43+ package_dir = create_sub_paths (git_path , purl .type , purl .namespace , purl .name )
44+ pck_filepath = package_dir .joinpath (f"{ purl .type } -{ purl .namespace } -{ purl .name } .yaml" )
45+ write_package_data (pck_filepath , purl )
46+
47+ for vul in purl .vulnerabilities .all ():
48+ vul_filepath = package_dir .joinpath (f"{ vul .vulnerability_id } .yaml" )
49+ write_vul_data (vul_filepath , vul )
50+
51+
52+ def write_vul_data (filepath , vul ):
7153 """
72- write the vulnerablecode-code data in a file with a path like this
54+ write the vulnerability data in a file with a path like this
7355 `path/ecosystem/package/VCID-XXXX-XXXX-XXXX` and create the directories if it doesn't exist
7456 """
75- ecosystem_dir = git_path .joinpath (ecosystem )
57+
58+ vul_data = saneyaml .dump (
59+ {
60+ "vulnerability_id" : vul .vulnerability_id ,
61+ "aliases" : [alias .alias for alias in vul .get_aliases ],
62+ "summary" : vul .summary ,
63+ "severities" : [severity for severity in vul .severities .values ()],
64+ "references" : [ref for ref in vul .references .values ()],
65+ "weaknesses" : [
66+ "CWE-" + str (weakness ["cwe_id" ]) for weakness in vul .weaknesses .values ()
67+ ],
68+ }
69+ )
70+
71+ with open (filepath , encoding = "utf-8" , mode = "w" ) as f :
72+ f .write (vul_data )
73+
74+
75+ def write_package_data (filepath , purl ):
76+ """
77+ write the pacakge data in a file with a path like this
78+ `path/ecosystem/package/package_type-package_name` and create the directories if it doesn't exist
79+ and if the pacakge file doesn't exist we create the new header
80+ """
81+ purl_object = PackageURL .from_string (purl .package_url )
82+ purl_without_version = PackageURL (
83+ type = purl_object .type ,
84+ namespace = purl_object .namespace ,
85+ name = purl_object .name ,
86+ )
87+
88+ package_data_with_header = saneyaml .dump (
89+ {
90+ "pacakge" : str (purl_without_version ),
91+ "versions" : [
92+ {
93+ "purl" : str (purl_object ),
94+ "affected_by_vulnerabilities" : [
95+ vuln .vulnerability_id for vuln in purl .affected_by
96+ ],
97+ "fixing_vulnerabilities" : [vuln .vulnerability_id for vuln in purl .fixing ],
98+ }
99+ ],
100+ }
101+ )
102+
103+ package_data = {
104+ "purl" : str (purl_object ),
105+ "affected_by_vulnerabilities" : [vuln .vulnerability_id for vuln in purl .affected_by ],
106+ "fixing_vulnerabilities" : [vuln .vulnerability_id for vuln in purl .fixing ],
107+ }
108+
109+ if Path (filepath ).is_file ():
110+ with open (filepath , "r" ) as f :
111+ old_yaml = saneyaml .load (f )
112+ old_yaml ["versions" ].append (package_data )
113+
114+ if old_yaml :
115+ with open (filepath , "w" ) as f :
116+ f .write (saneyaml .dump (old_yaml ))
117+ else :
118+ with open (filepath , encoding = "utf-8" , mode = "w" ) as f :
119+ f .write (package_data_with_header )
120+
121+
122+ def create_sub_paths (git_path , purl_type , purl_namespace , purl_name ):
123+ """
124+ create the directories if it doesn't exist : `path/ecosystem/package/`
125+ """
126+ ecosystem_dir = git_path .joinpath (purl_type )
76127 if not ecosystem_dir .is_dir ():
77128 ecosystem_dir .mkdir ()
78129
79- package_dir = ecosystem_dir .joinpath (package )
130+ package_dir = ecosystem_dir .joinpath (purl_namespace )
131+ if not package_dir .is_dir ():
132+ package_dir .mkdir ()
133+
134+ package_dir = ecosystem_dir .joinpath (purl_name )
80135 if not package_dir .is_dir ():
81136 package_dir .mkdir ()
82137
83- with open (package_dir .joinpath (f"{ vuln_id } .yaml" ), mode = "w" , encoding = "utf-8" ) as f :
84- f .write (yaml .dump (vuln_data ))
138+ return package_dir
0 commit comments