cortexapps-cli 0.26.7__py3-none-any.whl → 1.0.0__py3-none-any.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.
- cortexapps_cli/cli.py +144 -0
- cortexapps_cli/command_options.py +43 -0
- cortexapps_cli/commands/api_keys.py +152 -0
- cortexapps_cli/commands/audit_logs.py +97 -0
- cortexapps_cli/commands/backup.py +310 -0
- cortexapps_cli/commands/backup_commands/cortex_export.py +174 -0
- cortexapps_cli/commands/catalog.py +365 -0
- cortexapps_cli/commands/custom_data.py +200 -0
- cortexapps_cli/commands/custom_events.py +248 -0
- cortexapps_cli/commands/custom_metrics.py +133 -0
- cortexapps_cli/commands/dependencies.py +232 -0
- cortexapps_cli/commands/deploys.py +242 -0
- cortexapps_cli/commands/discovery_audit.py +80 -0
- cortexapps_cli/commands/docs.py +63 -0
- cortexapps_cli/commands/entity_types.py +129 -0
- cortexapps_cli/commands/gitops_logs.py +75 -0
- cortexapps_cli/commands/groups.py +87 -0
- cortexapps_cli/commands/initiatives.py +121 -0
- cortexapps_cli/commands/integrations.py +35 -0
- cortexapps_cli/commands/integrations_commands/aws.py +221 -0
- cortexapps_cli/commands/integrations_commands/azure_devops.py +174 -0
- cortexapps_cli/commands/integrations_commands/azure_resources.py +258 -0
- cortexapps_cli/commands/integrations_commands/circleci.py +170 -0
- cortexapps_cli/commands/integrations_commands/coralogix.py +179 -0
- cortexapps_cli/commands/integrations_commands/datadog.py +178 -0
- cortexapps_cli/commands/integrations_commands/github.py +170 -0
- cortexapps_cli/commands/integrations_commands/gitlab.py +170 -0
- cortexapps_cli/commands/integrations_commands/incidentio.py +170 -0
- cortexapps_cli/commands/integrations_commands/launchdarkly.py +170 -0
- cortexapps_cli/commands/integrations_commands/newrelic.py +170 -0
- cortexapps_cli/commands/integrations_commands/pagerduty.py +170 -0
- cortexapps_cli/commands/integrations_commands/prometheus.py +170 -0
- cortexapps_cli/commands/integrations_commands/sonarqube.py +170 -0
- cortexapps_cli/commands/ip_allowlist.py +115 -0
- cortexapps_cli/commands/on_call.py +33 -0
- cortexapps_cli/commands/packages.py +72 -0
- cortexapps_cli/commands/packages_commands/go.py +37 -0
- cortexapps_cli/commands/packages_commands/java.py +51 -0
- cortexapps_cli/commands/packages_commands/node.py +65 -0
- cortexapps_cli/commands/packages_commands/nuget.py +50 -0
- cortexapps_cli/commands/packages_commands/python.py +51 -0
- cortexapps_cli/commands/plugins.py +153 -0
- cortexapps_cli/commands/queries.py +64 -0
- cortexapps_cli/commands/rest.py +137 -0
- cortexapps_cli/commands/scim.py +77 -0
- cortexapps_cli/commands/scorecards.py +192 -0
- cortexapps_cli/commands/scorecards_commands/exemptions.py +94 -0
- cortexapps_cli/commands/teams.py +210 -0
- cortexapps_cli/commands/workflows.py +144 -0
- cortexapps_cli/cortex.py +60 -1
- cortexapps_cli/cortex_client.py +178 -0
- cortexapps_cli/models/team.py +201 -0
- cortexapps_cli/utils.py +202 -0
- {cortexapps_cli-0.26.7.dist-info → cortexapps_cli-1.0.0.dist-info}/METADATA +29 -236
- cortexapps_cli-1.0.0.dist-info/RECORD +58 -0
- {cortexapps_cli-0.26.7.dist-info → cortexapps_cli-1.0.0.dist-info}/WHEEL +1 -1
- cortexapps_cli-1.0.0.dist-info/entry_points.txt +3 -0
- cortexapps_cli-0.26.7.dist-info/RECORD +0 -6
- cortexapps_cli-0.26.7.dist-info/entry_points.txt +0 -3
- {cortexapps_cli-0.26.7.dist-info → cortexapps_cli-1.0.0.dist-info}/LICENSE +0 -0
cortexapps_cli/cli.py
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
import typer
|
|
4
|
+
from typing_extensions import Annotated
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
import sys
|
|
8
|
+
import importlib.metadata
|
|
9
|
+
import tomllib
|
|
10
|
+
import configparser
|
|
11
|
+
import logging
|
|
12
|
+
|
|
13
|
+
from cortexapps_cli.cortex_client import CortexClient
|
|
14
|
+
|
|
15
|
+
import cortexapps_cli.commands.api_keys as api_keys
|
|
16
|
+
import cortexapps_cli.commands.audit_logs as audit_logs
|
|
17
|
+
import cortexapps_cli.commands.backup as backup
|
|
18
|
+
import cortexapps_cli.commands.catalog as catalog
|
|
19
|
+
import cortexapps_cli.commands.custom_data as custom_data
|
|
20
|
+
import cortexapps_cli.commands.custom_events as custom_events
|
|
21
|
+
import cortexapps_cli.commands.custom_metrics as custom_metrics
|
|
22
|
+
import cortexapps_cli.commands.dependencies as dependencies
|
|
23
|
+
import cortexapps_cli.commands.deploys as deploys
|
|
24
|
+
import cortexapps_cli.commands.discovery_audit as discovery_audit
|
|
25
|
+
import cortexapps_cli.commands.docs as docs
|
|
26
|
+
import cortexapps_cli.commands.entity_types as entity_types
|
|
27
|
+
import cortexapps_cli.commands.gitops_logs as gitops_logs
|
|
28
|
+
import cortexapps_cli.commands.groups as groups
|
|
29
|
+
import cortexapps_cli.commands.initiatives as initiatives
|
|
30
|
+
import cortexapps_cli.commands.integrations as integrations
|
|
31
|
+
import cortexapps_cli.commands.ip_allowlist as ip_allowlist
|
|
32
|
+
import cortexapps_cli.commands.on_call as on_call
|
|
33
|
+
import cortexapps_cli.commands.packages as packages
|
|
34
|
+
import cortexapps_cli.commands.plugins as plugins
|
|
35
|
+
import cortexapps_cli.commands.queries as queries
|
|
36
|
+
import cortexapps_cli.commands.rest as rest
|
|
37
|
+
import cortexapps_cli.commands.scim as scim
|
|
38
|
+
import cortexapps_cli.commands.scorecards as scorecards
|
|
39
|
+
import cortexapps_cli.commands.teams as teams
|
|
40
|
+
import cortexapps_cli.commands.workflows as workflows
|
|
41
|
+
|
|
42
|
+
app = typer.Typer(
|
|
43
|
+
no_args_is_help=True,
|
|
44
|
+
rich_markup_mode="rich",
|
|
45
|
+
context_settings={"help_option_names": ["-h", "--help"]}
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
# add subcommands
|
|
49
|
+
app.add_typer(api_keys.app, name="api-keys")
|
|
50
|
+
app.add_typer(audit_logs.app, name="audit-logs")
|
|
51
|
+
app.add_typer(backup.app, name="backup")
|
|
52
|
+
app.add_typer(catalog.app, name="catalog")
|
|
53
|
+
app.add_typer(custom_data.app, name="custom-data")
|
|
54
|
+
app.add_typer(custom_events.app, name="custom-events")
|
|
55
|
+
app.add_typer(custom_metrics.app, name="custom-metrics")
|
|
56
|
+
app.add_typer(dependencies.app, name="dependencies")
|
|
57
|
+
app.add_typer(deploys.app, name="deploys")
|
|
58
|
+
app.add_typer(discovery_audit.app, name="discovery-audit")
|
|
59
|
+
app.add_typer(docs.app, name="docs")
|
|
60
|
+
app.add_typer(entity_types.app, name="entity-types")
|
|
61
|
+
app.add_typer(gitops_logs.app, name="gitops-logs")
|
|
62
|
+
app.add_typer(groups.app, name="groups")
|
|
63
|
+
app.add_typer(initiatives.app, name="initiatives")
|
|
64
|
+
app.add_typer(integrations.app, name="integrations")
|
|
65
|
+
app.add_typer(ip_allowlist.app, name="ip-allowlist")
|
|
66
|
+
app.add_typer(on_call.app, name="on-call")
|
|
67
|
+
app.add_typer(packages.app, name="packages")
|
|
68
|
+
app.add_typer(plugins.app, name="plugins")
|
|
69
|
+
app.add_typer(queries.app, name="queries")
|
|
70
|
+
app.add_typer(rest.app, name="rest")
|
|
71
|
+
app.add_typer(scim.app, name="scim")
|
|
72
|
+
app.add_typer(scorecards.app, name="scorecards")
|
|
73
|
+
app.add_typer(teams.app, name="teams")
|
|
74
|
+
app.add_typer(workflows.app, name="workflows")
|
|
75
|
+
|
|
76
|
+
# global options
|
|
77
|
+
@app.callback()
|
|
78
|
+
def global_callback(
|
|
79
|
+
ctx: typer.Context,
|
|
80
|
+
api_key: str = typer.Option(None, "--api-key", "-k", help="API key", envvar="CORTEX_API_KEY"),
|
|
81
|
+
url: str = typer.Option("https://api.getcortexapp.com", "--url", "-u", help="Base URL for the API", envvar="CORTEX_BASE_URL"),
|
|
82
|
+
config_file: str = typer.Option(os.path.join(os.path.expanduser('~'), '.cortex', 'config'), "--config", "-c", help="Config file path", envvar="CORTEX_CONFIG"),
|
|
83
|
+
tenant: str = typer.Option("default", "--tenant", "-t", help="Tenant alias", envvar="CORTEX_TENANT_ALIAS"),
|
|
84
|
+
log_level: Annotated[str, typer.Option("--log-level", "-l", help="Set the logging level")] = "INFO"
|
|
85
|
+
):
|
|
86
|
+
if not ctx.obj:
|
|
87
|
+
ctx.obj = {}
|
|
88
|
+
|
|
89
|
+
numeric_level = getattr(logging, log_level.upper(), None)
|
|
90
|
+
if not isinstance(numeric_level, int):
|
|
91
|
+
raise ValueError(f"Invalid log level: {log_level}")
|
|
92
|
+
|
|
93
|
+
if not os.path.isfile(config_file):
|
|
94
|
+
# no config file found
|
|
95
|
+
if not api_key:
|
|
96
|
+
raise typer.BadParameter("No API key provided and no config file found")
|
|
97
|
+
create_config = False
|
|
98
|
+
|
|
99
|
+
# check if we are in a terminal, if so, ask the user if they want to create a config file
|
|
100
|
+
if sys.stdin.isatty() and sys.stdout.isatty():
|
|
101
|
+
create_config = typer.confirm("No config file found. Do you want to create one?")
|
|
102
|
+
|
|
103
|
+
if create_config:
|
|
104
|
+
os.makedirs(os.path.dirname(config_file), exist_ok=True)
|
|
105
|
+
with open(config_file, "w") as f:
|
|
106
|
+
f.write(f"[{tenant}]\n")
|
|
107
|
+
f.write(f"api_key = {api_key}\n")
|
|
108
|
+
f.write(f"base_url = {url}\n")
|
|
109
|
+
else:
|
|
110
|
+
# config file found
|
|
111
|
+
# if api_key is provided, use that in preference to the config file
|
|
112
|
+
if not api_key:
|
|
113
|
+
config = configparser.ConfigParser()
|
|
114
|
+
config.read(config_file)
|
|
115
|
+
if tenant not in config:
|
|
116
|
+
raise typer.BadParameter(f"Tenant {tenant} not found in config file")
|
|
117
|
+
api_key = config[tenant]["api_key"]
|
|
118
|
+
if url not in config[tenant]:
|
|
119
|
+
url = url
|
|
120
|
+
else:
|
|
121
|
+
url = config[tenant]["base_url"]
|
|
122
|
+
|
|
123
|
+
# strip any quotes or spaces from the api_key and url
|
|
124
|
+
api_key = api_key.strip('"\' ')
|
|
125
|
+
url = url.strip('"\' /')
|
|
126
|
+
|
|
127
|
+
ctx.obj["client"] = CortexClient(api_key, tenant, numeric_level, url)
|
|
128
|
+
|
|
129
|
+
@app.command()
|
|
130
|
+
def version():
|
|
131
|
+
|
|
132
|
+
"""
|
|
133
|
+
Show the version and exit.
|
|
134
|
+
"""
|
|
135
|
+
try:
|
|
136
|
+
with open("pyproject.toml", "rb") as f:
|
|
137
|
+
pyproject = tomllib.load(f)
|
|
138
|
+
version = pyproject["tool"]["poetry"]["version"]
|
|
139
|
+
except Exception as e:
|
|
140
|
+
version = importlib.metadata.version('cortexapps_cli')
|
|
141
|
+
print(version)
|
|
142
|
+
|
|
143
|
+
if __name__ == "__main__":
|
|
144
|
+
app()
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
from typing import List, Optional
|
|
3
|
+
from typing_extensions import Annotated
|
|
4
|
+
|
|
5
|
+
class ListCommandOptions:
|
|
6
|
+
table_output = Annotated[
|
|
7
|
+
Optional[bool],
|
|
8
|
+
typer.Option("--table", help="Output the response as a table", show_default=False) # , callback=table_output_cb)
|
|
9
|
+
]
|
|
10
|
+
csv_output = Annotated[
|
|
11
|
+
Optional[bool],
|
|
12
|
+
typer.Option("--csv", help="Output the response as CSV", show_default=False) # , callback=csv_output_cb)
|
|
13
|
+
]
|
|
14
|
+
columns = Annotated[
|
|
15
|
+
Optional[List[str]],
|
|
16
|
+
typer.Option("--columns", "-C", help="Columns to include in the table, in the format HeaderName=jsonpath", show_default=False)
|
|
17
|
+
]
|
|
18
|
+
filters = Annotated[
|
|
19
|
+
Optional[List[str]],
|
|
20
|
+
typer.Option("--filter", "-F", help="Filters to apply on rows, in the format jsonpath=regex", show_default=False)
|
|
21
|
+
]
|
|
22
|
+
no_headers = Annotated[
|
|
23
|
+
Optional[bool],
|
|
24
|
+
typer.Option("--no-headers", help="For csv output type only: don't print header columns.", show_default=False)
|
|
25
|
+
]
|
|
26
|
+
sort = Annotated[
|
|
27
|
+
Optional[List[str]],
|
|
28
|
+
typer.Option("--sort", "-S", help="Sort order to apply on rows, in the format jsonpath:asc or jsonpath:desc", show_default=False)
|
|
29
|
+
]
|
|
30
|
+
page = Annotated[
|
|
31
|
+
Optional[int],
|
|
32
|
+
typer.Option("--page", "-p", help="Page number to return, 0 indexed - omit to fetch all pages", show_default=False)
|
|
33
|
+
]
|
|
34
|
+
page_size = Annotated[
|
|
35
|
+
Optional[int],
|
|
36
|
+
typer.Option("--page-size", "-z", help="Page size for results", show_default=False)
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
class CommandOptions:
|
|
40
|
+
_print = Annotated[
|
|
41
|
+
Optional[bool],
|
|
42
|
+
typer.Option("--print", help="If result should be printed to the terminal", hidden=True)
|
|
43
|
+
]
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
import typer
|
|
3
|
+
import json
|
|
4
|
+
from enum import Enum
|
|
5
|
+
from typing_extensions import Annotated
|
|
6
|
+
from cortexapps_cli.utils import print_output_with_context
|
|
7
|
+
from cortexapps_cli.command_options import CommandOptions
|
|
8
|
+
from cortexapps_cli.command_options import ListCommandOptions
|
|
9
|
+
|
|
10
|
+
app = typer.Typer(
|
|
11
|
+
help="API Keys commands",
|
|
12
|
+
no_args_is_help=True
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
class DefaultRole(str, Enum):
|
|
16
|
+
ADMIN = "ADMIN"
|
|
17
|
+
USER = "USER"
|
|
18
|
+
READ_ONLY = "READ_ONLY"
|
|
19
|
+
|
|
20
|
+
@app.command()
|
|
21
|
+
def list(
|
|
22
|
+
ctx: typer.Context,
|
|
23
|
+
page: ListCommandOptions.page = None,
|
|
24
|
+
page_size: ListCommandOptions.page_size = 250,
|
|
25
|
+
table_output: ListCommandOptions.table_output = False,
|
|
26
|
+
csv_output: ListCommandOptions.csv_output = False,
|
|
27
|
+
columns: ListCommandOptions.columns = [],
|
|
28
|
+
no_headers: ListCommandOptions.no_headers = False,
|
|
29
|
+
filters: ListCommandOptions.filters = [],
|
|
30
|
+
sort: ListCommandOptions.sort = [],
|
|
31
|
+
):
|
|
32
|
+
"""
|
|
33
|
+
List API keys. The API key used to make the request must have the Edit API keys permission.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
client = ctx.obj["client"]
|
|
37
|
+
|
|
38
|
+
params = {
|
|
39
|
+
"page": page,
|
|
40
|
+
"pageSize": page_size
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (table_output or csv_output) and not ctx.params.get('columns'):
|
|
44
|
+
ctx.params['columns'] = [
|
|
45
|
+
"CID=cid",
|
|
46
|
+
"Name=name",
|
|
47
|
+
"Last4=last4",
|
|
48
|
+
"Description=description",
|
|
49
|
+
"Roles=roles",
|
|
50
|
+
"CreatedDate=createdDate",
|
|
51
|
+
"ExpirationDate=expirationDate",
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
# remove any params that are None
|
|
55
|
+
params = {k: v for k, v in params.items() if v is not None}
|
|
56
|
+
|
|
57
|
+
if page is None:
|
|
58
|
+
r = client.fetch("api/v1/auth/key", params=params)
|
|
59
|
+
else:
|
|
60
|
+
r = client.get("api/v1/auth/key", params=params)
|
|
61
|
+
print_output_with_context(ctx, r)
|
|
62
|
+
|
|
63
|
+
@app.command()
|
|
64
|
+
def create(
|
|
65
|
+
ctx: typer.Context,
|
|
66
|
+
description: str | None = typer.Option(None, "--description", "-d", help="Description of the API key"),
|
|
67
|
+
name: str | None = typer.Option(None, "--name", "-n", help="Name of the API key"),
|
|
68
|
+
file_input: Annotated[typer.FileText, typer.Option("--file", "-f", help=" File containing content; can be passed as stdin with -, example: -f-")] = None,
|
|
69
|
+
default_roles: str | None = typer.Option(None, "--default-roles", "-dr", help="Comma-separated list of default roles (only if file input not provided."),
|
|
70
|
+
custom_roles: str | None = typer.Option(None, "--custom-roles", "-cr", help="Comma-separated list of custom roles (only if file input not provided."),
|
|
71
|
+
expiration_date: datetime | None = typer.Option(None, "--expiration-date", "-e", help="Expiration date of the API key", formats=["%Y-%m-%d", "%Y-%m-%dT%H:%M:%S", "%Y-%m-%dT%H:%M"]),
|
|
72
|
+
):
|
|
73
|
+
"""
|
|
74
|
+
Create new API key. The API key used to make the request must have the Create API keys permission
|
|
75
|
+
"""
|
|
76
|
+
client = ctx.obj["client"]
|
|
77
|
+
|
|
78
|
+
if file_input:
|
|
79
|
+
if name or description or expiration_date or default_roles or custom_roles:
|
|
80
|
+
raise typer.BadParameter("When providing an API definition file, do not specify any other attributes")
|
|
81
|
+
data = json.loads("".join([line for line in file_input]))
|
|
82
|
+
else:
|
|
83
|
+
if not default_roles and not custom_roles:
|
|
84
|
+
raise typer.BadParameter("One of default-roles or custom-roles is required")
|
|
85
|
+
|
|
86
|
+
data = {
|
|
87
|
+
"roles": [],
|
|
88
|
+
"name": name
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if default_roles is not None:
|
|
92
|
+
for role in default_roles.split(","):
|
|
93
|
+
data["roles"].append({"role": role, "type": "DEFAULT"})
|
|
94
|
+
if custom_roles is not None:
|
|
95
|
+
for role in custom_roles.split(","):
|
|
96
|
+
data["roles"].append({"tag": role, "type": "CUSTOM"})
|
|
97
|
+
|
|
98
|
+
if description:
|
|
99
|
+
data["description"] = description
|
|
100
|
+
if expiration_date:
|
|
101
|
+
data["expirationDate"] = expiration_date.strftime('%Y-%m-%dT%H:%M:%S.000Z')
|
|
102
|
+
|
|
103
|
+
r = client.post("api/v1/auth/key", data=data)
|
|
104
|
+
print_output_with_context(ctx, r)
|
|
105
|
+
|
|
106
|
+
@app.command()
|
|
107
|
+
def update(
|
|
108
|
+
ctx: typer.Context,
|
|
109
|
+
cid: str = typer.Option(..., "--cid", "-c", help="The unique, auto-generated identifier for the API key"),
|
|
110
|
+
description: str | None = typer.Option(None, "--description", "-d", help="Description of the API key"),
|
|
111
|
+
name: str = typer.Option(..., "--name", "-n", help="Name of the API key"),
|
|
112
|
+
):
|
|
113
|
+
"""
|
|
114
|
+
Update API key. The API key used to make the request must have the Edit API keys permission.
|
|
115
|
+
"""
|
|
116
|
+
client = ctx.obj["client"]
|
|
117
|
+
|
|
118
|
+
data = {
|
|
119
|
+
"name": name
|
|
120
|
+
}
|
|
121
|
+
if description is not None:
|
|
122
|
+
data["description"] = description
|
|
123
|
+
|
|
124
|
+
r = client.put("api/v1/auth/key/" + cid, data=data)
|
|
125
|
+
print_output_with_context(ctx, r)
|
|
126
|
+
|
|
127
|
+
@app.command()
|
|
128
|
+
def get(
|
|
129
|
+
ctx: typer.Context,
|
|
130
|
+
cid: str = typer.Option(..., "--cid", "-c", help="The unique, auto-generated identifier for the API key"),
|
|
131
|
+
):
|
|
132
|
+
"""
|
|
133
|
+
Get API key.
|
|
134
|
+
"""
|
|
135
|
+
|
|
136
|
+
client = ctx.obj["client"]
|
|
137
|
+
|
|
138
|
+
r = client.get("api/v1/auth/key/"+ cid)
|
|
139
|
+
print_output_with_context(ctx, r)
|
|
140
|
+
|
|
141
|
+
@app.command()
|
|
142
|
+
def delete(
|
|
143
|
+
ctx: typer.Context,
|
|
144
|
+
cid: str = typer.Option(..., "--cid", "-c", help="The unique, auto-generated identifier for the API key"),
|
|
145
|
+
):
|
|
146
|
+
"""
|
|
147
|
+
Delete API key.
|
|
148
|
+
"""
|
|
149
|
+
|
|
150
|
+
client = ctx.obj["client"]
|
|
151
|
+
|
|
152
|
+
r = client.delete("api/v1/auth/key/"+ cid)
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from enum import Enum
|
|
3
|
+
import typer
|
|
4
|
+
from cortexapps_cli.command_options import ListCommandOptions
|
|
5
|
+
from cortexapps_cli.utils import print_output_with_context, print_output
|
|
6
|
+
|
|
7
|
+
app = typer.Typer(
|
|
8
|
+
help="Audit log commands",
|
|
9
|
+
no_args_is_help=True
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
class Action(str, Enum):
|
|
13
|
+
CREATE = "CREATE"
|
|
14
|
+
DELETE = "DELETE"
|
|
15
|
+
UPDATE = "UPDATE"
|
|
16
|
+
|
|
17
|
+
class ActorType(str, Enum):
|
|
18
|
+
ANONYMOUS = "ANONYMOUS"
|
|
19
|
+
API_KEY = "API_KEY"
|
|
20
|
+
BACKSTAGE = "BACKSTAGE"
|
|
21
|
+
OAUTH2 = "OAUTH2"
|
|
22
|
+
PERSONAL_API_KEY = "PERSONAL_API_KEY"
|
|
23
|
+
|
|
24
|
+
class ActorRequestType(str, Enum):
|
|
25
|
+
API_KEY_ENTITY = "API_KEY_ENTITY"
|
|
26
|
+
ATLASSIAN_WEBHOOK = "ATLASSIAN_WEBHOOK"
|
|
27
|
+
SCORECARD_BADGES = "SCORECARD_BADGES"
|
|
28
|
+
SLACK_COMMAND = "SLACK_COMMAND"
|
|
29
|
+
|
|
30
|
+
@app.command()
|
|
31
|
+
def get(
|
|
32
|
+
ctx: typer.Context,
|
|
33
|
+
actions: list[Action] | None = typer.Option(None, "--actions", "-a", help="The audit action"),
|
|
34
|
+
actorApiKeyIdentifiers: list[str] | None = typer.Option(None, "--actorApiKeyIdentifiers", "-ak", help="API key name associated with audit event"),
|
|
35
|
+
actorEmails: list[str] | None = typer.Option(None, "--actorEmails", "-ae", help="Email address associated with audit event"),
|
|
36
|
+
actorIpAddresses: list[str] | None = typer.Option(None, "--actorIpAddresses", "-ai", help="Source IP Addresses associated with audit event"),
|
|
37
|
+
actorRequestTypes: list[ActorRequestType] | None = typer.Option(None, "--actorRequestTypes", "-ar", help="Request event associated with audit event"),
|
|
38
|
+
actorTypes: list[ActorType] | None = typer.Option(None, "--actorTypes", "-at", help="Actor that triggered the audit event"),
|
|
39
|
+
end_time: datetime = typer.Option(None, "--end-time", "-e", help="End time of audit logs to retrieve", formats=["%Y-%m-%dT%H:%M:%S", "%Y-%m-%dT%H:%M"]),
|
|
40
|
+
objectIdentifiers: list[str] | None = typer.Option(None, "--objectIdentifiers", "-oi", help="The name of the Cortex object that was modified, ie x-cortex-tag value, metadata field name, etc."),
|
|
41
|
+
objectTypes: list[str] | None = typer.Option(None, "--objectTypes", "-ot", help="ObjectTypes"),
|
|
42
|
+
start_time: datetime = typer.Option(None, "--start-time", "-s", help="Start time of audit logs to retrieve", formats=["%Y-%m-%dT%H:%M:%S", "%Y-%m-%dT%H:%M"]),
|
|
43
|
+
page: ListCommandOptions.page = None,
|
|
44
|
+
page_size: ListCommandOptions.page_size = 250,
|
|
45
|
+
table_output: ListCommandOptions.table_output = False,
|
|
46
|
+
csv_output: ListCommandOptions.csv_output = False,
|
|
47
|
+
columns: ListCommandOptions.columns = [],
|
|
48
|
+
no_headers: ListCommandOptions.no_headers = False,
|
|
49
|
+
filters: ListCommandOptions.filters = [],
|
|
50
|
+
sort: ListCommandOptions.sort = [],
|
|
51
|
+
):
|
|
52
|
+
"""
|
|
53
|
+
Note: To see the complete list of possible values, please reference the available filter options for audit logs under Settings in the app.
|
|
54
|
+
"""
|
|
55
|
+
client = ctx.obj["client"]
|
|
56
|
+
|
|
57
|
+
params = {
|
|
58
|
+
"actions": actions,
|
|
59
|
+
"actorApiKeyIdentifiers": actorApiKeyIdentifiers,
|
|
60
|
+
"actorEmails": actorEmails,
|
|
61
|
+
"actorIpAddresses": actorIpAddresses,
|
|
62
|
+
"actorRequestTypes": actorRequestTypes,
|
|
63
|
+
"actorTypes": actorTypes,
|
|
64
|
+
"endTime": end_time,
|
|
65
|
+
"objectIdentifiers": objectIdentifiers,
|
|
66
|
+
"objectTypes": objectTypes,
|
|
67
|
+
"page": page,
|
|
68
|
+
"pageSize": page_size,
|
|
69
|
+
"startTime": start_time
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
# remove any params that are None
|
|
73
|
+
params = {k: v for k, v in params.items() if v is not None}
|
|
74
|
+
|
|
75
|
+
# convert datetime and list types to string
|
|
76
|
+
for k, v in params.items():
|
|
77
|
+
if str(type(v)) == "<class 'datetime.datetime'>":
|
|
78
|
+
params[k] = v.strftime('%Y-%m-%dT%H:%M:%S')
|
|
79
|
+
if str(type(v)) == "<class 'list'>":
|
|
80
|
+
params[k] = ','.join(v)
|
|
81
|
+
|
|
82
|
+
if (table_output or csv_output) and not ctx.params.get('columns'):
|
|
83
|
+
ctx.params['columns'] = [
|
|
84
|
+
"Action=action",
|
|
85
|
+
"ObjectType=objectType",
|
|
86
|
+
"ActorIdentifier=actorIdentifier",
|
|
87
|
+
"ObjectIdentifier=objectIdentifier",
|
|
88
|
+
"IpAddress=ipAddress",
|
|
89
|
+
"Timestamp=timestamp",
|
|
90
|
+
]
|
|
91
|
+
|
|
92
|
+
if page is None:
|
|
93
|
+
r = client.fetch("api/v1/audit-logs", params=params)
|
|
94
|
+
else:
|
|
95
|
+
r = client.get("api/v1/audit-logs", params=params)
|
|
96
|
+
|
|
97
|
+
print_output_with_context(ctx, r)
|