3333app = None
3434
3535
36+ def fetch_upstream_json (
37+ path : str ,
38+ timeout : Optional [float ] = None ,
39+ max_attempts : Optional [int ] = None ,
40+ backoff_seconds : Optional [float ] = None ,
41+ ) -> Dict [str , Any ]:
42+ base_url = os .environ .get ("CRE_UPSTREAM_API_URL" , "https://opencre.org/rest/v1" )
43+ timeout = timeout or float (os .environ .get ("CRE_UPSTREAM_TIMEOUT_SECONDS" , "30" ))
44+ max_attempts = max_attempts or int (os .environ .get ("CRE_UPSTREAM_MAX_ATTEMPTS" , "4" ))
45+ backoff_seconds = backoff_seconds or float (
46+ os .environ .get ("CRE_UPSTREAM_RETRY_BACKOFF_SECONDS" , "2" )
47+ )
48+ url = f"{ base_url } { path } "
49+ last_error : Optional [Exception ] = None
50+
51+ for attempt in range (1 , max_attempts + 1 ):
52+ try :
53+ response = requests .get (url , timeout = timeout )
54+ if response .status_code == 200 :
55+ return response .json ()
56+
57+ status_error = RuntimeError (
58+ f"cannot connect to upstream status code { response .status_code } "
59+ )
60+ # Retry only on transient upstream failures.
61+ if response .status_code < 500 and response .status_code != 429 :
62+ raise status_error
63+ last_error = status_error
64+ except requests .exceptions .RequestException as exc :
65+ last_error = exc
66+
67+ if attempt < max_attempts :
68+ logger .warning (
69+ "upstream fetch failed for %s on attempt %s/%s, retrying" ,
70+ url ,
71+ attempt ,
72+ max_attempts ,
73+ )
74+ time .sleep (backoff_seconds * attempt )
75+
76+ if last_error :
77+ raise RuntimeError (f"upstream fetch failed for { url } " ) from last_error
78+ raise RuntimeError (f"upstream fetch failed for { url } " )
79+
80+
3681def register_node (node : defs .Node , collection : db .Node_collection ) -> db .Node :
3782 """
3883 for each link find if either the root node or the link have a CRE,
@@ -238,6 +283,8 @@ def register_standard(
238283):
239284 if os .environ .get ("CRE_NO_GEN_EMBEDDINGS" ):
240285 generate_embeddings = False
286+ if os .environ .get ("CRE_NO_CALCULATE_GAP_ANALYSIS" ):
287+ calculate_gap_analysis = False
241288
242289 if not standard_entries :
243290 logger .warning ("register_standard() called with no standard_entries" )
@@ -246,11 +293,11 @@ def register_standard(
246293 if collection is None :
247294 collection = db_connect (path = db_connection_str )
248295
249- conn = redis .connect ()
296+ conn = redis .connect () if calculate_gap_analysis else None
250297 ph = prompt_client .PromptHandler (database = collection )
251298 importing_name = standard_entries [0 ].name
252299 standard_hash = gap_analysis .make_resources_key ([importing_name ])
253- if calculate_gap_analysis and conn .get (standard_hash ):
300+ if calculate_gap_analysis and conn and conn .get (standard_hash ):
254301 logger .info (
255302 f"Standard importing job with info-hash { standard_hash } has already returned, skipping"
256303 )
@@ -273,7 +320,7 @@ def register_standard(
273320 if generate_embeddings and importing_name :
274321 ph .generate_embeddings_for (importing_name )
275322
276- if calculate_gap_analysis and not os . environ . get ( "CRE_NO_CALCULATE_GAP_ANALYSIS" ) :
323+ if calculate_gap_analysis :
277324 # calculate gap analysis
278325 populate_neo4j_db (db_connection_str )
279326 jobs = []
@@ -466,15 +513,7 @@ def download_graph_from_upstream(cache: str) -> None:
466513 collection = db_connect (path = cache ).with_graph ()
467514
468515 def download_cre_from_upstream (creid : str ):
469- cre_response = requests .get (
470- os .environ .get ("CRE_UPSTREAM_API_URL" , "https://opencre.org/rest/v1" )
471- + f"/id/{ creid } "
472- )
473- if cre_response .status_code != 200 :
474- raise RuntimeError (
475- f"cannot connect to upstream status code { cre_response .status_code } "
476- )
477- data = cre_response .json ()
516+ data = fetch_upstream_json (f"/id/{ creid } " )
478517 credict = data ["data" ]
479518 cre = defs .Document .from_dict (credict )
480519 if cre .id in imported_cres :
@@ -486,15 +525,7 @@ def download_cre_from_upstream(creid: str):
486525 if link .document .doctype == defs .Credoctypes .CRE :
487526 download_cre_from_upstream (link .document .id )
488527
489- root_cres_response = requests .get (
490- os .environ .get ("CRE_UPSTREAM_API_URL" , "https://opencre.org/rest/v1" )
491- + "/root_cres"
492- )
493- if root_cres_response .status_code != 200 :
494- raise RuntimeError (
495- f"cannot connect to upstream status code { root_cres_response .status_code } "
496- )
497- data = root_cres_response .json ()
528+ data = fetch_upstream_json ("/root_cres" )
498529 for root_cre in data ["data" ]:
499530 cre = defs .Document .from_dict (root_cre )
500531 register_cre (cre , collection )
@@ -625,6 +656,54 @@ def run(args: argparse.Namespace) -> None: # pragma: no cover
625656 BaseParser ().register_resource (
626657 secure_headers .SecureHeaders , db_connection_str = args .cache_file
627658 )
659+ if args .owasp_top10_2025_in :
660+ from application .utils .external_project_parsers .parsers import owasp_top10_2025
661+
662+ BaseParser ().register_resource (
663+ owasp_top10_2025 .OwaspTop10_2025 , db_connection_str = args .cache_file
664+ )
665+ if args .owasp_api_top10_2023_in :
666+ from application .utils .external_project_parsers .parsers import (
667+ owasp_api_top10_2023 ,
668+ )
669+
670+ BaseParser ().register_resource (
671+ owasp_api_top10_2023 .OwaspApiTop10_2023 ,
672+ db_connection_str = args .cache_file ,
673+ )
674+ if args .owasp_kubernetes_top10_2022_in :
675+ from application .utils .external_project_parsers .parsers import (
676+ owasp_kubernetes_top10_2022 ,
677+ )
678+
679+ BaseParser ().register_resource (
680+ owasp_kubernetes_top10_2022 .OwaspKubernetesTop10_2022 ,
681+ db_connection_str = args .cache_file ,
682+ )
683+ if args .owasp_kubernetes_top10_2025_in :
684+ from application .utils .external_project_parsers .parsers import (
685+ owasp_kubernetes_top10_2025 ,
686+ )
687+
688+ BaseParser ().register_resource (
689+ owasp_kubernetes_top10_2025 .OwaspKubernetesTop10_2025 ,
690+ db_connection_str = args .cache_file ,
691+ )
692+ if args .owasp_llm_top10_2025_in :
693+ from application .utils .external_project_parsers .parsers import (
694+ owasp_llm_top10_2025 ,
695+ )
696+
697+ BaseParser ().register_resource (
698+ owasp_llm_top10_2025 .OwaspLlmTop10_2025 ,
699+ db_connection_str = args .cache_file ,
700+ )
701+ if args .owasp_aisvs_in :
702+ from application .utils .external_project_parsers .parsers import owasp_aisvs
703+
704+ BaseParser ().register_resource (
705+ owasp_aisvs .OwaspAisvs , db_connection_str = args .cache_file
706+ )
628707 if args .pci_dss_4_in :
629708 from application .utils .external_project_parsers .parsers import pci_dss
630709
0 commit comments