vgs-cli 1.33.0.dev3__py3-none-any.whl → 1.34.0.dev2__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 (43) hide show
  1. vgs_cli-1.34.0.dev2.data/data/vgscli/credentials-admin.yaml +26 -0
  2. vgs_cli-1.34.0.dev2.data/data/vgscli/notification-integration-schema.yaml +89 -0
  3. vgs_cli-1.33.0.dev3.data/data/vgscli/calm.yaml → vgs_cli-1.34.0.dev2.data/data/vgscli/public-credential-collect.yaml +7 -2
  4. vgs_cli-1.34.0.dev2.data/data/vgscli/read-credentials-no-pci.yaml +22 -0
  5. vgs_cli-1.34.0.dev2.data/data/vgscli/read-credentials-with-pci.yaml +23 -0
  6. {vgs_cli-1.33.0.dev3.dist-info → vgs_cli-1.34.0.dev2.dist-info}/METADATA +56 -3
  7. {vgs_cli-1.33.0.dev3.dist-info → vgs_cli-1.34.0.dev2.dist-info}/RECORD +35 -33
  8. vgscli/_version.py +1 -1
  9. vgscli/cli/__init__.py +17 -0
  10. vgscli/cli/commands/apply.py +152 -0
  11. vgscli/cli/commands/delete.py +43 -1
  12. vgscli/cli/commands/generate.py +6 -1
  13. vgscli/cli/commands/get.py +95 -0
  14. vgscli/click_extensions.py +1 -1
  15. vgscli/errors.py +1 -1
  16. vgscli/notifications.py +185 -0
  17. vgscli/notifications_api.py +78 -0
  18. vgscli/resource-templates/service-account/credentials-admin.yaml +26 -0
  19. vgscli/resource-templates/service-account/{calm.yaml → public-credential-collect.yaml} +7 -2
  20. vgscli/resource-templates/service-account/read-credentials-no-pci.yaml +22 -0
  21. vgscli/resource-templates/service-account/read-credentials-with-pci.yaml +23 -0
  22. vgscli/validation-schemas/notification-integration-schema.yaml +89 -0
  23. vgs_cli-1.33.0.dev3.data/data/vgscli/checkout.yaml +0 -21
  24. vgs_cli-1.33.0.dev3.data/data/vgscli/payments-admin.yaml +0 -25
  25. vgs_cli-1.33.0.dev3.data/data/vgscli/sub-account-checkout.yaml +0 -23
  26. vgs_cli-1.33.0.dev3.data/data/vgscli/vgs-cli.yaml +0 -17
  27. vgscli/resource-templates/service-account/checkout.yaml +0 -21
  28. vgscli/resource-templates/service-account/payments-admin.yaml +0 -25
  29. vgscli/resource-templates/service-account/sub-account-checkout.yaml +0 -23
  30. vgscli/resource-templates/service-account/vgs-cli.yaml +0 -17
  31. {vgs_cli-1.33.0.dev3.data → vgs_cli-1.34.0.dev2.data}/data/vgscli/collect-form-api-schema.yaml +0 -0
  32. {vgs_cli-1.33.0.dev3.data → vgs_cli-1.34.0.dev2.data}/data/vgscli/collect-form-schema.yaml +0 -0
  33. {vgs_cli-1.33.0.dev3.data → vgs_cli-1.34.0.dev2.data}/data/vgscli/http-route-template.yaml +0 -0
  34. {vgs_cli-1.33.0.dev3.data → vgs_cli-1.34.0.dev2.data}/data/vgscli/mft-route-template.yaml +0 -0
  35. {vgs_cli-1.33.0.dev3.data → vgs_cli-1.34.0.dev2.data}/data/vgscli/service-account-schema.yaml +0 -0
  36. {vgs_cli-1.33.0.dev3.data → vgs_cli-1.34.0.dev2.data}/data/vgscli/tenant-template.yaml +0 -0
  37. {vgs_cli-1.33.0.dev3.data → vgs_cli-1.34.0.dev2.data}/data/vgscli/vault-resources.yaml +0 -0
  38. {vgs_cli-1.33.0.dev3.data → vgs_cli-1.34.0.dev2.data}/data/vgscli/vault-schema.yaml +0 -0
  39. {vgs_cli-1.33.0.dev3.data → vgs_cli-1.34.0.dev2.data}/data/vgscli/vault-template.yaml +0 -0
  40. {vgs_cli-1.33.0.dev3.dist-info → vgs_cli-1.34.0.dev2.dist-info}/WHEEL +0 -0
  41. {vgs_cli-1.33.0.dev3.dist-info → vgs_cli-1.34.0.dev2.dist-info}/entry_points.txt +0 -0
  42. {vgs_cli-1.33.0.dev3.dist-info → vgs_cli-1.34.0.dev2.dist-info}/licenses/LICENSE +0 -0
  43. {vgs_cli-1.33.0.dev3.dist-info → vgs_cli-1.34.0.dev2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,26 @@
1
+ apiVersion: 1.0.0
2
+ kind: ServiceAccount
3
+ data:
4
+ {%- if name | length == 0 or name | length > 20 %}
5
+ {{ cli_fail("Service Account name must contain between 1 and 20 characters. Use '--var name=<NAME>' to specify it.") }}
6
+ {%- endif %}
7
+ name: {{ name }}
8
+ {%- if vaults | length == 0 %}
9
+ {{ cli_fail("This template needs one tenant. Use '--tenant <TENANT_ID>' to specify it.") }}
10
+ {% elif vaults | length == 1 %}
11
+ vaults:
12
+ - {{ vaults[0] }}
13
+ {%- else %}
14
+ {{ cli_fail("This template doesn't allow multiple tenants.") }}
15
+ {% endif %}
16
+ scopes:
17
+ - name: cards:read
18
+ - name: cards:write
19
+ - name: card-attributes:read
20
+ - name: network-tokens:read
21
+ - name: network-tokens:write
22
+ - name: 3ds:write
23
+ - name: 3ds:read
24
+ - name: account-validations:write
25
+ - name: account-validations:read
26
+ - name: account-reference-numbers:read
@@ -0,0 +1,89 @@
1
+ ---
2
+ "$schema": http://json-schema.org/draft-07/schema#
3
+ type: object
4
+ properties:
5
+ apiVersion:
6
+ type: string
7
+ enum:
8
+ - 1.0.0
9
+ kind:
10
+ type: string
11
+ enum:
12
+ - NotificationIntegration
13
+ data:
14
+ type: object
15
+ properties:
16
+ id:
17
+ type: string
18
+ minLength: 1
19
+ provider:
20
+ type: string
21
+ minLength: 1
22
+ name:
23
+ type: string
24
+ minLength: 1
25
+ pattern: ^[a-zA-Z0-9-_ ]+$
26
+ description:
27
+ type: string
28
+ enabled:
29
+ type: boolean
30
+ providerParameters:
31
+ type: array
32
+ minItems: 1
33
+ items:
34
+ type: object
35
+ properties:
36
+ name:
37
+ type: string
38
+ minLength: 1
39
+ value:
40
+ type: string
41
+ minLength: 1
42
+ required:
43
+ - name
44
+ - value
45
+ additionalProperties: false
46
+ events:
47
+ type: array
48
+ items:
49
+ type: object
50
+ properties:
51
+ id:
52
+ type: string
53
+ minLength: 1
54
+ enabled:
55
+ type: boolean
56
+ resourceIds:
57
+ oneOf:
58
+ - type: "null"
59
+ - type: array
60
+ minItems: 1
61
+ uniqueItems: true
62
+ items:
63
+ type: string
64
+ minLength: 1
65
+ required:
66
+ - id
67
+ - enabled
68
+ additionalProperties: false
69
+ required:
70
+ - provider
71
+ - name
72
+ - providerParameters
73
+ allOf:
74
+ - if:
75
+ not:
76
+ required:
77
+ - id
78
+ then:
79
+ required:
80
+ - events
81
+ properties:
82
+ events:
83
+ minItems: 1
84
+ additionalProperties: false
85
+ required:
86
+ - apiVersion
87
+ - kind
88
+ - data
89
+ additionalProperties: false
@@ -1,7 +1,10 @@
1
1
  apiVersion: 1.0.0
2
2
  kind: ServiceAccount
3
3
  data:
4
- name: calm
4
+ {%- if name | length == 0 or name | length > 20 %}
5
+ {{ cli_fail("Service Account name must contain between 1 and 20 characters. Use '--var name=<NAME>' to specify it.") }}
6
+ {%- endif %}
7
+ name: {{ name }}
5
8
  {%- if vaults | length == 0 %}
6
9
  {{ cli_fail("This template needs one tenant. Use '--tenant <TENANT_ID>' to specify it.") }}
7
10
  {% elif vaults | length == 1 %}
@@ -12,5 +15,7 @@ data:
12
15
  {% endif %}
13
16
  scopes:
14
17
  - name: cards:write
18
+ - name: card-attributes:read
15
19
  - name: network-tokens:write
16
- - name: merchants:write
20
+ - name: 3ds:write
21
+ - name: 3ds:read
@@ -0,0 +1,22 @@
1
+ apiVersion: 1.0.0
2
+ kind: ServiceAccount
3
+ data:
4
+ {%- if name | length == 0 or name | length > 20 %}
5
+ {{ cli_fail("Service Account name must contain between 1 and 20 characters. Use '--var name=<NAME>' to specify it.") }}
6
+ {%- endif %}
7
+ name: {{ name }}
8
+ {%- if vaults | length == 0 %}
9
+ {{ cli_fail("This template needs one tenant. Use '--tenant <TENANT_ID>' to specify it.") }}
10
+ {% elif vaults | length == 1 %}
11
+ vaults:
12
+ - {{ vaults[0] }}
13
+ {%- else %}
14
+ {{ cli_fail("This template doesn't allow multiple tenants.") }}
15
+ {% endif %}
16
+ scopes:
17
+ - name: cards:read
18
+ - name: cards-attributes:read
19
+ - name: network-tokens:read
20
+ - name: account-validations:write
21
+ - name: account-validations:read
22
+ - name: account-reference-numbers:read
@@ -0,0 +1,23 @@
1
+ apiVersion: 1.0.0
2
+ kind: ServiceAccount
3
+ data:
4
+ {%- if name | length == 0 or name | length > 20 %}
5
+ {{ cli_fail("Service Account name must contain between 1 and 20 characters. Use '--var name=<NAME>' to specify it.") }}
6
+ {%- endif %}
7
+ name: {{ name }}
8
+ {%- if vaults | length == 0 %}
9
+ {{ cli_fail("This template needs one tenant. Use '--tenant <TENANT_ID>' to specify it.") }}
10
+ {% elif vaults | length == 1 %}
11
+ vaults:
12
+ - {{ vaults[0] }}
13
+ {%- else %}
14
+ {{ cli_fail("This template doesn't allow multiple tenants.") }}
15
+ {% endif %}
16
+ scopes:
17
+ - name: cards:read-pci
18
+ - name: cards:read
19
+ - name: card-attributes:read
20
+ - name: network-tokens:read
21
+ - name: account-validations:write
22
+ - name: account-validations:read
23
+ - name: account-reference-numbers:read
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vgs-cli
3
- Version: 1.33.0.dev3
3
+ Version: 1.34.0.dev2
4
4
  Summary: VGS Client
5
5
  Home-page: https://github.com/verygoodsecurity/vgs-cli
6
6
  Author: Very Good Security
@@ -64,9 +64,11 @@ Command Line Tool for programmatic configurations on VGS.
64
64
  - [Commands](#commands)
65
65
  - [Authentication](#authentication)
66
66
  - [Organizations and tenants](#organizations-and-tenants)
67
+ - [Organization notifications](#organization-notifications)
67
68
  - [Routes](#routes)
68
69
  - [Collect Forms](#collect-forms)
69
70
  - [Access credentials and logs](#access-credentials-and-logs)
71
+ - [Service accounts](#service-accounts)
70
72
  - [Certificates](#certificates)
71
73
  - [Automation with VGS CLI](#automation-with-vgs-cli)
72
74
 
@@ -100,7 +102,7 @@ Check our [official documentation](https://docs.verygoodsecurity.com/vault/devel
100
102
  Install the agent skill:
101
103
 
102
104
  ```bash
103
- npx skills add verygoodsecurity/vgs-cli --skill vgs-cli-guide
105
+ npx skills add verygoodsecurity/skills --skill vgs-cli-guide
104
106
  ```
105
107
 
106
108
  The guide covers Dashboard-assisted onboarding, the complete built-in command
@@ -139,9 +141,31 @@ Use **tenant** and `--tenant/-T` in new commands. Legacy vault commands and
139
141
  | Command | Purpose |
140
142
  | --- | --- |
141
143
  | `vgs get organizations` | List accessible organizations. |
142
- | `vgs get tenants` | List accessible tenants. |
144
+ | `vgs get tenants` | List all tenants visible to the authenticated identity. |
143
145
  | `vgs generate tenant > tenant.yaml` | Generate a tenant template. |
144
146
  | `vgs apply tenant -f tenant.yaml` | Create a tenant from a reviewed template. |
147
+ | `vgs apply tenant -O <ORGANIZATION_ID> -f tenant.yaml` | Create a tenant when `organizationId` is omitted from the template. |
148
+ | `vgs apply tenant-resources -T <TENANT_ID> -f resources.yaml --dry-run true` | Validate tenant resources without applying them. |
149
+ | `vgs apply tenant-resources -T <TENANT_ID> -f resources.yaml` | Apply reviewed resources to a tenant. |
150
+
151
+ `vgs get tenants` does not take an organization option. `vgs apply tenant`
152
+ requires the organization ID either in `tenant.yaml` as `data.organizationId`
153
+ or through `-O/--organization`; if both are present, they must match.
154
+
155
+ ### Organization notifications
156
+
157
+ | Command | Purpose |
158
+ | --- | --- |
159
+ | `vgs get notification-providers` | List supported notification providers. |
160
+ | `vgs get notifications -O <ORGANIZATION_ID>` | List notification integrations. |
161
+ | `vgs get notification-events -O <ORGANIZATION_ID> <INTEGRATION_ID>` | List configured events for a notification integration. |
162
+ | `vgs apply notification -O <ORGANIZATION_ID> -f notification.yaml` | Create or update a notification integration from a file. |
163
+ | `vgs apply notification -O <ORGANIZATION_ID> --enable <INTEGRATION_ID>` | Enable a notification integration. |
164
+ | `vgs apply notification -O <ORGANIZATION_ID> --disable <INTEGRATION_ID>` | Disable a notification integration. |
165
+ | `vgs delete notification -O <ORGANIZATION_ID> <INTEGRATION_ID>` | Delete a notification integration. |
166
+
167
+ Notification management requires an active organization, organization-admin
168
+ access. The CLI masks generated webhook secrets in its output.
145
169
 
146
170
  ### Routes
147
171
 
@@ -170,6 +194,35 @@ Use **tenant** and `--tenant/-T` in new commands. Legacy vault commands and
170
194
  | `vgs logs access -T <TENANT_ID>` | View tenant access logs. |
171
195
  | `vgs logs operations -T <TENANT_ID> -R <REQUEST_ID>` | View request operation logs. |
172
196
 
197
+ ### Service accounts
198
+
199
+ Generate a service-account resource for exactly one tenant. Names must contain
200
+ 1–20 characters. Save the generated YAML so you can review it before applying
201
+ it.
202
+
203
+ ```bash
204
+ vgs generate service-account --template <TEMPLATE> -T <TENANT_ID> --var name=<NAME> > service-account.yaml
205
+ ```
206
+
207
+ | Template | Purpose |
208
+ | --- | --- |
209
+ | `public-credential-collect` | Collect payment credentials without read access. |
210
+ | `read-credentials-no-pci` | Read tokenized credentials without PCI data. |
211
+ | `read-credentials-with-pci` | Read credentials including PCI data. |
212
+ | `credentials-admin` | Read and write payment credentials. |
213
+
214
+ After reviewing the generated scopes, apply the resource to the organization:
215
+
216
+ ```bash
217
+ vgs apply service-account -O <ORGANIZATION_ID> -f service-account.yaml
218
+ ```
219
+
220
+ The apply response contains a one-time client secret. Run the command only in
221
+ your private terminal, store the secret in an approved secret manager, and do
222
+ not commit or share the response. See the
223
+ [service-account documentation](https://docs.verygoodsecurity.com/vault/developer-tools/vgs-cli/service-account)
224
+ for the full workflow.
225
+
173
226
  ### Certificates
174
227
 
175
228
  | Command | Purpose |
@@ -1,20 +1,20 @@
1
- vgs_cli-1.33.0.dev3.data/data/vgscli/calm.yaml,sha256=HyCIHO5LZdPaeczNw_IOSGxzBBhrSa42lWtGm3GF4mY,448
2
- vgs_cli-1.33.0.dev3.data/data/vgscli/checkout.yaml,sha256=O2hfGAmgLcM9BGvo4tjIhMe8DX1x6Tbj0Ep6dSxmu2I,555
3
- vgs_cli-1.33.0.dev3.data/data/vgscli/collect-form-api-schema.yaml,sha256=THuJbLUo7LOr0c1JUo3FPJEc9Jvde59K4JjdlkVF3hw,1246
4
- vgs_cli-1.33.0.dev3.data/data/vgscli/collect-form-schema.yaml,sha256=vHAN6_Gsg14CeSL41sHEQgboYF-CHF2RaNw72aJ3W8o,1337
5
- vgs_cli-1.33.0.dev3.data/data/vgscli/http-route-template.yaml,sha256=HHKoTF4pSGWUTR1lsw6CIBNdTvTyqNjkeocco80_K38,1663
6
- vgs_cli-1.33.0.dev3.data/data/vgscli/mft-route-template.yaml,sha256=3TwiVS6yDir3uc0g0G_p5Hj4Gje2aq8Zi6vnnRa4j5Q,142
7
- vgs_cli-1.33.0.dev3.data/data/vgscli/payments-admin.yaml,sha256=zMTRLAeuSrMdDZau7AdHr2GVBbvblwxrj1hCZfR4zE8,700
8
- vgs_cli-1.33.0.dev3.data/data/vgscli/service-account-schema.yaml,sha256=L1pjNXgnks15N1wNgf_1GmGcOvxn0nu49v7ersUjFno,1090
9
- vgs_cli-1.33.0.dev3.data/data/vgscli/sub-account-checkout.yaml,sha256=bTYscQeNxU2nfNzSeZ3ffmVFni4Iuigh1rxd2_uKn3M,629
10
- vgs_cli-1.33.0.dev3.data/data/vgscli/tenant-template.yaml,sha256=Q0z5_ds5UWign6ndBodLtXVZHWWCV-VsUVMnvJAhqPM,388
11
- vgs_cli-1.33.0.dev3.data/data/vgscli/vault-resources.yaml,sha256=95CCxQher3MBQq96bvjZviNgo1rgv_NhCtI8X-oxIpA,26335
12
- vgs_cli-1.33.0.dev3.data/data/vgscli/vault-schema.yaml,sha256=a-wW7X8RyHr-669wtOZrlxlIfeQVtx8EUfA-3vpYytk,637
13
- vgs_cli-1.33.0.dev3.data/data/vgscli/vault-template.yaml,sha256=IlDisL3H5LXUDMkhUaouKMarRdu0-pJxpTz8ij_lp_M,383
14
- vgs_cli-1.33.0.dev3.data/data/vgscli/vgs-cli.yaml,sha256=5gCjjloyepaKI6zZfDLeUEWxuRExI-dGJI9RO3omP2k,484
15
- vgs_cli-1.33.0.dev3.dist-info/licenses/LICENSE,sha256=NwSyzgDYdzv6O2ns2C6UODGI8LN1VnVe_FPTnWS4eXY,1082
1
+ vgs_cli-1.34.0.dev2.data/data/vgscli/collect-form-api-schema.yaml,sha256=THuJbLUo7LOr0c1JUo3FPJEc9Jvde59K4JjdlkVF3hw,1246
2
+ vgs_cli-1.34.0.dev2.data/data/vgscli/collect-form-schema.yaml,sha256=vHAN6_Gsg14CeSL41sHEQgboYF-CHF2RaNw72aJ3W8o,1337
3
+ vgs_cli-1.34.0.dev2.data/data/vgscli/credentials-admin.yaml,sha256=acyLd54Cp7l2fpugfjVfYh07-MIE0BX-JVq4lHraE1s,869
4
+ vgs_cli-1.34.0.dev2.data/data/vgscli/http-route-template.yaml,sha256=HHKoTF4pSGWUTR1lsw6CIBNdTvTyqNjkeocco80_K38,1663
5
+ vgs_cli-1.34.0.dev2.data/data/vgscli/mft-route-template.yaml,sha256=3TwiVS6yDir3uc0g0G_p5Hj4Gje2aq8Zi6vnnRa4j5Q,142
6
+ vgs_cli-1.34.0.dev2.data/data/vgscli/notification-integration-schema.yaml,sha256=1qHzS5ZxlhTdrDab6-qJhszwu7cpith2HleX3uAO_4E,1837
7
+ vgs_cli-1.34.0.dev2.data/data/vgscli/public-credential-collect.yaml,sha256=CiorC-6TMx7M0TI8DHmoRSfVKDpOom2wIr_ilwmHQNA,696
8
+ vgs_cli-1.34.0.dev2.data/data/vgscli/read-credentials-no-pci.yaml,sha256=7-31MJewfRI8VVveobdLjeusYE1Edk1xRrWplU3VMow,770
9
+ vgs_cli-1.34.0.dev2.data/data/vgscli/read-credentials-with-pci.yaml,sha256=jWXgFdcqZYisakAt9COM6cjf2-x_Q4eidDLaUh8CZOk,796
10
+ vgs_cli-1.34.0.dev2.data/data/vgscli/service-account-schema.yaml,sha256=L1pjNXgnks15N1wNgf_1GmGcOvxn0nu49v7ersUjFno,1090
11
+ vgs_cli-1.34.0.dev2.data/data/vgscli/tenant-template.yaml,sha256=Q0z5_ds5UWign6ndBodLtXVZHWWCV-VsUVMnvJAhqPM,388
12
+ vgs_cli-1.34.0.dev2.data/data/vgscli/vault-resources.yaml,sha256=95CCxQher3MBQq96bvjZviNgo1rgv_NhCtI8X-oxIpA,26335
13
+ vgs_cli-1.34.0.dev2.data/data/vgscli/vault-schema.yaml,sha256=a-wW7X8RyHr-669wtOZrlxlIfeQVtx8EUfA-3vpYytk,637
14
+ vgs_cli-1.34.0.dev2.data/data/vgscli/vault-template.yaml,sha256=IlDisL3H5LXUDMkhUaouKMarRdu0-pJxpTz8ij_lp_M,383
15
+ vgs_cli-1.34.0.dev2.dist-info/licenses/LICENSE,sha256=NwSyzgDYdzv6O2ns2C6UODGI8LN1VnVe_FPTnWS4eXY,1082
16
16
  vgscli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
- vgscli/_version.py,sha256=fEZhDhsdgs73-mUrVWYLJTeZdBnM7u6CDGSyxS9EqNE,1681
17
+ vgscli/_version.py,sha256=LLDTvaySlCanrTjEZQVXiEcbLIGJtg9ZoJOV79fURSM,1681
18
18
  vgscli/access_logs.py,sha256=G0GjlLjWiC-N6OzK6-RCvWddcVGQlLCLAcyO9pLWIOM,1928
19
19
  vgscli/audits_api.py,sha256=6FjpS1yTALio-DejgIS2eDw75ChjDp4GoAGXh4uZExU,3211
20
20
  vgscli/auth.py,sha256=vdUZ12nqtefIuSHNmwCFvxoqwS3m6ZP5TqLZFNwKnSU,2104
@@ -23,25 +23,27 @@ vgscli/auth_utils.py,sha256=aC1VI0dFdFeupLS9Okz4uDz-wHhhFabqiLUg2R5vO2s,600
23
23
  vgscli/callback_server.py,sha256=oFFF5AGbbwhF7Hsc5fzS7jeGFzIMbebc9Qdq8uEl1PY,1055
24
24
  vgscli/cert_manager_api.py,sha256=ek25BcyGeUo0pBoqineMTYMgmQaYJfimFFHMljZh5yA,1646
25
25
  vgscli/cli_utils.py,sha256=NzXK29_yIDrB-3T_XdLLB8NCWneQ-cpZFi9mazQL9tQ,3810
26
- vgscli/click_extensions.py,sha256=1E0yyAMBn1xmZvi9Gz3FNAp1ir1JTZIVC6eUHz2gPh0,6667
26
+ vgscli/click_extensions.py,sha256=VoaBJpR_ZVNQYTX1x-TZrGAyLiuAGXQq_ZkLU7Y6sZ0,6678
27
27
  vgscli/collect_forms.py,sha256=HAg-tvpXxmVq5Zns4v8G0cP-tgYKuWmVFwzuNjieu-A,4619
28
28
  vgscli/collect_forms_api.py,sha256=JHnnsOUyStD7yR92LfGqn8DOpnu0l0yqTUMQnWE_NGs,1246
29
29
  vgscli/config_file.py,sha256=HB8lANU0qoO09Wnkf-QDzPh2qtrnFcqcetnCaQgtQ3U,1543
30
- vgscli/errors.py,sha256=vzB-dfrzveNUBZ4QIIn-0JpW1iGizsx00tQDyxTXLvE,10359
30
+ vgscli/errors.py,sha256=6ENjyWFV6kenwYqOfLMDCuLcHb8GL5Xo_K_uViRQUMc,10385
31
31
  vgscli/file_token_util.py,sha256=537b54paMGw0u5PL5VJgQqQ7awKa9lQP88n3tUc_lyw,771
32
32
  vgscli/id_generator.py,sha256=3CbvSOUSyLON76p6M8wUhVQVig8j75_rnWdpxLhBifM,1510
33
33
  vgscli/keyring_token_util.py,sha256=cnR72-0AInzujUsIwHoXwPbgprbkllgAXN-AAI3qsPM,4632
34
+ vgscli/notifications.py,sha256=6D8HFDEl3X4V0V9fYZT-9nWYe2KYVahfhRLMF0pbh4I,6252
35
+ vgscli/notifications_api.py,sha256=1EXmRb2fOJrU1QOAZ6gmq8yMjBLhNZGSVs3kRtD2Dfw,2342
34
36
  vgscli/testing.py,sha256=MLrsvy3mEwvjtqyuG0UjwEX-rDkbWUo52aXvu2H2sTk,1437
35
37
  vgscli/text.py,sha256=c2d1As7awq8PlEF9NiI6JrjsYYousj9YT0o1xOQ2MQM,172
36
38
  vgscli/token_handler.py,sha256=MvtmlicqnGrcopNkTr8Q2RlKE7IDj_sJFxF_39Jd7W8,183
37
39
  vgscli/vgs.py,sha256=BiQuHeOuH25zbTdwNOsW_O69YuKsZFTYA2jr9JFRZng,6262
38
- vgscli/cli/__init__.py,sha256=y6rnaI0aRFn0KZbEGEukfrOLK5Jay_cqjTG5KV05kpM,971
40
+ vgscli/cli/__init__.py,sha256=VRKz8oZF1OhAzkZHZGFYJEQgu3oMHk2nSld3lCoJtuQ,1624
39
41
  vgscli/cli/commands/__init__.py,sha256=8ptc9-Vzdx0HU3ZeMcKERYjmJyuB5IMjBSF3Igx5yQ4,206
40
- vgscli/cli/commands/apply.py,sha256=IMixlZFgZ9hUvJpbqOMigfOQ006IMExnMgzDNpN8zSw,14943
42
+ vgscli/cli/commands/apply.py,sha256=D3YwW9vNxyq25IuObfd_jPM0m-U_GmrNauN0wS1LL0U,20049
41
43
  vgscli/cli/commands/certificate.py,sha256=xQV-G8ZWP9uPFqrczlCpCZkHUt2aJflBP2cc5hjobIw,22930
42
- vgscli/cli/commands/delete.py,sha256=39RfiBg3NL6aLqAQpzQ2Z-yr33bUqBT6Jwd2IG8l4JY,2667
43
- vgscli/cli/commands/generate.py,sha256=nkS5--kBHbJhUo7QvslGza5c8Cu2ue-bVitDVGwUYFE,4025
44
- vgscli/cli/commands/get.py,sha256=bl55fMe_xgLuwFJNmIVOxcZp4p-lrMfG5cNAnQydE9Q,6183
44
+ vgscli/cli/commands/delete.py,sha256=2nuYKhp0FhoGTcmJUECjRnlYrKLdAgIoIp-y25ViwDg,3873
45
+ vgscli/cli/commands/generate.py,sha256=k0bw3Cu8Y6qs0sHHnC-CBtlvnl7Rzx2rjlCwTCFaWes,4117
46
+ vgscli/cli/commands/get.py,sha256=5X9CS8FdC33JUwGn-0qaZYDPeNakhfxSU8aX40LPW-M,8818
45
47
  vgscli/cli/types/__init__.py,sha256=a-P-SoGHpLzMg7CL1hhg5x_nf6sHq0qAuGm_AtIITmw,107
46
48
  vgscli/cli/types/resource_id.py,sha256=7JILR-KjoVGQDHB40tXJfTcU53iR8wM9Zr24fY5le3o,1172
47
49
  vgscli/cli/types/variable.py,sha256=IVcszPoWmTjeo_evDsLN06LuUZGTLL-wcZCVfBNBP8I,414
@@ -49,18 +51,18 @@ vgscli/resource-templates/http-route-template.yaml,sha256=HHKoTF4pSGWUTR1lsw6CIB
49
51
  vgscli/resource-templates/mft-route-template.yaml,sha256=3TwiVS6yDir3uc0g0G_p5Hj4Gje2aq8Zi6vnnRa4j5Q,142
50
52
  vgscli/resource-templates/tenant-template.yaml,sha256=Q0z5_ds5UWign6ndBodLtXVZHWWCV-VsUVMnvJAhqPM,388
51
53
  vgscli/resource-templates/vault-template.yaml,sha256=IlDisL3H5LXUDMkhUaouKMarRdu0-pJxpTz8ij_lp_M,383
52
- vgscli/resource-templates/service-account/calm.yaml,sha256=HyCIHO5LZdPaeczNw_IOSGxzBBhrSa42lWtGm3GF4mY,448
53
- vgscli/resource-templates/service-account/checkout.yaml,sha256=O2hfGAmgLcM9BGvo4tjIhMe8DX1x6Tbj0Ep6dSxmu2I,555
54
- vgscli/resource-templates/service-account/payments-admin.yaml,sha256=zMTRLAeuSrMdDZau7AdHr2GVBbvblwxrj1hCZfR4zE8,700
55
- vgscli/resource-templates/service-account/sub-account-checkout.yaml,sha256=bTYscQeNxU2nfNzSeZ3ffmVFni4Iuigh1rxd2_uKn3M,629
56
- vgscli/resource-templates/service-account/vgs-cli.yaml,sha256=5gCjjloyepaKI6zZfDLeUEWxuRExI-dGJI9RO3omP2k,484
54
+ vgscli/resource-templates/service-account/credentials-admin.yaml,sha256=acyLd54Cp7l2fpugfjVfYh07-MIE0BX-JVq4lHraE1s,869
55
+ vgscli/resource-templates/service-account/public-credential-collect.yaml,sha256=CiorC-6TMx7M0TI8DHmoRSfVKDpOom2wIr_ilwmHQNA,696
56
+ vgscli/resource-templates/service-account/read-credentials-no-pci.yaml,sha256=7-31MJewfRI8VVveobdLjeusYE1Edk1xRrWplU3VMow,770
57
+ vgscli/resource-templates/service-account/read-credentials-with-pci.yaml,sha256=jWXgFdcqZYisakAt9COM6cjf2-x_Q4eidDLaUh8CZOk,796
57
58
  vgscli/validation-schemas/collect-form-api-schema.yaml,sha256=THuJbLUo7LOr0c1JUo3FPJEc9Jvde59K4JjdlkVF3hw,1246
58
59
  vgscli/validation-schemas/collect-form-schema.yaml,sha256=vHAN6_Gsg14CeSL41sHEQgboYF-CHF2RaNw72aJ3W8o,1337
60
+ vgscli/validation-schemas/notification-integration-schema.yaml,sha256=1qHzS5ZxlhTdrDab6-qJhszwu7cpith2HleX3uAO_4E,1837
59
61
  vgscli/validation-schemas/service-account-schema.yaml,sha256=L1pjNXgnks15N1wNgf_1GmGcOvxn0nu49v7ersUjFno,1090
60
62
  vgscli/validation-schemas/vault-resources.yaml,sha256=95CCxQher3MBQq96bvjZviNgo1rgv_NhCtI8X-oxIpA,26335
61
63
  vgscli/validation-schemas/vault-schema.yaml,sha256=a-wW7X8RyHr-669wtOZrlxlIfeQVtx8EUfA-3vpYytk,637
62
- vgs_cli-1.33.0.dev3.dist-info/METADATA,sha256=e8Qpg3hzYyODNHD-CzbAQK1UJoNHt16HXcPU-B56zfc,5404
63
- vgs_cli-1.33.0.dev3.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
64
- vgs_cli-1.33.0.dev3.dist-info/entry_points.txt,sha256=wCWhRQiMX4Ja6kkqJlYr8LbuiywpmXyyRAZPsau-_RY,39
65
- vgs_cli-1.33.0.dev3.dist-info/top_level.txt,sha256=gabTxCWMkl80q6ha_m-hs_1wQMfGntZcv5DEmkl8JEw,7
66
- vgs_cli-1.33.0.dev3.dist-info/RECORD,,
64
+ vgs_cli-1.34.0.dev2.dist-info/METADATA,sha256=xUPQHj1GSm6f6bBcNqliRrHQEDwNBgnx_elm2S38jWg,8226
65
+ vgs_cli-1.34.0.dev2.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
66
+ vgs_cli-1.34.0.dev2.dist-info/entry_points.txt,sha256=wCWhRQiMX4Ja6kkqJlYr8LbuiywpmXyyRAZPsau-_RY,39
67
+ vgs_cli-1.34.0.dev2.dist-info/top_level.txt,sha256=gabTxCWMkl80q6ha_m-hs_1wQMfGntZcv5DEmkl8JEw,7
68
+ vgs_cli-1.34.0.dev2.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.33.0.dev3"
9
+ __version__ = "1.34.0.dev2"
10
10
 
11
11
 
12
12
  # noinspection PyBroadException
vgscli/cli/__init__.py CHANGED
@@ -4,6 +4,8 @@ from vgs.sdk.vault_mgmt import VaultMgmtAPI
4
4
 
5
5
  from vgscli.auth import handshake, token_util
6
6
  from vgscli.collect_forms_api import create_api as create_collect_forms_api_client
7
+ from vgscli.notifications import resolve_organization
8
+ from vgscli.notifications_api import create_api as create_notifications_api_client
7
9
 
8
10
 
9
11
  def create_account_mgmt_api(ctx: click.Context) -> AccountMgmtAPI:
@@ -31,3 +33,18 @@ def create_collect_forms_api(ctx: click.Context, vault_id: str):
31
33
  access_token = token_util.get_access_token()
32
34
 
33
35
  return create_collect_forms_api_client(vault_id, environment, access_token)
36
+
37
+
38
+ def create_notifications_api(ctx: click.Context, organization_id: str = None):
39
+ environment = ctx.obj.env
40
+
41
+ handshake(ctx, environment)
42
+ access_token = token_util.get_access_token()
43
+ organization_internal_id = None
44
+ if organization_id:
45
+ account_mgmt = AccountMgmtAPI(access_token, environment)
46
+ organization_internal_id = resolve_organization(account_mgmt, organization_id)
47
+
48
+ return create_notifications_api_client(
49
+ environment, access_token, organization_internal_id
50
+ )
@@ -14,6 +14,7 @@ from vgscli.auth import handshake, token_util
14
14
  from vgscli.cli import (
15
15
  create_account_mgmt_api,
16
16
  create_collect_forms_api,
17
+ create_notifications_api,
17
18
  create_vault_mgmt_api,
18
19
  )
19
20
  from vgscli.cli.types import ResourceId, ResourceIdParamType
@@ -41,6 +42,13 @@ from vgscli.errors import (
41
42
  get_error_details,
42
43
  handle_errors,
43
44
  )
45
+ from vgscli.notifications import (
46
+ event_request_data,
47
+ integration_request_data,
48
+ provider_input_parameters,
49
+ redact_notification_integration,
50
+ validate_notification_configuration,
51
+ )
44
52
 
45
53
  logger = logging.getLogger()
46
54
 
@@ -152,6 +160,150 @@ def apply_service_account(ctx: click.Context, org_id: ResourceId, file) -> None:
152
160
  )
153
161
 
154
162
 
163
+ def _notification_apply_mode(file, enable, disable):
164
+ selected = [file is not None, enable is not None, disable is not None]
165
+ if sum(selected) != 1:
166
+ raise click.UsageError("Use exactly one of --file, --enable, or --disable.")
167
+
168
+
169
+ def _notification_error_message(error):
170
+ details = get_error_details(error)
171
+ return details[0] if details else "API error occurred"
172
+
173
+
174
+ @apply.command("notification")
175
+ @click.option(
176
+ "-O",
177
+ "--organization",
178
+ "org_id",
179
+ type=ResourceIdParamType(prefix="AC"),
180
+ required=True,
181
+ help="Organization ID that owns the notification integration.",
182
+ )
183
+ @click.option(
184
+ "--file",
185
+ "-f",
186
+ type=click.File(),
187
+ help="Notification integration configuration to apply.",
188
+ )
189
+ @click.option(
190
+ "--enable",
191
+ "integration_id_to_enable",
192
+ metavar="INTEGRATION_ID",
193
+ help="Enable an existing notification integration.",
194
+ )
195
+ @click.option(
196
+ "--disable",
197
+ "integration_id_to_disable",
198
+ metavar="INTEGRATION_ID",
199
+ help="Disable an existing notification integration.",
200
+ )
201
+ @click.pass_context
202
+ @handle_errors()
203
+ def apply_notification_integration(
204
+ ctx: click.Context,
205
+ org_id: ResourceId,
206
+ file,
207
+ integration_id_to_enable,
208
+ integration_id_to_disable,
209
+ ):
210
+ """
211
+ Create, update, enable, or disable a notification integration.
212
+ """
213
+ _notification_apply_mode(file, integration_id_to_enable, integration_id_to_disable)
214
+ organization_id = org_id.base58
215
+
216
+ if file is not None:
217
+ document = validate_yaml(
218
+ file, "validation-schemas/notification-integration-schema.yaml"
219
+ )
220
+ data = document["data"]
221
+ integration_id = data.get("id")
222
+
223
+ api = create_notifications_api(ctx, organization_id)
224
+ providers = api.notification_providers.list().body.get("data", [])
225
+ supported_events = api.supported_notification_events.list().body.get("data", [])
226
+ validate_notification_configuration(data, providers, supported_events)
227
+
228
+ current = None
229
+ if integration_id:
230
+ current = api.notification_integrations.retrieve(
231
+ organization_id, integration_id
232
+ ).body["data"]
233
+
234
+ request_data = integration_request_data(data, current=current)
235
+ if integration_id:
236
+ response = api.notification_integrations.update(
237
+ organization_id,
238
+ integration_id,
239
+ body={"data": request_data},
240
+ )
241
+ action = "updated"
242
+ else:
243
+ response = api.notification_integrations.create(
244
+ organization_id, body={"data": request_data}
245
+ )
246
+ integration_id = response.body["data"]["id"]
247
+ action = "created"
248
+
249
+ applied_events = []
250
+ for event in data.get("events", []):
251
+ try:
252
+ event_response = api.notification_integration_events.update(
253
+ organization_id,
254
+ integration_id,
255
+ event["id"],
256
+ body={"data": event_request_data(event)},
257
+ )
258
+ except (exceptions.ClientError, exceptions.ServerError) as error:
259
+ raise VgsCliError(
260
+ f"Notification integration {integration_id} was {action}, but "
261
+ f"event {event['id']} failed: {_notification_error_message(error)}."
262
+ ) from error
263
+ applied_events.append(event_response.body["data"])
264
+
265
+ output = redact_notification_integration(response.body["data"], providers)
266
+ output["events"] = applied_events
267
+ click.echo(
268
+ dump_camelized_yaml(
269
+ {
270
+ "apiVersion": "1.0.0",
271
+ "kind": "NotificationIntegration",
272
+ "data": output,
273
+ }
274
+ )
275
+ )
276
+ return
277
+
278
+ integration_id = integration_id_to_enable or integration_id_to_disable
279
+ enabled = integration_id_to_enable is not None
280
+ api = create_notifications_api(ctx, organization_id)
281
+ providers = api.notification_providers.list().body.get("data", [])
282
+ current = api.notification_integrations.retrieve(
283
+ organization_id, integration_id
284
+ ).body["data"]
285
+ request_data = {
286
+ "provider": current["provider"],
287
+ "name": current["name"],
288
+ "description": current.get("description") or "",
289
+ "enabled": enabled,
290
+ "provider_parameters": provider_input_parameters(current, providers),
291
+ }
292
+ response = api.notification_integrations.update(
293
+ organization_id, integration_id, body={"data": request_data}
294
+ )
295
+ output = redact_notification_integration(response.body["data"], providers)
296
+ click.echo(
297
+ dump_camelized_yaml(
298
+ {
299
+ "apiVersion": "1.0.0",
300
+ "kind": "NotificationIntegration",
301
+ "data": output,
302
+ }
303
+ )
304
+ )
305
+
306
+
155
307
  def _apply_tenant(
156
308
  ctx: click.Context,
157
309
  org_id: Optional[ResourceId],
@@ -3,7 +3,12 @@ from click_plugins import with_plugins
3
3
  from vgs.sdk.vaults_api import create_api as create_vaults_api
4
4
 
5
5
  from vgscli.auth import handshake, token_util
6
- from vgscli.cli import create_account_mgmt_api, create_collect_forms_api
6
+ from vgscli.cli import (
7
+ create_account_mgmt_api,
8
+ create_collect_forms_api,
9
+ create_notifications_api,
10
+ )
11
+ from vgscli.cli.types import ResourceId, ResourceIdParamType
7
12
  from vgscli.cli_utils import iter_entry_points
8
13
  from vgscli.click_extensions import tenant_option
9
14
  from vgscli.collect_forms import validate_collect_form_identifier
@@ -32,6 +37,43 @@ def delete_service_account(ctx, organization, client_id):
32
37
  account_mgmt.service_accounts.delete(organization, client_id)
33
38
 
34
39
 
40
+ @delete.command("notification")
41
+ @click.option(
42
+ "--organization",
43
+ "-O",
44
+ "org_id",
45
+ type=ResourceIdParamType(prefix="AC"),
46
+ required=True,
47
+ help="Organization ID that owns the notification integration.",
48
+ )
49
+ @click.argument("integration_id", type=click.STRING)
50
+ @click.option("--confirm", "-y", is_flag=True, help="Skip confirmation prompt")
51
+ @click.pass_context
52
+ @handle_errors()
53
+ def delete_notification_integration(
54
+ ctx: click.Context,
55
+ org_id: ResourceId,
56
+ integration_id: str,
57
+ confirm: bool,
58
+ ):
59
+ """
60
+ Delete a notification integration from an organization.
61
+ """
62
+ organization_id = org_id.base58
63
+ if not confirm:
64
+ click.confirm(
65
+ f"Are you sure you want to delete notification integration "
66
+ f"{integration_id} from organization {organization_id}?",
67
+ abort=True,
68
+ )
69
+
70
+ api = create_notifications_api(ctx, organization_id)
71
+ api.notification_integrations.delete(organization_id, integration_id)
72
+ click.secho(
73
+ f"Notification integration {integration_id} deleted successfully", fg="green"
74
+ )
75
+
76
+
35
77
  @delete.command("routes")
36
78
  @tenant_option
37
79
  @click.argument("route_id", type=click.STRING)