reedb 0.10.rc1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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"})