kbsecret 0.0.1 → 0.0.2
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.
- checksums.yaml +4 -4
- data/README.md +4 -2
- data/lib/kbsecret/config.rb +21 -0
- data/lib/kbsecret/exceptions.rb +2 -0
- data/lib/kbsecret/record/abstract.rb +27 -0
- data/lib/kbsecret/record/environment.rb +21 -1
- data/lib/kbsecret/record/login.rb +13 -0
- data/lib/kbsecret/record/unstructured.rb +8 -0
- data/lib/kbsecret/record.rb +9 -0
- data/lib/kbsecret/session.rb +26 -0
- data/lib/kbsecret.rb +4 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f468bb679d062bf75ce1d379e4cd76c4544c090f
|
4
|
+
data.tar.gz: d862b1c03920b88de8942fac32ad6f7b4fb89bd2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
31
|
+
$ RUBYLIB=./lib PATH=./bin:${PATH} ./bin/kbsecret help
|
30
32
|
```
|
31
33
|
|
32
34
|
### Usage
|
data/lib/kbsecret/config.rb
CHANGED
@@ -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 }
|
data/lib/kbsecret/exceptions.rb
CHANGED
@@ -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}
|
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!
|
data/lib/kbsecret/record.rb
CHANGED
@@ -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] }
|
data/lib/kbsecret/session.rb
CHANGED
@@ -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
|
-
|
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.
|
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
|
64
|
-
- kbsecret-list
|
65
|
-
- kbsecret-sessions
|
65
|
+
- kbsecret
|
66
66
|
extensions: []
|
67
67
|
extra_rdoc_files: []
|
68
68
|
files:
|