envstack 0.7.4__tar.gz → 0.8.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 (30) hide show
  1. {envstack-0.7.4/lib/envstack.egg-info → envstack-0.8.0}/PKG-INFO +218 -91
  2. {envstack-0.7.4 → envstack-0.8.0}/README.md +216 -90
  3. {envstack-0.7.4 → envstack-0.8.0}/lib/envstack/__init__.py +2 -2
  4. {envstack-0.7.4 → envstack-0.8.0}/lib/envstack/cli.py +76 -5
  5. envstack-0.8.0/lib/envstack/encrypt.py +322 -0
  6. {envstack-0.7.4 → envstack-0.8.0}/lib/envstack/env.py +185 -45
  7. envstack-0.8.0/lib/envstack/node.py +377 -0
  8. {envstack-0.7.4 → envstack-0.8.0}/lib/envstack/path.py +9 -9
  9. {envstack-0.7.4 → envstack-0.8.0}/lib/envstack/util.py +241 -23
  10. {envstack-0.7.4 → envstack-0.8.0/lib/envstack.egg-info}/PKG-INFO +218 -91
  11. {envstack-0.7.4 → envstack-0.8.0}/lib/envstack.egg-info/SOURCES.txt +4 -0
  12. envstack-0.8.0/lib/envstack.egg-info/requires.txt +2 -0
  13. {envstack-0.7.4 → envstack-0.8.0}/setup.py +2 -1
  14. {envstack-0.7.4 → envstack-0.8.0}/tests/test_cmds.py +166 -28
  15. envstack-0.8.0/tests/test_encrypt.py +117 -0
  16. {envstack-0.7.4 → envstack-0.8.0}/tests/test_env.py +232 -8
  17. envstack-0.8.0/tests/test_node.py +306 -0
  18. {envstack-0.7.4 → envstack-0.8.0}/tests/test_util.py +189 -1
  19. envstack-0.7.4/lib/envstack.egg-info/requires.txt +0 -1
  20. {envstack-0.7.4 → envstack-0.8.0}/LICENSE +0 -0
  21. {envstack-0.7.4 → envstack-0.8.0}/dist.json +0 -0
  22. {envstack-0.7.4 → envstack-0.8.0}/lib/envstack/config.py +0 -0
  23. {envstack-0.7.4 → envstack-0.8.0}/lib/envstack/exceptions.py +0 -0
  24. {envstack-0.7.4 → envstack-0.8.0}/lib/envstack/logger.py +0 -0
  25. {envstack-0.7.4 → envstack-0.8.0}/lib/envstack/wrapper.py +0 -0
  26. {envstack-0.7.4 → envstack-0.8.0}/lib/envstack.egg-info/dependency_links.txt +0 -0
  27. {envstack-0.7.4 → envstack-0.8.0}/lib/envstack.egg-info/entry_points.txt +0 -0
  28. {envstack-0.7.4 → envstack-0.8.0}/lib/envstack.egg-info/not-zip-safe +0 -0
  29. {envstack-0.7.4 → envstack-0.8.0}/lib/envstack.egg-info/top_level.txt +0 -0
  30. {envstack-0.7.4 → envstack-0.8.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: envstack
3
- Version: 0.7.4
3
+ Version: 0.8.0
4
4
  Summary: Stacked environment variable management system
5
5
  Home-page: http://github.com/rsgalloway/envstack
6
6
  Author: Ryan Galloway
@@ -20,16 +20,28 @@ Requires-Python: >=3.6
20
20
  Description-Content-Type: text/markdown
21
21
  License-File: LICENSE
22
22
  Requires-Dist: PyYAML==5.1.2
23
+ Requires-Dist: cryptography==43.0.1
23
24
 
24
25
  envstack
25
26
  ========
26
27
 
27
28
  Environment variable management system.
28
29
 
30
+ [Installation](#installation) |
31
+ [Quickstart](#quickstart) |
32
+ [Setting Values](#setting-values) |
33
+ [Creating Stacks](#creating-stacks) |
34
+ [Encryption](#encryption) |
35
+ [Usage](#usage) |
36
+ [Python API](#python-api) |
37
+ [Running Commands](#running-commands)
38
+
39
+
29
40
  | Feature | Description |
30
41
  |---------|-------------|
31
42
  | Namespaced environments | Environments in envstack are namespaced, allowing you to organize and manage variables based on different contexts or projects. Each environment stack can have its own set of variables, providing a clean separation and avoiding conflicts between different environments. |
32
43
  | Environment stacks | Allows you to manage environment variables using .env files called environment stacks. These stacks provide a hierarchical and contextual approach to managing variables. |
44
+ | Encryption support | Secure encryption, including AES-GCM, Fernet, and Base64. This allows you to securely encrypt and decrypt sensitive environment variables. |
33
45
  | Hierarchical structure | Stacks can be combined and have a defined order of priority. Variables defined in higher scope stacks flow from higher scope to lower scope, left to right. |
34
46
  | Variable expansion modifiers | Supports bash-like variable expansion modifiers, allowing you to set default values for variables and override them in the environment or by higher scope stacks. |
35
47
  | Platform-specific variables | Stacks can have platform-specific variables and values. This allows you to define different values for variables based on the platform. |
@@ -72,35 +84,45 @@ root folder defined by `${DEPLOY_ROOT}` (defined in `env/default.env`).
72
84
 
73
85
  ## Quickstart
74
86
 
75
- Envstack looks for .env files in directories specified by `${ENVPATH}` and i
76
- the current working directory. Start by getting the latest `default.env`
77
- environment stack file:
87
+ Start by getting the latest `default.env` environment stack file:
78
88
 
79
89
  ```bash
80
- $ wget -O default.env \
81
- https://raw.githubusercontent.com/rsgalloway/envstack/master/env/default.env
90
+ $ curl -o default.env https://raw.githubusercontent.com/rsgalloway/envstack/master/env/default.env
82
91
  ```
83
92
 
84
- Set `$ENVPATH` to the directory containing your environment stack files:
93
+ Alternatively, set `${ENVPATH}` to the directory containing your environment
94
+ stack files:
85
95
 
96
+ #### bash
86
97
  ```bash
87
- $ export ENVPATH=/path/to/env/stack/files
98
+ $ export ENVPATH=/path/to/env/files
99
+ ```
100
+
101
+ #### cmd
102
+ ```cmd
103
+ > set ENVPATH=/path/to/env/files
88
104
  ```
89
105
 
90
- Define as many paths as you want, and envstack will search for stack file in
106
+ Define as many paths as you want, and envstack will search for stack files in
91
107
  order from left to right, for example:
92
108
 
109
+ #### bash
93
110
  ```bash
94
111
  $ export ENVPATH=/mnt/pipe/dev/env:/mnt/pipe/prod/env
95
112
  ```
96
113
 
97
- In the case above, stack files in `/mnt/pipe/dev/env` will take precedence over those
98
- found in `/mnt/pipe/prod/env`.
114
+ #### cmd
115
+ ```cmd
116
+ > set ENVPATH=X:/pipe/dev/env;X:/pipe/prod/env
117
+ ```
118
+
119
+ In the examples above, stack files in `dev` will take precedence over those
120
+ found in `prod`.
99
121
 
100
122
  #### Basic Usage
101
123
 
102
- Running the `envstack` command will show you the default environment stack,
103
- defined in the `default.env` stack file:
124
+ Running the `envstack` command will show you the default, unresolved environment
125
+ stack, defined in `default.env` files in `${ENVPATH}`:
104
126
 
105
127
  ```bash
106
128
  $ envstack
@@ -115,54 +137,27 @@ ROOT=/mnt/pipe
115
137
  STACK=default
116
138
  ```
117
139
 
118
- If you are not seeing the above output, make sure the `default.env`
119
- stack file is in your `$ENVPATH` or current working directory.
140
+ If you are not seeing the above output, make sure the `default.env` stack file
141
+ is in `${ENVPATH}` or the current working directory.
120
142
 
121
- > NOTE: The name of the current stack will always be stored in `${STACK}`.
143
+ > NOTE: The name of the current stack will always be stored in `${STACK}`
122
144
 
123
- To see stacks, pass the stack name as the first arg. Environment stacks can be
124
- combined, in order of priority (variables defined in stacks flow from higher
125
- scope to lower scope, left to right):
145
+ Environments can be combined, or stacked, in order of priority (variables
146
+ defined in stacks flow from higher scope to lower scope, left to right):
126
147
 
127
148
  ```bash
128
149
  $ envstack [STACK [STACK ...]]
129
150
  ```
130
151
 
131
- #### Executing Scripts
132
-
133
- Environment stack files are also executable scripts that can be run directly:
134
-
135
-
136
- ```bash
137
- $ ./env/test.env
138
- DEPLOY_ROOT=${ROOT}/${STACK}
139
- ENV=${STACK}
140
- ENVPATH=${DEPLOY_ROOT}/env:${ROOT}/prod/env
141
- HELLO=${HELLO:=world}
142
- LOG_LEVEL=DEBUG
143
- PATH=${DEPLOY_ROOT}/bin:${ROOT}/prod/bin:${PATH}
144
- PYTHONPATH=${DEPLOY_ROOT}/lib/python:${ROOT}/prod/lib/python:${PYTHONPATH}
145
- ROOT=/mnt/pipe
146
- STACK=test
147
- ```
148
-
149
- Run commands inside a specific environment stack file:
150
-
151
- ```bash
152
- $ ./env/test.env -- <command>
153
- ```
154
-
155
- For example:
156
-
157
- ```bash
158
- $ ./env/hello.env -- echo {HELLO}
159
- world
160
- ```
152
+ #### Resolving Values
161
153
 
162
- Export a specific environment stack file:
154
+ To resolve an environment stack or a variable use `--resolve/-r [VAR]`.
163
155
 
164
156
  ```bash
165
- $ ./env/hello.env --export
157
+ $ envstack -r HELLO
158
+ HELLO=world
159
+ $ envstack -r DEPLOY_ROOT
160
+ DEPLOY_ROOT=/mnt/pipe/prod
166
161
  ```
167
162
 
168
163
  ## Setting Values
@@ -182,7 +177,7 @@ Without the expansion modifier, values are set and do not change (but can be
182
177
  overridden by lower scope stacks, i.e. a lower scope stack file may override
183
178
  a higher one).
184
179
 
185
- If we define `$HELLO` like this:
180
+ If we define `${HELLO}` like this:
186
181
 
187
182
  ```yaml
188
183
  HELLO: world
@@ -218,54 +213,35 @@ goodbye
218
213
  Several example or starter stacks are available in the [env folder of the
219
214
  envstack repo](https://github.com/rsgalloway/envstack/tree/master/env).
220
215
 
221
- To create a blank environment stack, create a new envstack file and declare some
216
+ To create a new environment stack, create an envstack file and declare some
222
217
  variables.
223
218
 
224
- Create a new stack file called "foobar.env" and make it executable (note: at
225
- least one VAR needs to be defined under all):
219
+ ```bash
220
+ $ envstack foobar -o foobar.env
221
+ ```
226
222
 
227
- #### foobar.env
223
+ Add the `${FOO}` and `${BAR}` env vars to the foobar.env environment stack file:
228
224
 
229
225
  ```yaml
230
226
  #!/usr/bin/env envstack
231
-
232
- all: &default
227
+ all: &all
233
228
  FOO: bar
234
229
  BAR: ${FOO}
235
230
  darwin:
236
- <<: *default
231
+ <<: *all
237
232
  linux:
238
- <<: *default
233
+ <<: *all
239
234
  windows:
240
- <<: *default
241
- ```
242
-
243
- Make it executable
244
-
245
- ```bash
246
- $ chmod +x ./foobar.env
247
- ```
248
-
249
- To see the resolved environment for the `foobar` stack, run:
250
-
251
- ```bash
252
- $ envstack foobar
253
- FOO=bar
254
- BAR=$FOO
255
- ```
256
-
257
- or execute it directly:
258
-
259
- ```bash
260
- $ ./foobar.env
235
+ <<: *all
261
236
  ```
262
237
 
263
- To see resolved values:
238
+ Get the resolved environment for the `foobar` stack:
264
239
 
265
240
  ```bash
266
241
  $ ./foobar.env -r
267
- FOO=bar
268
242
  BAR=bar
243
+ FOO=bar
244
+ STACK=foobar
269
245
  ```
270
246
 
271
247
  #### More Details
@@ -274,20 +250,17 @@ Variables can be platform specific:
274
250
 
275
251
  ```yaml
276
252
  darwin:
277
- <<: *default
278
253
  HELLO: olleh
279
254
  linux:
280
- <<: *default
281
255
  HELLO: world
282
256
  windows:
283
- <<: *default
284
257
  HELLO: goodbye
285
258
  ```
286
259
 
287
260
  Variables can reference other variables:
288
261
 
289
262
  ```yaml
290
- all: &default
263
+ all: &all
291
264
  FOO: ${BAR}
292
265
  BAR: ${BAZ}
293
266
  BAZ: ${BIZ}
@@ -313,6 +286,105 @@ probably always include the `default` stack):
313
286
  include: [default, test]
314
287
  ```
315
288
 
289
+ ## Encryption
290
+
291
+ Supported encryption algorithms include
292
+ [AES-GCM](https://en.wikipedia.org/wiki/Galois/Counter_Mode),
293
+ [Fernet](https://github.com/fernet/spec/),
294
+ and
295
+ [Base64](https://en.wikipedia.org/wiki/Base64). This allows
296
+ you to securely encrypt and decrypt sensitive environment variables.
297
+
298
+ To use AES-GCM or Fernet, and encryption key must be found somewhere in the
299
+ environment. No key is required for Base64 encryption (the default). Encrypted
300
+ nodes look for keys in the following order, favoring AES-GCM over Fernet:
301
+
302
+ | Algorithm | Key |
303
+ |---------|-------------|
304
+ | Base64 | (no key required) |
305
+ | AES-GCM | ${ENVSTACK_SYMMETRIC_KEY} |
306
+ | Fernet | ${ENVSTACK_FERNET_KEY} |
307
+
308
+ If no encryption keys are found in the environment, envstack will default to
309
+ using Base64 encryption:
310
+
311
+ ```bash
312
+ $ envstack --encrypt
313
+ DEPLOY_ROOT=JHtST09UfS8ke0VOVn0=
314
+ ENV=cHJvZA==
315
+ ENVPATH=JHtERVBMT1lfUk9PVH0vZW52OiR7RU5WUEFUSH0=
316
+ HELLO=JHtIRUxMTzo9d29ybGR9
317
+ LOG_LEVEL=JHtMT0dfTEVWRUw6PUlORk99
318
+ PATH=JHtERVBMT1lfUk9PVH0vYmluOiR7UEFUSH0=
319
+ PYTHONPATH=JHtERVBMT1lfUk9PVH0vbGliL3B5dGhvbjoke1BZVEhPTlBBVEh9
320
+ ROOT=L21udC9waXBl
321
+ STACK=ZGVmYXVsdA==
322
+ ```
323
+
324
+ #### Generating Keys
325
+
326
+ To use AES-GCM or Fernet encryption and serialize to an `encrypted.env` file,
327
+ first generate and source keys in the shell using the `--keygen` option:
328
+
329
+ ```bash
330
+ $ source <(envstack --keygen --export)
331
+ ```
332
+
333
+ In Windows CMD you have to output the commands to a .bat file to source them:
334
+
335
+ ```cmd
336
+ > envstack --keygen > keys.bat
337
+ > call keys.bat
338
+ ```
339
+
340
+ Once the keys are in the environment, you can encrypt the env stack:
341
+
342
+ ```bash
343
+ $ envstack --encrypt -o encrypted.env
344
+ ```
345
+
346
+ Encrypted variables will resolve as long as the key is in the environment:
347
+
348
+ ```bash
349
+ $ envstack encrypted -r HELLO
350
+ HELLO=world
351
+ ```
352
+
353
+ #### Storing Keys
354
+
355
+ Keys can be stored in other environment stacks, e.g. a `keys.env` file. To
356
+ generate keys and store them in a `keys.env` env stack file:
357
+
358
+ ```bash
359
+ $ envstack --keygen -o keys.env
360
+ ```
361
+
362
+ Then use the `keys.env` env stack to encrypt any other env stack:
363
+
364
+ ```bash
365
+ $ envstack keys -- envstack --encrypt -o encrypted.env
366
+ ```
367
+
368
+ To decrypt, add `keys` to the env stack:
369
+
370
+ ```bash
371
+ $ envstack keys encrypted -r HELLO
372
+ HELLO=world
373
+ ```
374
+
375
+ Or add the `keys` env stack to `include` to automatically decrypt:
376
+
377
+ ```yaml
378
+ include: [keys]
379
+ ```
380
+
381
+ Variables will automatically decrypt when resolved:
382
+
383
+ ```bash
384
+ $ ./encrypted.env -r HELLO
385
+ HELLO=world
386
+ ```
387
+
316
388
  ## Usage
317
389
 
318
390
  To see the unresolved environment for one or more environment stacks (values are
@@ -334,6 +406,12 @@ To trace where one or more environment vars is being set:
334
406
  $ envstack [STACK] -t [VAR [VAR ...]]
335
407
  ```
336
408
 
409
+ To run commands in an environment stack:
410
+
411
+ ```bash
412
+ $ envstack [STACK] -- [COMMAND]
413
+ ```
414
+
337
415
  To get the list of source files for a given stack:
338
416
 
339
417
  ```bash
@@ -375,11 +453,20 @@ Creating and resolving environments:
375
453
  {'BAR': 'foo', 'FOO': 'foo'}
376
454
  ```
377
455
 
456
+ Create an encrypted environment:
457
+
458
+ ```python
459
+ >>> from envstack.env import Env, encrypt_environ
460
+ >>> env = Env({"SECRET": "super_secret", "PASSWORD": "my_password"})
461
+ >>> encrypted = encrypt_environ(env)
462
+ ```
463
+
378
464
  Loading and resolving predefined environments from stack files:
379
465
 
380
466
  ```python
381
467
  >>> from envstack.env import load_environ, resolve_environ
382
- >>> env = resolve_environ(load_environ(name))
468
+ >>> env = load_environ(name)
469
+ >>> resolved = resolve_environ(env)
383
470
  ```
384
471
 
385
472
  ## Running Commands
@@ -439,7 +526,7 @@ environment stack that sets a value for `${PYEXE}`:
439
526
 
440
527
  #### hello.env
441
528
  ```yaml
442
- all: &default
529
+ all: &all
443
530
  PYEXE: /usr/bin/python
444
531
  ```
445
532
 
@@ -468,6 +555,43 @@ $ hello HELLO
468
555
  world
469
556
  ```
470
557
 
558
+ #### Executing Scripts
559
+
560
+ On linux, environment stack files are also executable scripts that can be called
561
+ directly:
562
+
563
+ ```bash
564
+ $ ./env/test.env
565
+ DEPLOY_ROOT=${ROOT}/${STACK}
566
+ ENV=${STACK}
567
+ ENVPATH=${DEPLOY_ROOT}/env:${ROOT}/prod/env
568
+ HELLO=${HELLO:=world}
569
+ LOG_LEVEL=DEBUG
570
+ PATH=${DEPLOY_ROOT}/bin:${ROOT}/prod/bin:${PATH}
571
+ PYTHONPATH=${DEPLOY_ROOT}/lib/python:${ROOT}/prod/lib/python:${PYTHONPATH}
572
+ ROOT=/mnt/pipe
573
+ STACK=test
574
+ ```
575
+
576
+ Run commands inside a specific environment stack file:
577
+
578
+ ```bash
579
+ $ ./env/test.env -- <command>
580
+ ```
581
+
582
+ For example:
583
+
584
+ ```bash
585
+ $ ./env/hello.env -- echo {HELLO}
586
+ world
587
+ ```
588
+
589
+ Export a specific environment stack file:
590
+
591
+ ```bash
592
+ $ ./env/hello.env --export
593
+ ```
594
+
471
595
  ## Shells
472
596
 
473
597
  In order to set an environment stack in your current shell, the stack must be
@@ -507,13 +631,16 @@ The following environment variables are used to help manage functionality:
507
631
 
508
632
  | Name | Description |
509
633
  |------|-------------|
634
+ | DEFAULT_ENV_STACK | Name of the default environment stack (default) |
510
635
  | ENVPATH | Colon-separated paths to search for stack files |
511
636
  | IGNORE_MISSING | Ignore missing stack files when resolving environments |
512
- | STACK | Name of the current environment stack |
637
+ | STACK | Stores the name of the current environment stack |
513
638
 
514
639
  # Tests
515
640
 
516
- Unit tests can be run using pytest (currently only tested on linux):
641
+ Unit tests can be run using pytest (note: some tests fail on win32 currently).
642
+ Make sure you don't have any local .env files that may intefere with the unit
643
+ tests.
517
644
 
518
645
  ```bash
519
646
  $ pytest tests -s