Skip to content

Commit cb2248d

Browse files
authored
Merge pull request #203 from DomainTools/release-v2.9.0
DT Python Wrapper Release v2.9.0
2 parents 55584ad + 2d08e15 commit cb2248d

52 files changed

Lines changed: 12119 additions & 12 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,69 @@
11
# Changelog
22

3+
### 2.9.0
4+
- [NEW] Add support for querying real-time IP feeds (`iphotlist` and `iprisk`).
5+
- [FIX] Type hint used for `top` parameter in Feeds API from str to int.
6+
7+
### 2.8.1
8+
- [FIX] Update python wrapper with a patch that allows the wrapper to proceed with Iris Enrich call even if `account_information` returns a 503 error only (rate limit error).
9+
10+
### 2.8.0
11+
- [NEW] Add IrisQL Support in `iris_investigate` function.
12+
- [NEW] Add `domain_history` command/function in the wrapper.
13+
14+
### 2.7.4
15+
- [FIX] Handle validation error for none value arguments.
16+
17+
### 2.7.3
18+
- [FIX] Issue on missing `risk_score` when passing it on `iris_investigate` function.
19+
20+
### 2.7.2
21+
- [FIX] Issue on importing OpenAPI spec.
22+
23+
### 2.7.0
24+
- [FIX] `iris_investigate` API parity updates (update help documentation)
25+
- [FIX] `iris_investigate` `active` should raise an error as it requires a boolean not a string
26+
27+
### 2.6.0
28+
- [NEW] Implement streaming request for RTTF endpoints to handle the feeds properly and yield the feed line by line and not storing all of it in memory.
29+
- [UPDATE] Test cases.
30+
- [FIX] `available_api_calls` function for RTTF products
31+
32+
### 2.5.3
33+
- [UPDATE] Add IrisQL Support in `iris_investigate` function.
34+
- [UPDATE] Change default Feeds authentication behavior
35+
36+
### 2.5.2
37+
- [FIX] Total count bug for Iris Investigate and Iris Enrich results.
38+
39+
### 2.5.1
40+
- [FIX] Fix for bug found in `realtime_domain_risk` endpoint. Changed product name from `domain-risk-<source>` to `domain-risk-feed-<source>`
41+
42+
### 2.5.0
43+
- [NEW] Add support for Real Time Domain Risk Feed
44+
- [NEW] Add support for Domain Hotlist Feed
45+
- [NEW] Add e2e tests for proxy and ssl
46+
- [UPDATE] Integrate e2e tests in CI pipeline.
47+
- [FIX] Bugs found in `/domainrisk` and `/domainhotlist` endpoints
48+
49+
### 2.4.1
50+
- [UPDATE] Remove support for MD5 based signing.
51+
52+
### 2.4.0
53+
- [NEW] Integrate the NOH Feed to be supportable with the Python Wrapper.
54+
- [NEW] Improve worfklow to automate publishing the package to PyPI.
55+
- [UPDATE] Remove PhishEye.
56+
- [FIX] Improvements on help texts.
57+
- [FIX] Pegged httpxdependency to v.0.28.1 to prevent proxy key error.
58+
59+
### 2.3.0
60+
- [NEW] Integrate the Domain RDAP Feed to be supportable with the Python Wrapper.
61+
- [NEW] Integrate the Domain Discovery Feed to be supportable with the Python Wrapper.
62+
- [UPDATE] Enhancements to RTUF endpoints to support the following: download API, header authentication, csv format.
63+
- [UPDATE] Processing of Iterative Response (HTTP 206) from RTUF endpoints.
64+
- [UPDATE] Help Text and Information Using New Documentation.
65+
- [FIX] Simplification of using the new `proxy` param of httpx.Client. Before we’re using proxy mounts equivalent which we used `proxies` but this was deprecated on httpx v.0.28.x and onward causing errors in the python_wrapper
66+
367
### 2.0.0
468
- [NEW] Modernize package - migrate package settings to pyproject.toml
569
- [NEW] Migrate CLI wrapper to use `typer` library. (CLI comes now with new interface.)
@@ -11,12 +75,11 @@
1175
- Filtering of results based on `updated_after` field.
1276
- Filtering of results based on a missing field. (include_domains_with_missing_field` or `exclude_domains_with_missing_field`).
1377
- [NEW] Add support on removing/stripping colon in when passing a value in `--ssl_hash` in `iris_investigate` cli command.
14-
- [UPDATE] replace use of upcoming deprecated `datetime.uctnow()` to `timezone.utc`
78+
- [UPDATE] replace use of upcoming deprecated `datetime.utcnow()` to `timezone.utc`
1579
- [UPDATE] Improve help text in CLI commands.
1680
- [UPDATE] Remove `dateparser` dependency and use native python `datetime` library.
1781
- [FIX] Fix error in `-o` or `--out-file` parameter.
1882

19-
2083
### 1.0.1
2184

2285
- Adds support for the hourly query limit on the Account API endpoint

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.8.1
1+
2.9.0

domaintools/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@
2020
2121
"""
2222

23-
current = "2.8.1"
23+
current = "2.9.0"

domaintools/api.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1412,3 +1412,71 @@ def domainhotlist(self, **kwargs) -> FeedsResults:
14121412
cls=FeedsResults,
14131413
**kwargs,
14141414
)
1415+
1416+
def iphotlist(self, **kwargs) -> FeedsResults:
1417+
"""Returns back list of ip hotlist feed.
1418+
Captures IP addresses that meet strict criteria for both risk level and recent activity, making it ideal for immediate blocking and threat response.
1419+
1420+
before: str: Filter for records before the given time value inclusive or time offset relative to now
1421+
1422+
after: str: Filter for records after the given time value inclusive or time offset relative to now
1423+
1424+
headers: bool: Use in combination with Accept: text/csv headers to control if headers are sent or not
1425+
1426+
sessionID: str: A custom string to distinguish between different sessions
1427+
1428+
fromBeginning: bool: Requires a sessionID. When used with a new session ID, returns the first hour of data in the time window (rather than the last). Returns an error if the session ID already exists
1429+
1430+
top: int: Limits the number of results in the response payload. Primarily intended for testing. When you apply this parameter to risk feeds, results are sorted by all_threats_combined_percent (descending).
1431+
"""
1432+
validate_feeds_parameters(kwargs)
1433+
endpoint = kwargs.pop("endpoint", Endpoint.FEED.value)
1434+
source = ENDPOINT_TO_SOURCE_MAP.get(endpoint).value
1435+
if (
1436+
endpoint == Endpoint.DOWNLOAD.value
1437+
or kwargs.get("output_format", OutputFormat.JSONL.value) != OutputFormat.CSV.value
1438+
):
1439+
# headers param is allowed only in Feed API and CSV format
1440+
kwargs.pop("headers", None)
1441+
1442+
return self._results(
1443+
f"real-time-ip-hotlist-({source})",
1444+
f"v1/{endpoint}/iphotlist/",
1445+
response_path=(),
1446+
cls=FeedsResults,
1447+
**kwargs,
1448+
)
1449+
1450+
def iprisk(self, **kwargs) -> FeedsResults:
1451+
"""Returns back list of domain hotlist feed.
1452+
Captures all IP addresses that actively host one or more domains, providing risk assessment and enrichment data for each IP address.
1453+
1454+
before: str: Filter for records before the given time value inclusive or time offset relative to now
1455+
1456+
after: str: Filter for records after the given time value inclusive or time offset relative to now
1457+
1458+
headers: bool: Use in combination with Accept: text/csv headers to control if headers are sent or not
1459+
1460+
sessionID: str: A custom string to distinguish between different sessions
1461+
1462+
fromBeginning: bool: Requires a sessionID. When used with a new session ID, returns the first hour of data in the time window (rather than the last). Returns an error if the session ID already exists
1463+
1464+
top: int: Limits the number of results in the response payload. Primarily intended for testing. When you apply this parameter to risk feeds, results are sorted by all_threats_combined_percent (descending).
1465+
"""
1466+
validate_feeds_parameters(kwargs)
1467+
endpoint = kwargs.pop("endpoint", Endpoint.FEED.value)
1468+
source = ENDPOINT_TO_SOURCE_MAP.get(endpoint).value
1469+
if (
1470+
endpoint == Endpoint.DOWNLOAD.value
1471+
or kwargs.get("output_format", OutputFormat.JSONL.value) != OutputFormat.CSV.value
1472+
):
1473+
# headers param is allowed only in Feed API and CSV format
1474+
kwargs.pop("headers", None)
1475+
1476+
return self._results(
1477+
f"real-time-ip-risk-({source})",
1478+
f"v1/{endpoint}/iprisk/",
1479+
response_path=(),
1480+
cls=FeedsResults,
1481+
**kwargs,
1482+
)

domaintools/cli/commands/feeds.py

Lines changed: 167 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def feeds_nad(
7979
"--headers",
8080
help="Adds a header to the first line of response when text/csv is set in header parameters",
8181
),
82-
top: str = typer.Option(
82+
top: int = typer.Option(
8383
None,
8484
"--top",
8585
help="Number of results to return in the response payload. This is ignored in download endpoint",
@@ -159,7 +159,7 @@ def feeds_nod(
159159
"--headers",
160160
help="Adds a header to the first line of response when text/csv is set in header parameters",
161161
),
162-
top: str = typer.Option(
162+
top: int = typer.Option(
163163
None,
164164
"--top",
165165
help="Number of results to return in the response payload. This is ignored in download endpoint",
@@ -227,7 +227,7 @@ def feeds_domainrdap(
227227
"--domain",
228228
help="A string value used to filter feed results",
229229
),
230-
top: str = typer.Option(
230+
top: int = typer.Option(
231231
None,
232232
"--top",
233233
help="Number of results to return in the response payload",
@@ -307,7 +307,7 @@ def feeds_domaindiscovery(
307307
"--headers",
308308
help="Adds a header to the first line of response when text/csv is set in header parameters",
309309
),
310-
top: str = typer.Option(
310+
top: int = typer.Option(
311311
None,
312312
"--top",
313313
help="Number of results to return in the response payload. This is ignored in download endpoint",
@@ -387,7 +387,7 @@ def feeds_noh(
387387
"--headers",
388388
help="Adds a header to the first line of response when text/csv is set in header parameters",
389389
),
390-
top: str = typer.Option(
390+
top: int = typer.Option(
391391
None,
392392
"--top",
393393
help="Number of results to return in the response payload. This is ignored in download endpoint",
@@ -467,7 +467,7 @@ def feeds_domainhotlist(
467467
"--headers",
468468
help="Adds a header to the first line of response when text/csv is set in header parameters",
469469
),
470-
top: str = typer.Option(
470+
top: int = typer.Option(
471471
None,
472472
"--top",
473473
help="Number of results to return in the response payload. This is ignored in download endpoint",
@@ -547,10 +547,170 @@ def feeds_realtime_domain_risk(
547547
"--headers",
548548
help="Adds a header to the first line of response when text/csv is set in header parameters",
549549
),
550-
top: str = typer.Option(
550+
top: int = typer.Option(
551551
None,
552552
"--top",
553553
help="Number of results to return in the response payload. This is ignored in download endpoint",
554554
),
555555
):
556556
DTCLICommand.run(name=c.FEEDS_REALTIME_DOMAIN_RISK, params=ctx.params)
557+
558+
559+
@dt_cli.command(
560+
name=c.FEEDS_IPHOTLIST,
561+
help=get_cli_helptext_by_name(command_name=c.FEEDS_IPHOTLIST),
562+
)
563+
def feeds_iphotlist(
564+
ctx: typer.Context,
565+
user: str = typer.Option(None, "-u", "--user", help="Domaintools API Username."),
566+
key: str = typer.Option(None, "-k", "--key", help="DomainTools API key"),
567+
creds_file: str = typer.Option(
568+
"~/.dtapi",
569+
"-c",
570+
"--credfile",
571+
help="Optional file with API username and API key, one per line.",
572+
),
573+
no_verify_ssl: bool = typer.Option(
574+
False,
575+
"--no-verify-ssl",
576+
help="Skip verification of SSL certificate when making HTTPs API calls",
577+
),
578+
no_sign_api_key: bool = typer.Option(
579+
False,
580+
"--no-sign-api-key",
581+
help="Skip signing of api key",
582+
),
583+
no_header_authentication: bool = typer.Option(
584+
False,
585+
"--no-header-auth",
586+
help="Don't use header authentication",
587+
),
588+
output_format: str = typer.Option(
589+
"jsonl",
590+
"-f",
591+
"--format",
592+
help=f"Output format in [{OutputFormat.JSONL.value}, {OutputFormat.CSV.value}]",
593+
callback=DTCLICommand.validate_feeds_format_input,
594+
),
595+
endpoint: str = typer.Option(
596+
Endpoint.FEED.value,
597+
"-e",
598+
"--endpoint",
599+
help=f"Valid endpoints: [{Endpoint.FEED.value}, {Endpoint.DOWNLOAD.value}]",
600+
callback=DTCLICommand.validate_endpoint_input,
601+
),
602+
sessionID: str = typer.Option(
603+
None,
604+
"--session-id",
605+
help="Unique identifier for the session",
606+
),
607+
after: str = typer.Option(
608+
None,
609+
"--after",
610+
help="Start of the time window, relative to the current time in seconds, for which data will be provided",
611+
callback=DTCLICommand.validate_after_or_before_input,
612+
),
613+
before: str = typer.Option(
614+
None,
615+
"--before",
616+
help="The end of the query window in seconds, relative to the current time, inclusive",
617+
callback=DTCLICommand.validate_after_or_before_input,
618+
),
619+
fromBeginning: bool = typer.Option(
620+
None,
621+
"-fb",
622+
"--frombeginning",
623+
help="Requires a sessionID. When used with a new session ID, returns the first hour of data in the time window (rather than the last). Returns an error if the session ID already exists",
624+
),
625+
top: int = typer.Option(
626+
None,
627+
"--top",
628+
help="Number of results to return in the response payload. This is ignored in download endpoint",
629+
),
630+
headers: bool = typer.Option(
631+
False,
632+
"--headers",
633+
help="Adds a header to the first line of response when text/csv is set in header parameters",
634+
),
635+
):
636+
DTCLICommand.run(name=c.FEEDS_IPHOTLIST, params=ctx.params)
637+
638+
639+
@dt_cli.command(
640+
name=c.FEEDS_IPRISK,
641+
help=get_cli_helptext_by_name(command_name=c.FEEDS_IPRISK),
642+
)
643+
def feeds_iprisk(
644+
ctx: typer.Context,
645+
user: str = typer.Option(None, "-u", "--user", help="Domaintools API Username."),
646+
key: str = typer.Option(None, "-k", "--key", help="DomainTools API key"),
647+
creds_file: str = typer.Option(
648+
"~/.dtapi",
649+
"-c",
650+
"--credfile",
651+
help="Optional file with API username and API key, one per line.",
652+
),
653+
no_verify_ssl: bool = typer.Option(
654+
False,
655+
"--no-verify-ssl",
656+
help="Skip verification of SSL certificate when making HTTPs API calls",
657+
),
658+
no_sign_api_key: bool = typer.Option(
659+
False,
660+
"--no-sign-api-key",
661+
help="Skip signing of api key",
662+
),
663+
no_header_authentication: bool = typer.Option(
664+
False,
665+
"--no-header-auth",
666+
help="Don't use header authentication",
667+
),
668+
output_format: str = typer.Option(
669+
"jsonl",
670+
"-f",
671+
"--format",
672+
help=f"Output format in [{OutputFormat.JSONL.value}, {OutputFormat.CSV.value}]",
673+
callback=DTCLICommand.validate_feeds_format_input,
674+
),
675+
endpoint: str = typer.Option(
676+
Endpoint.FEED.value,
677+
"-e",
678+
"--endpoint",
679+
help=f"Valid endpoints: [{Endpoint.FEED.value}, {Endpoint.DOWNLOAD.value}]",
680+
callback=DTCLICommand.validate_endpoint_input,
681+
),
682+
sessionID: str = typer.Option(
683+
None,
684+
"--session-id",
685+
help="Unique identifier for the session",
686+
),
687+
after: str = typer.Option(
688+
None,
689+
"--after",
690+
help="Start of the time window, relative to the current time in seconds, for which data will be provided",
691+
callback=DTCLICommand.validate_after_or_before_input,
692+
),
693+
before: str = typer.Option(
694+
None,
695+
"--before",
696+
help="The end of the query window in seconds, relative to the current time, inclusive",
697+
callback=DTCLICommand.validate_after_or_before_input,
698+
),
699+
fromBeginning: bool = typer.Option(
700+
None,
701+
"-fb",
702+
"--frombeginning",
703+
help="Requires a sessionID. When used with a new session ID, returns the first hour of data in the time window (rather than the last). Returns an error if the session ID already exists",
704+
),
705+
top: int = typer.Option(
706+
None,
707+
"--top",
708+
help="Number of results to return in the response payload. This is ignored in download endpoint",
709+
),
710+
headers: bool = typer.Option(
711+
False,
712+
"--headers",
713+
help="Adds a header to the first line of response when text/csv is set in header parameters",
714+
),
715+
):
716+
DTCLICommand.run(name=c.FEEDS_IPRISK, params=ctx.params)

domaintools/cli/constants.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,5 @@
4848
FEEDS_DOMAINRDAP = "domainrdap"
4949
FEEDS_DOMAINDISCOVERY = "domaindiscovery"
5050
FEEDS_REALTIME_DOMAIN_RISK = "realtime_domain_risk"
51+
FEEDS_IPHOTLIST = "iphotlist"
52+
FEEDS_IPRISK = "iprisk"

0 commit comments

Comments
 (0)