praetorian-cli 2.4.3__tar.gz → 2.4.4__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.
- {praetorian_cli-2.4.3/praetorian_cli.egg-info → praetorian_cli-2.4.4}/PKG-INFO +1 -1
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/handlers/get.py +25 -7
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/entities/credentials.py +16 -3
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/test_credentials.py +156 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4/praetorian_cli.egg-info}/PKG-INFO +1 -1
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/setup.cfg +1 -1
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/LICENSE +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/MANIFEST.in +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/README.md +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/__init__.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/handlers/__init__.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/handlers/access.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/handlers/add.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/handlers/aegis.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/handlers/agent.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/handlers/chariot.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/handlers/cli_decorators.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/handlers/configure.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/handlers/critfinder.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/handlers/delete.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/handlers/engagement.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/handlers/enrich.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/handlers/export.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/handlers/find.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/handlers/imports.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/handlers/link.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/handlers/list.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/handlers/report.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/handlers/run.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/handlers/script.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/handlers/search.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/handlers/ssh_utils.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/handlers/test.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/handlers/unlink.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/handlers/update.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/handlers/utils.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/main.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/runners/__init__.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/runners/local.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/scripts/__init__.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/scripts/commands/__init__.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/scripts/commands/nmap-example.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/scripts/utils.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/__init__.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/chariot.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/entities/__init__.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/entities/account_discovery.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/entities/accounts.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/entities/ad.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/entities/aegis.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/entities/agents.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/entities/assets.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/entities/attributes.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/entities/capabilities.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/entities/configurations.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/entities/definitions.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/entities/files.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/entities/integrations.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/entities/jobs.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/entities/keys.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/entities/preseeds.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/entities/reports.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/entities/risks.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/entities/scanners.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/entities/schedules.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/entities/schema.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/entities/search.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/entities/seeds.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/entities/settings.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/entities/statistics.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/entities/webhook.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/entities/webpage.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/guard.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/keychain.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/mcp_server.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/model/__init__.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/model/aegis.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/model/globals.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/model/query.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/model/utils.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/__init__.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/pytest.ini +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/test_access_aws.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/test_account.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/test_agent.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/test_asset.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/test_attribute.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/test_bulk.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/test_capabilities.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/test_configuration.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/test_conversation.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/test_credential_process.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/test_definition.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/test_export_cli.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/test_extend.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/test_file.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/test_job.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/test_key.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/test_local_runner.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/test_mcp.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/test_preseed.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/test_report.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/test_risk.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/test_run_cli.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/test_search.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/test_seed.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/test_setting.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/test_webhook.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/test_webpage.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/test_z_cli.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/ui_mocks.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/utils.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/__init__.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/aegis/__init__.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/aegis/account_selector.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/aegis/commands/__init__.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/aegis/commands/cp.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/aegis/commands/help.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/aegis/commands/info.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/aegis/commands/job.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/aegis/commands/job_helpers.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/aegis/commands/list.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/aegis/commands/proxy.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/aegis/commands/schedule.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/aegis/commands/schedule_helpers.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/aegis/commands/set.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/aegis/commands/ssh.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/aegis/constants.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/aegis/menu.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/aegis/theme.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/aegis/utils.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/console/__init__.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/console/commands/__init__.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/console/commands/accounts.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/console/commands/context.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/console/commands/data.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/console/commands/marcus.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/console/commands/reporting.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/console/commands/search.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/console/commands/tools.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/console/console.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/console/context.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/console/renderer.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/conversation/__init__.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/conversation/textual_chat.py +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli.egg-info/SOURCES.txt +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli.egg-info/dependency_links.txt +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli.egg-info/entry_points.txt +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli.egg-info/requires.txt +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli.egg-info/top_level.txt +0 -0
- {praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/pyproject.toml +0 -0
|
@@ -4,7 +4,7 @@ import click
|
|
|
4
4
|
|
|
5
5
|
from praetorian_cli.handlers.chariot import chariot
|
|
6
6
|
from praetorian_cli.handlers.cli_decorators import cli_handler, praetorian_only
|
|
7
|
-
from praetorian_cli.handlers.utils import print_json
|
|
7
|
+
from praetorian_cli.handlers.utils import error, print_json
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
@chariot.group()
|
|
@@ -259,31 +259,49 @@ def configuration(chariot, key):
|
|
|
259
259
|
|
|
260
260
|
@get.command()
|
|
261
261
|
@cli_handler
|
|
262
|
-
@click.argument('credential_id', required=
|
|
262
|
+
@click.argument('credential_id', required=False, default='')
|
|
263
263
|
@click.option('--category', default='env-integration', help='The category of the credential (e.g., integration, cloud)')
|
|
264
264
|
@click.option('--type', default='default', help='The type of credential (e.g., aws, gcp, azure, static, ssh_key, json)')
|
|
265
265
|
@click.option('--format', default='token', help='The format of the credential response')
|
|
266
|
+
@click.option('--resolution',
|
|
267
|
+
type=click.Choice(['by-target', 'from-parent'], case_sensitive=False),
|
|
268
|
+
default='by-target',
|
|
269
|
+
show_default=True,
|
|
270
|
+
help='How the broker should locate the credential. '
|
|
271
|
+
'by-target: use the supplied CREDENTIAL_ID as-is. '
|
|
272
|
+
'from-parent: walk DISCOVERED ancestors of --resource-key to find one with a matching credential.')
|
|
273
|
+
@click.option('--resource-key', default=None,
|
|
274
|
+
help='Asset/resource key to scope the lookup. Required when --resolution=from-parent.')
|
|
266
275
|
@click.option('--parameters', nargs=2, multiple=True, help='Additional parameters, as --parameters key value')
|
|
267
|
-
def credential(chariot, credential_id, category, type, format, parameters):
|
|
276
|
+
def credential(chariot, credential_id, category, type, format, resolution, resource_key, parameters):
|
|
268
277
|
""" Get a specific credential
|
|
269
278
|
|
|
270
279
|
Retrieve a specific credential using the credential broker.
|
|
271
280
|
|
|
272
281
|
\b
|
|
273
282
|
Argument:
|
|
274
|
-
- CREDENTIAL_ID: the ID of the credential to retrieve
|
|
283
|
+
- CREDENTIAL_ID: the ID of the credential to retrieve. Required for
|
|
284
|
+
--resolution=by-target; optional for from-parent.
|
|
275
285
|
|
|
276
286
|
\b
|
|
277
287
|
Example usages:
|
|
278
288
|
- guard get credential aws-prod --category integration --type aws --format json
|
|
279
289
|
- guard get credential ssh-key-1 --category cloud --type ssh_key --format pem
|
|
290
|
+
- guard get credential --resolution from-parent --resource-key '#asset#example.com#1.2.3.4' --type aws
|
|
280
291
|
"""
|
|
281
|
-
|
|
292
|
+
if resolution == 'by-target' and not credential_id:
|
|
293
|
+
error('CREDENTIAL_ID is required when --resolution=by-target.')
|
|
294
|
+
if resolution == 'from-parent' and not resource_key:
|
|
295
|
+
error('--resource-key is required when --resolution=from-parent.')
|
|
296
|
+
|
|
282
297
|
params = {}
|
|
283
298
|
if parameters:
|
|
284
299
|
params = {key: value for key, value in parameters}
|
|
285
|
-
|
|
286
|
-
result = chariot.credentials.get(
|
|
300
|
+
|
|
301
|
+
result = chariot.credentials.get(
|
|
302
|
+
credential_id, category, type, [format],
|
|
303
|
+
resolution=resolution, resource_key=resource_key, **params,
|
|
304
|
+
)
|
|
287
305
|
output = chariot.credentials.format_output(result)
|
|
288
306
|
click.echo(output)
|
|
289
307
|
|
|
@@ -72,11 +72,14 @@ class Credentials:
|
|
|
72
72
|
"""
|
|
73
73
|
return self.api.search.by_key_prefix('#credential', offset=offset, pages=pages)
|
|
74
74
|
|
|
75
|
-
def get(self, credential_id, category, type, format,
|
|
75
|
+
def get(self, credential_id, category, type, format, resolution='by-target',
|
|
76
|
+
resource_key=None, **parameters):
|
|
76
77
|
"""
|
|
77
78
|
Get a specific credential using the credential broker.
|
|
78
79
|
|
|
79
|
-
:param credential_id: The ID of the credential to retrieve
|
|
80
|
+
:param credential_id: The ID of the credential to retrieve. Required for
|
|
81
|
+
resolution='by-target'; optional for 'from-parent' (broker walks the
|
|
82
|
+
graph if empty).
|
|
80
83
|
:type credential_id: str
|
|
81
84
|
:param category: The category of the credential ('integration', 'cloud', 'env-integration')
|
|
82
85
|
:type category: str
|
|
@@ -84,6 +87,13 @@ class Credentials:
|
|
|
84
87
|
:type type: str
|
|
85
88
|
:param format: The format of the credential response ('token', 'file', 'env')
|
|
86
89
|
:type format: str or list
|
|
90
|
+
:param resolution: How the broker should locate the credential. One of
|
|
91
|
+
'by-target' (use credential_id as-is; default) or 'from-parent'
|
|
92
|
+
(walk DISCOVERED ancestors of resource_key).
|
|
93
|
+
:type resolution: str
|
|
94
|
+
:param resource_key: Asset/resource key the credential is scoped to.
|
|
95
|
+
Required when resolution='from-parent'.
|
|
96
|
+
:type resource_key: str or None
|
|
87
97
|
:param parameters: Additional parameters required for the credential request (e.g., region, role_arn)
|
|
88
98
|
:type parameters: dict
|
|
89
99
|
:return: The processed credential response based on the requested format
|
|
@@ -101,8 +111,11 @@ class Credentials:
|
|
|
101
111
|
'Category': category,
|
|
102
112
|
'Type': type,
|
|
103
113
|
'Format': broker_format,
|
|
104
|
-
'
|
|
114
|
+
'Resolution': resolution,
|
|
115
|
+
'Parameters': parameters,
|
|
105
116
|
}
|
|
117
|
+
if resource_key:
|
|
118
|
+
request['ResourceKey'] = resource_key
|
|
106
119
|
response = self.api.post('broker', request)
|
|
107
120
|
return self._process_credential_output(response, format)
|
|
108
121
|
|
|
@@ -9,6 +9,7 @@ from click.testing import CliRunner
|
|
|
9
9
|
# Click commands on the `chariot` group via decorators at import time.
|
|
10
10
|
import praetorian_cli.handlers.add # noqa: F401
|
|
11
11
|
import praetorian_cli.handlers.delete # noqa: F401
|
|
12
|
+
import praetorian_cli.handlers.get # noqa: F401
|
|
12
13
|
import praetorian_cli.handlers.update # noqa: F401
|
|
13
14
|
from praetorian_cli.handlers.chariot import chariot
|
|
14
15
|
from praetorian_cli.sdk.entities.assets import Assets
|
|
@@ -46,6 +47,89 @@ class TestCredentialsAdd:
|
|
|
46
47
|
})
|
|
47
48
|
|
|
48
49
|
|
|
50
|
+
class TestCredentialsGet:
|
|
51
|
+
def test_get_builds_broker_request_with_resolution_by_target(self):
|
|
52
|
+
"""The broker rejects Get requests without Resolution (PR #5457). The
|
|
53
|
+
CLI always passes an explicit credential_id, so Resolution must be
|
|
54
|
+
'by-target' — anything else either ignores the id (global) or requires
|
|
55
|
+
a ResourceKey the CLI doesn't have (from-parent)."""
|
|
56
|
+
api = MagicMock()
|
|
57
|
+
api.post.return_value = {'credentialValue': {'token': 'abc'}}
|
|
58
|
+
creds = Credentials(api=api)
|
|
59
|
+
|
|
60
|
+
creds.get(
|
|
61
|
+
credential_id='e699e73e-e371-4117-9192-e32147dfe98c',
|
|
62
|
+
category='env-integration',
|
|
63
|
+
type='aws',
|
|
64
|
+
format=['token'],
|
|
65
|
+
accountId='123456789012',
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
api.post.assert_called_once_with('broker', {
|
|
69
|
+
'Operation': 'get',
|
|
70
|
+
'CredentialID': 'e699e73e-e371-4117-9192-e32147dfe98c',
|
|
71
|
+
'Category': 'env-integration',
|
|
72
|
+
'Type': 'aws',
|
|
73
|
+
'Format': ['token'],
|
|
74
|
+
'Resolution': 'by-target',
|
|
75
|
+
'Parameters': {'accountId': '123456789012'},
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
def test_get_rewrites_credential_process_format_to_token(self):
|
|
79
|
+
"""`credential-process` is a client-side format — the broker sees
|
|
80
|
+
'token' and the SDK assembles the AWS credential_process JSON from the
|
|
81
|
+
response."""
|
|
82
|
+
api = MagicMock()
|
|
83
|
+
api.post.return_value = {
|
|
84
|
+
'credentialValue': {
|
|
85
|
+
'accessKeyId': 'ASIA...',
|
|
86
|
+
'secretAccessKey': 'secret',
|
|
87
|
+
'sessionToken': 'session',
|
|
88
|
+
'expiration': '2026-04-10T12:00:00Z',
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
creds = Credentials(api=api)
|
|
92
|
+
|
|
93
|
+
creds.get(
|
|
94
|
+
credential_id='abc-123',
|
|
95
|
+
category='env-integration',
|
|
96
|
+
type='aws',
|
|
97
|
+
format=['credential-process'],
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
sent = api.post.call_args.args[1]
|
|
101
|
+
assert sent['Format'] == ['token']
|
|
102
|
+
assert sent['Resolution'] == 'by-target'
|
|
103
|
+
|
|
104
|
+
def test_get_with_from_parent_sends_resource_key(self):
|
|
105
|
+
"""from-parent: broker walks DISCOVERED ancestors of ResourceKey for a
|
|
106
|
+
matching credential. ResourceKey is required, CredentialID may be
|
|
107
|
+
empty."""
|
|
108
|
+
api = MagicMock()
|
|
109
|
+
api.post.return_value = {'ok': True}
|
|
110
|
+
creds = Credentials(api=api)
|
|
111
|
+
|
|
112
|
+
creds.get(
|
|
113
|
+
credential_id='',
|
|
114
|
+
category='env-integration',
|
|
115
|
+
type='aws',
|
|
116
|
+
format=['token'],
|
|
117
|
+
resolution='from-parent',
|
|
118
|
+
resource_key='#asset#example.com#1.2.3.4',
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
api.post.assert_called_once_with('broker', {
|
|
122
|
+
'Operation': 'get',
|
|
123
|
+
'CredentialID': '',
|
|
124
|
+
'Category': 'env-integration',
|
|
125
|
+
'Type': 'aws',
|
|
126
|
+
'Format': ['token'],
|
|
127
|
+
'Resolution': 'from-parent',
|
|
128
|
+
'Parameters': {},
|
|
129
|
+
'ResourceKey': '#asset#example.com#1.2.3.4',
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
|
|
49
133
|
class TestCredentialsDelete:
|
|
50
134
|
def test_delete_builds_broker_request(self):
|
|
51
135
|
api = MagicMock()
|
|
@@ -105,6 +189,8 @@ def fake_sdk():
|
|
|
105
189
|
sdk = MagicMock()
|
|
106
190
|
sdk.credentials.add.return_value = {'ok': True}
|
|
107
191
|
sdk.credentials.delete.return_value = {'ok': True}
|
|
192
|
+
sdk.credentials.get.return_value = {'credentialValue': {'token': 'abc'}}
|
|
193
|
+
sdk.credentials.format_output.side_effect = lambda r: str(r)
|
|
108
194
|
sdk.assets.update.return_value = {'ok': True}
|
|
109
195
|
return sdk
|
|
110
196
|
|
|
@@ -251,6 +337,76 @@ class TestDeleteCredential:
|
|
|
251
337
|
)
|
|
252
338
|
|
|
253
339
|
|
|
340
|
+
class TestGetCredentialCLI:
|
|
341
|
+
"""`guard get credential ...` — verifies the --resolution flag and its
|
|
342
|
+
interaction with CREDENTIAL_ID / --resource-key."""
|
|
343
|
+
|
|
344
|
+
def test_default_resolution_is_by_target(self, runner, fake_sdk):
|
|
345
|
+
result = _invoke(runner, fake_sdk, [
|
|
346
|
+
'get', 'credential', 'cred-abc-123',
|
|
347
|
+
'--category', 'env-integration',
|
|
348
|
+
'--type', 'aws',
|
|
349
|
+
])
|
|
350
|
+
assert result.exit_code == 0, result.output
|
|
351
|
+
fake_sdk.credentials.get.assert_called_once_with(
|
|
352
|
+
'cred-abc-123', 'env-integration', 'aws', ['token'],
|
|
353
|
+
resolution='by-target', resource_key=None,
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
def test_explicit_by_target_passes_through(self, runner, fake_sdk):
|
|
357
|
+
result = _invoke(runner, fake_sdk, [
|
|
358
|
+
'get', 'credential', 'cred-abc-123',
|
|
359
|
+
'--resolution', 'by-target',
|
|
360
|
+
'--type', 'aws',
|
|
361
|
+
])
|
|
362
|
+
assert result.exit_code == 0, result.output
|
|
363
|
+
kwargs = fake_sdk.credentials.get.call_args.kwargs
|
|
364
|
+
assert kwargs['resolution'] == 'by-target'
|
|
365
|
+
assert kwargs['resource_key'] is None
|
|
366
|
+
|
|
367
|
+
def test_from_parent_requires_resource_key(self, runner, fake_sdk):
|
|
368
|
+
result = _invoke(runner, fake_sdk, [
|
|
369
|
+
'get', 'credential',
|
|
370
|
+
'--resolution', 'from-parent',
|
|
371
|
+
'--type', 'aws',
|
|
372
|
+
])
|
|
373
|
+
assert result.exit_code != 0
|
|
374
|
+
assert '--resource-key' in result.output
|
|
375
|
+
fake_sdk.credentials.get.assert_not_called()
|
|
376
|
+
|
|
377
|
+
def test_from_parent_with_resource_key(self, runner, fake_sdk):
|
|
378
|
+
result = _invoke(runner, fake_sdk, [
|
|
379
|
+
'get', 'credential',
|
|
380
|
+
'--resolution', 'from-parent',
|
|
381
|
+
'--resource-key', '#asset#example.com#1.2.3.4',
|
|
382
|
+
'--type', 'aws',
|
|
383
|
+
])
|
|
384
|
+
assert result.exit_code == 0, result.output
|
|
385
|
+
fake_sdk.credentials.get.assert_called_once_with(
|
|
386
|
+
'', 'env-integration', 'aws', ['token'],
|
|
387
|
+
resolution='from-parent',
|
|
388
|
+
resource_key='#asset#example.com#1.2.3.4',
|
|
389
|
+
)
|
|
390
|
+
|
|
391
|
+
def test_by_target_requires_credential_id(self, runner, fake_sdk):
|
|
392
|
+
result = _invoke(runner, fake_sdk, [
|
|
393
|
+
'get', 'credential',
|
|
394
|
+
'--resolution', 'by-target',
|
|
395
|
+
'--type', 'aws',
|
|
396
|
+
])
|
|
397
|
+
assert result.exit_code != 0
|
|
398
|
+
assert 'CREDENTIAL_ID' in result.output
|
|
399
|
+
fake_sdk.credentials.get.assert_not_called()
|
|
400
|
+
|
|
401
|
+
def test_invalid_resolution_value_is_rejected(self, runner, fake_sdk):
|
|
402
|
+
result = _invoke(runner, fake_sdk, [
|
|
403
|
+
'get', 'credential', 'cred-abc-123',
|
|
404
|
+
'--resolution', 'nope',
|
|
405
|
+
])
|
|
406
|
+
assert result.exit_code != 0
|
|
407
|
+
assert 'nope' in result.output or "'by-target'" in result.output
|
|
408
|
+
|
|
409
|
+
|
|
254
410
|
class TestUpdateAssetSecret:
|
|
255
411
|
def test_update_asset_with_secret_passes_through(self, runner, fake_sdk):
|
|
256
412
|
result = _invoke(runner, fake_sdk, [
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/scripts/commands/nmap-example.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/entities/account_discovery.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
|
|
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
|
|
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
|
|
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
|
|
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
|
{praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/sdk/test/test_credential_process.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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
{praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/aegis/commands/job_helpers.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/aegis/commands/schedule_helpers.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
|
{praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/console/commands/__init__.py
RENAMED
|
File without changes
|
{praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/console/commands/accounts.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/console/commands/reporting.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{praetorian_cli-2.4.3 → praetorian_cli-2.4.4}/praetorian_cli/ui/conversation/textual_chat.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|