Class: SafeDb::Store::ColdStore

Inherits:
Object
  • Object
show all
Defined in:
lib/modules/storage/coldstore.rb

Overview

Cold storage can sync repositories with a bias during conflicts either to the remote repository when pulling, and then conversely to the local reposiory when pushing.

In between the sync operations a ColdStore can create, read, update and delete to and from the local mirror.

ColdStore | Use Cases

Any self-respecting coldstore must, after initialization, provide some basic (and mandatory) behaviour.

These include

  • read - reading text from a (possibly unavailable) frozen path

  • write - writing text (effectively freezing it) to a path

  • pull - sync with a collision bias that favours the remote mirror

  • push - sync with a collision bias that favours the local mirror

Cold Storage is borrowed from BitCoin and represents offline storage for keys and crypts. safe separates keys and crypts so that you can transfer and share secrets by moving keys (not the crypts).

Houses and Gold Bullion

You don’t carry houses or gold bullion around to rent, share or transfer their ownership.

You copy keys to rent secrets and when the tenure is up (or you change your mind) you revoke access with a metaphorical lock change.

safe embodies concepts like an owner who rents as opposed to a change in ownership.

trade secrets | commoditizing secrets

safe is a conduit through which secrets can be bought and sold.

It commoditizes secrets so that they can be owned, traded, leased and auctioned. Options to acquire or relinquish them at set prices can easily be taken out.

Instance Method Summary collapse

Constructor Details

#initialize(local_path) ⇒ ColdStore

Returns a new instance of ColdStore.

Parameters:

  • base_path (String)

    path to the store’s (mirror) base directory. If the denoted directory does not exist an attempt will be made to create it. If a file exists at this path an error will be thrown.

  • domain (String)

    the domain is an identifier (and namespace) denoting which safe “account” is being accessed. safe allows the creation and use of multiple domains.



60
61
62
63
64
65
# File 'lib/modules/storage/coldstore.rb', line 60

def initialize local_path

  @store_path = local_path
  FileUtils.mkdir_p @store_path

end

Instance Method Details

#read(from_path) ⇒ String

Read the file frozen (in this store mirror) at this path and return its contents.

Coldstores are usually frozen offline (offmachine) so for this to work the #pull behaviour must have executed to create a local store mirror. This method reads from that mirror.

Parameters:

  • from_path (String)

    read the file frozen at this path and return its contents so that the defreeze process can begin.

    This path is relative to the base of the store defined in the constructor.

Returns:

  • (String)

    return the text frozen in a file at the denoted local path

    nil is reurned if no file can be found in the local mirror at the configured path

Raises:

  • (RuntimeError)

    unless the path exists in this coldstore and that path is a directory (as opposed to a file).

  • (ArgumentError)

    if more than one file match is made at the path specified.



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/modules/storage/coldstore.rb', line 94

def read from_path

  frozen_filepath = File.join @store_path, from_path
  frozen_dir_path = File.dirname(frozen_filepath)

  log.info(x) { "Coldstore will search in folder [#{frozen_dir_path.hr_path}]" }

  exists_msg = "Directory #{frozen_dir_path} does not exist in store."
  is_dir_msg = "Path #{frozen_dir_path} should be a directory (not a file)."
  raise RuntimeError, exists_msg unless File.exists? frozen_dir_path
  raise RuntimeError, is_dir_msg unless File.directory? frozen_dir_path

  full_filepath = ""
  file_matched = false

  Dir.glob("#{frozen_dir_path}/**/*.os.txt").each do |matched_path|

    log.info(x) { "Coldstore search with [#{from_path}] has matched [#{matched_path.hr_path}]" }
    log.info(x) { "Ignore directory at [#{matched_path.hr_path}]." } if File.directory? matched_path
    next if File.directory? matched_path

    two_match_msg = "More than one file matched. The second is #{matched_path}."
    raise ArgumentError, two_match_msg if file_matched
    file_matched = true

    full_filepath = matched_path

  end

  no_file_msg = "Coldstore could not find path [#{from_path}] from [#{@store_path}]."
  raise RuntimeError, no_file_msg unless file_matched

  log.info(x) { "Coldstore matched exactly one envelope at [#{full_filepath.hr_path}]." }
  return File.read full_filepath

end

#write(this_text, to_path) ⇒ Object

Write (freeze) the text into a file at the denoted path. The folder path will be created if need be.

Coldstores are usually frozen offline (offmachine) so after this method completes the #push behaviour must be executed to synchronize the local coldstore freezer with the remote mirror.

Parameters:

  • this_text (String)

    this is the text that needs to be frozen into the local and subsequently the remote coldstore freezer.

  • to_path (String)

    write the text (effectively freezing it) into the file at this path. An attempt will be made to put down the necessary directory structure.

    This path is relative to the base of the store defined in the constructor.



151
152
153
154
155
156
157
158
159
160
161
# File 'lib/modules/storage/coldstore.rb', line 151

def write this_text, to_path

  freeze_filepath = File.join @store_path, to_path

  log.info(x) { "ColdStore freezing #{this_text.length} characters of worthless text."}
  log.info(x) { "ColdStore freeze file path => #{freeze_filepath.hr_path}"}

  FileUtils.mkdir_p(File.dirname(freeze_filepath))
  File.write freeze_filepath, this_text

end