vgs-cli 1.36.0.dev3__py3-none-any.whl → 1.37.0.dev1__py3-none-any.whl

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 (49) hide show
  1. {vgs_cli-1.36.0.dev3.data → vgs_cli-1.37.0.dev1.data}/data/vgscli/theme.tcss +18 -0
  2. {vgs_cli-1.36.0.dev3.dist-info → vgs_cli-1.37.0.dev1.dist-info}/METADATA +17 -4
  3. {vgs_cli-1.36.0.dev3.dist-info → vgs_cli-1.37.0.dev1.dist-info}/RECORD +48 -44
  4. vgscli/_version.py +1 -1
  5. vgscli/cert_manager_api.py +1 -0
  6. vgscli/cli/commands/certificate.py +229 -9
  7. vgscli/console/app.py +532 -359
  8. vgscli/console/backend.py +125 -1
  9. vgscli/console/capability_screen.py +7 -13
  10. vgscli/console/commands.py +1 -2
  11. vgscli/console/domain_create_screen.py +253 -0
  12. vgscli/console/domain_delete_screen.py +143 -0
  13. vgscli/console/domain_screen.py +137 -0
  14. vgscli/console/mutation_screen.py +32 -116
  15. vgscli/console/tenant_onboarding_screen.py +5 -53
  16. vgscli/console/theme.tcss +18 -0
  17. vgscli/console/workflows/forms.py +2 -32
  18. vgscli/console/workflows/mutation.py +3 -52
  19. vgscli/console/workflows/routes.py +3 -38
  20. vgscli/console/workflows/tenant.py +11 -107
  21. vgscli/operations/certificates.py +228 -0
  22. vgscli/operations/forms.py +0 -11
  23. vgscli/operations/models.py +11 -0
  24. vgscli/operations/routes.py +0 -27
  25. vgscli/personalization_api.py +48 -0
  26. vgscli/recovery_journal.py +0 -158
  27. {vgs_cli-1.36.0.dev3.data → vgs_cli-1.37.0.dev1.data}/data/vgscli/collect-form-api-schema.yaml +0 -0
  28. {vgs_cli-1.36.0.dev3.data → vgs_cli-1.37.0.dev1.data}/data/vgscli/collect-form-schema.yaml +0 -0
  29. {vgs_cli-1.36.0.dev3.data → vgs_cli-1.37.0.dev1.data}/data/vgscli/console-route-schema.yaml +0 -0
  30. {vgs_cli-1.36.0.dev3.data → vgs_cli-1.37.0.dev1.data}/data/vgscli/credentials-admin.yaml +0 -0
  31. {vgs_cli-1.36.0.dev3.data → vgs_cli-1.37.0.dev1.data}/data/vgscli/form-template.yaml +0 -0
  32. {vgs_cli-1.36.0.dev3.data → vgs_cli-1.37.0.dev1.data}/data/vgscli/http-route-template.yaml +0 -0
  33. {vgs_cli-1.36.0.dev3.data → vgs_cli-1.37.0.dev1.data}/data/vgscli/notification-integration-schema.yaml +0 -0
  34. {vgs_cli-1.36.0.dev3.data → vgs_cli-1.37.0.dev1.data}/data/vgscli/notification-template.yaml +0 -0
  35. {vgs_cli-1.36.0.dev3.data → vgs_cli-1.37.0.dev1.data}/data/vgscli/public-credential-collect.yaml +0 -0
  36. {vgs_cli-1.36.0.dev3.data → vgs_cli-1.37.0.dev1.data}/data/vgscli/read-credentials-no-pci.yaml +0 -0
  37. {vgs_cli-1.36.0.dev3.data → vgs_cli-1.37.0.dev1.data}/data/vgscli/read-credentials-with-pci.yaml +0 -0
  38. {vgs_cli-1.36.0.dev3.data → vgs_cli-1.37.0.dev1.data}/data/vgscli/service-account-schema.yaml +0 -0
  39. {vgs_cli-1.36.0.dev3.data → vgs_cli-1.37.0.dev1.data}/data/vgscli/sftp-route-template.yaml +0 -0
  40. {vgs_cli-1.36.0.dev3.data → vgs_cli-1.37.0.dev1.data}/data/vgscli/tenant-schema.yaml +0 -0
  41. {vgs_cli-1.36.0.dev3.data → vgs_cli-1.37.0.dev1.data}/data/vgscli/tenant-template.yaml +0 -0
  42. {vgs_cli-1.36.0.dev3.data → vgs_cli-1.37.0.dev1.data}/data/vgscli/vault-resources.yaml +0 -0
  43. {vgs_cli-1.36.0.dev3.data → vgs_cli-1.37.0.dev1.data}/data/vgscli/vault-schema.yaml +0 -0
  44. {vgs_cli-1.36.0.dev3.data → vgs_cli-1.37.0.dev1.data}/data/vgscli/vault-template.yaml +0 -0
  45. {vgs_cli-1.36.0.dev3.data → vgs_cli-1.37.0.dev1.data}/data/vgscli/vgs-cli.yaml +0 -0
  46. {vgs_cli-1.36.0.dev3.dist-info → vgs_cli-1.37.0.dev1.dist-info}/WHEEL +0 -0
  47. {vgs_cli-1.36.0.dev3.dist-info → vgs_cli-1.37.0.dev1.dist-info}/entry_points.txt +0 -0
  48. {vgs_cli-1.36.0.dev3.dist-info → vgs_cli-1.37.0.dev1.dist-info}/licenses/LICENSE +0 -0
  49. {vgs_cli-1.36.0.dev3.dist-info → vgs_cli-1.37.0.dev1.dist-info}/top_level.txt +0 -0
@@ -339,6 +339,24 @@ Screen.home #content-scroll {
339
339
  color: $error;
340
340
  }
341
341
 
342
+ #domain-create-options {
343
+ height: auto;
344
+ max-height: 12;
345
+ margin: 1 0;
346
+ background: $console-elevated;
347
+ border: none;
348
+ }
349
+
350
+ #domain-create-input {
351
+ height: 3;
352
+ margin: 1 0;
353
+ }
354
+
355
+ #domain-create-error {
356
+ height: auto;
357
+ color: $error;
358
+ }
359
+
342
360
  #resource-yaml {
343
361
  height: 1fr;
344
362
  min-height: 12;
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vgs-cli
3
- Version: 1.36.0.dev3
3
+ Version: 1.37.0.dev1
4
4
  Summary: VGS Client
5
5
  Home-page: https://github.com/verygoodsecurity/vgs-cli
6
6
  Author: Very Good Security
@@ -176,8 +176,8 @@ access. The CLI masks generated webhook secrets in its output.
176
176
 
177
177
  | Command | Purpose |
178
178
  | --- | --- |
179
- | `vgs generate route --protocol http` | Generate an HTTP route template. |
180
- | `vgs generate route --protocol sftp` | Generate an SFTP route template. |
179
+ | `vgs generate route --protocol http > http-route.yaml` | Generate an HTTP route template. |
180
+ | `vgs generate route --protocol sftp > sftp-route.yaml` | Generate an SFTP route template. |
181
181
  | `vgs get routes -T <TENANT_ID>` | List tenant routes. |
182
182
  | `vgs apply routes -T <TENANT_ID> -f <FILE>` | Apply tenant routes. |
183
183
  | `vgs delete routes -T <TENANT_ID> <ROUTE_ID>` | Delete one tenant route. |
@@ -198,10 +198,23 @@ access. The CLI masks generated webhook secrets in its output.
198
198
  | Command | Purpose |
199
199
  | --- | --- |
200
200
  | `vgs get access-credentials -T <TENANT_ID>` | List tenant access credentials. |
201
- | `vgs generate access-credentials -T <TENANT_ID>` | Generate tenant access credentials. |
201
+ | `vgs generate access-credentials -T <TENANT_ID>` | Generate tenant access credentials. Capture the output securely as shown below. |
202
202
  | `vgs logs access -T <TENANT_ID>` | View tenant access logs. |
203
203
  | `vgs logs operations -T <TENANT_ID> -R <REQUEST_ID>` | View request operation logs. |
204
204
 
205
+ Access-credential generation is a live mutation that returns secret material.
206
+ Write it to a new, approved absolute path outside version control with
207
+ owner-only permissions, and do not display or inspect it in shared logs:
208
+
209
+ ```bash
210
+ (
211
+ umask 077
212
+ set -o noclobber
213
+ vgs generate access-credentials -T <TENANT_ID> \
214
+ > /absolute/secure/new-access-credentials.yaml
215
+ )
216
+ ```
217
+
205
218
  ### Service accounts
206
219
 
207
220
  Generate a service-account resource and save the YAML so you can review it
@@ -1,26 +1,26 @@
1
- vgs_cli-1.36.0.dev3.data/data/vgscli/collect-form-api-schema.yaml,sha256=THuJbLUo7LOr0c1JUo3FPJEc9Jvde59K4JjdlkVF3hw,1246
2
- vgs_cli-1.36.0.dev3.data/data/vgscli/collect-form-schema.yaml,sha256=vHAN6_Gsg14CeSL41sHEQgboYF-CHF2RaNw72aJ3W8o,1337
3
- vgs_cli-1.36.0.dev3.data/data/vgscli/console-route-schema.yaml,sha256=hKME9kKILXFWkf-zwbAAWwMoXZWnzFHG37_51SqPKKw,1305
4
- vgs_cli-1.36.0.dev3.data/data/vgscli/credentials-admin.yaml,sha256=acyLd54Cp7l2fpugfjVfYh07-MIE0BX-JVq4lHraE1s,869
5
- vgs_cli-1.36.0.dev3.data/data/vgscli/form-template.yaml,sha256=pY4gOd8jXJRohcpJYijBt4m5cPyHvEVlCBtHgs2AL8M,927
6
- vgs_cli-1.36.0.dev3.data/data/vgscli/http-route-template.yaml,sha256=vGHvBXA_6pwFtH1vVRWKiwxb4sahzuLvpqGAlavrStc,1085
7
- vgs_cli-1.36.0.dev3.data/data/vgscli/notification-integration-schema.yaml,sha256=1qHzS5ZxlhTdrDab6-qJhszwu7cpith2HleX3uAO_4E,1837
8
- vgs_cli-1.36.0.dev3.data/data/vgscli/notification-template.yaml,sha256=hr36msbrgiTjWligLHVDHMmO49QDzjTwBSLYoBw3WQE,1288
9
- vgs_cli-1.36.0.dev3.data/data/vgscli/public-credential-collect.yaml,sha256=CiorC-6TMx7M0TI8DHmoRSfVKDpOom2wIr_ilwmHQNA,696
10
- vgs_cli-1.36.0.dev3.data/data/vgscli/read-credentials-no-pci.yaml,sha256=_kWRne_ARh8v7A_jHG08gwgPG6NqZhrDRyq6L-ULs2M,769
11
- vgs_cli-1.36.0.dev3.data/data/vgscli/read-credentials-with-pci.yaml,sha256=jWXgFdcqZYisakAt9COM6cjf2-x_Q4eidDLaUh8CZOk,796
12
- vgs_cli-1.36.0.dev3.data/data/vgscli/service-account-schema.yaml,sha256=L1pjNXgnks15N1wNgf_1GmGcOvxn0nu49v7ersUjFno,1090
13
- vgs_cli-1.36.0.dev3.data/data/vgscli/sftp-route-template.yaml,sha256=zkT6lIVDgVyzLKgZ8QnyJJooy2egZk1cQthdjan_JrM,853
14
- vgs_cli-1.36.0.dev3.data/data/vgscli/tenant-schema.yaml,sha256=xqFEnG6Pcxj3EFsW8URNQexkTo6d6SQK0cMtqsAS5x8,1794
15
- vgs_cli-1.36.0.dev3.data/data/vgscli/tenant-template.yaml,sha256=ucEV4p2cZ1G43nh1Mt8dcNH4-xtrP9C1XW2LjVM5xD4,914
16
- vgs_cli-1.36.0.dev3.data/data/vgscli/theme.tcss,sha256=3J_y9kF-sb2tgiqCBZmhJeQrV3Tt9Ac1OB-VOM5r7Tw,7793
17
- vgs_cli-1.36.0.dev3.data/data/vgscli/vault-resources.yaml,sha256=95CCxQher3MBQq96bvjZviNgo1rgv_NhCtI8X-oxIpA,26335
18
- vgs_cli-1.36.0.dev3.data/data/vgscli/vault-schema.yaml,sha256=a-wW7X8RyHr-669wtOZrlxlIfeQVtx8EUfA-3vpYytk,637
19
- vgs_cli-1.36.0.dev3.data/data/vgscli/vault-template.yaml,sha256=IlDisL3H5LXUDMkhUaouKMarRdu0-pJxpTz8ij_lp_M,383
20
- vgs_cli-1.36.0.dev3.data/data/vgscli/vgs-cli.yaml,sha256=5gCjjloyepaKI6zZfDLeUEWxuRExI-dGJI9RO3omP2k,484
21
- vgs_cli-1.36.0.dev3.dist-info/licenses/LICENSE,sha256=NwSyzgDYdzv6O2ns2C6UODGI8LN1VnVe_FPTnWS4eXY,1082
1
+ vgs_cli-1.37.0.dev1.data/data/vgscli/collect-form-api-schema.yaml,sha256=THuJbLUo7LOr0c1JUo3FPJEc9Jvde59K4JjdlkVF3hw,1246
2
+ vgs_cli-1.37.0.dev1.data/data/vgscli/collect-form-schema.yaml,sha256=vHAN6_Gsg14CeSL41sHEQgboYF-CHF2RaNw72aJ3W8o,1337
3
+ vgs_cli-1.37.0.dev1.data/data/vgscli/console-route-schema.yaml,sha256=hKME9kKILXFWkf-zwbAAWwMoXZWnzFHG37_51SqPKKw,1305
4
+ vgs_cli-1.37.0.dev1.data/data/vgscli/credentials-admin.yaml,sha256=acyLd54Cp7l2fpugfjVfYh07-MIE0BX-JVq4lHraE1s,869
5
+ vgs_cli-1.37.0.dev1.data/data/vgscli/form-template.yaml,sha256=pY4gOd8jXJRohcpJYijBt4m5cPyHvEVlCBtHgs2AL8M,927
6
+ vgs_cli-1.37.0.dev1.data/data/vgscli/http-route-template.yaml,sha256=vGHvBXA_6pwFtH1vVRWKiwxb4sahzuLvpqGAlavrStc,1085
7
+ vgs_cli-1.37.0.dev1.data/data/vgscli/notification-integration-schema.yaml,sha256=1qHzS5ZxlhTdrDab6-qJhszwu7cpith2HleX3uAO_4E,1837
8
+ vgs_cli-1.37.0.dev1.data/data/vgscli/notification-template.yaml,sha256=hr36msbrgiTjWligLHVDHMmO49QDzjTwBSLYoBw3WQE,1288
9
+ vgs_cli-1.37.0.dev1.data/data/vgscli/public-credential-collect.yaml,sha256=CiorC-6TMx7M0TI8DHmoRSfVKDpOom2wIr_ilwmHQNA,696
10
+ vgs_cli-1.37.0.dev1.data/data/vgscli/read-credentials-no-pci.yaml,sha256=_kWRne_ARh8v7A_jHG08gwgPG6NqZhrDRyq6L-ULs2M,769
11
+ vgs_cli-1.37.0.dev1.data/data/vgscli/read-credentials-with-pci.yaml,sha256=jWXgFdcqZYisakAt9COM6cjf2-x_Q4eidDLaUh8CZOk,796
12
+ vgs_cli-1.37.0.dev1.data/data/vgscli/service-account-schema.yaml,sha256=L1pjNXgnks15N1wNgf_1GmGcOvxn0nu49v7ersUjFno,1090
13
+ vgs_cli-1.37.0.dev1.data/data/vgscli/sftp-route-template.yaml,sha256=zkT6lIVDgVyzLKgZ8QnyJJooy2egZk1cQthdjan_JrM,853
14
+ vgs_cli-1.37.0.dev1.data/data/vgscli/tenant-schema.yaml,sha256=xqFEnG6Pcxj3EFsW8URNQexkTo6d6SQK0cMtqsAS5x8,1794
15
+ vgs_cli-1.37.0.dev1.data/data/vgscli/tenant-template.yaml,sha256=ucEV4p2cZ1G43nh1Mt8dcNH4-xtrP9C1XW2LjVM5xD4,914
16
+ vgs_cli-1.37.0.dev1.data/data/vgscli/theme.tcss,sha256=6teLRfBJkyWzIx8y6OjB8MW_DjIujuLjj01OtfQApus,8050
17
+ vgs_cli-1.37.0.dev1.data/data/vgscli/vault-resources.yaml,sha256=95CCxQher3MBQq96bvjZviNgo1rgv_NhCtI8X-oxIpA,26335
18
+ vgs_cli-1.37.0.dev1.data/data/vgscli/vault-schema.yaml,sha256=a-wW7X8RyHr-669wtOZrlxlIfeQVtx8EUfA-3vpYytk,637
19
+ vgs_cli-1.37.0.dev1.data/data/vgscli/vault-template.yaml,sha256=IlDisL3H5LXUDMkhUaouKMarRdu0-pJxpTz8ij_lp_M,383
20
+ vgs_cli-1.37.0.dev1.data/data/vgscli/vgs-cli.yaml,sha256=5gCjjloyepaKI6zZfDLeUEWxuRExI-dGJI9RO3omP2k,484
21
+ vgs_cli-1.37.0.dev1.dist-info/licenses/LICENSE,sha256=NwSyzgDYdzv6O2ns2C6UODGI8LN1VnVe_FPTnWS4eXY,1082
22
22
  vgscli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
- vgscli/_version.py,sha256=VnNtk3D2RWEWuquUhMYrSh-jqlwTpGSMQBsMNPfLl2A,1681
23
+ vgscli/_version.py,sha256=xjR9tC_jCHh0Buw1P5a1jVVZFzFeTEVlQFb8oviRwos,1681
24
24
  vgscli/access_logs.py,sha256=G0GjlLjWiC-N6OzK6-RCvWddcVGQlLCLAcyO9pLWIOM,1928
25
25
  vgscli/audits_api.py,sha256=AaF5Go019TOerBlQzygwMeOxeW9vPPJPgxa95kttF-M,3215
26
26
  vgscli/auth.py,sha256=vdUZ12nqtefIuSHNmwCFvxoqwS3m6ZP5TqLZFNwKnSU,2104
@@ -28,7 +28,7 @@ vgscli/auth_server.py,sha256=J12vthy2FhOr4Kfyp1waxu3bFErV_kXAycE8rcBKYW8,4993
28
28
  vgscli/auth_utils.py,sha256=aC1VI0dFdFeupLS9Okz4uDz-wHhhFabqiLUg2R5vO2s,600
29
29
  vgscli/callback_server.py,sha256=yOB9YuAy1JcpMcsvuBQmF3EB1qQND-uiirAmbAjrulY,1533
30
30
  vgscli/calm_api.py,sha256=5ZZhJUCuA2E5X670L-EkB_mL2kqHPrYy-ca6WtwTacg,1384
31
- vgscli/cert_manager_api.py,sha256=b_IEIZFLY7Q4ygThWcUUR8Ynr02MXgVVe9qDFE7CQUc,1650
31
+ vgscli/cert_manager_api.py,sha256=aIRS8d_uL7skTghqMwyfGZhz-TQqFExp6J786aRwP88,1725
32
32
  vgscli/cli_progress.py,sha256=Kpc7iZo0zO6YX3WynteBELuWSYGVvqEjKLq2E5x4lnE,2520
33
33
  vgscli/cli_utils.py,sha256=uwYzRSIMlPTM1WHlaWVebrg6mIIp0VaPu5YldkMmGUw,3779
34
34
  vgscli/click_extensions.py,sha256=m-RpaPaH69m4caYbuiu0j2blxeyy8c8hA0Tvygw1Mvc,7271
@@ -45,7 +45,7 @@ vgscli/notifications.py,sha256=6D8HFDEl3X4V0V9fYZT-9nWYe2KYVahfhRLMF0pbh4I,6252
45
45
  vgscli/notifications_api.py,sha256=1EXmRb2fOJrU1QOAZ6gmq8yMjBLhNZGSVs3kRtD2Dfw,2342
46
46
  vgscli/payment_accounts_api.py,sha256=wF6K3m7nlKtPmqO9RCpmGFSXYHWtwfhXqNfgI1IGqFI,1665
47
47
  vgscli/payment_credentials_api.py,sha256=Gwz5tLIS1gRc2Hzi877_mynznNOKEGF-VoKzxqkj-mM,2169
48
- vgscli/recovery_journal.py,sha256=FwDlu52YLvVRaQSqKX_xyUx48DRyez6mGOtTFbeu2b0,5485
48
+ vgscli/personalization_api.py,sha256=mtbtJYX9pKG5CC7CBSiOfs6O1K8UOpergs6kAKUWaYI,1415
49
49
  vgscli/secure_store.py,sha256=wRLQv6qrTp1PJkb5N1zSmv2bA5NSJjEhqMNMFMoSbiY,3625
50
50
  vgscli/telemetry.py,sha256=BFkAe0Bxm96xiffIOsfPY6Q6Lv5xueJBIwGfLmctXRE,25755
51
51
  vgscli/tenant_configuration.py,sha256=mX6DUFNOr8Rnppzpw6SMV_FADLWm8w543_jYvipOxdE,6404
@@ -58,7 +58,7 @@ vgscli/vgs.py,sha256=pciuwbJGV0i-4HhpirTfyqa8JTdM12Zrcm8ulHD-kN0,7395
58
58
  vgscli/cli/__init__.py,sha256=da9LPKYdnal26ntEP22PNn-dZYBbsNkP7tzOwzD6kY4,3915
59
59
  vgscli/cli/commands/__init__.py,sha256=8ptc9-Vzdx0HU3ZeMcKERYjmJyuB5IMjBSF3Igx5yQ4,206
60
60
  vgscli/cli/commands/apply.py,sha256=_BKC1cRLbDGF1T05UEnqTGLKllfGYY6Piw6qr0YJYTU,26193
61
- vgscli/cli/commands/certificate.py,sha256=cy8oRiEkUYfFExCG5GdjYqEJ91rCgA6hy98cpHkorHM,22994
61
+ vgscli/cli/commands/certificate.py,sha256=JjZFLvfMKeAL65s-y7DwtqpkTrmGKJ84ywdZyVT5ajQ,30038
62
62
  vgscli/cli/commands/delete.py,sha256=6cfYVczMmXo8nv6yXRsHP6Na8fsJJsPovfos_9JPTxw,4080
63
63
  vgscli/cli/commands/generate.py,sha256=6SkeXN7lyzllezjYliWQ_CUncMWbDFX1Jx_1vlwDCh8,5512
64
64
  vgscli/cli/commands/get.py,sha256=EuFeEw0oLHht9b0IbWwkF2gxABbaGKcKxCEingK5MPw,9790
@@ -66,34 +66,38 @@ vgscli/cli/types/__init__.py,sha256=a-P-SoGHpLzMg7CL1hhg5x_nf6sHq0qAuGm_AtIITmw,
66
66
  vgscli/cli/types/resource_id.py,sha256=7JILR-KjoVGQDHB40tXJfTcU53iR8wM9Zr24fY5le3o,1172
67
67
  vgscli/cli/types/variable.py,sha256=IVcszPoWmTjeo_evDsLN06LuUZGTLL-wcZCVfBNBP8I,414
68
68
  vgscli/console/__init__.py,sha256=X48mjIkHuvVqtCrsN4vJ7CubJrL4xAE678jm1AFSm1o,44
69
- vgscli/console/app.py,sha256=WqYlMesMbN5GDqO9Iv4k_j80QN2xyfxbs2PLm6SpePE,116429
69
+ vgscli/console/app.py,sha256=r72EeHI57VJy1J9OyoYbRWcUW2o9cN5t-PC6Dfbe5UE,122762
70
70
  vgscli/console/auth.py,sha256=PpIvuFCxTLSHiDmmOSU67nbsdru78pT4cmaD_TmBbU0,1517
71
- vgscli/console/backend.py,sha256=DHelXVKwySaVQUgU6qMpmoKmrzgKf1cqttIAnVU-xvw,13010
71
+ vgscli/console/backend.py,sha256=HY8g87bg_aRiQyDE3JzRg8JFhlWok6H-JSs_dm7cN-M,17866
72
72
  vgscli/console/bootstrap.py,sha256=R75enSa2MrAJ4jWl-IDvpansglIa02R28N7CfKCh3Vs,1121
73
- vgscli/console/capability_screen.py,sha256=3hQdHB2imt6UnlHMbw3U1fkqIIti5HMVXJiVc8Yj9Tg,7578
74
- vgscli/console/commands.py,sha256=3sAWTmNCiRby37bQ9edpyp6CR_-VVKwyP3RfVT2VTJY,3946
73
+ vgscli/console/capability_screen.py,sha256=QiXPDQlzRW250-yYq2XqKbrIhezE_Gf_gfe85_iRGU0,7324
74
+ vgscli/console/commands.py,sha256=GF_7DzZIAJzaGTZqODV6oErIF5Wrtp2jCJAqXhMTUEI,3867
75
75
  vgscli/console/context.py,sha256=TgDgsqt52pbSeLsTZ-VX6PHuQFJTSUSrl4y2I36tquk,1719
76
+ vgscli/console/domain_create_screen.py,sha256=usrqHea97RmjRG11u-2ro5cxySEEF7EVDFUoll0TYik,10438
77
+ vgscli/console/domain_delete_screen.py,sha256=-0RH2tnTXCQiLVKrodfCqQ_lBbBioyAaWeI-Hly0YLc,5684
78
+ vgscli/console/domain_screen.py,sha256=GSHE0D5MqYXmYd0KbvXVVRU1Eaeq2j9J83B-1zulb4Q,5579
76
79
  vgscli/console/form_editor.py,sha256=o5u4aUWWOOaCAyI7Djco0yLR4po2bHLapyVwbMbHFNk,5268
77
80
  vgscli/console/intro.py,sha256=cZ93gvP0czRpoGbu9HB1QGrJYJ6DMtvX_EVlTg9DEvQ,5348
78
- vgscli/console/mutation_screen.py,sha256=21xwQNZuWnAOidzYC4konDMSPQdcNf1CfiHY04pp1eM,28417
81
+ vgscli/console/mutation_screen.py,sha256=7uhUS7t-53i-bTa9YKKHnWfJV6c2oQpv7YNRqXF1h9c,24819
79
82
  vgscli/console/responsive.py,sha256=C1jVLg_kunp8maeQl9W2KumDuKWFev2iL-ZXiQvyN4w,688
80
- vgscli/console/tenant_onboarding_screen.py,sha256=b-nxzUL7PtB_ZJnIGEKzX8PL8eBATvROCuWLQrrvF0A,26180
81
- vgscli/console/theme.tcss,sha256=3J_y9kF-sb2tgiqCBZmhJeQrV3Tt9Ac1OB-VOM5r7Tw,7793
83
+ vgscli/console/tenant_onboarding_screen.py,sha256=7tiXgqkRRBdrkhQBEiJU91lopGs_LYs701RakHrxhts,24155
84
+ vgscli/console/theme.tcss,sha256=6teLRfBJkyWzIx8y6OjB8MW_DjIujuLjj01OtfQApus,8050
82
85
  vgscli/console/workflows/__init__.py,sha256=NGtIiPpn-y2EQKXlt40G4nLlLZ1y9se_KewknReDiKI,212
83
- vgscli/console/workflows/forms.py,sha256=ob7GpX8Ig7h6WFaAzW663Lge8RVEGbtwGa4Z3N_AZj0,1310
84
- vgscli/console/workflows/mutation.py,sha256=mkjrWnEpRGgb1SRuWs2xh37NdSCx71gsV2GTpZFR7pg,9195
85
- vgscli/console/workflows/routes.py,sha256=kliVIEj9KzznRZ5KRkA91vzsihnq9UpCv3k_2zavmXw,1499
86
- vgscli/console/workflows/tenant.py,sha256=8sdsaKKPiThQLhwG123g6F8f4xUWdYZzJcsVewpFdx8,7997
86
+ vgscli/console/workflows/forms.py,sha256=_sxRraE_jVg67chsYA4txdcBZPqjxReIPQy5XjqVJVE,201
87
+ vgscli/console/workflows/mutation.py,sha256=1fdkKTrj-sg-IIAVVuPNLHIU_kQCwnWhDFnY9evxCFQ,6956
88
+ vgscli/console/workflows/routes.py,sha256=Pz-wg7nkj2BACyDLpS-52TQnoU52LJ0rZLmOCMxdG-k,205
89
+ vgscli/console/workflows/tenant.py,sha256=dHH7iv_oaGZcSXOoSQpCc8V1OVsuGtv3ujomYXCwCKo,4167
87
90
  vgscli/operations/__init__.py,sha256=o5WOygn8wXdVcpKXqVL8kLDc0MS1jZumb1yGECiupiw,74
91
+ vgscli/operations/certificates.py,sha256=2G9-iEYzYKWQZgVZTs4JsEkGmgHBop3I30Eh_QD6BUw,7721
88
92
  vgscli/operations/context.py,sha256=jA8BToRVCx-ZCsEV05tfENuTaYGzaw0acjokuCVxpbQ,1538
89
93
  vgscli/operations/documents.py,sha256=sfHmI4uyDH1weDFkLeF4QmwDjzp0Op_XA8kYQ5RnDtU,827
90
94
  vgscli/operations/errors.py,sha256=4MQN71x7COJSAz7wEYd8Wxq2D5spT8VaGM8eukMbncE,3744
91
95
  vgscli/operations/form_documents.py,sha256=IZucBFeGLCzsXS_NukA_8fmHycjDq-dpC_I8kj8ZnXU,3695
92
- vgscli/operations/forms.py,sha256=cN5oJLvPDDNqoiYP8d-N8q5-kJ8Awo53YoRSlWikrsg,5585
96
+ vgscli/operations/forms.py,sha256=ocIenT2xlE-TtmrCP-q4Bfmz_uX9JnjwZzz4nkGiiJQ,5184
93
97
  vgscli/operations/logs.py,sha256=69gIjPhjjtLcoZFITUEYXnMMaRQbE5hEGsMgeNoGMfg,5956
94
- vgscli/operations/models.py,sha256=NoyAIe3iC56t8f0u77rJC5TsgnNKhO1lD3TDI9jKXi8,1396
98
+ vgscli/operations/models.py,sha256=YVpYAO7xxCMgHYItIPR5oW-GtCledBlQRC9oB5aGTy8,1618
95
99
  vgscli/operations/payment_credentials.py,sha256=b0iH68UeAdfUpR_B4Da2Wpj-lwcNsEEH11Xrvb-HPw0,10798
96
- vgscli/operations/routes.py,sha256=HgVbxYufi2Em0odqG3fM-SyBY8j_kQmUBiXwnLwRU58,8165
100
+ vgscli/operations/routes.py,sha256=oJ0EbG_M9mjXex_aBA2TNXO7XVbp7UD1jkIO2G_YyrU,7309
97
101
  vgscli/operations/tenant_details.py,sha256=vtzxYjUFyjToweKf3ZqdBMB14P87USpqNzxWW1SuL_U,3364
98
102
  vgscli/resource-templates/form-template.yaml,sha256=pY4gOd8jXJRohcpJYijBt4m5cPyHvEVlCBtHgs2AL8M,927
99
103
  vgscli/resource-templates/http-route-template.yaml,sha256=vGHvBXA_6pwFtH1vVRWKiwxb4sahzuLvpqGAlavrStc,1085
@@ -114,8 +118,8 @@ vgscli/validation-schemas/service-account-schema.yaml,sha256=L1pjNXgnks15N1wNgf_
114
118
  vgscli/validation-schemas/tenant-schema.yaml,sha256=xqFEnG6Pcxj3EFsW8URNQexkTo6d6SQK0cMtqsAS5x8,1794
115
119
  vgscli/validation-schemas/vault-resources.yaml,sha256=95CCxQher3MBQq96bvjZviNgo1rgv_NhCtI8X-oxIpA,26335
116
120
  vgscli/validation-schemas/vault-schema.yaml,sha256=a-wW7X8RyHr-669wtOZrlxlIfeQVtx8EUfA-3vpYytk,637
117
- vgs_cli-1.36.0.dev3.dist-info/METADATA,sha256=RFTdfTZri8fVGIcyZqDNzex1fpkEU5Qz8xYwfJW_Hwg,9969
118
- vgs_cli-1.36.0.dev3.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
119
- vgs_cli-1.36.0.dev3.dist-info/entry_points.txt,sha256=wCWhRQiMX4Ja6kkqJlYr8LbuiywpmXyyRAZPsau-_RY,39
120
- vgs_cli-1.36.0.dev3.dist-info/top_level.txt,sha256=gabTxCWMkl80q6ha_m-hs_1wQMfGntZcv5DEmkl8JEw,7
121
- vgs_cli-1.36.0.dev3.dist-info/RECORD,,
121
+ vgs_cli-1.37.0.dev1.dist-info/METADATA,sha256=IU_6ZwK1MoqaKvmFQkG1skQ7jVkT3UK7T3b-aqaCSlg,10422
122
+ vgs_cli-1.37.0.dev1.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
123
+ vgs_cli-1.37.0.dev1.dist-info/entry_points.txt,sha256=wCWhRQiMX4Ja6kkqJlYr8LbuiywpmXyyRAZPsau-_RY,39
124
+ vgs_cli-1.37.0.dev1.dist-info/top_level.txt,sha256=gabTxCWMkl80q6ha_m-hs_1wQMfGntZcv5DEmkl8JEw,7
125
+ vgs_cli-1.37.0.dev1.dist-info/RECORD,,
vgscli/_version.py CHANGED
@@ -6,7 +6,7 @@ from packaging.version import InvalidVersion, Version
6
6
 
7
7
  from vgscli.text import bold, green
8
8
 
9
- __version__ = "1.36.0.dev3"
9
+ __version__ = "1.37.0.dev1"
10
10
 
11
11
 
12
12
  # noinspection PyBroadException
@@ -20,6 +20,7 @@ class CertificatesResource(Resource):
20
20
  "url": "api/certificates/{}/certificate",
21
21
  },
22
22
  "create_csr": {"method": "POST", "url": "api/certificates/csr"},
23
+ "metadata": {"method": "GET", "url": "api/certificates/metadata"},
23
24
  }
24
25
 
25
26
 
@@ -10,13 +10,22 @@ from pathlib import Path
10
10
  from typing import Any
11
11
 
12
12
  import click
13
+ import requests
13
14
 
14
15
  from vgscli.auth import token_util
15
16
  from vgscli.cert_manager_api import create_cert_manager_api
16
17
  from vgscli.cli_utils import dump_camelized_yaml
17
18
  from vgscli.click_extensions import tenant_option
18
19
  from vgscli.errors import handle_errors
19
- from vgscli.telemetry import TelemetryGroup
20
+ from vgscli.operations.certificates import (
21
+ BRANDED_DOMAIN_TYPE,
22
+ COLLECT_CDN_URLS,
23
+ SDK_ENABLEABLE_STATUSES,
24
+ allowed_vgs_domains,
25
+ validate_domain_name,
26
+ )
27
+ from vgscli.personalization_api import create_personalization_api
28
+ from vgscli.telemetry import TelemetryGroup, request_headers
20
29
 
21
30
  logger = logging.getLogger(__name__)
22
31
 
@@ -231,6 +240,59 @@ def _assert_certificate_is_downloadable(
231
240
  )
232
241
 
233
242
 
243
+ def _assert_certificate_sdk_enableable(
244
+ api: Any, *, vault: str, domain_or_id: str
245
+ ) -> str:
246
+ """
247
+ Enabling for SDKs requires an issued, currently-valid branded domain
248
+ certificate. Returns the resolved domain name to enable.
249
+ """
250
+ cert_item = _resolve_certificate_metadata(
251
+ api, vault=vault, domain_or_id=domain_or_id
252
+ )
253
+
254
+ if _is_csr_resource(cert_item):
255
+ cert_id = cert_item.get("id") or domain_or_id
256
+ raise click.ClickException(
257
+ f"Cannot enable a CSR for SDKs. Target '{cert_id}' is a CSR, not an "
258
+ "issued branded domain certificate."
259
+ )
260
+
261
+ attrs = (
262
+ cert_item.get("attributes")
263
+ if isinstance(cert_item.get("attributes"), dict)
264
+ else {}
265
+ )
266
+ cert_id = cert_item.get("id") or domain_or_id
267
+ cert_type = attrs.get("type")
268
+ if (
269
+ not isinstance(cert_type, str)
270
+ or cert_type.strip().upper() != BRANDED_DOMAIN_TYPE
271
+ ):
272
+ raise click.ClickException(
273
+ f"Certificate '{cert_id}' is not a branded domain certificate. "
274
+ "Only branded domains can be enabled for SDKs."
275
+ )
276
+
277
+ try:
278
+ resolved_domain = validate_domain_name(attrs.get("domain"))
279
+ except ValueError:
280
+ raise click.ClickException(
281
+ f"Certificate '{cert_id}' has no valid hostname. "
282
+ "Only branded domains with a hostname can be enabled for SDKs."
283
+ )
284
+
285
+ status = attrs.get("status")
286
+ if status not in SDK_ENABLEABLE_STATUSES:
287
+ cert_id = cert_item.get("id") or domain_or_id
288
+ raise click.ClickException(
289
+ f"Certificate '{cert_id}' has status '{status}'. Enabling for SDKs "
290
+ "requires status VALID or RENEWAL_REQUIRED."
291
+ )
292
+
293
+ return resolved_domain
294
+
295
+
234
296
  def _looks_like_backend_500(exc: BaseException) -> bool:
235
297
  status = getattr(exc, "status", None) or getattr(exc, "status_code", None)
236
298
  if status == 500:
@@ -276,22 +338,29 @@ def _fetch_public_certificate_payload(
276
338
  raise
277
339
 
278
340
 
279
- def _get_api(ctx: click.Context, vault: str):
341
+ def _resolve_env(ctx: click.Context) -> str:
280
342
  """
281
343
  Env resolution order:
282
344
  1) ctx.obj.env (normal CLI flow)
283
345
  2) root click params (if ctx.obj isn't initialized)
284
346
  3) DEFAULT_ENV ("prod")
285
347
  """
286
- token = token_util.get_access_token()
287
-
288
348
  env = getattr(getattr(ctx, "obj", None), "env", None)
289
349
  if not env:
290
350
  env = (ctx.find_root().params or {}).get("environment")
291
351
  if not env:
292
352
  env = DEFAULT_ENV
353
+ return env
354
+
355
+
356
+ def _get_api(ctx: click.Context, vault: str):
357
+ token = token_util.get_access_token()
358
+ return create_cert_manager_api(vault, _resolve_env(ctx), token)
293
359
 
294
- return create_cert_manager_api(vault, env, token)
360
+
361
+ def _get_personalization_api(ctx: click.Context, vault: str):
362
+ token = token_util.get_access_token()
363
+ return create_personalization_api(vault, _resolve_env(ctx), token)
295
364
 
296
365
 
297
366
  def _der_to_pem_certificate(der_bytes: bytes) -> str:
@@ -341,9 +410,47 @@ def certificate_list(ctx: click.Context, vault: str) -> None:
341
410
  )
342
411
 
343
412
 
413
+ @certificate.command("metadata")
414
+ @tenant_option
415
+ @click.pass_context
416
+ @handle_errors()
417
+ def certificate_metadata(ctx: click.Context, vault: str) -> None:
418
+ """
419
+ Show this tenant's allowed certificate authorities and VGS domain
420
+ suffixes for branded domains (used to build DigiCert subdomains and to
421
+ check which authorities `certificate create --authority` may use).
422
+ """
423
+ api = _get_api(ctx, vault)
424
+ response = api.certificates.metadata(params={"vault_identifier": vault})
425
+
426
+ click.echo(
427
+ dump_camelized_yaml(
428
+ {
429
+ "apiVersion": "1.0.0",
430
+ "kind": "CertificateMetadata",
431
+ "data": response.body,
432
+ }
433
+ )
434
+ )
435
+
436
+
344
437
  @certificate.command("create")
345
438
  @tenant_option
346
- @click.option("--domain", "-d", required=True)
439
+ @click.option(
440
+ "--domain",
441
+ "-d",
442
+ required=False,
443
+ help="Full branded domain name. Required unless --subdomain is used with --authority digicert.",
444
+ )
445
+ @click.option(
446
+ "--subdomain",
447
+ required=False,
448
+ help=(
449
+ "Subdomain to combine with this tenant's allowed VGS domain suffix "
450
+ "(DigiCert branded domains only). Mutually exclusive with --domain. "
451
+ "See `vgs certificate metadata` for the allowed suffix."
452
+ ),
453
+ )
347
454
  @click.option(
348
455
  "--authority",
349
456
  "-a",
@@ -353,20 +460,53 @@ def certificate_list(ctx: click.Context, vault: str) -> None:
353
460
  @click.pass_context
354
461
  @handle_errors()
355
462
  def certificate_create(
356
- ctx: click.Context, vault: str, domain: str, authority: str
463
+ ctx: click.Context,
464
+ vault: str,
465
+ domain: str | None,
466
+ subdomain: str | None,
467
+ authority: str,
357
468
  ) -> None:
469
+ normalized_authority = authority.upper().replace("-", "_")
470
+
471
+ if domain and subdomain:
472
+ raise click.UsageError("Use either --domain or --subdomain, not both.")
473
+
474
+ if subdomain and normalized_authority != "DIGICERT":
475
+ raise click.UsageError(
476
+ "--subdomain is only supported with --authority digicert."
477
+ )
478
+
479
+ if not domain and not subdomain:
480
+ raise click.UsageError(
481
+ "Missing option '--domain' / '-d' (or use --subdomain with "
482
+ "--authority digicert)."
483
+ )
484
+
485
+ api = _get_api(ctx, vault)
486
+
487
+ if subdomain:
488
+ metadata_response = api.certificates.metadata(
489
+ params={"vault_identifier": vault}
490
+ )
491
+ vgs_domains = allowed_vgs_domains(metadata_response.body)
492
+ if not vgs_domains:
493
+ raise click.ClickException(
494
+ "No VGS domain suffix is available for this tenant's DigiCert "
495
+ "certificates."
496
+ )
497
+ domain = f"{subdomain}.{vgs_domains[0]}"
498
+
358
499
  payload = {
359
500
  "data": {
360
501
  "type": "certificate",
361
502
  "attributes": {
362
503
  "vault_identifier": vault,
363
504
  "domain": domain,
364
- "authority": authority.upper().replace("-", "_"),
505
+ "authority": normalized_authority,
365
506
  },
366
507
  }
367
508
  }
368
509
 
369
- api = _get_api(ctx, vault)
370
510
  response = api.certificates.create(body=payload)
371
511
 
372
512
  click.secho(f"Certificate for {domain} created successfully.", fg="green", err=True)
@@ -547,6 +687,86 @@ def certificate_download(
547
687
  click.echo(output)
548
688
 
549
689
 
690
+ @certificate.command("enable-sdk")
691
+ @tenant_option
692
+ @click.option(
693
+ "--domain",
694
+ "-d",
695
+ required=True,
696
+ help="Certificate ID (CRTxxxx) or branded domain to enable for VGS Collect, Show, and Checkout SDKs.",
697
+ )
698
+ @click.option("--confirm", "-y", is_flag=True, help="Skip confirmation prompt")
699
+ @click.pass_context
700
+ @handle_errors()
701
+ def certificate_enable_sdk(
702
+ ctx: click.Context, vault: str, domain: str, confirm: bool
703
+ ) -> None:
704
+ """
705
+ Enable a branded domain for VGS Collect, Show, and Checkout SDKs.
706
+
707
+ The certificate must already be issued (status VALID or
708
+ RENEWAL_REQUIRED). This action cannot be undone from the API; to disable
709
+ it, delete and recreate the branded domain.
710
+ """
711
+ cert_api = _get_api(ctx, vault)
712
+ resolved_domain = _assert_certificate_sdk_enableable(
713
+ cert_api, vault=vault, domain_or_id=domain
714
+ )
715
+
716
+ if not confirm:
717
+ click.confirm(
718
+ f"Enable SDKs for {resolved_domain}? This cannot be undone "
719
+ "(disabling requires deleting and recreating the branded domain).",
720
+ abort=True,
721
+ )
722
+
723
+ personalization_api = _get_personalization_api(ctx, vault)
724
+ personalization_api.hostnames.create(body={"data": {"hostname": resolved_domain}})
725
+
726
+ click.secho(f"{resolved_domain} enabled for SDKs successfully.", fg="green")
727
+
728
+
729
+ @certificate.command("sdk-status")
730
+ @tenant_option
731
+ @click.option(
732
+ "--domain",
733
+ "-d",
734
+ required=True,
735
+ help="Branded domain to check SDK activation status for.",
736
+ )
737
+ @click.pass_context
738
+ @handle_errors()
739
+ def certificate_sdk_status(ctx: click.Context, vault: str, domain: str) -> None:
740
+ """Check whether a branded domain is enabled for VGS Collect, Show, and Checkout SDKs."""
741
+ cdn_base = COLLECT_CDN_URLS.get(_resolve_env(ctx).lower(), COLLECT_CDN_URLS["prod"])
742
+ config_url = f"{cdn_base}/collect-configs/{domain}__{vault}.txt"
743
+
744
+ try:
745
+ response = requests.get(config_url, headers=request_headers({}), timeout=10)
746
+ except requests.RequestException as e:
747
+ raise click.ClickException(f"Unable to determine SDK activation status: {e}")
748
+
749
+ if response.status_code == 200:
750
+ enabled = True
751
+ elif response.status_code in (403, 404):
752
+ enabled = False
753
+ else:
754
+ raise click.ClickException(
755
+ "Unable to determine SDK activation status "
756
+ f"(HTTP {response.status_code})."
757
+ )
758
+
759
+ click.echo(
760
+ dump_camelized_yaml(
761
+ {
762
+ "apiVersion": "1.0.0",
763
+ "kind": "CertificateSdkStatus",
764
+ "data": {"domain": domain, "enabled": enabled},
765
+ }
766
+ )
767
+ )
768
+
769
+
550
770
  @certificate.command("generate-csr")
551
771
  @tenant_option
552
772
  @click.option(