cloudcheck 8.4.3__cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cloudcheck/__init__.py +3 -0
- cloudcheck/cloudcheck.cpython-39-arm-linux-gnueabihf.so +0 -0
- cloudcheck/helpers.py +249 -0
- cloudcheck/providers/__init__.py +51 -0
- cloudcheck/providers/akamai.py +33 -0
- cloudcheck/providers/alibaba.py +11 -0
- cloudcheck/providers/amazon.py +37 -0
- cloudcheck/providers/arvancloud.py +20 -0
- cloudcheck/providers/azure.py +37 -0
- cloudcheck/providers/backblaze.py +11 -0
- cloudcheck/providers/base.py +269 -0
- cloudcheck/providers/cisco.py +39 -0
- cloudcheck/providers/cloudflare.py +40 -0
- cloudcheck/providers/cloudfront.py +18 -0
- cloudcheck/providers/dell.py +11 -0
- cloudcheck/providers/digitalocean.py +30 -0
- cloudcheck/providers/fastly.py +22 -0
- cloudcheck/providers/github.py +28 -0
- cloudcheck/providers/google.py +61 -0
- cloudcheck/providers/heroku.py +7 -0
- cloudcheck/providers/hetzner.py +18 -0
- cloudcheck/providers/hpe.py +12 -0
- cloudcheck/providers/huawei.py +17 -0
- cloudcheck/providers/ibm.py +57 -0
- cloudcheck/providers/imperva.py +24 -0
- cloudcheck/providers/kamatera.py +17 -0
- cloudcheck/providers/oracle.py +31 -0
- cloudcheck/providers/ovh.py +15 -0
- cloudcheck/providers/rackspace.py +21 -0
- cloudcheck/providers/salesforce.py +15 -0
- cloudcheck/providers/scaleway.py +15 -0
- cloudcheck/providers/tencent.py +15 -0
- cloudcheck/providers/wasabi.py +15 -0
- cloudcheck/providers/zoho.py +25 -0
- cloudcheck-8.4.3.dist-info/METADATA +157 -0
- cloudcheck-8.4.3.dist-info/RECORD +37 -0
- cloudcheck-8.4.3.dist-info/WHEEL +5 -0
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import ipaddress
|
|
2
|
+
import os
|
|
3
|
+
import traceback
|
|
4
|
+
import subprocess
|
|
5
|
+
import time
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Dict, List, Union
|
|
8
|
+
from pydantic import BaseModel, field_validator, computed_field
|
|
9
|
+
|
|
10
|
+
from ..helpers import defrag_cidrs, parse_v2fly_domain_file, request
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
v2fly_repo_pulled = False
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class BaseProvider(BaseModel):
|
|
17
|
+
"""
|
|
18
|
+
Base class for all cloud providers.
|
|
19
|
+
|
|
20
|
+
Each provider inherits from this class and overrides any of the default values.
|
|
21
|
+
They can also override the update_cidrs() method to fetch cidrs from a different source.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
# these values are static and always loaded from the class definition
|
|
25
|
+
regexes: Dict[str, List[str]] = {}
|
|
26
|
+
tags: List[str] = [] # Tags for the provider (e.g. "cdn", "waf", etc.)
|
|
27
|
+
org_ids: List[str] = [] # ASN Organization IDs (e.g. GOGL-ARIN)
|
|
28
|
+
v2fly_company: str = "" # Company name for v2fly domain fetching
|
|
29
|
+
|
|
30
|
+
# these values are dynamic and set by the update() method
|
|
31
|
+
last_updated: float = time.time()
|
|
32
|
+
|
|
33
|
+
# these we allow static values but they are later merged with dynamic values
|
|
34
|
+
asns: List[int] = []
|
|
35
|
+
cidrs: List[str] = []
|
|
36
|
+
domains: List[str] = []
|
|
37
|
+
|
|
38
|
+
@field_validator("cidrs")
|
|
39
|
+
@classmethod
|
|
40
|
+
def validate_cidrs(cls, value):
|
|
41
|
+
ips = []
|
|
42
|
+
for v in value:
|
|
43
|
+
try:
|
|
44
|
+
ips.append(ipaddress.ip_network(v, strict=False))
|
|
45
|
+
except ValueError:
|
|
46
|
+
print(f"Invalid CIDR: from {cls.__name__}: {v}")
|
|
47
|
+
continue
|
|
48
|
+
ips = [str(ip) for ip in defrag_cidrs(ips)]
|
|
49
|
+
return sorted(ips)
|
|
50
|
+
|
|
51
|
+
@field_validator("domains")
|
|
52
|
+
@classmethod
|
|
53
|
+
def validate_domains(cls, value):
|
|
54
|
+
return sorted(list(set([d.lower().strip(".") for d in value])))
|
|
55
|
+
|
|
56
|
+
@computed_field(return_type=str)
|
|
57
|
+
@property
|
|
58
|
+
def name(self):
|
|
59
|
+
return self.__class__.__name__
|
|
60
|
+
|
|
61
|
+
def __init__(self, **data):
|
|
62
|
+
super().__init__(**data)
|
|
63
|
+
print(f"Initializing {self.name}")
|
|
64
|
+
self._cidrs = []
|
|
65
|
+
self._cache_dir = Path.home() / ".cache" / "cloudcheck"
|
|
66
|
+
self._repo_url = "https://github.com/v2fly/domain-list-community.git"
|
|
67
|
+
self._asndb_url = os.getenv("ASNDB_URL", "https://asndb.api.bbot.io/v1")
|
|
68
|
+
self._bbot_io_api_key = os.getenv("BBOT_IO_API_KEY")
|
|
69
|
+
|
|
70
|
+
def update(self):
|
|
71
|
+
print(f"Updating {self.name}")
|
|
72
|
+
errors = []
|
|
73
|
+
errors.extend(self.update_domains())
|
|
74
|
+
errors.extend(self.update_cidrs())
|
|
75
|
+
return errors
|
|
76
|
+
|
|
77
|
+
def update_domains(self):
|
|
78
|
+
# update dynamic domains
|
|
79
|
+
errors = []
|
|
80
|
+
if self.v2fly_company:
|
|
81
|
+
domains, errors = self.fetch_v2fly_domains()
|
|
82
|
+
if domains:
|
|
83
|
+
self.domains = sorted(list(set(self.domains + domains)))
|
|
84
|
+
else:
|
|
85
|
+
errors.append(
|
|
86
|
+
f"No v2fly domains were found for {self.name} (company name: {self.v2fly_company})"
|
|
87
|
+
)
|
|
88
|
+
return errors
|
|
89
|
+
|
|
90
|
+
def update_cidrs(self):
|
|
91
|
+
cidrs = set()
|
|
92
|
+
errors = []
|
|
93
|
+
|
|
94
|
+
# query by direct ASNs
|
|
95
|
+
if self.asns:
|
|
96
|
+
_cidrs, _errors = self.fetch_asns()
|
|
97
|
+
print(f"Got {len(_cidrs)} ASN cidrs for {self.name}'s ASNs {self.asns}")
|
|
98
|
+
if not _cidrs:
|
|
99
|
+
errors.append(
|
|
100
|
+
f"No ASN cidrs were found for {self.name}'s ASNs {self.asns}"
|
|
101
|
+
)
|
|
102
|
+
errors.extend(_errors)
|
|
103
|
+
cidrs.update(_cidrs)
|
|
104
|
+
|
|
105
|
+
# query by org IDs
|
|
106
|
+
if self.org_ids:
|
|
107
|
+
_cidrs, _asns, _errors = self.fetch_org_ids()
|
|
108
|
+
_asns = _asns.copy()
|
|
109
|
+
_asns.update(self.asns)
|
|
110
|
+
self.asns = list(sorted(_asns))
|
|
111
|
+
print(
|
|
112
|
+
f"Got {len(_cidrs)} org id cidrs for {self.name}'s org ids {self.org_ids}"
|
|
113
|
+
)
|
|
114
|
+
if not _cidrs:
|
|
115
|
+
errors.append(
|
|
116
|
+
f"No cidrs were found for {self.name}'s org ids {self.org_ids}"
|
|
117
|
+
)
|
|
118
|
+
errors.extend(_errors)
|
|
119
|
+
cidrs.update(_cidrs)
|
|
120
|
+
|
|
121
|
+
# fetch any dynamically-updated lists of CIDRs
|
|
122
|
+
try:
|
|
123
|
+
dynamic_cidrs = self.fetch_cidrs()
|
|
124
|
+
print(f"Got {len(dynamic_cidrs)} dynamic cidrs for {self.name}")
|
|
125
|
+
cidrs.update(dynamic_cidrs)
|
|
126
|
+
except Exception as e:
|
|
127
|
+
errors.append(
|
|
128
|
+
f"Failed to fetch dynamic cidrs for {self.name}: {e}:\n{traceback.format_exc()}"
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
# finally, put in any manually-specified CIDRs
|
|
132
|
+
print(f"Adding {len(self.cidrs)} manually-specified cidrs for {self.name}")
|
|
133
|
+
if self.cidrs:
|
|
134
|
+
cidrs.update(self.cidrs)
|
|
135
|
+
|
|
136
|
+
print(f"Total {len(cidrs)} cidrs for {self.name}")
|
|
137
|
+
|
|
138
|
+
try:
|
|
139
|
+
self.cidrs = self.validate_cidrs(cidrs)
|
|
140
|
+
except Exception as e:
|
|
141
|
+
errors.append(
|
|
142
|
+
f"Error validating ASN cidrs for {self.name}: {e}:\n{traceback.format_exc()}"
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
self.last_updated = time.time()
|
|
146
|
+
|
|
147
|
+
return errors
|
|
148
|
+
|
|
149
|
+
def fetch_org_ids(
|
|
150
|
+
self,
|
|
151
|
+
) -> List[Union[ipaddress.IPv4Network, ipaddress.IPv6Network]]:
|
|
152
|
+
"""Takes org_ids and populates the .asns and .cidrs attributes."""
|
|
153
|
+
errors = []
|
|
154
|
+
cidrs = set()
|
|
155
|
+
print(f"Fetching {len(self.org_ids)} org ids for {self.name}")
|
|
156
|
+
asns = set()
|
|
157
|
+
for org_id in self.org_ids:
|
|
158
|
+
print(f"Fetching cidrs for {org_id} from asndb")
|
|
159
|
+
try:
|
|
160
|
+
url = f"{self._asndb_url}/org/{org_id}"
|
|
161
|
+
print(f"Fetching {url}")
|
|
162
|
+
res = self.request(url, include_api_key=True)
|
|
163
|
+
print(f"{url} -> {res}: {res.text}")
|
|
164
|
+
j = res.json()
|
|
165
|
+
except Exception as e:
|
|
166
|
+
errors.append(
|
|
167
|
+
f"Failed to fetch cidrs for {org_id} from asndb: {e}:\n{traceback.format_exc()}"
|
|
168
|
+
)
|
|
169
|
+
continue
|
|
170
|
+
_asns = j.get("asns", [])
|
|
171
|
+
for asn in _asns:
|
|
172
|
+
asns.add(asn)
|
|
173
|
+
asn_cidrs, _errors = self.fetch_asn(asn)
|
|
174
|
+
errors.extend(_errors)
|
|
175
|
+
cidrs.update(asn_cidrs)
|
|
176
|
+
return cidrs, asns, errors
|
|
177
|
+
|
|
178
|
+
def fetch_asns(self) -> List[Union[ipaddress.IPv4Network, ipaddress.IPv6Network]]:
|
|
179
|
+
"""Fetch CIDRs for a given list of ASNs from ASNDB."""
|
|
180
|
+
cidrs = []
|
|
181
|
+
errors = []
|
|
182
|
+
print(f"Fetching {len(self.asns)} ASNs for {self.name}")
|
|
183
|
+
for asn in self.asns:
|
|
184
|
+
asn_cidrs, _errors = self.fetch_asn(asn)
|
|
185
|
+
errors.extend(_errors)
|
|
186
|
+
cidrs.update(asn_cidrs)
|
|
187
|
+
return cidrs, errors
|
|
188
|
+
|
|
189
|
+
def fetch_asn(
|
|
190
|
+
self, asn: int
|
|
191
|
+
) -> List[Union[ipaddress.IPv4Network, ipaddress.IPv6Network]]:
|
|
192
|
+
"""Fetch CIDRs for a given ASN from ASNDB."""
|
|
193
|
+
cidrs = []
|
|
194
|
+
errors = []
|
|
195
|
+
url = f"{self._asndb_url}/asn/{asn}"
|
|
196
|
+
print(f"Fetching {url}")
|
|
197
|
+
try:
|
|
198
|
+
res = self.request(url, include_api_key=True)
|
|
199
|
+
print(f"{url} -> {res.text}")
|
|
200
|
+
j = res.json()
|
|
201
|
+
cidrs = j.get("subnets", [])
|
|
202
|
+
except Exception as e:
|
|
203
|
+
errors.append(
|
|
204
|
+
f"Failed to fetch cidrs for {asn} from asndb: {e}:\n{traceback.format_exc()}"
|
|
205
|
+
)
|
|
206
|
+
print(f"Got {len(cidrs)} cidrs for {asn}")
|
|
207
|
+
return cidrs, errors
|
|
208
|
+
|
|
209
|
+
def fetch_v2fly_domains(self) -> List[str]:
|
|
210
|
+
"""Fetch domains from the v2fly community repository."""
|
|
211
|
+
if not self.v2fly_company:
|
|
212
|
+
return [], []
|
|
213
|
+
|
|
214
|
+
errors = []
|
|
215
|
+
repo_path, _success = self._ensure_v2fly_repo_cached()
|
|
216
|
+
company_file = repo_path / "data" / self.v2fly_company
|
|
217
|
+
try:
|
|
218
|
+
domains = parse_v2fly_domain_file(company_file)
|
|
219
|
+
except Exception as e:
|
|
220
|
+
errors.append(
|
|
221
|
+
f"Failed to parse {self.v2fly_company} domains: {e}:\n{traceback.format_exc()}"
|
|
222
|
+
)
|
|
223
|
+
return sorted(list(domains)), errors
|
|
224
|
+
|
|
225
|
+
def fetch_cidrs(self) -> List[str]:
|
|
226
|
+
"""Fetch CIDRs from a custom source."""
|
|
227
|
+
return []
|
|
228
|
+
|
|
229
|
+
def fetch_domains(self) -> List[str]:
|
|
230
|
+
"""Fetch domains from a custom source."""
|
|
231
|
+
return []
|
|
232
|
+
|
|
233
|
+
def _ensure_v2fly_repo_cached(self) -> Path:
|
|
234
|
+
"""Ensure the community repo is cloned and up-to-date."""
|
|
235
|
+
global v2fly_repo_pulled
|
|
236
|
+
errors = []
|
|
237
|
+
repo_dir = self._cache_dir / "domain-list-community"
|
|
238
|
+
if not repo_dir.exists():
|
|
239
|
+
self._cache_dir.mkdir(parents=True, exist_ok=True)
|
|
240
|
+
try:
|
|
241
|
+
subprocess.run(
|
|
242
|
+
["git", "clone", "--depth", "1", self._repo_url, str(repo_dir)],
|
|
243
|
+
check=True,
|
|
244
|
+
capture_output=True,
|
|
245
|
+
)
|
|
246
|
+
v2fly_repo_pulled = True
|
|
247
|
+
except subprocess.CalledProcessError as e:
|
|
248
|
+
errors.append(
|
|
249
|
+
f"Failed to clone v2fly repo: {e}:\n{traceback.format_exc()}"
|
|
250
|
+
)
|
|
251
|
+
elif not v2fly_repo_pulled:
|
|
252
|
+
try:
|
|
253
|
+
subprocess.run(
|
|
254
|
+
["git", "pull"], cwd=repo_dir, check=True, capture_output=True
|
|
255
|
+
)
|
|
256
|
+
except subprocess.CalledProcessError as e:
|
|
257
|
+
errors.append(
|
|
258
|
+
f"Failed to pull v2fly repo: {e}:\n{traceback.format_exc()}"
|
|
259
|
+
)
|
|
260
|
+
return repo_dir, errors
|
|
261
|
+
|
|
262
|
+
def request(self, *args, **kwargs):
|
|
263
|
+
return request(*args, **kwargs)
|
|
264
|
+
|
|
265
|
+
def __str__(self):
|
|
266
|
+
return self.name
|
|
267
|
+
|
|
268
|
+
def __repr__(self):
|
|
269
|
+
return f"{self.__class__.__name__}(name='{self.name}')"
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from cloudcheck.providers.base import BaseProvider
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Cisco(BaseProvider):
|
|
6
|
+
v2fly_company: str = "cisco"
|
|
7
|
+
tags: List[str] = ["cloud"]
|
|
8
|
+
# {"org_id": "CISCO-25-ARIN", "org_name": "Cisco Systems Inc.", "country": "US", "asns": [25949]}
|
|
9
|
+
# {"org_id": "CISCO-32-ARIN", "org_name": "Cisco Systems, Inc.", "country": "US", "asns": [63096]}
|
|
10
|
+
# {"org_id": "CISCOR-ARIN", "org_name": "CIS Corporation", "country": "US", "asns": [3792]}
|
|
11
|
+
# {"org_id": "CISL-7-ARIN", "org_name": "Cisco Systems Ironport Division", "country": "US", "asns": [16417,30214,30215,30238,40427]}
|
|
12
|
+
# {"org_id": "CS-2787-ARIN", "org_name": "Cisco Systems Inc", "country": "US", "asns": [398699]}
|
|
13
|
+
# {"org_id": "CS-2821-ARIN", "org_name": "Cisco IoT", "country": "US", "asns": [36180,393544]}
|
|
14
|
+
# {"org_id": "CS-2825-ARIN", "org_name": "Cisco Systems, Inc.", "country": "US", "asns": [396922]}
|
|
15
|
+
# {"org_id": "CS-2831-ARIN", "org_name": "CISCO SYSTEMS, INC.", "country": "US", "asns": [109,2051,3943,22183,23460,26092,36519,40590,54140,399780]}
|
|
16
|
+
# {"org_id": "CS-691-ARIN", "org_name": "Cisco Systems Cloud Division", "country": "US", "asns": [1343,32644]}
|
|
17
|
+
# {"org_id": "CS-985-ARIN", "org_name": "Cisco Systems, Inc.", "country": "US", "asns": [55219]}
|
|
18
|
+
# {"org_id": "OPEND-2-ARIN", "org_name": "Cisco OpenDNS, LLC", "country": "US", "asns": [25605,30607,36692]}
|
|
19
|
+
# {"org_id": "ORG-CIL21-RIPE", "org_name": "Cisco International Limited", "country": "GB", "asns": [201799]}
|
|
20
|
+
# {"org_id": "ORG-CL586-RIPE", "org_name": "CISCOM Ltd", "country": "RU", "asns": [61035]}
|
|
21
|
+
# {"org_id": "ORG-CSNA1-RIPE", "org_name": "Cisco Systems Norway AS", "country": "NO", "asns": [58298]}
|
|
22
|
+
# {"org_id": "WEX-ARIN", "org_name": "Cisco Webex LLC", "country": "US", "asns": [6577,13445,16472,26152,53258,399937]}
|
|
23
|
+
org_ids: List[str] = [
|
|
24
|
+
"CISCO-25-ARIN",
|
|
25
|
+
"CISCO-32-ARIN",
|
|
26
|
+
"CISCOR-ARIN",
|
|
27
|
+
"CISL-7-ARIN",
|
|
28
|
+
"CS-2787-ARIN",
|
|
29
|
+
"CS-2821-ARIN",
|
|
30
|
+
"CS-2825-ARIN",
|
|
31
|
+
"CS-2831-ARIN",
|
|
32
|
+
"CS-691-ARIN",
|
|
33
|
+
"CS-985-ARIN",
|
|
34
|
+
"OPEND-2-ARIN",
|
|
35
|
+
"ORG-CIL21-RIPE",
|
|
36
|
+
"ORG-CL586-RIPE",
|
|
37
|
+
"ORG-CSNA1-RIPE",
|
|
38
|
+
"WEX-ARIN",
|
|
39
|
+
]
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from cloudcheck.providers.base import BaseProvider
|
|
2
|
+
from typing import List, Dict
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Cloudflare(BaseProvider):
|
|
6
|
+
v2fly_company: str = "cloudflare"
|
|
7
|
+
tags: List[str] = ["cdn"]
|
|
8
|
+
# {"org_id": "CLOUD14-ARIN", "org_name": "Cloudflare, Inc.", "country": "US", "asns": [13335,14789,394536,395747,400095]}
|
|
9
|
+
# {"org_id": "ORG-CHKL1-AP-APNIC", "org_name": "Cloudflare Hong Kong, LLC", "country": "US", "asns": [133877]}
|
|
10
|
+
# {"org_id": "ORG-CI4-AP-APNIC", "org_name": "Cloudflare, Inc.", "country": "US", "asns": [132892]}
|
|
11
|
+
# {"org_id": "ORG-CI40-RIPE", "org_name": "Cloudflare Inc", "country": "US", "asns": [202623,203898]}
|
|
12
|
+
# {"org_id": "ORG-CLL6-RIPE", "org_name": "Cloudflare London, LLC", "country": "US", "asns": [209242]}
|
|
13
|
+
# {"org_id": "ORG-CSL5-AP-APNIC", "org_name": "Cloudflare Sydney, LLC", "country": "US", "asns": [139242]}
|
|
14
|
+
org_ids: List[str] = [
|
|
15
|
+
"CLOUD14-ARIN",
|
|
16
|
+
"ORG-CHKL1-AP-APNIC",
|
|
17
|
+
"ORG-CI4-AP-APNIC",
|
|
18
|
+
"ORG-CI40-RIPE",
|
|
19
|
+
"ORG-CLL6-RIPE",
|
|
20
|
+
"ORG-CSL5-AP-APNIC",
|
|
21
|
+
]
|
|
22
|
+
_bucket_name_regex = r"[a-z0-9_][a-z0-9-\.]{1,61}[a-z0-9]"
|
|
23
|
+
regexes: Dict[str, List[str]] = {
|
|
24
|
+
"STORAGE_BUCKET_NAME": [_bucket_name_regex],
|
|
25
|
+
"STORAGE_BUCKET_HOSTNAME": [
|
|
26
|
+
r"(" + _bucket_name_regex + r")\.(r2\.dev)",
|
|
27
|
+
r"(" + _bucket_name_regex + r")\.(r2\.cloudflarestorage\.com)",
|
|
28
|
+
],
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
_ips_url = "https://api.cloudflare.com/client/v4/ips"
|
|
32
|
+
|
|
33
|
+
def fetch_cidrs(self):
|
|
34
|
+
response = self.request(self._ips_url)
|
|
35
|
+
ranges = set()
|
|
36
|
+
response_json = response.json()
|
|
37
|
+
for ip_type in ("ipv4_cidrs", "ipv6_cidrs"):
|
|
38
|
+
for ip_range in response_json.get("result", {}).get(ip_type, []):
|
|
39
|
+
ranges.add(ip_range)
|
|
40
|
+
return list(ranges)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from cloudcheck.providers.base import BaseProvider
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Cloudfront(BaseProvider):
|
|
6
|
+
tags: List[str] = ["cdn"]
|
|
7
|
+
|
|
8
|
+
_ips_url = "https://d7uri8nf7uskq.cloudfront.net/tools/list-cloudfront-ips"
|
|
9
|
+
|
|
10
|
+
def fetch_cidrs(self):
|
|
11
|
+
response = self.request(self._ips_url)
|
|
12
|
+
ranges = set()
|
|
13
|
+
response_json = response.json()
|
|
14
|
+
if not isinstance(response_json, dict):
|
|
15
|
+
raise ValueError(f"Invalid response format: {type(response_json)}")
|
|
16
|
+
for r in response_json.values():
|
|
17
|
+
ranges.update(r)
|
|
18
|
+
return list(ranges)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from cloudcheck.providers.base import BaseProvider
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Dell(BaseProvider):
|
|
6
|
+
v2fly_company: str = "dell"
|
|
7
|
+
tags: List[str] = ["cloud"]
|
|
8
|
+
# {"org_id": "DCC-25-ARIN", "org_name": "Dell, Inc.", "country": "US", "asns": [3612,3613,3614,3615,7977,12257,14876,17187,23144,30614,46507,46977,53878,54701,64208]}
|
|
9
|
+
org_ids: List[str] = [
|
|
10
|
+
"DCC-25-ARIN",
|
|
11
|
+
]
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import csv
|
|
2
|
+
from cloudcheck.providers.base import BaseProvider
|
|
3
|
+
from typing import List, Dict
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class DigitalOcean(BaseProvider):
|
|
7
|
+
v2fly_company: str = "digitalocean"
|
|
8
|
+
tags: List[str] = ["cloud"]
|
|
9
|
+
# {"org_id": "DO-13-ARIN", "org_name": "DigitalOcean, LLC", "country": "US", "asns": [14061,46652,62567,393406,394362]}
|
|
10
|
+
org_ids: List[str] = [
|
|
11
|
+
"DO-13-ARIN",
|
|
12
|
+
]
|
|
13
|
+
_bucket_name_regex = r"[a-z0-9][a-z0-9-]{2,62}"
|
|
14
|
+
regexes: Dict[str, List[str]] = {
|
|
15
|
+
"STORAGE_BUCKET_NAME": [_bucket_name_regex],
|
|
16
|
+
"STORAGE_BUCKET_HOSTNAME": [
|
|
17
|
+
r"(" + _bucket_name_regex + r")\.([a-z]{3}[\d]{1}\.digitaloceanspaces\.com)"
|
|
18
|
+
],
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
_ips_url = "https://www.digitalocean.com/geo/google.csv"
|
|
22
|
+
|
|
23
|
+
def fetch_cidrs(self):
|
|
24
|
+
response = self.request(self._ips_url)
|
|
25
|
+
do_ips = csv.DictReader(
|
|
26
|
+
response.content.decode("utf-8").splitlines(),
|
|
27
|
+
fieldnames=["range", "country", "region", "city", "postcode"],
|
|
28
|
+
)
|
|
29
|
+
ranges = set(i["range"] for i in do_ips)
|
|
30
|
+
return list(ranges)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from cloudcheck.providers.base import BaseProvider
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Fastly(BaseProvider):
|
|
6
|
+
v2fly_company: str = "fastly"
|
|
7
|
+
tags: List[str] = ["cdn"]
|
|
8
|
+
# {"org_id": "SKYCA-3-ARIN", "org_name": "Fastly, Inc.", "country": "US", "asns": [895,54113,394192]}
|
|
9
|
+
org_ids: List[str] = [
|
|
10
|
+
"SKYCA-3-ARIN",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
_ips_url = "https://api.fastly.com/public-ip-list"
|
|
14
|
+
|
|
15
|
+
def fetch_cidrs(self):
|
|
16
|
+
response = self.request(self._ips_url)
|
|
17
|
+
j = response.json()
|
|
18
|
+
if j and isinstance(j, dict):
|
|
19
|
+
addresses = j.get("addresses", [])
|
|
20
|
+
if addresses and isinstance(addresses, list):
|
|
21
|
+
return list(set(addresses))
|
|
22
|
+
return []
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import ipaddress
|
|
2
|
+
from cloudcheck.providers.base import BaseProvider
|
|
3
|
+
from typing import List
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class GitHub(BaseProvider):
|
|
7
|
+
v2fly_company: str = "github"
|
|
8
|
+
tags: List[str] = ["cdn"]
|
|
9
|
+
# {"org_id": "GITHU-ARIN", "org_name": "GitHub, Inc.", "country": "US", "asns": [36459]}
|
|
10
|
+
org_ids: List[str] = [
|
|
11
|
+
"GITHU-ARIN",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
_ips_url = "https://api.github.com/meta"
|
|
15
|
+
|
|
16
|
+
def fetch_cidrs(self):
|
|
17
|
+
response = self.request(self._ips_url)
|
|
18
|
+
ranges = set()
|
|
19
|
+
response_json = response.json()
|
|
20
|
+
for k, v in response_json.items():
|
|
21
|
+
if isinstance(v, list):
|
|
22
|
+
for n in v:
|
|
23
|
+
try:
|
|
24
|
+
ipaddress.ip_network(n)
|
|
25
|
+
ranges.add(n)
|
|
26
|
+
except ValueError:
|
|
27
|
+
pass
|
|
28
|
+
return list(ranges)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
from cloudcheck.providers.base import BaseProvider
|
|
2
|
+
from typing import List, Dict
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Google(BaseProvider):
|
|
6
|
+
v2fly_company: str = "google"
|
|
7
|
+
# domains = ["googleapis.cn", "googleapis.com", "cloud.google.com", "gcp.gvt2.com", "appspot.com", "firebaseio.com", "google"]
|
|
8
|
+
tags: List[str] = ["cloud"]
|
|
9
|
+
# {"org_id": "GAL-53-ARIN", "org_name": "Google Access LLC", "country": "US", "asns": [32381]}
|
|
10
|
+
# {"org_id": "GF-ARIN", "org_name": "Google Fiber Inc.", "country": "US", "asns": [6432,16591,19448]}
|
|
11
|
+
# {"org_id": "GL-946-ARIN", "org_name": "Google LLC", "country": "US", "asns": [33715]}
|
|
12
|
+
# {"org_id": "GOGL-ARIN", "org_name": "Google LLC", "country": "US", "asns": [13949,15169,19425,22577,22859,26684,36039,36040,40873]}
|
|
13
|
+
# {"org_id": "GOOGL-1-ARIN", "org_name": "Google LLC", "country": "US", "asns": [36383,36384,36385,36411,36520]}
|
|
14
|
+
# {"org_id": "GOOGL-2-ARIN", "org_name": "Google LLC", "country": "US", "asns": [16550,19527,26910,36561,55023,394089,395973,396178,396982]}
|
|
15
|
+
# {"org_id": "GOOGL-5-ARIN", "org_name": "Google LLC", "country": "US", "asns": [394639]}
|
|
16
|
+
# {"org_id": "GOOGL-9-ARIN", "org_name": "Google LLC", "country": "US", "asns": [394507]}
|
|
17
|
+
# {"org_id": "GOOGL-ARIN", "org_name": "Google, LLC", "country": "US", "asns": [36492]}
|
|
18
|
+
# {"org_id": "ORG-GAPP2-AP-APNIC", "org_name": "Google Asia Pacific Pte. Ltd.", "country": "SG", "asns": [139070,139190]}
|
|
19
|
+
# {"org_id": "ORG-GCEL1-RIPE", "org_name": "Google Cloud EMEA Ltd", "country": "IE", "asns": [209504,209519,209539,214609,214611]}
|
|
20
|
+
# {"org_id": "ORG-GIL4-RIPE", "org_name": "Google Ireland Limited", "country": "IE", "asns": [43515]}
|
|
21
|
+
# {"org_id": "ORG-GKL1-AFRINIC", "org_name": "Google Kenya Limited", "country": "KE", "asns": [36987]}
|
|
22
|
+
# {"org_id": "ORG-GSG10-RIPE", "org_name": "Google Switzerland GmbH", "country": "CH", "asns": [41264]}
|
|
23
|
+
# {"org_id": "ORG-GSPL5-AP-APNIC", "org_name": "Google Singapore Pte. Ltd.", "country": "SG", "asns": [45566]}
|
|
24
|
+
org_ids: List[str] = [
|
|
25
|
+
"GAL-53-ARIN",
|
|
26
|
+
"GF-ARIN",
|
|
27
|
+
"GL-946-ARIN",
|
|
28
|
+
"GOGL-ARIN",
|
|
29
|
+
"GOOGL-1-ARIN",
|
|
30
|
+
"GOOGL-2-ARIN",
|
|
31
|
+
"GOOGL-5-ARIN",
|
|
32
|
+
"GOOGL-9-ARIN",
|
|
33
|
+
"GOOGL-ARIN",
|
|
34
|
+
"ORG-GAPP2-AP-APNIC",
|
|
35
|
+
"ORG-GCEL1-RIPE",
|
|
36
|
+
"ORG-GIL4-RIPE",
|
|
37
|
+
"ORG-GKL1-AFRINIC",
|
|
38
|
+
"ORG-GSG10-RIPE",
|
|
39
|
+
"ORG-GSPL5-AP-APNIC",
|
|
40
|
+
]
|
|
41
|
+
_bucket_name_regex = r"[a-z0-9][a-z0-9-_\.]{1,61}[a-z0-9]"
|
|
42
|
+
_firebase_bucket_name_regex = r"[a-z0-9][a-z0-9-\.]{1,61}[a-z0-9]"
|
|
43
|
+
regexes: Dict[str, List[str]] = {
|
|
44
|
+
"STORAGE_BUCKET_NAME": [_bucket_name_regex, _firebase_bucket_name_regex],
|
|
45
|
+
"STORAGE_BUCKET_HOSTNAME": [
|
|
46
|
+
r"(" + _firebase_bucket_name_regex + r")\.(firebaseio\.com)",
|
|
47
|
+
r"(" + _bucket_name_regex + r")\.(storage\.googleapis\.com)",
|
|
48
|
+
],
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
_ips_url = "https://www.gstatic.com/ipranges/cloud.json"
|
|
52
|
+
|
|
53
|
+
def fetch_cidrs(self):
|
|
54
|
+
response = self.request(self._ips_url)
|
|
55
|
+
ranges = set()
|
|
56
|
+
for p in response.json()["prefixes"]:
|
|
57
|
+
try:
|
|
58
|
+
ranges.add(p["ipv4Prefix"])
|
|
59
|
+
except KeyError:
|
|
60
|
+
ranges.add(p["ipv6Prefix"])
|
|
61
|
+
return list(ranges)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from cloudcheck.providers.base import BaseProvider
|
|
2
|
+
from typing import List, Dict
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Hetzner(BaseProvider):
|
|
6
|
+
v2fly_company: str = "hetzner"
|
|
7
|
+
tags: List[str] = ["cloud"]
|
|
8
|
+
# {"org_id": "ORG-HOA1-RIPE", "org_name": "Hetzner Online GmbH", "country": "DE", "asns": [24940,212317,213230,215859]}
|
|
9
|
+
org_ids: List[str] = [
|
|
10
|
+
"ORG-HOA1-RIPE",
|
|
11
|
+
]
|
|
12
|
+
_bucket_name_regex = r"[a-z0-9][a-z0-9-_\.]{1,61}[a-z0-9]"
|
|
13
|
+
regexes: Dict[str, List[str]] = {
|
|
14
|
+
"STORAGE_BUCKET_NAME": [_bucket_name_regex],
|
|
15
|
+
"STORAGE_BUCKET_HOSTNAME": [
|
|
16
|
+
r"(" + _bucket_name_regex + r")\.(your-objectstorage\.com)"
|
|
17
|
+
],
|
|
18
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from cloudcheck.providers.base import BaseProvider
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class HPE(BaseProvider):
|
|
6
|
+
# Hewlett Packard Enterprise Development, L.P.
|
|
7
|
+
v2fly_company: str = "hpe"
|
|
8
|
+
tags: List[str] = ["cloud"]
|
|
9
|
+
# {"org_id": "HPE-15-ARIN", "org_name": "HEWLETT PACKARD ENTERPRISE COMPANY", "country": "US", "asns": [157,1033,1034,13481,20096,22149,25867,27510,40617,395714,395992,396063,397363,397957,398199,399185,399610,400054,400624,400737,400763]}
|
|
10
|
+
org_ids: List[str] = [
|
|
11
|
+
"HPE-15-ARIN",
|
|
12
|
+
]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from cloudcheck.providers.base import BaseProvider
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Huawei(BaseProvider):
|
|
6
|
+
v2fly_company: str = "huawei"
|
|
7
|
+
tags: List[str] = ["cloud"]
|
|
8
|
+
# {"org_id": "ORG-HIPL2-AP-APNIC", "org_name": "HUAWEI INTERNATIONAL PTE. LTD.", "country": "SG", "asns": [131444,136907,141180,149167,151610]}
|
|
9
|
+
# {"org_id": "ORG-HT57-RIPE", "org_name": "HUAWEI TECHNOLOGIES(UK)CO.,LTD", "country": "GB", "asns": [206798]}
|
|
10
|
+
# {"org_id": "ORG-HT61-RIPE", "org_name": "Huawei Tech(UAE)FZ-LLC", "country": "AE", "asns": [206204]}
|
|
11
|
+
# {"org_id": "ORG-HTB10-RIPE", "org_name": "Huawei Technologies (Netherlands) B.V.", "country": "NL", "asns": [200756]
|
|
12
|
+
org_ids: List[str] = [
|
|
13
|
+
"ORG-HIPL2-AP-APNIC",
|
|
14
|
+
"ORG-HT57-RIPE",
|
|
15
|
+
"ORG-HT61-RIPE",
|
|
16
|
+
"ORG-HTB10-RIPE",
|
|
17
|
+
]
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from cloudcheck.providers.base import BaseProvider
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class IBM(BaseProvider):
|
|
6
|
+
v2fly_company: str = "ibm"
|
|
7
|
+
tags: List[str] = ["cloud"]
|
|
8
|
+
# {"org_id": "AWDIC-ARIN", "org_name": "Advanced Workstations Division, IBM Corporation", "country": "US", "asns": [706]}
|
|
9
|
+
# {"org_id": "IAD-7-ARIN", "org_name": "IBM AS/400 Division", "country": "US", "asns": [10337]}
|
|
10
|
+
# {"org_id": "IBM-1-ARIN", "org_name": "IBM", "country": "US", "asns": [763,10676,12237,15293,17390,18703,19152,19604,19898,22722,23145,23257,26543,27477,27530,29834,393850,395473]}
|
|
11
|
+
# {"org_id": "IBM-1-Z-ARIN", "org_name": "IBM", "country": "US", "asns": [163,547,1747,1786,1956,1997,2538,3082,3383]}
|
|
12
|
+
# {"org_id": "IBM-43-ARIN", "org_name": "IBM", "country": "US", "asns": [2560]}
|
|
13
|
+
# {"org_id": "IBMC-14-ARIN", "org_name": "IBM Corporation", "country": "US", "asns": [19765]}
|
|
14
|
+
# {"org_id": "IBMC-24-ARIN", "org_name": "IBM Cloud", "country": "US", "asns": [13749,13884,21844,30315,36351,36420,46702,46703,46704]}
|
|
15
|
+
# {"org_id": "IBML-1-ARIN", "org_name": "ibml", "country": "US", "asns": [40847]}
|
|
16
|
+
# {"org_id": "ICNS-4-ARIN", "org_name": "IBM Canada Network Services Company", "country": "CA", "asns": [3059]}
|
|
17
|
+
# {"org_id": "ORG-ACL6-AP-APNIC", "org_name": "FIBMESH IN LIMITED", "country": "IN", "asns": [133082,149779]}
|
|
18
|
+
# {"org_id": "ORG-CIF2-RIPE", "org_name": "COMPAGNIE IBM FRANCE SAS", "country": "FR", "asns": [202213]}
|
|
19
|
+
# {"org_id": "ORG-IBBC1-RIPE", "org_name": "IBM BTO Business Consulting Services Sp. z o.o.", "country": "PL", "asns": [200138]}
|
|
20
|
+
# {"org_id": "ORG-IBMC1-RIPE", "org_name": "INTERNATIONAL BUSINESS MACHINES CORPORATION", "country": "US", "asns": [204764,209394]}
|
|
21
|
+
# {"org_id": "ORG-IBMO1-RIPE", "org_name": "International Business Machines of Belgium Ltd", "country": "BE", "asns": [15776]}
|
|
22
|
+
# {"org_id": "ORG-IBSI1-AP-APNIC", "org_name": "IBM Business Services, Inc", "country": "PH", "asns": [133377]}
|
|
23
|
+
# {"org_id": "ORG-IDG12-RIPE", "org_name": "IBM Deutschland GmbH", "country": "DE", "asns": [214585]}
|
|
24
|
+
# {"org_id": "ORG-IIAT1-RIPE", "org_name": "IBM Israel-Science and technology Ltd.", "country": "IL", "asns": [50995]}
|
|
25
|
+
# {"org_id": "ORG-INZL1-AP-APNIC", "org_name": "IBM New Zealand Limited", "country": "NZ", "asns": [24189]}
|
|
26
|
+
# {"org_id": "ORG-IR9-RIPE", "org_name": "IBM Romania SRL", "country": "RO", "asns": [61179]}
|
|
27
|
+
# {"org_id": "ORG-IRS1-RIPE", "org_name": "IBM Romania S.R.L.", "country": "RO", "asns": [43283]}
|
|
28
|
+
# {"org_id": "ORG-ISPL9-AP-APNIC", "org_name": "IBM Singapore Pte Ltd", "country": "SG", "asns": [10120,134667,135291,136468,138450]}
|
|
29
|
+
# {"org_id": "ORG-IUL5-RIPE", "org_name": "IBM United Kingdom Limited", "country": "GB", "asns": [203652]}
|
|
30
|
+
# {"org_id": "ORG-LS306-RIPE", "org_name": "LTD SibMediaFon", "country": "RU", "asns": [48507]}
|
|
31
|
+
# {"org_id": "ORG-SCG6-RIPE", "org_name": "IBM Deutschland GmbH", "country": "DE", "asns": [50524]}
|
|
32
|
+
org_ids: List[str] = [
|
|
33
|
+
"AWDIC-ARIN",
|
|
34
|
+
"IAD-7-ARIN",
|
|
35
|
+
"IBM-1-ARIN",
|
|
36
|
+
"IBM-1-Z-ARIN",
|
|
37
|
+
"IBM-43-ARIN",
|
|
38
|
+
"IBMC-14-ARIN",
|
|
39
|
+
"IBMC-24-ARIN",
|
|
40
|
+
"IBML-1-ARIN",
|
|
41
|
+
"ICNS-4-ARIN",
|
|
42
|
+
"ORG-ACL6-AP-APNIC",
|
|
43
|
+
"ORG-CIF2-RIPE",
|
|
44
|
+
"ORG-IBBC1-RIPE",
|
|
45
|
+
"ORG-IBMC1-RIPE",
|
|
46
|
+
"ORG-IBMO1-RIPE",
|
|
47
|
+
"ORG-IBSI1-AP-APNIC",
|
|
48
|
+
"ORG-IDG12-RIPE",
|
|
49
|
+
"ORG-IIAT1-RIPE",
|
|
50
|
+
"ORG-INZL1-AP-APNIC",
|
|
51
|
+
"ORG-IR9-RIPE",
|
|
52
|
+
"ORG-IRS1-RIPE",
|
|
53
|
+
"ORG-ISPL9-AP-APNIC",
|
|
54
|
+
"ORG-IUL5-RIPE",
|
|
55
|
+
"ORG-LS306-RIPE",
|
|
56
|
+
"ORG-SCG6-RIPE",
|
|
57
|
+
]
|