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/printer.py CHANGED
@@ -69,3 +69,6 @@ class Printer():
69
69
  click.secho(msg, fg="green", bold=True, file=sys.stderr)
70
70
  self.line() if print_line_after else None
71
71
 
72
+ def progress_indicator(self):
73
+ print('.', flush=True, file=sys.stderr, end='')
74
+
@@ -1,22 +1,23 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tgwrap
3
- Version: 0.8.12
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.8,<4.0
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,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.8.1
2
+ Generator: poetry-core 1.9.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -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,,