bt-cli 0.4.38__tar.gz → 0.4.40__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.38 → bt_cli-0.4.40}/.claude/skills/epml/SKILL.md +50 -1
- {bt_cli-0.4.38/src/bt_cli/data → bt_cli-0.4.40}/CLAUDE.md +13 -1
- {bt_cli-0.4.38 → bt_cli-0.4.40}/PKG-INFO +1 -1
- {bt_cli-0.4.38 → bt_cli-0.4.40}/pyproject.toml +1 -1
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/__init__.py +1 -1
- {bt_cli-0.4.38 → bt_cli-0.4.40/src/bt_cli/data}/CLAUDE.md +13 -1
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/data/skills/epml/SKILL.md +50 -1
- {bt_cli-0.4.38/src/bt_cli/data → bt_cli-0.4.40/.claude}/skills/bt/SKILL.md +0 -0
- {bt_cli-0.4.38/src/bt_cli/data → bt_cli-0.4.40/.claude}/skills/entitle/SKILL.md +0 -0
- {bt_cli-0.4.38/src/bt_cli/data → bt_cli-0.4.40/.claude}/skills/epmw/SKILL.md +0 -0
- {bt_cli-0.4.38/src/bt_cli/data → bt_cli-0.4.40/.claude}/skills/pra/SKILL.md +0 -0
- {bt_cli-0.4.38/src/bt_cli/data → bt_cli-0.4.40/.claude}/skills/pws/SKILL.md +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/.env.example +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/.github/workflows/ci.yml +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/.github/workflows/release.yml +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/.gitignore +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/README.md +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/assets/cli-help.png +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/assets/cli-output.png +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/bt-cli.spec +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/bt_entry.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/epml-implementation-plan.md +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/scripts/bt_entry.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/scripts/sync-package-data.sh +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/cli.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/commands/__init__.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/commands/configure.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/commands/learn.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/commands/quick.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/core/__init__.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/core/auth.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/core/client.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/core/config.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/core/config_file.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/core/csv_utils.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/core/errors.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/core/output.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/core/prompts.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/core/rest_debug.py +0 -0
- {bt_cli-0.4.38/tests/pws → bt_cli-0.4.40/src/bt_cli/data}/__init__.py +0 -0
- {bt_cli-0.4.38/.claude → bt_cli-0.4.40/src/bt_cli/data}/skills/bt/SKILL.md +0 -0
- {bt_cli-0.4.38/.claude → bt_cli-0.4.40/src/bt_cli/data}/skills/entitle/SKILL.md +0 -0
- {bt_cli-0.4.38/.claude → bt_cli-0.4.40/src/bt_cli/data}/skills/epmw/SKILL.md +0 -0
- {bt_cli-0.4.38/.claude → bt_cli-0.4.40/src/bt_cli/data}/skills/pra/SKILL.md +0 -0
- {bt_cli-0.4.38/.claude → bt_cli-0.4.40/src/bt_cli/data}/skills/pws/SKILL.md +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/entitle/__init__.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/entitle/client/__init__.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/entitle/client/base.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/entitle/commands/__init__.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/entitle/commands/accounts.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/entitle/commands/applications.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/entitle/commands/auth.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/entitle/commands/bundles.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/entitle/commands/integrations.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/entitle/commands/permissions.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/entitle/commands/policies.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/entitle/commands/resources.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/entitle/commands/roles.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/entitle/commands/users.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/entitle/commands/workflows.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/entitle/models/__init__.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/entitle/models/bundle.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/entitle/models/common.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/entitle/models/integration.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/entitle/models/permission.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/entitle/models/policy.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/entitle/models/resource.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/entitle/models/role.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/entitle/models/user.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/entitle/models/workflow.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epml/__init__.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epml/client/__init__.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epml/client/base.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epml/commands/__init__.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epml/commands/audit.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epml/commands/auth.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epml/commands/client_pkg.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epml/commands/external_apis.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epml/commands/hosts.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epml/commands/iolog.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epml/commands/license.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epml/commands/quick.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epml/commands/rbp_cmdgrps.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epml/commands/rbp_entitlement.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epml/commands/rbp_hostgrps.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epml/commands/rbp_policy.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epml/commands/rbp_roles.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epml/commands/rbp_tests.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epml/commands/rbp_tmdategrps.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epml/commands/rbp_tx.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epml/commands/rbp_usergrps.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epml/commands/settings.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epml/commands/siems.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epml/commands/users.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epml/models/__init__.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epmw/__init__.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epmw/client/__init__.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epmw/client/base.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epmw/commands/__init__.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epmw/commands/audits.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epmw/commands/auth.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epmw/commands/computers.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epmw/commands/events.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epmw/commands/groups.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epmw/commands/policies.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epmw/commands/quick.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epmw/commands/requests.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epmw/commands/roles.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epmw/commands/tasks.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epmw/commands/users.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/epmw/models/__init__.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pra/__init__.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pra/client/__init__.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pra/client/base.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pra/commands/__init__.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pra/commands/auth.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pra/commands/import_export.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pra/commands/jump_clients.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pra/commands/jump_groups.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pra/commands/jump_items.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pra/commands/jumpoints.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pra/commands/policies.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pra/commands/quick.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pra/commands/teams.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pra/commands/users.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pra/commands/vault.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pra/models/__init__.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pra/models/common.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pra/models/jump_client.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pra/models/jump_group.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pra/models/jump_item.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pra/models/jumpoint.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pra/models/team.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pra/models/user.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pra/models/vault.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pws/__init__.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pws/client/__init__.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pws/client/base.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pws/client/beyondinsight.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pws/client/passwordsafe.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pws/commands/__init__.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pws/commands/accounts.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pws/commands/assets.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pws/commands/attributes.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pws/commands/auth.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pws/commands/clouds.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pws/commands/config.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pws/commands/credentials.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pws/commands/databases.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pws/commands/directories.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pws/commands/functional.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pws/commands/import_export.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pws/commands/platforms.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pws/commands/quick.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pws/commands/search.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pws/commands/secrets.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pws/commands/systems.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pws/commands/users.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pws/commands/workgroups.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pws/config.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pws/models/__init__.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pws/models/account.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pws/models/asset.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pws/models/common.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/src/bt_cli/pws/models/system.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/__init__.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/conftest.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/core/__init__.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/core/test_auth.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/core/test_config.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/core/test_errors.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/core/test_rest_debug.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/entitle/__init__.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/entitle/test_client.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/entitle/test_commands.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/entitle-smoke-test.sh +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/epml/__init__.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/epml/test_client.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/epml/test_commands.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/epmw/__init__.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/epmw/test_client.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/epmw/test_commands.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/epmw-quick-test-plan.md +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/fixtures/__init__.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/fixtures/responses.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/integration/__init__.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/integration/conftest.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/integration/helpers.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/integration/test_entitle_integration.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/integration/test_epmw_integration.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/integration/test_epmw_lifecycle.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/integration/test_pra_integration.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/integration/test_pra_lifecycle.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/integration/test_pws_integration.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/integration/test_pws_lifecycle.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/pra/__init__.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/pra/test_client.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/pra/test_commands.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/pra-smoke-test.sh +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/pra-test-plan.md +0 -0
- {bt_cli-0.4.38/src/bt_cli/data → bt_cli-0.4.40/tests/pws}/__init__.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/pws/test_client.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/pws/test_commands.py +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/pws-quick-test-plan.md +0 -0
- {bt_cli-0.4.38 → bt_cli-0.4.40}/tests/pws-smoke-test.sh +0 -0
|
@@ -163,6 +163,54 @@ bt epml rbp policy revert
|
|
|
163
163
|
bt epml rbp policy delete-all --yes-i-mean-it # destructive, gated
|
|
164
164
|
```
|
|
165
165
|
|
|
166
|
+
## Worked example: build a role from scratch
|
|
167
|
+
|
|
168
|
+
End-to-end recipe for a "users in group X can run shells on all hosts at any time" role with I/O logging and a session banner. Mirrors the pattern of the tenant's existing roles (Postgres, Docker Admin, etc.).
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
# 1. Command group containing the commands the role allows
|
|
172
|
+
bt epml rbp cmdgrps create --name "RootShells" --description "Root shells with arguments"
|
|
173
|
+
# captures: id 35
|
|
174
|
+
bt epml rbp cmdgrps commands add 35 --commands "bash *,sh *,ksh *,zsh *,csh *,bash,sh,ksh,zsh,csh"
|
|
175
|
+
|
|
176
|
+
# 2. Role itself, all metadata in one shot
|
|
177
|
+
bt epml rbp roles create \
|
|
178
|
+
--name "RootShells" \
|
|
179
|
+
--description "Root shell access — I/O logged" \
|
|
180
|
+
--comment "Root shell access — I/O logged" \
|
|
181
|
+
--tag "RootAccess" \
|
|
182
|
+
--risk 9 \
|
|
183
|
+
--rpt 1 \
|
|
184
|
+
--action A \
|
|
185
|
+
--iolog '/iologs/%date%/%uniqueid%.iolog' \
|
|
186
|
+
--banner-text "Root Shell Access"
|
|
187
|
+
# captures: id 126
|
|
188
|
+
|
|
189
|
+
# 3. Wire up the four group assignments
|
|
190
|
+
bt epml rbp roles cmdgrps add 126 --ids 35 # cmdgrp: just IDs
|
|
191
|
+
bt epml rbp roles hostgrps add 126 --ids 1 --kind B # All Hosts, both Submit and Run-as
|
|
192
|
+
bt epml rbp roles usergrps add 126 --ids 4 --kind S # Administrators as Submit (who requests)
|
|
193
|
+
bt epml rbp roles usergrps add 126 --ids 3 --kind R # 'root' as Run-as (whose identity)
|
|
194
|
+
bt epml rbp roles tmdategrps add 126 --ids 1 # Any Time
|
|
195
|
+
|
|
196
|
+
# 4. Verify
|
|
197
|
+
bt epml rbp roles list -o json | python3 -c 'import json,sys;[print(json.dumps(r,indent=2)) for r in json.load(sys.stdin) if r["id"]==126]'
|
|
198
|
+
bt epml rbp roles cmdgrps list 126
|
|
199
|
+
bt epml rbp roles hostgrps list 126
|
|
200
|
+
bt epml rbp roles usergrps list 126
|
|
201
|
+
bt epml rbp roles tmdategrps list 126
|
|
202
|
+
bt epml rbp entitlement run -o json | grep RootShells # rpt=1 makes it surface
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
The resulting banner displayed to users (server-substituted at session time):
|
|
206
|
+
```
|
|
207
|
+
############################################################
|
|
208
|
+
Policy: Root Shell Access
|
|
209
|
+
Status: %event%
|
|
210
|
+
Session Recorded: Yes
|
|
211
|
+
############################################################
|
|
212
|
+
```
|
|
213
|
+
|
|
166
214
|
## Test suites + transactions (the killer workflow)
|
|
167
215
|
|
|
168
216
|
```bash
|
|
@@ -211,7 +259,8 @@ bt epml quick tests-then-deploy --suite <suite_id> # commits if pass; rollb
|
|
|
211
259
|
- **Children share the parent's `id`** in GET responses — the listed `id` field is the cmdgrp/hostgrp/usergrp ID, not unique per child. The actual identifier is the `cmd`/`host`/`user` text.
|
|
212
260
|
- **Role assignments take a single object per request, not an array**. The CLI loops under the hood; the wire body is e.g. `{"cmds": 35}`, `{"hosts": 1, "type": "S"}`, `{"users": 4, "type": "R"}`, `{"tmdates": 1}`.
|
|
213
261
|
- **Hostgrp / usergrp assignments require a `type` field** (`S` = Submit / who requests, `R` = Run-as / whose identity the command runs under). Without `type` the request 400s with "RBP role type not in: [S,R]". CLI: `--kind S|R|B` on `roles hostgrps add` and `roles usergrps add`. `B` (default) creates both an S row and an R row for the same id — appropriate when the same group plays both roles. For "Admin requests, runs as root", do `--ids 4 --kind S` and `--ids 3 --kind R` separately.
|
|
214
|
-
- **Roles need `rpt: 1`** to appear in `bt epml rbp entitlement run`. The role still functions for policy evaluation either way, but only `rpt=1` roles are surfaced in the report.
|
|
262
|
+
- **Roles need `rpt: 1`** to appear in `bt epml rbp entitlement run`. The role still functions for policy evaluation either way, but only `rpt=1` roles are surfaced in the report. Set with `--rpt 1` on `roles create` / `roles update` (added in 0.4.38).
|
|
263
|
+
- **Role update is upsert-on-id, not partial**: hitting POST `/roles` with `{id, ...}` *overwrites* the matching record — fields you omit get cleared. The CLI's `roles update` does read-modify-write (fetch the role, merge changes, post the whole record) so this feels partial. Role-child relations (rolecmds/roleusers/etc.) are filtered out of the merge so assignments survive an update. **If you hit the API directly via curl**, you must send the full record yourself.
|
|
215
264
|
|
|
216
265
|
## Known gaps (TODO)
|
|
217
266
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# BT-CLI
|
|
2
2
|
|
|
3
|
-
BeyondTrust Platform CLI for Password Safe, Entitle, PRA, EPM Windows, and EPM Linux. **Version: 0.4.
|
|
3
|
+
BeyondTrust Platform CLI for Password Safe, Entitle, PRA, EPM Windows, and EPM Linux. **Version: 0.4.40**
|
|
4
4
|
|
|
5
5
|
## Setup
|
|
6
6
|
|
|
@@ -10,6 +10,15 @@ source .venv/bin/activate && source .env
|
|
|
10
10
|
bt whoami # Test all connections
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
+
Each product reads its own `BT_<PRODUCT>_*` env vars. EPM Linux is the odd one out — it uses a Personal Access Token (PAT) against the BeyondTrust public API gateway:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
export BT_EPML_API_URL=https://api.beyondtrust.io # default
|
|
17
|
+
export BT_EPML_SITE_ID=<site-uuid> # required
|
|
18
|
+
export BT_EPML_PAT=PAT_xxx # required (mint at app.beyondtrust.io)
|
|
19
|
+
export BT_EPML_DEFAULT_HOST=100 # default PMUL host id (optional)
|
|
20
|
+
```
|
|
21
|
+
|
|
13
22
|
## Skills Available
|
|
14
23
|
|
|
15
24
|
Use these slash commands for detailed product guidance:
|
|
@@ -72,6 +81,9 @@ PASSWORD=$(bt pws quick checkout -s server -a admin --raw)
|
|
|
72
81
|
- Windows builds: Rich must be pinned to `<14.0.0` (Rich 14 has PyInstaller unicode issues)
|
|
73
82
|
- **EPML URL transform**: spec paths start with `/api/...` but real URL is `https://api.beyondtrust.io/site/<site-id>/epm/linux/<spec-path-minus-/api/>`. Encapsulated in client `_build_url` — never bypass it.
|
|
74
83
|
- **EPML two authorizers**: spec claims `nomine-authorizer` (PAT) globally but the gateway has IAM-only routes (return 403 with AWS-flavored body). PAT cannot reach those. Documented per-op in `src/bt_cli/data/skills/epml/SKILL.md`. Where `/v6/pbul/rbp/...` exists alongside legacy `/pbul/{hostid}/rbp/...`, prefer legacy — v6 is mostly IAM-only.
|
|
84
|
+
- **EPML body-shape gotchas**: role create needs `action ∈ {A,R}`; hostgrp/usergrp create needs `type ∈ {I,E}` (Internal=static / External=directory-resolved); role assignments need `--kind S|R|B` for hostgrps/usergrps (S=Submit user, R=Run-as user); collection deletes use `?id=N` query params (CLI loops); child collections (commands/hosts/users/tmdates) have **no per-item delete** — `clear` nukes all, use `replace` to keep some.
|
|
85
|
+
- **EPML role update is upsert-on-id (overwrite, not partial)**: hitting `POST /roles` with `{id, ...}` clears any field you don't include. The CLI's `roles update` does read-modify-write so it feels partial; child relations are filtered out of the merge so assignments survive. Direct `curl` users must send the full record.
|
|
86
|
+
- **EPML role banner format**: `bt epml rbp roles create --banner-text "Title"` builds a `############`-framed message using `%rbprole%`/`%event%` server substitutions, mirroring the appliance's existing roles. See the worked role example in the EPM-L SKILL.md.
|
|
75
87
|
|
|
76
88
|
## Functional vs Managed Accounts
|
|
77
89
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# BT-CLI
|
|
2
2
|
|
|
3
|
-
BeyondTrust Platform CLI for Password Safe, Entitle, PRA, EPM Windows, and EPM Linux. **Version: 0.4.
|
|
3
|
+
BeyondTrust Platform CLI for Password Safe, Entitle, PRA, EPM Windows, and EPM Linux. **Version: 0.4.40**
|
|
4
4
|
|
|
5
5
|
## Setup
|
|
6
6
|
|
|
@@ -10,6 +10,15 @@ source .venv/bin/activate && source .env
|
|
|
10
10
|
bt whoami # Test all connections
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
+
Each product reads its own `BT_<PRODUCT>_*` env vars. EPM Linux is the odd one out — it uses a Personal Access Token (PAT) against the BeyondTrust public API gateway:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
export BT_EPML_API_URL=https://api.beyondtrust.io # default
|
|
17
|
+
export BT_EPML_SITE_ID=<site-uuid> # required
|
|
18
|
+
export BT_EPML_PAT=PAT_xxx # required (mint at app.beyondtrust.io)
|
|
19
|
+
export BT_EPML_DEFAULT_HOST=100 # default PMUL host id (optional)
|
|
20
|
+
```
|
|
21
|
+
|
|
13
22
|
## Skills Available
|
|
14
23
|
|
|
15
24
|
Use these slash commands for detailed product guidance:
|
|
@@ -72,6 +81,9 @@ PASSWORD=$(bt pws quick checkout -s server -a admin --raw)
|
|
|
72
81
|
- Windows builds: Rich must be pinned to `<14.0.0` (Rich 14 has PyInstaller unicode issues)
|
|
73
82
|
- **EPML URL transform**: spec paths start with `/api/...` but real URL is `https://api.beyondtrust.io/site/<site-id>/epm/linux/<spec-path-minus-/api/>`. Encapsulated in client `_build_url` — never bypass it.
|
|
74
83
|
- **EPML two authorizers**: spec claims `nomine-authorizer` (PAT) globally but the gateway has IAM-only routes (return 403 with AWS-flavored body). PAT cannot reach those. Documented per-op in `src/bt_cli/data/skills/epml/SKILL.md`. Where `/v6/pbul/rbp/...` exists alongside legacy `/pbul/{hostid}/rbp/...`, prefer legacy — v6 is mostly IAM-only.
|
|
84
|
+
- **EPML body-shape gotchas**: role create needs `action ∈ {A,R}`; hostgrp/usergrp create needs `type ∈ {I,E}` (Internal=static / External=directory-resolved); role assignments need `--kind S|R|B` for hostgrps/usergrps (S=Submit user, R=Run-as user); collection deletes use `?id=N` query params (CLI loops); child collections (commands/hosts/users/tmdates) have **no per-item delete** — `clear` nukes all, use `replace` to keep some.
|
|
85
|
+
- **EPML role update is upsert-on-id (overwrite, not partial)**: hitting `POST /roles` with `{id, ...}` clears any field you don't include. The CLI's `roles update` does read-modify-write so it feels partial; child relations are filtered out of the merge so assignments survive. Direct `curl` users must send the full record.
|
|
86
|
+
- **EPML role banner format**: `bt epml rbp roles create --banner-text "Title"` builds a `############`-framed message using `%rbprole%`/`%event%` server substitutions, mirroring the appliance's existing roles. See the worked role example in the EPM-L SKILL.md.
|
|
75
87
|
|
|
76
88
|
## Functional vs Managed Accounts
|
|
77
89
|
|
|
@@ -163,6 +163,54 @@ bt epml rbp policy revert
|
|
|
163
163
|
bt epml rbp policy delete-all --yes-i-mean-it # destructive, gated
|
|
164
164
|
```
|
|
165
165
|
|
|
166
|
+
## Worked example: build a role from scratch
|
|
167
|
+
|
|
168
|
+
End-to-end recipe for a "users in group X can run shells on all hosts at any time" role with I/O logging and a session banner. Mirrors the pattern of the tenant's existing roles (Postgres, Docker Admin, etc.).
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
# 1. Command group containing the commands the role allows
|
|
172
|
+
bt epml rbp cmdgrps create --name "RootShells" --description "Root shells with arguments"
|
|
173
|
+
# captures: id 35
|
|
174
|
+
bt epml rbp cmdgrps commands add 35 --commands "bash *,sh *,ksh *,zsh *,csh *,bash,sh,ksh,zsh,csh"
|
|
175
|
+
|
|
176
|
+
# 2. Role itself, all metadata in one shot
|
|
177
|
+
bt epml rbp roles create \
|
|
178
|
+
--name "RootShells" \
|
|
179
|
+
--description "Root shell access — I/O logged" \
|
|
180
|
+
--comment "Root shell access — I/O logged" \
|
|
181
|
+
--tag "RootAccess" \
|
|
182
|
+
--risk 9 \
|
|
183
|
+
--rpt 1 \
|
|
184
|
+
--action A \
|
|
185
|
+
--iolog '/iologs/%date%/%uniqueid%.iolog' \
|
|
186
|
+
--banner-text "Root Shell Access"
|
|
187
|
+
# captures: id 126
|
|
188
|
+
|
|
189
|
+
# 3. Wire up the four group assignments
|
|
190
|
+
bt epml rbp roles cmdgrps add 126 --ids 35 # cmdgrp: just IDs
|
|
191
|
+
bt epml rbp roles hostgrps add 126 --ids 1 --kind B # All Hosts, both Submit and Run-as
|
|
192
|
+
bt epml rbp roles usergrps add 126 --ids 4 --kind S # Administrators as Submit (who requests)
|
|
193
|
+
bt epml rbp roles usergrps add 126 --ids 3 --kind R # 'root' as Run-as (whose identity)
|
|
194
|
+
bt epml rbp roles tmdategrps add 126 --ids 1 # Any Time
|
|
195
|
+
|
|
196
|
+
# 4. Verify
|
|
197
|
+
bt epml rbp roles list -o json | python3 -c 'import json,sys;[print(json.dumps(r,indent=2)) for r in json.load(sys.stdin) if r["id"]==126]'
|
|
198
|
+
bt epml rbp roles cmdgrps list 126
|
|
199
|
+
bt epml rbp roles hostgrps list 126
|
|
200
|
+
bt epml rbp roles usergrps list 126
|
|
201
|
+
bt epml rbp roles tmdategrps list 126
|
|
202
|
+
bt epml rbp entitlement run -o json | grep RootShells # rpt=1 makes it surface
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
The resulting banner displayed to users (server-substituted at session time):
|
|
206
|
+
```
|
|
207
|
+
############################################################
|
|
208
|
+
Policy: Root Shell Access
|
|
209
|
+
Status: %event%
|
|
210
|
+
Session Recorded: Yes
|
|
211
|
+
############################################################
|
|
212
|
+
```
|
|
213
|
+
|
|
166
214
|
## Test suites + transactions (the killer workflow)
|
|
167
215
|
|
|
168
216
|
```bash
|
|
@@ -211,7 +259,8 @@ bt epml quick tests-then-deploy --suite <suite_id> # commits if pass; rollb
|
|
|
211
259
|
- **Children share the parent's `id`** in GET responses — the listed `id` field is the cmdgrp/hostgrp/usergrp ID, not unique per child. The actual identifier is the `cmd`/`host`/`user` text.
|
|
212
260
|
- **Role assignments take a single object per request, not an array**. The CLI loops under the hood; the wire body is e.g. `{"cmds": 35}`, `{"hosts": 1, "type": "S"}`, `{"users": 4, "type": "R"}`, `{"tmdates": 1}`.
|
|
213
261
|
- **Hostgrp / usergrp assignments require a `type` field** (`S` = Submit / who requests, `R` = Run-as / whose identity the command runs under). Without `type` the request 400s with "RBP role type not in: [S,R]". CLI: `--kind S|R|B` on `roles hostgrps add` and `roles usergrps add`. `B` (default) creates both an S row and an R row for the same id — appropriate when the same group plays both roles. For "Admin requests, runs as root", do `--ids 4 --kind S` and `--ids 3 --kind R` separately.
|
|
214
|
-
- **Roles need `rpt: 1`** to appear in `bt epml rbp entitlement run`. The role still functions for policy evaluation either way, but only `rpt=1` roles are surfaced in the report.
|
|
262
|
+
- **Roles need `rpt: 1`** to appear in `bt epml rbp entitlement run`. The role still functions for policy evaluation either way, but only `rpt=1` roles are surfaced in the report. Set with `--rpt 1` on `roles create` / `roles update` (added in 0.4.38).
|
|
263
|
+
- **Role update is upsert-on-id, not partial**: hitting POST `/roles` with `{id, ...}` *overwrites* the matching record — fields you omit get cleared. The CLI's `roles update` does read-modify-write (fetch the role, merge changes, post the whole record) so this feels partial. Role-child relations (rolecmds/roleusers/etc.) are filtered out of the merge so assignments survive an update. **If you hit the API directly via curl**, you must send the full record yourself.
|
|
215
264
|
|
|
216
265
|
## Known gaps (TODO)
|
|
217
266
|
|
|
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
|
|
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
|