bt-cli 0.4.27__tar.gz → 0.4.29__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.
Files changed (174) hide show
  1. {bt_cli-0.4.27 → bt_cli-0.4.29}/CLAUDE.md +1 -1
  2. {bt_cli-0.4.27 → bt_cli-0.4.29}/PKG-INFO +1 -1
  3. {bt_cli-0.4.27 → bt_cli-0.4.29}/pyproject.toml +1 -1
  4. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/__init__.py +1 -1
  5. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/commands/configure.py +218 -2
  6. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pra/client/base.py +12 -4
  7. {bt_cli-0.4.27 → bt_cli-0.4.29}/.claude/skills/bt/SKILL.md +0 -0
  8. {bt_cli-0.4.27 → bt_cli-0.4.29}/.claude/skills/entitle/SKILL.md +0 -0
  9. {bt_cli-0.4.27 → bt_cli-0.4.29}/.claude/skills/epmw/SKILL.md +0 -0
  10. {bt_cli-0.4.27 → bt_cli-0.4.29}/.claude/skills/pra/SKILL.md +0 -0
  11. {bt_cli-0.4.27 → bt_cli-0.4.29}/.claude/skills/pws/SKILL.md +0 -0
  12. {bt_cli-0.4.27 → bt_cli-0.4.29}/.env.example +0 -0
  13. {bt_cli-0.4.27 → bt_cli-0.4.29}/.github/workflows/ci.yml +0 -0
  14. {bt_cli-0.4.27 → bt_cli-0.4.29}/.github/workflows/release.yml +0 -0
  15. {bt_cli-0.4.27 → bt_cli-0.4.29}/.gitignore +0 -0
  16. {bt_cli-0.4.27 → bt_cli-0.4.29}/README.md +0 -0
  17. {bt_cli-0.4.27 → bt_cli-0.4.29}/assets/cli-help.png +0 -0
  18. {bt_cli-0.4.27 → bt_cli-0.4.29}/assets/cli-output.png +0 -0
  19. {bt_cli-0.4.27 → bt_cli-0.4.29}/bt-cli.spec +0 -0
  20. {bt_cli-0.4.27 → bt_cli-0.4.29}/bt_entry.py +0 -0
  21. {bt_cli-0.4.27 → bt_cli-0.4.29}/scripts/bt_entry.py +0 -0
  22. {bt_cli-0.4.27 → bt_cli-0.4.29}/scripts/sync-package-data.sh +0 -0
  23. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/cli.py +0 -0
  24. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/commands/__init__.py +0 -0
  25. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/commands/learn.py +0 -0
  26. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/commands/quick.py +0 -0
  27. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/core/__init__.py +0 -0
  28. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/core/auth.py +0 -0
  29. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/core/client.py +0 -0
  30. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/core/config.py +0 -0
  31. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/core/config_file.py +0 -0
  32. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/core/csv_utils.py +0 -0
  33. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/core/errors.py +0 -0
  34. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/core/output.py +0 -0
  35. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/core/prompts.py +0 -0
  36. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/core/rest_debug.py +0 -0
  37. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/data/CLAUDE.md +0 -0
  38. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/data/__init__.py +0 -0
  39. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/data/skills/bt/SKILL.md +0 -0
  40. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/data/skills/entitle/SKILL.md +0 -0
  41. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/data/skills/epmw/SKILL.md +0 -0
  42. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/data/skills/pra/SKILL.md +0 -0
  43. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/data/skills/pws/SKILL.md +0 -0
  44. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/entitle/__init__.py +0 -0
  45. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/entitle/client/__init__.py +0 -0
  46. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/entitle/client/base.py +0 -0
  47. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/__init__.py +0 -0
  48. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/accounts.py +0 -0
  49. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/applications.py +0 -0
  50. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/auth.py +0 -0
  51. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/bundles.py +0 -0
  52. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/integrations.py +0 -0
  53. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/permissions.py +0 -0
  54. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/policies.py +0 -0
  55. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/resources.py +0 -0
  56. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/roles.py +0 -0
  57. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/users.py +0 -0
  58. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/workflows.py +0 -0
  59. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/entitle/models/__init__.py +0 -0
  60. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/entitle/models/bundle.py +0 -0
  61. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/entitle/models/common.py +0 -0
  62. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/entitle/models/integration.py +0 -0
  63. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/entitle/models/permission.py +0 -0
  64. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/entitle/models/policy.py +0 -0
  65. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/entitle/models/resource.py +0 -0
  66. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/entitle/models/role.py +0 -0
  67. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/entitle/models/user.py +0 -0
  68. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/entitle/models/workflow.py +0 -0
  69. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/epmw/__init__.py +0 -0
  70. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/epmw/client/__init__.py +0 -0
  71. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/epmw/client/base.py +0 -0
  72. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/__init__.py +0 -0
  73. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/audits.py +0 -0
  74. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/auth.py +0 -0
  75. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/computers.py +0 -0
  76. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/events.py +0 -0
  77. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/groups.py +0 -0
  78. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/policies.py +0 -0
  79. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/quick.py +0 -0
  80. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/requests.py +0 -0
  81. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/roles.py +0 -0
  82. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/tasks.py +0 -0
  83. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/users.py +0 -0
  84. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/epmw/models/__init__.py +0 -0
  85. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pra/__init__.py +0 -0
  86. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pra/client/__init__.py +0 -0
  87. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pra/commands/__init__.py +0 -0
  88. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pra/commands/auth.py +0 -0
  89. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pra/commands/import_export.py +0 -0
  90. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pra/commands/jump_clients.py +0 -0
  91. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pra/commands/jump_groups.py +0 -0
  92. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pra/commands/jump_items.py +0 -0
  93. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pra/commands/jumpoints.py +0 -0
  94. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pra/commands/policies.py +0 -0
  95. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pra/commands/quick.py +0 -0
  96. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pra/commands/teams.py +0 -0
  97. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pra/commands/users.py +0 -0
  98. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pra/commands/vault.py +0 -0
  99. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pra/models/__init__.py +0 -0
  100. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pra/models/common.py +0 -0
  101. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pra/models/jump_client.py +0 -0
  102. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pra/models/jump_group.py +0 -0
  103. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pra/models/jump_item.py +0 -0
  104. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pra/models/jumpoint.py +0 -0
  105. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pra/models/team.py +0 -0
  106. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pra/models/user.py +0 -0
  107. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pra/models/vault.py +0 -0
  108. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pws/__init__.py +0 -0
  109. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pws/client/__init__.py +0 -0
  110. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pws/client/base.py +0 -0
  111. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pws/client/beyondinsight.py +0 -0
  112. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pws/client/passwordsafe.py +0 -0
  113. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pws/commands/__init__.py +0 -0
  114. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pws/commands/accounts.py +0 -0
  115. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pws/commands/assets.py +0 -0
  116. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pws/commands/attributes.py +0 -0
  117. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pws/commands/auth.py +0 -0
  118. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pws/commands/clouds.py +0 -0
  119. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pws/commands/config.py +0 -0
  120. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pws/commands/credentials.py +0 -0
  121. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pws/commands/databases.py +0 -0
  122. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pws/commands/directories.py +0 -0
  123. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pws/commands/functional.py +0 -0
  124. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pws/commands/import_export.py +0 -0
  125. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pws/commands/platforms.py +0 -0
  126. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pws/commands/quick.py +0 -0
  127. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pws/commands/search.py +0 -0
  128. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pws/commands/secrets.py +0 -0
  129. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pws/commands/systems.py +0 -0
  130. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pws/commands/users.py +0 -0
  131. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pws/commands/workgroups.py +0 -0
  132. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pws/config.py +0 -0
  133. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pws/models/__init__.py +0 -0
  134. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pws/models/account.py +0 -0
  135. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pws/models/asset.py +0 -0
  136. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pws/models/common.py +0 -0
  137. {bt_cli-0.4.27 → bt_cli-0.4.29}/src/bt_cli/pws/models/system.py +0 -0
  138. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/__init__.py +0 -0
  139. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/conftest.py +0 -0
  140. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/core/__init__.py +0 -0
  141. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/core/test_auth.py +0 -0
  142. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/core/test_config.py +0 -0
  143. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/core/test_errors.py +0 -0
  144. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/core/test_rest_debug.py +0 -0
  145. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/entitle/__init__.py +0 -0
  146. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/entitle/test_client.py +0 -0
  147. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/entitle/test_commands.py +0 -0
  148. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/entitle-smoke-test.sh +0 -0
  149. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/epmw/__init__.py +0 -0
  150. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/epmw/test_client.py +0 -0
  151. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/epmw/test_commands.py +0 -0
  152. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/epmw-quick-test-plan.md +0 -0
  153. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/fixtures/__init__.py +0 -0
  154. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/fixtures/responses.py +0 -0
  155. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/integration/__init__.py +0 -0
  156. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/integration/conftest.py +0 -0
  157. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/integration/helpers.py +0 -0
  158. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/integration/test_entitle_integration.py +0 -0
  159. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/integration/test_epmw_integration.py +0 -0
  160. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/integration/test_epmw_lifecycle.py +0 -0
  161. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/integration/test_pra_integration.py +0 -0
  162. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/integration/test_pra_lifecycle.py +0 -0
  163. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/integration/test_pws_integration.py +0 -0
  164. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/integration/test_pws_lifecycle.py +0 -0
  165. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/pra/__init__.py +0 -0
  166. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/pra/test_client.py +0 -0
  167. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/pra/test_commands.py +0 -0
  168. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/pra-smoke-test.sh +0 -0
  169. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/pra-test-plan.md +0 -0
  170. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/pws/__init__.py +0 -0
  171. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/pws/test_client.py +0 -0
  172. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/pws/test_commands.py +0 -0
  173. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/pws-quick-test-plan.md +0 -0
  174. {bt_cli-0.4.27 → bt_cli-0.4.29}/tests/pws-smoke-test.sh +0 -0
@@ -1,6 +1,6 @@
1
1
  # BT-CLI
2
2
 
3
- BeyondTrust Platform CLI for Password Safe, Entitle, PRA, and EPM Windows. **Version: 0.4.27**
3
+ BeyondTrust Platform CLI for Password Safe, Entitle, PRA, and EPM Windows. **Version: 0.4.29**
4
4
 
5
5
  ## Setup
6
6
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bt-cli
3
- Version: 0.4.27
3
+ Version: 0.4.29
4
4
  Summary: BeyondTrust Platform CLI (unofficial) - Password Safe, Entitle, PRA, EPM
5
5
  Author-email: Dave Grendysz <dgrendysz@beyondtrust.com>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "bt-cli"
7
- version = "0.4.27"
7
+ version = "0.4.29"
8
8
  description = "BeyondTrust Platform CLI (unofficial) - Password Safe, Entitle, PRA, EPM"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -1,3 +1,3 @@
1
1
  """BeyondTrust Unified Admin CLI."""
2
2
 
3
- __version__ = "0.4.27"
3
+ __version__ = "0.4.29"
@@ -298,11 +298,21 @@ def show_config(
298
298
  profile: Optional[str] = typer.Option(None, "--profile", help="Profile to show"),
299
299
  show_secrets: bool = typer.Option(False, "--show-secrets", help="Show secret values"),
300
300
  ) -> None:
301
- """Show current configuration."""
301
+ """Show configuration from config file.
302
+
303
+ Note: This only shows profiles saved to ~/.bt-cli/config.yaml.
304
+ If you're using environment variables or .env file, use:
305
+
306
+ bt configure effective
307
+
308
+ to see the actual configuration in use.
309
+ """
302
310
  config = load_config_file()
303
311
 
304
312
  if not config.profiles:
305
- print_warning("No configuration found. Run 'bt configure' to set up.")
313
+ print_warning("No profiles in config file. Run 'bt configure' to set up.")
314
+ console.print("\n[dim]Tip: If using .env or environment variables, run:[/dim]")
315
+ console.print("[cyan] bt configure effective[/cyan]")
306
316
  raise typer.Exit(0)
307
317
 
308
318
  profiles_to_show = [profile] if profile else config.list_profiles()
@@ -413,3 +423,209 @@ def show_path() -> None:
413
423
  console.print("[green]Config file exists[/green]")
414
424
  else:
415
425
  console.print("[yellow]Config file does not exist yet[/yellow]")
426
+
427
+
428
+ @app.command("import-env")
429
+ def import_from_env(
430
+ profile: str = typer.Option("default", "--profile", "-p", help="Profile name to save as"),
431
+ force: bool = typer.Option(False, "--force", "-f", help="Overwrite existing profile"),
432
+ ) -> None:
433
+ """Import configuration from environment variables into a profile.
434
+
435
+ This saves the current BT_* environment variables (including .env file)
436
+ into a named profile in the config file. Useful for:
437
+
438
+ - Converting .env setup to profile-based config
439
+ - Creating profiles from existing environment
440
+ - Backing up current config to file
441
+
442
+ Example:
443
+ bt configure import-env --profile production
444
+ """
445
+ import os
446
+ from dotenv import load_dotenv, find_dotenv
447
+ from rich.prompt import Confirm
448
+
449
+ # Load .env if present
450
+ env_file = find_dotenv()
451
+ if env_file:
452
+ load_dotenv(env_file)
453
+ console.print(f"[dim]Loaded .env from: {env_file}[/dim]\n")
454
+
455
+ config = load_config_file()
456
+
457
+ # Check if profile exists
458
+ if profile in config.profiles and not force:
459
+ if not Confirm.ask(f"Profile '{profile}' exists. Overwrite?", default=False):
460
+ print_info("Cancelled")
461
+ raise typer.Exit(0)
462
+
463
+ # Product environment variable mappings
464
+ env_mappings = {
465
+ "pws": {
466
+ "api_url": "BT_PWS_API_URL",
467
+ "api_key": "BT_PWS_API_KEY",
468
+ "client_id": "BT_PWS_CLIENT_ID",
469
+ "client_secret": "BT_PWS_CLIENT_SECRET",
470
+ "run_as": "BT_PWS_RUN_AS",
471
+ "verify_ssl": "BT_PWS_VERIFY_SSL",
472
+ "timeout": "BT_PWS_TIMEOUT",
473
+ },
474
+ "pra": {
475
+ "api_url": "BT_PRA_API_URL",
476
+ "client_id": "BT_PRA_CLIENT_ID",
477
+ "client_secret": "BT_PRA_CLIENT_SECRET",
478
+ "verify_ssl": "BT_PRA_VERIFY_SSL",
479
+ "timeout": "BT_PRA_TIMEOUT",
480
+ },
481
+ "entitle": {
482
+ "api_url": "BT_ENTITLE_API_URL",
483
+ "api_key": "BT_ENTITLE_API_KEY",
484
+ "verify_ssl": "BT_ENTITLE_VERIFY_SSL",
485
+ "timeout": "BT_ENTITLE_TIMEOUT",
486
+ },
487
+ "epmw": {
488
+ "api_url": "BT_EPM_API_URL",
489
+ "client_id": "BT_EPM_CLIENT_ID",
490
+ "client_secret": "BT_EPM_CLIENT_SECRET",
491
+ "verify_ssl": "BT_EPM_VERIFY_SSL",
492
+ "timeout": "BT_EPM_TIMEOUT",
493
+ },
494
+ }
495
+
496
+ imported = []
497
+ for product, env_vars in env_mappings.items():
498
+ product_config = {}
499
+ for setting, env_var in env_vars.items():
500
+ value = os.getenv(env_var)
501
+ if value:
502
+ # Convert types
503
+ if setting == "verify_ssl":
504
+ product_config[setting] = value.lower() not in ("false", "0", "no")
505
+ elif setting == "timeout":
506
+ try:
507
+ product_config[setting] = float(value)
508
+ except ValueError:
509
+ product_config[setting] = 30.0
510
+ else:
511
+ product_config[setting] = value
512
+
513
+ if product_config.get("api_url"):
514
+ # Infer auth_method for PWS
515
+ if product == "pws":
516
+ if product_config.get("api_key"):
517
+ product_config["auth_method"] = "apikey"
518
+ elif product_config.get("client_id"):
519
+ product_config["auth_method"] = "oauth"
520
+
521
+ config.set_product_config(product, product_config, profile)
522
+ imported.append(product)
523
+
524
+ if imported:
525
+ if not config.default_profile or profile == "default":
526
+ config.default_profile = profile
527
+ save_config_file(config)
528
+ print_success(f"Imported {', '.join(imported)} into profile '{profile}'")
529
+ console.print(f"[dim]Config saved to: {CONFIG_FILE}[/dim]")
530
+ else:
531
+ print_warning("No configuration found in environment variables")
532
+
533
+
534
+ @app.command("effective")
535
+ def show_effective_config(
536
+ show_secrets: bool = typer.Option(False, "--show-secrets", help="Show secret values"),
537
+ ) -> None:
538
+ """Show effective configuration from all sources.
539
+
540
+ Shows what configuration is actually in use, combining:
541
+ - Environment variables (BT_PWS_*, BT_PRA_*, etc.)
542
+ - .env file (if present)
543
+ - Config file profiles (~/.bt-cli/config.yaml)
544
+
545
+ This is useful for debugging why the CLI connects successfully
546
+ but 'bt configure show' appears empty.
547
+ """
548
+ import os
549
+ from dotenv import load_dotenv, find_dotenv
550
+
551
+ # Load .env if present
552
+ env_file = find_dotenv()
553
+ if env_file:
554
+ load_dotenv(env_file)
555
+ console.print(f"[dim]Loaded .env from: {env_file}[/dim]\n")
556
+
557
+ def mask_secret(key: str, value: str) -> str:
558
+ if not value:
559
+ return "[dim]not set[/dim]"
560
+ if not show_secrets and any(s in key.lower() for s in ["secret", "key", "password"]):
561
+ return "****" + value[-4:] if len(value) > 4 else "****"
562
+ return value
563
+
564
+ # Product environment variable mappings
565
+ products = {
566
+ "Password Safe": {
567
+ "api_url": "BT_PWS_API_URL",
568
+ "api_key": "BT_PWS_API_KEY",
569
+ "client_id": "BT_PWS_CLIENT_ID",
570
+ "client_secret": "BT_PWS_CLIENT_SECRET",
571
+ "run_as": "BT_PWS_RUN_AS",
572
+ "verify_ssl": "BT_PWS_VERIFY_SSL",
573
+ "timeout": "BT_PWS_TIMEOUT",
574
+ },
575
+ "PRA": {
576
+ "api_url": "BT_PRA_API_URL",
577
+ "client_id": "BT_PRA_CLIENT_ID",
578
+ "client_secret": "BT_PRA_CLIENT_SECRET",
579
+ "verify_ssl": "BT_PRA_VERIFY_SSL",
580
+ "timeout": "BT_PRA_TIMEOUT",
581
+ },
582
+ "Entitle": {
583
+ "api_url": "BT_ENTITLE_API_URL",
584
+ "api_key": "BT_ENTITLE_API_KEY",
585
+ "verify_ssl": "BT_ENTITLE_VERIFY_SSL",
586
+ "timeout": "BT_ENTITLE_TIMEOUT",
587
+ },
588
+ "EPM Windows": {
589
+ "api_url": "BT_EPM_API_URL",
590
+ "client_id": "BT_EPM_CLIENT_ID",
591
+ "client_secret": "BT_EPM_CLIENT_SECRET",
592
+ "verify_ssl": "BT_EPM_VERIFY_SSL",
593
+ "timeout": "BT_EPM_TIMEOUT",
594
+ },
595
+ }
596
+
597
+ # Check active profile
598
+ active_profile = os.getenv("BT_PROFILE", "default")
599
+ console.print(f"[bold]Active Profile:[/bold] {active_profile}\n")
600
+
601
+ # Show effective config for each product
602
+ for product_name, env_vars in products.items():
603
+ table = Table(title=product_name, show_header=True, title_style="bold cyan")
604
+ table.add_column("Setting", style="green")
605
+ table.add_column("Env Var", style="dim")
606
+ table.add_column("Value")
607
+ table.add_column("Source", style="dim")
608
+
609
+ has_config = False
610
+ for setting, env_var in env_vars.items():
611
+ value = os.getenv(env_var, "")
612
+ if value:
613
+ has_config = True
614
+ source = ".env" if env_file else "environment"
615
+ table.add_row(setting, env_var, mask_secret(setting, value), source)
616
+
617
+ if has_config:
618
+ console.print(table)
619
+ console.print()
620
+ else:
621
+ console.print(f"[dim]{product_name}: not configured[/dim]\n")
622
+
623
+ # Also show config file info
624
+ config = load_config_file()
625
+ if config.profiles:
626
+ console.print("[bold]Config File Profiles:[/bold]")
627
+ for profile_name in config.list_profiles():
628
+ products_list = list(config.profiles[profile_name].keys())
629
+ is_default = " (default)" if profile_name == config.default_profile else ""
630
+ console.print(f" {profile_name}{is_default}: {', '.join(products_list)}")
631
+ console.print(f"\n[dim]Note: Environment variables override config file settings[/dim]")
@@ -489,19 +489,27 @@ class PRAClient:
489
489
  name: Optional[str] = None,
490
490
  hostname: Optional[str] = None,
491
491
  ) -> List[Dict[str, Any]]:
492
- """List Protocol Tunnel Jump items (TCP, MSSQL, K8s) with optional filters."""
492
+ """List Protocol Tunnel Jump items (TCP, MSSQL, K8s) with optional filters.
493
+
494
+ Note: tunnel_type is filtered client-side as the API doesn't support it.
495
+ """
493
496
  params = {}
494
497
  if jump_group_id:
495
498
  params["jump_group_id"] = jump_group_id
496
- if tunnel_type:
497
- params["tunnel_type"] = tunnel_type
498
499
  if tag:
499
500
  params["tag"] = tag
500
501
  if name:
501
502
  params["name"] = name
502
503
  if hostname:
503
504
  params["hostname"] = hostname
504
- return self.get_paginated("/jump-item/protocol-tunnel-jump", params)
505
+
506
+ items = self.get_paginated("/jump-item/protocol-tunnel-jump", params)
507
+
508
+ # Filter tunnel_type client-side (API doesn't support this filter)
509
+ if tunnel_type:
510
+ items = [i for i in items if i.get("tunnel_type") == tunnel_type]
511
+
512
+ return items
505
513
 
506
514
  def get_protocol_tunnel(self, item_id: int) -> Dict[str, Any]:
507
515
  """Get a Protocol Tunnel Jump item."""
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes