keyring 0.1.0 → 0.2.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.
@@ -0,0 +1,79 @@
1
+ # keyring: System keyring abstraction library
2
+ # License: MIT (http://www.opensource.org/licenses/mit-license.php)
3
+
4
+ require 'slop'
5
+ require 'keyring'
6
+
7
+ class Keyring::CLI
8
+ def initialize(options={})
9
+ @options = options
10
+
11
+ @method = @arg = nil
12
+ @opts = Slop.parse(:help => true) do
13
+ banner 'Usage: keyring get|set|delete <service> <username> [password (for set)]'
14
+
15
+ on :v, :version, 'Print the version' do
16
+ puts Keyring::VERSION
17
+ exit
18
+ end
19
+
20
+ command 'set' do
21
+ # FIXME: option to prompt for password
22
+ run do |opts, args|
23
+ @method = :set
24
+ @arg = args
25
+ end
26
+ end
27
+ command 'get' do
28
+ run do |opts, args|
29
+ @method = :get
30
+ @arg = args
31
+ end
32
+ end
33
+ command 'delete' do
34
+ run do |opts, args|
35
+ @method = :delete
36
+ @arg = args
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ def main
43
+ if @method && respond_to?(@method)
44
+ send(@method, @arg)
45
+ else
46
+ puts @opts
47
+ exit 1
48
+ end
49
+ end
50
+
51
+ def set(args)
52
+ ensure_arg_presence(args, 3)
53
+ keyring = Keyring.new
54
+ keyring.set_password(args[0], args[1], args[2])
55
+ end
56
+ def get(args)
57
+ ensure_arg_presence(args, 2)
58
+ keyring = Keyring.new
59
+ puts keyring.get_password(args[0], args[1])
60
+ end
61
+ def delete(args)
62
+ ensure_arg_presence(args, 2)
63
+ keyring = Keyring.new
64
+ keyring.delete_password(args[0], args[1])
65
+ end
66
+
67
+ def ensure_arg_presence(args, count)
68
+ 0.upto(count-1) do |i|
69
+ if !args[i] || args[i].empty?
70
+ if !@options[:testing]
71
+ puts @opts
72
+ exit 1
73
+ else
74
+ raise ArgumentError
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,6 @@
1
+ # keyring: System keyring abstraction library
2
+ # License: MIT (http://www.opensource.org/licenses/mit-license.php)
3
+
4
+ class Keyring
5
+ VERSION = "0.2.0"
6
+ end
@@ -0,0 +1,7 @@
1
+ # keyring: System keyring abstraction library
2
+ # License: MIT (http://www.opensource.org/licenses/mit-license.php)
3
+
4
+ module KeyringTestConstants
5
+ # Fake commands used in place of system commands
6
+ TESTCMDDIR = File.expand_path('testcmds', File.dirname(__FILE__))
7
+ end
@@ -0,0 +1,38 @@
1
+ # keyring: System keyring abstraction library
2
+ # License: MIT (http://www.opensource.org/licenses/mit-license.php)
3
+
4
+ require 'test/unit'
5
+ require 'keyring'
6
+
7
+ class KeyringBackendTests < Test::Unit::TestCase
8
+ def setup
9
+ @backend = Keyring::Backend.new
10
+ end
11
+
12
+ class Keyring::Backend::Test < Keyring::Backend; end
13
+ def test_register_implementation
14
+ Keyring::Backend.register_implementation(Keyring::Backend::Test)
15
+ assert Keyring::Backend.implementations.include?(Keyring::Backend::Test)
16
+ Keyring::Backend.implementations.delete(Keyring::Backend::Test)
17
+ end
18
+ def test_create
19
+ # This should be a bit more thorough
20
+ assert_kind_of Keyring::Backend, Keyring::Backend.create
21
+ end
22
+
23
+ def test_supported
24
+ refute @backend.supported?
25
+ end
26
+ def test_priority
27
+ assert_equal 0, @backend.priority
28
+ end
29
+ def test_set_password
30
+ assert_raises(NotImplementedError) {@backend.set_password('service', 'username', 'password')}
31
+ end
32
+ def test_get_password
33
+ assert_raises(NotImplementedError) {@backend.get_password('service', 'username')}
34
+ end
35
+ def test_delete_password
36
+ assert_raises(NotImplementedError) {@backend.delete_password('service', 'username')}
37
+ end
38
+ end
@@ -0,0 +1,73 @@
1
+ # keyring: System keyring abstraction library
2
+ # License: MIT (http://www.opensource.org/licenses/mit-license.php)
3
+
4
+ require File.expand_path('keyring_tests', File.dirname(__FILE__))
5
+ require 'test/unit'
6
+ require 'mocha/setup'
7
+ require 'keyring'
8
+
9
+ class KeyringBackendMacosxKeychainTests < Test::Unit::TestCase
10
+ include KeyringTestConstants
11
+
12
+ def setup
13
+ @backend = Keyring::Backend::MacosxKeychain.new
14
+ end
15
+
16
+ def test_supported
17
+ @backend.security = File.join(TESTCMDDIR, 'macosx/security-wronghelp')
18
+ refute @backend.supported?
19
+ @backend.security = File.join(TESTCMDDIR, 'macosx/bogus')
20
+ refute @backend.supported?
21
+ @backend.security = File.join(TESTCMDDIR, 'macosx/security-righthelp')
22
+ assert @backend.supported?
23
+ end
24
+ def test_priority
25
+ assert_equal 1, @backend.priority
26
+ end
27
+
28
+ def test_security_command
29
+ assert_equal 'add-generic-password', @backend.security_command('add')
30
+ assert_equal 'find-generic-password', @backend.security_command('find')
31
+ assert_equal 'delete-generic-password', @backend.security_command('delete')
32
+ end
33
+
34
+ def test_set_password
35
+ @backend.expects(:system).with(
36
+ '/usr/bin/security', 'add-generic-password', '-s', 'service', '-a', 'username', '-w', 'password', '-U')
37
+ # We need to set $? to make up for the fact that system was not actually run
38
+ # FIXME: surely there's a better way?
39
+ `true`
40
+ @backend.set_password('service', 'username', 'password')
41
+ end
42
+
43
+ def test_get_password
44
+ @backend.security = File.join(TESTCMDDIR, 'macosx/security-find')
45
+ assert_equal 'password', @backend.get_password('service', 'username')
46
+ end
47
+ def test_get_password_hex
48
+ @backend.security = File.join(TESTCMDDIR, 'macosx/security-findhex')
49
+ assert_equal "\0100\0101\0100\0101\0100\0101\0100\0101", @backend.get_password('service', 'hexuser')
50
+ end
51
+ def test_get_password_empty
52
+ @backend.security = File.join(TESTCMDDIR, 'macosx/security-findempty')
53
+ assert_equal '', @backend.get_password('service', 'emptyuser')
54
+ end
55
+ def test_get_password_notfound
56
+ @backend.security = File.join(TESTCMDDIR, 'macosx/security-notfound')
57
+ assert_nil @backend.get_password('bogus', 'bogus')
58
+ end
59
+
60
+ def test_delete_password_options
61
+ Open3.expects(:popen3).with(
62
+ '/usr/bin/security', 'delete-generic-password', '-s', 'service', '-a', 'username')
63
+ @backend.delete_password('service', 'username')
64
+ end
65
+ def test_delete_password_output
66
+ @backend.security = File.join(TESTCMDDIR, 'macosx/security-delete')
67
+ assert @backend.delete_password('service', 'gooduser')
68
+ end
69
+ def test_delete_password_errors
70
+ @backend.security = File.join(TESTCMDDIR, 'macosx/security-notfound')
71
+ refute @backend.delete_password('bogus', 'bogus')
72
+ end
73
+ end
@@ -0,0 +1,43 @@
1
+ # keyring: System keyring abstraction library
2
+ # License: MIT (http://www.opensource.org/licenses/mit-license.php)
3
+
4
+ require 'test/unit'
5
+ require 'keyring'
6
+
7
+ class KeyringBackendMemoryTests < Test::Unit::TestCase
8
+ def setup
9
+ @backend = Keyring::Backend::Memory.new
10
+ end
11
+
12
+ def test_supported
13
+ assert @backend.supported?
14
+ end
15
+ def test_priority
16
+ assert_equal 0.1, @backend.priority
17
+ end
18
+
19
+ def test_set_password
20
+ @backend.set_password('service', 'username', 'password')
21
+ assert_equal 'password', @backend.instance_variable_get('@keyring')['service']['username']
22
+ end
23
+ def test_get_password
24
+ @backend.set_password('service', 'username', 'password')
25
+ assert_equal 'password', @backend.get_password('service', 'username')
26
+
27
+ # Ensure that get_password behaves properly when asked for things that
28
+ # have not been set
29
+ assert_nil @backend.get_password('service', 'bogus')
30
+ assert_nil @backend.get_password('bogus', 'bogus')
31
+ end
32
+ def test_delete_password
33
+ @backend.set_password('service', 'username', 'password')
34
+ @backend.delete_password('service', 'username')
35
+ assert_nil @backend.instance_variable_get('@keyring')['service']['username']
36
+ assert_nil @backend.get_password('service', 'username')
37
+
38
+ # Ensure that delete_password behaves properly when asked to delete
39
+ # things that have not been set
40
+ @backend.delete_password('service', 'bogus')
41
+ @backend.delete_password('bogus', 'bogus')
42
+ end
43
+ end
@@ -0,0 +1,58 @@
1
+ # keyring: System keyring abstraction library
2
+ # License: MIT (http://www.opensource.org/licenses/mit-license.php)
3
+
4
+ require 'keyring/cli'
5
+ require 'test/unit'
6
+ require 'mocha/setup'
7
+
8
+ class KeyringCLITests < Test::Unit::TestCase
9
+ def setup
10
+ @cli = Keyring::CLI.new(testing: true)
11
+ end
12
+
13
+ EXE = File.expand_path('../bin/keyring', File.dirname(__FILE__))
14
+ def test_help_option
15
+ assert_match /\AUsage:/, `#{EXE} --help`
16
+ assert $?.success?
17
+ end
18
+ def test_version_option
19
+ assert_equal "#{Keyring::VERSION}\n", `#{EXE} --version`
20
+ assert $?.success?
21
+ end
22
+
23
+ def test_set
24
+ assert_raise(ArgumentError) {@cli.set([])}
25
+ assert_raise(ArgumentError) {@cli.set(['service'])}
26
+ assert_raise(ArgumentError) {@cli.set(['service', 'username'])}
27
+
28
+ Keyring.any_instance.expects(:set_password).with('service', 'username', 'password')
29
+ @cli.set(['service', 'username', 'password'])
30
+ end
31
+ def test_get
32
+ assert_raise(ArgumentError) {@cli.get([])}
33
+ assert_raise(ArgumentError) {@cli.get(['service'])}
34
+
35
+ Keyring.any_instance.expects(:get_password).with('service', 'username').returns('password')
36
+ $stdout = output = StringIO.new
37
+ @cli.get(['service', 'username'])
38
+ $stdout = STDOUT
39
+ assert_equal "password\n", output.string
40
+ end
41
+ def test_delete
42
+ assert_raise(ArgumentError) {@cli.delete([])}
43
+ assert_raise(ArgumentError) {@cli.delete(['service'])}
44
+
45
+ Keyring.any_instance.expects(:delete_password).with('service', 'username')
46
+ @cli.delete(['service', 'username'])
47
+ end
48
+
49
+ def test_ensure_arg_presence
50
+ assert_nothing_raised {@cli.ensure_arg_presence([], 0)}
51
+ assert_raise(ArgumentError) {@cli.ensure_arg_presence([], 1)}
52
+ assert_raise(ArgumentError) {@cli.ensure_arg_presence([''], 1)}
53
+
54
+ assert_nothing_raised {@cli.ensure_arg_presence(['a'], 1)}
55
+ assert_raise(ArgumentError) {@cli.ensure_arg_presence(['a'], 2)}
56
+ assert_raise(ArgumentError) {@cli.ensure_arg_presence(['a', ''], 2)}
57
+ end
58
+ end
@@ -0,0 +1,36 @@
1
+ # keyring: System keyring abstraction library
2
+ # License: MIT (http://www.opensource.org/licenses/mit-license.php)
3
+
4
+ require 'test/unit'
5
+ require 'mocha/setup'
6
+ require 'keyring'
7
+
8
+ class KeyringTests < Test::Unit::TestCase
9
+ def setup
10
+ @backend = Keyring::Backend::Memory.new
11
+ @keyring = Keyring.new(@backend)
12
+ end
13
+
14
+ def test_initialize
15
+ keyring = Keyring.new
16
+ assert_kind_of Keyring::Backend, keyring.instance_variable_get(:@backend)
17
+
18
+ backend = Keyring::Backend::Memory.new
19
+ keyring = Keyring.new(backend)
20
+ assert_equal backend, keyring.instance_variable_get(:@backend)
21
+ end
22
+
23
+ def test_get_password
24
+ @backend.expects(:get_password).with('service', 'username').returns('password')
25
+ password = @keyring.get_password('service', 'username')
26
+ assert_equal 'password', password
27
+ end
28
+ def test_set_password
29
+ @backend.expects(:set_password).with('service', 'username', 'password')
30
+ @keyring.set_password('service', 'username', 'password')
31
+ end
32
+ def test_delete_password
33
+ @backend.expects(:delete_password).with('service', 'username')
34
+ @keyring.delete_password('service', 'username')
35
+ end
36
+ end
@@ -0,0 +1 @@
1
+ 01010101
@@ -0,0 +1 @@
1
+ password:
@@ -0,0 +1 @@
1
+ ô%A���t;. u�@r
@@ -0,0 +1,27 @@
1
+ #!/bin/sh
2
+ # keyring: System keyring abstraction library
3
+ # License: MIT (http://www.opensource.org/licenses/mit-license.php)
4
+
5
+ cat <<-EOF
6
+ keychain: "/Users/jheiss/Library/Keychains/login.keychain"
7
+ class: "genp"
8
+ attributes:
9
+ 0x00000007 <blob>="service"
10
+ 0x00000008 <blob>=<NULL>
11
+ "acct"<blob>="username"
12
+ "cdat"<timedate>=0x32303133313132303233353532395A00 "20131120235529Z\000"
13
+ "crtr"<uint32>=<NULL>
14
+ "cusi"<sint32>=<NULL>
15
+ "desc"<blob>=<NULL>
16
+ "gena"<blob>=<NULL>
17
+ "icmt"<blob>=<NULL>
18
+ "invi"<sint32>=<NULL>
19
+ "mdat"<timedate>=0x32303133313132313232353534395A00 "20131121225549Z\000"
20
+ "nega"<sint32>=<NULL>
21
+ "prot"<blob>=<NULL>
22
+ "scrp"<sint32>=<NULL>
23
+ "svce"<blob>="service"
24
+ "type"<uint32>=<NULL>
25
+ EOF
26
+
27
+ printf "password has been deleted.\n" >&2
@@ -0,0 +1,26 @@
1
+ #!/bin/sh
2
+ # keyring: System keyring abstraction library
3
+ # License: MIT (http://www.opensource.org/licenses/mit-license.php)
4
+
5
+ cat <<-EOF
6
+ keychain: "/Users/example/Library/Keychains/login.keychain"
7
+ class: "genp"
8
+ attributes:
9
+ 0x00000007 <blob>="service"
10
+ 0x00000008 <blob>=<NULL>
11
+ "acct"<blob>="username"
12
+ "cdat"<timedate>=0x32303133313132303233353532395A00 "20131120235529Z\000"
13
+ "crtr"<uint32>=<NULL>
14
+ "cusi"<sint32>=<NULL>
15
+ "desc"<blob>=<NULL>
16
+ "gena"<blob>=<NULL>
17
+ "icmt"<blob>=<NULL>
18
+ "invi"<sint32>=<NULL>
19
+ "mdat"<timedate>=0x32303133313132313132343834315A00 "20131121124841Z\000"
20
+ "nega"<sint32>=<NULL>
21
+ "prot"<blob>=<NULL>
22
+ "scrp"<sint32>=<NULL>
23
+ "svce"<blob>="service"
24
+ "type"<uint32>=<NULL>
25
+ EOF
26
+ printf "password: \"password\"\n" >&2
@@ -0,0 +1,26 @@
1
+ #!/bin/sh
2
+ # keyring: System keyring abstraction library
3
+ # License: MIT (http://www.opensource.org/licenses/mit-license.php)
4
+
5
+ cat <<-EOF
6
+ keychain: "/Users/example/Library/Keychains/login.keychain"
7
+ class: "genp"
8
+ attributes:
9
+ 0x00000007 <blob>="service"
10
+ 0x00000008 <blob>=<NULL>
11
+ "acct"<blob>="emptyuser"
12
+ "cdat"<timedate>=0x32303133313132303233353532395A00 "20131120235529Z\000"
13
+ "crtr"<uint32>=<NULL>
14
+ "cusi"<sint32>=<NULL>
15
+ "desc"<blob>=<NULL>
16
+ "gena"<blob>=<NULL>
17
+ "icmt"<blob>=<NULL>
18
+ "invi"<sint32>=<NULL>
19
+ "mdat"<timedate>=0x32303133313132313132343834315A00 "20131121124841Z\000"
20
+ "nega"<sint32>=<NULL>
21
+ "prot"<blob>=<NULL>
22
+ "scrp"<sint32>=<NULL>
23
+ "svce"<blob>="service"
24
+ "type"<uint32>=<NULL>
25
+ EOF
26
+ printf "password: \n" >&2
@@ -0,0 +1,26 @@
1
+ #!/bin/sh
2
+ # keyring: System keyring abstraction library
3
+ # License: MIT (http://www.opensource.org/licenses/mit-license.php)
4
+
5
+ cat <<-EOF
6
+ keychain: "/Users/example/Library/Keychains/login.keychain"
7
+ class: "genp"
8
+ attributes:
9
+ 0x00000007 <blob>="service"
10
+ 0x00000008 <blob>=<NULL>
11
+ "acct"<blob>="hexuser"
12
+ "cdat"<timedate>=0x32303133313132303233353532395A00 "20131120235529Z\000"
13
+ "crtr"<uint32>=<NULL>
14
+ "cusi"<sint32>=<NULL>
15
+ "desc"<blob>=<NULL>
16
+ "gena"<blob>=<NULL>
17
+ "icmt"<blob>=<NULL>
18
+ "invi"<sint32>=<NULL>
19
+ "mdat"<timedate>=0x32303133313132313132343834315A00 "20131121124841Z\000"
20
+ "nega"<sint32>=<NULL>
21
+ "prot"<blob>=<NULL>
22
+ "scrp"<sint32>=<NULL>
23
+ "svce"<blob>="service"
24
+ "type"<uint32>=<NULL>
25
+ EOF
26
+ printf "password: 0x08300831083008310830083108300831 \"\0100\0101\0100\0101\0100\0101\0100\0101\"\n" >&2