sym 2.8.0 → 2.10.0
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 +5 -5
- data/.circleci/config.yml +30 -31
- data/.envrc +7 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +150 -928
- data/.travis.yml +16 -26
- data/CHANGELOG.md +206 -167
- data/Gemfile +1 -0
- data/README.adoc +650 -0
- data/Rakefile +9 -3
- data/bin/{sym.completion → sym.completion.bash} +9 -14
- data/bin/sym.symit.bash +781 -0
- data/codecov.yml +29 -0
- data/design/sym-help.png +0 -0
- data/exe/keychain +1 -1
- data/exe/sym +5 -2
- data/lib/ruby_warnings.rb +7 -0
- data/lib/sym.rb +1 -7
- data/lib/sym/app.rb +1 -1
- data/lib/sym/app/args.rb +3 -2
- data/lib/sym/app/cli.rb +1 -2
- data/lib/sym/app/cli_slop.rb +1 -1
- data/lib/sym/app/commands.rb +1 -1
- data/lib/sym/app/commands/base_command.rb +1 -1
- data/lib/sym/app/commands/bash_completion.rb +20 -8
- data/lib/sym/app/commands/open_editor.rb +1 -1
- data/lib/sym/app/commands/password_protect_key.rb +4 -4
- data/lib/sym/app/commands/show_examples.rb +1 -1
- data/lib/sym/app/input/handler.rb +7 -1
- data/lib/sym/app/keychain.rb +15 -9
- data/lib/sym/app/output/noop.rb +2 -1
- data/lib/sym/app/password/cache.rb +1 -1
- data/lib/sym/app/password/providers.rb +2 -3
- data/lib/sym/app/private_key/decryptor.rb +2 -2
- data/lib/sym/app/private_key/detector.rb +4 -7
- data/lib/sym/application.rb +6 -11
- data/lib/sym/constants.rb +28 -13
- data/lib/sym/data/wrapper_struct.rb +20 -12
- data/lib/sym/errors.rb +11 -2
- data/lib/sym/extensions/instance_methods.rb +7 -8
- data/lib/sym/extensions/stdlib.rb +0 -1
- data/lib/sym/extensions/with_retry.rb +1 -1
- data/lib/sym/extensions/with_timeout.rb +1 -1
- data/lib/sym/version.rb +30 -5
- data/sym.gemspec +35 -35
- metadata +88 -71
- data/.codeclimate.yml +0 -30
- data/README.md +0 -623
- data/bin/sym.symit +0 -565
- data/lib/sym/app/password/providers/drb_provider.rb +0 -41
data/Rakefile
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
require 'bundler/gem_tasks'
|
2
2
|
require 'rspec/core/rake_task'
|
3
|
+
require 'rubocop/rake_task'
|
3
4
|
require 'yard'
|
4
|
-
|
5
|
+
require 'timeout'
|
5
6
|
|
6
7
|
def shell(*args)
|
7
8
|
puts "running: #{args.join(' ')}"
|
@@ -25,12 +26,17 @@ task :build => :permissions
|
|
25
26
|
|
26
27
|
YARD::Rake::YardocTask.new(:doc) do |t|
|
27
28
|
t.files = %w(lib/**/*.rb exe/*.rb - README.md LICENSE)
|
28
|
-
t.options.unshift('--title','"Sym – Symmetric Key Encryption for Your Data"')
|
29
|
-
t.after = ->
|
29
|
+
t.options.unshift('--title', '"Sym – Symmetric Key Encryption for Your Data"')
|
30
|
+
t.after = -> { exec('open doc/index.html') }
|
30
31
|
end
|
31
32
|
|
32
33
|
RSpec::Core::RakeTask.new(:spec)
|
33
34
|
|
35
|
+
RuboCop::RakeTask.new
|
36
|
+
|
34
37
|
task :default => :spec
|
35
38
|
|
36
39
|
|
40
|
+
|
41
|
+
|
42
|
+
|
@@ -11,24 +11,19 @@
|
|
11
11
|
( [[ -n $ZSH_EVAL_CONTEXT && $ZSH_EVAL_CONTEXT =~ :file$ ]] || \
|
12
12
|
[[ -n $BASH_VERSION && $0 != "$BASH_SOURCE" ]]) && _s_=1 || _s_=0
|
13
13
|
|
14
|
-
bash_version=$(
|
14
|
+
bash_version=$(bash --version | awk '{FS="version"}{print $4}')
|
15
15
|
bash_version=${bash_version:0:1}
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
declare -a bash_completion_locations=(/usr/local/etc/bash_completion /usr/etc/bash_completion /etc/bash_completion)
|
25
|
-
loaded=false
|
26
|
-
for file in ${bash_completion_locations[@]}; do
|
27
|
-
[[ -s $file ]] && {
|
28
|
-
source $file
|
17
|
+
[[ -z $(type _filedir 2>/dev/null) ]] && {
|
18
|
+
declare -a bash_completion_locations=(/usr/local/etc/bash_completion /usr/etc/bash_completion /etc/bash_completion)
|
19
|
+
loaded=false
|
20
|
+
for file in ${bash_completion_locations[@]}; do
|
21
|
+
[[ -s ${file} ]] && {
|
22
|
+
source ${file}
|
29
23
|
break
|
30
24
|
}
|
31
|
-
done
|
25
|
+
done
|
26
|
+
}
|
32
27
|
|
33
28
|
_sym_long_opts() {
|
34
29
|
sym -h | grep -- '--' | egrep '^ -' | awk '{print $2}' | sort
|
data/bin/sym.symit.bash
ADDED
@@ -0,0 +1,781 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
#
|
3
|
+
# (c) 2017-2018 Konstantin Gredeskoul
|
4
|
+
#
|
5
|
+
# MIT License, distributed as part of `sym` ruby gem.
|
6
|
+
# • https://github.com/kigster/sym
|
7
|
+
#
|
8
|
+
#==============================================================================
|
9
|
+
#
|
10
|
+
# The purpose of this script is to transparently edit application secrets in
|
11
|
+
# Rails apps or other projects. It simplifies the process of key import, as well
|
12
|
+
# as the direct editing, as well as multi-file encryption/decryption routines.
|
13
|
+
#
|
14
|
+
# The idea is that you set some of the variables below to values specific to your
|
15
|
+
# system and working with encrypted files will become very easy.
|
16
|
+
#
|
17
|
+
# SYMIT__FOLDER is a relative folder to your project root, under which you
|
18
|
+
# might keep ALL of your encrypted files. Alternatively, if you keep encrypted
|
19
|
+
# files sprinkled around your project, just leave it out, because it defaults
|
20
|
+
# to "." — the current folder, and search anything beneath.
|
21
|
+
#
|
22
|
+
# Variables:
|
23
|
+
#
|
24
|
+
# # only search ./config folder
|
25
|
+
# export SYMIT__FOLDER="config"
|
26
|
+
#
|
27
|
+
# # this will be the name of your key in OS-X KeyChain
|
28
|
+
# export SYMIT__KEY="my-org.engineering.dev" # just a name
|
29
|
+
#
|
30
|
+
# # This is the extension given to the encrypted files. Ideally, leave it
|
31
|
+
# # be as ".enc"
|
32
|
+
# export SYMIT__EXTENSION=".enc"
|
33
|
+
#
|
34
|
+
# And then
|
35
|
+
#
|
36
|
+
# symit import key [ insecure ] # import a key and password-protect it (or not)
|
37
|
+
# symit auto application.yml.enc # auto-decrypts it
|
38
|
+
# symit auto application.yml # auto-encrypts it
|
39
|
+
# symit decrypt application.yml # finds application.yml.enc and decrypts that.
|
40
|
+
#
|
41
|
+
#
|
42
|
+
# ...and vola! You are editing the encrypted file with sym from the root of
|
43
|
+
# your Rails application. Neat, no?
|
44
|
+
#
|
45
|
+
|
46
|
+
|
47
|
+
# Check if we are being sourced in, or run as a script:
|
48
|
+
( [[ -n ${ZSH_EVAL_CONTEXT} && ${ZSH_EVAL_CONTEXT} =~ :file$ ]] || \
|
49
|
+
[[ -n $BASH_VERSION && $0 != "$BASH_SOURCE" ]]) && _s_=1 || _s_=0
|
50
|
+
|
51
|
+
(( $_s_ )) && _is_sourced=1
|
52
|
+
(( $_s_ )) || _is_sourced=0
|
53
|
+
|
54
|
+
# Set all the defaults
|
55
|
+
function __symit::init() {
|
56
|
+
export SYMIT__EXTENSION=${SYMIT__EXTENSION:-'.enc'}
|
57
|
+
export SYMIT__FOLDER=${SYMIT__FOLDER:-'.'}
|
58
|
+
export SYMIT__KEY=${SYMIT__KEY}
|
59
|
+
export SYMIT__MIN_VERSION='latest'
|
60
|
+
}
|
61
|
+
|
62
|
+
# Returns name of the current shell, eg 'bash'
|
63
|
+
function __lib::shell::name() {
|
64
|
+
echo $(basename $(printf $SHELL))
|
65
|
+
}
|
66
|
+
|
67
|
+
# Returns 'yes' if current shell is BASH
|
68
|
+
function __lib::shell::is_bash() {
|
69
|
+
[[ $(__lib::shell::name) == "bash" ]] && echo yes
|
70
|
+
}
|
71
|
+
|
72
|
+
# Returns a number representing shell version, eg.
|
73
|
+
# 3 or 4 for BASH v3 and v4 respectively.
|
74
|
+
function __lib::bash::version_number() {
|
75
|
+
echo $BASH_VERSION | awk 'BEGIN{FS="."}{print $1}'
|
76
|
+
}
|
77
|
+
|
78
|
+
# Enable all colors, but only if the STDOUT is a terminal
|
79
|
+
function __lib::color::setup() {
|
80
|
+
if [[ -t 1 ]]; then
|
81
|
+
export txtblk='\e[0;30m' # Black - Regular
|
82
|
+
export txtred='\e[0;31m' # Red
|
83
|
+
export txtgrn='\e[0;32m' # Green
|
84
|
+
export txtylw='\e[0;33m' # Yellow
|
85
|
+
export txtblu='\e[0;34m' # Blue
|
86
|
+
export txtpur='\e[0;35m' # Purple
|
87
|
+
export txtcyn='\e[0;36m' # Cyan
|
88
|
+
export txtwht='\e[0;37m' # White
|
89
|
+
|
90
|
+
export bldblk='\e[1;30m' # Black - Bold
|
91
|
+
export bldred='\e[1;31m' # Red
|
92
|
+
export bldgrn='\e[1;32m' # Green
|
93
|
+
export bldylw='\e[1;33m' # Yellow
|
94
|
+
export bldblu='\e[1;34m' # Blue
|
95
|
+
export bldpur='\e[1;35m' # Purple
|
96
|
+
export bldcyn='\e[1;36m' # Cyan
|
97
|
+
export bldwht='\e[1;37m' # White
|
98
|
+
|
99
|
+
export unkblk='\e[4;30m' # Black - Underline
|
100
|
+
export undred='\e[4;31m' # Red
|
101
|
+
export undgrn='\e[4;32m' # Green
|
102
|
+
export undylw='\e[4;33m' # Yellow
|
103
|
+
export undblu='\e[4;34m' # Blue
|
104
|
+
export undpur='\e[4;35m' # Purple
|
105
|
+
export undcyn='\e[4;36m' # Cyan
|
106
|
+
export undwht='\e[4;37m' # White
|
107
|
+
|
108
|
+
export bakblk='\e[40m' # Black - Background
|
109
|
+
export bakred='\e[41m' # Red
|
110
|
+
export bakgrn='\e[42m' # Green
|
111
|
+
export bakylw='\e[43m' # Yellow
|
112
|
+
export bakblu='\e[44m' # Blue
|
113
|
+
export bakpur='\e[45m' # Purple
|
114
|
+
export bakcyn='\e[46m' # Cyan
|
115
|
+
export bakwht='\e[47m' # White
|
116
|
+
|
117
|
+
export clr='\e[0m' # Text Reset
|
118
|
+
export txtrst='\e[0m' # Text Reset
|
119
|
+
export rst='\e[0m' # Text Reset
|
120
|
+
fi
|
121
|
+
}
|
122
|
+
|
123
|
+
# Unset all the colors, in case we a being piped into
|
124
|
+
# something else.
|
125
|
+
function __lib::color::reset() {
|
126
|
+
export txtblk=
|
127
|
+
export txtred=
|
128
|
+
export txtgrn=
|
129
|
+
export txtylw=
|
130
|
+
export txtblu=
|
131
|
+
export txtpur=
|
132
|
+
export txtcyn=
|
133
|
+
export txtwht=
|
134
|
+
|
135
|
+
export bldblk=
|
136
|
+
export bldred=
|
137
|
+
export bldgrn=
|
138
|
+
export bldylw=
|
139
|
+
export bldblu=
|
140
|
+
export bldpur=
|
141
|
+
export bldcyn=
|
142
|
+
export bldwht=
|
143
|
+
|
144
|
+
export unkblk=
|
145
|
+
export undred=
|
146
|
+
export undgrn=
|
147
|
+
export undylw=
|
148
|
+
export undblu=
|
149
|
+
export undpur=
|
150
|
+
export undcyn=
|
151
|
+
export undwht=
|
152
|
+
|
153
|
+
export bakblk=
|
154
|
+
export bakred=
|
155
|
+
export bakgrn=
|
156
|
+
export bakylw=
|
157
|
+
export bakblu=
|
158
|
+
export bakpur=
|
159
|
+
export bakcyn=
|
160
|
+
export bakwht=
|
161
|
+
|
162
|
+
export clr=
|
163
|
+
export txtrst=
|
164
|
+
export rst=
|
165
|
+
}
|
166
|
+
|
167
|
+
# Enable or disable the colors based on whether the STDOUT
|
168
|
+
# is a proper terminal, or a pipe.
|
169
|
+
function __lib::stdout::configure() {
|
170
|
+
if [[ -t 1 ]]; then
|
171
|
+
__lib::color::setup
|
172
|
+
else
|
173
|
+
__lib::color::reset
|
174
|
+
fi
|
175
|
+
}
|
176
|
+
|
177
|
+
__lib::stdout::configure
|
178
|
+
|
179
|
+
# Check if we are being run as a script, and if so — bail.
|
180
|
+
(( $_s_ )) || {
|
181
|
+
printf "${bldred}This script is meant to be sourced into your environment,\n"
|
182
|
+
printf "not run on a command line.${clr} \n\n"
|
183
|
+
|
184
|
+
printf "Please add 'source $0' to your BASH initialization file,\n"
|
185
|
+
printf "or run the following command:\n\n"
|
186
|
+
|
187
|
+
printf " \$ ${bldgrn}sym -B ~/.bash_profile${clr}\n\n"
|
188
|
+
|
189
|
+
printf "${bldblu}Thanks for using Sym!${clr}\n"
|
190
|
+
exit 1
|
191
|
+
}
|
192
|
+
|
193
|
+
# Horizontal line, width of the full terminal
|
194
|
+
function __lib::color::hr() {
|
195
|
+
local cols=${1:-${COLUMNS}}
|
196
|
+
local char=${2:-"—"}
|
197
|
+
local color=${3:-${txtylw}}
|
198
|
+
|
199
|
+
printf "${color}"
|
200
|
+
eval "printf \"%0.s${char}\" {1..${cols}}"
|
201
|
+
printf "${clr}\n"
|
202
|
+
}
|
203
|
+
|
204
|
+
# Large header, all caps
|
205
|
+
function __lib::color::h1() {
|
206
|
+
local title=$(echo "$*" | tr 'a-z' 'A-Z')
|
207
|
+
len=${#title}
|
208
|
+
printf "${bldylw}${title}\n"
|
209
|
+
__lib::color::hr ${len} '─'
|
210
|
+
}
|
211
|
+
|
212
|
+
# Smaller header
|
213
|
+
function __lib::color::h2() {
|
214
|
+
printf "${bldpur}$*${clr}\n"
|
215
|
+
}
|
216
|
+
|
217
|
+
# Shift cursor by N positions to the right
|
218
|
+
function __lib::color::cursor-right-by() {
|
219
|
+
position=$1
|
220
|
+
printf "\e[${position}C"
|
221
|
+
}
|
222
|
+
|
223
|
+
# Shift cursor by N positions to the left
|
224
|
+
function __lib::color::cursor-left-by() {
|
225
|
+
position=$1
|
226
|
+
printf "\e[${position}D"
|
227
|
+
}
|
228
|
+
|
229
|
+
# Shift cursor by N positions up
|
230
|
+
function __lib::color::cursor-up-by() {
|
231
|
+
position=$1
|
232
|
+
printf "\e[${position}A"
|
233
|
+
}
|
234
|
+
|
235
|
+
# Shift cursor by N positions down
|
236
|
+
function __lib::color::cursor-down-by() {
|
237
|
+
position=$1
|
238
|
+
printf "\e[${position}B"
|
239
|
+
}
|
240
|
+
|
241
|
+
# Convert a version string such as "1.50.17" to an integer
|
242
|
+
# 101050017 for numeric comparison:
|
243
|
+
function __lib::ver-to-i() {
|
244
|
+
version=${1}
|
245
|
+
echo ${version} | awk 'BEGIN{FS="."}{ printf "1%02d%03.3d%03.3d", $1, $2, $3}'
|
246
|
+
}
|
247
|
+
|
248
|
+
# Convert a result of __lib::ver-to-i() back to a regular version.
|
249
|
+
function __lib::i-to-ver() {
|
250
|
+
version=${1}
|
251
|
+
/usr/bin/env ruby -e "ver='${version}'; printf %Q{%d.%d.%d}, ver[1..2].to_i, ver[3..5].to_i, ver[6..8].to_i"
|
252
|
+
}
|
253
|
+
|
254
|
+
# Prints Usage
|
255
|
+
function __symit::usage() {
|
256
|
+
echo
|
257
|
+
__lib::color::h1 "symit"
|
258
|
+
|
259
|
+
printf "
|
260
|
+
${bldylw}symit${bldgrn} is a powerful BASH helper, that enhances the CLI encryption
|
261
|
+
tool called ${bldred}Sym${clr}, which is a Ruby Gem.
|
262
|
+
|
263
|
+
Sym has an extensive CLI interface, but it only handles one
|
264
|
+
encryption/decryption operation per invocation. With this script, you can
|
265
|
+
auto decrypt all files in a given folder, you can import the key in a
|
266
|
+
simpler way, and you can save into the environment sym configuration that
|
267
|
+
will be used. It also streamlines editing of encrypted files in a given
|
268
|
+
folder. Symit can be configured either with the ENV variables, or using
|
269
|
+
the CLI flags.\n"
|
270
|
+
|
271
|
+
printf "
|
272
|
+
The recommended way to use ${bldred}symit${clr} is to set the following
|
273
|
+
environment variables, which removes the need to pass these values via the
|
274
|
+
flags. These variables default to the shown values if not set elsewhere:
|
275
|
+
|
276
|
+
Perhaps the most critically important variable to set is ${txtylw}SYMIT__KEY${clr}:
|
277
|
+
${txtylw}
|
278
|
+
export SYMIT__KEY='my-org.my-app.dev'
|
279
|
+
eg: export SYMIT__KEY='github.web.development'
|
280
|
+
${clr}
|
281
|
+
The ${txtcya}key${clr} can resolve to a file name, or a name of ENV variable,
|
282
|
+
a keychain entry, or be the actual key (not recommended!). See the following
|
283
|
+
link for more info:
|
284
|
+
|
285
|
+
${undblu}https://github.com/kigster/sym#resolving-the--k-argument${clr}
|
286
|
+
|
287
|
+
Additional configuration is available through these variables:
|
288
|
+
${txtylw}
|
289
|
+
export SYMIT__EXTENSION='${SYMIT__EXTENSION}'
|
290
|
+
export SYMIT__FOLDER='${SYMIT__FOLDER}'
|
291
|
+
export SYMIT__MIN_VERSION='latest'
|
292
|
+
${clr}
|
293
|
+
The last variable defines the minimum Sym version desired. Set it to
|
294
|
+
'latest' to have symit auto-upgrade Sym every time it is invoked.
|
295
|
+
|
296
|
+
${clr}\n"
|
297
|
+
|
298
|
+
__lib::color::h2 "Usage:"
|
299
|
+
printf " ${bldgrn}symit [ action ] [ file-path/pattern ] [ flags ]${clr}\n\n"
|
300
|
+
|
301
|
+
__lib::color::h2 "Actions:"
|
302
|
+
printf " Action is the first word that defaults to ${bldylw}edit${clr}.\n\n"
|
303
|
+
printf " ${bldcya}Valid actions are below, starting with the Key import or creation:${clr}\n\n"
|
304
|
+
printf " ${bldylw}— generate ${clr}create a new secure key, and copies it to the\n"
|
305
|
+
printf " clipboard (if supported), otherwise prints to STDOUT\n"
|
306
|
+
printf " Key name (set via SYMIT__KEY or -k flag) is required,\n"
|
307
|
+
printf " and is used as the KeyChain entry name for the new key.\n\n"
|
308
|
+
printf " ${bldylw}— import [insecure]\n"
|
309
|
+
printf " ${clr}imports the key from clipboard and adds password\n"
|
310
|
+
printf " encryption unless 'insecure' is passed in. Same as above\n"
|
311
|
+
printf " in relation with the key parameter.\n\n"
|
312
|
+
printf " ${bldcya}The following actions require the file pattern/path argument:${clr}\n"
|
313
|
+
printf " ${bldylw}— edit ${clr}Finds all files, and opens them in $EDITOR\n"
|
314
|
+
printf " ${bldylw}— encrypt ${clr}Encrypts files matching file-path\n"
|
315
|
+
printf " ${bldylw}— decrypt ${clr}Adds the extension to file pattern and decrypts\n"
|
316
|
+
printf " ${bldylw}— auto ${clr}encrypts decrypted file, and vice versa\n"
|
317
|
+
|
318
|
+
echo
|
319
|
+
__lib::color::h2 "Flags:"
|
320
|
+
printf " -f | --folder DIR ${clr}Top level folder to search.${clr}\n"
|
321
|
+
printf " -k | --key KEY ${clr}Key identifier${clr}\n"
|
322
|
+
printf " -x | --extension EXT ${clr}Default extension of encrypted files.${clr}\n"
|
323
|
+
printf " -n | --dry-run ${clr}Print stuff, but dont do it${clr}\n"
|
324
|
+
printf " -a | --all-files ${clr}If provided ALL FILES are operated on${clr}\n"
|
325
|
+
printf " ${clr}Use with CAUTION!${clr}\n"
|
326
|
+
printf " -v | --verbose ${clr}Print more stuff${clr}\n"
|
327
|
+
printf " -q | --quiet ${clr}Print less stuff${clr}\n"
|
328
|
+
printf " -h | --help ${clr}Show this help message${clr}\n"
|
329
|
+
|
330
|
+
echo
|
331
|
+
__lib::color::h2 'Encryption key identifier can be:'
|
332
|
+
printf "${clr}"
|
333
|
+
|
334
|
+
printf '
|
335
|
+
1. name of the keychain item storing the keychain (secure)
|
336
|
+
2. name of the environment variable storing the Key (*)
|
337
|
+
3. name of the file storing the key (*)
|
338
|
+
4. the key itself (*)'
|
339
|
+
|
340
|
+
echo
|
341
|
+
printf "${bldred}"
|
342
|
+
printf '
|
343
|
+
(*) 2-4 are insecure UNLESS the key is encrypted with a password.'; echo
|
344
|
+
printf "${clr}\
|
345
|
+
Please refer to README about generating password protected keys:\n
|
346
|
+
${bldblu}${undblu}https://github.com/kigster/sym#generating-the-key--examples${clr}\n\n"
|
347
|
+
echo
|
348
|
+
|
349
|
+
__lib::color::h1 'Examples:'
|
350
|
+
|
351
|
+
printf " To import a key securely, first copy the key to your clipboard,\n"
|
352
|
+
printf " and then run the following command, pasting the key when asked:\n\n"
|
353
|
+
printf " ❯ ${bldgrn}symit${bldblu} import key ${clr}\n\n"
|
354
|
+
|
355
|
+
printf " To encrypt or decrypt ALL files in the 'config' directory:${clr}\n\n"
|
356
|
+
printf " ❯ ${bldgrn}symit${bldblu} encrypt|decrypt -a -f config ${clr}\n\n"
|
357
|
+
|
358
|
+
printf " To decrypt all *.yml.enc files in the 'config' directory:${clr}\n\n"
|
359
|
+
printf " ❯ ${bldgrn}symit${bldblu} decrypt '*.yml' -f config ${clr}\n\n"
|
360
|
+
|
361
|
+
printf " To edit an encrypted file ${txtblu}config/application.yml.enc${clr}\n\n"
|
362
|
+
printf " ❯ ${bldgrn}symit${bldblu} application.yml${clr}\n\n"
|
363
|
+
|
364
|
+
printf " To auto decrypt a file ${txtblu}config/settings/crypt/pass.yml.enc${clr}\n\n"
|
365
|
+
printf " ❯ ${bldgrn}symit${bldblu} auto config/settings/crypt/pass.yml.enc${clr}\n\n"
|
366
|
+
|
367
|
+
printf " To automatically decide to either encrypt or decrypt a file,\n"
|
368
|
+
printf " based on the file extension use 'auto' command. The first line below\n"
|
369
|
+
printf " encrypts the file, second decrypts it, because the file extension is .enc:${clr}\n\n"
|
370
|
+
|
371
|
+
printf " ❯ ${bldgrn}symit${bldblu} auto config/settings/crypt/pass.yml${clr}\n"
|
372
|
+
printf " ❯ ${bldgrn}symit${bldblu} auto config/settings/crypt/pass.yml.enc${clr}\n\n"
|
373
|
+
|
374
|
+
printf " To encrypt a file ${txtblu}config/settings.yml${clr}\n"
|
375
|
+
printf " ❯ ${bldgrn}symit${bldblu} encrypt config/settings.yml${clr}\n\n"
|
376
|
+
}
|
377
|
+
|
378
|
+
function __datum() {
|
379
|
+
date +"%m/%d/%Y.%H:%M:%S"
|
380
|
+
}
|
381
|
+
|
382
|
+
function __warn() {
|
383
|
+
__lib::color::cursor-left-by 1000
|
384
|
+
printf "${bldylw}$* ${bldylw}\n"
|
385
|
+
}
|
386
|
+
function __err() {
|
387
|
+
__lib::color::cursor-left-by 1000
|
388
|
+
printf "${bldred}ERROR: ${txtred}$* ${bldylw}\n"
|
389
|
+
}
|
390
|
+
|
391
|
+
function __inf() {
|
392
|
+
[[ ${cli__opts__quiet} ]] && return
|
393
|
+
__lib::color::cursor-left-by 1000
|
394
|
+
printf "${txtblu}$*${clr}\n"
|
395
|
+
}
|
396
|
+
|
397
|
+
function __dbg() {
|
398
|
+
[[ ${cli__opts__verbose} ]] || return
|
399
|
+
__lib::color::cursor-left-by 1000
|
400
|
+
printf "${txtgrn}$*${clr}\n"
|
401
|
+
}
|
402
|
+
|
403
|
+
function __lib::command::print() {
|
404
|
+
__inf "${bldylw}❯ ${bldcya}$*${clr}"
|
405
|
+
}
|
406
|
+
|
407
|
+
function __symit::sym::installed_version() {
|
408
|
+
__lib::ver-to-i $(gem list | grep sym | awk '{print $2}' | sed 's/(//g;s/)//g')
|
409
|
+
}
|
410
|
+
|
411
|
+
function __symit::sym::latest_version() {
|
412
|
+
__lib::ver-to-i $(gem query --remote -n '^sym$' | awk '{print $2}' | sed 's/(//g;s/)//g')
|
413
|
+
}
|
414
|
+
|
415
|
+
function __symit::install::update() {
|
416
|
+
local desired_version=$1
|
417
|
+
shift
|
418
|
+
local current_version=$2
|
419
|
+
shift
|
420
|
+
local version_args=$*
|
421
|
+
|
422
|
+
__inf "updating sym to version ${bldylw}$(__lib::i-to-ver ${desired_version})${clr}..."
|
423
|
+
printf "${bldblu}" >&1
|
424
|
+
echo y | gem uninstall sym --force -x 2>/dev/null
|
425
|
+
printf "${clr}" >&1
|
426
|
+
|
427
|
+
command="gem install sym ${version_args} "
|
428
|
+
eval "${command}" >/dev/null
|
429
|
+
code=$?
|
430
|
+
printf "${clr}" >&2
|
431
|
+
if [[ ${code} != 0 ]]; then
|
432
|
+
__err "gem install returned ${code}, with command ${bldylw}${command}"
|
433
|
+
return 127
|
434
|
+
fi
|
435
|
+
current_version=$(__symit::sym::installed_version)
|
436
|
+
__inf "sym version ${bldylw}$(__lib::i-to-ver ${current_version}) was successfully installed."
|
437
|
+
}
|
438
|
+
|
439
|
+
function __symit::install::gem() {
|
440
|
+
if [[ -n ${__symit_last_checked_at} ]]; then
|
441
|
+
now=$(date +'%s')
|
442
|
+
if [[ $(( $now - ${__symit_last_checked_at} )) -lt 3600 ]]; then
|
443
|
+
return
|
444
|
+
fi
|
445
|
+
fi
|
446
|
+
|
447
|
+
export __symit_last_checked_at=${now:-$(date +'%s')}
|
448
|
+
|
449
|
+
__inf "Verifying current sym version, please wait..."
|
450
|
+
current_version=$(__symit::sym::installed_version)
|
451
|
+
if [[ -n ${SYMIT__MIN_VERSION} ]]; then
|
452
|
+
if [[ ${SYMIT__MIN_VERSION} -eq 'latest' ]]; then
|
453
|
+
desired_version=$(__symit::sym::latest_version)
|
454
|
+
version_args=''
|
455
|
+
else
|
456
|
+
desired_version=$( __lib::ver-to-i ${SYMIT__MIN_VERSION})
|
457
|
+
version_args=" --version ${SYMIT__MIN_VERSION}"
|
458
|
+
fi
|
459
|
+
|
460
|
+
if [[ "${desired_version}" != "${current_version}" ]]; then
|
461
|
+
__symit::install::update "${desired_version}" "${current_version}" "${version_args}"
|
462
|
+
else
|
463
|
+
__inf "${bldgrn}sym${clr} ${txtblu}is on the correct version ${bldylw}$(__lib::i-to-ver ${desired_version})${txtblu} already"
|
464
|
+
fi
|
465
|
+
else
|
466
|
+
if [[ -z ${current_version} ]] ; then
|
467
|
+
__dbg "installing latest version of ${bldylw}sym..."
|
468
|
+
fi
|
469
|
+
fi
|
470
|
+
}
|
471
|
+
|
472
|
+
function __symit::files() {
|
473
|
+
eval $(__symit::files::cmd)
|
474
|
+
}
|
475
|
+
|
476
|
+
function __symit::files::cmd() {
|
477
|
+
if [[ -n ${cli__opts__file} && -n ${cli__opts__extension} ]]; then
|
478
|
+
|
479
|
+
local folder=${cli__opts__folder}
|
480
|
+
local file="${cli__opts__file}"
|
481
|
+
local ext="${cli__opts__extension}"
|
482
|
+
|
483
|
+
if [[ ${file} =~ '/' ]]; then
|
484
|
+
if [[ ${folder} == '.' ]]; then
|
485
|
+
folder="$(dirname ${file})"
|
486
|
+
else
|
487
|
+
folder="${folder}/$(dirname ${file})"
|
488
|
+
fi
|
489
|
+
file="$(basename ${file})"
|
490
|
+
fi
|
491
|
+
|
492
|
+
if [[ "${cli__opts__action}" == "encrypt" ]] ; then
|
493
|
+
printf "find ${folder} -name '${file}' -and -not -name '*${ext}'"
|
494
|
+
elif [[ "${cli__opts__action}" == "auto" ]] ; then
|
495
|
+
printf "find ${folder} -name '${file}'"
|
496
|
+
else # edit, decrypt
|
497
|
+
[[ ${file} =~ "${ext}" ]] || file="${file}${ext}"
|
498
|
+
printf "find ${folder} -name '${file}'"
|
499
|
+
fi
|
500
|
+
fi
|
501
|
+
}
|
502
|
+
|
503
|
+
function __symit::command() {
|
504
|
+
file=${1}
|
505
|
+
if [[ -n "${cli__opts__key}" && -n "${cli__opts__extension}" ]]; then
|
506
|
+
action="${cli__opts__action}"
|
507
|
+
v="sym__actions__${action}"
|
508
|
+
flags="${!v}"
|
509
|
+
if [[ ${action} =~ "key" ]]; then
|
510
|
+
[[ -n ${cli__opts__verbose} ]] && printf "processing key import action ${bldylw}${action}${clr}\n" >&2
|
511
|
+
printf "sym ${flags} ${cli__opts__key} "
|
512
|
+
elif [[ ${action} =~ "generate" ]] ; then
|
513
|
+
[[ -n ${cli__opts__verbose} ]] && printf "processing generate key action ${bldylw}${action}${clr}\n" >&2
|
514
|
+
if [[ -n $(which pbcopy) ]]; then
|
515
|
+
out_key=/tmp/outkey
|
516
|
+
command="sym ${flags} ${cli__opts__key} -q -o ${out_key}; cat ${out_key} | pbcopy; rm -f ${out_key}"
|
517
|
+
printf "${command}"
|
518
|
+
else
|
519
|
+
printf "sym ${flags} ${cli__opts__key} "
|
520
|
+
fi
|
521
|
+
elif [[ -n ${file} ]] ; then
|
522
|
+
ext="${cli__opts__extension}"
|
523
|
+
[[ -z ${ext} ]] && ext='.enc'
|
524
|
+
ext=$(echo ${ext} | sed -E 's/[\*\/,.]//g')
|
525
|
+
if [[ ${action} =~ "encrypt" ]]; then
|
526
|
+
printf "sym ${flags} ${file} -ck ${cli__opts__key} -o ${file}.${ext}"
|
527
|
+
elif [[ ${action} =~ "decrypt" ]]; then
|
528
|
+
new_name=$(echo ${file} | sed "s/\.${ext}//g")
|
529
|
+
[[ "${new_name}" == "${file}" ]] && name="${file}.decrypted"
|
530
|
+
printf "sym ${flags} ${file} -ck ${cli__opts__key} -o ${new_name}"
|
531
|
+
else
|
532
|
+
printf "sym ${flags} ${file} -ck ${cli__opts__key} "
|
533
|
+
fi
|
534
|
+
else
|
535
|
+
printf "printf \"ERROR: not sure how to generate a correct command\\n\""
|
536
|
+
fi
|
537
|
+
fi
|
538
|
+
}
|
539
|
+
|
540
|
+
function __symit::cleanup() {
|
541
|
+
unset sym__actions
|
542
|
+
unset cli__opts
|
543
|
+
}
|
544
|
+
|
545
|
+
function __symit::exit() {
|
546
|
+
code=${1:-0}
|
547
|
+
__symit::cleanup
|
548
|
+
echo -n ${code}
|
549
|
+
}
|
550
|
+
|
551
|
+
function __symit::print_cli_args() {
|
552
|
+
__dbg "action ${bldylw}: ${cli__opts__action}${clr}"
|
553
|
+
__dbg "key ${bldylw}: ${cli__opts__key}${clr}"
|
554
|
+
__dbg "file ${bldylw}: ${cli__opts__file}${clr}"
|
555
|
+
__dbg "extension ${bldylw}: ${cli__opts__extension}${clr}"
|
556
|
+
__dbg "folder ${bldylw}: ${cli__opts__folder}${clr}"
|
557
|
+
__dbg "verbose ${bldylw}: ${cli__opts__verbose}${clr}"
|
558
|
+
__dbg "dry_run ${bldylw}: ${cli__opts__dry_run}${clr}"
|
559
|
+
}
|
560
|
+
|
561
|
+
function __symit::args::needs_file() {
|
562
|
+
if [[ "${cli__opts__action}" == 'edit' || \
|
563
|
+
"${cli__opts__action}" == 'auto' || \
|
564
|
+
"${cli__opts__action}" == 'encrypt' || \
|
565
|
+
"${cli__opts__action}" == 'decrypt' ]]; then
|
566
|
+
printf 'yes'
|
567
|
+
fi
|
568
|
+
}
|
569
|
+
|
570
|
+
function __symit::validate_args() {
|
571
|
+
if [[ -n $(__symit::args::needs_file) && -z ${cli__opts__file} ]]; then
|
572
|
+
__err "missing file argument, config/application.yml"
|
573
|
+
return $(__symit::exit 2)
|
574
|
+
fi
|
575
|
+
|
576
|
+
if [[ -z "${cli__opts__key}" ]]; then
|
577
|
+
__err "Key was not defined, pass it with ${bldblu}-k KEY_ID${bldred}"
|
578
|
+
__err "or set it via ${bldgrn}\$SYMIT__KEY${bldred} variable."
|
579
|
+
return $(__symit::exit 4)
|
580
|
+
fi
|
581
|
+
|
582
|
+
if [[ -z ${cli__opts__extension} ]]; then
|
583
|
+
cli__opts__extension='.enc'
|
584
|
+
fi
|
585
|
+
}
|
586
|
+
|
587
|
+
function __symit::run() {
|
588
|
+
__symit::cleanup
|
589
|
+
__symit::init
|
590
|
+
|
591
|
+
cli__opts__verbose=''
|
592
|
+
cli__opts__quiet=''
|
593
|
+
cli__opts__key=${SYMIT__KEY}
|
594
|
+
cli__opts__extension=${SYMIT__EXTENSION}
|
595
|
+
cli__opts__folder=${SYMIT__FOLDER}
|
596
|
+
cli__opts__dry_run=''
|
597
|
+
cli__opts__action=edit
|
598
|
+
cli__opts__file=''
|
599
|
+
|
600
|
+
sym__actions__generate=' -cpgx '
|
601
|
+
sym__actions__edit=' -t '
|
602
|
+
sym__actions__encrypt='-e -f '
|
603
|
+
sym__actions__decrypt='-d -f '
|
604
|
+
sym__actions__auto=' -n '
|
605
|
+
sym__actions__key_secure=' -iqcpx '
|
606
|
+
sym__actions__key_insecure=' -iqcx '
|
607
|
+
sym__actions__install='install'
|
608
|
+
|
609
|
+
if [[ -z $1 ]]; then
|
610
|
+
__symit::usage
|
611
|
+
return $(__symit::exit 0)
|
612
|
+
fi
|
613
|
+
|
614
|
+
while :; do
|
615
|
+
case $1 in
|
616
|
+
-h|-\?|--help)
|
617
|
+
shift
|
618
|
+
__symit::usage
|
619
|
+
__symit::cleanup
|
620
|
+
return $(__symit::exit 0)
|
621
|
+
;;
|
622
|
+
|
623
|
+
-k|--key)
|
624
|
+
shift
|
625
|
+
if [[ -z $1 ]]; then
|
626
|
+
__err "-k/--key requires an argument" && return $(__symit::exit 1)
|
627
|
+
else
|
628
|
+
cli__opts__key=$1
|
629
|
+
shift
|
630
|
+
fi
|
631
|
+
;;
|
632
|
+
|
633
|
+
-x|--extension)
|
634
|
+
shift
|
635
|
+
if [[ -z $1 ]]; then
|
636
|
+
__err "-x/--extension requires an argument" && return $(__symit::exit 1)
|
637
|
+
else
|
638
|
+
cli__opts__extension=${1}
|
639
|
+
shift
|
640
|
+
fi
|
641
|
+
;;
|
642
|
+
|
643
|
+
-f|--folder)
|
644
|
+
shift
|
645
|
+
if [[ -z $1 ]]; then
|
646
|
+
__err "-f/--folder requires an argument" && return $(__symit::exit 1)
|
647
|
+
else
|
648
|
+
cli__opts__folder=${1}
|
649
|
+
shift
|
650
|
+
fi
|
651
|
+
;;
|
652
|
+
|
653
|
+
-a|--all-files)
|
654
|
+
shift
|
655
|
+
cli__opts__file="'*'"
|
656
|
+
;;
|
657
|
+
|
658
|
+
-n|--dry-run)
|
659
|
+
shift
|
660
|
+
cli__opts__dry_run="yes"
|
661
|
+
;;
|
662
|
+
|
663
|
+
-v|--verbose)
|
664
|
+
shift
|
665
|
+
cli__opts__verbose="yes"
|
666
|
+
;;
|
667
|
+
|
668
|
+
-q|--quiet)
|
669
|
+
shift
|
670
|
+
cli__opts__quiet="yes"
|
671
|
+
;;
|
672
|
+
|
673
|
+
import|key)
|
674
|
+
shift
|
675
|
+
cli__opts__action="key_secure"
|
676
|
+
;;
|
677
|
+
|
678
|
+
insecure)
|
679
|
+
shift
|
680
|
+
if [[ "${cli__opts__action}" == 'key_secure' ]] ; then
|
681
|
+
cli__opts__action="key_insecure"
|
682
|
+
fi
|
683
|
+
;;
|
684
|
+
|
685
|
+
--) # End of all options.
|
686
|
+
shift
|
687
|
+
break
|
688
|
+
;;
|
689
|
+
|
690
|
+
-?*)
|
691
|
+
__err 'WARN: Unknown option: %s\n' "$1" >&2
|
692
|
+
return $(__symit::exit 127)
|
693
|
+
shift
|
694
|
+
;;
|
695
|
+
|
696
|
+
|
697
|
+
?*)
|
698
|
+
param=$1
|
699
|
+
v="sym__actions__${param}"
|
700
|
+
if [[ ! ${param} =~ '.' && -n "${!v}" ]]; then
|
701
|
+
__dbg "Action ${bldylw}${param}${clr} is a valid action."
|
702
|
+
cli__opts__action=${param}
|
703
|
+
else
|
704
|
+
__dbg "Parameter ${bldylw}${param}${clr} is not a valid action,"
|
705
|
+
__dbg "therefore it must be a file pattern."
|
706
|
+
cli__opts__file=${1}
|
707
|
+
fi
|
708
|
+
shift
|
709
|
+
;;
|
710
|
+
|
711
|
+
*) # Default case: If no more options then break out of the loop.
|
712
|
+
break
|
713
|
+
shift
|
714
|
+
esac
|
715
|
+
done
|
716
|
+
|
717
|
+
[[ -n "${cli__opts__verbose}" ]] && __symit::print_cli_args
|
718
|
+
|
719
|
+
if [[ "${cli__opts__action}" == 'install' ]]; then
|
720
|
+
if [[ -n ${cli__opts__dry_run} ]]; then
|
721
|
+
__dbg "This command verifies that Sym is properly installed,"
|
722
|
+
__dbg "and if not found — installs it."
|
723
|
+
return $(__symit::exit 0)
|
724
|
+
else
|
725
|
+
__symit::install::gem
|
726
|
+
return $(__symit::exit 0)
|
727
|
+
fi
|
728
|
+
fi
|
729
|
+
|
730
|
+
__symit::validate_args
|
731
|
+
|
732
|
+
code=$?
|
733
|
+
if [[ ${code} != 0 ]]; then
|
734
|
+
return $(__symit::exit ${code})
|
735
|
+
fi
|
736
|
+
|
737
|
+
__symit::install::gem
|
738
|
+
|
739
|
+
changed_count=0
|
740
|
+
|
741
|
+
if [[ -n "${cli__opts__dry_run}" ]] ; then
|
742
|
+
__lib::color::h1 "DRY RUN"
|
743
|
+
for file in $(__symit::files); do
|
744
|
+
printf " \$ ${bldblu}$(__symit::command ${file})${clr}\n"
|
745
|
+
done
|
746
|
+
else
|
747
|
+
if [[ -n "${cli__opts__file}" ]]; then
|
748
|
+
[[ -n ${cli__opts__verbose} ]] && __dbg $(__symit::files)
|
749
|
+
declare -a file_list
|
750
|
+
|
751
|
+
for file in $(__symit::files); do
|
752
|
+
local cmd="$(__symit::command ${file})"
|
753
|
+
__lib::command::print "${cmd}"
|
754
|
+
eval "${cmd}"
|
755
|
+
code=$?; [[ ${code} != 0 ]] && __err "command '${bldblu}${cmd}${bldred}' exited with code ${bldylw}${code}"
|
756
|
+
changed_count=$(( ${changed_count} + 1))
|
757
|
+
done
|
758
|
+
|
759
|
+
if [[ ${changed_count} == 0 ]]; then
|
760
|
+
printf "${undylw}Bad news:${clr}\n\n"
|
761
|
+
__warn " No files matched your specification. The following 'find' command"
|
762
|
+
__warn " ran to find the file you requested. Please change the name, and "
|
763
|
+
__warn " try again.\n"
|
764
|
+
__warn " ${bldblu}$(__symit::files::cmd)${clr}\n\n"
|
765
|
+
return $(__symit::exit 5)
|
766
|
+
fi
|
767
|
+
|
768
|
+
else # opts[file]
|
769
|
+
cmd=$(__symit::command)
|
770
|
+
__lib::command::print "${cmd}"
|
771
|
+
eval "${cmd}"
|
772
|
+
code=$?; [[ ${code} != 0 ]] && return $(__symit::exit ${code})
|
773
|
+
changed_count=$(( ${changed_count} + 1))
|
774
|
+
fi
|
775
|
+
fi
|
776
|
+
}
|
777
|
+
|
778
|
+
function symit() {
|
779
|
+
__lib::stdout::configure
|
780
|
+
__symit::run $@
|
781
|
+
}
|