tgwrap 0.8.12__py3-none-any.whl → 0.11.2__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.
- tgwrap/analyze.py +62 -18
- tgwrap/cli.py +117 -25
- tgwrap/deploy.py +10 -3
- tgwrap/inspector-resources-template.yml +63 -0
- tgwrap/inspector.py +438 -0
- tgwrap/main.py +583 -126
- tgwrap/printer.py +3 -0
- {tgwrap-0.8.12.dist-info → tgwrap-0.11.2.dist-info}/METADATA +163 -6
- tgwrap-0.11.2.dist-info/RECORD +13 -0
- {tgwrap-0.8.12.dist-info → tgwrap-0.11.2.dist-info}/WHEEL +1 -1
- tgwrap-0.8.12.dist-info/RECORD +0 -11
- {tgwrap-0.8.12.dist-info → tgwrap-0.11.2.dist-info}/LICENSE +0 -0
- {tgwrap-0.8.12.dist-info → tgwrap-0.11.2.dist-info}/entry_points.txt +0 -0
tgwrap/printer.py
CHANGED
@@ -1,22 +1,23 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: tgwrap
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.11.2
|
4
4
|
Summary: A (terragrunt) wrapper around a (terraform) wrapper around ....
|
5
5
|
Home-page: https://gitlab.com/lunadata/tgwrap
|
6
6
|
License: MIT
|
7
7
|
Keywords: terraform,terragrunt,terrasafe,python
|
8
8
|
Author: Gerco Grandia
|
9
9
|
Author-email: gerco.grandia@4synergy.nl
|
10
|
-
Requires-Python: >=3.
|
10
|
+
Requires-Python: >=3.12,<4.0
|
11
11
|
Classifier: License :: OSI Approved :: MIT License
|
12
12
|
Classifier: Programming Language :: Python :: 3
|
13
|
-
Classifier: Programming Language :: Python :: 3.8
|
14
|
-
Classifier: Programming Language :: Python :: 3.9
|
15
|
-
Classifier: Programming Language :: Python :: 3.10
|
16
|
-
Classifier: Programming Language :: Python :: 3.11
|
17
13
|
Classifier: Programming Language :: Python :: 3.12
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
15
|
+
Requires-Dist: azure-core (>=1.30.2,<2.0.0)
|
16
|
+
Requires-Dist: azure-identity (>=1.17.1,<2.0.0)
|
17
|
+
Requires-Dist: azure-mgmt-authorization (>=4.0.0,<5.0.0)
|
18
18
|
Requires-Dist: click (>=8.0)
|
19
19
|
Requires-Dist: inquirer (>=3.1.4,<4.0.0)
|
20
|
+
Requires-Dist: jinja2 (>=3.1.4,<4.0.0)
|
20
21
|
Requires-Dist: networkx (>=2.8.8,<3.0.0)
|
21
22
|
Requires-Dist: outdated (>=0.2.2)
|
22
23
|
Requires-Dist: pydot (>=1.4.2,<2.0.0)
|
@@ -72,6 +73,8 @@ And this was not something a bunch of aliases could solve, hence this wrapper wa
|
|
72
73
|
|
73
74
|
When using the run-all, analyzing what is about to be changed is not going to be easier. Hence we created the `tgwrap analyze` function that lists all the planned changes and (if a config file is availabe) calculates a drift score and runs a [terrasafe](https://pypi.org/project/terrasafe/) style validation check.
|
74
75
|
|
76
|
+
> you can ignore minor changes, such as tag updates, with `tgwrap analyze -i tags`
|
77
|
+
|
75
78
|
It needs a config file as follows:
|
76
79
|
|
77
80
|
```yaml
|
@@ -142,6 +145,75 @@ export TGWRAP_PLANFILE_DIR=".terragrunt-cache/current"
|
|
142
145
|
|
143
146
|
Or pass it along with the `--planfile-dir|-P` option and it will use that.
|
144
147
|
|
148
|
+
### Logging the results
|
149
|
+
|
150
|
+
`tgwrap` supports logging the analyze results to an [Azure Log Analytics](https://learn.microsoft.com/en-us/azure/azure-monitor/logs/log-analytics-overview) custom table.
|
151
|
+
|
152
|
+
For that, the custom table need to be present, including a [data collection endpoint](https://learn.microsoft.com/en-us/azure/azure-monitor/essentials/data-collection-endpoint-overview?tabs=portal) and associated [data collection rule](https://learn.microsoft.com/en-us/azure/azure-monitor/essentials/data-collection-rule-overview?tabs=portal).
|
153
|
+
|
154
|
+
When you want to activate this, just pass `--data-collection-endpoint` (or, more conveniently, set the `TGWRAP_ANALYZE_DATA_COLLECTION_ENDPOINT` environment variable) with the url to which the data can be posted.
|
155
|
+
|
156
|
+
> Note that for this to work, `tgwrap` assumes that there is a functioning [azure cli](https://learn.microsoft.com/en-us/cli/azure/) available on the system.
|
157
|
+
|
158
|
+
A payload as below will be posted, and the log analytics table should be able to accomodate for that:
|
159
|
+
|
160
|
+
```json
|
161
|
+
[
|
162
|
+
{
|
163
|
+
"scope": "terragrunt/dlzs/data-platform/global/platform/rbac/",
|
164
|
+
"principal": "myself",
|
165
|
+
"repo": "https://gitlab.com/my-git-repo.git",
|
166
|
+
"creations": 0,
|
167
|
+
"updates": 0,
|
168
|
+
"deletions": 0,
|
169
|
+
"minor": 0,
|
170
|
+
"medium": 0,
|
171
|
+
"major": 0,
|
172
|
+
"unknown": 0,
|
173
|
+
"total": 0,
|
174
|
+
"score": 0.0,
|
175
|
+
"details": [
|
176
|
+
{
|
177
|
+
"drifts": {
|
178
|
+
"minor": 0,
|
179
|
+
"medium": 0,
|
180
|
+
"major": 0,
|
181
|
+
"unknown": 0,
|
182
|
+
"total": 0,
|
183
|
+
"score": 0.0
|
184
|
+
},
|
185
|
+
"all": [],
|
186
|
+
"creations": [],
|
187
|
+
"updates": [],
|
188
|
+
"deletions": [],
|
189
|
+
"unauthorized": [],
|
190
|
+
"unknowns": [],
|
191
|
+
"module": ""
|
192
|
+
}
|
193
|
+
]
|
194
|
+
}
|
195
|
+
]
|
196
|
+
```
|
197
|
+
|
198
|
+
The log analytics (custom) table should have a schema that is able to cope with the message above:
|
199
|
+
|
200
|
+
| Field | Type |
|
201
|
+
|----------------|----------|
|
202
|
+
| creations | Int |
|
203
|
+
| deletions | Int |
|
204
|
+
| details | Dynamic |
|
205
|
+
| major | Int |
|
206
|
+
| medium | Int |
|
207
|
+
| minor | Int |
|
208
|
+
| principal | String |
|
209
|
+
| repo | String |
|
210
|
+
| scope | String |
|
211
|
+
| score | Int |
|
212
|
+
| TimeGenerated | Datetime |
|
213
|
+
| total | Int |
|
214
|
+
| unknown | Int |
|
215
|
+
| updates | Int |
|
216
|
+
|
145
217
|
## More than a wrapper
|
146
218
|
|
147
219
|
Over time, tgwrap became more than a wrapper, blantly violating [#1 of the unix philosophy](https://en.wikipedia.org/wiki/Unix_philosophy#:~:text=The%20Unix%20philosophy%20is%20documented,%2C%20as%20yet%20unknown%2C%20program.): 'Make each program do one thing well'.
|
@@ -216,6 +288,7 @@ deploy: # which modules do you want to deploy
|
|
216
288
|
source_stage: dev
|
217
289
|
source_dir: platform # optional, if the source modules are not directly in the stage dir, but in <stage>/<source_dir> directory
|
218
290
|
base_dir: platform # optional, if you want to deploy the base modules in its own dir, side by side with substacks
|
291
|
+
include_global_config_files: false # optional, overrides the CLI input
|
219
292
|
config_dir: ../../../config # this is relative to where you run the deploy
|
220
293
|
configs:
|
221
294
|
- my-config.hcl
|
@@ -257,6 +330,90 @@ global_config_files:
|
|
257
330
|
source: ../../terrasafe-config.json
|
258
331
|
```
|
259
332
|
|
333
|
+
## Inspecting deployed infrastructure
|
334
|
+
|
335
|
+
Testing infra-as-code is hard, even though test frameworks are becoming more common these days. But the standard test approaches typically work with temporary infrastructures, while it is often also useful to test a deployed infrastructure.
|
336
|
+
|
337
|
+
Frameworks like [Chef's InSpec](https://docs.chef.io/inspec/) aims at solving that, but it is pretty config management heavy (but there are add-ons for aws and azure infra). It has a steep learning curve, we only need a tiny part of it, and also comes with a commercial license.
|
338
|
+
|
339
|
+
For what we need ('is infra deployed and are the main role assignments still in place') it was pretty easy to implement in python.
|
340
|
+
|
341
|
+
For this, you can now run the `inspect` command, which will then inspect real infrastructure and role assignments, and report back whether it meets the expectations (as declared in a config file):
|
342
|
+
|
343
|
+
```yaml
|
344
|
+
---
|
345
|
+
location:
|
346
|
+
code: westeurope
|
347
|
+
full: West Europe
|
348
|
+
|
349
|
+
# the entra id groups ar specified as a map as these will be checked for existence
|
350
|
+
# but also used for role assignment validation
|
351
|
+
entra_id_groups:
|
352
|
+
platform_admins: '{domain}-platform-admins'
|
353
|
+
cost_admins: '{domain}-cost-admins'
|
354
|
+
data_admins: '{domain}-data-admins'
|
355
|
+
just_testing: group-does-not-exist
|
356
|
+
|
357
|
+
# the resources to check
|
358
|
+
resources:
|
359
|
+
- identifier: 'kv-{domain}-euw-{stage}-base'
|
360
|
+
# due to length limitations in resource names, some shortening in the name might have taken place
|
361
|
+
# so you can provide alternative ids
|
362
|
+
alternative_ids:
|
363
|
+
- 'kv-{domain}-euw-{stage}-bs'
|
364
|
+
- 'kv{domain}euw{stage}bs'
|
365
|
+
- 'kv{domain}euw{stage}base'
|
366
|
+
type: key_vault
|
367
|
+
resource_group: 'rg-{domain}-euw-{stage}-base'
|
368
|
+
role_assignments:
|
369
|
+
- platform_admins: Owner
|
370
|
+
- platform_admins: Key Vault Secrets Officer
|
371
|
+
- data_admins: Key Vault Secrets Officer
|
372
|
+
```
|
373
|
+
|
374
|
+
After which you can run the following:
|
375
|
+
|
376
|
+
```console
|
377
|
+
tgwrap inspect -d domain -s sbx -a 886d4e58-a178-4c50-ae65-xxxxxxxxxx -c ./inspect-config.yml
|
378
|
+
......
|
379
|
+
|
380
|
+
Inspection status:
|
381
|
+
entra_id_group: dps-platform-admins
|
382
|
+
-> Resource: OK (Resource dps-platform-admins of type entra_id_group OK)
|
383
|
+
entra_id_group: dps-cost-admins
|
384
|
+
-> Resource: OK (Resource dps-cost-admins of type entra_id_group OK)
|
385
|
+
entra_id_group: dps-data-admins
|
386
|
+
-> Resource: OK (Resource dps-data-admins of type entra_id_group OK)
|
387
|
+
entra_id_group: group-does-not-exist
|
388
|
+
-> Resource: NEX (Resource group-does-not-exist of type entra_id_group not found)
|
389
|
+
key_vault: kv-dps-euw-sbx-base
|
390
|
+
-> Resource: OK (Resource kv-dps-euw-sbx-base of type key_vault OK)
|
391
|
+
-> RBAC: NOK (Principal platform_admins has NOT role Owner assigned; )
|
392
|
+
subscription: 886d4e58-a178-4c50-ae65-xxxxxxxxxx
|
393
|
+
-> Resource: OK (Resource 886d4e58-a178-4c50-ae65-xxxxxxxxxx of type subscription OK)
|
394
|
+
-> RBAC: NC (Role assignments not checked)
|
395
|
+
```
|
396
|
+
|
397
|
+
You can sent the results also to a data collection endpoint (seel also [Logging the results](#logging-the-results)).
|
398
|
+
|
399
|
+
For that, a custom table should exist with the following structure:
|
400
|
+
|
401
|
+
|
402
|
+
| Field | Type |
|
403
|
+
|----------------------------|----------|
|
404
|
+
| domain | String |
|
405
|
+
| substack | String |
|
406
|
+
| stage | String |
|
407
|
+
| subscription_id | String |
|
408
|
+
| resource_type | String |
|
409
|
+
| inspect_status_code | String |
|
410
|
+
| inspect_status | String |
|
411
|
+
| inspect_message | String |
|
412
|
+
| rbac_assignment_status_code| String |
|
413
|
+
| rbac_assignment_status | String |
|
414
|
+
| rbac_assignment_message | String |
|
415
|
+
| resource | String |
|
416
|
+
|
260
417
|
## Generating change logs
|
261
418
|
|
262
419
|
tgwrap can generate a change log by running:
|
@@ -0,0 +1,13 @@
|
|
1
|
+
tgwrap/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
+
tgwrap/analyze.py,sha256=5C0OcDpOfn6U39QNIoc7V9ePjjcXKbJH6cOVNr9jJ9A,10289
|
3
|
+
tgwrap/cli.py,sha256=9zvBop3Gm5B2b8K-zXVHEvRUCC7t5ffZUJZEpj1Fxtw,32186
|
4
|
+
tgwrap/deploy.py,sha256=-fSk-Ix_HqrXY7KQX_L27TnFzIuhBHYv4xYJW6zRDN4,10243
|
5
|
+
tgwrap/inspector-resources-template.yml,sha256=Mos8NDzzZ3VxdXgeiVL9cmQfRcIXIHMLf79_KLwdXu8,3297
|
6
|
+
tgwrap/inspector.py,sha256=5pW7Ex1lkKRoXY6hZGbCNmSD2iRzgMSfqi9w7gb-AcY,16990
|
7
|
+
tgwrap/main.py,sha256=Vzmy9GEuBT-T6TB_ZzN_lET5ihY0P-9WcPZ_MPCus_k,94366
|
8
|
+
tgwrap/printer.py,sha256=frn1PARd8A28mkRCYR6ybN2x0NBULhNOutn4l2U7REY,2754
|
9
|
+
tgwrap-0.11.2.dist-info/LICENSE,sha256=VT-AVxIXt3EQTC-7Hy1uPGnrDNJLqfcgLgJD78fiyx4,1065
|
10
|
+
tgwrap-0.11.2.dist-info/METADATA,sha256=fYWSDZfgDmERSCJ7ZOJqMmf7M6cdemNBjFg_jsUG5KQ,17686
|
11
|
+
tgwrap-0.11.2.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
12
|
+
tgwrap-0.11.2.dist-info/entry_points.txt,sha256=H8X0PMPmd4aW7Y9iyChZ0Ug6RWGXqhRUvHH-6f6Mxz0,42
|
13
|
+
tgwrap-0.11.2.dist-info/RECORD,,
|
tgwrap-0.8.12.dist-info/RECORD
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
tgwrap/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
tgwrap/analyze.py,sha256=CsSaGv-be6ATy36z9X7x00gpKY59soJys2VbIzD-tmg,8726
|
3
|
-
tgwrap/cli.py,sha256=weYPXnpZ1200L28tNGzVaO_GlX7wAdLn1nQZsHKpe3k,29060
|
4
|
-
tgwrap/deploy.py,sha256=bJiox_fz8JsoPreX4woW6-EqAebhpJWnKUVLVeGXkrI,10000
|
5
|
-
tgwrap/main.py,sha256=82f4Wc-jPczDpP4vCMeJeaF1CBfiDGizNy0KDw_iDZw,74720
|
6
|
-
tgwrap/printer.py,sha256=dkcOCPIPB-IP6pn8QMpa06xlcqPFVaDvxnz-QEpDJV0,2663
|
7
|
-
tgwrap-0.8.12.dist-info/LICENSE,sha256=VT-AVxIXt3EQTC-7Hy1uPGnrDNJLqfcgLgJD78fiyx4,1065
|
8
|
-
tgwrap-0.8.12.dist-info/METADATA,sha256=RGlxakJg0v5wKWoma5H3rip2BTJ7mcmbq41iazo-VVE,11616
|
9
|
-
tgwrap-0.8.12.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
10
|
-
tgwrap-0.8.12.dist-info/entry_points.txt,sha256=H8X0PMPmd4aW7Y9iyChZ0Ug6RWGXqhRUvHH-6f6Mxz0,42
|
11
|
-
tgwrap-0.8.12.dist-info/RECORD,,
|
File without changes
|
File without changes
|