kbsecret 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9587292e2be80b4a53d26f4bdda06e2a94d1b7be
4
- data.tar.gz: 5dd01f1c1819f0f17537487ff73e621e27193938
3
+ metadata.gz: f468bb679d062bf75ce1d379e4cd76c4544c090f
4
+ data.tar.gz: d862b1c03920b88de8942fac32ad6f7b4fb89bd2
5
5
  SHA512:
6
- metadata.gz: 4227a95d277ed064a5cd1b4dd3add4dedcabb97d041c66c5dffec753a87ab0de73684582a4d18e34bd33c192912d54dc173527516daa10a172dbd19d55e73574
7
- data.tar.gz: b14e1d1524a71d70e85185c7c61c43a3791923c5698273b68398b6dcf1d072a682a3f7bfb695666d1cd25819812d740e5cf150c71142571d741dd5e426091845
6
+ metadata.gz: a9de681a6224e5f577deb31e8a72cafe288fa9d48c7de5e7438616c8887408a3705e813bd588fdfc328b84683e0f5b51540f58911163c81494cde918851306a4
7
+ data.tar.gz: 0fbe3224bc94a6a39eea6e1e0c578ab01fcd4755e92e827cd08441151086bd1cc2c65d00c2de8cfbefca0a32847001d53d7fc5496058de45bdf937cc7e3e64b7
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  kbsecret
2
2
  ========
3
3
 
4
+ *Note*: This is still a work in process. Use it with caution.
5
+
4
6
  kbsecret is a combined library/utility that provides a secret management
5
7
  interface for [KBFS](https://keybase.io/docs/kbfs) and
6
8
  [Keybase](https://keybase.io/).
@@ -16,7 +18,7 @@ interface for [KBFS](https://keybase.io/docs/kbfs) and
16
18
 
17
19
  ### Installation
18
20
 
19
- kbsecret is available via RubyGems:
21
+ kbsecret is available via [RubyGems](https://rubygems.org/gems/kbsecret):
20
22
 
21
23
  ```bash
22
24
  $ gem install kbsecret
@@ -26,7 +28,7 @@ For hacking:
26
28
 
27
29
  ```bash
28
30
  $ git clone git@github.com:woodruffw/kbsecret.git && cd kbsecret
29
- $ RUBYLIB=./lib PATH=${PATH}:./bin ./bin/kbsecret help
31
+ $ RUBYLIB=./lib PATH=./bin:${PATH} ./bin/kbsecret help
30
32
  ```
31
33
 
32
34
  ### Usage
@@ -2,11 +2,18 @@ require "yaml"
2
2
  require "fileutils"
3
3
 
4
4
  module KBSecret
5
+ # Global and per-session configuration for kbsecret.
5
6
  class Config
7
+ # the configuration directory
8
+ # @api private
6
9
  CONFIG_DIR = File.expand_path("~/.config/kbsecret").freeze
7
10
 
11
+ # the configuration file
12
+ # @api private
8
13
  CONFIG_FILE = File.join(CONFIG_DIR, "config.yml").freeze
9
14
 
15
+ # configuration defaults
16
+ # @api private
10
17
  DEFAULT_CONFIG = {
11
18
  mount: "/keybase",
12
19
 
@@ -18,22 +25,36 @@ module KBSecret
18
25
  }
19
26
  }.freeze
20
27
 
28
+ # Retrieve a configured value.
29
+ # @param key [String]
30
+ # @return [Object] the corresponding configuration
21
31
  def self.[](key)
22
32
  @@config[key]
23
33
  end
24
34
 
35
+ # Retrieve a session's configuration.
36
+ # @param sess [Symbol] the session's label
37
+ # @return [Hash] the session configuration
25
38
  def self.session(sess)
26
39
  @@config[:sessions][sess]
27
40
  end
28
41
 
42
+ # @return [Array<Symbol>] all configured session labels
43
+ # @todo This should be session_labels.
29
44
  def self.session_names
30
45
  @@config[:sessions].keys
31
46
  end
32
47
 
48
+ # @param sess [Symbol] the session label
49
+ # @return [Boolean] whether or not the given session is configured
33
50
  def self.session?(sess)
34
51
  session_names.include?(sess.to_sym)
35
52
  end
36
53
 
54
+ # Configure a session.
55
+ # @param label [Symbol] the session label
56
+ # @param hsh [Hash] the session configuration
57
+ # @todo This should be configure_session.
37
58
  def self.add_session(label, hsh)
38
59
  @@config[:sessions][label.to_sym] = hsh
39
60
  File.open(CONFIG_FILE, "w") { |io| io.write @@config.to_yaml }
@@ -1,7 +1,9 @@
1
1
  module KBSecret
2
+ # A generic error in kbsecret.
2
3
  class KBSecretError < RuntimeError
3
4
  end
4
5
 
6
+ # Raised during record creation if too many/few arguments are given.
5
7
  class RecordCreationArityError < RuntimeError
6
8
  def initialize(exp, act)
7
9
  super "Needed #{exp} arguments for this record, got #{act}"
@@ -2,6 +2,8 @@ require "json"
2
2
 
3
3
  module KBSecret
4
4
  module Record
5
+ # Represents an abstract kbsecret record that can be subclassed to produce
6
+ # more useful records.
5
7
  # @abstract
6
8
  class Abstract
7
9
  attr_accessor :session
@@ -10,10 +12,18 @@ module KBSecret
10
12
  attr_reader :type
11
13
  attr_reader :data
12
14
 
15
+ # @return [String] the record's type
16
+ # @example
17
+ # KBSecret::Record::Abstract.type # => "abstract"
13
18
  def self.type
14
19
  name.split("::").last.downcase
15
20
  end
16
21
 
22
+ # Load the given hash-representation into a record.
23
+ # @param session [Session] the session to associate with
24
+ # @param hsh [Hash] the record's hash-representation
25
+ # @return [Record::AbstractRecord] the created record
26
+ # @api private
17
27
  def self.load!(session, hsh)
18
28
  instance = allocate
19
29
  instance.session = session
@@ -22,6 +32,10 @@ module KBSecret
22
32
  instance
23
33
  end
24
34
 
35
+ # Create a brand new record, associated with a session.
36
+ # @param session [Session] the session to associate with
37
+ # @param label [Symbol] the new record's label
38
+ # @note Creation does *not* sync the new record; see {#sync!} for that.
25
39
  def initialize(session, label)
26
40
  @session = session
27
41
  @timestamp = Time.now.to_i
@@ -30,6 +44,10 @@ module KBSecret
30
44
  @data = {}
31
45
  end
32
46
 
47
+ # Fill in instance fields from a record's hash-representation.
48
+ # @param hsh [Hash] the record's hash-representation.
49
+ # @return [void]
50
+ # @api private
33
51
  def initialize_from_hash(hsh)
34
52
  @timestamp = hsh[:timestamp]
35
53
  @label = hsh[:label]
@@ -37,10 +55,16 @@ module KBSecret
37
55
  @data = hsh[:data]
38
56
  end
39
57
 
58
+ # The fully qualified path to the record's file.
59
+ # @return [String] the path
60
+ # @note If the record hasn't been synced to disk, this path may not
61
+ # exist yet.
40
62
  def path
41
63
  File.join(session.directory, "#{label}.json")
42
64
  end
43
65
 
66
+ # Create a hash-representation of the current record.
67
+ # @return [Hash] the hash-representation
44
68
  def to_h
45
69
  {
46
70
  timestamp: timestamp,
@@ -50,6 +74,9 @@ module KBSecret
50
74
  }
51
75
  end
52
76
 
77
+ # Write the record's in-memory state to disk.
78
+ # @note Every sync updates the record's timestamp.
79
+ # @return [void]
53
80
  def sync!
54
81
  # bump the timestamp every time we sync
55
82
  @timestamp = Time.now.to_i
@@ -1,9 +1,19 @@
1
+ require "shellwords"
2
+
1
3
  module KBSecret
2
4
  module Record
5
+ # Represents a record containing an environment variable and value.
3
6
  class Environment < Abstract
7
+ # @param session [Session] the session to associate with
8
+ # @param label [Symbol] the new record's label
9
+ # @param variable [String] the new record's variable
10
+ # @param value [String] the new record's value
4
11
  def initialize(session, label, variable, value)
5
12
  super(session, label)
6
13
 
14
+ value = value.shellescape
15
+ variable = variable.shellescape
16
+
7
17
  @data = {
8
18
  environment: {
9
19
  variable: variable,
@@ -12,28 +22,38 @@ module KBSecret
12
22
  }
13
23
  end
14
24
 
25
+ # @return [String] the record's variable
15
26
  def variable
16
27
  @data[:environment][:variable]
17
28
  end
18
29
 
30
+ # @param var [String] the new variable to insert into the record
31
+ # @return [void]
32
+ # @note Triggers a record sync; see {Abstract#sync!}.
19
33
  def variable=(var)
20
34
  @data[:environment][:variable] = var
21
35
  sync!
22
36
  end
23
37
 
38
+ # @return [String] the record's value
24
39
  def value
25
40
  @data[:environment][:value]
26
41
  end
27
42
 
43
+ # @param val [String] the new value to insert into the record
44
+ # @return [void]
45
+ # @note Triggers a record sync; see {Abstract#sync!}.
28
46
  def value=(val)
29
47
  @data[:environment][:value] = val
30
48
  sync!
31
49
  end
32
50
 
51
+ # @return [String] a sh-style environment assignment
33
52
  def to_assignment
34
- "#{variable}='#{value}'"
53
+ "#{variable}=#{value}"
35
54
  end
36
55
 
56
+ # @return [String] a sh-style environment export line
37
57
  def to_export
38
58
  "export #{to_assignment}"
39
59
  end
@@ -1,6 +1,11 @@
1
1
  module KBSecret
2
2
  module Record
3
+ # Represents a record containing a login (username, password) pair.
3
4
  class Login < Abstract
5
+ # @param session [Session] the session to associate with
6
+ # @param label [Symbol] the new record's label
7
+ # @param user [String] the new record's username
8
+ # @param pass [String] the new record's password
4
9
  def initialize(session, label, user, pass)
5
10
  super(session, label)
6
11
 
@@ -12,19 +17,27 @@ module KBSecret
12
17
  }
13
18
  end
14
19
 
20
+ # @return [String] the record's username
15
21
  def username
16
22
  @data[:login][:username]
17
23
  end
18
24
 
25
+ # @param user [String] the new username to insert into the record
26
+ # @return [void]
27
+ # @note Triggers a record sync; see {Abstract#sync!}.
19
28
  def username=(user)
20
29
  @data[:login][:username] = user
21
30
  sync!
22
31
  end
23
32
 
33
+ # @return [String] the record's password
24
34
  def password
25
35
  @data[:login][:password]
26
36
  end
27
37
 
38
+ # @param pass [String] the new password to insert into the record
39
+ # @return [void]
40
+ # @note Triggers a record sync; see {Abstract#sync!}.
28
41
  def password=(pass)
29
42
  @data[:login][:password] = pass
30
43
  sync!
@@ -1,6 +1,10 @@
1
1
  module KBSecret
2
2
  module Record
3
+ # Represents a record containing unstructured text.
3
4
  class Unstructured < Abstract
5
+ # @param session [Session] the session to associate with
6
+ # @param label [Symbol] the new record's label
7
+ # @param text [String] the new record's unstructured text
4
8
  def initialize(session, label, text)
5
9
  super(session, label)
6
10
 
@@ -9,10 +13,14 @@ module KBSecret
9
13
  }
10
14
  end
11
15
 
16
+ # @return [String] the record's unstructured text
12
17
  def text
13
18
  @data[:text]
14
19
  end
15
20
 
21
+ # @param new_text [String] the new text to insert into the record
22
+ # @return [void]
23
+ # @note Triggers a record sync; see {Abstract#sync!}.
16
24
  def text=(new_text)
17
25
  @data[:text] = new_text
18
26
  sync!
@@ -6,21 +6,30 @@ require_relative "record/environment"
6
6
  require_relative "record/unstructured"
7
7
 
8
8
  module KBSecret
9
+ # The namespace for kbsecret records types.
9
10
  module Record
11
+ # @return [Array<Class>] the class objects of all non-abstract record types
10
12
  def self.record_classes
11
13
  klasses = constants.map(&Record.method(:const_get)).grep(Class)
12
14
  klasses.delete(Record::Abstract)
13
15
  klasses
14
16
  end
15
17
 
18
+ # @return [Array<String>] the types of all records
16
19
  def self.record_types
17
20
  record_classes.map(&:type)
18
21
  end
19
22
 
23
+ # @return [Boolean] whether a record class exists of the given type
20
24
  def self.type?(type)
21
25
  record_types.include?(type)
22
26
  end
23
27
 
28
+ # Load a record by path into the given session.
29
+ # @param session [Session] the session to load into
30
+ # @param path [String] the fully-qualified record path
31
+ # @return [Record::AbstractRecord] the loaded record
32
+ # @api private
24
33
  def self.load_record!(session, path)
25
34
  hsh = JSON.parse(File.read(path), symbolize_names: true)
26
35
  klass = record_classes.find { |c| c.type == hsh[:type] }
@@ -1,10 +1,20 @@
1
1
  module KBSecret
2
+ # Represents a session of N keybase users with collective read/write
3
+ # access to a collection of records.
2
4
  class Session
5
+ # @return [Symbol] the session's label
3
6
  attr_reader :label
7
+
8
+ # @return [Hash] the session-specific configuration, from
9
+ # {Config::CONFIG_FILE}
4
10
  attr_reader :config
5
11
  attr_reader :directory
6
12
  attr_reader :records
7
13
 
14
+ # @param label [Symbol] the label of the session to initialize
15
+ # @note This does not *create* a new session, but loads one already
16
+ # specified in {Config::CONFIG_FILE}. To *create* a new session,
17
+ # see {Config.add_session}.
8
18
  def initialize(label: :default)
9
19
  @label = label
10
20
  @config = Config.session(label.to_sym)
@@ -13,10 +23,20 @@ module KBSecret
13
23
  @records = load_records!
14
24
  end
15
25
 
26
+ # @return [Array<Symbol>] the labels of all records known to the session
27
+ # @example
28
+ # session.record_labels # => [:website1, :apikey1, :website2]
16
29
  def record_labels
17
30
  records.map(&:label)
18
31
  end
19
32
 
33
+ # Add a record to the session.
34
+ # @param type [String] the type of record (see {Record.record_types})
35
+ # @param label [Symbol] the new record's label
36
+ # @param args [Array<String>] the record-type specific arguments
37
+ # @return [void]
38
+ # @raise RecordCreationArityError if the number of specified record
39
+ # arguments does not match the record type's constructor
20
40
  def add_record(type, label, *args)
21
41
  klass = Record.record_classes.find { |k| k.type == type }
22
42
  arity = klass.instance_method(:initialize).arity - 2
@@ -30,6 +50,10 @@ module KBSecret
30
50
  record.sync!
31
51
  end
32
52
 
53
+ # Delete a record from the session, if it exists. Does nothing if
54
+ # no such record can be found.
55
+ # @param rec_label [Symbol] the label of the record to delete
56
+ # @return [void]
33
57
  def delete_record(rec_label)
34
58
  record = records.find { |r| r.label == rec_label }
35
59
  return unless record
@@ -38,6 +62,8 @@ module KBSecret
38
62
  records.delete(record)
39
63
  end
40
64
 
65
+ # @return [Boolean] whether or not the session contains a record with the
66
+ # given label
41
67
  def record?(label)
42
68
  record_labels.include?(label)
43
69
  end
data/lib/kbsecret.rb CHANGED
@@ -5,9 +5,12 @@ require_relative "kbsecret/exceptions"
5
5
  require_relative "kbsecret/record"
6
6
  require_relative "kbsecret/session"
7
7
 
8
+ # The primary namespace for kbsecret.
8
9
  module KBSecret
9
- VERSION = "0.0.1".freeze
10
+ # kbsecret's current version
11
+ VERSION = "0.0.2".freeze
10
12
 
13
+ # fail very early if the user doesn't have keybase and KBFS running
11
14
  raise Keybase::KeybaseNotRunningError unless Keybase.running?
12
15
  raise Keybase::KBFSNotRunningError unless Dir.exist?(Config[:mount])
13
16
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kbsecret
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - William Woodruff
@@ -55,14 +55,14 @@ dependencies:
55
55
  description: Manages your passwords, environment, and more via KBFS.
56
56
  email: william@tuffbizz.com
57
57
  executables:
58
- - kbsecret
58
+ - kbsecret-sessions
59
+ - kbsecret-new-session
60
+ - kbsecret-new
59
61
  - kbsecret-rm
62
+ - kbsecret-list
60
63
  - kbsecret-login
61
- - kbsecret-new
62
64
  - kbsecret-env
63
- - kbsecret-new-session
64
- - kbsecret-list
65
- - kbsecret-sessions
65
+ - kbsecret
66
66
  extensions: []
67
67
  extra_rdoc_files: []
68
68
  files: