Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit098db4f

Browse files
committed
Refactor API services to use a common base APIService with standardized request handling
1 parente0273f4 commit098db4f

File tree

10 files changed

+299
-346
lines changed

10 files changed

+299
-346
lines changed

‎server/config/service_config.py‎

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Server configuration settings
2+
3+
# Service-specific cache TTL (in hours)
4+
CACHE_TTL= {
5+
"nvd":24,# NVD data changes infrequently
6+
"epss":12,# EPSS scores update daily
7+
"exploitdb":24,# ExploitDB updates daily
8+
"github":6,# GitHub PoCs can update frequently
9+
"nuclei":24,# Nuclei templates update daily
10+
"kev":24,# KEV catalog updates daily
11+
"vulncheck":12,# VulnCheck data updates frequently
12+
}
13+
14+
# Service-specific request timeouts (in seconds)
15+
REQUEST_TIMEOUTS= {
16+
"nvd":60,
17+
"epss":30,
18+
"exploitdb":60,
19+
"github":30,
20+
"nuclei":60,
21+
"kev":30,
22+
"vulncheck":30,
23+
}
24+
25+
# Service proxy settings (True = use proxy if configured in user settings)
26+
SERVICE_PROXY= {
27+
"nvd":True,
28+
"epss":True,
29+
"exploitdb":True,
30+
"github":True,
31+
"nuclei":True,
32+
"kev":True,
33+
"vulncheck":True,
34+
}
35+
36+
# Cache cleanup settings
37+
CACHE_CLEANUP= {
38+
"enabled":True,
39+
"interval":24,# hours
40+
"max_size":1000,# maximum number of entries per service
41+
}
42+
43+
# Logging settings
44+
LOGGING= {
45+
"level":"INFO",
46+
"max_files":50,# maximum number of log files to keep
47+
"max_size":10*1024*1024,# 10 MB per file
48+
}
Lines changed: 23 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,13 @@
1-
importrequests
2-
fromtimeimportsleep
3-
from ..baseimportCacheService
1+
from ..base.api_serviceimportAPIService
42
fromconstantsimportEPSS_API_URL
5-
fromlogger_configimportget_logger
6-
fromproxy_utilsimportget_proxy_config
73

84

9-
classEPSSService(CacheService):
5+
classEPSSService(APIService):
106
"""Service for interacting with EPSS (Exploit Prediction Scoring System) API"""
117

128
def__init__(self,logger=None):
139
"""Initialize EPSS service"""
14-
super().__init__("EPSSService",logger=logger)
10+
super().__init__("epss",logger=logger)
1511

1612
deffetch_score(self,cve_id,proxy_settings=None,max_retries=3):
1713
"""
@@ -37,27 +33,17 @@ def fetch_score(self, cve_id, proxy_settings=None, max_retries=3):
3733
url=EPSS_API_URL.format(cve_id=cve_id)
3834
self.logger.debug(f"[EPSSService] Request URL:{url}")
3935

40-
# Configure proxy
41-
proxies=get_proxy_config(proxy_settings)
42-
verify=proxies.pop("verify",True)
43-
44-
# Make request with retries
45-
forattemptinrange(max_retries):
46-
try:
47-
response=requests.get(url,proxies=proxies,verify=verify,timeout=60)
48-
49-
ifresponse.status_code==429:# Rate limit
50-
wait_time=int(response.headers.get("Retry-After",60))
51-
self.logger.warning(
52-
f"[EPSSService] Rate limit hit, waiting{wait_time}s"
53-
)
54-
sleep(wait_time)
55-
continue
56-
57-
response.raise_for_status()
58-
data=response.json()
59-
60-
ifdataand"data"indataanddata["data"]:
36+
try:
37+
# Make request
38+
response=self.make_request(
39+
url,proxy_settings=proxy_settings,max_retries=max_retries
40+
)
41+
ifnotresponse:
42+
returnNone,"Failed to get response from EPSS API"
43+
44+
data=response.json()
45+
ifdataand"data"indataanddata["data"]:
46+
try:
6147
epss_score=float(data["data"][0]["epss"])
6248
result= {"data": [{"epss":epss_score}]}
6349

@@ -67,21 +53,15 @@ def fetch_score(self, cve_id, proxy_settings=None, max_retries=3):
6753
self.logger.info(f"[EPSSService] Score for{cve_id}:{epss_score}")
6854
returnresult,None
6955

70-
self.logger.warning(f"[EPSSService] No data found for{cve_id}")
71-
returnNone,"No EPSS data found"
72-
73-
exceptrequests.RequestExceptionase:
74-
ifattempt==max_retries-1:
75-
error_msg=f"Error fetching data:{str(e)}"
56+
except (ValueError,KeyError)ase:
57+
error_msg=f"Error parsing data:{str(e)}"
7658
self.logger.error(f"[EPSSService]{error_msg}")
7759
returnNone,error_msg
78-
self.logger.warning(
79-
f"[EPSSService] Request failed (attempt{attempt+1}/{max_retries})"
80-
)
81-
sleep(1)# Wait before retry
82-
except (ValueError,KeyError)ase:
83-
error_msg=f"Error parsing data:{str(e)}"
84-
self.logger.error(f"[EPSSService]{error_msg}")
85-
returnNone,error_msg
8660

87-
returnNone,"Max retries exceeded"
61+
self.logger.warning(f"[EPSSService] No data found for{cve_id}")
62+
returnNone,"No EPSS data found"
63+
64+
exceptExceptionase:
65+
error_msg=f"Error fetching EPSS data:{str(e)}"
66+
self.logger.error(f"[EPSSService]{error_msg}")
67+
returnNone,error_msg

‎server/services/api/exploitdb_service.py‎

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,21 @@
1-
importrequests
21
importcsv
32
importos
4-
fromtimeimportsleep
53
fromdatetimeimportdatetime,timedelta
6-
from ..base.cache_serviceimportCacheService
4+
from ..base.api_serviceimportAPIService
75
fromconstantsimportEXPLOITDB_URL,CACHE_DIRECTORY
8-
fromlogger_configimportget_logger
9-
fromproxy_utilsimportget_proxy_config
106

117

12-
classExploitDBService(CacheService):
8+
classExploitDBService(APIService):
139
"""Service for interacting with ExploitDB API"""
1410

15-
def__init__(self,logger=None,ttl_hours=24):
11+
def__init__(self,logger=None):
1612
"""
1713
Initialize ExploitDB service
1814
1915
Args:
2016
logger: Optional logger instance
21-
ttl_hours (int): Time to live for cache entries in hours
2217
"""
23-
super().__init__("ExploitDBService",logger=logger,ttl_hours=ttl_hours)
24-
self.logger=loggerorget_logger("ExploitDBService")
18+
super().__init__("exploitdb",logger=logger)
2519
self.csv_path=os.path.join(CACHE_DIRECTORY,"edb_exploits.csv")
2620

2721
def_is_csv_expired(self)->bool:
@@ -56,19 +50,21 @@ def _download_csv_file(self, proxy_settings: dict = None) -> bool:
5650
"""
5751
try:
5852
self.logger.info("[ExploitDBService] Downloading fresh ExploitDB database")
59-
proxies=get_proxy_config(proxy_settings)
60-
verify=notbool(proxies)
6153

62-
ifproxies:
63-
self.logger.info("[ExploitDBService] Using proxy configuration")
64-
65-
response=requests.get(EXPLOITDB_URL,proxies=proxies,verify=verify)
66-
response.raise_for_status()
54+
# Make request using base class method
55+
response=self.make_request(
56+
EXPLOITDB_URL,proxy_settings=proxy_settings,max_retries=3
57+
)
58+
ifnotresponse:
59+
self.logger.error(
60+
f"[ExploitDBService] Failed to get response from ExploitDB API"
61+
)
62+
returnFalse
6763

6864
withopen(self.csv_path,"wb")asf:
6965
f.write(response.content)
7066

71-
file_size=len(response.content)/ (1024*1024)# Size in MB
67+
file_size=os.path.getsize(self.csv_path)/ (1024*1024)# Size in MB
7268
self.logger.info(
7369
f"[ExploitDBService] Successfully downloaded database ({file_size:.1f} MB)"
7470
)

‎server/services/api/github_service.py‎

Lines changed: 6 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,17 @@
11
importjson
2-
importrequests
3-
importtime
42
fromtypingimportDict,Optional,Tuple,List
5-
6-
fromservices.base.cache_serviceimportCacheService
3+
from ..base.api_serviceimportAPIService
74
fromconstantsimportGITHUB_API_URL
8-
fromproxy_utilsimportget_proxy_config
95

106

11-
classGitHubService(CacheService):
7+
classGitHubService(APIService):
128
"""Service for fetching and caching GitHub exploit data."""
139

1410
def__init__(self,logger=None):
1511
"""Initialize the GitHubService."""
16-
super().__init__("github_exploits",logger=logger)
12+
super().__init__("github",logger=logger)
1713
self.api_url=GITHUB_API_URL
1814

19-
defmake_request(
20-
self,url:str,max_retries:int=3,timeout:int=60,**kwargs
21-
)->Optional[requests.Response]:
22-
"""Make HTTP request with retries and timeout"""
23-
forattemptinrange(max_retries):
24-
try:
25-
response=requests.get(url,timeout=timeout,**kwargs)
26-
response.raise_for_status()
27-
returnresponse
28-
except (requests.RequestException,requests.Timeout)ase:
29-
ifattempt==max_retries-1:
30-
self.logger.error(
31-
f"[GitHubService] Request failed after{max_retries} attempts:{str(e)}"
32-
)
33-
returnNone
34-
self.logger.warning(
35-
f"[GitHubService] Request failed (attempt{attempt+1}/{max_retries}):{str(e)}"
36-
)
37-
time.sleep(1)# Wait 1 second before retrying
38-
3915
deffetch_exploits(
4016
self,cve_id:str,proxy_settings:Optional[Dict]=None
4117
)->Tuple[Optional[Dict],Optional[str]]:
@@ -63,20 +39,15 @@ def fetch_exploits(
6339
)
6440
returncached_data,None
6541

66-
# If no cache or cache is expired, fetch fresh data
6742
try:
68-
proxies=get_proxy_config(proxy_settings)
69-
verify=proxies.pop("verify",True)
70-
43+
# If no cache or cache is expired, fetch fresh data
7144
response=self.make_request(
72-
self.api_url,params={"cve_id":cve_id},proxies=proxies,verify=verify
45+
self.api_url,params={"cve_id":cve_id},proxy_settings=proxy_settings
7346
)
74-
7547
ifnotresponse:
7648
returnNone,"Failed to get response from GitHub API"
7749

7850
data=response.json()
79-
8051
if"pocs"indata:
8152
self.logger.info(
8253
f"[GitHubService] Found{len(data['pocs'])} exploits for{cve_id}"
@@ -89,7 +60,7 @@ def fetch_exploits(
8960
returndata,None
9061

9162
exceptExceptionase:
92-
error_msg=f"Error fetching GitHubexploits:{str(e)}"
63+
error_msg=f"Error fetching GitHubdata:{str(e)}"
9364
self.logger.error(f"[GitHubService]{error_msg}")
9465
returnNone,error_msg
9566

‎server/services/api/kev_service.py‎

Lines changed: 13 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,18 @@
11
importjson
22
importos
3-
importrequests
4-
importtime
53
fromtypingimportDict,Optional,Tuple,Any
6-
7-
fromservices.base.cache_serviceimportCacheService
4+
from ..base.api_serviceimportAPIService
85
fromconstantsimportKEV_URL
9-
fromproxy_utilsimportget_proxy_config
106

117

12-
classKEVService(CacheService):
8+
classKEVService(APIService):
139
"""Service for fetching and caching KEV (Known Exploited Vulnerabilities) data."""
1410

1511
def__init__(self,logger=None):
1612
"""Initialize the KEVService."""
1713
super().__init__("kev",logger=logger)
1814
self.api_url=KEV_URL
1915

20-
defmake_request(
21-
self,url:str,max_retries:int=3,timeout:int=60,**kwargs
22-
)->Optional[requests.Response]:
23-
"""Make HTTP request with retries and timeout"""
24-
forattemptinrange(max_retries):
25-
try:
26-
response=requests.get(url,timeout=timeout,**kwargs)
27-
response.raise_for_status()
28-
returnresponse
29-
except (requests.RequestException,requests.Timeout)ase:
30-
ifattempt==max_retries-1:
31-
self.logger.error(
32-
f"[KEVService] Request failed after{max_retries} attempts:{str(e)}"
33-
)
34-
returnNone
35-
self.logger.warning(
36-
f"[KEVService] Request failed (attempt{attempt+1}/{max_retries}):{str(e)}"
37-
)
38-
time.sleep(1)# Wait 1 second before retrying
39-
4016
deffetch_data(
4117
self,cve_id:str,proxy_settings:Optional[Dict]=None
4218
)->Tuple[Optional[Dict],Optional[str]]:
@@ -62,18 +38,18 @@ def fetch_data(
6238

6339
# If no cache or cache is expired, fetch fresh data
6440
try:
65-
response,error=self.make_request(self.api_url,proxy_settings)
66-
iferror:
67-
returnNone,error
41+
response=self.make_request(self.api_url,proxy_settings=proxy_settings)
42+
ifnotresponse:
43+
returnNone,"Failed to get response from KEV API"
6844

69-
kev_data=response.json()
70-
ifnotkev_data.get("vulnerabilities"):
45+
data=response.json()
46+
ifnotdata.get("vulnerabilities"):
7147
self.logger.info(f"[KEVService] No KEV data found for{cve_id}")
7248
return {"data": []},None
7349

7450
# Filter vulnerabilities for the specific CVE
7551
matching_vulns= []
76-
forvulninkev_data["vulnerabilities"]:
52+
forvulnindata["vulnerabilities"]:
7753
ifvuln.get("cveID")==cve_id:
7854
matching_vulns.append(vuln)
7955

@@ -116,25 +92,20 @@ def get_all_vulnerabilities(
11692

11793
# If no cache or cache is expired, fetch fresh data
11894
try:
119-
proxies=get_proxy_config(proxy_settings)
120-
verify=proxies.pop("verify",True)
121-
122-
response=self.make_request(self.api_url,proxies=proxies,verify=verify)
123-
95+
response=self.make_request(self.api_url,proxy_settings=proxy_settings)
12496
ifnotresponse:
12597
returnNone,"Failed to get response from KEV API"
12698

127-
kev_data=response.json()
128-
vulnerabilities_count=len(kev_data.get("vulnerabilities", []))
129-
99+
data=response.json()
100+
vulnerabilities_count=len(data.get("vulnerabilities", []))
130101
self.logger.info(
131102
f"[KEVService] Successfully downloaded{vulnerabilities_count} vulnerabilities"
132103
)
133104

134105
# Save to cache
135-
self._save_to_cache("kev_catalog",kev_data)
106+
self._save_to_cache("kev_catalog",data)
136107

137-
returnkev_data,None
108+
returndata,None
138109

139110
exceptExceptionase:
140111
error_msg=f"Error fetching KEV data:{str(e)}"

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp