domaintools-api-test-upload 2.2.2__tar.gz → 2.4.1__tar.gz
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.
- {domaintools_api_test_upload-2.2.2/domaintools_api_test_upload.egg-info → domaintools_api_test_upload-2.4.1}/PKG-INFO +5 -4
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/README.md +1 -1
- domaintools_api_test_upload-2.4.1/VERSION +1 -0
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/_version.py +1 -1
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/api.py +160 -42
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/cli/api.py +1 -0
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/cli/commands/__init__.py +0 -1
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/cli/commands/feeds.py +240 -0
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/cli/constants.py +3 -4
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/cli/utils.py +3 -21
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/constants.py +6 -0
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/utils.py +2 -1
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1/domaintools_api_test_upload.egg-info}/PKG-INFO +5 -4
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools_api_test_upload.egg-info/SOURCES.txt +0 -1
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools_api_test_upload.egg-info/requires.txt +1 -1
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/pyproject.toml +5 -1
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/tests/test_api.py +68 -32
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/tests/test_utils.py +6 -4
- domaintools_api_test_upload-2.2.2/VERSION +0 -1
- domaintools_api_test_upload-2.2.2/domaintools/cli/commands/phisheye.py +0 -100
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/LICENSE +0 -0
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/__init__.py +0 -0
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/base_results.py +0 -0
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/cli/__init__.py +0 -0
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/cli/commands/accounts.py +0 -0
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/cli/commands/detects.py +0 -0
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/cli/commands/domains.py +0 -0
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/cli/commands/ips.py +0 -0
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/cli/commands/iris.py +0 -0
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/cli/main.py +0 -0
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/exceptions.py +0 -0
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/filters.py +0 -0
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/results.py +0 -0
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools_api_test_upload.egg-info/dependency_links.txt +0 -0
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools_api_test_upload.egg-info/entry_points.txt +0 -0
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools_api_test_upload.egg-info/top_level.txt +0 -0
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools_async/__init__.py +0 -0
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/setup.cfg +0 -0
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/setup.py +0 -0
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/tests/test_async.py +0 -0
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/tests/test_cli.py +0 -0
- {domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/tests/test_filters.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: domaintools_api_test_upload
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.1
|
|
4
4
|
Summary: DomainTools Official Python API
|
|
5
5
|
Author-email: DomainTools <integrations@domaintools.com>
|
|
6
6
|
License: The MIT License (MIT)
|
|
@@ -40,12 +40,13 @@ Classifier: Topic :: Utilities
|
|
|
40
40
|
Requires-Python: >=3.9
|
|
41
41
|
Description-Content-Type: text/markdown
|
|
42
42
|
License-File: LICENSE
|
|
43
|
-
Requires-Dist: httpx
|
|
43
|
+
Requires-Dist: httpx==0.28.1
|
|
44
44
|
Requires-Dist: rich
|
|
45
45
|
Requires-Dist: typer
|
|
46
46
|
Provides-Extra: test
|
|
47
47
|
Requires-Dist: pytest; extra == "test"
|
|
48
48
|
Requires-Dist: mock; extra == "test"
|
|
49
|
+
Dynamic: license-file
|
|
49
50
|
|
|
50
51
|

|
|
51
52
|
===================
|
|
@@ -275,7 +276,7 @@ Custom parameters aside from the common `GET` Request parameters:
|
|
|
275
276
|
api = API(USERNAME, KEY, always_sign_api_key=False)
|
|
276
277
|
api.nod(endpoint="feed", **kwargs)
|
|
277
278
|
```
|
|
278
|
-
- `header_authentication`: by default, we're using API Header Authentication. Set this False if you want to use API Key and Secret Authentication. Apparently, you can't use API Header Authentication for `download` endpoints so
|
|
279
|
+
- `header_authentication`: by default, we're using API Header Authentication. Set this False if you want to use API Key and Secret Authentication. Apparently, you can't use API Header Authentication for `download` endpoints so this will be defaulted to `False` even without explicitly setting it.
|
|
279
280
|
```python
|
|
280
281
|
api = API(USERNAME, KEY, always_sign_api_key=False)
|
|
281
282
|
api.nod(header_authentication=False, **kwargs)
|
|
@@ -226,7 +226,7 @@ Custom parameters aside from the common `GET` Request parameters:
|
|
|
226
226
|
api = API(USERNAME, KEY, always_sign_api_key=False)
|
|
227
227
|
api.nod(endpoint="feed", **kwargs)
|
|
228
228
|
```
|
|
229
|
-
- `header_authentication`: by default, we're using API Header Authentication. Set this False if you want to use API Key and Secret Authentication. Apparently, you can't use API Header Authentication for `download` endpoints so
|
|
229
|
+
- `header_authentication`: by default, we're using API Header Authentication. Set this False if you want to use API Key and Secret Authentication. Apparently, you can't use API Header Authentication for `download` endpoints so this will be defaulted to `False` even without explicitly setting it.
|
|
230
230
|
```python
|
|
231
231
|
api = API(USERNAME, KEY, always_sign_api_key=False)
|
|
232
232
|
api.nod(header_authentication=False, **kwargs)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.4.1
|
|
@@ -89,15 +89,12 @@ class API(object):
|
|
|
89
89
|
|
|
90
90
|
if not https:
|
|
91
91
|
raise Exception("The DomainTools API endpoints no longer support http traffic. Please make sure https=True.")
|
|
92
|
-
if proxy_url:
|
|
93
|
-
|
|
94
|
-
self.proxy_url = {"http://": proxy_url, "https://": proxy_url}
|
|
95
|
-
else:
|
|
96
|
-
raise Exception("Proxy URL must be a string. For example: '127.0.0.1:8888'")
|
|
92
|
+
if proxy_url and not isinstance(proxy_url, str):
|
|
93
|
+
raise Exception("Proxy URL must be a string. For example: '127.0.0.1:8888'")
|
|
97
94
|
|
|
98
95
|
def _build_api_url(self, api_url=None, api_port=None):
|
|
99
96
|
"""Build the API url based on the given url and port. Defaults to `https://api.domaintools.com`"""
|
|
100
|
-
rest_api_url = "https://api.domaintools.com"
|
|
97
|
+
rest_api_url = "https://api.domaintools.com.test"
|
|
101
98
|
if api_url:
|
|
102
99
|
rest_api_url = api_url
|
|
103
100
|
|
|
@@ -414,38 +411,6 @@ class API(object):
|
|
|
414
411
|
**kwargs,
|
|
415
412
|
)
|
|
416
413
|
|
|
417
|
-
def phisheye(self, query, days_back=None, **kwargs):
|
|
418
|
-
"""Returns domain results for the specified term for today or the specified number of days_back.
|
|
419
|
-
Terms must be setup for monitoring via the web interface: https://research.domaintools.com/phisheye.
|
|
420
|
-
|
|
421
|
-
NOTE: Properties of a domain are only provided if we have been able to obtain them.
|
|
422
|
-
Many domains will have incomplete data because that information isn't available in their Whois records,
|
|
423
|
-
or they don't have DNS results for a name server or IP address.
|
|
424
|
-
"""
|
|
425
|
-
return self._results(
|
|
426
|
-
"phisheye",
|
|
427
|
-
"/v1/phisheye",
|
|
428
|
-
query=query,
|
|
429
|
-
days_back=days_back,
|
|
430
|
-
items_path=("domains",),
|
|
431
|
-
**kwargs,
|
|
432
|
-
)
|
|
433
|
-
|
|
434
|
-
def phisheye_term_list(self, include_inactive=False, **kwargs):
|
|
435
|
-
"""Provides a list of terms that are set up for this account.
|
|
436
|
-
This call is not charged against your API usage limit.
|
|
437
|
-
|
|
438
|
-
NOTE: The terms must be configured in the PhishEye web interface: https://research.domaintools.com/phisheye.
|
|
439
|
-
There is no API call to set up the terms.
|
|
440
|
-
"""
|
|
441
|
-
return self._results(
|
|
442
|
-
"phisheye_term_list",
|
|
443
|
-
"/v1/phisheye/term-list",
|
|
444
|
-
include_inactive=include_inactive,
|
|
445
|
-
items_path=("terms",),
|
|
446
|
-
**kwargs,
|
|
447
|
-
)
|
|
448
|
-
|
|
449
414
|
def iris(
|
|
450
415
|
self,
|
|
451
416
|
domain=None,
|
|
@@ -1068,7 +1033,21 @@ class API(object):
|
|
|
1068
1033
|
)
|
|
1069
1034
|
|
|
1070
1035
|
def nod(self, **kwargs) -> FeedsResults:
|
|
1071
|
-
"""Returns back list of the newly observed domains feed
|
|
1036
|
+
"""Returns back list of the newly observed domains feed.
|
|
1037
|
+
Apex-level domains (e.g. example.com but not www.example.com) that we observe for the first time, and have not observed previously with our global DNS sensor network.
|
|
1038
|
+
|
|
1039
|
+
domain: str: Filter for an exact domain or a substring contained within a domain by prefixing or suffixing your substring with "*". Check the documentation for examples
|
|
1040
|
+
|
|
1041
|
+
before: str: Filter for records before the given time value inclusive or time offset relative to now
|
|
1042
|
+
|
|
1043
|
+
after: str: Filter for records after the given time value inclusive or time offset relative to now
|
|
1044
|
+
|
|
1045
|
+
headers: bool: Use in combination with Accept: text/csv headers to control if headers are sent or not
|
|
1046
|
+
|
|
1047
|
+
sessionID: str: A custom string to distinguish between different sessions
|
|
1048
|
+
|
|
1049
|
+
top: int: Limit the number of results to the top N, where N is the value of this parameter.
|
|
1050
|
+
"""
|
|
1072
1051
|
validate_feeds_parameters(kwargs)
|
|
1073
1052
|
endpoint = kwargs.pop("endpoint", Endpoint.FEED.value)
|
|
1074
1053
|
source = ENDPOINT_TO_SOURCE_MAP.get(endpoint)
|
|
@@ -1085,7 +1064,22 @@ class API(object):
|
|
|
1085
1064
|
)
|
|
1086
1065
|
|
|
1087
1066
|
def nad(self, **kwargs) -> FeedsResults:
|
|
1088
|
-
"""Returns back list of the newly active domains feed
|
|
1067
|
+
"""Returns back list of the newly active domains feed. Contains domains that have been observed after having not been seen for at least 10 days in passive DNS.
|
|
1068
|
+
Apex-level domains (e.g. example.com but not www.example.com) that we observe based on the latest lifecycle of the domain. A domain may be seen either for the first time ever, or again after at least 10 days of inactivity (no observed resolutions in DNS).
|
|
1069
|
+
Populated with our global passive DNS (pDNS) sensor network.
|
|
1070
|
+
|
|
1071
|
+
domain: str: Filter for an exact domain or a substring contained within a domain by prefixing or suffixing your substring with "*". Check the documentation for examples
|
|
1072
|
+
|
|
1073
|
+
before: str: Filter for records before the given time value inclusive or time offset relative to now
|
|
1074
|
+
|
|
1075
|
+
after: str: Filter for records after the given time value inclusive or time offset relative to now
|
|
1076
|
+
|
|
1077
|
+
headers: bool: Use in combination with Accept: text/csv headers to control if headers are sent or not
|
|
1078
|
+
|
|
1079
|
+
sessionID: str: A custom string to distinguish between different sessions
|
|
1080
|
+
|
|
1081
|
+
top: int: Limit the number of results to the top N, where N is the value of this parameter.
|
|
1082
|
+
"""
|
|
1089
1083
|
validate_feeds_parameters(kwargs)
|
|
1090
1084
|
endpoint = kwargs.pop("endpoint", Endpoint.FEED.value)
|
|
1091
1085
|
source = ENDPOINT_TO_SOURCE_MAP.get(endpoint).value
|
|
@@ -1102,7 +1096,22 @@ class API(object):
|
|
|
1102
1096
|
)
|
|
1103
1097
|
|
|
1104
1098
|
def domainrdap(self, **kwargs) -> FeedsResults:
|
|
1105
|
-
"""Returns changes to global domain registration information, populated by the Registration Data Access Protocol (RDAP)
|
|
1099
|
+
"""Returns changes to global domain registration information, populated by the Registration Data Access Protocol (RDAP).
|
|
1100
|
+
Compliments the 5-Minute WHOIS Feed as registries and registrars switch from Whois to RDAP.
|
|
1101
|
+
Contains parsed and raw RDAP-format domain registration data, emitted as soon as they are collected and parsed into a normalized structure.
|
|
1102
|
+
|
|
1103
|
+
domain: str: Filter for an exact domain or a substring contained within a domain by prefixing or suffixing your substring with "*". Check the documentation for examples
|
|
1104
|
+
|
|
1105
|
+
before: str: Filter for records before the given time value inclusive or time offset relative to now
|
|
1106
|
+
|
|
1107
|
+
after: str: Filter for records after the given time value inclusive or time offset relative to now
|
|
1108
|
+
|
|
1109
|
+
headers: bool: Use in combination with Accept: text/csv headers to control if headers are sent or not
|
|
1110
|
+
|
|
1111
|
+
sessionID: str: A custom string to distinguish between different sessions
|
|
1112
|
+
|
|
1113
|
+
top: int: Limit the number of results to the top N, where N is the value of this parameter.
|
|
1114
|
+
"""
|
|
1106
1115
|
validate_feeds_parameters(kwargs)
|
|
1107
1116
|
endpoint = kwargs.pop("endpoint", Endpoint.FEED.value)
|
|
1108
1117
|
source = ENDPOINT_TO_SOURCE_MAP.get(endpoint).value
|
|
@@ -1116,7 +1125,22 @@ class API(object):
|
|
|
1116
1125
|
)
|
|
1117
1126
|
|
|
1118
1127
|
def domaindiscovery(self, **kwargs) -> FeedsResults:
|
|
1119
|
-
"""Returns new domains as they are either discovered in domain registration information, observed by our global sensor network, or reported by trusted third parties"
|
|
1128
|
+
"""Returns new domains as they are either discovered in domain registration information, observed by our global sensor network, or reported by trusted third parties".
|
|
1129
|
+
Contains domains that are newly-discovered by Domain Tools in both passive and active DNS sources, emitted as soon as they are first observed.
|
|
1130
|
+
New domains as they are either discovered in domain registration information, observed by our global sensor network, or reported by trusted third parties.
|
|
1131
|
+
|
|
1132
|
+
domain: str: Filter for an exact domain or a substring contained within a domain by prefixing or suffixing your substring with "*". Check the documentation for examples
|
|
1133
|
+
|
|
1134
|
+
before: str: Filter for records before the given time value inclusive or time offset relative to now
|
|
1135
|
+
|
|
1136
|
+
after: str: Filter for records after the given time value inclusive or time offset relative to now
|
|
1137
|
+
|
|
1138
|
+
headers: bool: Use in combination with Accept: text/csv headers to control if headers are sent or not
|
|
1139
|
+
|
|
1140
|
+
sessionID: str: A custom string to distinguish between different sessions
|
|
1141
|
+
|
|
1142
|
+
top: int: Limit the number of results to the top N, where N is the value of this parameter.
|
|
1143
|
+
"""
|
|
1120
1144
|
validate_feeds_parameters(kwargs)
|
|
1121
1145
|
endpoint = kwargs.pop("endpoint", Endpoint.FEED.value)
|
|
1122
1146
|
source = ENDPOINT_TO_SOURCE_MAP.get(endpoint).value
|
|
@@ -1131,3 +1155,97 @@ class API(object):
|
|
|
1131
1155
|
cls=FeedsResults,
|
|
1132
1156
|
**kwargs,
|
|
1133
1157
|
)
|
|
1158
|
+
|
|
1159
|
+
def noh(self, **kwargs) -> FeedsResults:
|
|
1160
|
+
"""Returns back list of the newly observed hostnames feed.
|
|
1161
|
+
Contains fully qualified domain names (i.e. host names) that have never been seen before in passive DNS, emitted as soon as they are first observed.
|
|
1162
|
+
Hostname resolutions that we observe for the first time with our global DNS sensor network.
|
|
1163
|
+
|
|
1164
|
+
domain: str: Filter for an exact domain or a substring contained within a domain by prefixing or suffixing your substring with "*". Check the documentation for examples
|
|
1165
|
+
|
|
1166
|
+
before: str: Filter for records before the given time value inclusive or time offset relative to now
|
|
1167
|
+
|
|
1168
|
+
after: str: Filter for records after the given time value inclusive or time offset relative to now
|
|
1169
|
+
|
|
1170
|
+
headers: bool: Use in combination with Accept: text/csv headers to control if headers are sent or not
|
|
1171
|
+
|
|
1172
|
+
sessionID: str: A custom string to distinguish between different sessions
|
|
1173
|
+
|
|
1174
|
+
top: int: Limit the number of results to the top N, where N is the value of this parameter.
|
|
1175
|
+
"""
|
|
1176
|
+
validate_feeds_parameters(kwargs)
|
|
1177
|
+
endpoint = kwargs.pop("endpoint", Endpoint.FEED.value)
|
|
1178
|
+
source = ENDPOINT_TO_SOURCE_MAP.get(endpoint).value
|
|
1179
|
+
if endpoint == Endpoint.DOWNLOAD.value or kwargs.get("output_format", OutputFormat.JSONL.value) != OutputFormat.CSV.value:
|
|
1180
|
+
# headers param is allowed only in Feed API and CSV format
|
|
1181
|
+
kwargs.pop("headers", None)
|
|
1182
|
+
|
|
1183
|
+
return self._results(
|
|
1184
|
+
f"newly-observed-hosts-feed-({source})",
|
|
1185
|
+
f"v1/{endpoint}/noh/",
|
|
1186
|
+
response_path=(),
|
|
1187
|
+
cls=FeedsResults,
|
|
1188
|
+
**kwargs,
|
|
1189
|
+
)
|
|
1190
|
+
|
|
1191
|
+
def realtime_domain_risk(self, **kwargs) -> FeedsResults:
|
|
1192
|
+
"""Returns back list of the realtime domain risk feed.
|
|
1193
|
+
Contains realtime domain risk information for apex-level domains, regardless of observed traffic.
|
|
1194
|
+
|
|
1195
|
+
domain: str: Filter for an exact domain or a substring contained within a domain by prefixing or suffixing your substring with "*". Check the documentation for examples
|
|
1196
|
+
|
|
1197
|
+
before: str: Filter for records before the given time value inclusive or time offset relative to now
|
|
1198
|
+
|
|
1199
|
+
after: str: Filter for records after the given time value inclusive or time offset relative to now
|
|
1200
|
+
|
|
1201
|
+
headers: bool: Use in combination with Accept: text/csv headers to control if headers are sent or not
|
|
1202
|
+
|
|
1203
|
+
sessionID: str: A custom string to distinguish between different sessions
|
|
1204
|
+
|
|
1205
|
+
top: int: Limit the number of results to the top N, where N is the value of this parameter.
|
|
1206
|
+
"""
|
|
1207
|
+
validate_feeds_parameters(kwargs)
|
|
1208
|
+
endpoint = kwargs.pop("endpoint", Endpoint.FEED.value)
|
|
1209
|
+
source = ENDPOINT_TO_SOURCE_MAP.get(endpoint).value
|
|
1210
|
+
if endpoint == Endpoint.DOWNLOAD.value or kwargs.get("output_format", OutputFormat.JSONL.value) != OutputFormat.CSV.value:
|
|
1211
|
+
# headers param is allowed only in Feed API and CSV format
|
|
1212
|
+
kwargs.pop("headers", None)
|
|
1213
|
+
|
|
1214
|
+
return self._results(
|
|
1215
|
+
f"domain-risk-({source})",
|
|
1216
|
+
f"v1/{endpoint}/domainrisk/",
|
|
1217
|
+
response_path=(),
|
|
1218
|
+
cls=FeedsResults,
|
|
1219
|
+
**kwargs,
|
|
1220
|
+
)
|
|
1221
|
+
|
|
1222
|
+
def domainhotlist(self, **kwargs) -> FeedsResults:
|
|
1223
|
+
"""Returns back list of domain hotlist feed.
|
|
1224
|
+
Contains high-risk, apex-level domains that are observed by DomainTools' global sensor network to be active within 24 hours.
|
|
1225
|
+
|
|
1226
|
+
domain: str: Filter for an exact domain or a substring contained within a domain by prefixing or suffixing your substring with "*". Check the documentation for examples
|
|
1227
|
+
|
|
1228
|
+
before: str: Filter for records before the given time value inclusive or time offset relative to now
|
|
1229
|
+
|
|
1230
|
+
after: str: Filter for records after the given time value inclusive or time offset relative to now
|
|
1231
|
+
|
|
1232
|
+
headers: bool: Use in combination with Accept: text/csv headers to control if headers are sent or not
|
|
1233
|
+
|
|
1234
|
+
sessionID: str: A custom string to distinguish between different sessions
|
|
1235
|
+
|
|
1236
|
+
top: int: Limit the number of results to the top N, where N is the value of this parameter.
|
|
1237
|
+
"""
|
|
1238
|
+
validate_feeds_parameters(kwargs)
|
|
1239
|
+
endpoint = kwargs.pop("endpoint", Endpoint.FEED.value)
|
|
1240
|
+
source = ENDPOINT_TO_SOURCE_MAP.get(endpoint).value
|
|
1241
|
+
if endpoint == Endpoint.DOWNLOAD.value or kwargs.get("output_format", OutputFormat.JSONL.value) != OutputFormat.CSV.value:
|
|
1242
|
+
# headers param is allowed only in Feed API and CSV format
|
|
1243
|
+
kwargs.pop("headers", None)
|
|
1244
|
+
|
|
1245
|
+
return self._results(
|
|
1246
|
+
f"domain-hotlist-feed-({source})",
|
|
1247
|
+
f"v1/{endpoint}/domainhotlist/",
|
|
1248
|
+
response_path=(),
|
|
1249
|
+
cls=FeedsResults,
|
|
1250
|
+
**kwargs,
|
|
1251
|
+
)
|
|
@@ -314,3 +314,243 @@ def feeds_domaindiscovery(
|
|
|
314
314
|
),
|
|
315
315
|
):
|
|
316
316
|
DTCLICommand.run(name=c.FEEDS_DOMAINDISCOVERY, params=ctx.params)
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
@dt_cli.command(
|
|
320
|
+
name=c.FEEDS_NOH,
|
|
321
|
+
help=get_cli_helptext_by_name(command_name=c.FEEDS_NOH),
|
|
322
|
+
)
|
|
323
|
+
def feeds_noh(
|
|
324
|
+
ctx: typer.Context,
|
|
325
|
+
user: str = typer.Option(None, "-u", "--user", help="Domaintools API Username."),
|
|
326
|
+
key: str = typer.Option(None, "-k", "--key", help="DomainTools API key"),
|
|
327
|
+
creds_file: str = typer.Option(
|
|
328
|
+
"~/.dtapi",
|
|
329
|
+
"-c",
|
|
330
|
+
"--credfile",
|
|
331
|
+
help="Optional file with API username and API key, one per line.",
|
|
332
|
+
),
|
|
333
|
+
no_verify_ssl: bool = typer.Option(
|
|
334
|
+
False,
|
|
335
|
+
"--no-verify-ssl",
|
|
336
|
+
help="Skip verification of SSL certificate when making HTTPs API calls",
|
|
337
|
+
),
|
|
338
|
+
no_sign_api_key: bool = typer.Option(
|
|
339
|
+
False,
|
|
340
|
+
"--no-sign-api-key",
|
|
341
|
+
help="Skip signing of api key",
|
|
342
|
+
),
|
|
343
|
+
header_authentication: bool = typer.Option(
|
|
344
|
+
True,
|
|
345
|
+
"--no-header-auth",
|
|
346
|
+
help="Don't use header authentication",
|
|
347
|
+
),
|
|
348
|
+
output_format: str = typer.Option(
|
|
349
|
+
"jsonl",
|
|
350
|
+
"-f",
|
|
351
|
+
"--format",
|
|
352
|
+
help=f"Output format in [{OutputFormat.JSONL.value}, {OutputFormat.CSV.value}]",
|
|
353
|
+
callback=DTCLICommand.validate_feeds_format_input,
|
|
354
|
+
),
|
|
355
|
+
endpoint: str = typer.Option(
|
|
356
|
+
Endpoint.FEED.value,
|
|
357
|
+
"-e",
|
|
358
|
+
"--endpoint",
|
|
359
|
+
help=f"Valid endpoints: [{Endpoint.FEED.value}, {Endpoint.DOWNLOAD.value}]",
|
|
360
|
+
callback=DTCLICommand.validate_endpoint_input,
|
|
361
|
+
),
|
|
362
|
+
sessionID: str = typer.Option(
|
|
363
|
+
None,
|
|
364
|
+
"--session-id",
|
|
365
|
+
help="Unique identifier for the session",
|
|
366
|
+
),
|
|
367
|
+
after: str = typer.Option(
|
|
368
|
+
None,
|
|
369
|
+
"--after",
|
|
370
|
+
help="Start of the time window, relative to the current time in seconds, for which data will be provided",
|
|
371
|
+
callback=DTCLICommand.validate_after_or_before_input,
|
|
372
|
+
),
|
|
373
|
+
before: str = typer.Option(
|
|
374
|
+
None,
|
|
375
|
+
"--before",
|
|
376
|
+
help="The end of the query window in seconds, relative to the current time, inclusive",
|
|
377
|
+
callback=DTCLICommand.validate_after_or_before_input,
|
|
378
|
+
),
|
|
379
|
+
domain: str = typer.Option(
|
|
380
|
+
None,
|
|
381
|
+
"-d",
|
|
382
|
+
"--domain",
|
|
383
|
+
help="A string value used to filter feed results",
|
|
384
|
+
),
|
|
385
|
+
headers: bool = typer.Option(
|
|
386
|
+
False,
|
|
387
|
+
"--headers",
|
|
388
|
+
help="Adds a header to the first line of response when text/csv is set in header parameters",
|
|
389
|
+
),
|
|
390
|
+
top: str = typer.Option(
|
|
391
|
+
None,
|
|
392
|
+
"--top",
|
|
393
|
+
help="Number of results to return in the response payload. This is ignored in download endpoint",
|
|
394
|
+
),
|
|
395
|
+
):
|
|
396
|
+
DTCLICommand.run(name=c.FEEDS_NOH, params=ctx.params)
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
@dt_cli.command(
|
|
400
|
+
name=c.FEEDS_DOMAINHOTLIST,
|
|
401
|
+
help=get_cli_helptext_by_name(command_name=c.FEEDS_DOMAINHOTLIST),
|
|
402
|
+
)
|
|
403
|
+
def feeds_domainhotlist(
|
|
404
|
+
ctx: typer.Context,
|
|
405
|
+
user: str = typer.Option(None, "-u", "--user", help="Domaintools API Username."),
|
|
406
|
+
key: str = typer.Option(None, "-k", "--key", help="DomainTools API key"),
|
|
407
|
+
creds_file: str = typer.Option(
|
|
408
|
+
"~/.dtapi",
|
|
409
|
+
"-c",
|
|
410
|
+
"--credfile",
|
|
411
|
+
help="Optional file with API username and API key, one per line.",
|
|
412
|
+
),
|
|
413
|
+
no_verify_ssl: bool = typer.Option(
|
|
414
|
+
False,
|
|
415
|
+
"--no-verify-ssl",
|
|
416
|
+
help="Skip verification of SSL certificate when making HTTPs API calls",
|
|
417
|
+
),
|
|
418
|
+
no_sign_api_key: bool = typer.Option(
|
|
419
|
+
False,
|
|
420
|
+
"--no-sign-api-key",
|
|
421
|
+
help="Skip signing of api key",
|
|
422
|
+
),
|
|
423
|
+
header_authentication: bool = typer.Option(
|
|
424
|
+
True,
|
|
425
|
+
"--no-header-auth",
|
|
426
|
+
help="Don't use header authentication",
|
|
427
|
+
),
|
|
428
|
+
output_format: str = typer.Option(
|
|
429
|
+
"jsonl",
|
|
430
|
+
"-f",
|
|
431
|
+
"--format",
|
|
432
|
+
help=f"Output format in [{OutputFormat.JSONL.value}, {OutputFormat.CSV.value}]",
|
|
433
|
+
callback=DTCLICommand.validate_feeds_format_input,
|
|
434
|
+
),
|
|
435
|
+
endpoint: str = typer.Option(
|
|
436
|
+
Endpoint.FEED.value,
|
|
437
|
+
"-e",
|
|
438
|
+
"--endpoint",
|
|
439
|
+
help=f"Valid endpoints: [{Endpoint.FEED.value}, {Endpoint.DOWNLOAD.value}]",
|
|
440
|
+
callback=DTCLICommand.validate_endpoint_input,
|
|
441
|
+
),
|
|
442
|
+
sessionID: str = typer.Option(
|
|
443
|
+
None,
|
|
444
|
+
"--session-id",
|
|
445
|
+
help="Unique identifier for the session",
|
|
446
|
+
),
|
|
447
|
+
after: str = typer.Option(
|
|
448
|
+
None,
|
|
449
|
+
"--after",
|
|
450
|
+
help="Start of the time window, relative to the current time in seconds, for which data will be provided",
|
|
451
|
+
callback=DTCLICommand.validate_after_or_before_input,
|
|
452
|
+
),
|
|
453
|
+
before: str = typer.Option(
|
|
454
|
+
None,
|
|
455
|
+
"--before",
|
|
456
|
+
help="The end of the query window in seconds, relative to the current time, inclusive",
|
|
457
|
+
callback=DTCLICommand.validate_after_or_before_input,
|
|
458
|
+
),
|
|
459
|
+
domain: str = typer.Option(
|
|
460
|
+
None,
|
|
461
|
+
"-d",
|
|
462
|
+
"--domain",
|
|
463
|
+
help="A string value used to filter feed results",
|
|
464
|
+
),
|
|
465
|
+
headers: bool = typer.Option(
|
|
466
|
+
False,
|
|
467
|
+
"--headers",
|
|
468
|
+
help="Adds a header to the first line of response when text/csv is set in header parameters",
|
|
469
|
+
),
|
|
470
|
+
top: str = typer.Option(
|
|
471
|
+
None,
|
|
472
|
+
"--top",
|
|
473
|
+
help="Number of results to return in the response payload. This is ignored in download endpoint",
|
|
474
|
+
),
|
|
475
|
+
):
|
|
476
|
+
DTCLICommand.run(name=c.FEEDS_DOMAINHOTLIST, params=ctx.params)
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
@dt_cli.command(
|
|
480
|
+
name=c.FEEDS_REALTIME_DOMAIN_RISK,
|
|
481
|
+
help=get_cli_helptext_by_name(command_name=c.FEEDS_REALTIME_DOMAIN_RISK),
|
|
482
|
+
)
|
|
483
|
+
def feeds_realtime_domain_risk(
|
|
484
|
+
ctx: typer.Context,
|
|
485
|
+
user: str = typer.Option(None, "-u", "--user", help="Domaintools API Username."),
|
|
486
|
+
key: str = typer.Option(None, "-k", "--key", help="DomainTools API key"),
|
|
487
|
+
creds_file: str = typer.Option(
|
|
488
|
+
"~/.dtapi",
|
|
489
|
+
"-c",
|
|
490
|
+
"--credfile",
|
|
491
|
+
help="Optional file with API username and API key, one per line.",
|
|
492
|
+
),
|
|
493
|
+
no_verify_ssl: bool = typer.Option(
|
|
494
|
+
False,
|
|
495
|
+
"--no-verify-ssl",
|
|
496
|
+
help="Skip verification of SSL certificate when making HTTPs API calls",
|
|
497
|
+
),
|
|
498
|
+
no_sign_api_key: bool = typer.Option(
|
|
499
|
+
False,
|
|
500
|
+
"--no-sign-api-key",
|
|
501
|
+
help="Skip signing of api key",
|
|
502
|
+
),
|
|
503
|
+
header_authentication: bool = typer.Option(
|
|
504
|
+
True,
|
|
505
|
+
"--no-header-auth",
|
|
506
|
+
help="Don't use header authentication",
|
|
507
|
+
),
|
|
508
|
+
output_format: str = typer.Option(
|
|
509
|
+
"jsonl",
|
|
510
|
+
"-f",
|
|
511
|
+
"--format",
|
|
512
|
+
help=f"Output format in [{OutputFormat.JSONL.value}, {OutputFormat.CSV.value}]",
|
|
513
|
+
callback=DTCLICommand.validate_feeds_format_input,
|
|
514
|
+
),
|
|
515
|
+
endpoint: str = typer.Option(
|
|
516
|
+
Endpoint.FEED.value,
|
|
517
|
+
"-e",
|
|
518
|
+
"--endpoint",
|
|
519
|
+
help=f"Valid endpoints: [{Endpoint.FEED.value}, {Endpoint.DOWNLOAD.value}]",
|
|
520
|
+
callback=DTCLICommand.validate_endpoint_input,
|
|
521
|
+
),
|
|
522
|
+
sessionID: str = typer.Option(
|
|
523
|
+
None,
|
|
524
|
+
"--session-id",
|
|
525
|
+
help="Unique identifier for the session",
|
|
526
|
+
),
|
|
527
|
+
after: str = typer.Option(
|
|
528
|
+
None,
|
|
529
|
+
"--after",
|
|
530
|
+
help="Start of the time window, relative to the current time in seconds, for which data will be provided",
|
|
531
|
+
callback=DTCLICommand.validate_after_or_before_input,
|
|
532
|
+
),
|
|
533
|
+
before: str = typer.Option(
|
|
534
|
+
None,
|
|
535
|
+
"--before",
|
|
536
|
+
help="The end of the query window in seconds, relative to the current time, inclusive",
|
|
537
|
+
callback=DTCLICommand.validate_after_or_before_input,
|
|
538
|
+
),
|
|
539
|
+
domain: str = typer.Option(
|
|
540
|
+
None,
|
|
541
|
+
"-d",
|
|
542
|
+
"--domain",
|
|
543
|
+
help="A string value used to filter feed results",
|
|
544
|
+
),
|
|
545
|
+
headers: bool = typer.Option(
|
|
546
|
+
False,
|
|
547
|
+
"--headers",
|
|
548
|
+
help="Adds a header to the first line of response when text/csv is set in header parameters",
|
|
549
|
+
),
|
|
550
|
+
top: str = typer.Option(
|
|
551
|
+
None,
|
|
552
|
+
"--top",
|
|
553
|
+
help="Number of results to return in the response payload. This is ignored in download endpoint",
|
|
554
|
+
),
|
|
555
|
+
):
|
|
556
|
+
DTCLICommand.run(name=c.FEEDS_REALTIME_DOMAIN_RISK, params=ctx.params)
|
{domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/cli/constants.py
RENAMED
|
@@ -39,12 +39,11 @@ IRIS_DETECT_MANAGE_WATCHLIST_DOMAINS = "iris_detect_manage_watchlist_domains"
|
|
|
39
39
|
IRIS_DETECT_ESCALATE_DOMAINS = "iris_detect_escalate_domains"
|
|
40
40
|
IRIS_DETECT_IGNORED_DOMAINS = "iris_detect_ignored_domains"
|
|
41
41
|
|
|
42
|
-
# phisheye
|
|
43
|
-
PHISHEYE = "phisheye"
|
|
44
|
-
PHISHEYE_TERM_LIST = "phisheye_term_list"
|
|
45
|
-
|
|
46
42
|
# feeds
|
|
47
43
|
FEEDS_NAD = "nad"
|
|
48
44
|
FEEDS_NOD = "nod"
|
|
45
|
+
FEEDS_NOH = "noh"
|
|
46
|
+
FEEDS_DOMAINHOTLIST = "domainhotlist"
|
|
49
47
|
FEEDS_DOMAINRDAP = "domainrdap"
|
|
50
48
|
FEEDS_DOMAINDISCOVERY = "domaindiscovery"
|
|
49
|
+
FEEDS_REALTIME_DOMAIN_RISK = "realtime_domain_risk"
|
{domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/cli/utils.py
RENAMED
|
@@ -29,25 +29,6 @@ def _iris_investigate_helptext():
|
|
|
29
29
|
"""
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
def _phisheye_helptext():
|
|
33
|
-
return """
|
|
34
|
-
Returns domain results for the specified term for today or the specified number of days_back. Terms must be setup for monitoring via the web interface: https://research.domaintools.com/phisheye. \n
|
|
35
|
-
|
|
36
|
-
NOTE: Properties of a domain are only provided if we have been able to obtain them. \n
|
|
37
|
-
Many domains will have incomplete data because that information isn't available in their Whois records,
|
|
38
|
-
or they don't have DNS results for a name server or IP address.
|
|
39
|
-
"""
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def _phisheye_termlist():
|
|
43
|
-
return """
|
|
44
|
-
Provides a list of terms that are set up for this account. This call is not charged against your API usage limit.
|
|
45
|
-
|
|
46
|
-
NOTE: The terms must be configured in the PhishEye web interface: https://research.domaintools.com/phisheye. \n
|
|
47
|
-
There is no API call to set up the terms.
|
|
48
|
-
"""
|
|
49
|
-
|
|
50
|
-
|
|
51
32
|
_command_help_mapper = {
|
|
52
33
|
c.ACCOUNT_INFORMATION: "Provides a snapshot of your accounts current API usage.",
|
|
53
34
|
c.AVAILABLE_API_CALLS: "Provides a list of api calls that you can use based on your account information.",
|
|
@@ -71,8 +52,6 @@ _command_help_mapper = {
|
|
|
71
52
|
c.REVERSE_WHOIS: "Provides list of one or more terms to search for in the Whois record, as a Python list or separated with the pipe character ( | ).",
|
|
72
53
|
c.WHOIS: "Pass in a domain name or an IP address to perform a whois lookup.",
|
|
73
54
|
c.WHOIS_HISTORY: "Retrieve historical Whois records of a given domain name.",
|
|
74
|
-
c.PHISHEYE: _phisheye_helptext(),
|
|
75
|
-
c.PHISHEYE_TERM_LIST: _phisheye_termlist(),
|
|
76
55
|
c.IRIS: "Performs a search for the provided search terms ANDed together, returning the pivot engine row data for the resulting domains.",
|
|
77
56
|
c.RISK: "Returns back the risk score for a given domain.",
|
|
78
57
|
c.RISK_EVIDENCE: "Returns back the detailed risk evidence associated with a given domain.",
|
|
@@ -84,8 +63,11 @@ _command_help_mapper = {
|
|
|
84
63
|
c.IRIS_DETECT_IGNORED_DOMAINS: "Returns back a list of ignored domains in Iris Detect based on the provided filters.",
|
|
85
64
|
c.FEEDS_NAD: "Returns back newly active domains feed.",
|
|
86
65
|
c.FEEDS_NOD: "Returns back newly observed domains feed.",
|
|
66
|
+
c.FEEDS_NOH: "Returns back newly observed hosts feed.",
|
|
67
|
+
c.FEEDS_DOMAINHOTLIST: "Returns domaint hotlist feed.",
|
|
87
68
|
c.FEEDS_DOMAINRDAP: "Returns changes to global domain registration information, populated by the Registration Data Access Protocol (RDAP).",
|
|
88
69
|
c.FEEDS_DOMAINDISCOVERY: "Returns new domains as they are either discovered in domain registration information, observed by our global sensor network, or reported by trusted third parties.",
|
|
70
|
+
c.FEEDS_REALTIME_DOMAIN_RISK: "Returns realtime domain risk information for apex-level domains, regardless of observed traffic.",
|
|
89
71
|
}
|
|
90
72
|
|
|
91
73
|
|
{domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/constants.py
RENAMED
|
@@ -28,8 +28,14 @@ FEEDS_PRODUCTS_LIST = [
|
|
|
28
28
|
"newly-active-domains-feed-(s3)",
|
|
29
29
|
"newly-observed-domains-feed-(api)",
|
|
30
30
|
"newly-observed-domains-feed-(s3)",
|
|
31
|
+
"newly-observed-hosts-feed-(api)",
|
|
32
|
+
"newly-observed-hosts-feed-(s3)",
|
|
33
|
+
"domain-hotlist-feed-(api)",
|
|
34
|
+
"domain-hotlist-feed-(s3)",
|
|
31
35
|
"domain-registration-data-access-protocol-feed-(api)",
|
|
32
36
|
"domain-registration-data-access-protocol-feed-(s3)",
|
|
37
|
+
"domain-risk-feed-(api)",
|
|
38
|
+
"domain-risk-feed-(s3)",
|
|
33
39
|
"real-time-domain-discovery-feed-(api)",
|
|
34
40
|
"real-time-domain-discovery-feed-(s3)",
|
|
35
41
|
]
|
{domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/utils.py
RENAMED
|
@@ -185,4 +185,5 @@ def validate_feeds_parameters(params):
|
|
|
185
185
|
raise ValueError(f"{format} format is not available in {Endpoint.DOWNLOAD.value} API.")
|
|
186
186
|
|
|
187
187
|
if endpoint == Endpoint.DOWNLOAD.value and params.get("header_authentication", True):
|
|
188
|
-
|
|
188
|
+
# For download endpoint, header_authentication will be False by default
|
|
189
|
+
params["header_authentication"] = False
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: domaintools_api_test_upload
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.1
|
|
4
4
|
Summary: DomainTools Official Python API
|
|
5
5
|
Author-email: DomainTools <integrations@domaintools.com>
|
|
6
6
|
License: The MIT License (MIT)
|
|
@@ -40,12 +40,13 @@ Classifier: Topic :: Utilities
|
|
|
40
40
|
Requires-Python: >=3.9
|
|
41
41
|
Description-Content-Type: text/markdown
|
|
42
42
|
License-File: LICENSE
|
|
43
|
-
Requires-Dist: httpx
|
|
43
|
+
Requires-Dist: httpx==0.28.1
|
|
44
44
|
Requires-Dist: rich
|
|
45
45
|
Requires-Dist: typer
|
|
46
46
|
Provides-Extra: test
|
|
47
47
|
Requires-Dist: pytest; extra == "test"
|
|
48
48
|
Requires-Dist: mock; extra == "test"
|
|
49
|
+
Dynamic: license-file
|
|
49
50
|
|
|
50
51
|

|
|
51
52
|
===================
|
|
@@ -275,7 +276,7 @@ Custom parameters aside from the common `GET` Request parameters:
|
|
|
275
276
|
api = API(USERNAME, KEY, always_sign_api_key=False)
|
|
276
277
|
api.nod(endpoint="feed", **kwargs)
|
|
277
278
|
```
|
|
278
|
-
- `header_authentication`: by default, we're using API Header Authentication. Set this False if you want to use API Key and Secret Authentication. Apparently, you can't use API Header Authentication for `download` endpoints so
|
|
279
|
+
- `header_authentication`: by default, we're using API Header Authentication. Set this False if you want to use API Key and Secret Authentication. Apparently, you can't use API Header Authentication for `download` endpoints so this will be defaulted to `False` even without explicitly setting it.
|
|
279
280
|
```python
|
|
280
281
|
api = API(USERNAME, KEY, always_sign_api_key=False)
|
|
281
282
|
api.nod(header_authentication=False, **kwargs)
|
|
@@ -25,7 +25,6 @@ domaintools/cli/commands/domains.py
|
|
|
25
25
|
domaintools/cli/commands/feeds.py
|
|
26
26
|
domaintools/cli/commands/ips.py
|
|
27
27
|
domaintools/cli/commands/iris.py
|
|
28
|
-
domaintools/cli/commands/phisheye.py
|
|
29
28
|
domaintools_api_test_upload.egg-info/PKG-INFO
|
|
30
29
|
domaintools_api_test_upload.egg-info/SOURCES.txt
|
|
31
30
|
domaintools_api_test_upload.egg-info/dependency_links.txt
|
|
@@ -4,7 +4,11 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "domaintools_api_test_upload"
|
|
7
|
-
dependencies = [
|
|
7
|
+
dependencies = [
|
|
8
|
+
"httpx==0.28.1",
|
|
9
|
+
"rich",
|
|
10
|
+
"typer"
|
|
11
|
+
]
|
|
8
12
|
requires-python = ">= 3.9"
|
|
9
13
|
authors = [{ name = "DomainTools", email = "integrations@domaintools.com" }]
|
|
10
14
|
description = "DomainTools Official Python API"
|
|
@@ -322,16 +322,6 @@ def test_dict_like_behaviour():
|
|
|
322
322
|
assert isinstance(whois_google.pop("whois", {}), dict)
|
|
323
323
|
|
|
324
324
|
|
|
325
|
-
@vcr.use_cassette
|
|
326
|
-
def test_list_like_behaviour():
|
|
327
|
-
with api.phisheye("google") as data:
|
|
328
|
-
data.insert(0, {"domain": "woot", "tld": "com"})
|
|
329
|
-
assert data["term"] == "google"
|
|
330
|
-
for result in data:
|
|
331
|
-
assert result["domain"]
|
|
332
|
-
assert result["tld"]
|
|
333
|
-
|
|
334
|
-
|
|
335
325
|
@vcr.use_cassette
|
|
336
326
|
def test_exception_handling():
|
|
337
327
|
exception = None
|
|
@@ -386,24 +376,6 @@ def test_formats():
|
|
|
386
376
|
assert "\n" in str(data.as_list())
|
|
387
377
|
|
|
388
378
|
|
|
389
|
-
@vcr.use_cassette
|
|
390
|
-
def test_phisheye():
|
|
391
|
-
with api.phisheye("google") as data:
|
|
392
|
-
assert data["term"] == "google"
|
|
393
|
-
for result in data:
|
|
394
|
-
assert result["domain"]
|
|
395
|
-
assert result["tld"]
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
@vcr.use_cassette
|
|
399
|
-
def test_phisheye_term_list():
|
|
400
|
-
with api.phisheye_term_list() as data:
|
|
401
|
-
assert data
|
|
402
|
-
for term in data:
|
|
403
|
-
assert "term" in term
|
|
404
|
-
assert type(term["active"]) == bool
|
|
405
|
-
|
|
406
|
-
|
|
407
379
|
@vcr.use_cassette
|
|
408
380
|
def test_iris():
|
|
409
381
|
with pytest.raises(ValueError):
|
|
@@ -545,6 +517,22 @@ def test_newly_observed_domains_feed():
|
|
|
545
517
|
assert "domain" in feed_result.keys()
|
|
546
518
|
|
|
547
519
|
|
|
520
|
+
@vcr.use_cassette
|
|
521
|
+
def test_newly_observed_hosts_feed():
|
|
522
|
+
results = feeds_api.noh(after="-60", header_authentication=False)
|
|
523
|
+
for response in results.response():
|
|
524
|
+
assert results.status == 200
|
|
525
|
+
|
|
526
|
+
rows = response.strip().split("\n")
|
|
527
|
+
assert response is not None
|
|
528
|
+
assert len(rows) >= 1
|
|
529
|
+
|
|
530
|
+
for row in rows:
|
|
531
|
+
feed_result = json.loads(row)
|
|
532
|
+
assert "timestamp" in feed_result.keys()
|
|
533
|
+
assert "domain" in feed_result.keys()
|
|
534
|
+
|
|
535
|
+
|
|
548
536
|
@vcr.use_cassette
|
|
549
537
|
def test_newly_observed_domains_feed_pagination():
|
|
550
538
|
results = feeds_api.nod(sessionID="integrations-testing", after="2025-01-16T10:20:00Z")
|
|
@@ -646,11 +634,19 @@ def test_verify_response_is_a_generator():
|
|
|
646
634
|
|
|
647
635
|
|
|
648
636
|
@vcr.use_cassette
|
|
649
|
-
def
|
|
650
|
-
|
|
651
|
-
|
|
637
|
+
def test_feeds_endpoint_should_non_header_auth_be_the_default():
|
|
638
|
+
results = feeds_api.domaindiscovery(after="-60", endpoint="download")
|
|
639
|
+
for response in results.response():
|
|
640
|
+
assert results.status == 200
|
|
641
|
+
|
|
642
|
+
rows = response.strip().split("\n")
|
|
643
|
+
assert response is not None
|
|
644
|
+
assert len(rows) >= 1
|
|
652
645
|
|
|
653
|
-
|
|
646
|
+
for row in rows:
|
|
647
|
+
feed_result = json.loads(row)
|
|
648
|
+
assert "download_name" in feed_result["response"].keys()
|
|
649
|
+
assert "files" in feed_result["response"].keys()
|
|
654
650
|
|
|
655
651
|
|
|
656
652
|
@vcr.use_cassette
|
|
@@ -667,3 +663,43 @@ def test_feeds_endpoint_should_raise_error_if_asked_csv_format_for_download_api(
|
|
|
667
663
|
feeds_api.domaindiscovery(after="-60", output_format="csv", endpoint="download")
|
|
668
664
|
|
|
669
665
|
assert str(excinfo.value) == "csv format is not available in download API."
|
|
666
|
+
|
|
667
|
+
|
|
668
|
+
@vcr.use_cassette
|
|
669
|
+
def test_realtime_domain_risk():
|
|
670
|
+
results = feeds_api.realtime_domain_risk(after="-60", header_authentication=False)
|
|
671
|
+
for response in results.response():
|
|
672
|
+
assert results.status == 200
|
|
673
|
+
|
|
674
|
+
rows = response.strip().split("\n")
|
|
675
|
+
assert response is not None
|
|
676
|
+
assert len(rows) >= 1
|
|
677
|
+
|
|
678
|
+
for row in rows:
|
|
679
|
+
feed_result = json.loads(row)
|
|
680
|
+
assert "timestamp" in feed_result.keys()
|
|
681
|
+
assert "domain" in feed_result.keys()
|
|
682
|
+
assert "phishing_risk" in feed_result.keys()
|
|
683
|
+
assert "malware_risk" in feed_result.keys()
|
|
684
|
+
assert "proximity_risk" in feed_result.keys()
|
|
685
|
+
assert "overall_risk" in feed_result.keys()
|
|
686
|
+
|
|
687
|
+
|
|
688
|
+
@vcr.use_cassette
|
|
689
|
+
def test_domain_hotlist():
|
|
690
|
+
results = feeds_api.domainhotlist(after="-60", header_authentication=False)
|
|
691
|
+
for response in results.response():
|
|
692
|
+
assert results.status == 200
|
|
693
|
+
|
|
694
|
+
rows = response.strip().split("\n")
|
|
695
|
+
assert response is not None
|
|
696
|
+
assert len(rows) >= 1
|
|
697
|
+
|
|
698
|
+
for row in rows:
|
|
699
|
+
feed_result = json.loads(row)
|
|
700
|
+
assert "timestamp" in feed_result.keys()
|
|
701
|
+
assert "domain" in feed_result.keys()
|
|
702
|
+
assert "phishing_risk" in feed_result.keys()
|
|
703
|
+
assert "malware_risk" in feed_result.keys()
|
|
704
|
+
assert "proximity_risk" in feed_result.keys()
|
|
705
|
+
assert "overall_risk" in feed_result.keys()
|
|
@@ -119,13 +119,15 @@ def test_get_pivots():
|
|
|
119
119
|
assert pivots == [["IP ADDRESS", ("199.30.228.112", 4)], ["IP ASN", (17318, 111)], ["IP ISP", ("DomainTools LLC", 222)]]
|
|
120
120
|
|
|
121
121
|
|
|
122
|
-
def
|
|
122
|
+
def test_validate_feeds_parameters_update_header_auth_to_False(test_feeds_params):
|
|
123
123
|
test_feeds_params["output_format"] = "jsonl"
|
|
124
124
|
|
|
125
|
-
|
|
126
|
-
|
|
125
|
+
assert test_feeds_params.get("header_authentication", True) # header_authentication is True whether existing or not
|
|
126
|
+
assert test_feeds_params["endpoint"] == "download"
|
|
127
|
+
|
|
128
|
+
utils.validate_feeds_parameters(test_feeds_params)
|
|
127
129
|
|
|
128
|
-
assert
|
|
130
|
+
assert not test_feeds_params["header_authentication"] # header_authentication will be defaulted to False if endpoint is download
|
|
129
131
|
|
|
130
132
|
|
|
131
133
|
def test_validate_feeds_parameters_should_raise_error_if_no_required_params(test_feeds_params):
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
2.2.2
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import sys
|
|
2
|
-
import typer
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
from domaintools.cli.main import dt_cli
|
|
6
|
-
from domaintools.cli.api import DTCLICommand
|
|
7
|
-
from domaintools.cli.utils import get_cli_helptext_by_name
|
|
8
|
-
from domaintools.cli import constants as c
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
@dt_cli.command(
|
|
12
|
-
name=c.PHISHEYE,
|
|
13
|
-
help=get_cli_helptext_by_name(command_name=c.PHISHEYE),
|
|
14
|
-
)
|
|
15
|
-
def phisheye(
|
|
16
|
-
ctx: typer.Context,
|
|
17
|
-
query: str = typer.Option(..., "-q", "--query", help="The domain to query."),
|
|
18
|
-
days_back: str = typer.Option(
|
|
19
|
-
None,
|
|
20
|
-
"--days-back",
|
|
21
|
-
help="Use this parameter in exceptional circumstances where you need to search domains registered up to six days prior to the current date. Set the value to an integer in the range of 1-6.",
|
|
22
|
-
),
|
|
23
|
-
user: str = typer.Option(None, "-u", "--user", help="Domaintools API Username."),
|
|
24
|
-
key: str = typer.Option(None, "-k", "--key", help="DomainTools API key"),
|
|
25
|
-
creds_file: str = typer.Option(
|
|
26
|
-
"~/.dtapi",
|
|
27
|
-
"-c",
|
|
28
|
-
"--credfile",
|
|
29
|
-
help="Optional file with API username and API key, one per line.",
|
|
30
|
-
),
|
|
31
|
-
rate_limit: bool = typer.Option(
|
|
32
|
-
False,
|
|
33
|
-
"-l",
|
|
34
|
-
"--rate-limit",
|
|
35
|
-
help="Rate limit API calls against the API based on per minute limits.",
|
|
36
|
-
),
|
|
37
|
-
format: str = typer.Option(
|
|
38
|
-
"json",
|
|
39
|
-
"-f",
|
|
40
|
-
"--format",
|
|
41
|
-
help="Output format in {'list', 'json', 'xml', 'html'}",
|
|
42
|
-
callback=DTCLICommand.validate_format_input,
|
|
43
|
-
),
|
|
44
|
-
out_file: typer.FileTextWrite = typer.Option(
|
|
45
|
-
sys.stdout, "-o", "--out-file", help="Output file (defaults to stdout)"
|
|
46
|
-
),
|
|
47
|
-
no_verify_ssl: bool = typer.Option(
|
|
48
|
-
False,
|
|
49
|
-
"--no-verify-ssl",
|
|
50
|
-
help="Skip verification of SSL certificate when making HTTPs API calls",
|
|
51
|
-
),
|
|
52
|
-
):
|
|
53
|
-
DTCLICommand.run(name=c.PHISHEYE, params=ctx.params)
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
@dt_cli.command(
|
|
57
|
-
name=c.PHISHEYE_TERM_LIST,
|
|
58
|
-
help=get_cli_helptext_by_name(command_name=c.PHISHEYE_TERM_LIST),
|
|
59
|
-
)
|
|
60
|
-
def phisheye_termlist(
|
|
61
|
-
ctx: typer.Context,
|
|
62
|
-
include_inactive: bool = typer.Option(
|
|
63
|
-
False,
|
|
64
|
-
"--include-inactive",
|
|
65
|
-
help="Use this parameter to display terms that may have been inactivated in users' lists.",
|
|
66
|
-
),
|
|
67
|
-
user: str = typer.Option(None, "-u", "--user", help="Domaintools API Username."),
|
|
68
|
-
key: str = typer.Option(None, "-k", "--key", help="DomainTools API key"),
|
|
69
|
-
creds_file: str = typer.Option(
|
|
70
|
-
"~/.dtapi",
|
|
71
|
-
"-c",
|
|
72
|
-
"--credfile",
|
|
73
|
-
help="Optional file with API username and API key, one per line.",
|
|
74
|
-
),
|
|
75
|
-
rate_limit: bool = typer.Option(
|
|
76
|
-
False,
|
|
77
|
-
"-l",
|
|
78
|
-
"--rate-limit",
|
|
79
|
-
help="Rate limit API calls against the API based on per minute limits.",
|
|
80
|
-
),
|
|
81
|
-
format: str = typer.Option(
|
|
82
|
-
"json",
|
|
83
|
-
"-f",
|
|
84
|
-
"--format",
|
|
85
|
-
help="Output format in {'list', 'json', 'xml', 'html'}",
|
|
86
|
-
callback=DTCLICommand.validate_format_input,
|
|
87
|
-
),
|
|
88
|
-
out_file: typer.FileTextWrite = typer.Option(
|
|
89
|
-
sys.stdout, "-o", "--out-file", help="Output file (defaults to stdout)"
|
|
90
|
-
),
|
|
91
|
-
no_verify_ssl: bool = typer.Option(
|
|
92
|
-
False,
|
|
93
|
-
"--no-verify-ssl",
|
|
94
|
-
help="Skip verification of SSL certificate when making HTTPs API calls",
|
|
95
|
-
),
|
|
96
|
-
):
|
|
97
|
-
DTCLICommand.run(name=c.PHISHEYE_TERM_LIST, params=ctx.params)
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
__all__ = ["phisheye", "phisheye_termlist"]
|
|
File without changes
|
{domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/__init__.py
RENAMED
|
File without changes
|
{domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/base_results.py
RENAMED
|
File without changes
|
{domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/cli/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/cli/main.py
RENAMED
|
File without changes
|
{domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/exceptions.py
RENAMED
|
File without changes
|
{domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/filters.py
RENAMED
|
File without changes
|
{domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/domaintools/results.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{domaintools_api_test_upload-2.2.2 → domaintools_api_test_upload-2.4.1}/tests/test_filters.py
RENAMED
|
File without changes
|