-
Notifications
You must be signed in to change notification settings - Fork 208
/
api.py
163 lines (133 loc) · 4.02 KB
/
api.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import os
from requests import Session
from requests.exceptions import HTTPError
from urllib.parse import urlencode
SECURITY_API_URL = os.getenv(
"SECURITY_API_URL", "https://ubuntu.com/security/"
)
class SecurityAPIError(HTTPError):
def __init__(self, error: HTTPError):
super().__init__(request=error.request, response=error.response)
class SecurityAPI:
def __init__(
self,
session: Session,
base_url=SECURITY_API_URL,
):
self.session = session
self.base_url = base_url
def _get(self, path: str, params={}):
"""
Defines get request set up, returns data if succesful,
raises HTTP errors if not
"""
uri = f"{self.base_url}{path}"
response = self.session.get(uri, params=params)
response.raise_for_status()
return response
def get_cve(
self,
id: str,
):
"""
Makes request for specific cve_id,
returns json object if found
"""
try:
cve_response = self._get(f"cves/{id.upper()}.json")
except HTTPError as error:
if error.response.status_code == 404:
return None
raise SecurityAPIError(error)
return cve_response.json()
def get_releases(self):
"""
Makes request for all releases with ongoing support,
returns json object if found
"""
try:
releases_response = self._get("releases.json")
except HTTPError as error:
raise SecurityAPIError(error)
return releases_response.json().get("releases")
def get_notice(
self,
id: str,
):
"""
Makes request for specific notice_id,
returns json object if found
"""
try:
notice_response = self._get(f"notices/{id.upper()}.json")
except HTTPError as error:
if error.response.status_code == 404:
return None
raise SecurityAPIError(error)
return notice_response.json()
def get_page_notices(
self,
limit: int,
offset: int,
details: str,
release: str,
order: str,
):
"""
Makes request for all notices with ongoing support,
returns json object if found.
Note that these notices are missing the 'cves' fields.
"""
parameters = {
"limit": limit,
"offset": offset,
"details": details,
"release": release,
"order": order,
}
# Remove falsey items from dictionary
parameters = {k: v for k, v in parameters.items() if v}
filtered_parameters = urlencode(parameters)
try:
notices_response = self._get(
f"page/notices.json?{filtered_parameters}"
)
except HTTPError as error:
raise SecurityAPIError(error)
return notices_response.json()
def get_cves(
self,
query: str,
priority: list,
package: str,
limit: int,
offset: int,
component: str,
versions: list,
statuses: list,
order: str,
):
parameters = {
"q": query,
"priority": priority,
"package": package,
"limit": limit,
"offset": offset,
"component": component,
"version": versions,
"status": statuses,
"order": order,
}
# Remove falsey items from dictionary
filtered_parameters = {}
for key, value in parameters.items():
if value:
filtered_parameters[key] = value
query_string = urlencode(filtered_parameters, doseq=True)
try:
cves_response = self._get(f"cves.json?{query_string}")
except HTTPError as error:
if error.response.status_code == 404:
return None
raise SecurityAPIError(error)
return cves_response.json()