bt-cli 0.5.0__tar.gz → 0.6.0__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.6.0/.claude/skills/pf/SKILL.md +281 -0
- bt_cli-0.6.0/.claude/skills/secrets/SKILL.md +19 -0
- bt_cli-0.6.0/.claude/skills/wlc/SKILL.md +452 -0
- {bt_cli-0.5.0/src/bt_cli/data → bt_cli-0.6.0}/CLAUDE.md +16 -11
- {bt_cli-0.5.0 → bt_cli-0.6.0}/PKG-INFO +59 -18
- {bt_cli-0.5.0 → bt_cli-0.6.0}/README.md +58 -17
- {bt_cli-0.5.0 → bt_cli-0.6.0}/bt-cli-cheatsheet.html +44 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/pyproject.toml +1 -1
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/__init__.py +1 -1
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/cli.py +30 -19
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/commands/configure.py +6 -6
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/core/config.py +68 -30
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/core/config_file.py +36 -4
- {bt_cli-0.5.0 → bt_cli-0.6.0/src/bt_cli/data}/CLAUDE.md +16 -11
- bt_cli-0.6.0/src/bt_cli/data/skills/pf/SKILL.md +281 -0
- bt_cli-0.6.0/src/bt_cli/data/skills/secrets/SKILL.md +19 -0
- bt_cli-0.6.0/src/bt_cli/data/skills/wlc/SKILL.md +452 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pf/client/base.py +126 -16
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pf/commands/__init__.py +6 -1
- bt_cli-0.6.0/src/bt_cli/pf/commands/_common.py +77 -0
- bt_cli-0.6.0/src/bt_cli/pf/commands/policies.py +568 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pf/commands/users.py +25 -62
- bt_cli-0.6.0/src/bt_cli/pf/commands/workload_identities.py +259 -0
- bt_cli-0.6.0/src/bt_cli/pf/validation.py +104 -0
- bt_cli-0.6.0/src/bt_cli/wlc/__init__.py +1 -0
- bt_cli-0.6.0/src/bt_cli/wlc/client/__init__.py +5 -0
- {bt_cli-0.5.0/src/bt_cli/secrets → bt_cli-0.6.0/src/bt_cli/wlc}/client/base.py +54 -21
- bt_cli-0.6.0/src/bt_cli/wlc/commands/__init__.py +37 -0
- {bt_cli-0.5.0/src/bt_cli/secrets → bt_cli-0.6.0/src/bt_cli/wlc}/commands/_hints.py +1 -1
- bt_cli-0.6.0/src/bt_cli/wlc/commands/access.py +216 -0
- bt_cli-0.6.0/src/bt_cli/wlc/commands/auth.py +84 -0
- {bt_cli-0.5.0/src/bt_cli/secrets → bt_cli-0.6.0/src/bt_cli/wlc}/commands/dynamic.py +17 -17
- {bt_cli-0.5.0/src/bt_cli/secrets → bt_cli-0.6.0/src/bt_cli/wlc}/commands/folders.py +7 -7
- {bt_cli-0.5.0/src/bt_cli/secrets → bt_cli-0.6.0/src/bt_cli/wlc}/commands/integrations.py +6 -6
- {bt_cli-0.5.0/src/bt_cli/secrets → bt_cli-0.6.0/src/bt_cli/wlc}/commands/leases.py +5 -5
- {bt_cli-0.5.0/src/bt_cli/secrets → bt_cli-0.6.0/src/bt_cli/wlc}/commands/static.py +8 -8
- bt_cli-0.6.0/src/bt_cli/wlc/commands/tree.py +102 -0
- bt_cli-0.6.0/src/bt_cli/wlc/models/__init__.py +1 -0
- bt_cli-0.6.0/src/bt_cli/wlc/policy.py +654 -0
- bt_cli-0.6.0/src/bt_cli/wlc/snapshot.py +40 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/core/test_command_tree.py +1 -0
- bt_cli-0.6.0/tests/pf/conftest.py +21 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/pf/test_client.py +61 -2
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/pf/test_commands.py +40 -0
- bt_cli-0.6.0/tests/pf/test_policies.py +485 -0
- bt_cli-0.6.0/tests/pf/test_workload_identities.py +244 -0
- bt_cli-0.6.0/tests/wlc/conftest.py +21 -0
- {bt_cli-0.5.0/tests/secrets → bt_cli-0.6.0/tests/wlc}/test_client.py +9 -7
- {bt_cli-0.5.0/tests/secrets → bt_cli-0.6.0/tests/wlc}/test_commands.py +27 -14
- bt_cli-0.6.0/tests/wlc/test_policy.py +366 -0
- bt_cli-0.6.0/tests/wlc/test_rename.py +170 -0
- bt_cli-0.6.0/tests/wlc/test_tree_access.py +244 -0
- bt_cli-0.5.0/.claude/skills/pf/SKILL.md +0 -116
- bt_cli-0.5.0/.claude/skills/secrets/SKILL.md +0 -229
- bt_cli-0.5.0/src/bt_cli/data/skills/pf/SKILL.md +0 -116
- bt_cli-0.5.0/src/bt_cli/data/skills/secrets/SKILL.md +0 -229
- bt_cli-0.5.0/src/bt_cli/secrets/__init__.py +0 -1
- bt_cli-0.5.0/src/bt_cli/secrets/client/__init__.py +0 -5
- bt_cli-0.5.0/src/bt_cli/secrets/commands/__init__.py +0 -23
- bt_cli-0.5.0/src/bt_cli/secrets/commands/auth.py +0 -67
- bt_cli-0.5.0/src/bt_cli/secrets/models/__init__.py +0 -1
- {bt_cli-0.5.0 → bt_cli-0.6.0}/.claude/skills/bt/SKILL.md +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/.claude/skills/entitle/SKILL.md +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/.claude/skills/epml/SKILL.md +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/.claude/skills/epmw/SKILL.md +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/.claude/skills/pra/SKILL.md +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/.claude/skills/pws/SKILL.md +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/.claude/skills/session-analysis/SKILL.md +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/.env.example +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/.github/workflows/ci.yml +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/.github/workflows/release.yml +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/.gitignore +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/assets/cli-help.png +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/assets/cli-output.png +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/bt-cli.spec +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/bt_entry.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/entitle-gaps-implementation-plan.md +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/epml-clients-server-side-filters-plan.md +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/epml-implementation-plan.md +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/pf-implementation-plan.md +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/scripts/bt_entry.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/scripts/pf_onboard.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/scripts/sync-package-data.sh +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/commands/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/commands/learn.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/commands/quick.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/core/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/core/auth.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/core/client.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/core/command_tree.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/core/csv_utils.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/core/errors.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/core/output.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/core/prompts.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/core/rest_debug.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/data/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/data/skills/bt/SKILL.md +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/data/skills/entitle/SKILL.md +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/data/skills/epml/SKILL.md +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/data/skills/epmw/SKILL.md +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/data/skills/pra/SKILL.md +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/data/skills/pws/SKILL.md +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/data/skills/session-analysis/SKILL.md +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/client/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/client/base.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/commands/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/commands/_helpers.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/commands/accounts.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/commands/agent_tokens.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/commands/applications.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/commands/audit.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/commands/auth.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/commands/bundles.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/commands/chats.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/commands/directory_groups.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/commands/forwards.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/commands/integrations.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/commands/jit.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/commands/permissions.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/commands/policies.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/commands/requests.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/commands/resources.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/commands/roles.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/commands/tasks.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/commands/user_accounts.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/commands/users.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/commands/webhooks.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/commands/workflow_webhook_writes.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/commands/workflows.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/models/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/models/bundle.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/models/common.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/models/integration.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/models/permission.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/models/policy.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/models/resource.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/models/role.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/models/user.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/entitle/models/workflow.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epml/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epml/client/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epml/client/base.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epml/commands/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epml/commands/audit.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epml/commands/auth.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epml/commands/client_pkg.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epml/commands/clients.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epml/commands/external_apis.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epml/commands/hosts.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epml/commands/iolog.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epml/commands/license.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epml/commands/quick.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epml/commands/rbp_cmdgrps.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epml/commands/rbp_entitlement.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epml/commands/rbp_hostgrps.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epml/commands/rbp_policy.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epml/commands/rbp_roles.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epml/commands/rbp_tests.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epml/commands/rbp_tmdategrps.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epml/commands/rbp_tx.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epml/commands/rbp_usergrps.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epml/commands/settings.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epml/commands/siems.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epml/commands/users.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epml/models/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epmw/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epmw/client/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epmw/client/base.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epmw/commands/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epmw/commands/audits.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epmw/commands/auth.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epmw/commands/computers.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epmw/commands/events.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epmw/commands/groups.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epmw/commands/policies.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epmw/commands/quick.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epmw/commands/requests.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epmw/commands/roles.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epmw/commands/tasks.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epmw/commands/users.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/epmw/models/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pf/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pf/client/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pf/commands/auth.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pf/commands/machines.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pf/commands/tokens.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pf/commands/user.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pra/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pra/client/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pra/client/base.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pra/commands/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pra/commands/auth.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pra/commands/group_policies.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pra/commands/import_export.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pra/commands/jump_clients.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pra/commands/jump_groups.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pra/commands/jump_items.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pra/commands/jumpoints.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pra/commands/policies.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pra/commands/quick.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pra/commands/teams.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pra/commands/users.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pra/commands/vault.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pra/models/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pra/models/common.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pra/models/group_policy.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pra/models/jump_client.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pra/models/jump_group.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pra/models/jump_item.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pra/models/jumpoint.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pra/models/team.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pra/models/user.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pra/models/vault.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/client/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/client/base.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/client/beyondinsight.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/client/passwordsafe.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/commands/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/commands/accounts.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/commands/assets.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/commands/attributes.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/commands/audit.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/commands/auth.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/commands/clouds.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/commands/config.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/commands/credentials.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/commands/databases.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/commands/directories.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/commands/functional.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/commands/import_export.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/commands/platforms.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/commands/quick.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/commands/search.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/commands/secrets.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/commands/sessions.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/commands/systems.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/commands/users.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/commands/workgroups.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/config.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/models/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/models/account.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/models/asset.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/models/common.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/src/bt_cli/pws/models/system.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/_runner.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/conftest.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/core/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/core/test_auth.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/core/test_config.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/core/test_config_file.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/core/test_errors.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/core/test_json_stdout_purity.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/core/test_output.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/core/test_package_data_sync.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/core/test_rest_debug.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/data/entitle-api-reference.openapi.json +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/entitle/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/entitle/test_agent_tokens.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/entitle/test_agent_tokens_writes.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/entitle/test_chats.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/entitle/test_client.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/entitle/test_commands.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/entitle/test_coverage.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/entitle/test_directory_groups.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/entitle/test_forwards.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/entitle/test_forwards_writes.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/entitle/test_integrations_writes.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/entitle/test_policies_writes.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/entitle/test_resources_writes.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/entitle/test_roles_writes.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/entitle/test_tasks.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/entitle/test_tasks_writes.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/entitle/test_user_accounts.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/entitle/test_user_accounts_writes.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/entitle/test_webhooks.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/entitle/test_webhooks_writes.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/entitle/test_workflow_webhook_writes.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/entitle/test_workflows_writes.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/entitle-smoke-test.sh +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/epml/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/epml/test_client.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/epml/test_commands.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/epmw/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/epmw/test_client.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/epmw/test_commands.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/epmw-quick-test-plan.md +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/fixtures/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/fixtures/responses.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/integration/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/integration/conftest.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/integration/helpers.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/integration/test_entitle_integration.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/integration/test_epmw_integration.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/integration/test_epmw_lifecycle.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/integration/test_pra_integration.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/integration/test_pra_lifecycle.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/integration/test_pws_integration.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/integration/test_pws_lifecycle.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/pf/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/pra/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/pra/test_client.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/pra/test_commands.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/pra/test_jump_item_fixes.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/pra-smoke-test.sh +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/pra-test-plan.md +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/pws/__init__.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/pws/test_client.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/pws/test_commands.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/pws/test_quick_sessions.py +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/pws-quick-test-plan.md +0 -0
- {bt_cli-0.5.0 → bt_cli-0.6.0}/tests/pws-smoke-test.sh +0 -0
- {bt_cli-0.5.0/tests/secrets → bt_cli-0.6.0/tests/wlc}/__init__.py +0 -0
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pf
|
|
3
|
+
description: Pathfinder platform commands — whoami, site/product access, PAT/MCP token listing, machine registry, user invites and product/site access grants, workload identities (OIDC trust for CI/pods/apps) and Cedar IAM policies that grant access to Workload Credentials. Use when working with the Pathfinder portal API (Nomine), platform PATs, site IDs, user onboarding, machine identities, workload identities, or IAM/RBAC policies.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Pathfinder Platform (`bt pf`)
|
|
7
|
+
|
|
8
|
+
The Pathfinder platform API (internal name: **Nomine**) manages the BeyondTrust
|
|
9
|
+
cloud portal layer: users, sites, product access, tokens, and machine
|
|
10
|
+
identities, plus the auth service's **workload identities** and the **IAM
|
|
11
|
+
policy service** (Cedar RBAC). `bt pf` talks to it through the public API
|
|
12
|
+
gateway with PAT auth — the same pattern as `bt wlc` / `bt epml`.
|
|
13
|
+
|
|
14
|
+
## Configuration
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
export BT_PF_API_URL=https://api.beyondtrust.io # default
|
|
18
|
+
export BT_PF_SITE_ID=<site-uuid> # required — the site the PAT was minted on
|
|
19
|
+
export BT_PF_PAT=PAT_xxx # required (mint at app.beyondtrust.io → Manage Profile)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Site ID discovery: log into app.beyondtrust.io, choose your site, then browse
|
|
23
|
+
to `https://app.beyondtrust.io/api/platform/currentSite`.
|
|
24
|
+
|
|
25
|
+
**For `bt pf policies` and `bt pf wi`, point `pf` at the Administration site**:
|
|
26
|
+
the **org id doubles as the Administration site id**, and the PAT must be
|
|
27
|
+
minted there. The policy commands also need the **WLC site id** for Cedar's
|
|
28
|
+
`@siteId` — taken from the `wlc` config (`BT_WLC_SITE_ID`), overridable with
|
|
29
|
+
`--site`. Two sites, two PATs, because PATs are site-bound.
|
|
30
|
+
|
|
31
|
+
## URL mapping (the thing everyone gets wrong)
|
|
32
|
+
|
|
33
|
+
The Nomine swagger writes paths as `/api/auth/X`. On the gateway the product
|
|
34
|
+
segment is `platform` and the `auth/` prefix stays:
|
|
35
|
+
|
|
36
|
+
spec /api/auth/UserInfo → https://api.beyondtrust.io/site/<site-id>/platform/auth/UserInfo
|
|
37
|
+
|
|
38
|
+
**PATs are site-bound**: minted while a site is active in the portal, valid
|
|
39
|
+
only for that site's `/site/<id>/...` paths. Any other site → `401 Access
|
|
40
|
+
denied for this site`. A just-minted PAT can take ~1s to propagate
|
|
41
|
+
(transient `401 Personal access token not found` — retry once).
|
|
42
|
+
|
|
43
|
+
## Commands
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
bt pf auth test # connectivity + PAT validity
|
|
47
|
+
bt pf whoami # UserInfo for the PAT owner
|
|
48
|
+
bt pf access # site + product access rules (also -o json)
|
|
49
|
+
bt pf pats list # PATs (values masked; --show-tokens to reveal)
|
|
50
|
+
bt pf mcp-tokens list # MCP tokens (same masking)
|
|
51
|
+
bt pf machines list # registered machine IDs
|
|
52
|
+
bt pf machines get <uuid> # one machine's record (secret hash never shown)
|
|
53
|
+
bt pf wi list # workload identities (alias of `bt pf workload-identities`)
|
|
54
|
+
bt pf policies list # Cedar IAM policies (deleted ones hidden; --all shows them)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## User onboarding & access assignment (`bt pf users`)
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# Invite a user to the org (sends a real email; confirms unless --yes).
|
|
61
|
+
# Default site = BT_PF_SITE_ID; -p grants products on that site at invite time.
|
|
62
|
+
bt pf users invite -e new.user@corp.com --first-name New --last-name User \
|
|
63
|
+
-p pra -p epml
|
|
64
|
+
|
|
65
|
+
bt pf users cancel-invite new.user@corp.com # cancel a pending invite
|
|
66
|
+
|
|
67
|
+
# Per-user product access on a site (product slugs are lowercase:
|
|
68
|
+
# epmwm, pra, psc, rs, entitle, epml, insights, secrets)
|
|
69
|
+
bt pf users grant -u <user-uuid> -p epml # default site
|
|
70
|
+
bt pf users revoke -u <user-uuid> -p epml -s <site-uuid>
|
|
71
|
+
|
|
72
|
+
# Site membership (optionally granting products in the same call)
|
|
73
|
+
bt pf users add-to-site -u <user-uuid> -s <site-uuid> -p pra -p psc
|
|
74
|
+
bt pf users remove-from-site -u <user-uuid> -s <site-uuid>
|
|
75
|
+
|
|
76
|
+
bt pf users delete <user-uuid> [...] # bulk delete (org admin; confirms)
|
|
77
|
+
bt pf users list # every page (admin-site PAT with 'admin' scope); --page N for one
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**PAT matters (re-verified 2026-10-21):** the org-admin surface answers only a
|
|
81
|
+
PAT minted on the **Administration site** (`BT_PF_SITE_ID` = the org id) that
|
|
82
|
+
carries the **`admin`** scope. With that PAT, `auth/Users`, `auth/SAMLProviders`,
|
|
83
|
+
`auth/Auditing` and `auth/{productaccess,siteaccess,access}/org` are all **200**.
|
|
84
|
+
A product-site PAT still gets the empty-body 403 on every one of them, and that
|
|
85
|
+
is what every PAT we had on 2026-06-11 got, which is why these commands looked
|
|
86
|
+
permanently blocked. Every Administration-site command (`users`, `policies`, `wi`)
|
|
87
|
+
shares one contract: an empty-body 403 (the wrong kind of PAT) exits **3** with a
|
|
88
|
+
hint naming the fix; a 401, or a 403 with a body, exits 1.
|
|
89
|
+
|
|
90
|
+
Writes work too, with the admin-scoped PAT (2026-10-21):
|
|
91
|
+
- `bt pf users delete` removes the Pathfinder user record only, never the IdP
|
|
92
|
+
(Entra ID etc.) account.
|
|
93
|
+
- `bt pf users invite -s <site> -p <slug>...` → `{inviteId, userId,
|
|
94
|
+
organizationId, email, isFederated}`. The user then lists as `status:
|
|
95
|
+
Invited`, `active: false`, with a **new** user id. A re-invited former SAML
|
|
96
|
+
user came back with `isFederated: false`.
|
|
97
|
+
|
|
98
|
+
- `bt pf users add-to-site` / `remove-from-site` / `grant` / `revoke` all work
|
|
99
|
+
(live round trip on a test user, 2026-10-21, net zero). Order matters:
|
|
100
|
+
- **Site first:** a product grant on a site the user isn't a member of →
|
|
101
|
+
`404 "User does not have site access"`. Run `add-to-site` first.
|
|
102
|
+
- **Revoking a rule that doesn't exist** → `500 "Unable to remove product
|
|
103
|
+
access rule."` (exit 1), not a 404.
|
|
104
|
+
- **Reading access back:** site membership is visible through `users list
|
|
105
|
+
--site-id <site>` (`auth/Users?siteId=`). Product rules aren't:
|
|
106
|
+
`auth/productaccess?userId=` is in the swagger but 404s on the gateway.
|
|
107
|
+
- **A pending invite creates no site rule** until it's accepted, so an invitee
|
|
108
|
+
doesn't show in `users list --site-id` for the invited site.
|
|
109
|
+
- `cancel-invite` removes the invitation, but the user record keeps
|
|
110
|
+
`status: Invited`, so the list can't tell a live invite from a cancelled one.
|
|
111
|
+
Re-inviting the same email **reuses that user id** and sends a fresh email.
|
|
112
|
+
After a full `delete`, the next invite gets a new id.
|
|
113
|
+
- The org's *default* access rules (`auth/{site,product}access/org`) may grant
|
|
114
|
+
products to every user anyway. `invite` sends a
|
|
115
|
+
real email. Note `invite`'s default site is `BT_PF_SITE_ID`, which for these
|
|
116
|
+
commands is the Administration site, so pass `-s <product-site>` to grant
|
|
117
|
+
products on a real site.
|
|
118
|
+
|
|
119
|
+
`users list` pages for you: without paging params the server returns a bare
|
|
120
|
+
array **capped at 200** (no total), and with `page`/`pageSize` it returns
|
|
121
|
+
`{users, totalCount}`. The CLI asks for 1000 per page, walks pages to
|
|
122
|
+
`totalCount`, de-duplicates by id, and warns if it comes up short.
|
|
123
|
+
`--page N` fetches just that page.
|
|
124
|
+
|
|
125
|
+
## Workload identities (`bt pf workload-identities`, alias `bt pf wi`)
|
|
126
|
+
|
|
127
|
+
OIDC issuer trust configs for non-human callers (CI jobs, k8s pods, Azure
|
|
128
|
+
apps). Administration site, admin PAT. An identity is granted **nothing**
|
|
129
|
+
until a policy names it.
|
|
130
|
+
|
|
131
|
+
| Command | Method & path |
|
|
132
|
+
|---|---|
|
|
133
|
+
| `list [--wlc] [--for-site S]` | `GET /site/{admin}/platform/auth/workload-identities` → `{issuers: [...], totalCount}` |
|
|
134
|
+
| `get <id>` | `GET .../workload-identities/{id}` → `{issuer: {...}}` — CLI also lists the live policies naming it |
|
|
135
|
+
| `create` | `POST .../workload-identities` → `{issuer}` |
|
|
136
|
+
| `update <id>` | `PUT .../workload-identities/{id}` — full body, read-modify-write |
|
|
137
|
+
| `delete <id>` | `DELETE .../workload-identities/{id}` (confirms; `--yes`) |
|
|
138
|
+
|
|
139
|
+
Item keys (live): `conditions, description, expectedAud, identityId,
|
|
140
|
+
idpCategory, issuerUrl, organizationId, registeredScopes, scopeLevel,
|
|
141
|
+
serviceName, siteId, sites` (`sites[]` = `{siteId, registeredScopes,
|
|
142
|
+
scopeLevel, expectedAud}`).
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
bt pf wi create -n k8s-wc-reader --issuer-url https://kubernetes.default.svc --idp-category Custom \
|
|
146
|
+
-c sub=system:serviceaccount:demo-app:wc-reader --scope secrets --dry-run
|
|
147
|
+
bt pf wi create -n gh-deploy --issuer-url https://token.actions.githubusercontent.com \
|
|
148
|
+
--idp-category GitHubActions -c "sub=repo:owner/repo:*" -c ref=refs/heads/main
|
|
149
|
+
bt pf wi update <id> --description "new" # -c / --conditions-file REPLACE all conditions
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Rules checked client-side (ported from the Terraform provider):
|
|
153
|
+
`idpCategory` ∈ GitHubActions | AzureEntra | Custom; ≥ 1 registered scope
|
|
154
|
+
(`secrets` = WLC, default; `psc`, `admin` also seen); condition values
|
|
155
|
+
non-empty, ≤ 256 chars, at most one `*` and only at the end; GitHubActions
|
|
156
|
+
keys ∈ {sub, repository, repository_owner, ref, job_workflow_ref,
|
|
157
|
+
workflow_ref, environment, event_name, actor} and `sub` must start
|
|
158
|
+
`repo:<owner>/<repo>`. Only `conditions`, `description`, `scopeLevel`,
|
|
159
|
+
`registeredScopes` are updatable; the service lower-cases `serviceName` and
|
|
160
|
+
`issuerUrl`.
|
|
161
|
+
|
|
162
|
+
## IAM policies (`bt pf policies`) — Cedar RBAC for Workload Credentials
|
|
163
|
+
|
|
164
|
+
| Command | Method & path (admin site) |
|
|
165
|
+
|---|---|
|
|
166
|
+
| `list [--all]` | `GET /site/{admin}/platform/iam/policies` → `{policies: [...]}`; DELETED / PENDING_UNBIND hidden unless `--all` |
|
|
167
|
+
| `get <name>` | `GET .../iam/policies/{name}` |
|
|
168
|
+
| `apply <name> -f p.cedar` / `--stdin` | `PUT .../iam/policies/{name}`, **`Content-Type: text/plain`**, raw Cedar — upsert |
|
|
169
|
+
| `grant ...` | build Cedar from flags, show it, confirm (says REPLACE if the name is live), PUT, wait |
|
|
170
|
+
| `render ...` | same flags, print Cedar (`--curl` for the curl). No write |
|
|
171
|
+
| `validate -f p.cedar` | local checks only |
|
|
172
|
+
| `delete <name>` | `DELETE .../iam/policies/{name}` — soft delete (then listed as DELETED) |
|
|
173
|
+
| `wait <name>` | poll until ACTIVE / WAITING_FOR_RESOURCE (`--timeout`) |
|
|
174
|
+
|
|
175
|
+
Policy object: `name, cedar, status, product, site, createdAt, updatedAt`
|
|
176
|
+
(no id, no description). No pagination (query params ignored, 2026-10-21).
|
|
177
|
+
|
|
178
|
+
Cedar the service accepts — one `permit`, `@siteId` = the site the grant
|
|
179
|
+
applies to (the **WLC** site, not the admin site):
|
|
180
|
+
|
|
181
|
+
```cedar
|
|
182
|
+
@siteId("<wlc-site-uuid>")
|
|
183
|
+
permit(
|
|
184
|
+
principal == Pathfinder::Workload::Id::"<identityId>", // or User::Email / Group / Role
|
|
185
|
+
action in [WorkloadCredentials::Action::"ReadSecret", WorkloadCredentials::Action::"ListFolderContents"],
|
|
186
|
+
resource == WorkloadCredentials::Folder::"/btlab/app/demo" // or Secret / DynamicSecret / Integration, or `resource is WorkloadCredentials::Product`
|
|
187
|
+
);
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Not supported: `forbid`, `when`, `unless`, multiple statements, missing
|
|
191
|
+
`@siteId`. Roles are written as actions (`WorkloadCredentials::Action::"Viewer"`,
|
|
192
|
+
`Pathfinder::Action::"Admin"`). Full action catalog, role expansion and the
|
|
193
|
+
folder cascade are in the `/wlc` skill.
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
# Viewer for k8s-wc-reader on a folder (cascades to everything below)
|
|
197
|
+
bt pf policies grant --name k8s-wc-reader-demo-viewer --workload-name k8s-wc-reader \
|
|
198
|
+
--folder /btlab/app/demo --role-grant Viewer
|
|
199
|
+
# ReadSecret on one secret
|
|
200
|
+
bt pf policies grant --name k8s-db-pass --workload <id> --secret /btlab/app/demo/db-pass \
|
|
201
|
+
--action ReadSecret --action ReadSecretMetadata
|
|
202
|
+
# Revoke
|
|
203
|
+
bt pf policies delete k8s-db-pass
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Gotchas (live-verified 2026-10-20/21):
|
|
207
|
+
- The **docs' path `/platform/iam/policies` is wrong** — it is
|
|
208
|
+
`/site/{admin-site}/platform/iam/policies`.
|
|
209
|
+
- The list **includes soft-deleted** policies — history, never grants.
|
|
210
|
+
- **PUT is an upsert keyed by name** (unique per org). Reusing a name silently
|
|
211
|
+
replaces it; `grant`/`apply` say REPLACE and show the current Cedar. A
|
|
212
|
+
DELETED name is reusable.
|
|
213
|
+
- **A wrong workload id still goes ACTIVE** (the service doesn't validate
|
|
214
|
+
principals) and grants nothing — `grant` warns.
|
|
215
|
+
- **A missing path → WAITING_FOR_RESOURCE**, which binds when it's created.
|
|
216
|
+
- Statuses: `RESOURCE_LOOKUP`, `PENDING_BIND` (settling) → `ACTIVE`;
|
|
217
|
+
`WAITING_FOR_RESOURCE`; `RESOURCE_LOOKUP_ERROR`, `NO_PRODUCT_ACCESS`
|
|
218
|
+
(failed); `PENDING_UNBIND` → `DELETED`.
|
|
219
|
+
- Names: 1-100 chars, letters/digits/`-`/`_`, alnum at both ends (the
|
|
220
|
+
provider's server-mirrored rule — no dots).
|
|
221
|
+
- A non-admin-site PAT on the policy API → `403 forbidden: caller cannot
|
|
222
|
+
perform this action`.
|
|
223
|
+
|
|
224
|
+
## Groups and roles — known gap
|
|
225
|
+
|
|
226
|
+
Policies can name `Pathfinder::Group::"name"` and `Pathfinder::Role::"name"`,
|
|
227
|
+
but **group and role membership is not visible to PAT callers, so access
|
|
228
|
+
through groups can't be resolved.** There is no groups/roles API in the Nomine
|
|
229
|
+
swagger or the Terraform provider, and read-only probes on the Administration
|
|
230
|
+
site (2026-10-21) found none: `platform/auth/{groups,Groups,roles,Roles,UserGroups}`
|
|
231
|
+
and `platform/iam/{groups,Groups,roles}` → 404; `platform/auth/User/Groups` →
|
|
232
|
+
405 (a route exists but not for GET; not probed further). The only membership
|
|
233
|
+
data a PAT sees is the caller's own `groups` in `bt pf whoami`. `bt wlc access`
|
|
234
|
+
reports group/role grants as "membership not resolved", and always notes that
|
|
235
|
+
Admin-console role assignments can make effective access larger than policies show.
|
|
236
|
+
|
|
237
|
+
## What works over PAT vs what doesn't (re-verified 2026-10-21)
|
|
238
|
+
|
|
239
|
+
| Endpoint | Product-site PAT | Administration-site PAT (`admin` scope) |
|
|
240
|
+
|----------|------------------|------------------------------------------|
|
|
241
|
+
| `auth/UserInfo`, `auth/User/Access`, `auth/User/Token`, `auth/User/McpToken` | 200 | 200 |
|
|
242
|
+
| `auth/Users`, `auth/SAMLProviders`, `auth/Auditing` | 403 (empty body) | **200** |
|
|
243
|
+
| `auth/productaccess/org`, `auth/access/org`, `auth/siteaccess/org` | 403 (empty body) | **200** |
|
|
244
|
+
| `auth/workload-identities`, `iam/policies` | 403 | **200** |
|
|
245
|
+
| `auth/Machine`, `auth/Machine/{id}` | **200** | 403 |
|
|
246
|
+
| `auth/productaccess` (collection GET) | 404 (not deployed) | n/a |
|
|
247
|
+
| `auth/Users/delete` | 405 on GET; POST → 403 (2026-06-11) | **POST works** (deleted a test user, 2026-10-21) |
|
|
248
|
+
| `auth/UserInvitation` | 405 on GET; POST → 403 (2026-06-11) | **POST works**: invited a user to a product site with products, 2026-10-21 |
|
|
249
|
+
| `auth/UserInvitation/Cancel` | 405 on GET | **POST works** (2026-10-21); a second cancel → `404 "User invitation not found."` |
|
|
250
|
+
| `auth/UserInvitation/Product` | 405 on GET | 405 on GET; POST not yet tested |
|
|
251
|
+
| `auth/siteaccess/{s}/user/{u}` | 405 on GET | **POST and DELETE work** (2026-10-21) |
|
|
252
|
+
| `auth/productaccess/{p}/site/{s}/user/{u}` | 405 on GET; grant POST → empty-body 403 (2026-06-11) | **POST and DELETE work** (2026-10-21) |
|
|
253
|
+
| `auth/productaccess?userId=` (read a user's product rules, in the swagger) | 404 | 404: not deployed, so a user's product grants can't be read back |
|
|
254
|
+
|
|
255
|
+
PAT `access` scopes are listed in `bt pf pats list`. The Administration-site PAT
|
|
256
|
+
in use on 2026-10-21 carried `admin` plus every product slug. Note that machines
|
|
257
|
+
work the other way round: they need a product-site PAT.
|
|
258
|
+
|
|
259
|
+
## Machines
|
|
260
|
+
|
|
261
|
+
Platform machine identities: non-user principals (machineId + machineSecret)
|
|
262
|
+
used by agents/integrations to authenticate. `POST
|
|
263
|
+
login.beyondtrust.io/bt.identity/Machine/AccessToken {machineId,
|
|
264
|
+
machineSecret}` → 30-min JWT (machineEndpoints.* scopes only). Records carry
|
|
265
|
+
an activation-token lifecycle (created/expiration) and `active` flag —
|
|
266
|
+
an entry with `active: false` and a pending activation token was registered
|
|
267
|
+
but never activated.
|
|
268
|
+
|
|
269
|
+
## Not exposed via PAT (cookie-auth only, app.beyondtrust.io/api/auth/*)
|
|
270
|
+
|
|
271
|
+
User listing, auditing, SAML providers and the org-default access-rule reads
|
|
272
|
+
now work over an Administration-site PAT with the `admin` scope (see above).
|
|
273
|
+
Still cookie-only as far as tested: PAT/MCP token creation and revocation, and
|
|
274
|
+
invitation Accept. These need the `access` session cookie
|
|
275
|
+
(browser JWT ~5min TTL, or the programmatic SignIn → /session/login flow —
|
|
276
|
+
password-auth users only, not federated).
|
|
277
|
+
|
|
278
|
+
Invite body shape (spec `InviteOrganizationUserInput`): `{email, firstName,
|
|
279
|
+
lastName, siteMetaData: [{siteId, name, residency}], productMetaData:
|
|
280
|
+
[{name, siteId, siteName}]}` — `bt pf users invite` builds this, defaulting
|
|
281
|
+
the site to `BT_PF_SITE_ID` and omitting name/residency unless given.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: secrets
|
|
3
|
+
description: Old name for Workload Credentials (WLC). `bt secrets` is a deprecated alias of `bt wlc` — use the /wlc skill.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Secrets API → Workload Credentials (`bt wlc`)
|
|
7
|
+
|
|
8
|
+
BeyondTrust renamed the Secrets API (Secrets Safe) to **Workload Credentials
|
|
9
|
+
(WLC)**. In bt-cli 0.6.0 the commands moved to **`bt wlc`**; `bt secrets` is a
|
|
10
|
+
deprecated alias with the same commands (it prints a one-line notice on
|
|
11
|
+
stderr, so `-o json` output is unchanged).
|
|
12
|
+
|
|
13
|
+
- Commands: `bt wlc folders|static|dynamic|leases|integrations|auth|tree|access`
|
|
14
|
+
- Config: `BT_WLC_*` (falls back to `BT_SECRETS_*`), `wlc` profile section (falls back to `secrets`)
|
|
15
|
+
- URL prefix: `/site/{id}/wlc` (`/site/{id}/secrets` still answers)
|
|
16
|
+
- Access policies & workload identities: `bt pf policies`, `bt pf wi`
|
|
17
|
+
|
|
18
|
+
**Use the `/wlc` skill** — it has everything that used to be here, plus the
|
|
19
|
+
Cedar policy and effective-access material.
|