opensecret 0.0.2 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +4 -0
  3. data/README.md +2 -2
  4. data/bin/opensecret +3 -6
  5. data/lib/opensecret-domain.ini +23 -0
  6. data/lib/opensecret.rb +30 -2
  7. data/lib/opensecret/additions/array.rb +117 -0
  8. data/lib/opensecret/additions/dir.rb +35 -0
  9. data/lib/opensecret/additions/string.rb +312 -0
  10. data/lib/opensecret/commons/eco.cmdline.rb +446 -0
  11. data/lib/opensecret/commons/eco.faculty.rb +364 -0
  12. data/lib/opensecret/commons/eco.system.rb +437 -0
  13. data/lib/opensecret/commons/eco.systems.rb +98 -0
  14. data/lib/opensecret/{safe.rb → delegate.rb} +4 -2
  15. data/lib/opensecret/eco.do.rb +46 -0
  16. data/lib/opensecret/executors/crypt.keys/crypt.keys.ini +79 -0
  17. data/lib/opensecret/executors/crypt.keys/crypt.keys.rb +68 -0
  18. data/lib/opensecret/executors/decrypt/decrypt.ini +64 -0
  19. data/lib/opensecret/executors/decrypt/decrypt.rb +49 -0
  20. data/lib/opensecret/executors/encrypt/encrypt.ini +55 -0
  21. data/lib/opensecret/executors/encrypt/encrypt.rb +82 -0
  22. data/lib/opensecret/factbase/hub-runtime.ini +123 -0
  23. data/lib/opensecret/factbase/known-hosts.ini +75 -0
  24. data/lib/opensecret/factbase/published.facts/blobbolicious-facts.ini +553 -0
  25. data/lib/opensecret/factbase/published.facts/credential-facts.ini +40 -0
  26. data/lib/opensecret/factbase/published.facts/infrastructure-facts.ini +63 -0
  27. data/lib/opensecret/factbase/readme.md +24 -0
  28. data/lib/opensecret/factbase/retired.facts/maven.database.ide.facts.ini +127 -0
  29. data/lib/opensecret/factbase/retired.facts/s3-upload-block-facts.ini +17 -0
  30. data/lib/opensecret/plugins.io/cipher/crypto.rb +174 -0
  31. data/lib/opensecret/plugins.io/error/eco.exceptions.rb +24 -0
  32. data/lib/opensecret/plugins.io/facts/fact.chars.rb +66 -0
  33. data/lib/opensecret/plugins.io/facts/fact.factor.rb +156 -0
  34. data/lib/opensecret/plugins.io/facts/fact.locator.rb +105 -0
  35. data/lib/opensecret/plugins.io/facts/fact.reader.rb +137 -0
  36. data/lib/opensecret/plugins.io/facts/fact.tree.rb +661 -0
  37. data/lib/opensecret/plugins.io/file/file.rb +483 -0
  38. data/lib/opensecret/plugins.io/git/git.flow.rb +388 -0
  39. data/lib/opensecret/plugins.io/logs/log.object.rb +89 -0
  40. data/lib/opensecret/plugins.io/logs/logging.rb +203 -0
  41. data/lib/opensecret/plugins.io/time/time.stamp.rb +425 -0
  42. data/lib/opensecret/version.rb +2 -2
  43. data/opensecret.gemspec +8 -13
  44. metadata +68 -18
@@ -0,0 +1,483 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # -- --------------------------------------------------------------- -- #
4
+ # -- File facts are placeholders (keys in effect) just begging to be -- #
5
+ # -- replaced by values sourced from some sort of map. This software -- #
6
+ # -- centres around the DevOps fact replacement placeholder pattern. -- #
7
+ # -- --------------------------------------------------------------- -- #
8
+ class Files
9
+ #### ==> ===================================================================================
10
+ #### ==> ===================================================================================
11
+ #### ==> Name this class FindReplace or simply just Replace => Replace.contains? Replace.do
12
+ #### ==> Name this class FindReplace or simply just Replace => Replace.contains? Replace.do
13
+ #### ==> Name this class FindReplace or simply just Replace => Replace.contains? Replace.do
14
+ #### ==> Name this class FindReplace or simply just Replace => Replace.contains? Replace.do
15
+ #### ==> Name this class FindReplace or simply just Replace => Replace.contains? Replace.do
16
+ #### ==> Name this class FindReplace or simply just Replace => Replace.contains? Replace.do
17
+ #### ==> Name this class FindReplace or simply just Replace => Replace.contains? Replace.do
18
+ #### ==> ===================================================================================
19
+ #### ==> ===================================================================================
20
+
21
+
22
+
23
+ ## --- ---------------------------------------------------------------------- --- #
24
+ ## --- How to Use File to extract different parts of an [absolute] file path. --- #
25
+ ## --- ---------------------------------------------------------------------- --- #
26
+ ### File Names ====] file = "/path/to/xyz.mp4"
27
+ ### File Names ====] comp = File.basename file # => "xyz.mp4"
28
+ ### File Names ====] extn = File.extname file # => ".mp4"
29
+ ### File Names ====] name = File.basename file, extn # => "xyz"
30
+ ### File Names ====] path = File.dirname file # => "/path/to"
31
+ ## --- ---------------------------------------------------------------------- --- #
32
+
33
+
34
+ # --
35
+ # -- Scan every file in directory for placeholder keys within the
36
+ # -- parameter map and replace them with the corresponding value.
37
+ # -- Not Recursive => the scan does [not] recurse into folders
38
+ # --
39
+ # -- ----------------------------------
40
+ # -- Replacing Betty (Nested Replace)
41
+ # -- ----------------------------------
42
+ # --
43
+ # -- "GoBBetBettytyettyne" => "Gone"
44
+ # --
45
+ # -- A nested replace is done up to approximately 5 levels deep.
46
+ # -- So replacing "Betty" from the above string does [NOT] produce
47
+ # -- "GoBBettyettyne". The string becomes "Gone".
48
+ # --
49
+ # -- -----------
50
+ # -- Parameters
51
+ # -- -----------
52
+ # -- fact_map : driving [placeholder] => [value] map
53
+ # -- replace_dir : dir subject of the scan and replace
54
+ # --
55
+ def self.find_replace fact_map, replace_folder
56
+
57
+ log.info(ere){ "#-- --------------------------------------------------------- #" }
58
+ log.info(ere){ "#-- File changing in #{File.basename replace_folder}" }
59
+ log.info(ere){ "#-- #{replace_folder}" }
60
+ log.info(ere){ "#-- --------------------------------------------------------- #" }
61
+
62
+ # -- ------------------------------------------------------------------------------ -- #
63
+ # -- Iterate to substitute matched strings in file with their corresponding values. -- #
64
+ # -- ------------------------------------------------------------------------------ -- #
65
+ Dir.foreach( replace_folder ) do | file_name |
66
+
67
+ file_path = File.join replace_folder, file_name
68
+ next if File.directory? file_path
69
+ next if File.extname(file_path).eql? ".log"
70
+
71
+ nested_key_replace fact_map, file_path
72
+
73
+ end
74
+
75
+ log.info(ere){ "#-- --------------------------------------------------------- #" }
76
+ log.info(ere){ "#-- Done changing files in #{File.basename replace_folder}" }
77
+ log.info(ere){ "#-- --------------------------------------------------------- #" }
78
+
79
+ end
80
+
81
+ #--
82
+ #-- Using the parameter [file] [replace] any occurence
83
+ #-- of any [key] found in the parameter [map] with the
84
+ #-- corresponding mapped key [value].
85
+ #--
86
+ #-- -----------------------------------
87
+ #-- [Nested Replace]
88
+ # -- Replacing Betty (Nested Replace)
89
+ # -- ----------------------------------
90
+ # --
91
+ # -- "GoBBetBettytyettyne" => "Gone"
92
+ # --
93
+ # -- A nested replace is done up to approximately 5 levels deep.
94
+ # -- So replacing "Betty" from the above string does [NOT] produce
95
+ # -- "GoBBettyettyne". The string becomes "Gone".
96
+ # --
97
+ def self.nested_key_replace source_map, filepath
98
+
99
+ for i in 1..5
100
+ file_changed = key_replace source_map, filepath
101
+ return unless file_changed
102
+ log.info(ere){ "#-- --------------------------------------------------------- #" }
103
+ log.info(ere){ "#-- File #{File.basename filepath} has been changed" }
104
+ log.info(ere){ "#-- --------------------------------------------------------- #" }
105
+ end
106
+
107
+ end
108
+
109
+ #--
110
+ #-- Using the parameter [file] [replace] any occurence
111
+ #-- of any [key] found in the parameter [map] with the
112
+ #-- corresponding mapped key [value].
113
+ #--
114
+ #-- Side Effect => If at least one replacement occured this
115
+ #-- method returns true, else false.
116
+ #--
117
+ def self.key_replace source_map, filepath
118
+
119
+ replace_happened = false
120
+
121
+ source_map.each do |theKey, theValue|
122
+
123
+ next unless has_string? filepath, theKey
124
+ factorize theKey, theValue, filepath
125
+ replace_happened = true
126
+
127
+ end
128
+
129
+ return replace_happened
130
+
131
+ end
132
+
133
+
134
+
135
+ #--
136
+ #-- Produce a map of every "recursive" file sitting under
137
+ #-- any and all of the parameter directories array.
138
+ #--
139
+ #-- Harboured folders are traversed but folder names are
140
+ #-- excluded from the resulting map.
141
+ #--
142
+ #-- The key/value structure of the map is
143
+ #--
144
+ #-- key => simple filename
145
+ #-- value => (abs) folder path
146
+ #--
147
+ #-- --------------------------------
148
+ #-- Filename NOT UNIQUE Exception
149
+ #-- --------------------------------
150
+ #--
151
+ #-- Simple filename UNIQUENESS must prevail.
152
+ #--
153
+ #-- If the same base filename is found in any part or level
154
+ #-- of the directory trees under the every parameter parent
155
+ #-- folder - an exception will be thrown.
156
+ #--
157
+ def self.in_folders parent_folders
158
+
159
+ files_map = {}
160
+
161
+ parent_folders.each do |parent_folder|
162
+
163
+ log.info(ere) { "Create map of files under #{nickname parent_folder}" }
164
+ Throw.if_not_exists parent_folder
165
+
166
+ Dir["#{parent_folder}/**/*"].each do |child_file|
167
+
168
+ next if File.directory? child_file
169
+ filename = File.basename child_file
170
+ foldername = File.dirname child_file
171
+ log.info(ere) { " #{filename} => #{nickname foldername}" }
172
+ error_str = "Name NOT UNIQUE Error => [#{filename}].\n\n#{files_map.inspect}"
173
+ raise RuntimeError.new error_str if files_map.has_key? filename
174
+ files_map.store filename, foldername
175
+
176
+ end
177
+
178
+ end
179
+
180
+ return files_map
181
+
182
+ end
183
+
184
+
185
+ #--
186
+ #-- Find files of a given type (extension) that exist
187
+ #-- recursively under a folder.
188
+ #--
189
+ #-- --------------------------------
190
+ #-- Filename NOT UNIQUE Exception
191
+ #-- --------------------------------
192
+ #--
193
+ #-- Simple filename UNIQUENESS must prevail.
194
+ #--
195
+ #-- If the same base filename is found in any part or level
196
+ #-- of the directory trees under the every parameter parent
197
+ #-- folder - an exception will be thrown.
198
+ #--
199
+ #-- ------------
200
+ #-- Parameters
201
+ #-- ------------
202
+ #--
203
+ #-- base_folder => the top-level folder to search
204
+ #-- dir at (abs) path must exist
205
+ #--
206
+ #-- file_extn => extension of interesting files
207
+ #-- including the leading [period].
208
+ #-- (send ".exe" for exe files)
209
+ #-- (send ".md" for markdown files)
210
+ #--
211
+ #-- ------------
212
+ #-- Map Returned
213
+ #-- ------------
214
+ #--
215
+ #-- Returns a { filename => rel_path } map of the matching
216
+ #-- files in the folder. The map
217
+ #--
218
+ #-- keys => simple filename without extension
219
+ #-- values => relative path from the base folder
220
+ #--
221
+ def self.to_name_path_map base_folder, file_extn
222
+
223
+ files_map = {}
224
+
225
+ Dir["#{base_folder}/**/*#{file_extn}"].each do |filepath|
226
+
227
+ next if File.directory? filepath
228
+ ext_error = "File extension not [#{file_extn}] in => #{nickname filepath}"
229
+ raise RuntimeError.new(ext_error) unless File.extname(filepath).eql? "#{file_extn}"
230
+
231
+ filename = File.basename filepath
232
+
233
+ error_str = "Name NOT UNIQUE Error => [#{filename}].\n\n#{files_map.inspect}"
234
+ raise RuntimeError.new error_str if files_map.has_key? filename
235
+ files_map.store filename, filepath
236
+
237
+ end
238
+
239
+ return files_map
240
+
241
+ end
242
+
243
+
244
+ #--
245
+ #-- Return a new map with the values folder path
246
+ #-- forwarded by one level
247
+ #--
248
+ #-- If the map contains the below
249
+ #--
250
+ #-- {
251
+ #-- file1 => user/docs/pdfs,
252
+ #-- file2 => user/docs/pdfs/good,
253
+ #-- file3 => user/docs/pdfs/bad
254
+ #-- }
255
+ #--
256
+ #-- This method will return a map like this
257
+ #--
258
+ #-- {
259
+ #-- file1 => docs/pdfs,
260
+ #-- file2 => docs/pdfs/good,
261
+ #-- file3 => docs/pdfs/bad
262
+ #-- }
263
+ #--
264
+ #-- The values part has been forwarded by one level.
265
+ #--
266
+ def self.forwarded_path files_map
267
+
268
+ changed_map = {}
269
+
270
+ files_map.each do |the_name, the_old_path|
271
+ the_new_path = the_old_path.split("/")[1..-1].join("/")
272
+ changed_map.store the_name, the_new_path
273
+ log.info(ere){ "Forwarded from #{the_old_path} to #{the_new_path}" }
274
+ end
275
+
276
+ return changed_map
277
+
278
+ end
279
+
280
+
281
+ #--
282
+ #-- Path stripper expects the path in the first parameter
283
+ #-- to start with the path in the second parameter.
284
+ #--
285
+ #-- It then returns the first parameter path with the
286
+ #-- leading path stripped out.
287
+ #--
288
+ #-- ---------------------------
289
+ #-- Strip Leading Path Example
290
+ #-- ---------------------------
291
+ #--
292
+ #-- 1st param path = /home/joe/docs/pdfs/websites
293
+ #-- 2nd param path = /home/joe/docs
294
+ #-- Returned Path = pdfs/websites
295
+ #--
296
+ #-- ---------------------------------
297
+ #-- The Middle Separator is Stripped
298
+ #-- ---------------------------------
299
+ #--
300
+ #-- Note above that the middle separator is stripped
301
+ #-- so the returned string has no leading separator.
302
+ #--
303
+ def self.lead_path_chopped long_path, lead_path
304
+
305
+ return long_path.gsub(lead_path, "")[1..-1]
306
+
307
+ end
308
+
309
+
310
+ # -- ------------------------------------------------------------------- -- #
311
+ # -- Returns true when the parameter file contains the parameter string. -- #
312
+ # -- As a side effect the lines with at least 1 string match are logged. -- #
313
+ # -- ------------------------------------------------------------------- -- #
314
+ def self.has_string? the_file, theString
315
+
316
+ containsMatch = false;
317
+ line_index = 0;
318
+
319
+ File.open( the_file, "r") do | file_obj |
320
+
321
+ name_abbrv = File.basename the_file
322
+ file_obj.each_line do | file_line |
323
+
324
+ line_index = line_index + 1
325
+ lineCount = sprintf '%03d', line_index
326
+ if file_line.include? theString then
327
+
328
+ squeezed_line = file_line.chomp.strip.squeeze(" ")
329
+ log.info(ere) { "== string [#{theString}] occurs @line #{lineCount} in #{name_abbrv}" }
330
+ log.info(ere) { "== |---> #{squeezed_line}" }
331
+ containsMatch = true
332
+
333
+ end
334
+
335
+ end
336
+
337
+ end
338
+
339
+ return containsMatch;
340
+
341
+ end
342
+
343
+
344
+ # --
345
+ # -- [FIND] lines that include a set of configured strings and
346
+ # -- [REPLACE] then with the configured alternative.
347
+ # --
348
+ # -- -----------
349
+ # -- Parameters
350
+ # -- -----------
351
+ # --
352
+ # -- filepath : path to existing "to be changed" file
353
+ # -- includes : include string array for line matching
354
+ # -- new_line : replace the matched line with this str
355
+ # --
356
+ # -- --------------------------------
357
+ # -- Dependencies and Assumptions
358
+ # -- --------------------------------
359
+ # --
360
+ # -- file exists at filepath
361
+ # --
362
+ def self.find_replace_lines filepath, includes, new_line
363
+
364
+ Throw.if_not_exists filepath
365
+ Throw.if_nil includes
366
+ Throw.if_nil new_line
367
+
368
+ line_matches_count = 0;
369
+ new_file_lines_set = ""
370
+
371
+ File.open( filepath, "r") do | file_obj |
372
+
373
+ file_obj.each_line do | file_line |
374
+
375
+ unless (String.includes_all?( file_line, includes ) ) then
376
+ new_file_lines_set += file_line
377
+ next
378
+ end
379
+
380
+ ++line_matches_count
381
+ new_file_lines_set += new_line
382
+
383
+ log.info(ere) { "[replace] - ------------------------------------------------------- ##" }
384
+ log.info(ere) { "[replace] - file name => #{File.basename filepath}" }
385
+ log.info(ere) { "[replace] - has words => #{pp includes}" }
386
+ log.info(ere) { "[replace] - orig line => #{file_line}" }
387
+ log.info(ere) { "[replace] - ------- --------- ------- ---------- ------ ##" }
388
+ log.info(ere) { "[replace] - outgoing line => #{file_line}" }
389
+ log.info(ere) { "[replace] - incoming line => #{new_line}" }
390
+ log.info(ere) { "[replace] - ------- --------- ------- ---------- ------ ##" }
391
+
392
+ end
393
+
394
+ end
395
+
396
+ # -- ---------------------------------------------------------- -- #
397
+ # -- [(over)write] new set of file lines to the parameter file. -- #
398
+ # -- ---------------------------------------------------------- -- #
399
+ File.write filepath, new_file_lines_set
400
+ LogObject.file filepath, "replace"
401
+
402
+ end
403
+
404
+
405
+ # --
406
+ # -- Write the 1D key/value map into a properties
407
+ # -- file at the parameter folder.
408
+ # --
409
+ # -- Parameters
410
+ # -- properties_map : the key/value map to serialize
411
+ # -- props_dir_path : folder holding new properties file
412
+ # -- props_filename : name of the new properties file
413
+ # --
414
+ # -- Dependencies and Assumptions
415
+ # -- the directory will be created if it does not exist
416
+ # -- we assume the properties file DOES NOT EXIST
417
+ # -- the map is 1D and is not nil (can be empty)
418
+ # -- the directory is writeable by the user
419
+ # --
420
+ def self.write_properties properties_map, props_dir_path, props_filename
421
+
422
+ Dir.mkdir props_dir_path unless File.exists? props_dir_path
423
+ prop_filepath = File.join props_dir_path, props_filename
424
+ File.write prop_filepath, to_properties_text(properties_map)
425
+
426
+ LogObject.file prop_filepath, "write properties"
427
+
428
+ end
429
+
430
+
431
+ # --
432
+ # -- Create txt file in the properties format containing
433
+ # -- a dictionary of name/value pairs separated by an
434
+ # -- equals sign.
435
+ # --
436
+ # -- Parameters
437
+ # -- properties_map : the key/value map to serialize
438
+ # --
439
+ # -- Dependencies and Assumptions
440
+ # -- the map is 1D and is not nil (can be empty)
441
+ # -- map keys are SYMBOLS so underscores are made dots
442
+ # --
443
+ def self.to_properties_text properties_map
444
+
445
+ hdr_1 = "## Properties file with [#{properties_map.length}] key/value pairs.\n"
446
+ hdr_u = "## @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ##\n"
447
+
448
+ property_text = hdr_u + hdr_1 + hdr_u + "\n"
449
+ properties_map.each do |key_symbol,value|
450
+ key_string = key_symbol.to_s.gsub("_", ".")
451
+ property_text += "#{key_string}=#{value}\n"
452
+ end
453
+
454
+ property_text += "\n" + hdr_u
455
+ return property_text
456
+
457
+ end
458
+
459
+
460
+ # -- ---------------------------------------------------------- -- #
461
+ # -- When the [file fact] replace [behaviour] is called against -- #
462
+ # -- a "file" it [replaces all occurrences] (as best it can) of -- #
463
+ # -- the given string within the file. Call replace occurrences -- #
464
+ # -- against a folder and it replaces in all constituent files. -- #
465
+ # -- ---------------------------------------------------------- -- #
466
+ # -- Be careful = this implementation is not that clever. So if -- #
467
+ # -- we try to replace all "Betty" occurrences - lines that may -- #
468
+ # -- contain ["BetBettyty"] will likely end up with a ["Betty"] -- #
469
+ # -- ---------------------------------------------------------- -- #
470
+ def self.factorize from_string, to_string, in_file
471
+
472
+ the_filename = File.basename in_file
473
+
474
+ log.info(ere) { "From String => #{from_string}" }
475
+ log.info(ere) { "[To] String => #{to_string}" }
476
+ log.info(ere) { "File [Name] => #{the_filename}" }
477
+
478
+ File.write( in_file, File.open( in_file, &:read ).gsub( from_string, to_string ) );
479
+
480
+ end
481
+
482
+
483
+ end