trunk 0.1.0 → 0.1.1

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
  SHA256:
3
- metadata.gz: d63e9f1885845c0dcfbddc0e2e2b8e9a685e732d19fdb0b6e0b319064b7093c6
4
- data.tar.gz: ea15f59e0f1864d0d8ad77ea6ad2be038938314481e9d299c00d5aa0a548a413
3
+ metadata.gz: 237505d740522814bab6d0401ae982a01d12b56792dc3913cf1594dcf50d2ad5
4
+ data.tar.gz: c9e2b68bdd588fee6e82095662f62bdd025def1c7f948f3085939f83f4d48b51
5
5
  SHA512:
6
- metadata.gz: 4878ac13c5a8508eb4b426bbf3f76d8907c8d2abbd6790fa508e2612f8da6f817309db678e301c67123899b7502f6981ce7c95b89e4abcc038fef05bea351d8e
7
- data.tar.gz: 42f5ddbc1b13dd8c82846b0363fcfb1edab7cbef80ef7714f73196e705025660ecb374a0db5f19d713601304b06aa3c9f45d0437fe81d2efb126530bfc974e69
6
+ metadata.gz: 7b6900e6f99a1bd58ebd0fa4185535be1c6ec03d9b7649d805263bb19a41715c7a5175d80bc32a13b922e431934c0cd0929ea28a446d7100e22dbd5cd8b9bb8f
7
+ data.tar.gz: bf4a7c862bdfb9ef31621f70cf6bcd3da6f2ab08221eb2c4ce0f4de2b8f2524fe986e9867e12317c5f5428b112ccc6b55f7ec52a86ca6f2b5003a1b67ac7fd62
data/.gitignore CHANGED
@@ -10,3 +10,5 @@
10
10
  # rspec failure tracking
11
11
  .rspec_status
12
12
  Gemfile.lock
13
+ .trunk.enc
14
+ .trunk.key.enc
data/README.md CHANGED
@@ -22,17 +22,9 @@ Or install it yourself as:
22
22
 
23
23
  ## Usage
24
24
 
25
- TODO: Write usage instructions here
26
-
27
25
  ```bash
28
- $ trunk add --title=title --username=username --password=password
29
- $ trunk add <title> <username> - # read password from stdin
30
- $ trunk add
31
- $ title:>
32
- $ username:>
33
- $ password:>
34
-
35
-
26
+ $ trunk add key password
27
+ $ trunk add key - # read password from stdin
36
28
  $ trunk show title
37
29
  ```
38
30
 
@@ -51,7 +43,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
51
43
 
52
44
  ## Contributing
53
45
 
54
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/trunk.
46
+ Bug reports and pull requests are welcome on GitHub at https://github.com/mokhan/trunk.
55
47
 
56
48
  ## License
57
49
 
data/lib/trunk.rb CHANGED
@@ -1,7 +1,15 @@
1
- require 'optparse'
1
+ require 'base64'
2
+ require 'fileutils'
3
+ require 'openssl'
4
+ require 'thor'
5
+ require 'yaml'
2
6
 
3
7
  require "trunk/cli"
8
+ require "trunk/serializers/base_64"
9
+ require "trunk/serializers/composite"
10
+ require "trunk/serializers/crypto"
4
11
  require "trunk/storage"
12
+ require "trunk/yaml_storage"
5
13
  require "trunk/version"
6
14
 
7
15
  module Trunk
data/lib/trunk/cli.rb CHANGED
@@ -1,77 +1,56 @@
1
1
  module Trunk
2
- class AddCommand
3
- def matches?(command)
4
- "add" == command
2
+ class CLI < Thor
3
+ desc "add NAME PASSWORD", "add a key and password"
4
+ def add(name, password = $stdin.gets.strip)
5
+ storage.store(name, password)
5
6
  end
6
7
 
7
- def run(arguments)
8
- OptionParser.new do |parser|
9
- parser.banner = "Usage: trunk add [options]"
10
- parser.on_tail("-h", "--help", "print help") do
11
- puts parser
12
- end
13
- end.parse!(arguments)
8
+ desc "show NAME", "print the password associated with a key"
9
+ def show(name)
10
+ print storage.fetch(name)
11
+ rescue OpenSSL::PKey::RSAError => error
12
+ say error.message, :red
13
+ end
14
14
 
15
- print "title:> "
16
- title = STDIN.gets
17
- print "username:> "
18
- username = STDIN.gets
19
- print "password:> "
20
- password = STDIN.gets
15
+ desc "version", "print the version"
16
+ def version
17
+ say Trunk::VERSION
18
+ end
21
19
 
22
- puts [title, username, password].inspect
20
+ desc "setup", "create the database and private key file."
21
+ method_option :algorithm, type: :string, default: 'AES-256-CBC'
22
+ def setup
23
+ FileUtils.mkdir_p(dir)
24
+ exit(0) unless file_collision(private_key_path) if File.exist?(private_key_path)
25
+ IO.write(private_key_path, OpenSSL::PKey::RSA.new(4096).export(options[:algorithm], passphrase))
26
+ FileUtils.touch(database_path)
27
+ [database_path, private_key_path].each { |x| FileUtils.chmod(0600, x) }
23
28
  end
24
- end
25
29
 
26
- class DefaultCommand
27
- def run(arguments)
28
- parser = OptionParser.new
29
- parser.banner = "Usage: trunk [options]"
30
- parser.on("-v", "--[no-]verbose", "run verbosely") do |v|
31
- end
32
- parser.on("--version", "show version") do |v|
33
- puts Trunk::VERSION
34
- end
35
- parser.on_tail("-h", "--help", "print help") do
36
- puts parser
37
- end
38
- parser.parse!(arguments)
30
+ private
31
+
32
+ def storage
33
+ @storage ||= Trunk::YAMLStorage.new(database_path, private_key)
39
34
  end
40
- end
41
35
 
42
- class CLI
43
- attr_reader :parser, :commands
36
+ def database_path
37
+ File.join(dir, '.trunk.enc')
38
+ end
44
39
 
45
- def initialize
46
- @commands = []
47
- @commands.push(AddCommand.new)
40
+ def private_key_path
41
+ File.join(dir, '.trunk.key.enc')
48
42
  end
49
43
 
50
- def command_for(arguments)
51
- if arguments.empty? || arguments[0]&.start_with?("-")
52
- DefaultCommand.new
53
- else
54
- commands.find { |x| x.matches?(arguments[0]) }
55
- end
44
+ def dir
45
+ ENV['TRUNK_HOME'] || File.join(Dir.home, '.trunk')
56
46
  end
57
47
 
58
- def run(arguments)
59
- parser.banner = "Usage: trunk [options]"
60
- parser.on("-v", "--[no-]verbose", "run verbosely") do |v|
61
- options[:verbose] = v
62
- end
63
- parser.on("--version", "show version") do |v|
64
- puts Trunk::VERSION
65
- end
66
- parser.on_tail("-h", "--help", "print help") do
67
- puts parser
68
- end
69
- parser.parse!(arguments)
48
+ def private_key
49
+ OpenSSL::PKey::RSA.new(IO.read(private_key_path), passphrase)
70
50
  end
71
51
 
72
- def self.start(arguments)
73
- cli = new
74
- cli.command_for(arguments).run(arguments)
52
+ def passphrase
53
+ ENV['TRUNK_PASSPHRASE'] || ask("passphrase:", echo: false)
75
54
  end
76
55
  end
77
56
  end
@@ -0,0 +1,13 @@
1
+ module Trunk
2
+ module Serializers
3
+ class Base64
4
+ def serialize(value)
5
+ ::Base64.strict_encode64(value)
6
+ end
7
+
8
+ def deserialize(value)
9
+ ::Base64.decode64(value)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,27 @@
1
+ module Trunk
2
+ module Serializers
3
+ class Composite
4
+ def initialize(serializers = [])
5
+ @serializers = serializers
6
+ end
7
+
8
+ def add(serializer)
9
+ @serializers.push(serializer)
10
+ end
11
+
12
+ def serialize(value)
13
+ @serializers.each do |x|
14
+ value = x.serialize(value)
15
+ end
16
+ value
17
+ end
18
+
19
+ def deserialize(value)
20
+ @serializers.reverse.each do |x|
21
+ value = x.deserialize(value)
22
+ end
23
+ value
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,17 @@
1
+ module Trunk
2
+ module Serializers
3
+ class Crypto
4
+ def initialize(private_key)
5
+ @private_key = private_key
6
+ end
7
+
8
+ def serialize(plain_text)
9
+ @private_key.public_encrypt(plain_text)
10
+ end
11
+
12
+ def deserialize(cipher_text)
13
+ @private_key.private_decrypt(cipher_text)
14
+ end
15
+ end
16
+ end
17
+ end
data/lib/trunk/storage.rb CHANGED
@@ -1,67 +1,7 @@
1
1
  module Trunk
2
- class CompositeSerializer
3
- def initialize(serializers = [])
4
- @serializers = serializers
5
- end
6
-
7
- def add(serializer)
8
- @serializers.push(serializer)
9
- end
10
-
11
- def serialize(value)
12
- @serializers.each do |x|
13
- value = x.serialize(value)
14
- end
15
- value
16
- end
17
-
18
- def deserialize(value)
19
- puts "deserialize"
20
- @serializers.reverse.each do |x|
21
- puts x.class
22
- value = x.deserialize(value)
23
- end
24
- value
25
- end
26
- end
27
-
28
- class Base64Serializer
29
- def serialize(value)
30
- Base64.strict_encode64(value)
31
- end
32
-
33
- def deserialize(value)
34
- Base64.decode64(value)
35
- end
36
- end
37
-
38
- class SymmetricCrypto
39
- attr_reader :private_key, :algorithm
40
-
41
- def initialize(private_key, algorithm: 'AES-256-CBC')
42
- @private_key = private_key
43
- @algorithm = algorithm
44
- end
45
-
46
- def serialize(plain_text)
47
- cipher = OpenSSL::Cipher.new(algorithm)
48
- cipher.encrypt
49
- cipher.key = private_key
50
- cipher.random_iv + cipher.update(plain_text) + cipher.final
51
- end
52
-
53
- def deserialize(cipher_text)
54
- cipher = OpenSSL::Cipher.new(algorithm)
55
- cipher.decrypt
56
- iv = cipher_text[0..cipher.iv_len - 1]
57
- data = cipher_text[cipher.iv_len..-1]
58
- cipher.key = private_key
59
- cipher.iv = iv
60
- cipher.update(data) + cipher.final
61
- end
62
- end
63
-
64
2
  class Storage
3
+ attr_reader :hash
4
+
65
5
  def initialize(hash, serializer)
66
6
  @hash = hash
67
7
  @serializer = serializer
data/lib/trunk/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Trunk
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
@@ -0,0 +1,39 @@
1
+ module Trunk
2
+ class YAMLStorage
3
+ attr_reader :private_key, :absolute_path
4
+
5
+ def initialize(absolute_path, private_key)
6
+ @absolute_path = absolute_path
7
+ @private_key = private_key
8
+ end
9
+
10
+ def fetch(*args)
11
+ transaction do |storage|
12
+ storage.fetch(*args)
13
+ end
14
+ end
15
+
16
+ def store(*args)
17
+ transaction do |storage|
18
+ storage.store(*args)
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def transaction
25
+ hash = YAML.load(IO.read(absolute_path)) || {}
26
+ storage = Storage.new(hash, serializer)
27
+ yield storage
28
+ ensure
29
+ IO.write(absolute_path, YAML.dump(hash))
30
+ end
31
+
32
+ def serializer
33
+ serializer = Trunk::Serializers::Composite.new
34
+ serializer.add(Trunk::Serializers::Crypto.new(private_key))
35
+ serializer.add(Trunk::Serializers::Base64.new)
36
+ serializer
37
+ end
38
+ end
39
+ end
data/trunk.gemspec CHANGED
@@ -6,8 +6,8 @@ require "trunk/version"
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "trunk"
8
8
  spec.version = Trunk::VERSION
9
- spec.authors = ["mokha"]
10
- spec.email = ["mokha@cisco.com"]
9
+ spec.authors = ["mo"]
10
+ spec.email = ["mo@mokhan.ca"]
11
11
 
12
12
  spec.summary = %q{A safe place to put things.}
13
13
  spec.description = %q{A safe place to put things.}
@@ -21,6 +21,7 @@ Gem::Specification.new do |spec|
21
21
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
22
  spec.require_paths = ["lib"]
23
23
 
24
+ spec.add_dependency "thor", "~> 0.20"
24
25
  spec.add_development_dependency "bundler", "~> 1.16"
25
26
  spec.add_development_dependency "rake", "~> 10.0"
26
27
  spec.add_development_dependency "rspec", "~> 3.0"
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trunk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
- - mokha
7
+ - mo
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-06-09 00:00:00.000000000 Z
11
+ date: 2018-06-14 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.20'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.20'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -54,7 +68,7 @@ dependencies:
54
68
  version: '3.0'
55
69
  description: A safe place to put things.
56
70
  email:
57
- - mokha@cisco.com
71
+ - mo@mokhan.ca
58
72
  executables:
59
73
  - trunk
60
74
  extensions: []
@@ -72,8 +86,12 @@ files:
72
86
  - exe/trunk
73
87
  - lib/trunk.rb
74
88
  - lib/trunk/cli.rb
89
+ - lib/trunk/serializers/base_64.rb
90
+ - lib/trunk/serializers/composite.rb
91
+ - lib/trunk/serializers/crypto.rb
75
92
  - lib/trunk/storage.rb
76
93
  - lib/trunk/version.rb
94
+ - lib/trunk/yaml_storage.rb
77
95
  - trunk.gemspec
78
96
  homepage: https://www.mokhan.ca
79
97
  licenses: