senv 0.4.2 → 0.4.3
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.
- checksums.yaml +4 -4
- data/EXAMPLES.md +7 -0
- data/README.md +401 -0
- data/a.sh +2 -0
- data/bin/senv +82 -10
- data/dist/senv-0.4.3-linux-x86.tgz +0 -0
- data/dist/senv-0.4.3-linux-x86_64.tgz +0 -0
- data/dist/senv-0.4.3-osx.tgz +0 -0
- data/dist/senv.rb +86 -12
- data/lib/senv.rb +4 -2
- data/senv.gemspec +9 -7
- metadata +8 -7
- data/README +0 -14
- data/a.rb +0 -92
- data/dist/senv-0.4.2-linux-x86.tgz +0 -0
- data/dist/senv-0.4.2-linux-x86_64.tgz +0 -0
- data/dist/senv-0.4.2-osx.tgz +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ed4a908e406bfd5fee464873562d6b99314b21b532ef9f6ccde5ebbdd5c516e9
|
4
|
+
data.tar.gz: 61394517a8621bc151b3233d007256454eca77d50ac6fc20e8db33eb05d4526b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c390f086f6e7d13f72ff876a116c1c4fee103debc3726743084b6a3c9ed67291aeae86f65747e963c51ffe677b103f004ba835af80c430be6055c31c03160dd1
|
7
|
+
data.tar.gz: 0473b4cc43793f588b87bb971a1dac4d607ad9479298739fa308579948022788710c1ee2914248c2180632ded53b5ce87c1dae60f1752834f90eb373e0ea66cf
|
data/EXAMPLES.md
ADDED
data/README.md
ADDED
@@ -0,0 +1,401 @@
|
|
1
|
+
NAME
|
2
|
+
====
|
3
|
+
senv - secure 12-factor env vars for your apps, in any lang, local and remote
|
4
|
+
|
5
|
+
SYNOPSIS
|
6
|
+
========
|
7
|
+
@ syntax
|
8
|
+
|
9
|
+
~> senv @development ./node/server
|
10
|
+
|
11
|
+
~> senv @staging ./go/server
|
12
|
+
|
13
|
+
~> senv @production ./ruby/server
|
14
|
+
|
15
|
+
inline via environment variable
|
16
|
+
|
17
|
+
~> SENV=production senv ./app/server
|
18
|
+
|
19
|
+
via environment variable
|
20
|
+
|
21
|
+
~> export SENV=development
|
22
|
+
~> senv ./app/server
|
23
|
+
|
24
|
+
DESCRIPTION
|
25
|
+
===========
|
26
|
+
*senv* is a command line tool that let's you manage named sets of encrypted
|
27
|
+
environment variables across platforms, frameworks, and languages. it works
|
28
|
+
for development and production, on dev boxen, and in docker
|
29
|
+
|
30
|
+
*senv* operates over text files stored in a '.senv' directory, typically in
|
31
|
+
your project's root. in this directory are meta stuff like your key:
|
32
|
+
|
33
|
+
.senv/.key
|
34
|
+
|
35
|
+
and config files in .json, .yaml, or .rb format:
|
36
|
+
|
37
|
+
.senv/development.json
|
38
|
+
.senv/development.enc.json
|
39
|
+
.senv/production.json
|
40
|
+
.senv/production.enc.json
|
41
|
+
|
42
|
+
*NOTE:* you will never check in your .senv/.key file. *ADD IT TO YOUR .gitignore*
|
43
|
+
|
44
|
+
config files can be either non-encrypted, or encrypted. encrpted files are
|
45
|
+
stored with '.enc' in the filename, obviously.
|
46
|
+
|
47
|
+
for json, or yaml (yml) files, one can define static dictionaries of
|
48
|
+
environment key=val mappings, for example, in a file named
|
49
|
+
|
50
|
+
.senv/development.yaml
|
51
|
+
|
52
|
+
one might have:
|
53
|
+
|
54
|
+
APP_ENV : development
|
55
|
+
USE_SSL : false
|
56
|
+
|
57
|
+
and, in a file that, to the naked eye, is full of encrypted garbage, named
|
58
|
+
|
59
|
+
.senv/development.enc.yaml
|
60
|
+
|
61
|
+
something like:
|
62
|
+
|
63
|
+
API_KEY : very-sensitive-info-654321
|
64
|
+
|
65
|
+
now, you can run commands with these variables loaded into the processs'
|
66
|
+
environment with, for example
|
67
|
+
|
68
|
+
~> senv @development ./start/my/server-process.js
|
69
|
+
|
70
|
+
of course, senv also supports management of these files, for example
|
71
|
+
encrypting them is as simple as
|
72
|
+
|
73
|
+
~> cat /tmp/development.json | senv .write .senv/development.enc.json
|
74
|
+
|
75
|
+
and reading it back as simply
|
76
|
+
|
77
|
+
~> senv .read .senv/development.enc.json
|
78
|
+
|
79
|
+
it can spawn your $EDITOR directly via
|
80
|
+
|
81
|
+
~> senv .edit .senv/production.enc.rb
|
82
|
+
|
83
|
+
in addition to simple yaml, and json files, one can also load '.rb' files,
|
84
|
+
which are parsed with ruby syntax. and this can massively simplify managing
|
85
|
+
complex sets of environment variables for any application
|
86
|
+
|
87
|
+
for example, this does what you'd expect
|
88
|
+
|
89
|
+
# file : .senv/all.enc.rb
|
90
|
+
ENV['API_KEY'] = '1234-xyz'
|
91
|
+
|
92
|
+
|
93
|
+
# file : .senv/development.rb
|
94
|
+
Senv.load(:all)
|
95
|
+
ENV['DB_URL'] = 'db://dev-url'
|
96
|
+
|
97
|
+
|
98
|
+
# file : .senv/production.rb
|
99
|
+
Senv.load(:all)
|
100
|
+
ENV['DB_URL'] = 'db://prod-url'
|
101
|
+
|
102
|
+
|
103
|
+
~> senv @production
|
104
|
+
---
|
105
|
+
API_KEY : 1234-xyz
|
106
|
+
DB_URL : db://prod-url
|
107
|
+
|
108
|
+
one can access the environment as in the examples above, using the senv cli
|
109
|
+
program to run another command, but the environment can also be loaded into
|
110
|
+
your shell scripts via
|
111
|
+
|
112
|
+
# import all senv env vars into this script
|
113
|
+
eval $(senv init -)
|
114
|
+
|
115
|
+
or, in ruby programs via
|
116
|
+
|
117
|
+
require 'senv'
|
118
|
+
Senv.load( ENV['APP_ENV'] || ENV['RAILS_ENV'] || 'development' )
|
119
|
+
|
120
|
+
learn more by installing senv and running
|
121
|
+
|
122
|
+
senv .help
|
123
|
+
|
124
|
+
INSTALL
|
125
|
+
=======
|
126
|
+
senv supports 3 methods of installation
|
127
|
+
|
128
|
+
* as a standalone binary, with *zero dependencies*
|
129
|
+
* grab the distribution for your platform at https://github.com/ahoward/senv/tree/main/dist
|
130
|
+
* if you don't know which flavor of linux you are on run `uname -a` and
|
131
|
+
* look at the output
|
132
|
+
* unpack the distribution
|
133
|
+
* make sure the ./bin/ directory in the distribution is your $PATH
|
134
|
+
|
135
|
+
* as standalone ruby script/lib, depending only on ruby (not rubygems/bundler etc)
|
136
|
+
* grab the distribution here https://github.com/ahoward/senv/blob/main/dist/senv.rb
|
137
|
+
* drop it in, for example, ./lib/, and 'require "./lib/senv.rb"'
|
138
|
+
* the distribution is both the lib, and the *command line script*, so that
|
139
|
+
*same file* can be saved both as './lib/senv.rb' *and* './bin/senv', a
|
140
|
+
clever person might save just as './lib/senv.rb' and make a symlink
|
141
|
+
'./bin/senv' -> './lib/senv.rb'
|
142
|
+
|
143
|
+
* via rubygems/bundler
|
144
|
+
* in Gemfile, gem 'senv'
|
145
|
+
* or via rubygems, 'gem install senv'
|
146
|
+
|
147
|
+
BIKESHED
|
148
|
+
========
|
149
|
+
|
150
|
+
Q1:
|
151
|
+
---
|
152
|
+
|
153
|
+
isn't this an imaginary problem? aren't i still pretty professional dropping
|
154
|
+
all my crap in a .env file and calling it a day?
|
155
|
+
|
156
|
+
A1:
|
157
|
+
---
|
158
|
+
|
159
|
+
no.
|
160
|
+
|
161
|
+
you will check it in. you will put it in your backups. but most of all
|
162
|
+
you'll pass all the info inside it around in slack, email, text, and whatsapp
|
163
|
+
because you don't have a better way to give it to people. and you'll do this
|
164
|
+
for each of the 17 config settings your 12-factor app nees. check it all in,
|
165
|
+
encrypt what is sensitive, and reduce your problem to merely needing to get
|
166
|
+
the next girl *one single key* to unpack the whole lot. btw, for this, i
|
167
|
+
recommend using
|
168
|
+
|
169
|
+
https://onetimesecret.com/
|
170
|
+
|
171
|
+
now, about the key. there are two main approaches.
|
172
|
+
|
173
|
+
put it on disk, in .senv/.key, this is, at least, a large level of
|
174
|
+
indirection, an attacker needs to know a lot more, and look a lot harder to
|
175
|
+
figure out how to locate that key, and run some commands to unpack config
|
176
|
+
files. however, ideally you won't store the key on disk at all and, instead,
|
177
|
+
with either manage some symlinks such that your .senv/.key resides on a
|
178
|
+
thumbdrive, or, far simpler, just understand how to set *one variable* in your
|
179
|
+
shell and do that when working on the project, after all what could be simpler
|
180
|
+
than just doing
|
181
|
+
|
182
|
+
export SENV_ENV=teh-passwordz-y
|
183
|
+
|
184
|
+
or, super fancy
|
185
|
+
|
186
|
+
SENV_KEY=my-key exec $SHELL
|
187
|
+
|
188
|
+
or, power-neck-beard
|
189
|
+
|
190
|
+
SENV_KEY=my-key tmux
|
191
|
+
|
192
|
+
or
|
193
|
+
|
194
|
+
SENV_KEY=teh-key visual-studio-magick-coding-ide
|
195
|
+
|
196
|
+
except that last one. that won't work. if you are uncomfortable on the
|
197
|
+
command line, and manging environment variables senv may not be for you.
|
198
|
+
however, if that is the case then managing *unencrypted* files full of api
|
199
|
+
keys is *definitely not for you*
|
200
|
+
|
201
|
+
in the end. simple is better.
|
202
|
+
|
203
|
+
|
204
|
+
WHY?
|
205
|
+
====
|
206
|
+
so many tools exist to load a file full of environment variables. all of them
|
207
|
+
expose these variables to arbitrary code anytime you:
|
208
|
+
|
209
|
+
* run `npm install`, `bundle install`, `pip install`
|
210
|
+
* accidentally commit .env files to git/version control
|
211
|
+
* loose your laptop
|
212
|
+
* a trillion other sloppy ways of leaking unencrypted files full of sensitive
|
213
|
+
information from your developer machine to the world wide web
|
214
|
+
|
215
|
+
this problem is neither theoritical nor FUD based:
|
216
|
+
|
217
|
+
* https://www.helpnetsecurity.com/2020/04/17/typosquatting-rubygems/
|
218
|
+
* https://codeburst.io/how-secure-is-your-environment-file-in-node-js-7c4d2ed0d15a
|
219
|
+
* https://www.twilio.com/blog/2017/08/find-projects-infected-by-malicious-npm-packages.html
|
220
|
+
* https://blog.sonatype.com/sonatype-spots-malicious-npm-packages
|
221
|
+
* *and a million other reasons not to store unencrypted environment variables*
|
222
|
+
* https://lmgtfy.app/#gsc.tab=0&gsc.q=malicious%20packages%20env
|
223
|
+
|
224
|
+
solutions to this problem exist, i authored the original solution for the ruby
|
225
|
+
programming language:
|
226
|
+
|
227
|
+
* https://github.com/ahoward/sekrets
|
228
|
+
|
229
|
+
this solution was eventually adapted and merged into 'Ruby on Rails':
|
230
|
+
|
231
|
+
* https://github.com/rails/rails/issues/25095#issuecomment-269054302
|
232
|
+
* https://guides.rubyonrails.org/4_1_release_notes.html
|
233
|
+
|
234
|
+
solutions exist for es6, javascript, go, and many languages. each operates
|
235
|
+
differently:
|
236
|
+
|
237
|
+
* https://github.com/kunalpanchal/secure-env
|
238
|
+
* https://github.com/envkey/envkeygo
|
239
|
+
|
240
|
+
however, all of these solutions, including some of my work, operate at the
|
241
|
+
wrong level, which is to say at the language or framework level. this misses,
|
242
|
+
entirely, the point of configuring applications via the environment in the
|
243
|
+
ordained 12-factor way; by requiring tight integration, such as the addition
|
244
|
+
of libraries and tooling into projects to manage, load, and set environment
|
245
|
+
variables, we reduce significantly the simplicity of a pure 12-factor app that
|
246
|
+
does only.
|
247
|
+
|
248
|
+
const DATABASE_URL = process.env.DATABASE_URL;
|
249
|
+
|
250
|
+
it's easy to make this mistake and, so long as your project remains a
|
251
|
+
monolith, it works just fine. until it doesn't.
|
252
|
+
|
253
|
+
as many of us know, a real, modern, web project is unlikely to remain a single
|
254
|
+
process in a single framework and language. micro-services will be
|
255
|
+
introduced. background jobs will get introduced. someone will split the main
|
256
|
+
web app from the consumer app. everything will get re-written in node, and
|
257
|
+
then go. finally, each developer in every language will solve the problem
|
258
|
+
their own way, and pass around unencrypted text files full of sensitive
|
259
|
+
information all day long like someone yelling 'b-crypt' very slowly in bounded
|
260
|
+
time. someone will port the application deployment from heroku to gcp, and
|
261
|
+
re-tool setting 100 confiuration variables instead of the one meta SENV\_KEY
|
262
|
+
to rule them all. he'll be a 'dev-ops' guy, kind of an asshole, and he'll
|
263
|
+
grind deployments down from a 3 minute process to a 3 week fight about vpns.
|
264
|
+
don't be that guy.
|
265
|
+
|
266
|
+
EXAMPLES
|
267
|
+
========
|
268
|
+
# setup a directory to use senv, including making some sample config files
|
269
|
+
|
270
|
+
~> senv .setup /full/path/to/directory
|
271
|
+
|
272
|
+
# setup _this_ directory
|
273
|
+
|
274
|
+
~> senv .setup
|
275
|
+
|
276
|
+
# encrypt a file
|
277
|
+
|
278
|
+
~> senv /tmp/development.json | senv .write .senv/development.enc.json
|
279
|
+
|
280
|
+
# read a file, encrypted or not
|
281
|
+
|
282
|
+
~> senv .read .senv/development.enc.json
|
283
|
+
~> senv .read .senv/development.json
|
284
|
+
|
285
|
+
# show all the environemnt settings for the production environment
|
286
|
+
|
287
|
+
~> senv @production
|
288
|
+
|
289
|
+
# run a command under an environment
|
290
|
+
|
291
|
+
~> senv @test ./run/the/tests.js
|
292
|
+
|
293
|
+
# edit a file, encrypted or not, using the $EDITOR like all unix citizens
|
294
|
+
|
295
|
+
~> senv .edit ./senv/production.enc.rb
|
296
|
+
|
297
|
+
# pluck a single value from a config set
|
298
|
+
|
299
|
+
~> senv .get API_KEY
|
300
|
+
|
301
|
+
# load an entire senv into a shell script
|
302
|
+
|
303
|
+
#! /bin/sh
|
304
|
+
export SENV=production
|
305
|
+
eval $(senv init -)
|
306
|
+
|
307
|
+
# load senv in ruby program
|
308
|
+
|
309
|
+
#! /usr/bin/env ruby
|
310
|
+
require 'senv'
|
311
|
+
Senv.load(:all)
|
312
|
+
|
313
|
+
# setup a project with a .senv directory and key, this will drop in some
|
314
|
+
# sample files
|
315
|
+
#
|
316
|
+
|
317
|
+
~> senv .setup .
|
318
|
+
|
319
|
+
ENVIRONMENT
|
320
|
+
===========
|
321
|
+
the following environment variables affect senv itself
|
322
|
+
|
323
|
+
SENV
|
324
|
+
specify which senv should be loaded
|
325
|
+
|
326
|
+
SENV_KEY
|
327
|
+
specify the encryption key via the environment
|
328
|
+
|
329
|
+
SENV_PATH
|
330
|
+
a colon separated set of paths in which to search for '.senv' directories
|
331
|
+
|
332
|
+
SENV_ROOT
|
333
|
+
the location of the .senv directory
|
334
|
+
|
335
|
+
SENV_DEBUG
|
336
|
+
you guessed it
|
337
|
+
|
338
|
+
|
339
|
+
REFMASTER
|
340
|
+
=========
|
341
|
+
http://github.com/ahoward/senv
|
342
|
+
|
343
|
+
TL;DR;
|
344
|
+
======
|
345
|
+
it's at the bottom because everyone should read the docs ;-)
|
346
|
+
|
347
|
+
```
|
348
|
+
↟ senv[]@master $ senv .setup .
|
349
|
+
[SENV] setup /home/ahoward/git/ahoward/senv/.senv
|
350
|
+
- .senv/all.rb
|
351
|
+
- .senv/development.enc.rb
|
352
|
+
- .senv/development.rb
|
353
|
+
- .senv/production.enc.rb
|
354
|
+
- .senv/production.rb
|
355
|
+
|
356
|
+
↟ senv[]@master $ cat .senv/all.rb
|
357
|
+
ENV['A'] = 'one'
|
358
|
+
ENV['B'] = 'two'
|
359
|
+
ENV['C'] = 'three'
|
360
|
+
|
361
|
+
↟ senv[]@master $ cat .senv/production.rb
|
362
|
+
Senv.load(:all)
|
363
|
+
ENV['B'] = 'two (via production.rb)'
|
364
|
+
|
365
|
+
↟ senv[]@master $ cat .senv/production.enc.rb
|
366
|
+
0GWID?䱐xAǼdW)\ 1waxE͑!k
|
367
|
+
|
368
|
+
↟ senv[]@master $ senv .read .senv/production.enc.rb
|
369
|
+
Senv.load(:all)
|
370
|
+
ENV['C'] = 'three (via production.enc.rb)'
|
371
|
+
|
372
|
+
↟ senv[]@master $ cat .senv/.key
|
373
|
+
770db0fd-fddc-4c8c-a264-37d15766d0a5
|
374
|
+
|
375
|
+
↟ senv[]@master $ senv @production
|
376
|
+
---
|
377
|
+
A: one
|
378
|
+
B: two (via production.rb)
|
379
|
+
C: three (via production.enc.rb)
|
380
|
+
|
381
|
+
↟ senv[]@master $ rm .senv/.key
|
382
|
+
|
383
|
+
↟ senv[]@master $ senv @production
|
384
|
+
Senv.key not found in : /home/ahoward/git/ahoward/senv/.senv/.key
|
385
|
+
|
386
|
+
↟ senv[]@master $ SENV_KEY=770db0fd-fddc-4c8c-a264-37d15766d0a5 senv @proudction
|
387
|
+
---
|
388
|
+
A: one
|
389
|
+
B: two (via production.rb)
|
390
|
+
C: three (via production.enc.rb)
|
391
|
+
|
392
|
+
↟ senv[]@master $ cat a.sh
|
393
|
+
#! /bin/sh
|
394
|
+
echo $C
|
395
|
+
|
396
|
+
↟ senv[]@master $ SENV=production SENV_KEY=770db0fd-fddc-4c8c-a264-37d15766d0a5 senv ./a.sh
|
397
|
+
three (via production.enc.rb)
|
398
|
+
```
|
399
|
+
|
400
|
+
:wq
|
401
|
+
|
data/bin/senv
CHANGED
@@ -1,18 +1,79 @@
|
|
1
1
|
#! /usr/bin/env ruby
|
2
2
|
# encoding: utf-8
|
3
|
+
if $0 == __FILE__
|
3
4
|
|
4
5
|
#
|
5
6
|
HELP = <<-____
|
6
7
|
|
7
|
-
|
8
|
-
|
8
|
+
NAME
|
9
|
+
========
|
10
|
+
senv - secure 12-factor env vars for your apps, in any lang, local and remote
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
+
EXAMPLES
|
13
|
+
========
|
14
|
+
# setup a directory to use senv, including making some sample config files
|
15
|
+
|
16
|
+
~> senv .setup /full/path/to/directory
|
12
17
|
|
13
|
-
|
18
|
+
# setup _this_ directory
|
14
19
|
|
15
|
-
|
20
|
+
~> senv .setup
|
21
|
+
|
22
|
+
# encrypt a file
|
23
|
+
|
24
|
+
~> senv /tmp/development.json | senv .write .senv/development.enc.json
|
25
|
+
|
26
|
+
# read a file, encrypted or not
|
27
|
+
|
28
|
+
~> senv .read .senv/development.enc.json
|
29
|
+
~> senv .read .senv/development.json
|
30
|
+
|
31
|
+
# show all the environemnt settings for the production environment
|
32
|
+
|
33
|
+
~> senv @production
|
34
|
+
|
35
|
+
# run a command under an environment
|
36
|
+
|
37
|
+
~> senv @test ./run/the/tests.js
|
38
|
+
|
39
|
+
# edit a file, encrypted or not, using the $EDITOR like all unix citizens
|
40
|
+
|
41
|
+
~> senv .edit ./senv/production.enc.rb
|
42
|
+
|
43
|
+
# pluck a single value from a config set
|
44
|
+
|
45
|
+
~> senv .get API_KEY
|
46
|
+
|
47
|
+
# load an entire senv into a shell script
|
48
|
+
|
49
|
+
#! /bin/sh
|
50
|
+
export SENV=production
|
51
|
+
eval $(senv init -)
|
52
|
+
|
53
|
+
# load senv into yer ruby program
|
54
|
+
|
55
|
+
#! /usr/bin/env ruby
|
56
|
+
require 'senv'
|
57
|
+
Senv.load(:all)
|
58
|
+
|
59
|
+
ENVIRONMENT
|
60
|
+
===========
|
61
|
+
the following environment variables affect senv itself
|
62
|
+
|
63
|
+
SENV
|
64
|
+
specify which senv should be loaded
|
65
|
+
|
66
|
+
SENV_KEY
|
67
|
+
specify the encryption key via the environment
|
68
|
+
|
69
|
+
SENV_PATH
|
70
|
+
a colon separated set of paths in which to search for '.senv' directories
|
71
|
+
|
72
|
+
SENV_ROOT
|
73
|
+
the location of the .senv directory
|
74
|
+
|
75
|
+
SENV_DEBUG
|
76
|
+
you guessed it
|
16
77
|
|
17
78
|
____
|
18
79
|
|
@@ -81,17 +142,23 @@
|
|
81
142
|
|
82
143
|
key.strip!
|
83
144
|
|
145
|
+
dir = File.expand_path(dir)
|
146
|
+
|
147
|
+
FileUtils.mkdir_p(dir)
|
148
|
+
|
84
149
|
Dir.chdir(dir) do
|
150
|
+
#
|
85
151
|
if test(?d, '.senv')
|
86
152
|
abort "#{ dir }/.senv directory exists"
|
87
153
|
end
|
88
154
|
|
89
155
|
FileUtils.mkdir_p('.senv')
|
90
156
|
|
91
|
-
IO.binwrite('.senv
|
157
|
+
IO.binwrite('.senv/.key', "#{ key }\n")
|
92
158
|
|
93
159
|
Senv.key = key
|
94
160
|
|
161
|
+
#
|
95
162
|
Senv.write(
|
96
163
|
'.senv/all.rb',
|
97
164
|
u.unindent(
|
@@ -109,7 +176,6 @@
|
|
109
176
|
u.unindent(
|
110
177
|
<<-____
|
111
178
|
Senv.load(:all)
|
112
|
-
|
113
179
|
ENV['B'] = 'two (via #{ env }.rb)'
|
114
180
|
____
|
115
181
|
)
|
@@ -120,14 +186,14 @@
|
|
120
186
|
u.unindent(
|
121
187
|
<<-____
|
122
188
|
Senv.load(:all)
|
123
|
-
|
124
189
|
ENV['C'] = 'three (via #{ env }.enc.rb)'
|
125
190
|
____
|
126
191
|
)
|
127
192
|
)
|
128
193
|
end
|
129
194
|
|
130
|
-
|
195
|
+
#
|
196
|
+
puts "[SENV] setup #{ dir }/.senv"
|
131
197
|
|
132
198
|
Dir.glob('.senv/**/**').sort.each do |entry|
|
133
199
|
next unless test(?f, entry)
|
@@ -225,6 +291,10 @@
|
|
225
291
|
end
|
226
292
|
end
|
227
293
|
|
294
|
+
run '.help' do
|
295
|
+
show_help!
|
296
|
+
end
|
297
|
+
|
228
298
|
#
|
229
299
|
def show_help!
|
230
300
|
help = ERB.new(u.unindent(HELP)).result(::TOPLEVEL_BINDING)
|
@@ -257,3 +327,5 @@
|
|
257
327
|
end
|
258
328
|
end
|
259
329
|
end
|
330
|
+
|
331
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
data/dist/senv.rb
CHANGED
@@ -1,18 +1,79 @@
|
|
1
1
|
#! /usr/bin/env ruby
|
2
2
|
# encoding: utf-8
|
3
|
+
if $0 == __FILE__
|
3
4
|
|
4
5
|
#
|
5
6
|
HELP = <<-____
|
6
7
|
|
7
|
-
|
8
|
-
|
8
|
+
NAME
|
9
|
+
========
|
10
|
+
senv - secure 12-factor env vars for your apps, in any lang, local and remote
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
+
EXAMPLES
|
13
|
+
========
|
14
|
+
# setup a directory to use senv, including making some sample config files
|
15
|
+
|
16
|
+
~> senv .setup /full/path/to/directory
|
12
17
|
|
13
|
-
|
18
|
+
# setup _this_ directory
|
14
19
|
|
15
|
-
|
20
|
+
~> senv .setup
|
21
|
+
|
22
|
+
# encrypt a file
|
23
|
+
|
24
|
+
~> senv /tmp/development.json | senv .write .senv/development.enc.json
|
25
|
+
|
26
|
+
# read a file, encrypted or not
|
27
|
+
|
28
|
+
~> senv .read .senv/development.enc.json
|
29
|
+
~> senv .read .senv/development.json
|
30
|
+
|
31
|
+
# show all the environemnt settings for the production environment
|
32
|
+
|
33
|
+
~> senv @production
|
34
|
+
|
35
|
+
# run a command under an environment
|
36
|
+
|
37
|
+
~> senv @test ./run/the/tests.js
|
38
|
+
|
39
|
+
# edit a file, encrypted or not, using the $EDITOR like all unix citizens
|
40
|
+
|
41
|
+
~> senv .edit ./senv/production.enc.rb
|
42
|
+
|
43
|
+
# pluck a single value from a config set
|
44
|
+
|
45
|
+
~> senv .get API_KEY
|
46
|
+
|
47
|
+
# load an entire senv into a shell script
|
48
|
+
|
49
|
+
#! /bin/sh
|
50
|
+
export SENV=production
|
51
|
+
eval $(senv init -)
|
52
|
+
|
53
|
+
# load senv into yer ruby program
|
54
|
+
|
55
|
+
#! /usr/bin/env ruby
|
56
|
+
require 'senv'
|
57
|
+
Senv.load(:all)
|
58
|
+
|
59
|
+
ENVIRONMENT
|
60
|
+
===========
|
61
|
+
the following environment variables affect senv itself
|
62
|
+
|
63
|
+
SENV
|
64
|
+
specify which senv should be loaded
|
65
|
+
|
66
|
+
SENV_KEY
|
67
|
+
specify the encryption key via the environment
|
68
|
+
|
69
|
+
SENV_PATH
|
70
|
+
a colon separated set of paths in which to search for '.senv' directories
|
71
|
+
|
72
|
+
SENV_ROOT
|
73
|
+
the location of the .senv directory
|
74
|
+
|
75
|
+
SENV_DEBUG
|
76
|
+
you guessed it
|
16
77
|
|
17
78
|
____
|
18
79
|
|
@@ -81,17 +142,23 @@
|
|
81
142
|
|
82
143
|
key.strip!
|
83
144
|
|
145
|
+
dir = File.expand_path(dir)
|
146
|
+
|
147
|
+
FileUtils.mkdir_p(dir)
|
148
|
+
|
84
149
|
Dir.chdir(dir) do
|
150
|
+
#
|
85
151
|
if test(?d, '.senv')
|
86
152
|
abort "#{ dir }/.senv directory exists"
|
87
153
|
end
|
88
154
|
|
89
155
|
FileUtils.mkdir_p('.senv')
|
90
156
|
|
91
|
-
IO.binwrite('.senv
|
157
|
+
IO.binwrite('.senv/.key', "#{ key }\n")
|
92
158
|
|
93
159
|
Senv.key = key
|
94
160
|
|
161
|
+
#
|
95
162
|
Senv.write(
|
96
163
|
'.senv/all.rb',
|
97
164
|
u.unindent(
|
@@ -109,7 +176,6 @@
|
|
109
176
|
u.unindent(
|
110
177
|
<<-____
|
111
178
|
Senv.load(:all)
|
112
|
-
|
113
179
|
ENV['B'] = 'two (via #{ env }.rb)'
|
114
180
|
____
|
115
181
|
)
|
@@ -120,14 +186,14 @@
|
|
120
186
|
u.unindent(
|
121
187
|
<<-____
|
122
188
|
Senv.load(:all)
|
123
|
-
|
124
189
|
ENV['C'] = 'three (via #{ env }.enc.rb)'
|
125
190
|
____
|
126
191
|
)
|
127
192
|
)
|
128
193
|
end
|
129
194
|
|
130
|
-
|
195
|
+
#
|
196
|
+
puts "[SENV] setup #{ dir }/.senv"
|
131
197
|
|
132
198
|
Dir.glob('.senv/**/**').sort.each do |entry|
|
133
199
|
next unless test(?f, entry)
|
@@ -225,6 +291,10 @@
|
|
225
291
|
end
|
226
292
|
end
|
227
293
|
|
294
|
+
run '.help' do
|
295
|
+
show_help!
|
296
|
+
end
|
297
|
+
|
228
298
|
#
|
229
299
|
def show_help!
|
230
300
|
help = ERB.new(u.unindent(HELP)).result(::TOPLEVEL_BINDING)
|
@@ -258,6 +328,8 @@
|
|
258
328
|
end
|
259
329
|
end
|
260
330
|
|
331
|
+
end
|
332
|
+
|
261
333
|
|
262
334
|
BEGIN {
|
263
335
|
|
@@ -280,7 +352,7 @@ BEGIN {
|
|
280
352
|
#
|
281
353
|
module Senv
|
282
354
|
#
|
283
|
-
VERSION = '0.4.
|
355
|
+
VERSION = '0.4.3'.freeze
|
284
356
|
|
285
357
|
def Senv.version
|
286
358
|
VERSION
|
@@ -562,7 +634,7 @@ BEGIN {
|
|
562
634
|
end
|
563
635
|
|
564
636
|
def Senv.key_path
|
565
|
-
Senv.directory.join('
|
637
|
+
Senv.directory.join('.key')
|
566
638
|
end
|
567
639
|
|
568
640
|
def Senv.key
|
@@ -641,6 +713,8 @@ BEGIN {
|
|
641
713
|
end
|
642
714
|
end
|
643
715
|
|
716
|
+
FileUtils.mkdir_p(File.dirname(path))
|
717
|
+
|
644
718
|
IO.binwrite(path, data)
|
645
719
|
end
|
646
720
|
|
data/lib/senv.rb
CHANGED
@@ -15,7 +15,7 @@
|
|
15
15
|
#
|
16
16
|
module Senv
|
17
17
|
#
|
18
|
-
VERSION = '0.4.
|
18
|
+
VERSION = '0.4.3'.freeze
|
19
19
|
|
20
20
|
def Senv.version
|
21
21
|
VERSION
|
@@ -297,7 +297,7 @@
|
|
297
297
|
end
|
298
298
|
|
299
299
|
def Senv.key_path
|
300
|
-
Senv.directory.join('
|
300
|
+
Senv.directory.join('.key')
|
301
301
|
end
|
302
302
|
|
303
303
|
def Senv.key
|
@@ -376,6 +376,8 @@
|
|
376
376
|
end
|
377
377
|
end
|
378
378
|
|
379
|
+
FileUtils.mkdir_p(File.dirname(path))
|
380
|
+
|
379
381
|
IO.binwrite(path, data)
|
380
382
|
end
|
381
383
|
|
data/senv.gemspec
CHANGED
@@ -3,29 +3,31 @@
|
|
3
3
|
|
4
4
|
Gem::Specification::new do |spec|
|
5
5
|
spec.name = "senv"
|
6
|
-
spec.version = "0.4.
|
6
|
+
spec.version = "0.4.3"
|
7
7
|
spec.platform = Gem::Platform::RUBY
|
8
8
|
spec.summary = "senv"
|
9
9
|
spec.description = "description: senv kicks the ass"
|
10
10
|
spec.license = "MIT"
|
11
11
|
|
12
12
|
spec.files =
|
13
|
-
["
|
14
|
-
"
|
13
|
+
["EXAMPLES.md",
|
14
|
+
"LICENSE",
|
15
|
+
"README.md",
|
15
16
|
"Rakefile",
|
16
|
-
"a.
|
17
|
+
"a.sh",
|
17
18
|
"bin",
|
18
19
|
"bin/senv",
|
19
20
|
"dist",
|
20
|
-
"dist/senv-0.4.
|
21
|
-
"dist/senv-0.4.
|
22
|
-
"dist/senv-0.4.
|
21
|
+
"dist/senv-0.4.3-linux-x86.tgz",
|
22
|
+
"dist/senv-0.4.3-linux-x86_64.tgz",
|
23
|
+
"dist/senv-0.4.3-osx.tgz",
|
23
24
|
"dist/senv.rb",
|
24
25
|
"dist/senv.sh",
|
25
26
|
"lib",
|
26
27
|
"lib/senv",
|
27
28
|
"lib/senv.rb",
|
28
29
|
"lib/senv/script.rb",
|
30
|
+
"samples",
|
29
31
|
"senv.gemspec"]
|
30
32
|
|
31
33
|
spec.executables = ["senv"]
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: senv
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ara T. Howard
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-01-
|
11
|
+
date: 2021-01-19 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: 'description: senv kicks the ass'
|
14
14
|
email: ara.t.howard@gmail.com
|
@@ -17,14 +17,15 @@ executables:
|
|
17
17
|
extensions: []
|
18
18
|
extra_rdoc_files: []
|
19
19
|
files:
|
20
|
+
- EXAMPLES.md
|
20
21
|
- LICENSE
|
21
|
-
- README
|
22
|
+
- README.md
|
22
23
|
- Rakefile
|
23
|
-
- a.
|
24
|
+
- a.sh
|
24
25
|
- bin/senv
|
25
|
-
- dist/senv-0.4.
|
26
|
-
- dist/senv-0.4.
|
27
|
-
- dist/senv-0.4.
|
26
|
+
- dist/senv-0.4.3-linux-x86.tgz
|
27
|
+
- dist/senv-0.4.3-linux-x86_64.tgz
|
28
|
+
- dist/senv-0.4.3-osx.tgz
|
28
29
|
- dist/senv.rb
|
29
30
|
- dist/senv.sh
|
30
31
|
- lib/senv.rb
|
data/README
DELETED
data/a.rb
DELETED
@@ -1,92 +0,0 @@
|
|
1
|
-
task :dist => [:dist_rb] do
|
2
|
-
Dir.chdir(This.dir)
|
3
|
-
|
4
|
-
version = This.version
|
5
|
-
name = This.name.downcase
|
6
|
-
|
7
|
-
platforms = %w[
|
8
|
-
linux-x86 linux-x86_64 osx
|
9
|
-
]
|
10
|
-
|
11
|
-
Dir.glob("./dist/#{ name }-*").each{|entry| FileUtils.rm_rf(entry)}
|
12
|
-
|
13
|
-
spawn = proc{|cmd| system(cmd) or abort("#{ cmd } #=> #{ $? }")}
|
14
|
-
|
15
|
-
entrypoint = File.expand_path("./dist/#{ name }.sh")
|
16
|
-
|
17
|
-
platforms.each do |platform|
|
18
|
-
distdir = "./dist/#{ name }-#{ version }-#{ platform }"
|
19
|
-
FileUtils.mkdir_p(distdir)
|
20
|
-
|
21
|
-
libdir = File.join(distdir, 'lib')
|
22
|
-
FileUtils.mkdir_p(libdir)
|
23
|
-
|
24
|
-
appdir = File.join(libdir, 'app')
|
25
|
-
FileUtils.mkdir_p(appdir)
|
26
|
-
|
27
|
-
rubydir = File.join(libdir, 'ruby')
|
28
|
-
FileUtils.mkdir_p(rubydir)
|
29
|
-
|
30
|
-
FileUtils.cp('./dist/senv.rb', appdir)
|
31
|
-
|
32
|
-
Dir.chdir(rubydir) do
|
33
|
-
basename = "traveling-ruby-20141215-2.1.5-#{ platform }.tar.gz"
|
34
|
-
cmd = "curl -s -L -O --fail https://d6r77u77i8pq3.cloudfront.net/releases/#{ basename }"
|
35
|
-
spawn[cmd]
|
36
|
-
spawn["tar -xzf #{ basename }"]
|
37
|
-
FileUtils.rm(basename)
|
38
|
-
end
|
39
|
-
|
40
|
-
Dir.chdir(distdir) do
|
41
|
-
FileUtils.cp(entrypoint, name)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
system('tree -L 4 dist 2>/dev/null') if STDOUT.tty?
|
46
|
-
|
47
|
-
Dir.chdir './dist' do
|
48
|
-
platforms.each do |platform|
|
49
|
-
dist = "#{ name }-#{ version }-#{ platform }"
|
50
|
-
spawn["tar cvfz #{ dist }.tgz ./#{ dist } >/dev/null 2>&1"]
|
51
|
-
FileUtils.rm_rf(dist)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
HELP = <<-____.tap{|s| s.gsub!(s[%r/^\s*/], '')}
|
60
|
-
VERSION
|
61
|
-
<%= Senv.version %>
|
62
|
-
|
63
|
-
TL;DR;
|
64
|
-
|
65
|
-
$ tree ./config/senvs/
|
66
|
-
|
67
|
-
config/senvs/
|
68
|
-
development.enc.rb
|
69
|
-
development.rb
|
70
|
-
development.yml
|
71
|
-
development.json
|
72
|
-
production.enc.rb
|
73
|
-
production.rb
|
74
|
-
production.yml
|
75
|
-
staging.json
|
76
|
-
staging.enc.rb
|
77
|
-
staging.rb
|
78
|
-
staging.yml
|
79
|
-
staging.json
|
80
|
-
|
81
|
-
|
82
|
-
~> export SENV=production
|
83
|
-
|
84
|
-
~> ./bin/senv run-something-in-production senv
|
85
|
-
|
86
|
-
~> ./bin/senv @staging # show it
|
87
|
-
|
88
|
-
~> ./bin/senv @staging run-something-in-staging-senv
|
89
|
-
|
90
|
-
____
|
91
|
-
|
92
|
-
puts HELP
|
Binary file
|
Binary file
|
data/dist/senv-0.4.2-osx.tgz
DELETED
Binary file
|