3737app = None
3838
3939
40+ def fetch_upstream_json (
41+ path : str ,
42+ timeout : Optional [float ] = None ,
43+ max_attempts : Optional [int ] = None ,
44+ backoff_seconds : Optional [float ] = None ,
45+ ) -> Dict [str , Any ]:
46+ base_url = os .environ .get ("CRE_UPSTREAM_API_URL" , "https://opencre.org/rest/v1" )
47+ timeout = timeout or float (os .environ .get ("CRE_UPSTREAM_TIMEOUT_SECONDS" , "30" ))
48+ max_attempts = max_attempts or int (os .environ .get ("CRE_UPSTREAM_MAX_ATTEMPTS" , "4" ))
49+ backoff_seconds = backoff_seconds or float (
50+ os .environ .get ("CRE_UPSTREAM_RETRY_BACKOFF_SECONDS" , "2" )
51+ )
52+ url = f"{ base_url } { path } "
53+ last_error : Optional [Exception ] = None
54+
55+ for attempt in range (1 , max_attempts + 1 ):
56+ try :
57+ response = requests .get (url , timeout = timeout )
58+ if response .status_code == 200 :
59+ return response .json ()
60+
61+ status_error = RuntimeError (
62+ f"cannot connect to upstream status code { response .status_code } "
63+ )
64+ # Retry only on transient upstream failures.
65+ if response .status_code < 500 and response .status_code != 429 :
66+ raise status_error
67+ last_error = status_error
68+ except requests .exceptions .RequestException as exc :
69+ last_error = exc
70+
71+ if attempt < max_attempts :
72+ logger .warning (
73+ "upstream fetch failed for %s on attempt %s/%s, retrying" ,
74+ url ,
75+ attempt ,
76+ max_attempts ,
77+ )
78+ time .sleep (backoff_seconds * attempt )
79+
80+ if last_error :
81+ raise RuntimeError (f"upstream fetch failed for { url } " ) from last_error
82+ raise RuntimeError (f"upstream fetch failed for { url } " )
83+
84+
4085def register_node (node : defs .Node , collection : db .Node_collection ) -> db .Node :
4186 """
4287 for each link find if either the root node or the link have a CRE,
@@ -354,6 +399,8 @@ def register_standard(
354399):
355400 if os .environ .get ("CRE_NO_GEN_EMBEDDINGS" ) == "1" :
356401 generate_embeddings = False
402+ if os .environ .get ("CRE_NO_CALCULATE_GAP_ANALYSIS" ):
403+ calculate_gap_analysis = False
357404
358405 if not standard_entries :
359406 logger .warning ("register_standard() called with no standard_entries" )
@@ -590,15 +637,7 @@ def download_graph_from_upstream(cache: str) -> None:
590637 collection = db_connect (path = cache ).with_graph ()
591638
592639 def download_cre_from_upstream (creid : str ):
593- cre_response = requests .get (
594- os .environ .get ("CRE_UPSTREAM_API_URL" , "https://opencre.org/rest/v1" )
595- + f"/id/{ creid } "
596- )
597- if cre_response .status_code != 200 :
598- raise RuntimeError (
599- f"cannot connect to upstream status code { cre_response .status_code } "
600- )
601- data = cre_response .json ()
640+ data = fetch_upstream_json (f"/id/{ creid } " )
602641 credict = data ["data" ]
603642 cre = defs .Document .from_dict (credict )
604643 if cre .id in imported_cres :
@@ -610,15 +649,7 @@ def download_cre_from_upstream(creid: str):
610649 if link .document .doctype == defs .Credoctypes .CRE :
611650 download_cre_from_upstream (link .document .id )
612651
613- root_cres_response = requests .get (
614- os .environ .get ("CRE_UPSTREAM_API_URL" , "https://opencre.org/rest/v1" )
615- + "/root_cres"
616- )
617- if root_cres_response .status_code != 200 :
618- raise RuntimeError (
619- f"cannot connect to upstream status code { root_cres_response .status_code } "
620- )
621- data = root_cres_response .json ()
652+ data = fetch_upstream_json ("/root_cres" )
622653 for root_cre in data ["data" ]:
623654 cre = defs .Document .from_dict (root_cre )
624655 register_cre (cre , collection )
@@ -900,6 +931,54 @@ def run(args: argparse.Namespace) -> None: # pragma: no cover
900931 BaseParser ().register_resource (
901932 secure_headers .SecureHeaders , db_connection_str = args .cache_file
902933 )
934+ if args .owasp_top10_2025_in :
935+ from application .utils .external_project_parsers .parsers import owasp_top10_2025
936+
937+ BaseParser ().register_resource (
938+ owasp_top10_2025 .OwaspTop10_2025 , db_connection_str = args .cache_file
939+ )
940+ if args .owasp_api_top10_2023_in :
941+ from application .utils .external_project_parsers .parsers import (
942+ owasp_api_top10_2023 ,
943+ )
944+
945+ BaseParser ().register_resource (
946+ owasp_api_top10_2023 .OwaspApiTop10_2023 ,
947+ db_connection_str = args .cache_file ,
948+ )
949+ if args .owasp_kubernetes_top10_2022_in :
950+ from application .utils .external_project_parsers .parsers import (
951+ owasp_kubernetes_top10_2022 ,
952+ )
953+
954+ BaseParser ().register_resource (
955+ owasp_kubernetes_top10_2022 .OwaspKubernetesTop10_2022 ,
956+ db_connection_str = args .cache_file ,
957+ )
958+ if args .owasp_kubernetes_top10_2025_in :
959+ from application .utils .external_project_parsers .parsers import (
960+ owasp_kubernetes_top10_2025 ,
961+ )
962+
963+ BaseParser ().register_resource (
964+ owasp_kubernetes_top10_2025 .OwaspKubernetesTop10_2025 ,
965+ db_connection_str = args .cache_file ,
966+ )
967+ if args .owasp_llm_top10_2025_in :
968+ from application .utils .external_project_parsers .parsers import (
969+ owasp_llm_top10_2025 ,
970+ )
971+
972+ BaseParser ().register_resource (
973+ owasp_llm_top10_2025 .OwaspLlmTop10_2025 ,
974+ db_connection_str = args .cache_file ,
975+ )
976+ if args .owasp_aisvs_in :
977+ from application .utils .external_project_parsers .parsers import owasp_aisvs
978+
979+ BaseParser ().register_resource (
980+ owasp_aisvs .OwaspAisvs , db_connection_str = args .cache_file
981+ )
903982 if args .pci_dss_4_in :
904983 from application .utils .external_project_parsers .parsers import pci_dss
905984
0 commit comments