bt-cli 0.4.19__tar.gz → 0.4.21__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.
- {bt_cli-0.4.19 → bt_cli-0.4.21}/.claude/skills/entitle/SKILL.md +34 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/.github/workflows/release.yml +3 -0
- {bt_cli-0.4.19/src/bt_cli/data → bt_cli-0.4.21}/CLAUDE.md +7 -1
- {bt_cli-0.4.19 → bt_cli-0.4.21}/PKG-INFO +2 -2
- {bt_cli-0.4.19 → bt_cli-0.4.21}/pyproject.toml +2 -2
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/__init__.py +1 -1
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/cli.py +14 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/data/skills/entitle/SKILL.md +34 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/entitle/client/base.py +3 -3
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/entitle/commands/users.py +7 -3
- {bt_cli-0.4.19 → bt_cli-0.4.21}/.claude/skills/bt/SKILL.md +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/.claude/skills/epmw/SKILL.md +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/.claude/skills/pra/SKILL.md +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/.claude/skills/pws/SKILL.md +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/.env.example +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/.github/workflows/ci.yml +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/.gitignore +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/README.md +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/assets/cli-help.png +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/assets/cli-output.png +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/bt-cli.spec +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/bt_entry.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/scripts/bt_entry.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/scripts/sync-package-data.sh +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/commands/__init__.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/commands/configure.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/commands/learn.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/commands/quick.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/core/__init__.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/core/auth.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/core/client.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/core/config.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/core/config_file.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/core/csv_utils.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/core/errors.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/core/output.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/core/prompts.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/core/rest_debug.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21/src/bt_cli/data}/CLAUDE.md +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/data/__init__.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/data/skills/bt/SKILL.md +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/data/skills/epmw/SKILL.md +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/data/skills/pra/SKILL.md +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/data/skills/pws/SKILL.md +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/entitle/__init__.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/entitle/client/__init__.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/entitle/commands/__init__.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/entitle/commands/accounts.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/entitle/commands/applications.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/entitle/commands/auth.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/entitle/commands/bundles.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/entitle/commands/integrations.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/entitle/commands/permissions.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/entitle/commands/policies.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/entitle/commands/resources.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/entitle/commands/roles.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/entitle/commands/workflows.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/entitle/models/__init__.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/entitle/models/bundle.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/entitle/models/common.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/entitle/models/integration.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/entitle/models/permission.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/entitle/models/policy.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/entitle/models/resource.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/entitle/models/role.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/entitle/models/user.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/entitle/models/workflow.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/epmw/__init__.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/epmw/client/__init__.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/epmw/client/base.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/epmw/commands/__init__.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/epmw/commands/audits.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/epmw/commands/auth.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/epmw/commands/computers.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/epmw/commands/events.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/epmw/commands/groups.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/epmw/commands/policies.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/epmw/commands/quick.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/epmw/commands/requests.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/epmw/commands/roles.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/epmw/commands/tasks.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/epmw/commands/users.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/epmw/models/__init__.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pra/__init__.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pra/client/__init__.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pra/client/base.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pra/commands/__init__.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pra/commands/auth.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pra/commands/import_export.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pra/commands/jump_clients.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pra/commands/jump_groups.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pra/commands/jump_items.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pra/commands/jumpoints.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pra/commands/policies.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pra/commands/quick.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pra/commands/teams.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pra/commands/users.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pra/commands/vault.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pra/models/__init__.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pra/models/common.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pra/models/jump_client.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pra/models/jump_group.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pra/models/jump_item.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pra/models/jumpoint.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pra/models/team.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pra/models/user.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pra/models/vault.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pws/__init__.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pws/client/__init__.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pws/client/base.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pws/client/beyondinsight.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pws/client/passwordsafe.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pws/commands/__init__.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pws/commands/accounts.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pws/commands/assets.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pws/commands/auth.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pws/commands/clouds.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pws/commands/config.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pws/commands/credentials.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pws/commands/databases.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pws/commands/directories.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pws/commands/functional.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pws/commands/import_export.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pws/commands/platforms.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pws/commands/quick.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pws/commands/search.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pws/commands/secrets.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pws/commands/systems.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pws/commands/users.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pws/commands/workgroups.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pws/config.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pws/models/__init__.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pws/models/account.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pws/models/asset.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pws/models/common.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/src/bt_cli/pws/models/system.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/__init__.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/conftest.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/core/__init__.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/core/test_auth.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/core/test_config.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/core/test_errors.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/core/test_rest_debug.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/entitle/__init__.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/entitle/test_client.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/entitle/test_commands.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/entitle-smoke-test.sh +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/epmw/__init__.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/epmw/test_client.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/epmw/test_commands.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/epmw-quick-test-plan.md +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/fixtures/__init__.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/fixtures/responses.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/integration/__init__.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/integration/conftest.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/integration/helpers.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/integration/test_entitle_integration.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/integration/test_epmw_integration.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/integration/test_epmw_lifecycle.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/integration/test_pra_integration.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/integration/test_pra_lifecycle.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/integration/test_pws_integration.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/integration/test_pws_lifecycle.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/pra/__init__.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/pra/test_client.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/pra/test_commands.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/pra-smoke-test.sh +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/pra-test-plan.md +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/pws/__init__.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/pws/test_client.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/pws/test_commands.py +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/pws-quick-test-plan.md +0 -0
- {bt_cli-0.4.19 → bt_cli-0.4.21}/tests/pws-smoke-test.sh +0 -0
|
@@ -14,6 +14,40 @@ description: Entitle commands for JIT access, bundles, workflows, and permission
|
|
|
14
14
|
|
|
15
15
|
List affected resources first, then ask for explicit confirmation.
|
|
16
16
|
|
|
17
|
+
## Performance Tips
|
|
18
|
+
|
|
19
|
+
**ALWAYS use server-side filters** - never download all data and filter locally.
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# ✓ FAST - Server-side filtering
|
|
23
|
+
bt entitle permissions list --resource <resource_id>
|
|
24
|
+
bt entitle permissions list --user <user_id>
|
|
25
|
+
bt entitle permissions list --integration <integration_id>
|
|
26
|
+
|
|
27
|
+
# ✗ SLOW - Downloads ALL 23k+ permissions, filters locally
|
|
28
|
+
bt entitle permissions list | jq 'select(...)'
|
|
29
|
+
bt entitle permissions list -o json | grep "something"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Available filters for permissions list:**
|
|
33
|
+
|
|
34
|
+
| Flag | Purpose |
|
|
35
|
+
|------|---------|
|
|
36
|
+
| `--resource -r` | Filter by resource ID |
|
|
37
|
+
| `--user -u` | Filter by user ID |
|
|
38
|
+
| `--integration -i` | Filter by integration ID |
|
|
39
|
+
|
|
40
|
+
**Dataset size warning:** Entitle can have 20,000+ permissions. Unfiltered queries will be very slow.
|
|
41
|
+
|
|
42
|
+
**Workflow - Check standing access for a resource:**
|
|
43
|
+
```bash
|
|
44
|
+
# 1. Find resource ID
|
|
45
|
+
bt entitle resources list --integration <integration_id> | grep -i "admin"
|
|
46
|
+
|
|
47
|
+
# 2. Query permissions with resource filter (fast)
|
|
48
|
+
bt entitle permissions list --resource <resource_id> -o json | jq -r '.[] | "\(.actor.name) | \(.actor.email)"'
|
|
49
|
+
```
|
|
50
|
+
|
|
17
51
|
## Integrations & Resources
|
|
18
52
|
|
|
19
53
|
```bash
|
|
@@ -236,6 +236,9 @@ jobs:
|
|
|
236
236
|
(github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')) ||
|
|
237
237
|
(github.event_name == 'workflow_dispatch' && inputs.skip_pypi == false)
|
|
238
238
|
|
|
239
|
+
permissions:
|
|
240
|
+
id-token: write # Required for trusted publishing to PyPI
|
|
241
|
+
|
|
239
242
|
environment:
|
|
240
243
|
name: pypi
|
|
241
244
|
url: https://pypi.org/project/bt-cli/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# BT-CLI
|
|
2
2
|
|
|
3
|
-
BeyondTrust Platform CLI for Password Safe, Entitle, PRA, and EPM Windows.
|
|
3
|
+
BeyondTrust Platform CLI for Password Safe, Entitle, PRA, and EPM Windows. **Version: 0.4.21**
|
|
4
4
|
|
|
5
5
|
## Setup
|
|
6
6
|
|
|
@@ -35,6 +35,9 @@ Use these slash commands for detailed product guidance:
|
|
|
35
35
|
## Common Patterns
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
|
+
# Version info
|
|
39
|
+
bt version # or bt --version or bt -V
|
|
40
|
+
|
|
38
41
|
# All list commands support JSON output
|
|
39
42
|
bt pws systems list -o json
|
|
40
43
|
bt pra jump-items shell list -o json
|
|
@@ -61,6 +64,9 @@ PASSWORD=$(bt pws quick checkout -s server -a admin --raw)
|
|
|
61
64
|
- PRA K8s tunnels: Require Linux jumpoint
|
|
62
65
|
- PWS assets: Must create via workgroup endpoint
|
|
63
66
|
- ECM integration: PWS system name must match PRA jump item name
|
|
67
|
+
- Entitle permissions: Use server-side filters (`--resource`, `--user`, `--integration`) - dataset can be 20k+ records
|
|
68
|
+
- Entitle users: Use `--all` flag only when needed - default fetches first page only
|
|
69
|
+
- Windows builds: Rich must be pinned to `<14.0.0` (Rich 14 has PyInstaller unicode issues)
|
|
64
70
|
|
|
65
71
|
## Functional vs Managed Accounts
|
|
66
72
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bt-cli
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.21
|
|
4
4
|
Summary: BeyondTrust Platform CLI (unofficial) - Password Safe, Entitle, PRA, EPM
|
|
5
5
|
Author-email: Dave Grendysz <dgrendysz@beyondtrust.com>
|
|
6
6
|
License: MIT
|
|
@@ -23,7 +23,7 @@ Requires-Dist: httpx>=0.27.0
|
|
|
23
23
|
Requires-Dist: pydantic>=2.0.0
|
|
24
24
|
Requires-Dist: python-dotenv>=1.0.0
|
|
25
25
|
Requires-Dist: pyyaml>=6.0.0
|
|
26
|
-
Requires-Dist: rich<
|
|
26
|
+
Requires-Dist: rich<14.0.0,>=13.7.0
|
|
27
27
|
Requires-Dist: shellingham>=1.5.0
|
|
28
28
|
Requires-Dist: truststore>=0.8.0; python_version >= '3.10'
|
|
29
29
|
Requires-Dist: typer<1.0.0,>=0.12.0
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "bt-cli"
|
|
7
|
-
version = "0.4.
|
|
7
|
+
version = "0.4.21"
|
|
8
8
|
description = "BeyondTrust Platform CLI (unofficial) - Password Safe, Entitle, PRA, EPM"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -39,7 +39,7 @@ dependencies = [
|
|
|
39
39
|
"typer>=0.12.0,<1.0.0",
|
|
40
40
|
"httpx>=0.27.0",
|
|
41
41
|
"pydantic>=2.0.0",
|
|
42
|
-
"rich>=13.7.0,<
|
|
42
|
+
"rich>=13.7.0,<14.0.0", # Pin to 13.x - Rich 14 has PyInstaller issues
|
|
43
43
|
"python-dotenv>=1.0.0",
|
|
44
44
|
"pyyaml>=6.0.0",
|
|
45
45
|
"shellingham>=1.5.0",
|
|
@@ -139,6 +139,13 @@ except Exception:
|
|
|
139
139
|
pass # Quick module not ready yet
|
|
140
140
|
|
|
141
141
|
|
|
142
|
+
def _version_callback(value: bool) -> None:
|
|
143
|
+
"""Print version and exit."""
|
|
144
|
+
if value:
|
|
145
|
+
print(f"bt-cli version {__version__}")
|
|
146
|
+
raise typer.Exit()
|
|
147
|
+
|
|
148
|
+
|
|
142
149
|
@app.callback()
|
|
143
150
|
def main_callback(
|
|
144
151
|
profile: Optional[str] = typer.Option(
|
|
@@ -153,6 +160,13 @@ def main_callback(
|
|
|
153
160
|
help="Show REST API calls (method, URL, headers, body)",
|
|
154
161
|
envvar="BT_SHOW_REST",
|
|
155
162
|
),
|
|
163
|
+
version: bool = typer.Option(
|
|
164
|
+
False,
|
|
165
|
+
"--version", "-V",
|
|
166
|
+
help="Show version and exit",
|
|
167
|
+
callback=_version_callback,
|
|
168
|
+
is_eager=True,
|
|
169
|
+
),
|
|
156
170
|
) -> None:
|
|
157
171
|
"""BeyondTrust Platform CLI.
|
|
158
172
|
|
|
@@ -14,6 +14,40 @@ description: Entitle commands for JIT access, bundles, workflows, and permission
|
|
|
14
14
|
|
|
15
15
|
List affected resources first, then ask for explicit confirmation.
|
|
16
16
|
|
|
17
|
+
## Performance Tips
|
|
18
|
+
|
|
19
|
+
**ALWAYS use server-side filters** - never download all data and filter locally.
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# ✓ FAST - Server-side filtering
|
|
23
|
+
bt entitle permissions list --resource <resource_id>
|
|
24
|
+
bt entitle permissions list --user <user_id>
|
|
25
|
+
bt entitle permissions list --integration <integration_id>
|
|
26
|
+
|
|
27
|
+
# ✗ SLOW - Downloads ALL 23k+ permissions, filters locally
|
|
28
|
+
bt entitle permissions list | jq 'select(...)'
|
|
29
|
+
bt entitle permissions list -o json | grep "something"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Available filters for permissions list:**
|
|
33
|
+
|
|
34
|
+
| Flag | Purpose |
|
|
35
|
+
|------|---------|
|
|
36
|
+
| `--resource -r` | Filter by resource ID |
|
|
37
|
+
| `--user -u` | Filter by user ID |
|
|
38
|
+
| `--integration -i` | Filter by integration ID |
|
|
39
|
+
|
|
40
|
+
**Dataset size warning:** Entitle can have 20,000+ permissions. Unfiltered queries will be very slow.
|
|
41
|
+
|
|
42
|
+
**Workflow - Check standing access for a resource:**
|
|
43
|
+
```bash
|
|
44
|
+
# 1. Find resource ID
|
|
45
|
+
bt entitle resources list --integration <integration_id> | grep -i "admin"
|
|
46
|
+
|
|
47
|
+
# 2. Query permissions with resource filter (fast)
|
|
48
|
+
bt entitle permissions list --resource <resource_id> -o json | jq -r '.[] | "\(.actor.name) | \(.actor.email)"'
|
|
49
|
+
```
|
|
50
|
+
|
|
17
51
|
## Integrations & Resources
|
|
18
52
|
|
|
19
53
|
```bash
|
|
@@ -351,10 +351,10 @@ class EntitleClient:
|
|
|
351
351
|
# =========================================================================
|
|
352
352
|
|
|
353
353
|
def list_users(
|
|
354
|
-
self, search: Optional[str] = None, limit: int = 100
|
|
354
|
+
self, search: Optional[str] = None, limit: int = 100, max_pages: Optional[int] = None
|
|
355
355
|
) -> list[dict[str, Any]]:
|
|
356
|
-
"""List
|
|
357
|
-
return self.paginate("/users", {"search": search}, page_size=limit)
|
|
356
|
+
"""List users with optional pagination limit."""
|
|
357
|
+
return self.paginate("/users", {"search": search}, page_size=limit, max_pages=max_pages)
|
|
358
358
|
|
|
359
359
|
def get_user(self, user_id: str) -> dict[str, Any]:
|
|
360
360
|
"""Get a user by ID."""
|
|
@@ -14,7 +14,8 @@ app = typer.Typer(no_args_is_help=True, help="Manage users")
|
|
|
14
14
|
@app.command("list")
|
|
15
15
|
def list_users(
|
|
16
16
|
search: Optional[str] = typer.Option(None, "--search", "-s", help="Search by email or name"),
|
|
17
|
-
limit: int = typer.Option(
|
|
17
|
+
limit: int = typer.Option(50, "--limit", "-l", help="Results per page"),
|
|
18
|
+
fetch_all: bool = typer.Option(False, "--all", help="Fetch all results (may be slow for large datasets)"),
|
|
18
19
|
output: str = typer.Option("table", "--output", "-o", help="Output format: table, json"),
|
|
19
20
|
) -> None:
|
|
20
21
|
"""List users in Entitle.
|
|
@@ -22,11 +23,14 @@ def list_users(
|
|
|
22
23
|
Examples:
|
|
23
24
|
bt entitle users list
|
|
24
25
|
bt entitle users list -s "john"
|
|
25
|
-
bt entitle users list -l
|
|
26
|
+
bt entitle users list -l 100 --all
|
|
27
|
+
bt entitle users list -o json
|
|
26
28
|
"""
|
|
27
29
|
try:
|
|
28
30
|
with get_client() as client:
|
|
29
|
-
|
|
31
|
+
# Only fetch first page by default, use --all for everything
|
|
32
|
+
max_pages = None if fetch_all else 1
|
|
33
|
+
data = client.list_users(search=search, limit=limit, max_pages=max_pages)
|
|
30
34
|
|
|
31
35
|
if output == "json":
|
|
32
36
|
print_json(data)
|
|
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
|
|
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
|
|
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
|
|
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
|