Class: PassStation::DB
- Inherits:
-
Object
- Object
- PassStation::DB
- Defined in:
- lib/pass_station.rb,
lib/pass_station/parse.rb,
lib/pass_station/output.rb,
lib/pass_station/search.rb,
lib/pass_station/source.rb
Overview
Password database handling
Constant Summary collapse
- UPSTREAM_DATABASE =
{ MAPPING: { 1 => :DEFAULT_CREDENTIALS_CHEAT_SHEET, 2 => :MANY_PASSWORDS }, DEFAULT_CREDENTIALS_CHEAT_SHEET: { URL: 'https://raw.githubusercontent.com/ihebski/DefaultCreds-cheat-sheet/main/DefaultCreds-Cheat-Sheet.csv', HASH: 'f03f3ed77a8a932b1b2891fbec705d42b1eec4911fb76ccf36cde9e79a385556', FILENAME: 'DefaultCreds-Cheat-Sheet.csv', COLUMNS: { productvendor: 'Product/Vendor', username: 'Username', password: 'Password' } }, MANY_PASSWORDS: { URL: 'https://raw.githubusercontent.com/many-passwords/many-passwords/main/passwords.csv', HASH: '293ce4411446c702aeda977b9a446ff42d045d980be0b5287a848b5bd7d39402', FILENAME: 'many-passwords.csv', COLUMNS: { vendor: 'Vendor', modelsoftware_name: 'Model/Software name', version: 'Version', access_type: 'Access Type', username: 'Username', password: 'Password', privileges: 'Privileges', notes: 'Notes' } } }.freeze
Instance Attribute Summary collapse
-
#data ⇒ Array<CSV::Row>
readonly
Get the password database in
Array<CSV::Row>
format. -
#database_name ⇒ String
Get / set the password database name.
-
#storage_location ⇒ String
Get / set storage location, where will be stored the password database.
Class Method Summary collapse
-
.check_for_update ⇒ Boolean
Check if an update is available.
-
.check_hash(file, hash) ⇒ Boolean
Check if a file match a SHA256 hash.
-
.download_file(file_url, destination_path, opts = {}) ⇒ String|nil
Download a file.
-
.download_upstream(destination_path, opts = {}) ⇒ String|nil
Download upstream password database.
-
.fetch_file(uri) ⇒ Bytes
Just fetch a file.
-
.write_file(destination_file, file_content) ⇒ String
Write a file to disk.
Instance Method Summary collapse
-
#highlight_found(term, text, sensitive) ⇒ Array<String>
Highlight (colorize) a searched term in the input When used with the search command, it will ignore in which column the search was made, and will instead colorize in every columns.
-
#initialize(db = nil) ⇒ DB
constructor
A new instance of Pass Station.
-
#output(formatter, data) ⇒ Array<String>
Output the data in the chosen format.
-
#output_list(formatter) ⇒ Array<String>
Output the data in the chosen format (list command).
-
#output_search(formatter) ⇒ Array<String>
Output the data in the chosen format (search command).
-
#parse(sort = nil) ⇒ Array<CSV::Row>
Parse, sort and sanitize the password database.
-
#search(term, col, opts = {}) ⇒ Array<CSV::Row>
Search term in the data table.
Constructor Details
#initialize(db = nil) ⇒ DB
A new instance of Pass Station
33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/pass_station.rb', line 33 def initialize(db = nil) db ||= 1 @storage_location = 'data/' @database_type = UPSTREAM_DATABASE[:MAPPING][db] @database_name = UPSTREAM_DATABASE[@database_type][:FILENAME] @database_path = absolute_db_path database_exists? @config = {} csv_config @data = nil @search_result = [] end |
Instance Attribute Details
#data ⇒ Array<CSV::Row> (readonly)
Get the password database in Array<CSV::Row>
format
29 30 31 |
# File 'lib/pass_station.rb', line 29 def data @data end |
#database_name ⇒ String
Get / set the password database name
25 26 27 |
# File 'lib/pass_station.rb', line 25 def database_name @database_name end |
#storage_location ⇒ String
Get / set storage location, where will be stored the password database.
20 21 22 |
# File 'lib/pass_station.rb', line 20 def storage_location @storage_location end |
Class Method Details
.check_for_update ⇒ Boolean
Check if an update is available
62 63 64 65 66 67 68 69 70 |
# File 'lib/pass_station/source.rb', line 62 def check_for_update ret_vals = [] UPSTREAM_DATABASE[:MAPPING].each do |_k, v| file = download_file(UPSTREAM_DATABASE[v][:URL], Dir.mktmpdir) # Same hash = no update ret_vals << !check_hash(file, UPSTREAM_DATABASE[v][:HASH]) end ret_vals.inject(:|) # logical OR, there is an update if at least one entry needs one end |
.check_hash(file, hash) ⇒ Boolean
Check if a file match a SHA256 hash
98 99 100 101 102 103 104 105 |
# File 'lib/pass_station/source.rb', line 98 def check_hash(file, hash) if !hash.nil? && File.file?(file) computed_h = Digest::SHA256.file(file) true if hash.casecmp(computed_h.hexdigest).zero? else false end end |
.download_file(file_url, destination_path, opts = {}) ⇒ String|nil
Download a file.
81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/pass_station/source.rb', line 81 def download_file(file_url, destination_path, opts = {}) opts[:sha256] ||= nil destination_path += '/' unless destination_path[-1] == '/' uri = URI(file_url) opts[:filename] ||= uri.path.split('/').last destination_file = destination_path + opts[:filename] # Verify hash to see if it is the latest skip_download = check_hash(destination_file, opts[:sha256]) write_file(destination_file, fetch_file(uri)) unless skip_download end |
.download_upstream(destination_path, opts = {}) ⇒ String|nil
Download upstream password database
52 53 54 55 56 57 58 |
# File 'lib/pass_station/source.rb', line 52 def download_upstream(destination_path, opts = {}) opts[:source_db] ||= 1 source_db = UPSTREAM_DATABASE[:MAPPING][opts[:source_db]] opts[:filename] = UPSTREAM_DATABASE[source_db][:FILENAME] source_url = UPSTREAM_DATABASE[source_db][:URL] download_file(source_url, destination_path, opts) end |
.fetch_file(uri) ⇒ Bytes
Just fetch a file
110 111 112 113 114 115 |
# File 'lib/pass_station/source.rb', line 110 def fetch_file(uri) res = Net::HTTP.get_response(uri) raise "#{file_url} ended with #{res.code} #{res.}" unless res.is_a?(Net::HTTPSuccess) res.body end |
.write_file(destination_file, file_content) ⇒ String
Write a file to disk
122 123 124 125 |
# File 'lib/pass_station/source.rb', line 122 def write_file(destination_file, file_content) File.binwrite(destination_file, file_content) destination_file end |
Instance Method Details
#highlight_found(term, text, sensitive) ⇒ Array<String>
Highlight (colorize) a searched term in the input When used with the search command, it will ignore in which column the search was made, and will instead colorize in every columns.
47 48 49 50 51 52 |
# File 'lib/pass_station/output.rb', line 47 def highlight_found(term, text, sensitive) text.map do |x| rgxp = build_regexp(term, sensitive: sensitive) x.gsub(rgxp) { |s| Paint[s, :red] } end end |
#output(formatter, data) ⇒ Array<String>
Output the data in the chosen format
18 19 20 21 |
# File 'lib/pass_station/output.rb', line 18 def output(formatter, data) # Convert string to class Object.const_get("PassStation::Output::#{normalize(formatter)}").format(data) end |
#output_list(formatter) ⇒ Array<String>
Output the data in the chosen format (list command)
26 27 28 29 |
# File 'lib/pass_station/output.rb', line 26 def output_list(formatter) data_nil? output(formatter, @data) end |
#output_search(formatter) ⇒ Array<String>
Output the data in the chosen format (search command)
34 35 36 37 38 |
# File 'lib/pass_station/output.rb', line 34 def output_search(formatter) return [] if @search_result.empty? output(formatter, @search_result) end |
#parse(sort = nil) ⇒ Array<CSV::Row>
Parse, sort and sanitize the password database
28 29 30 31 32 33 |
# File 'lib/pass_station/parse.rb', line 28 def parse(sort = nil) sort ||= UPSTREAM_DATABASE[@database_type][:COLUMNS].first[0] @data = CSV.table(@database_path, **@config).sort_by do |s| s[sort].downcase end end |
#search(term, col, opts = {}) ⇒ Array<CSV::Row>
Search term in the data table
14 15 16 17 18 19 20 21 22 |
# File 'lib/pass_station/search.rb', line 14 def search(term, col, opts = {}) col ||= UPSTREAM_DATABASE[@database_type][:COLUMNS].first[0] r1 = prepare_search(term, opts) condition = column_selector(col, r1) @data.each do |row| @search_result.push(row) if condition.call(row) end @search_result end |