Skip to content

Commit d2bb3e6

Browse files
committed
IDEV-1996: Implement domaindiscovery cli.
1 parent 63114d1 commit d2bb3e6

File tree

3 files changed

+106
-1
lines changed

3 files changed

+106
-1
lines changed

domaintools/cli/api.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from typing import Optional, Dict, Tuple
99
from rich.progress import Progress, SpinnerColumn, TextColumn
1010

11+
from domaintools.constants import Endpoint, OutputFormat
1112
from domaintools.api import API
1213
from domaintools.exceptions import ServiceException
1314
from domaintools.cli.utils import get_file_extension
@@ -32,6 +33,20 @@ def validate_format_input(value: str):
3233
raise typer.BadParameter(f"{value} is not in available formats: {VALID_FORMATS}")
3334
return value
3435

36+
@staticmethod
37+
def validate_feeds_format_input(value: str):
38+
VALID_FEEDS_FORMATS = ("jsonl", "csv")
39+
if value not in VALID_FEEDS_FORMATS:
40+
raise typer.BadParameter(f"{value} is not in available formats: {VALID_FEEDS_FORMATS}")
41+
return value
42+
43+
@staticmethod
44+
def validate_endpoint_input(value: str):
45+
VALID_ENDPOINTS = (Endpoint.FEED.value, Endpoint.DOWNLOAD.value)
46+
if value not in VALID_ENDPOINTS:
47+
raise typer.BadParameter(f"{value} is not in available endpoints: {VALID_ENDPOINTS}")
48+
return value
49+
3550
@staticmethod
3651
def validate_after_or_before_input(value: str):
3752
if value is None or value.replace("-", "").isdigit():
@@ -152,7 +167,13 @@ def run(cls, name: str, params: Optional[Dict] = {}, **kwargs):
152167
"""
153168
try:
154169
rate_limit = params.pop("rate_limit", False)
155-
response_format = params.pop("format", "json")
170+
response_format = (
171+
params.pop("format", "json")
172+
if params.get("format", None)
173+
else params.get(
174+
"output_format", OutputFormat.JSONL.value
175+
) # Using output_format for RTUF endpoints to separate from other endpoints. This will be needed further along the process
176+
)
156177
out_file = params.pop("out_file", sys.stdout)
157178
verify_ssl = params.pop("no_verify_ssl", False)
158179
always_sign_api_key = params.pop("no_sign_api_key", False)

domaintools/cli/commands/feeds.py

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from domaintools.cli.api import DTCLICommand
77
from domaintools.cli.utils import get_cli_helptext_by_name
88
from domaintools.cli import constants as c
9+
from domaintools.constants import Endpoint
910

1011

1112
@dt_cli.command(
@@ -158,6 +159,13 @@ def feeds_domainrdap(
158159
"--no-sign-api-key",
159160
help="Skip signing of api key",
160161
),
162+
endpoint: str = typer.Option(
163+
Endpoint.FEED.value,
164+
"-e",
165+
"--endpoint",
166+
help=f"Valid endpoints: [{Endpoint.FEED.value}, {Endpoint.DOWNLOAD.value}]",
167+
callback=DTCLICommand.validate_endpoint_input,
168+
),
161169
sessionID: str = typer.Option(
162170
None,
163171
"--session-id",
@@ -188,3 +196,78 @@ def feeds_domainrdap(
188196
),
189197
):
190198
DTCLICommand.run(name=c.FEEDS_DOMAINRDAP, params=ctx.params)
199+
200+
201+
@dt_cli.command(
202+
name=c.FEEDS_DOMAINDISCOVERY,
203+
help=get_cli_helptext_by_name(command_name=c.FEEDS_DOMAINDISCOVERY),
204+
)
205+
def feeds_domaindiscovery(
206+
ctx: typer.Context,
207+
user: str = typer.Option(None, "-u", "--user", help="Domaintools API Username."),
208+
key: str = typer.Option(None, "-k", "--key", help="DomainTools API key"),
209+
creds_file: str = typer.Option(
210+
"~/.dtapi",
211+
"-c",
212+
"--credfile",
213+
help="Optional file with API username and API key, one per line.",
214+
),
215+
no_verify_ssl: bool = typer.Option(
216+
False,
217+
"--no-verify-ssl",
218+
help="Skip verification of SSL certificate when making HTTPs API calls",
219+
),
220+
no_sign_api_key: bool = typer.Option(
221+
False,
222+
"--no-sign-api-key",
223+
help="Skip signing of api key",
224+
),
225+
output_format: str = typer.Option(
226+
"jsonl",
227+
"-f",
228+
"--format",
229+
help="Output format in {'jsonl'}",
230+
callback=DTCLICommand.validate_feeds_format_input,
231+
),
232+
endpoint: str = typer.Option(
233+
Endpoint.FEED.value,
234+
"-e",
235+
"--endpoint",
236+
help=f"Valid endpoints: [{Endpoint.FEED.value}, {Endpoint.DOWNLOAD.value}]",
237+
callback=DTCLICommand.validate_endpoint_input,
238+
),
239+
sessionID: str = typer.Option(
240+
None,
241+
"--session-id",
242+
help="Unique identifier for the session",
243+
),
244+
after: str = typer.Option(
245+
None,
246+
"--after",
247+
help="Start of the time window, relative to the current time in seconds, for which data will be provided",
248+
callback=DTCLICommand.validate_after_or_before_input,
249+
),
250+
before: str = typer.Option(
251+
None,
252+
"--before",
253+
help="The end of the query window in seconds, relative to the current time, inclusive",
254+
callback=DTCLICommand.validate_after_or_before_input,
255+
),
256+
domain: str = typer.Option(
257+
None,
258+
"-d",
259+
"--domain",
260+
help="A string value used to filter feed results",
261+
),
262+
headers: bool = typer.Option(
263+
False,
264+
"--headers",
265+
help="Adds a header to the first line of response when text/csv is set in header parameters",
266+
),
267+
top: str = typer.Option(
268+
None,
269+
"--top",
270+
help="Number of results to return in the response payload. This is ignored in download endpoint",
271+
),
272+
):
273+
DTCLICommand.run(name=c.FEEDS_DOMAINDISCOVERY, params=ctx.params)

domaintools/cli/constants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,4 @@
4747
FEEDS_NAD = "nad"
4848
FEEDS_NOD = "nod"
4949
FEEDS_DOMAINRDAP = "domainrdap"
50+
FEEDS_DOMAINDISCOVERY = "domaindiscovery"

0 commit comments

Comments
 (0)