bt-cli 0.4.51__tar.gz → 0.4.52__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.51 → bt_cli-0.4.52}/CLAUDE.md +1 -1
- {bt_cli-0.4.51 → bt_cli-0.4.52}/PKG-INFO +1 -1
- {bt_cli-0.4.51 → bt_cli-0.4.52}/pyproject.toml +1 -1
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/__init__.py +1 -1
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pws/client/passwordsafe.py +29 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pws/commands/accounts.py +166 -1
- {bt_cli-0.4.51 → bt_cli-0.4.52}/.claude/skills/bt/SKILL.md +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/.claude/skills/entitle/SKILL.md +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/.claude/skills/epml/SKILL.md +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/.claude/skills/epmw/SKILL.md +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/.claude/skills/pra/SKILL.md +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/.claude/skills/pws/SKILL.md +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/.env.example +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/.github/workflows/ci.yml +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/.github/workflows/release.yml +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/.gitignore +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/README.md +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/assets/cli-help.png +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/assets/cli-output.png +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/bt-cli.spec +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/bt_entry.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/epml-clients-server-side-filters-plan.md +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/epml-implementation-plan.md +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/pf-implementation-plan.md +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/scripts/bt_entry.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/scripts/pf_onboard.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/scripts/sync-package-data.sh +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/cli.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/commands/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/commands/configure.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/commands/learn.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/commands/quick.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/core/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/core/auth.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/core/client.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/core/config.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/core/config_file.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/core/csv_utils.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/core/errors.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/core/output.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/core/prompts.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/core/rest_debug.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/data/CLAUDE.md +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/data/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/data/skills/bt/SKILL.md +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/data/skills/entitle/SKILL.md +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/data/skills/epml/SKILL.md +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/data/skills/epmw/SKILL.md +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/data/skills/pra/SKILL.md +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/data/skills/pws/SKILL.md +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/data/skills/secrets/SKILL.md +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/entitle/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/entitle/client/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/entitle/client/base.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/entitle/commands/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/entitle/commands/accounts.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/entitle/commands/applications.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/entitle/commands/auth.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/entitle/commands/bundles.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/entitle/commands/integrations.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/entitle/commands/permissions.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/entitle/commands/policies.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/entitle/commands/requests.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/entitle/commands/resources.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/entitle/commands/roles.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/entitle/commands/users.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/entitle/commands/workflows.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/entitle/models/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/entitle/models/bundle.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/entitle/models/common.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/entitle/models/integration.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/entitle/models/permission.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/entitle/models/policy.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/entitle/models/resource.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/entitle/models/role.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/entitle/models/user.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/entitle/models/workflow.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epml/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epml/client/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epml/client/base.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epml/commands/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epml/commands/audit.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epml/commands/auth.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epml/commands/client_pkg.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epml/commands/clients.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epml/commands/external_apis.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epml/commands/hosts.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epml/commands/iolog.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epml/commands/license.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epml/commands/quick.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epml/commands/rbp_cmdgrps.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epml/commands/rbp_entitlement.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epml/commands/rbp_hostgrps.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epml/commands/rbp_policy.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epml/commands/rbp_roles.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epml/commands/rbp_tests.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epml/commands/rbp_tmdategrps.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epml/commands/rbp_tx.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epml/commands/rbp_usergrps.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epml/commands/settings.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epml/commands/siems.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epml/commands/users.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epml/models/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epmw/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epmw/client/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epmw/client/base.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epmw/commands/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epmw/commands/audits.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epmw/commands/auth.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epmw/commands/computers.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epmw/commands/events.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epmw/commands/groups.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epmw/commands/policies.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epmw/commands/quick.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epmw/commands/requests.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epmw/commands/roles.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epmw/commands/tasks.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epmw/commands/users.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/epmw/models/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pra/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pra/client/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pra/client/base.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pra/commands/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pra/commands/auth.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pra/commands/group_policies.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pra/commands/import_export.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pra/commands/jump_clients.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pra/commands/jump_groups.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pra/commands/jump_items.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pra/commands/jumpoints.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pra/commands/policies.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pra/commands/quick.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pra/commands/teams.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pra/commands/users.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pra/commands/vault.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pra/models/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pra/models/common.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pra/models/group_policy.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pra/models/jump_client.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pra/models/jump_group.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pra/models/jump_item.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pra/models/jumpoint.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pra/models/team.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pra/models/user.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pra/models/vault.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pws/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pws/client/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pws/client/base.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pws/client/beyondinsight.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pws/commands/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pws/commands/assets.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pws/commands/attributes.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pws/commands/auth.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pws/commands/clouds.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pws/commands/config.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pws/commands/credentials.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pws/commands/databases.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pws/commands/directories.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pws/commands/functional.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pws/commands/import_export.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pws/commands/platforms.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pws/commands/quick.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pws/commands/search.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pws/commands/secrets.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pws/commands/systems.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pws/commands/users.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pws/commands/workgroups.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pws/config.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pws/models/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pws/models/account.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pws/models/asset.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pws/models/common.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/pws/models/system.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/secrets/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/secrets/client/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/secrets/client/base.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/secrets/commands/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/secrets/commands/_hints.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/secrets/commands/auth.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/secrets/commands/dynamic.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/secrets/commands/folders.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/secrets/commands/integrations.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/secrets/commands/leases.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/secrets/commands/static.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/src/bt_cli/secrets/models/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/conftest.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/core/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/core/test_auth.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/core/test_config.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/core/test_errors.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/core/test_rest_debug.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/entitle/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/entitle/test_client.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/entitle/test_commands.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/entitle-smoke-test.sh +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/epml/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/epml/test_client.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/epml/test_commands.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/epmw/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/epmw/test_client.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/epmw/test_commands.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/epmw-quick-test-plan.md +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/fixtures/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/fixtures/responses.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/integration/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/integration/conftest.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/integration/helpers.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/integration/test_entitle_integration.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/integration/test_epmw_integration.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/integration/test_epmw_lifecycle.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/integration/test_pra_integration.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/integration/test_pra_lifecycle.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/integration/test_pws_integration.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/integration/test_pws_lifecycle.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/pra/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/pra/test_client.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/pra/test_commands.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/pra-smoke-test.sh +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/pra-test-plan.md +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/pws/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/pws/test_client.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/pws/test_commands.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/pws-quick-test-plan.md +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/pws-smoke-test.sh +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/secrets/__init__.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/secrets/test_client.py +0 -0
- {bt_cli-0.4.51 → bt_cli-0.4.52}/tests/secrets/test_commands.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# BT-CLI
|
|
2
2
|
|
|
3
|
-
BeyondTrust Platform CLI for Password Safe, Entitle, PRA, EPM Windows, EPM Linux, and the BeyondTrust Secrets API. **Version: 0.4.
|
|
3
|
+
BeyondTrust Platform CLI for Password Safe, Entitle, PRA, EPM Windows, EPM Linux, and the BeyondTrust Secrets API. **Version: 0.4.52**
|
|
4
4
|
|
|
5
5
|
## Setup
|
|
6
6
|
|
|
@@ -80,6 +80,35 @@ class PasswordSafeMixin:
|
|
|
80
80
|
"""
|
|
81
81
|
return self.get(f"/ManagedAccounts/{account_id}")
|
|
82
82
|
|
|
83
|
+
# =========================================================================
|
|
84
|
+
# Synced Accounts
|
|
85
|
+
# =========================================================================
|
|
86
|
+
|
|
87
|
+
def list_synced_accounts(
|
|
88
|
+
self: "PasswordSafeClient", account_id: int
|
|
89
|
+
) -> list[dict[str, Any]]:
|
|
90
|
+
"""List accounts synced to a managed account."""
|
|
91
|
+
result = self.get(f"/ManagedAccounts/{account_id}/SyncedAccounts")
|
|
92
|
+
return result if isinstance(result, list) else []
|
|
93
|
+
|
|
94
|
+
def add_synced_account(
|
|
95
|
+
self: "PasswordSafeClient", account_id: int, synced_account_id: int
|
|
96
|
+
) -> dict[str, Any]:
|
|
97
|
+
"""Add a synced account relationship."""
|
|
98
|
+
return self.post(f"/ManagedAccounts/{account_id}/SyncedAccounts/{synced_account_id}")
|
|
99
|
+
|
|
100
|
+
def remove_synced_account(
|
|
101
|
+
self: "PasswordSafeClient", account_id: int, synced_account_id: int
|
|
102
|
+
) -> None:
|
|
103
|
+
"""Remove a specific synced account."""
|
|
104
|
+
self.delete(f"/ManagedAccounts/{account_id}/SyncedAccounts/{synced_account_id}")
|
|
105
|
+
|
|
106
|
+
def remove_all_synced_accounts(
|
|
107
|
+
self: "PasswordSafeClient", account_id: int
|
|
108
|
+
) -> None:
|
|
109
|
+
"""Remove all synced accounts from a managed account."""
|
|
110
|
+
self.delete(f"/ManagedAccounts/{account_id}/SyncedAccounts")
|
|
111
|
+
|
|
83
112
|
def get_managed_account_by_name(
|
|
84
113
|
self: "PasswordSafeClient",
|
|
85
114
|
system_name: str,
|
|
@@ -8,7 +8,7 @@ import typer
|
|
|
8
8
|
from rich.console import Console
|
|
9
9
|
from rich.table import Table
|
|
10
10
|
|
|
11
|
-
from ...core.output import print_api_error
|
|
11
|
+
from ...core.output import print_api_error, print_success
|
|
12
12
|
from ..client.base import get_client
|
|
13
13
|
|
|
14
14
|
app = typer.Typer(no_args_is_help=True, help="""Manage managed accounts in Password Safe.
|
|
@@ -370,3 +370,168 @@ def rotate_password(
|
|
|
370
370
|
except Exception as e:
|
|
371
371
|
print_api_error(e, "manage accounts")
|
|
372
372
|
raise typer.Exit(1)
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
# =============================================================================
|
|
376
|
+
# Synced Accounts
|
|
377
|
+
# =============================================================================
|
|
378
|
+
|
|
379
|
+
@app.command("synced-list")
|
|
380
|
+
def synced_list(
|
|
381
|
+
account_id: int = typer.Argument(..., help="Parent managed account ID"),
|
|
382
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table or json"),
|
|
383
|
+
) -> None:
|
|
384
|
+
"""List accounts synced to a managed account.
|
|
385
|
+
|
|
386
|
+
Examples:
|
|
387
|
+
bt pws accounts synced-list 14
|
|
388
|
+
bt pws accounts synced-list 14 -o json
|
|
389
|
+
"""
|
|
390
|
+
try:
|
|
391
|
+
with get_client() as client:
|
|
392
|
+
client.authenticate()
|
|
393
|
+
accounts = client.list_synced_accounts(account_id)
|
|
394
|
+
|
|
395
|
+
if output == "json":
|
|
396
|
+
console.print_json(json.dumps(accounts, default=str))
|
|
397
|
+
elif accounts:
|
|
398
|
+
table = Table(title=f"Synced Accounts (parent ID: {account_id})")
|
|
399
|
+
table.add_column("Acct ID", style="cyan", no_wrap=True)
|
|
400
|
+
table.add_column("Account Name", style="green")
|
|
401
|
+
table.add_column("Domain", style="yellow")
|
|
402
|
+
table.add_column("Sys ID", style="blue", no_wrap=True)
|
|
403
|
+
table.add_column("Description", style="dim")
|
|
404
|
+
for a in accounts:
|
|
405
|
+
table.add_row(
|
|
406
|
+
str(a.get("ManagedAccountID", "")),
|
|
407
|
+
a.get("AccountName", ""),
|
|
408
|
+
a.get("DomainName") or "-",
|
|
409
|
+
str(a.get("ManagedSystemID", "")),
|
|
410
|
+
(a.get("Description") or "-")[:50],
|
|
411
|
+
)
|
|
412
|
+
console.print(table)
|
|
413
|
+
else:
|
|
414
|
+
console.print("[yellow]No synced accounts.[/yellow]")
|
|
415
|
+
|
|
416
|
+
except httpx.HTTPStatusError as e:
|
|
417
|
+
print_api_error(e, "synced-list")
|
|
418
|
+
raise typer.Exit(1)
|
|
419
|
+
except httpx.RequestError as e:
|
|
420
|
+
print_api_error(e, "synced-list")
|
|
421
|
+
raise typer.Exit(1)
|
|
422
|
+
except Exception as e:
|
|
423
|
+
print_api_error(e, "synced-list")
|
|
424
|
+
raise typer.Exit(1)
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
@app.command("synced-add")
|
|
428
|
+
def synced_add(
|
|
429
|
+
account_id: int = typer.Argument(..., help="Parent managed account ID"),
|
|
430
|
+
synced_account_id: int = typer.Argument(..., help="Account ID to sync"),
|
|
431
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table or json"),
|
|
432
|
+
) -> None:
|
|
433
|
+
"""Add a synced account relationship.
|
|
434
|
+
|
|
435
|
+
Synced accounts share password changes with the parent account.
|
|
436
|
+
|
|
437
|
+
Examples:
|
|
438
|
+
bt pws accounts synced-add 14 25
|
|
439
|
+
bt pws accounts synced-add 14 25 -o json
|
|
440
|
+
"""
|
|
441
|
+
try:
|
|
442
|
+
with get_client() as client:
|
|
443
|
+
client.authenticate()
|
|
444
|
+
result = client.add_synced_account(account_id, synced_account_id)
|
|
445
|
+
|
|
446
|
+
if output == "json":
|
|
447
|
+
console.print_json(json.dumps(result, default=str))
|
|
448
|
+
else:
|
|
449
|
+
name = result.get("AccountName", str(synced_account_id))
|
|
450
|
+
print_success(f"Synced account '{name}' (ID: {synced_account_id}) added to account ID: {account_id}")
|
|
451
|
+
|
|
452
|
+
except httpx.HTTPStatusError as e:
|
|
453
|
+
print_api_error(e, "synced-add")
|
|
454
|
+
raise typer.Exit(1)
|
|
455
|
+
except httpx.RequestError as e:
|
|
456
|
+
print_api_error(e, "synced-add")
|
|
457
|
+
raise typer.Exit(1)
|
|
458
|
+
except Exception as e:
|
|
459
|
+
print_api_error(e, "synced-add")
|
|
460
|
+
raise typer.Exit(1)
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
@app.command("synced-remove")
|
|
464
|
+
def synced_remove(
|
|
465
|
+
account_id: int = typer.Argument(..., help="Parent managed account ID"),
|
|
466
|
+
synced_account_id: int = typer.Argument(..., help="Synced account ID to remove"),
|
|
467
|
+
force: bool = typer.Option(False, "--force", "-f", help="Skip confirmation"),
|
|
468
|
+
) -> None:
|
|
469
|
+
"""Remove a specific synced account.
|
|
470
|
+
|
|
471
|
+
Examples:
|
|
472
|
+
bt pws accounts synced-remove 14 25
|
|
473
|
+
bt pws accounts synced-remove 14 25 --force
|
|
474
|
+
"""
|
|
475
|
+
try:
|
|
476
|
+
with get_client() as client:
|
|
477
|
+
client.authenticate()
|
|
478
|
+
|
|
479
|
+
if not force:
|
|
480
|
+
confirm = typer.confirm(f"Remove synced account {synced_account_id} from account {account_id}?")
|
|
481
|
+
if not confirm:
|
|
482
|
+
console.print("[yellow]Cancelled.[/yellow]")
|
|
483
|
+
raise typer.Exit(0)
|
|
484
|
+
|
|
485
|
+
client.remove_synced_account(account_id, synced_account_id)
|
|
486
|
+
|
|
487
|
+
print_success(f"Removed synced account ID: {synced_account_id} from account ID: {account_id}")
|
|
488
|
+
|
|
489
|
+
except httpx.HTTPStatusError as e:
|
|
490
|
+
print_api_error(e, "synced-remove")
|
|
491
|
+
raise typer.Exit(1)
|
|
492
|
+
except httpx.RequestError as e:
|
|
493
|
+
print_api_error(e, "synced-remove")
|
|
494
|
+
raise typer.Exit(1)
|
|
495
|
+
except typer.Exit:
|
|
496
|
+
raise
|
|
497
|
+
except Exception as e:
|
|
498
|
+
print_api_error(e, "synced-remove")
|
|
499
|
+
raise typer.Exit(1)
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
@app.command("synced-clear")
|
|
503
|
+
def synced_clear(
|
|
504
|
+
account_id: int = typer.Argument(..., help="Parent managed account ID"),
|
|
505
|
+
force: bool = typer.Option(False, "--force", "-f", help="Skip confirmation"),
|
|
506
|
+
) -> None:
|
|
507
|
+
"""Remove all synced accounts from a managed account.
|
|
508
|
+
|
|
509
|
+
Examples:
|
|
510
|
+
bt pws accounts synced-clear 14
|
|
511
|
+
bt pws accounts synced-clear 14 --force
|
|
512
|
+
"""
|
|
513
|
+
try:
|
|
514
|
+
with get_client() as client:
|
|
515
|
+
client.authenticate()
|
|
516
|
+
|
|
517
|
+
if not force:
|
|
518
|
+
confirm = typer.confirm(f"Remove ALL synced accounts from account {account_id}?")
|
|
519
|
+
if not confirm:
|
|
520
|
+
console.print("[yellow]Cancelled.[/yellow]")
|
|
521
|
+
raise typer.Exit(0)
|
|
522
|
+
|
|
523
|
+
client.remove_all_synced_accounts(account_id)
|
|
524
|
+
|
|
525
|
+
print_success(f"All synced accounts removed from account ID: {account_id}")
|
|
526
|
+
|
|
527
|
+
except httpx.HTTPStatusError as e:
|
|
528
|
+
print_api_error(e, "synced-clear")
|
|
529
|
+
raise typer.Exit(1)
|
|
530
|
+
except httpx.RequestError as e:
|
|
531
|
+
print_api_error(e, "synced-clear")
|
|
532
|
+
raise typer.Exit(1)
|
|
533
|
+
except typer.Exit:
|
|
534
|
+
raise
|
|
535
|
+
except Exception as e:
|
|
536
|
+
print_api_error(e, "synced-clear")
|
|
537
|
+
raise typer.Exit(1)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|