senv 0.4.2 → 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|