bt-cli 0.5.0__tar.gz → 0.6.0__tar.gz

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