reedb 0.10.rc1

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.
@@ -0,0 +1,24 @@
1
+ # ====================================================
2
+ # Copyright 2015 Lonely Robot (see @author)
3
+ # @author: Katharina Sabel | www.2rsoftworks.de
4
+ #
5
+ # Distributed under the GNU Lesser GPL Version 3
6
+ # (See accompanying LICENSE file or get a copy at
7
+ # https://www.gnu.org/licenses/lgpl.html)
8
+ # ====================================================
9
+
10
+ module Reedb
11
+
12
+ class VaultConfig
13
+
14
+ # Takes the containing vault as a parameter
15
+ #
16
+ def initialize(master)
17
+ @secure_cypher = ""
18
+ @head = {}
19
+ @body = {}
20
+ end
21
+
22
+ end
23
+
24
+ end
@@ -0,0 +1,42 @@
1
+ # ====================================================
2
+ # Copyright 2015 Lonely Robot (see @author)
3
+ # @author: Katharina Sabel | www.2rsoftworks.de
4
+ #
5
+ # Distributed under the GNU Lesser GPL Version 3
6
+ # (See accompanying LICENSE file or get a copy at
7
+ # https://www.gnu.org/licenses/lgpl.html)
8
+ # ====================================================
9
+
10
+ # A bunch of constants
11
+ module Reedb
12
+
13
+ # The version of reedb. This is actually written into vaults to identify
14
+ # breaking changes and using an older sub-set of the API to interact with
15
+ # legacy vaults.
16
+ VERSION = "0.10.rc1"
17
+ NET_PORT = 55736
18
+ TOKEN_BYTE_SIZE = 16 # in bytes
19
+ DEF_MASTER_PATH = "__sysmas__" # Placeholder
20
+ FILE_CACHE_TIME = 2500 # Time in ms
21
+ KEY_CACHE_TIME = (15 * 60) * 1000 # (30 minutes in ms)
22
+
23
+
24
+
25
+ #
26
+ # THIS SECTION WILL BE RESERVED FOR ERROR CODES AS RETURN VALUES
27
+ #
28
+ FILE_MALFORMED_DATA_ERROR = 0x11
29
+
30
+ #
31
+ # VAULT ERROR CODES
32
+ #
33
+ VAULT_FILE_NOT_FOUND_ERROR = 0x12
34
+
35
+
36
+ #
37
+ # RETURN ERROR CODES
38
+ #
39
+ DAEMON_UNKNOWN_TOKEN_ERROR = 0x31
40
+ DAEMON_UNAUTHORISED_TOKEN_ERROR = 0x32
41
+ DAEMON_INACTIVE_VAULT_ERROR = 0x33
42
+ end
@@ -0,0 +1,617 @@
1
+ # ====================================================
2
+ # Copyright 2015 Lonely Robot (see @author)
3
+ # @author: Katharina Sabel | www.2rsoftworks.de
4
+ #
5
+ # Distributed under the GNU Lesser GPL Version 3
6
+ # (See accompanying LICENSE file or get a copy at
7
+ # https://www.gnu.org/licenses/lgpl.html)
8
+ # ====================================================
9
+
10
+ # This is a wrapper script that gets called by the reedb daemon to init the
11
+ # HTTP stack and Reedb modules.
12
+ # DO NOT USE THIS FILE WHEN USING REEDB AS A GEM DEPENDENCY!
13
+ # (unless you know what you're doing...)
14
+
15
+ # System requirements (HTTP stuff)
16
+ require 'optparse'
17
+ require 'sinatra'
18
+ require 'rack'
19
+
20
+ # Reedb requirements
21
+ require 'reedb'
22
+
23
+ # HTTP handler class that registers the functions
24
+ # for the vault interface
25
+ #
26
+ class ReedbHandler < Sinatra::Base
27
+
28
+ # funct url descr
29
+ #
30
+ # GET /vaults List of all vaults
31
+ # PUT /vaults Create a new vault.
32
+ # PUT /vaults/scope Scope a vault that already exists
33
+
34
+ # POST /vaults/*vault-id*/request_token Auth for vault with ID
35
+ # [AUTH] POST /vaults/*vault-id*/headers Return vault headers
36
+ # [AUTH] POST /vaults/*vault-id*/close Close vault with ID
37
+
38
+ # [AUTH] POST /vaults/*vault-id*/files/*file-id* Returns body of a file
39
+ # [AUTH] POST /vaults/*vault-id*/files/*file-id*/history Returns history of a file (???)
40
+
41
+ # [AUTH] PUT /vaults/*vault-id*/files Create file
42
+ # [AUTH] POST /vaults/*vault-id*/files/*file-id* Update file contents
43
+ # [AUTH] POST /vaults/*vault-id*/files/*file-id*/remove Removes a file
44
+
45
+ configure :production, :development do
46
+ enable :logging
47
+ end
48
+
49
+ def build_response(status_code, message, payload = nil)
50
+ status status_code # Set http status code
51
+ content_type 'application/json'
52
+ response = { 'success' => (status_code >= 400 ? false : true),
53
+ 'message' => message,
54
+ 'payload' => payload }
55
+ return response.to_json
56
+ end
57
+
58
+ # Returns a list of vaults scoped on the system
59
+ get '/vaults' do
60
+ payload = Reedb::Vault::available_vaults
61
+ return build_response(200, "Currently scoped vaults", payload)
62
+ end
63
+
64
+ # Create a new vault on the system
65
+ put '/vaults' do
66
+
67
+ # If request was garbage
68
+ unless request.content_type == 'application/json'
69
+ return build_response(400, 'Data was malformed. Expects JSON!')
70
+ end
71
+
72
+ # Check if the JSON data
73
+ data = nil
74
+ begin
75
+ data = JSON.parse(request.body.read)
76
+ rescue
77
+ return build_response(400, 'JSON data was malformed!')
78
+ end
79
+
80
+ name = data["name"] if data["name"]
81
+ path = data["path"] if data["path"]
82
+ passphrase = data["passphrase"] if data["passphrase"]
83
+ encryption = :auto # TODO: Handle this better!
84
+
85
+ # This gets fired if not all neccesary information was provided.
86
+ if name == nil && path == nil && passphrase == nil
87
+ return build_response(400, 'Required data fields are missing from JSON data body!')
88
+ end
89
+
90
+ # Now deal with the actual stuff
91
+ token = nil
92
+
93
+ # Catches ALL possible errors that can occur during this operation!
94
+ begin
95
+ token = Reedb::Vault::create_vault(name, path, passphrase, encryption)
96
+ rescue InsecureUserPasswordError => e
97
+ return build_response(400, e.message)
98
+
99
+ rescue VaultExistsAtLocationError => e
100
+ return build_response(409, e.message)
101
+
102
+ rescue VaultWritePermissionsError,
103
+ VaultMissingConfigurationError,
104
+ VaultLoggerError,
105
+ BadCacheError,
106
+ EncryptionFailedError,
107
+ DecryptionFailedError => e
108
+
109
+ # Bundled error return
110
+ return build_response(500, e.message)
111
+ end
112
+
113
+ return build_response(201, "Vault was successfully crated at location", token)
114
+ end
115
+
116
+ # Scope a new vault on the system.
117
+ put '/vaults/scope' do
118
+ # If request was garbage
119
+ unless request.content_type == 'application/json'
120
+ return build_response(400, 'Data was malformed. Expects JSON!')
121
+ end
122
+
123
+ # Check if the JSON data
124
+ data = nil
125
+ begin
126
+ data = JSON.parse(request.body.read)
127
+ rescue
128
+ return build_response(400, 'JSON data was malformed!')
129
+ end
130
+
131
+ name = data["name"] if data["name"]
132
+ path = data["path"] if data["path"]
133
+
134
+ if name == nil && path == nil
135
+ return build_response(400, 'Required data fields are missing from JSON data body!')
136
+ end
137
+
138
+ begin
139
+ Reedb::Vault::scope_vault(name, path)
140
+ rescue VaultAlreadyScopedError, VaultDoesNotExistError => e
141
+ return build_response(400, e.message)
142
+ end
143
+
144
+ # If everything went well
145
+ return build_response(200, "Vault successfully scoped. It is now available to load.")
146
+ end
147
+
148
+ put '/vaults/unscope' do
149
+ # If request was garbage
150
+ unless request.content_type == 'application/json'
151
+ return build_response(400, 'Data was malformed. Expects JSON!')
152
+ end
153
+
154
+ # Check if the JSON data
155
+ data = nil
156
+ begin
157
+ data = JSON.parse(request.body.read)
158
+ rescue
159
+ return build_response(400, 'JSON data was malformed!')
160
+ end
161
+
162
+ name = data["name"] if data["name"]
163
+ path = data["path"] if data["path"]
164
+
165
+ if name == nil && path == nil
166
+ return build_response(400, 'Required data fields are missing from JSON data body!')
167
+ end
168
+
169
+ begin
170
+ Reedb::Vault::scope_vault(name, path)
171
+ rescue VaultNotScopedError => e
172
+ return build_response(400, e.message)
173
+ end
174
+
175
+ # If everything went well
176
+ return build_response(200, "Vault successfully unscoped and will not show up in vault lists anymore.")
177
+ end
178
+
179
+ # Request a token for a vault
180
+ post '/vaults/*/request_token' do
181
+ vault_uuid = params[:splat][0]
182
+
183
+ puts vault_uuid
184
+
185
+ if vault_uuid == nil
186
+ return build_response(400, 'Missing vault access id.')
187
+ end
188
+
189
+ # If request was garbage
190
+ unless request.content_type == 'application/json'
191
+ return build_response(400, 'Data was malformed. Expects JSON!')
192
+ end
193
+
194
+ # Check if the JSON data
195
+ data = nil
196
+ begin
197
+ data = JSON.parse(request.body.read)
198
+ rescue
199
+ return build_response(400, 'JSON data was malformed!')
200
+ end
201
+
202
+ passphrase = data["passphrase"] if data["passphrase"]
203
+ permanent = false # TODO: Implement this!
204
+
205
+ if passphrase == nil && permanent == nil
206
+ return build_response(400, 'Required data fields are missing from JSON data body!')
207
+ end
208
+
209
+ token = nil
210
+ begin
211
+ token = Reedb::Daemon::request_token(vault_uuid, passphrase)
212
+ rescue VaultNotScopedError, VaultDoesNotExistError => e
213
+ return build_response(404, e.message)
214
+
215
+ rescue WrongUserPasswordError => e
216
+ return build_response(401, e.message)
217
+ end
218
+
219
+ return build_response(200, "Access successfully granted for vault", token)
220
+ end
221
+
222
+ post '/vaults/*/free_token' do
223
+ vault_uuid = params[:splat][0]
224
+
225
+ unless vault_uuid
226
+ return build_response(400, 'Missing vault access id.')
227
+ end
228
+
229
+ # If request was garbage
230
+ unless request.content_type == 'application/json'
231
+ return build_response(400, 'Data was malformed. Expects JSON!')
232
+ end
233
+
234
+ # Check if the JSON data
235
+ data = nil
236
+ begin
237
+ data = JSON.parse(request.body.read)
238
+ rescue
239
+ return build_response(400, 'JSON data was malformed!')
240
+ end
241
+
242
+ token = data["token"] if data["token"]
243
+
244
+ if token == nil
245
+ return build_response(400, 'Required data fields are missing from JSON data body!')
246
+ end
247
+
248
+ begin
249
+ Reedb::Daemon::free_token(token)
250
+ rescue
251
+ return build_response(400, 'Token unknown to Reedb. Can not free it!')
252
+ end
253
+
254
+ return build_response(200, "Token successfully freed")
255
+ end
256
+
257
+ # [AUTH] Close vault with id + token
258
+ post '/vaults/*/close' do
259
+ vault_uuid = params[:splat][0]
260
+
261
+ unless vault_uuid
262
+ return build_response(400, 'Missing vault access id.')
263
+ end
264
+
265
+ # If request was garbage
266
+ unless request.content_type == 'application/json'
267
+ return build_response(400, 'Data was malformed. Expects JSON!')
268
+ end
269
+
270
+ # Check if the JSON data
271
+ data = nil
272
+ begin
273
+ data = JSON.parse(request.body.read)
274
+ rescue
275
+ return build_response(400, 'JSON data was malformed!')
276
+ end
277
+
278
+ token = data["token"] if data["token"]
279
+
280
+ unless token
281
+ return build_response(400, 'Required data fields are missing from JSON data body!')
282
+ end
283
+
284
+ begin
285
+ Reedb::Vault::close_vault(vault_uuid, token)
286
+
287
+ rescue VaultNotAvailableError => e
288
+ return build_response(404, e.message)
289
+
290
+ rescue UnknownTokenError => e
291
+ return build_response(401, e.message)
292
+
293
+ rescue UnautherisedTokenError => e
294
+ return build_response(403, e.message)
295
+
296
+ rescue Exception => e
297
+ return build_response(500, "An errror occured. #{e.message}")
298
+ end
299
+
300
+ return build_response(200, "Vault #{vault_uuid} successfully closed.")
301
+
302
+ end
303
+
304
+ # [AUTH] Request headers for a vault with token/ id
305
+ post '/vaults/*/headers' do
306
+ vault_uuid = params[:splat][0]
307
+
308
+ if vault_uuid == nil
309
+ return build_response(400, 'Missing vault access id.')
310
+ end
311
+
312
+ # If request was garbage
313
+ unless request.content_type == 'application/json'
314
+ return build_response(400, 'Data was malformed. Expects JSON!')
315
+ end
316
+
317
+ # Check if the JSON data
318
+ data = nil
319
+ begin
320
+ data = JSON.parse(request.body.read)
321
+ rescue
322
+ return build_response(400, 'JSON data was malformed!')
323
+ end
324
+
325
+ token = data["token"] if data["token"]
326
+ search = data["search"] if data["search"]
327
+
328
+ if token == nil
329
+ return build_response(400, 'Required data fields are missing from JSON data body!')
330
+ end
331
+
332
+ headers = nil
333
+ begin
334
+ headers = Reedb::Vault::access_headers(vault_uuid, token, search)
335
+
336
+ rescue VaultNotAvailableError => e
337
+ return build_response(404, e.message)
338
+
339
+ rescue UnknownTokenError => e
340
+ return build_response(401, e.message)
341
+
342
+ rescue UnautherisedTokenError => e
343
+ return build_response(403, e.message)
344
+
345
+ rescue Exception => e
346
+ return build_response(500, "An errror occured. #{e.message}")
347
+ end
348
+
349
+ return build_response(200, "Headers for vault #{vault_uuid}", headers)
350
+ end
351
+
352
+ # [AUTH] Return body of a file
353
+ post '/vaults/*/files/*' do
354
+ vault_uuid = params[:splat][0]
355
+ file_id = params[:splat][1]
356
+
357
+ unless vault_uuid
358
+ return build_response(400, 'Missing vault access id.')
359
+ end
360
+
361
+ # If request was garbage
362
+ unless request.content_type == 'application/json'
363
+ return build_response(400, 'Data was malformed. Expects JSON!')
364
+ end
365
+
366
+ # Check if the JSON data
367
+ data = nil
368
+ begin
369
+ data = JSON.parse(request.body.read)
370
+ rescue
371
+ return build_response(400, 'JSON data was malformed!')
372
+ end
373
+
374
+ token = data["token"].delete!("\n") if data["token"]
375
+
376
+ puts "#{token}\n"
377
+ puts "#{Reedb::Config::Master::dump_config}\n"
378
+
379
+ unless token
380
+ return build_response(400, 'Required data fields are missing from JSON data body!')
381
+ end
382
+
383
+ file = nil
384
+ begin
385
+ file = Reedb::Vault::access_file(vault_uuid, file_id, token, false)
386
+ rescue FileNotFoundError => e
387
+ return build_response(404, e.message)
388
+
389
+ rescue VaultNotAvailableError => e
390
+ return build_response(404, e.message)
391
+
392
+ rescue UnknownTokenError => e
393
+ return build_response(401, e.message)
394
+
395
+ rescue UnautherisedTokenError => e
396
+ return build_response(403, e.message)
397
+
398
+ end
399
+ return build_response(200, "File read without version history", file)
400
+ end
401
+
402
+ # [AUTH] Return history of a file
403
+ post '/vaults/*/files/*/history' do
404
+ vault_uuid = params[:splat][0]
405
+ file_id = params[:splat][1]
406
+
407
+ unless vault_uuid
408
+ return build_response(400, 'Missing vault access id.')
409
+ end
410
+
411
+ # If request was garbage
412
+ unless request.content_type == 'application/json'
413
+ return build_response(400, 'Data was malformed. Expects JSON!')
414
+ end
415
+
416
+ # Check if the JSON data
417
+ data = nil
418
+ begin
419
+ data = JSON.parse(request.body.read)
420
+ rescue
421
+ return build_response(400, 'JSON data was malformed!')
422
+ end
423
+
424
+ token = data["token"].delete!("\n") if data["token"]
425
+
426
+ puts "#{token}\n"
427
+ puts "#{Reedb::Config::Master::dump_config}\n"
428
+
429
+ unless token
430
+ return build_response(400, 'Required data fields are missing from JSON data body!')
431
+ end
432
+
433
+ file = nil
434
+ begin
435
+ file = Reedb::Vault::access_file(vault_uuid, file_id, token, true)
436
+ rescue FileNotFoundError => e
437
+ return build_response(404, e.message)
438
+
439
+ rescue VaultNotAvailableError => e
440
+ return build_response(404, e.message)
441
+
442
+ rescue UnknownTokenError => e
443
+ return build_response(401, e.message)
444
+
445
+ rescue UnautherisedTokenError => e
446
+ return build_response(403, e.message)
447
+
448
+ end
449
+ return build_response(200, "File read with version history", file)
450
+ end
451
+
452
+ # [AUTH] Creates a new file with data
453
+ put '/vaults/*/files' do
454
+ vault_uuid = params[:splat][0]
455
+
456
+ unless vault_uuid
457
+ return build_response(400, 'Missing vault access id.')
458
+ end
459
+
460
+ # If request was garbage
461
+ unless request.content_type == 'application/json'
462
+ return build_response(400, 'Data was malformed. Expects JSON!')
463
+ end
464
+
465
+ # Check if the JSON data
466
+ data = nil
467
+ begin
468
+ data = JSON.parse(request.body.read)
469
+ rescue
470
+ return build_response(400, 'JSON data was malformed!')
471
+ end
472
+
473
+ token = data["token"] if data["token"]
474
+ name = data["name"] if data["name"]
475
+ file_data = data["data"] if data["data"]
476
+
477
+ unless token && name && file_data
478
+ return build_response(400, 'Required data fields are missing from JSON data body!')
479
+ end
480
+
481
+ headers = Reedb::Vault::access_headers(vault_uuid, token, nil)
482
+ unless headers.include?(name)
483
+ return build_response(400, "File already exists. Use update POST instead.")
484
+ end
485
+
486
+ response = nil
487
+ begin
488
+ response = Reedb::Vault::insert(vault_uuid, token, name, file_data)
489
+ rescue VaultNotAvailableError => e
490
+ return build_response(404, e.message)
491
+
492
+ rescue UnknownTokenError => e
493
+ return build_response(401, e.message)
494
+
495
+ rescue UnautherisedTokenError => e
496
+ return build_response(403, e.message)
497
+
498
+ rescue FileBusyError => e
499
+ return build_response(418, "Dont take this error code too seriously: #{e.message}")
500
+ end
501
+
502
+ return build_response(200, "File successfully created!")
503
+ end
504
+
505
+ # [AUTH] Update file contents
506
+ post '/vaults/*/files/*' do
507
+ vault_uuid = params[:splat][0]
508
+ file_name = params[:splat][1]
509
+
510
+ unless vault_uuid
511
+ return build_response(400, 'Missing vault access id.')
512
+ end
513
+
514
+ # If request was garbage
515
+ unless request.content_type == 'application/json'
516
+ return build_response(400, 'Data was malformed. Expects JSON!')
517
+ end
518
+
519
+ # Check if the JSON data
520
+ data = nil
521
+ begin
522
+ data = JSON.parse(request.body.read)
523
+ rescue
524
+ return build_response(400, 'JSON data was malformed!')
525
+ end
526
+
527
+ token = data["token"] if data["token"]
528
+ file_data = data["data"] if data["data"]
529
+
530
+ unless token && file_data
531
+ return build_response(400, 'Required data fields are missing from JSON data body!')
532
+ end
533
+
534
+ begin
535
+ Reedb::Vault::insert(vault_uuid, token, file_name, file_data)
536
+
537
+ rescue VaultNotAvailableError => e
538
+ return build_response(404, e.message)
539
+
540
+ rescue UnknownTokenError => e
541
+ return build_response(401, e.message)
542
+
543
+ rescue UnautherisedTokenError => e
544
+ return build_response(403, e.message)
545
+
546
+ rescue FileBusyError => e
547
+ return build_response(418, "Dont take this error code too seriously: #{e.message}")
548
+ end
549
+
550
+ return build_response(200, "File successfully updated!")
551
+ end
552
+
553
+ # [AUTH] Removes a file
554
+ post '/vaults/*/files/*/remove' do
555
+ vault_uuid = params[:splat][0]
556
+ file_name = params[:splat][1]
557
+
558
+ unless vault_uuid
559
+ return build_response(400, 'Missing vault access id.')
560
+ end
561
+
562
+ # If request was garbage
563
+ unless request.content_type == 'application/json'
564
+ return build_response(400, 'Data was malformed. Expects JSON!')
565
+ end
566
+
567
+ # Check if the JSON data
568
+ data = nil
569
+ begin
570
+ data = JSON.parse(request.body.read)
571
+ rescue
572
+ return build_response(400, 'JSON data was malformed!')
573
+ end
574
+
575
+ token = data["token"] if data["token"]
576
+
577
+ begin
578
+ Reedb::Vault::remove(vault_uuid, token, file_name)
579
+
580
+ rescue FileNotFoundError, VaultNotAvailableError => e
581
+ return build_response(404, e.message)
582
+
583
+ rescue UnknownTokenError => e
584
+ return build_response(401, e.message)
585
+
586
+ rescue UnautherisedTokenError => e
587
+ return build_response(403, e.message)
588
+ end
589
+
590
+ return build_response(200, "File successfully deleted.")
591
+ end
592
+ end
593
+
594
+ options = {}
595
+
596
+ # Setting default options
597
+ options[:pw_length] = 12
598
+ options[:verbose] = false
599
+ options[:daemon] = true
600
+ options[:port] = Reedb::NET_PORT
601
+ options[:os] = Reedb::Utilities::parse_os
602
+ options[:path] = Reedb::DEF_MASTER_PATH
603
+
604
+ #create parsers
605
+ opts = OptionParser.new
606
+ opts.on('-l', '--pw-length INTEGER') { |o| options[:pw_length] = o }
607
+ opts.on('-p', '--port INTEGER') { |o| options[:port] = o }
608
+ opts.on('-v', '--verbose') { options[:verbose] = true }
609
+ opts.on('-d', '--no-daemon') { options[:daemon] = false }
610
+ opts.on('-a', '--app-path STRING') { |o| options[:path] = o }
611
+ opts.parse! unless ARGV == []
612
+
613
+ # This creates the Reedb module and binds it to a variable to be interacted with in the future
614
+ Reedb::Core::init({:os => options[:os], :pw_length => options[:pw_length],
615
+ :daemon => options[:daemon], :verbose => options[:verbose], :path => options[:path]})
616
+ # Next up we start the HTTP server and that's that. We're up and running :)
617
+ Rack::Handler::WEBrick.run(ReedbHandler.new, {:Port => options[:port], :BindAddress => "localhost"})