keyrack 0.3.0.pre → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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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
-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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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
-
ZhIVRdMIYr70BUhpTH3gqBLQlNX0D6DItCNdI+cr9p2BUqM87xTeQM84HfKOyZZO
|
20
|
-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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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
-
nCPZ8/ks84rXjAxWNcLHSCdVWzczHDKz22VJFa+AIrqMxz77r+aEAzMvxHNAbs5v
|
40
|
-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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
|