bt-cli 0.4.47__tar.gz → 0.4.48__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.47 → bt_cli-0.4.48}/CLAUDE.md +1 -1
- {bt_cli-0.4.47 → bt_cli-0.4.48}/PKG-INFO +1 -1
- {bt_cli-0.4.47 → bt_cli-0.4.48}/pyproject.toml +1 -1
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/__init__.py +1 -1
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/data/skills/secrets/SKILL.md +15 -3
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/secrets/commands/dynamic.py +40 -10
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/secrets/test_commands.py +46 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/.claude/skills/bt/SKILL.md +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/.claude/skills/entitle/SKILL.md +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/.claude/skills/epml/SKILL.md +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/.claude/skills/epmw/SKILL.md +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/.claude/skills/pra/SKILL.md +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/.claude/skills/pws/SKILL.md +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/.env.example +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/.github/workflows/ci.yml +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/.github/workflows/release.yml +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/.gitignore +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/README.md +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/assets/cli-help.png +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/assets/cli-output.png +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/bt-cli.spec +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/bt_entry.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/epml-clients-server-side-filters-plan.md +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/epml-implementation-plan.md +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/pf-implementation-plan.md +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/scripts/bt_entry.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/scripts/pf_onboard.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/scripts/sync-package-data.sh +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/cli.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/commands/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/commands/configure.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/commands/learn.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/commands/quick.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/core/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/core/auth.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/core/client.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/core/config.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/core/config_file.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/core/csv_utils.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/core/errors.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/core/output.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/core/prompts.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/core/rest_debug.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/data/CLAUDE.md +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/data/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/data/skills/bt/SKILL.md +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/data/skills/entitle/SKILL.md +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/data/skills/epml/SKILL.md +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/data/skills/epmw/SKILL.md +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/data/skills/pra/SKILL.md +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/data/skills/pws/SKILL.md +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/entitle/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/entitle/client/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/entitle/client/base.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/entitle/commands/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/entitle/commands/accounts.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/entitle/commands/applications.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/entitle/commands/auth.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/entitle/commands/bundles.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/entitle/commands/integrations.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/entitle/commands/permissions.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/entitle/commands/policies.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/entitle/commands/requests.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/entitle/commands/resources.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/entitle/commands/roles.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/entitle/commands/users.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/entitle/commands/workflows.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/entitle/models/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/entitle/models/bundle.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/entitle/models/common.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/entitle/models/integration.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/entitle/models/permission.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/entitle/models/policy.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/entitle/models/resource.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/entitle/models/role.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/entitle/models/user.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/entitle/models/workflow.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epml/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epml/client/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epml/client/base.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epml/commands/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epml/commands/audit.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epml/commands/auth.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epml/commands/client_pkg.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epml/commands/clients.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epml/commands/external_apis.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epml/commands/hosts.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epml/commands/iolog.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epml/commands/license.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epml/commands/quick.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epml/commands/rbp_cmdgrps.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epml/commands/rbp_entitlement.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epml/commands/rbp_hostgrps.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epml/commands/rbp_policy.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epml/commands/rbp_roles.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epml/commands/rbp_tests.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epml/commands/rbp_tmdategrps.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epml/commands/rbp_tx.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epml/commands/rbp_usergrps.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epml/commands/settings.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epml/commands/siems.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epml/commands/users.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epml/models/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epmw/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epmw/client/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epmw/client/base.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epmw/commands/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epmw/commands/audits.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epmw/commands/auth.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epmw/commands/computers.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epmw/commands/events.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epmw/commands/groups.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epmw/commands/policies.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epmw/commands/quick.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epmw/commands/requests.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epmw/commands/roles.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epmw/commands/tasks.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epmw/commands/users.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/epmw/models/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pra/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pra/client/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pra/client/base.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pra/commands/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pra/commands/auth.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pra/commands/group_policies.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pra/commands/import_export.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pra/commands/jump_clients.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pra/commands/jump_groups.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pra/commands/jump_items.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pra/commands/jumpoints.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pra/commands/policies.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pra/commands/quick.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pra/commands/teams.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pra/commands/users.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pra/commands/vault.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pra/models/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pra/models/common.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pra/models/group_policy.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pra/models/jump_client.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pra/models/jump_group.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pra/models/jump_item.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pra/models/jumpoint.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pra/models/team.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pra/models/user.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pra/models/vault.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pws/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pws/client/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pws/client/base.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pws/client/beyondinsight.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pws/client/passwordsafe.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pws/commands/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pws/commands/accounts.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pws/commands/assets.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pws/commands/attributes.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pws/commands/auth.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pws/commands/clouds.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pws/commands/config.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pws/commands/credentials.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pws/commands/databases.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pws/commands/directories.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pws/commands/functional.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pws/commands/import_export.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pws/commands/platforms.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pws/commands/quick.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pws/commands/search.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pws/commands/secrets.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pws/commands/systems.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pws/commands/users.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pws/commands/workgroups.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pws/config.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pws/models/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pws/models/account.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pws/models/asset.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pws/models/common.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/pws/models/system.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/secrets/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/secrets/client/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/secrets/client/base.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/secrets/commands/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/secrets/commands/_hints.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/secrets/commands/auth.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/secrets/commands/folders.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/secrets/commands/integrations.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/secrets/commands/leases.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/secrets/commands/static.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/src/bt_cli/secrets/models/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/conftest.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/core/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/core/test_auth.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/core/test_config.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/core/test_errors.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/core/test_rest_debug.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/entitle/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/entitle/test_client.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/entitle/test_commands.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/entitle-smoke-test.sh +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/epml/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/epml/test_client.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/epml/test_commands.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/epmw/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/epmw/test_client.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/epmw/test_commands.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/epmw-quick-test-plan.md +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/fixtures/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/fixtures/responses.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/integration/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/integration/conftest.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/integration/helpers.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/integration/test_entitle_integration.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/integration/test_epmw_integration.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/integration/test_epmw_lifecycle.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/integration/test_pra_integration.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/integration/test_pra_lifecycle.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/integration/test_pws_integration.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/integration/test_pws_lifecycle.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/pra/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/pra/test_client.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/pra/test_commands.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/pra-smoke-test.sh +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/pra-test-plan.md +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/pws/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/pws/test_client.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/pws/test_commands.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/pws-quick-test-plan.md +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/pws-smoke-test.sh +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/secrets/__init__.py +0 -0
- {bt_cli-0.4.47 → bt_cli-0.4.48}/tests/secrets/test_client.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.48**
|
|
4
4
|
|
|
5
5
|
## Setup
|
|
6
6
|
|
|
@@ -97,12 +97,24 @@ bt secrets dynamic get lab/aws/ec2-readonly
|
|
|
97
97
|
|
|
98
98
|
# Mint fresh credentials — default prints shell `export AWS_*` lines.
|
|
99
99
|
bt secrets dynamic generate lab/aws/ec2-readonly
|
|
100
|
-
|
|
101
|
-
|
|
100
|
+
|
|
101
|
+
# Apply to the current session (a child process can't mutate its parent's env,
|
|
102
|
+
# so the CLI emits shell-native syntax that you eval into your shell):
|
|
103
|
+
|
|
104
|
+
# bash / zsh:
|
|
105
|
+
eval $(bt secrets dynamic generate lab/aws/ec2-readonly)
|
|
106
|
+
|
|
107
|
+
# PowerShell:
|
|
108
|
+
bt secrets dynamic generate lab/aws/ec2-readonly --format powershell | iex
|
|
109
|
+
|
|
110
|
+
# cmd.exe:
|
|
111
|
+
for /f "delims=" %i in ('bt secrets dynamic generate lab/aws/ec2-readonly --format cmd') do %i
|
|
112
|
+
|
|
113
|
+
aws sts get-caller-identity # verify the creds are active
|
|
102
114
|
|
|
103
115
|
# Other formats:
|
|
104
116
|
bt secrets dynamic generate lab/aws/ec2-readonly --format json # full payload w/ leaseId
|
|
105
|
-
bt secrets dynamic generate lab/aws/ec2-readonly --format env # KEY=value
|
|
117
|
+
bt secrets dynamic generate lab/aws/ec2-readonly --format env # bare KEY=value
|
|
106
118
|
bt secrets dynamic generate lab/aws/ec2-readonly --format dotenv # KEY="value" for .env files
|
|
107
119
|
```
|
|
108
120
|
|
|
@@ -28,10 +28,12 @@ app = typer.Typer(no_args_is_help=True, help="Dynamic secrets (e.g. AWS STS, min
|
|
|
28
28
|
class GenerateFormat(str, Enum):
|
|
29
29
|
"""Output formats for `dynamic generate`."""
|
|
30
30
|
|
|
31
|
-
EXPORT = "export"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
EXPORT = "export" # default — bash/zsh `export AWS_*` lines
|
|
32
|
+
POWERSHELL = "powershell" # PowerShell `$env:AWS_* = "..."` lines
|
|
33
|
+
CMD = "cmd" # Windows cmd.exe `set AWS_*=...` lines
|
|
34
|
+
ENV = "env" # bare KEY=value lines (no `export`)
|
|
35
|
+
JSON = "json" # raw API payload
|
|
36
|
+
DOTENV = "dotenv" # KEY="value" lines suitable for .env files
|
|
35
37
|
|
|
36
38
|
|
|
37
39
|
def _dynamic_row(item: dict) -> dict:
|
|
@@ -51,6 +53,13 @@ def _format_credentials(secret: dict, fmt: GenerateFormat) -> str:
|
|
|
51
53
|
(``accessKeyId``, ``secretAccessKey``, ``sessionToken``). For shell
|
|
52
54
|
consumption we map those to the standard ``AWS_*`` env-var names that
|
|
53
55
|
boto3, aws-cli, and the EC2 SDK all read.
|
|
56
|
+
|
|
57
|
+
A subprocess can't mutate its parent shell's environment, so each
|
|
58
|
+
format is designed to be piped into the shell's eval mechanism:
|
|
59
|
+
|
|
60
|
+
* EXPORT → `eval $(bt secrets dynamic generate <path>)`
|
|
61
|
+
* POWERSHELL → `bt secrets dynamic generate <path> --format powershell | iex`
|
|
62
|
+
* CMD → cmd.exe needs a temp .bat or a `for /f` loop — see SKILL.md
|
|
54
63
|
"""
|
|
55
64
|
aws_map = [
|
|
56
65
|
("AWS_ACCESS_KEY_ID", "accessKeyId"),
|
|
@@ -63,6 +72,16 @@ def _format_credentials(secret: dict, fmt: GenerateFormat) -> str:
|
|
|
63
72
|
value = secret[payload_key]
|
|
64
73
|
if fmt is GenerateFormat.EXPORT:
|
|
65
74
|
lines.append(f"export {env_name}={value}")
|
|
75
|
+
elif fmt is GenerateFormat.POWERSHELL:
|
|
76
|
+
# `Invoke-Expression` parses these as statements that set the
|
|
77
|
+
# process env. Quote the value so PowerShell doesn't try to
|
|
78
|
+
# interpret embedded characters.
|
|
79
|
+
lines.append(f'$env:{env_name} = "{value}"')
|
|
80
|
+
elif fmt is GenerateFormat.CMD:
|
|
81
|
+
# `set` in cmd.exe doesn't quote and doesn't tolerate spaces
|
|
82
|
+
# around `=`. Values from STS are alphanumeric-plus-/+=_-, so
|
|
83
|
+
# bare assignment is safe.
|
|
84
|
+
lines.append(f"set {env_name}={value}")
|
|
66
85
|
elif fmt is GenerateFormat.ENV:
|
|
67
86
|
lines.append(f"{env_name}={value}")
|
|
68
87
|
elif fmt is GenerateFormat.DOTENV:
|
|
@@ -70,8 +89,13 @@ def _format_credentials(secret: dict, fmt: GenerateFormat) -> str:
|
|
|
70
89
|
if not lines:
|
|
71
90
|
return ""
|
|
72
91
|
if "expiration" in secret:
|
|
73
|
-
# Trailing comment is
|
|
74
|
-
|
|
92
|
+
# Trailing comment is informational — all four script-y formats
|
|
93
|
+
# tolerate `#` (bash/PowerShell) or treat the line as a label-style
|
|
94
|
+
# noop for cmd's set, which we replace with REM below.
|
|
95
|
+
if fmt is GenerateFormat.CMD:
|
|
96
|
+
lines.append(f"REM expires: {secret['expiration']}")
|
|
97
|
+
else:
|
|
98
|
+
lines.append(f"# expires: {secret['expiration']}")
|
|
75
99
|
return "\n".join(lines)
|
|
76
100
|
|
|
77
101
|
|
|
@@ -150,15 +174,21 @@ def generate(
|
|
|
150
174
|
full_path: str = typer.Argument(..., help="Full dynamic-secret path"),
|
|
151
175
|
format_: GenerateFormat = typer.Option(
|
|
152
176
|
GenerateFormat.EXPORT, "--format", "-F",
|
|
153
|
-
help="Output format: export | env | json | dotenv",
|
|
177
|
+
help="Output format: export | powershell | cmd | env | json | dotenv",
|
|
154
178
|
case_sensitive=False,
|
|
155
179
|
),
|
|
156
180
|
) -> None:
|
|
157
181
|
"""Mint fresh credentials from a dynamic-secret config.
|
|
158
182
|
|
|
159
|
-
Default ``--format export`` prints shell ``export AWS_*`` lines
|
|
160
|
-
|
|
161
|
-
|
|
183
|
+
Default ``--format export`` prints shell ``export AWS_*`` lines.
|
|
184
|
+
|
|
185
|
+
\b
|
|
186
|
+
Apply in your current session:
|
|
187
|
+
bash / zsh: eval $(bt secrets dynamic generate <path>)
|
|
188
|
+
PowerShell: bt secrets dynamic generate <path> --format powershell | iex
|
|
189
|
+
cmd.exe: for /f "delims=" %i in ('bt secrets dynamic generate <path> --format cmd') do %i
|
|
190
|
+
|
|
191
|
+
Use ``--format json`` to see the full payload (lease id, expiration).
|
|
162
192
|
|
|
163
193
|
Heads up: every call mints real STS credentials and shows up in the
|
|
164
194
|
audit trail. Don't loop this in development.
|
|
@@ -226,6 +226,52 @@ class TestDynamic:
|
|
|
226
226
|
assert "AWS_ACCESS_KEY_ID=AKIA-FAKE" in result.stdout
|
|
227
227
|
assert "export" not in result.stdout.split("\n")[0]
|
|
228
228
|
|
|
229
|
+
@respx.mock
|
|
230
|
+
def test_dynamic_generate_powershell_shape(self, env_overrides):
|
|
231
|
+
"""PowerShell format: $env:VAR = "val" — pipe to Invoke-Expression."""
|
|
232
|
+
respx.post(_url("/dynamic/ec2-readonly/generate")).mock(
|
|
233
|
+
return_value=httpx.Response(201, json={"secret": {
|
|
234
|
+
"accessKeyId": "ASIA-FAKE",
|
|
235
|
+
"secretAccessKey": "SAK-FAKE",
|
|
236
|
+
"sessionToken": "TOK-FAKE",
|
|
237
|
+
"expiration": "2026-01-01T00:00:00Z",
|
|
238
|
+
}})
|
|
239
|
+
)
|
|
240
|
+
result = CliRunner().invoke(
|
|
241
|
+
secrets_app,
|
|
242
|
+
["dynamic", "generate", "lab/aws/ec2-readonly", "--format", "powershell"],
|
|
243
|
+
)
|
|
244
|
+
assert result.exit_code == 0
|
|
245
|
+
assert '$env:AWS_ACCESS_KEY_ID = "ASIA-FAKE"' in result.stdout
|
|
246
|
+
assert '$env:AWS_SECRET_ACCESS_KEY = "SAK-FAKE"' in result.stdout
|
|
247
|
+
assert '$env:AWS_SESSION_TOKEN = "TOK-FAKE"' in result.stdout
|
|
248
|
+
# Comment must use `#` (valid PowerShell line comment)
|
|
249
|
+
assert "# expires:" in result.stdout
|
|
250
|
+
# Must NOT contain bash `export` syntax
|
|
251
|
+
assert "export AWS_" not in result.stdout
|
|
252
|
+
|
|
253
|
+
@respx.mock
|
|
254
|
+
def test_dynamic_generate_cmd_shape(self, env_overrides):
|
|
255
|
+
"""cmd.exe format: set VAR=val — for `for /f` extraction."""
|
|
256
|
+
respx.post(_url("/dynamic/ec2-readonly/generate")).mock(
|
|
257
|
+
return_value=httpx.Response(201, json={"secret": {
|
|
258
|
+
"accessKeyId": "ASIA-FAKE",
|
|
259
|
+
"secretAccessKey": "SAK-FAKE",
|
|
260
|
+
"sessionToken": "TOK-FAKE",
|
|
261
|
+
"expiration": "2026-01-01T00:00:00Z",
|
|
262
|
+
}})
|
|
263
|
+
)
|
|
264
|
+
result = CliRunner().invoke(
|
|
265
|
+
secrets_app,
|
|
266
|
+
["dynamic", "generate", "lab/aws/ec2-readonly", "--format", "cmd"],
|
|
267
|
+
)
|
|
268
|
+
assert result.exit_code == 0
|
|
269
|
+
assert "set AWS_ACCESS_KEY_ID=ASIA-FAKE" in result.stdout
|
|
270
|
+
assert "set AWS_SECRET_ACCESS_KEY=SAK-FAKE" in result.stdout
|
|
271
|
+
# cmd.exe uses REM, not #, for comments
|
|
272
|
+
assert "REM expires:" in result.stdout
|
|
273
|
+
assert "# expires" not in result.stdout
|
|
274
|
+
|
|
229
275
|
|
|
230
276
|
class TestLeases:
|
|
231
277
|
@respx.mock
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|