opensecret 0.0.962 → 0.0.988
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +16 -10
- data/bin/opensecret +3 -4
- data/bin/ops +5 -0
- data/lib/extension/string.rb +114 -0
- data/lib/factbase/facts.opensecret.io.ini +9 -21
- data/lib/interprete/begin.rb +232 -0
- data/lib/interprete/cmd.rb +621 -0
- data/lib/{plugins/usecases/unlock.rb → interprete/export.rb} +25 -70
- data/lib/interprete/init.rb +205 -0
- data/lib/interprete/key.rb +119 -0
- data/lib/interprete/open.rb +148 -0
- data/lib/{plugins/usecases → interprete}/put.rb +19 -6
- data/lib/{plugins/usecases → interprete}/safe.rb +2 -1
- data/lib/{plugins/usecases/lock.rb → interprete/seal.rb} +24 -34
- data/lib/interprete/set.rb +46 -0
- data/lib/interprete/use.rb +43 -0
- data/lib/interpreter.rb +165 -0
- data/lib/keytools/binary.map.rb +245 -0
- data/lib/keytools/digester.rb +245 -0
- data/lib/keytools/doc.conversion.to.ones.and.zeroes.ruby +179 -0
- data/lib/keytools/doc.rsa.radix.binary-mapping.ruby +190 -0
- data/lib/keytools/doc.star.schema.strategy.txt +77 -0
- data/lib/keytools/doc.using.pbkdf2.kdf.ruby +95 -0
- data/lib/keytools/doc.using.pbkdf2.pkcs.ruby +266 -0
- data/lib/keytools/kdf.bcrypt.rb +180 -0
- data/lib/keytools/kdf.pbkdf2.rb +164 -0
- data/lib/keytools/key.data.rb +227 -0
- data/lib/keytools/key.derivation.rb +341 -0
- data/lib/keytools/key.module.rb +140 -0
- data/lib/keytools/key.rb +481 -0
- data/lib/logging/gem.logging.rb +1 -2
- data/lib/modules/cryptology.md +43 -0
- data/lib/{plugins/ciphers → modules/cryptology}/aes-256.rb +6 -0
- data/lib/{crypto → modules/cryptology}/amalgam.rb +6 -0
- data/lib/modules/cryptology/blowfish.rb +130 -0
- data/lib/modules/cryptology/cipher.rb +207 -0
- data/lib/modules/cryptology/collect.rb +118 -0
- data/lib/{plugins → modules/cryptology}/crypt.io.rb +5 -0
- data/lib/{crypto → modules/cryptology}/engineer.rb +7 -1
- data/lib/{crypto → modules/cryptology}/open.bcrypt.rb +0 -0
- data/lib/modules/mappers/collateral.rb +282 -0
- data/lib/modules/mappers/dictionary.rb +288 -0
- data/lib/modules/mappers/envelope.rb +127 -0
- data/lib/modules/mappers/settings.rb +170 -0
- data/lib/modules/storage/coldstore.rb +186 -0
- data/lib/{opensecret/plugins.io/git/git.flow.rb → modules/storage/git.store.rb} +11 -0
- data/lib/notepad/scratch.pad.rb +17 -0
- data/lib/session/fact.finder.rb +13 -0
- data/lib/session/require.gem.rb +5 -0
- data/lib/store-commands.txt +180 -0
- data/lib/version.rb +1 -1
- data/opensecret.gemspec +5 -6
- metadata +74 -29
- data/lib/crypto/blowfish.rb +0 -85
- data/lib/crypto/collect.rb +0 -140
- data/lib/crypto/verify.rb +0 -33
- data/lib/opensecret.rb +0 -236
- data/lib/plugins/cipher.rb +0 -203
- data/lib/plugins/ciphers/blowfish.rb +0 -126
- data/lib/plugins/coldstore.rb +0 -181
- data/lib/plugins/envelope.rb +0 -116
- data/lib/plugins/secrets.uc.rb +0 -94
- data/lib/plugins/usecase.rb +0 -239
- data/lib/plugins/usecases/init.rb +0 -145
- data/lib/plugins/usecases/open.rb +0 -108
- data/lib/session/attributes.rb +0 -279
- data/lib/session/dictionary.rb +0 -191
- data/lib/session/file.path.rb +0 -53
- data/lib/session/session.rb +0 -80
@@ -0,0 +1,621 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
module OpenSecret
|
5
|
+
|
6
|
+
# The parent OpenSecret use case is designed to be extended by the cli
|
7
|
+
# (command line) use cases like {OpenSecret::Open}, {OpenSecret::Put} and
|
8
|
+
# {OpenSecret::Lock} because it describes behaviour common to at least two
|
9
|
+
# (but usually more) of the use cases.
|
10
|
+
#
|
11
|
+
# == Common Use Case Behaviour
|
12
|
+
#
|
13
|
+
# This {OpenSecret::Command} use case is designed to be extended and does preparatory
|
14
|
+
# work to create favourable and useful conditions to make use cases readable,
|
15
|
+
# less repetitive, simpler and concise.
|
16
|
+
class Command
|
17
|
+
|
18
|
+
|
19
|
+
# Get the envelope that <b>was opened</b> by the open command but
|
20
|
+
# <b>not locked</b> with the lock command.
|
21
|
+
#
|
22
|
+
# @return [Envelope]
|
23
|
+
# return the Envelope that has been opened. The state carried alongside an
|
24
|
+
# open envelope is an id, an encryption key and a filepath all inside the
|
25
|
+
# userhome configuration file.
|
26
|
+
def get_envelope
|
27
|
+
|
28
|
+
encrypt_key = Mapper::Settings.read @c[:open][:open_name], @c[:open][:open_keyname]
|
29
|
+
rel_filepath = Mapper::Settings.read @c[:open][:open_name], @c[:open][:open_pathname]
|
30
|
+
|
31
|
+
put_filepath = File.join( Mapper::Collateral.instance.session_envelopes_path, rel_filepath )
|
32
|
+
the_envelope = Mapper::Envelope.new
|
33
|
+
the_envelope.read put_filepath, encrypt_key
|
34
|
+
return the_envelope
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
# This method uses a one-way function to return a combinatorial digested
|
40
|
+
# session identification string using a number of distinct parameters that
|
41
|
+
# deliver the important behaviours of changing in certain circumstances
|
42
|
+
# and remaining unchanged in others.
|
43
|
+
#
|
44
|
+
# <b>Change | When Should the Session ID Change?</b>
|
45
|
+
#
|
46
|
+
# The session id is not a secret but it has to be unique due to its role
|
47
|
+
# in indexing the session envelopes and their changes.
|
48
|
+
#
|
49
|
+
# What is really important is that the <b>session id changes</b> when
|
50
|
+
#
|
51
|
+
# - the <b>domain</b> being used changes
|
52
|
+
# - the <b>command shell</b> changes
|
53
|
+
# - the user <b>switches to another workstation user</b>
|
54
|
+
# - the <b>workstation host</b> is changed
|
55
|
+
# - the <b>OPS KEY</b> environment variable changes
|
56
|
+
# - the user <b>SSH's</b> into another shell
|
57
|
+
#
|
58
|
+
# A distinct workstation is identified by the first MAC address and the
|
59
|
+
# hostname of the machine.
|
60
|
+
#
|
61
|
+
# <b>Unchanged | When Should it Remain Unchanged?</b>
|
62
|
+
#
|
63
|
+
# Remaining <b>unchanged</b> in certain scenarious is a session ID feature
|
64
|
+
# that is just as important as it changing in others.
|
65
|
+
#
|
66
|
+
# The session ID <b>must remain unchanged</b> when
|
67
|
+
#
|
68
|
+
# - the <b>user returns to a command shell</b>
|
69
|
+
# - the user <b>switches back to using a domain</b>
|
70
|
+
# - the user exits their <b>remote SSH session</b>
|
71
|
+
# - <b>sudo is used</b> to execute the commands
|
72
|
+
# - the user comes back to their <b>workstation</b>
|
73
|
+
# - the clock ticks into another day, month, year ...
|
74
|
+
#
|
75
|
+
# The pre-hash inputs are an amalgam of the below example data.
|
76
|
+
#
|
77
|
+
# Mac Address => 20cf3067dec3
|
78
|
+
# Parent PID => 5817
|
79
|
+
# Machine Host => data-cruncher
|
80
|
+
# Session Time => 18083.0310.41.796577366
|
81
|
+
#
|
82
|
+
# @return [String]
|
83
|
+
# the session id
|
84
|
+
def session_id
|
85
|
+
|
86
|
+
require 'macaddr'
|
87
|
+
session_data_points = [
|
88
|
+
Mac.addr.to_alphanumeric,
|
89
|
+
Process.ppid.to_s,
|
90
|
+
Socket.gethostname,
|
91
|
+
ENV[ Mapper::Collateral::ENV_OPS_KEY_NAME ].strip,
|
92
|
+
OpenSession::Home.instance.username,
|
93
|
+
@domain_name
|
94
|
+
].join
|
95
|
+
|
96
|
+
return OpenKey::Digester.mash( session_data_points, SESSION_ID_SIZE )
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
# Get the session key that is used for symmetric encryption and decryption
|
102
|
+
# of secret material pertinent to the opensecret use case.
|
103
|
+
#
|
104
|
+
# This depends on the {Command.session_key_password} for engineering the
|
105
|
+
# password using information specific to the workstation and the parent
|
106
|
+
# (bash) shell being used to execute opensecret.
|
107
|
+
#
|
108
|
+
# <b>Substituting Equals Back In</b>
|
109
|
+
#
|
110
|
+
# An environment variable holds the key's value and the <b>equals sign</b>
|
111
|
+
# is not allowed within environment variables (in some operating systems)
|
112
|
+
# mainly due to the fact that it is used as the key/value separator.
|
113
|
+
#
|
114
|
+
# The url safe base64 coding may produce one, two or three equal signs in
|
115
|
+
# a bid to pad the string into a multiple of 4 length.
|
116
|
+
#
|
117
|
+
# In this case, we replaced equals signs with @ symbols when encoding so
|
118
|
+
# we must reciprocate this action when decoding here.
|
119
|
+
#
|
120
|
+
# @return [String]
|
121
|
+
# Return the original key generated by the {OpenSecret::Key} usecase.
|
122
|
+
#
|
123
|
+
# @raise [RuntimeError]
|
124
|
+
# if either the ENV["OPS_KEY"] environment variable is not present or an
|
125
|
+
# exception is thrown during decryption. An error is also thrown if the
|
126
|
+
# environment variable or the key to be returned have a length less than
|
127
|
+
# 40 characters.
|
128
|
+
def get_session_key
|
129
|
+
|
130
|
+
key_ciphertext = mandatory_environment_variable Mapper::Collateral::ENV_OPS_KEY_NAME, 40
|
131
|
+
decoded_crypt = Base64.urlsafe_decode64( key_ciphertext.gsub("@","=") )
|
132
|
+
return ToolBelt::Blowfish.decryptor( decoded_crypt, session_key_password )
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
|
137
|
+
# @todo
|
138
|
+
# this method should be within the env var services class.
|
139
|
+
#
|
140
|
+
# Return the contents of the environment variable key specified
|
141
|
+
# in the first parameter. The returned value is striped of both
|
142
|
+
# leading and trailing whitespace before it is returned.
|
143
|
+
#
|
144
|
+
# @param env_var_name [String]
|
145
|
+
# the (uppercase) name of the environment variable to collect
|
146
|
+
#
|
147
|
+
# @param min_size [Number]
|
148
|
+
# the minimum number of characters the environment variable's
|
149
|
+
# value is allowed to contain.
|
150
|
+
#
|
151
|
+
# @return [String]
|
152
|
+
# Return the <b>stripped</b> environment variable value whose
|
153
|
+
# name matches the one specified by the first parameter.
|
154
|
+
#
|
155
|
+
# @raise [RuntimeError]
|
156
|
+
# if either the environment variable is not present or the length
|
157
|
+
# of the string value is less than the number of charactes
|
158
|
+
# specified in the second parameterr.
|
159
|
+
def mandatory_environment_variable env_var_name, min_size
|
160
|
+
|
161
|
+
raw_env_var_value = ENV[env_var_name]
|
162
|
+
raise_error( env_var_name, "not present") unless raw_env_var_value
|
163
|
+
|
164
|
+
env_var_value = raw_env_var_value.strip
|
165
|
+
raise_error( env_var_name, "consists only of whitespace") if raw_env_var_value.empty?
|
166
|
+
|
167
|
+
size_msg = "length should be at [least] #{min_size} characters"
|
168
|
+
raise_error( env_var_name, size_msg ) unless env_var_value.length >= min_size
|
169
|
+
|
170
|
+
return env_var_value
|
171
|
+
|
172
|
+
end
|
173
|
+
|
174
|
+
|
175
|
+
# Instantiate the collateral object which is the single
|
176
|
+
# source of knowledge for any client wishing to know the
|
177
|
+
# path to a particular resource (collateral) file or
|
178
|
+
# directory on the accessible file system.
|
179
|
+
#
|
180
|
+
# This method simply enables, for all (child) use cases,
|
181
|
+
# the @collateral instance variable.
|
182
|
+
def instantiate_collateral
|
183
|
+
|
184
|
+
@collateral = Mapper::Collateral.instance
|
185
|
+
|
186
|
+
the_domain_name = Mapper::Settings.grab @c[:global][:domain_now_id]
|
187
|
+
the_frontend_path = Mapper::Settings.read( the_domain_name, @c[:global][:front_path_id] )
|
188
|
+
@collateral.domain_name = the_domain_name
|
189
|
+
@collateral.frontend_path = the_frontend_path
|
190
|
+
|
191
|
+
end
|
192
|
+
|
193
|
+
|
194
|
+
# Unlock the {OpenSSL::PKey::RSA} private key and return the cipher object
|
195
|
+
# usable for asymmetric encryption, decryption, signing and signature
|
196
|
+
# verification use cases.
|
197
|
+
#
|
198
|
+
# The returned private key can be used to generate its twin public key
|
199
|
+
# and should be used to verify the same public key as (if) and when the
|
200
|
+
# need arises.
|
201
|
+
#
|
202
|
+
# @param locked_private_key [String]
|
203
|
+
# the locked up private key ciphertext
|
204
|
+
#
|
205
|
+
# @param unlock_key [String]
|
206
|
+
# the symmetric encryption key that can be used to unlock the private
|
207
|
+
# key ciphertext in the first parameter.
|
208
|
+
#
|
209
|
+
# @return [OpenSSL::PKey::RSA]
|
210
|
+
# return the {OpenSSL::PKey::RSA} private key that will be
|
211
|
+
# usable for asymmetric encryption, decryption, signing and signature
|
212
|
+
# verification.
|
213
|
+
def unlock_private_key locked_private_key, unlock_key
|
214
|
+
return OpenSSL::PKey::RSA.new locked_private_key, unlock_key
|
215
|
+
end
|
216
|
+
|
217
|
+
|
218
|
+
# Return the {OpenSSL::PKey::RSA} private key which is a cipher object
|
219
|
+
# usable for asymmetric encryption, decryption, signing and signature
|
220
|
+
# verification use cases.
|
221
|
+
#
|
222
|
+
# The returned private key can be used to generate its twin public key
|
223
|
+
# and should be used to verify the same public key as (if) and when the
|
224
|
+
# need arises.
|
225
|
+
#
|
226
|
+
# @param private_key_text [String]
|
227
|
+
# the private key plain text
|
228
|
+
#
|
229
|
+
# @return [OpenSSL::PKey::RSA]
|
230
|
+
# return the {OpenSSL::PKey::RSA} private key that will be
|
231
|
+
# usable for asymmetric encryption, decryption, signing and signature
|
232
|
+
# verification.
|
233
|
+
def to_private_key private_key_text
|
234
|
+
return OpenSSL::PKey::RSA.new private_key_text
|
235
|
+
end
|
236
|
+
|
237
|
+
|
238
|
+
# Execute the use cases's flow from beginning when
|
239
|
+
# you validate the input and parameters through the
|
240
|
+
# memorize, execute and the final cleanup.
|
241
|
+
def flow_of_events
|
242
|
+
|
243
|
+
check_pre_conditions
|
244
|
+
pre_memorize
|
245
|
+
execute
|
246
|
+
post_memorize
|
247
|
+
cleanup
|
248
|
+
check_post_conditions
|
249
|
+
|
250
|
+
end
|
251
|
+
|
252
|
+
|
253
|
+
# Validate the input parameters and check that the current
|
254
|
+
# state is perfect for executing the use case.
|
255
|
+
#
|
256
|
+
# If either of the above fail - the validation function should
|
257
|
+
# set a human readable string and then throw an exception.
|
258
|
+
def check_pre_conditions
|
259
|
+
|
260
|
+
|
261
|
+
begin
|
262
|
+
|
263
|
+
pre_validation
|
264
|
+
|
265
|
+
rescue OpenError::CliError => e
|
266
|
+
|
267
|
+
puts ""
|
268
|
+
puts "Your command did not complete successfully."
|
269
|
+
puts "Pre validation checks failed."
|
270
|
+
puts ""
|
271
|
+
puts " => #{e.message}"
|
272
|
+
puts ""
|
273
|
+
abort e.message
|
274
|
+
end
|
275
|
+
|
276
|
+
|
277
|
+
end
|
278
|
+
|
279
|
+
|
280
|
+
# After the main flow of events certain state conditions
|
281
|
+
# must hold true thus demonstrating that the observable
|
282
|
+
# value has indeed ben delivered.
|
283
|
+
#
|
284
|
+
# Child classes should subclass this method and place any
|
285
|
+
# post execution (post condition) checks in it and then
|
286
|
+
# make a call to this method through the "super" keyword.
|
287
|
+
def check_post_conditions
|
288
|
+
|
289
|
+
begin
|
290
|
+
|
291
|
+
post_validation
|
292
|
+
|
293
|
+
rescue OpenError::CliError => e
|
294
|
+
|
295
|
+
puts ""
|
296
|
+
puts "Your command did not complete successfully."
|
297
|
+
puts "Post validation checks failed."
|
298
|
+
puts ""
|
299
|
+
puts " => #{e.message}"
|
300
|
+
#### puts " => #{e.culprit}"
|
301
|
+
puts ""
|
302
|
+
abort e.message
|
303
|
+
end
|
304
|
+
|
305
|
+
end
|
306
|
+
|
307
|
+
|
308
|
+
# Child classes should subclass this method and place any
|
309
|
+
# post execution (post condition) checks in it and then
|
310
|
+
# make a call to this method through the "super" keyword if
|
311
|
+
# this method gets any global behaviour in it worth calling.
|
312
|
+
def post_validation
|
313
|
+
|
314
|
+
end
|
315
|
+
|
316
|
+
|
317
|
+
|
318
|
+
# (Pre) memorize adds to permanent storage a configuration
|
319
|
+
# directive and its value <tt>provided by the user</tt>
|
320
|
+
# primarily because it avoids repitition in subsequent
|
321
|
+
# use case commands.
|
322
|
+
def pre_memorize
|
323
|
+
|
324
|
+
end
|
325
|
+
|
326
|
+
|
327
|
+
|
328
|
+
# Execute the main flow of events of the use case. Any
|
329
|
+
# exceptions thrown are captured and if the instance
|
330
|
+
# variale [@human_readable_message] is set - tell the
|
331
|
+
# user about it. Without any message - just tell the
|
332
|
+
# user something went wrong and tell them where the logs
|
333
|
+
# are that might carry more information.
|
334
|
+
def execute
|
335
|
+
|
336
|
+
end
|
337
|
+
|
338
|
+
|
339
|
+
|
340
|
+
# (Post) memorize will add to permanent storage) any
|
341
|
+
# key/values that have been derived or looked up during
|
342
|
+
# use case execution. This allows subsequent use case
|
343
|
+
# commands to
|
344
|
+
#
|
345
|
+
# - capitalize on
|
346
|
+
# - take direction from
|
347
|
+
# - and/or simply use
|
348
|
+
#
|
349
|
+
# the value in later use cases or processing.
|
350
|
+
def post_memorize
|
351
|
+
|
352
|
+
end
|
353
|
+
|
354
|
+
|
355
|
+
|
356
|
+
# If the use case validation went well, the memorization
|
357
|
+
# went well the
|
358
|
+
def cleanup
|
359
|
+
|
360
|
+
end
|
361
|
+
|
362
|
+
|
363
|
+
|
364
|
+
# Resolve +two attached fact files+ with the first being general and
|
365
|
+
# relevant to every use case in the parameter specified domain, and
|
366
|
+
# the second being specific to this use case.
|
367
|
+
#
|
368
|
+
# The <b><em>general factfile</em></b> is expected to be on the class (load) path
|
369
|
+
# and below are paths for a generic domain name and for an example domain
|
370
|
+
# name of *openpost.io*
|
371
|
+
#
|
372
|
+
# - <tt>factbase/facts.<<domain>>.ini</tt>
|
373
|
+
# - <tt>factbase/facts.openpost.io.ini</tt>
|
374
|
+
#
|
375
|
+
# The <b><em>use case specific factfile</em></b> is also _expected_ to be on the class
|
376
|
+
# (load) path and below is a generic and a use case specific path using
|
377
|
+
# the example <tt>deliver</tt> use case.
|
378
|
+
#
|
379
|
+
# - <tt>factbase/facts.<<uc-name>>.usecase.ini</tt>
|
380
|
+
# - <tt>factbase/facts.deliver.usecase.ini</tt>
|
381
|
+
#
|
382
|
+
# The domain name is delivered in the parameter whilst the use case
|
383
|
+
# name is derived from the (extension) class name.
|
384
|
+
#
|
385
|
+
# @param fact_domain [String] domain of the general attached factfile
|
386
|
+
# @return [Hash] a 2d (two-dimensional) hash of keys and their corresponding values
|
387
|
+
def attached_facts fact_domain
|
388
|
+
|
389
|
+
end
|
390
|
+
|
391
|
+
|
392
|
+
# This use case is initialized primary by resolving the configured
|
393
|
+
# +general and use case specific facts+. To access the general facts,
|
394
|
+
# a domain name is expected in the parameter delegated by the extension
|
395
|
+
# use case classes.
|
396
|
+
def initialize
|
397
|
+
|
398
|
+
|
399
|
+
class_name = self.class.name.downcase.split(":").last
|
400
|
+
is_pre_init_usecase = [ "safe", "store", "email" ].include? class_name
|
401
|
+
return if is_pre_init_usecase
|
402
|
+
|
403
|
+
@ucid_str = self.class.name.do_flatten
|
404
|
+
log.info(x) { "Usecase class [self.class.name] converted to => #{@ucid_str}" }
|
405
|
+
@ucid_sym = @ucid_str.gsub(".", "_").to_sym
|
406
|
+
|
407
|
+
OpenSession::FactFind.instance.instantiate @ucid_str
|
408
|
+
OpenSession::FactFind.instance.assimilate "facts.opensecret.io.ini"
|
409
|
+
|
410
|
+
@c = OpenSession::FactFind.instance.f
|
411
|
+
@i = OpenSession::FactFind.instance.i
|
412
|
+
@p = OpenSession::FactFind.instance.f[@ucid_sym]
|
413
|
+
|
414
|
+
log.info(x) { "assimilated [#{@p.length}] facts specific to the [#{@ucid_str}] use case." }
|
415
|
+
|
416
|
+
end
|
417
|
+
|
418
|
+
|
419
|
+
private
|
420
|
+
|
421
|
+
## Important Refactor is to move Session behaviour to an OpenKey Session class.
|
422
|
+
## Important Refactor is to move Session behaviour to an OpenKey Session class.
|
423
|
+
## Important Refactor is to move Session behaviour to an OpenKey Session class.
|
424
|
+
## Important Refactor is to move Session behaviour to an OpenKey Session class.
|
425
|
+
## Important Refactor is to move Session behaviour to an OpenKey Session class.
|
426
|
+
## Important Refactor is to move Session behaviour to an OpenKey Session class.
|
427
|
+
## Important Refactor is to move Session behaviour to an OpenKey Session class.
|
428
|
+
## Important Refactor is to move Session behaviour to an OpenKey Session class.
|
429
|
+
## Important Refactor is to move Session behaviour to an OpenKey Session class.
|
430
|
+
## Important Refactor is to move Session behaviour to an OpenKey Session class.
|
431
|
+
## Important Refactor is to move Session behaviour to an OpenKey Session class.
|
432
|
+
## Important Refactor is to move Session behaviour to an OpenKey Session class.
|
433
|
+
## Important Refactor is to move Session behaviour to an OpenKey Session class.
|
434
|
+
## Important Refactor is to move Session behaviour to an OpenKey Session class.
|
435
|
+
## Important Refactor is to move Session behaviour to an OpenKey Session class.
|
436
|
+
## Important Refactor is to move Session behaviour to an OpenKey Session class.
|
437
|
+
## Important Refactor is to move Session behaviour to an OpenKey Session class.
|
438
|
+
## Important Refactor is to move Session behaviour to an OpenKey Session class.
|
439
|
+
|
440
|
+
|
441
|
+
|
442
|
+
OUTER_PATH = "outer.path"
|
443
|
+
INNER_PATH = "inner.path"
|
444
|
+
|
445
|
+
LAST_ACCESSED = "last.accessed.time"
|
446
|
+
|
447
|
+
SESSION_DICT_LOCK_SIZE = 32
|
448
|
+
|
449
|
+
SESSION_DICT_LOCK_NAME = "crypted.session.dict.lock"
|
450
|
+
|
451
|
+
ENVELOPE_KEY_SIZE = 32
|
452
|
+
|
453
|
+
ENVELOPE_KEY_NAME = "crypted.envelope.key"
|
454
|
+
|
455
|
+
ENVELOPE_ID_SIZE = 16
|
456
|
+
|
457
|
+
ENVELOPE_ID_NAME = "crypted.envelope.id"
|
458
|
+
|
459
|
+
SESSION_ID_SIZE = 64
|
460
|
+
|
461
|
+
SESSION_FILENAME_ID_SIZE = 24
|
462
|
+
|
463
|
+
SESSION_START_TIMESTAMP_NAME = "session.creation.time"
|
464
|
+
|
465
|
+
MASTER_LOCK_KEY_NAME = "master.session.lock.key"
|
466
|
+
|
467
|
+
def raise_error env_var_name, message
|
468
|
+
|
469
|
+
puts ""
|
470
|
+
puts "#{env_var_name} environment variable #{message}."
|
471
|
+
puts "To instantiate it you can use the below command."
|
472
|
+
puts ""
|
473
|
+
puts "$ export OPS_KEY=`ops key`"
|
474
|
+
puts ""
|
475
|
+
puts "ps => those are backticks around `ops key` (not apostrophes)."
|
476
|
+
puts ""
|
477
|
+
|
478
|
+
raise RuntimeError, "#{env_var_name} environment variable #{message}."
|
479
|
+
|
480
|
+
end
|
481
|
+
|
482
|
+
|
483
|
+
|
484
|
+
def ops_key_exists?
|
485
|
+
|
486
|
+
if ( ENV.has_key? Mapper::Collateral::ENV_OPS_KEY_NAME )
|
487
|
+
return true
|
488
|
+
end
|
489
|
+
|
490
|
+
puts ""
|
491
|
+
puts "opensecret needs you to create a session key."
|
492
|
+
puts "To automate this step see the documentation."
|
493
|
+
puts "To create the key run the below command."
|
494
|
+
puts ""
|
495
|
+
puts " export OPS_KEY=`ops key`"
|
496
|
+
puts ""
|
497
|
+
puts "Those are backticks surrounding `ops key`"
|
498
|
+
puts "Not apostrophes."
|
499
|
+
puts ""
|
500
|
+
|
501
|
+
return false
|
502
|
+
|
503
|
+
end
|
504
|
+
|
505
|
+
|
506
|
+
def private_key_exists?
|
507
|
+
|
508
|
+
if @collateral.private_key_exists?
|
509
|
+
return true
|
510
|
+
end
|
511
|
+
|
512
|
+
puts ""
|
513
|
+
puts "Domain [ #{@domain_name} ] has not been initialized."
|
514
|
+
puts "Have you run the ops init command?"
|
515
|
+
puts ""
|
516
|
+
puts " ops init #{@domain_name} $HOME/ops.#{@domain_name}"
|
517
|
+
puts ""
|
518
|
+
|
519
|
+
return false
|
520
|
+
|
521
|
+
end
|
522
|
+
|
523
|
+
|
524
|
+
def get_session_dictionary
|
525
|
+
|
526
|
+
session_index_filepath = @collateral.session_index_file( session_id[0 .. (SESSION_FILENAME_ID_SIZE-1)] )
|
527
|
+
|
528
|
+
unless File.file? session_index_filepath
|
529
|
+
return OpenKey::Dictionary.create_with_section( session_index_filepath, create_envelope_id )
|
530
|
+
end
|
531
|
+
|
532
|
+
return OpenKey::Dictionary.create_with_section( session_index_filepath, read_envelope_id, read_session_dict_lock )
|
533
|
+
|
534
|
+
end
|
535
|
+
|
536
|
+
|
537
|
+
def create_session_dict_lock
|
538
|
+
session_dict_lock = OpenSecret::ToolBelt::Engineer.strong_key SESSION_DICT_LOCK_SIZE
|
539
|
+
session_dict_lock_crypt = session_dict_lock.encrypt_url_encode( get_session_key )
|
540
|
+
Mapper::Settings.write session_id, SESSION_DICT_LOCK_NAME, session_dict_lock_crypt
|
541
|
+
return session_dict_lock
|
542
|
+
end
|
543
|
+
|
544
|
+
|
545
|
+
def read_session_dict_lock
|
546
|
+
session_dict_lock_crypt = Mapper::Settings.read session_id, SESSION_DICT_LOCK_NAME
|
547
|
+
return session_dict_lock_crypt.url_decode_decrypt( get_session_key )
|
548
|
+
end
|
549
|
+
|
550
|
+
|
551
|
+
def create_envelope_key
|
552
|
+
envelope_key = OpenSecret::ToolBelt::Engineer.strong_key ENVELOPE_KEY_SIZE
|
553
|
+
envelope_key_crypt = envelope_key.encrypt_url_encode( get_session_key )
|
554
|
+
Mapper::Settings.write session_id, ENVELOPE_KEY_NAME, envelope_key_crypt
|
555
|
+
return envelope_key
|
556
|
+
end
|
557
|
+
|
558
|
+
|
559
|
+
def read_envelope_key
|
560
|
+
envelope_key_crypt = Mapper::Settings.read session_id, ENVELOPE_KEY_NAME
|
561
|
+
return envelope_key_crypt.url_decode_decrypt( get_session_key )
|
562
|
+
end
|
563
|
+
|
564
|
+
|
565
|
+
def create_envelope_id
|
566
|
+
envelope_id = OpenSecret::ToolBelt::Engineer.strong_key ENVELOPE_ID_SIZE
|
567
|
+
envelope_id_crypt = envelope_id.encrypt_url_encode( get_session_key )
|
568
|
+
Mapper::Settings.write session_id, ENVELOPE_ID_NAME, envelope_id_crypt
|
569
|
+
return envelope_id
|
570
|
+
end
|
571
|
+
|
572
|
+
|
573
|
+
def read_envelope_id
|
574
|
+
envelope_id_crypt = Mapper::Settings.read session_id, ENVELOPE_ID_NAME
|
575
|
+
return envelope_id_crypt.url_decode_decrypt( get_session_key )
|
576
|
+
end
|
577
|
+
|
578
|
+
|
579
|
+
#### [cGWy7vU4WwxcTQ5X710kVQGWD5EujUco0WiaxyLrMFzXMdNhCAYAba3DXENKVz94]
|
580
|
+
#### master.session.lock.key = FY27lfm96o6KlIXHS3u8tsmh9oBJiS5IU-oUkn4CLCkVAsOx_E2Wkzm2-d3ZIHfhG35ik1ENjhHcBJO4JebYQ-TR-t7xI8AVKC8jS3Y40qUbeCjFHjGDbpJI0RNYEWdyr4iSMygI6FbH-iCg9V4awA==
|
581
|
+
#### session.creation.time = 18092.2238.43.302186561
|
582
|
+
#### crypted.envelope.id = iPamzaAD17vmOH72DLikbwadIMc5HW8IBS88mxUseks8il74JEXuLpJI0RNYEWdyr4iSMygI6FbH-iCg9V4awA==
|
583
|
+
#### crypted.session.dict.lock = iSbFR3ZFGWzkFEXHMByugL_09FJL3wVRnmgjxqsvd5ds8zpfeQT-7ERiAAst49gQr4iSMygI6FbH-iCg9V4awA==
|
584
|
+
|
585
|
+
def create_crypt_store_locking_key
|
586
|
+
|
587
|
+
config_keystore = Mapper::KeyStore.new( @collateral.domain_config_file, @domain_name )
|
588
|
+
digester = OpenKey::Digester.new( config_keystore.time_stamp )
|
589
|
+
|
590
|
+
locking_key = digester.generate @master_p4ss
|
591
|
+
config_keystore.set_init_vector( digester.encrypted_iv )
|
592
|
+
|
593
|
+
session_key_crypt = Base64.urlsafe_encode64( ToolBelt::Blowfish.encryptor( locking_key, get_session_key ) )
|
594
|
+
|
595
|
+
Mapper::Settings.write session_id, MASTER_LOCK_KEY_NAME, session_key_crypt
|
596
|
+
Mapper::Settings.write session_id, SESSION_START_TIMESTAMP_NAME, OpenSession::Stamp.yyjjj_hhmm_ss_nanosec
|
597
|
+
|
598
|
+
return locking_key
|
599
|
+
|
600
|
+
end
|
601
|
+
|
602
|
+
|
603
|
+
def print_success_initializing
|
604
|
+
|
605
|
+
puts ""
|
606
|
+
puts "Success - now open a secret envelope, put, then seal."
|
607
|
+
puts ""
|
608
|
+
puts " ops open aws.credentials:s3reader"
|
609
|
+
puts " ops put access_key ABCD1234"
|
610
|
+
puts " ops put secret_key FGHIJ56789"
|
611
|
+
puts " ops put region_key eu-central-1"
|
612
|
+
puts " ops seal"
|
613
|
+
puts ""
|
614
|
+
|
615
|
+
end
|
616
|
+
|
617
|
+
|
618
|
+
end
|
619
|
+
|
620
|
+
|
621
|
+
end
|