keyrack 0.3.0.pre → 0.3.0
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 +7 -0
- data/.gitignore +17 -0
- data/Gemfile +8 -15
- data/Guardfile +6 -0
- data/LICENSE.txt +4 -2
- data/Rakefile +2 -56
- data/keyrack.gemspec +22 -104
- data/lib/keyrack.rb +9 -1
- data/lib/keyrack/database.rb +64 -98
- data/lib/keyrack/event.rb +13 -0
- data/lib/keyrack/exceptions.rb +4 -0
- data/lib/keyrack/group.rb +225 -0
- data/lib/keyrack/migrator.rb +45 -0
- data/lib/keyrack/runner.rb +98 -44
- data/lib/keyrack/site.rb +92 -0
- data/lib/keyrack/ui/console.rb +234 -95
- data/lib/keyrack/utils.rb +0 -18
- data/lib/keyrack/version.rb +3 -0
- data/test/fixtures/database-3.dat +0 -0
- data/test/helper.rb +11 -1
- data/test/integration/test_interactive_console.rb +139 -0
- data/test/unit/store/test_filesystem.rb +21 -0
- data/test/unit/store/test_ssh.rb +32 -0
- data/test/unit/test_database.rb +201 -0
- data/test/unit/test_event.rb +41 -0
- data/test/unit/test_group.rb +703 -0
- data/test/unit/test_migrator.rb +105 -0
- data/test/unit/test_runner.rb +407 -0
- data/test/unit/test_site.rb +181 -0
- data/test/unit/test_store.rb +13 -0
- data/test/unit/test_utils.rb +8 -0
- data/test/unit/ui/test_console.rb +495 -0
- metadata +98 -94
- data/Gemfile.lock +0 -45
- data/TODO +0 -4
- data/VERSION +0 -1
- data/features/console.feature +0 -103
- data/features/step_definitions/keyrack_steps.rb +0 -61
- data/features/support/env.rb +0 -16
- data/test/fixtures/aes +0 -0
- data/test/fixtures/config.yml +0 -4
- data/test/fixtures/id_rsa +0 -54
- data/test/keyrack/store/test_filesystem.rb +0 -25
- data/test/keyrack/store/test_ssh.rb +0 -36
- data/test/keyrack/test_database.rb +0 -111
- data/test/keyrack/test_runner.rb +0 -111
- data/test/keyrack/test_store.rb +0 -15
- data/test/keyrack/test_utils.rb +0 -41
- data/test/keyrack/ui/test_console.rb +0 -308
@@ -1,61 +0,0 @@
|
|
1
|
-
Before do
|
2
|
-
@fake_home = Dir::Tmpname.create('keyrack') { }
|
3
|
-
Dir.mkdir(@fake_home)
|
4
|
-
@old_home = ENV['HOME']
|
5
|
-
ENV['HOME'] = @fake_home
|
6
|
-
end
|
7
|
-
|
8
|
-
After do
|
9
|
-
ENV['HOME'] = @old_home
|
10
|
-
FileUtils.rm_rf(@fake_home)
|
11
|
-
end
|
12
|
-
|
13
|
-
When /I run keyrack interactively/ do
|
14
|
-
@out, @in, @pid = PTY.spawn("bundle exec ruby -Ilib bin/keyrack")
|
15
|
-
end
|
16
|
-
|
17
|
-
Then /the output should contain "([^"]+)"/ do |expected|
|
18
|
-
if @slept
|
19
|
-
@slept = false
|
20
|
-
else
|
21
|
-
sleep 1
|
22
|
-
end
|
23
|
-
@output = @out.read_nonblock(255)
|
24
|
-
assert @output.include?(expected), "Output: #{@output.inspect}"
|
25
|
-
end
|
26
|
-
|
27
|
-
Then %r{the output should match /([^/]+)/} do |expected|
|
28
|
-
# This won't work for escaped backslashes
|
29
|
-
if @slept
|
30
|
-
@slept = false
|
31
|
-
else
|
32
|
-
sleep 1
|
33
|
-
end
|
34
|
-
@output = @out.read_nonblock(255)
|
35
|
-
assert @output.match(Regexp.new(expected))
|
36
|
-
end
|
37
|
-
|
38
|
-
Then /the output should also contain "([^"]+)"/ do |expected|
|
39
|
-
assert @output.include?(expected)
|
40
|
-
end
|
41
|
-
|
42
|
-
When /I type "([^"]+)"/ do |text|
|
43
|
-
@in.puts(text)
|
44
|
-
end
|
45
|
-
|
46
|
-
When /I wait a few seconds/ do
|
47
|
-
sleep 5
|
48
|
-
@slept = true
|
49
|
-
end
|
50
|
-
|
51
|
-
Then /my clipboard should contain "([^"]+)"/ do |expected|
|
52
|
-
sleep 1
|
53
|
-
result = %x{xclip -selection clipboard -o}.chomp
|
54
|
-
assert_equal expected, result
|
55
|
-
end
|
56
|
-
|
57
|
-
Then /my clipboard should match "([^"]+)"/ do |expected|
|
58
|
-
sleep 1
|
59
|
-
result = %x{xclip -selection clipboard -o}.chomp
|
60
|
-
assert_match Regexp.new(expected), result
|
61
|
-
end
|
data/features/support/env.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'bundler'
|
3
|
-
begin
|
4
|
-
Bundler.setup(:default, :development)
|
5
|
-
rescue Bundler::BundlerError => e
|
6
|
-
$stderr.puts e.message
|
7
|
-
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
-
exit e.status_code
|
9
|
-
end
|
10
|
-
require 'tempfile'
|
11
|
-
require 'fileutils'
|
12
|
-
require 'pty'
|
13
|
-
require 'yaml'
|
14
|
-
require 'test/unit/assertions'
|
15
|
-
|
16
|
-
World(Test::Unit::Assertions)
|
data/test/fixtures/aes
DELETED
Binary file
|
data/test/fixtures/config.yml
DELETED
data/test/fixtures/id_rsa
DELETED
@@ -1,54 +0,0 @@
|
|
1
|
-
-----BEGIN RSA PRIVATE KEY-----
|
2
|
-
Proc-Type: 4,ENCRYPTED
|
3
|
-
DEK-Info: DES-EDE3-CBC,030F0E3D8BD7BF1A
|
4
|
-
|
5
|
-
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
-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
-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
-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
-
3+gN9FnbWH3LNTOShzl4l4v2aBfxXgg5bHPnKkJiUNRDlY6ozyQYfxxoOs4uL8mI
|
10
|
-
WnfmVGezxkD3YWHB+xwevLaIjChowSNP/q7sSHVOD/bVadmhd30I7CnhFITKi0Wp
|
11
|
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-
OXV6MJGQYkVkm5xf3tmvuQYQNV3NK/nQpDixhMJye19Kjr7jelRpcr+Y5VXelRP5
|
25
|
-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
-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
-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
-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
-
CS0g15bqEmCyFxvbBkR8aUZ6c5fHvNngvxYbkGVLyHpgIHmszGj1+gz/8DlEXldM
|
30
|
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
-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
|
54
|
-
-----END RSA PRIVATE KEY-----
|
@@ -1,25 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
module Keyrack
|
4
|
-
module Store
|
5
|
-
class TestFilesystem < Test::Unit::TestCase
|
6
|
-
def test_read
|
7
|
-
path = fixture_path('foo.txt')
|
8
|
-
store = Filesystem.new('path' => path)
|
9
|
-
assert_equal File.read(path), store.read
|
10
|
-
end
|
11
|
-
|
12
|
-
def test_write
|
13
|
-
path = get_tmpname
|
14
|
-
store = Filesystem.new('path' => path)
|
15
|
-
store.write("foobar")
|
16
|
-
assert_equal "foobar", File.read(path)
|
17
|
-
end
|
18
|
-
|
19
|
-
def test_read_returns_nil_for_non_existant_file
|
20
|
-
store = Filesystem.new('path' => 'blargityblargh')
|
21
|
-
assert_nil store.read
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
@@ -1,36 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
module Keyrack
|
4
|
-
module Store
|
5
|
-
class TestSSH < Test::Unit::TestCase
|
6
|
-
def test_read
|
7
|
-
store = SSH.new('host' => 'example.com', 'user' => 'dude', 'port' => 22, 'path' => 'foo.txt')
|
8
|
-
scp = mock('scp session')
|
9
|
-
scp.expects(:download!).with("foo.txt").returns("foo")
|
10
|
-
session = mock('ssh session', :scp => scp)
|
11
|
-
Net::SSH.expects(:start).with('example.com', 'dude', :port => 22).yields(session)
|
12
|
-
assert_equal "foo", store.read
|
13
|
-
end
|
14
|
-
|
15
|
-
def test_write
|
16
|
-
store = SSH.new('host' => 'example.com', 'user' => 'dude', 'path' => 'foo.txt')
|
17
|
-
scp = mock('scp session')
|
18
|
-
session = mock('ssh session', :scp => scp)
|
19
|
-
Net::SSH.expects(:start).with('example.com', 'dude', :port => 22).yields(session)
|
20
|
-
scp.expects(:upload!).with do |local, remote|
|
21
|
-
local.is_a?(StringIO) && local.read == "foo" && remote == "foo.txt"
|
22
|
-
end
|
23
|
-
store.write("foo")
|
24
|
-
end
|
25
|
-
|
26
|
-
def test_read_returns_nil_for_non_existant_file
|
27
|
-
store = SSH.new('host' => 'example.com', 'user' => 'dude', 'port' => 22, 'path' => 'foo.txt')
|
28
|
-
scp = mock('scp session')
|
29
|
-
scp.expects(:download!).with("foo.txt").raises(Net::SCP::Error)
|
30
|
-
session = mock('ssh session', :scp => scp)
|
31
|
-
Net::SSH.expects(:start).with('example.com', 'dude', :port => 22).yields(session)
|
32
|
-
assert_nil store.read
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
@@ -1,111 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
module Keyrack
|
4
|
-
class TestDatabase < Test::Unit::TestCase
|
5
|
-
def setup
|
6
|
-
@key = "abcdefgh" * 32
|
7
|
-
@iv = @key.reverse
|
8
|
-
|
9
|
-
@path = get_tmpname
|
10
|
-
@store = Store['filesystem'].new('path' => @path)
|
11
|
-
|
12
|
-
@database = Keyrack::Database.new(@key, @iv, @store)
|
13
|
-
@database.add('Twitter', 'username', 'password')
|
14
|
-
@database.save
|
15
|
-
end
|
16
|
-
|
17
|
-
def test_encrypts_database
|
18
|
-
encrypted_data = File.read(@path)
|
19
|
-
cipher = OpenSSL::Cipher::Cipher.new("AES-128-CBC")
|
20
|
-
cipher.decrypt; cipher.key = @key; cipher.iv = @iv
|
21
|
-
marshalled_data = cipher.update(encrypted_data) + cipher.final
|
22
|
-
data = Marshal.load(marshalled_data)
|
23
|
-
assert_equal({'Twitter'=>{:username=>'username',:password=>'password'}}, data)
|
24
|
-
end
|
25
|
-
|
26
|
-
def test_reading_existing_database
|
27
|
-
database = Keyrack::Database.new(@key, @iv, @store)
|
28
|
-
expected = {:username => 'username', :password => 'password'}
|
29
|
-
assert_equal(expected, database.get('Twitter', 'username'))
|
30
|
-
end
|
31
|
-
|
32
|
-
def test_sites
|
33
|
-
@database.add('Blargh', 'dudeguy', 'secret', :group => "Junk")
|
34
|
-
assert_equal(%w{Twitter}, @database.sites)
|
35
|
-
assert_equal(%w{Blargh}, @database.sites(:group => "Junk"))
|
36
|
-
assert_equal([], @database.sites(:group => "New group"))
|
37
|
-
end
|
38
|
-
|
39
|
-
def test_groups
|
40
|
-
assert_equal [], @database.groups
|
41
|
-
@database.add('Blargh', 'dudeguy', 'secret', :group => "Junk")
|
42
|
-
assert_equal %w{Junk}, @database.groups
|
43
|
-
end
|
44
|
-
|
45
|
-
def test_dirty
|
46
|
-
assert !@database.dirty?
|
47
|
-
@database.add('Foo', 'bar', 'baz')
|
48
|
-
assert @database.dirty?
|
49
|
-
end
|
50
|
-
|
51
|
-
def test_large_number_of_entries
|
52
|
-
site = "abcdefg"; user = "1234567"; pass = "zyxwvut" * 2
|
53
|
-
500.times do |i|
|
54
|
-
@database.add(site, user, pass)
|
55
|
-
site.next!; user.next!; pass.next!
|
56
|
-
end
|
57
|
-
@database.save
|
58
|
-
assert_equal 501, @database.sites.length
|
59
|
-
end
|
60
|
-
|
61
|
-
def test_add_with_top_level_group
|
62
|
-
@database.add('Twitter', 'dudeguy', 'secret', :group => "Social")
|
63
|
-
expected = {:username => 'dudeguy', :password => 'secret'}
|
64
|
-
assert_equal expected, @database.get('Twitter', 'dudeguy', :group => "Social")
|
65
|
-
end
|
66
|
-
|
67
|
-
def test_delete
|
68
|
-
@database.delete('Twitter', 'username')
|
69
|
-
assert_equal [], @database.sites
|
70
|
-
assert @database.dirty?
|
71
|
-
end
|
72
|
-
|
73
|
-
def test_delete_non_existant_entry
|
74
|
-
@database.delete('Twitter', 'foobar')
|
75
|
-
assert_equal ['Twitter'], @database.sites
|
76
|
-
assert !@database.dirty?
|
77
|
-
end
|
78
|
-
|
79
|
-
def test_delete_group_entry
|
80
|
-
@database.add('Facebook', 'dudeguy', 'secret', :group => "Social")
|
81
|
-
@database.delete('Facebook', 'dudeguy', :group => 'Social')
|
82
|
-
assert_equal [], @database.sites(:group => 'Social')
|
83
|
-
assert_equal ['Twitter'], @database.sites
|
84
|
-
end
|
85
|
-
|
86
|
-
def test_multiple_entries_with_the_same_site
|
87
|
-
@database.add('Facebook', 'dudeguy', 'secret')
|
88
|
-
@database.add('Facebook', 'foobar', 'secret')
|
89
|
-
|
90
|
-
expected_1 = {:username => 'dudeguy', :password => 'secret'}
|
91
|
-
assert_equal expected_1, @database.get('Facebook', 'dudeguy')
|
92
|
-
expected_2 = {:username => 'foobar', :password => 'secret'}
|
93
|
-
assert_equal expected_2, @database.get('Facebook', 'foobar')
|
94
|
-
assert_equal [expected_1, expected_2], @database.get('Facebook')
|
95
|
-
assert_equal ['Facebook', 'Twitter'], @database.sites
|
96
|
-
end
|
97
|
-
|
98
|
-
def test_get_missing_entry_by_site_and_username
|
99
|
-
@database.add('Facebook', 'dudeguy', 'secret')
|
100
|
-
assert_nil @database.get('Facebook', 'foobar')
|
101
|
-
end
|
102
|
-
|
103
|
-
def test_deleting_one_of_two_entries_with_the_same_site
|
104
|
-
@database.add('Facebook', 'dudeguy', 'secret')
|
105
|
-
@database.add('Facebook', 'foobar', 'secret')
|
106
|
-
@database.delete('Facebook', 'dudeguy')
|
107
|
-
assert_nil @database.get('Facebook', 'dudeguy')
|
108
|
-
assert_equal({:username => 'foobar', :password => 'secret'}, @database.get('Facebook', 'foobar'))
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
data/test/keyrack/test_runner.rb
DELETED
@@ -1,111 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
module Keyrack
|
4
|
-
class TestRunner < Test::Unit::TestCase
|
5
|
-
def setup
|
6
|
-
@console = stub('console', {
|
7
|
-
:get_password => 'secret',
|
8
|
-
:database= => nil, :menu => :quit,
|
9
|
-
:get_new_entry => {:site => "Foo", :username => "bar", :password => "baz"}
|
10
|
-
})
|
11
|
-
UI::Console.stubs(:new).returns(@console)
|
12
|
-
@database = stub('database', { :add => nil })
|
13
|
-
Database.stubs(:new).returns(@database)
|
14
|
-
end
|
15
|
-
|
16
|
-
def test_console
|
17
|
-
store_path = 'foo/bar/hey/buddy'
|
18
|
-
rsa_path = 'omg/rsa/path'
|
19
|
-
aes_path = 'hey/its/some/aes/stuff'
|
20
|
-
config = {
|
21
|
-
'store' => { 'type' => 'filesystem', 'path' => store_path },
|
22
|
-
'rsa' => rsa_path, 'aes' => aes_path
|
23
|
-
}
|
24
|
-
keyrack_dir = get_tmpname
|
25
|
-
Dir.mkdir(keyrack_dir)
|
26
|
-
File.open(File.join(keyrack_dir, "config"), 'w') { |f| f.print(config.to_yaml) }
|
27
|
-
|
28
|
-
UI::Console.expects(:new).returns(@console)
|
29
|
-
|
30
|
-
seq = sequence('ui sequence')
|
31
|
-
@console.expects(:get_password).returns('secret').in_sequence(seq)
|
32
|
-
rsa = mock("rsa key")
|
33
|
-
Utils.expects(:open_rsa_key).with(File.expand_path(rsa_path, keyrack_dir), 'secret').returns(rsa).in_sequence(seq)
|
34
|
-
aes = {'key' => '12345', 'iv' => '54321'}
|
35
|
-
Utils.expects(:open_aes_data).with(File.expand_path(aes_path, keyrack_dir), rsa).returns(aes).in_sequence(seq)
|
36
|
-
store = mock('filesystem store')
|
37
|
-
Store::Filesystem.expects(:new).with('path' => store_path).returns(store).in_sequence(seq)
|
38
|
-
Database.expects(:new).with('12345', '54321', store).returns(@database).in_sequence(seq)
|
39
|
-
@console.expects(:database=).with(@database).in_sequence(seq)
|
40
|
-
|
41
|
-
@console.expects(:menu).returns(:new).in_sequence(seq)
|
42
|
-
@console.expects(:get_new_entry).returns({:site => "Foo", :username => "bar", :password => "baz"}).in_sequence(seq)
|
43
|
-
@database.expects(:add).with("Foo", "bar", "baz", {})
|
44
|
-
@console.expects(:menu).returns(nil).in_sequence(seq)
|
45
|
-
@console.expects(:menu).returns(:save).in_sequence(seq)
|
46
|
-
@database.expects(:save).in_sequence(seq)
|
47
|
-
@console.expects(:menu).returns(:delete).in_sequence(seq)
|
48
|
-
@console.expects(:delete_entry).with({}).in_sequence(seq)
|
49
|
-
@console.expects(:menu).returns(:new_group).in_sequence(seq)
|
50
|
-
@console.expects(:get_new_group).returns(:group => 'Blah').in_sequence(seq)
|
51
|
-
@console.expects(:menu).with(:group => 'Blah').returns(:top).in_sequence(seq)
|
52
|
-
@console.expects(:menu).returns(:group => 'Huge').in_sequence(seq)
|
53
|
-
@console.expects(:menu).with(:group => 'Huge').returns(nil).in_sequence(seq)
|
54
|
-
@console.expects(:menu).with(:group => 'Huge').returns(:new).in_sequence(seq)
|
55
|
-
@console.expects(:get_new_entry).returns({:site => "Bar", :username => "bar", :password => "baz"}).in_sequence(seq)
|
56
|
-
@database.expects(:add).with("Bar", "bar", "baz", :group => 'Huge')
|
57
|
-
@console.expects(:menu).with(:group => "Huge").returns(:delete).in_sequence(seq)
|
58
|
-
@console.expects(:delete_entry).with(:group => 'Huge').in_sequence(seq)
|
59
|
-
@console.expects(:menu).with(:group => 'Huge').returns(:top).in_sequence(seq)
|
60
|
-
@console.expects(:menu).returns(:quit).in_sequence(seq)
|
61
|
-
|
62
|
-
runner = Runner.new(["-d", keyrack_dir])
|
63
|
-
end
|
64
|
-
|
65
|
-
def test_console_first_run
|
66
|
-
keyrack_dir = get_tmpname
|
67
|
-
seq = sequence('ui sequence')
|
68
|
-
|
69
|
-
@console.expects(:display_first_time_notice).in_sequence(seq)
|
70
|
-
|
71
|
-
# RSA generation
|
72
|
-
rsa_path = 'id_rsa'
|
73
|
-
@console.expects(:rsa_setup).returns('password' => 'secret', 'path' => rsa_path).in_sequence(seq)
|
74
|
-
rsa = mock('rsa key')
|
75
|
-
Utils.expects(:generate_rsa_key).with('secret').returns([rsa, 'private key']).in_sequence(seq)
|
76
|
-
|
77
|
-
# AES generation
|
78
|
-
Utils.expects(:generate_aes_key).twice.returns('foobar', 'barfoo').in_sequence(seq)
|
79
|
-
dump = Marshal.dump('key' => 'foobar', 'iv' => 'barfoo')
|
80
|
-
rsa.expects(:public_encrypt).with(dump).returns("encrypted dump")
|
81
|
-
|
82
|
-
# Store setup
|
83
|
-
@console.expects(:store_setup).returns('type' => 'filesystem', 'path' => 'database').in_sequence(seq)
|
84
|
-
store = mock('filesystem store')
|
85
|
-
Store::Filesystem.expects(:new).with('path' => File.join(keyrack_dir, 'database')).returns(store).in_sequence(seq)
|
86
|
-
|
87
|
-
Database.expects(:new).with('foobar', 'barfoo', store).returns(@database).in_sequence(seq)
|
88
|
-
@console.expects(:database=).with(@database).in_sequence(seq)
|
89
|
-
@console.expects(:menu).returns(:quit).in_sequence(seq)
|
90
|
-
|
91
|
-
runner = Runner.new(["-d", keyrack_dir])
|
92
|
-
|
93
|
-
assert Dir.exist?(keyrack_dir)
|
94
|
-
expected_rsa_file = File.expand_path(rsa_path, keyrack_dir)
|
95
|
-
assert File.exist?(expected_rsa_file)
|
96
|
-
assert_equal 'private key', File.read(expected_rsa_file)
|
97
|
-
|
98
|
-
expected_aes_file = File.expand_path('aes', keyrack_dir)
|
99
|
-
assert File.exist?(expected_aes_file)
|
100
|
-
assert_equal 'encrypted dump', File.read(expected_aes_file)
|
101
|
-
|
102
|
-
expected_config_file = File.expand_path('config', keyrack_dir)
|
103
|
-
assert File.exist?(expected_config_file)
|
104
|
-
expected_config = {
|
105
|
-
'rsa' => expected_rsa_file, 'aes' => expected_aes_file,
|
106
|
-
'store' => { 'type' => 'filesystem', 'path' => File.join(keyrack_dir, 'database') }
|
107
|
-
}
|
108
|
-
assert_equal expected_config, YAML.load_file(expected_config_file)
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
data/test/keyrack/test_store.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
module Keyrack
|
4
|
-
class TestStore < Test::Unit::TestCase
|
5
|
-
def test_get_filesystem
|
6
|
-
assert_equal Store::Filesystem, Store[:filesystem]
|
7
|
-
assert_equal Store::Filesystem, Store['filesystem']
|
8
|
-
end
|
9
|
-
|
10
|
-
def test_get_ssh
|
11
|
-
assert_equal Store::SSH, Store[:ssh]
|
12
|
-
assert_equal Store::SSH, Store['ssh']
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
data/test/keyrack/test_utils.rb
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
module Keyrack
|
4
|
-
class TestUtils < Test::Unit::TestCase
|
5
|
-
def test_generate_password
|
6
|
-
result = Utils.generate_password
|
7
|
-
assert_match /^[!-~]{8}$/, result
|
8
|
-
end
|
9
|
-
|
10
|
-
def test_generate_rsa_key
|
11
|
-
rsa = mock('rsa')
|
12
|
-
OpenSSL::PKey::RSA.expects(:new).with(4096).returns(rsa)
|
13
|
-
cipher = mock('cipher')
|
14
|
-
OpenSSL::Cipher::Cipher.expects(:new).with('des3').returns(cipher)
|
15
|
-
rsa.expects(:to_pem).with(cipher, 'secret').returns('private key')
|
16
|
-
|
17
|
-
assert_equal([rsa, 'private key'], Utils.generate_rsa_key('secret'))
|
18
|
-
end
|
19
|
-
|
20
|
-
def test_generate_aes_key
|
21
|
-
SecureRandom.expects(:base64).with(128).returns("x" * 172)
|
22
|
-
result = Utils.generate_aes_key
|
23
|
-
assert_equal 128, result.length
|
24
|
-
end
|
25
|
-
|
26
|
-
def test_open_rsa_key
|
27
|
-
rsa_path = fixture_path('id_rsa')
|
28
|
-
rsa = mock('rsa')
|
29
|
-
OpenSSL::PKey::RSA.expects(:new).with(File.read(rsa_path), 'secret').returns(rsa)
|
30
|
-
assert_equal(rsa, Utils.open_rsa_key(rsa_path, 'secret'))
|
31
|
-
end
|
32
|
-
|
33
|
-
def test_open_aes_data
|
34
|
-
aes_path = fixture_path('aes')
|
35
|
-
aes = {'key' => '12345', 'iv' => '54321'}
|
36
|
-
rsa = mock('rsa')
|
37
|
-
rsa.expects(:private_decrypt).with(File.read(aes_path)).returns(Marshal.dump(aes))
|
38
|
-
assert_equal(aes, Utils.open_aes_data(aes_path, rsa))
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|