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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +7 -0
- data/LICENSE +20 -0
- data/README.md +62 -70
- data/Rakefile +10 -15
- data/bin/keyring +12 -0
- data/keyring.gemspec +28 -0
- data/lib/keyring.rb +22 -13
- data/lib/keyring/backend.rb +42 -0
- data/lib/keyring/backends/macosx_keychain.rb +91 -0
- data/lib/keyring/backends/memory.rb +29 -0
- data/lib/keyring/cli.rb +79 -0
- data/lib/keyring/version.rb +6 -0
- data/test/keyring_tests.rb +7 -0
- data/test/test_backend.rb +38 -0
- data/test/test_backend_macosx_keychain.rb +73 -0
- data/test/test_backend_memory.rb +43 -0
- data/test/test_cli.rb +58 -0
- data/test/test_keyring.rb +36 -0
- data/test/testcmds/macosx/binary +1 -0
- data/test/testcmds/macosx/emptything +1 -0
- data/test/testcmds/macosx/random +1 -0
- data/test/testcmds/macosx/security-delete +27 -0
- data/test/testcmds/macosx/security-find +26 -0
- data/test/testcmds/macosx/security-findempty +26 -0
- data/test/testcmds/macosx/security-findhex +26 -0
- data/test/testcmds/macosx/security-notfound +6 -0
- data/test/testcmds/macosx/security-righthelp +51 -0
- data/test/testcmds/macosx/security-wronghelp +7 -0
- metadata +129 -59
- data/History.txt +0 -4
- data/lib/keyring/Keyring.rb +0 -95
- data/lib/keyring/SimpleKeyring.rb +0 -38
- data/spec/keyring_spec.rb +0 -129
- data/spec/spec_helper.rb +0 -15
- data/version.txt +0 -1
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f67fb1efea2eb2eaa09bacafab9ef4e75fba84cd
|
4
|
+
data.tar.gz: 1a19d3f9507d0e606f08b0e60c9710d2e677432a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 73ef48738d5a0193754a983abbce3d5d666ea619fe4d25044d0dfe7350ef4667847aa7085fe35c9bbc4dc6a777b4fb1f77f1c6296ec8bbde108e991f553056cb
|
7
|
+
data.tar.gz: af4063ca11ba35150b2a8697aa58a468e8fe86d773a94d2d8c4486eb2710980e886265b5acd9a9e20a41edc590b3432c08a91f37055d1b82506d176e1039d493
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2013 Jason Heiss
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -1,70 +1,62 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
This
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
The
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
65
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
66
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
67
|
-
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
68
|
-
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
69
|
-
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
70
|
-
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
1
|
+
# Keyring
|
2
|
+
|
3
|
+
Store and access your passwords safely
|
4
|
+
|
5
|
+
This library provides a easy way to access the system keyring service from ruby.
|
6
|
+
It can be used in any application that needs safe password storage.
|
7
|
+
|
8
|
+
The keyring services supported by this library:
|
9
|
+
* Mac OS X Keychain: the Apple Keychain service in Mac OS X.
|
10
|
+
* In-memory keychain
|
11
|
+
|
12
|
+
Additional keyring services we'd like to support:
|
13
|
+
* KDE KWallet
|
14
|
+
* GNOME 2 Keyring
|
15
|
+
* SecretServiceKeyring: for newer GNOME and KDE environments.
|
16
|
+
* Windows Credential Manager
|
17
|
+
|
18
|
+
## Installation
|
19
|
+
|
20
|
+
Add this line to your application's Gemfile:
|
21
|
+
|
22
|
+
gem 'keyring'
|
23
|
+
|
24
|
+
And then execute:
|
25
|
+
|
26
|
+
$ bundle
|
27
|
+
|
28
|
+
Or install it yourself as:
|
29
|
+
|
30
|
+
$ gem install keyring
|
31
|
+
|
32
|
+
## Usage
|
33
|
+
|
34
|
+
The basic usage of keyring is simple: just call Keyring#set_password and
|
35
|
+
Keyring#get_password:
|
36
|
+
|
37
|
+
require 'keyring'
|
38
|
+
keyring = Keyring.new
|
39
|
+
keyring.set_password('service', 'username', 'password')
|
40
|
+
password = keyring.get_password('service', 'username')
|
41
|
+
keyring.delete_password('service', 'username')
|
42
|
+
|
43
|
+
'service' is an arbitrary string identifying your application.
|
44
|
+
|
45
|
+
## Credits
|
46
|
+
|
47
|
+
Copyright 2013, Jason Heiss
|
48
|
+
|
49
|
+
Inspired by the keyring library for Python:
|
50
|
+
https://bitbucket.org/kang/python-keyring-lib
|
51
|
+
|
52
|
+
## License
|
53
|
+
|
54
|
+
MIT
|
55
|
+
|
56
|
+
## Contributing
|
57
|
+
|
58
|
+
1. Fork it
|
59
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
60
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
61
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
62
|
+
5. Create new Pull Request
|
data/Rakefile
CHANGED
@@ -1,17 +1,12 @@
|
|
1
|
+
# keyring: System keyring abstraction library
|
2
|
+
# License: MIT (http://www.opensource.org/licenses/mit-license.php)
|
1
3
|
|
2
|
-
|
3
|
-
|
4
|
-
rescue LoadError
|
5
|
-
abort '### Please install the "bones" gem ###'
|
6
|
-
end
|
7
|
-
|
8
|
-
task :default => 'spec:run'
|
9
|
-
task 'gem:release' => 'spec:run'
|
10
|
-
|
11
|
-
Bones {
|
12
|
-
name 'keyring'
|
13
|
-
authors 'Frank Fischer'
|
14
|
-
email 'frank.fischer@mathematik.tu-chemnitz.de'
|
15
|
-
url 'http://darcsden.com/lyro/keyring'
|
16
|
-
}
|
4
|
+
require "bundler/gem_tasks"
|
5
|
+
require 'rake/testtask'
|
17
6
|
|
7
|
+
# Run a specific file: rake test TEST=test/make.rb
|
8
|
+
# Run a specific method:
|
9
|
+
# rake test TEST=test/test_make.rb TESTOPTS="--name=test_make_osarch_names"
|
10
|
+
Rake::TestTask.new do |t|
|
11
|
+
t.verbose = true
|
12
|
+
end
|
data/bin/keyring
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# keyring: System keyring abstraction library
|
3
|
+
# License: MIT (http://www.opensource.org/licenses/mit-license.php)
|
4
|
+
|
5
|
+
# When run from the source repository or from an unpacked copy of the
|
6
|
+
# distribution we want to find the local library, even if there's a copy
|
7
|
+
# installed on the system.
|
8
|
+
$:.unshift(File.expand_path('../lib', File.dirname(__FILE__)))
|
9
|
+
|
10
|
+
require 'keyring/cli'
|
11
|
+
|
12
|
+
Keyring::CLI.new.main
|
data/keyring.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# keyring: System keyring abstraction library
|
3
|
+
# License: MIT (http://www.opensource.org/licenses/mit-license.php)
|
4
|
+
|
5
|
+
lib = File.expand_path('../lib', __FILE__)
|
6
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
7
|
+
require 'keyring/version'
|
8
|
+
|
9
|
+
Gem::Specification.new do |spec|
|
10
|
+
spec.name = "keyring"
|
11
|
+
spec.version = Keyring::VERSION
|
12
|
+
spec.authors = ["Jason Heiss"]
|
13
|
+
spec.email = ["jheiss@aput.net"]
|
14
|
+
spec.description = %q{This library provides a easy way to access the system keyring service from ruby}
|
15
|
+
spec.summary = %q{Store and access your passwords safely}
|
16
|
+
spec.homepage = "https://github.com/jheiss/keyring"
|
17
|
+
spec.license = "MIT"
|
18
|
+
|
19
|
+
spec.files = `git ls-files`.split($/)
|
20
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
21
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
22
|
+
spec.require_paths = ["lib"]
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
25
|
+
spec.add_development_dependency "rake"
|
26
|
+
spec.add_development_dependency 'mocha'
|
27
|
+
spec.add_dependency 'slop'
|
28
|
+
end
|
data/lib/keyring.rb
CHANGED
@@ -1,15 +1,24 @@
|
|
1
|
+
# keyring: System keyring abstraction library
|
2
|
+
# License: MIT (http://www.opensource.org/licenses/mit-license.php)
|
1
3
|
|
2
|
-
|
3
|
-
|
4
|
-
# :stopdoc:
|
5
|
-
LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
|
6
|
-
PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
|
7
|
-
VERSION = ::File.read(PATH + 'version.txt').strip
|
8
|
-
|
9
|
-
%w(Keyring.rb SimpleKeyring.rb).each do |fname|
|
10
|
-
require File.join(LIBPATH, "keyring", fname)
|
11
|
-
end
|
12
|
-
|
13
|
-
end # module Keyring
|
14
|
-
|
4
|
+
require "keyring/version"
|
15
5
|
|
6
|
+
class Keyring
|
7
|
+
require 'keyring/backend'
|
8
|
+
|
9
|
+
# If you want a particular backend then use, for example,
|
10
|
+
# Keyring.new(Keyring::Backend::Memory.new)
|
11
|
+
def initialize(backend=nil)
|
12
|
+
@backend = backend || Keyring::Backend.create
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_password(service, username)
|
16
|
+
@backend.get_password(service, username)
|
17
|
+
end
|
18
|
+
def set_password(service, username, password)
|
19
|
+
@backend.set_password(service, username, password)
|
20
|
+
end
|
21
|
+
def delete_password(service, username)
|
22
|
+
@backend.delete_password(service, username)
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# keyring: System keyring abstraction library
|
2
|
+
# License: MIT (http://www.opensource.org/licenses/mit-license.php)
|
3
|
+
|
4
|
+
class Keyring::Backend
|
5
|
+
@implementations = []
|
6
|
+
class << self
|
7
|
+
attr_accessor :implementations
|
8
|
+
end
|
9
|
+
def self.register_implementation(impl)
|
10
|
+
Keyring::Backend.implementations << impl
|
11
|
+
end
|
12
|
+
Dir.glob(File.expand_path('backends/*.rb', File.dirname(__FILE__))).each {|b| require b}
|
13
|
+
def self.create
|
14
|
+
supported = implementations.collect{|i| b = i.new; b.supported? ? b : nil}.compact
|
15
|
+
if supported.empty?
|
16
|
+
raise(NotImplementedError)
|
17
|
+
end
|
18
|
+
supported.max{|b| b.priority}
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
# Backend classes must implement these methods
|
23
|
+
#
|
24
|
+
|
25
|
+
def supported?
|
26
|
+
false
|
27
|
+
end
|
28
|
+
# Returns a number between 0 and 1 (inclusive) indicating the relative
|
29
|
+
# preference for this backend.
|
30
|
+
def priority
|
31
|
+
0
|
32
|
+
end
|
33
|
+
def set_password(service, username, password)
|
34
|
+
raise NotImplementedError
|
35
|
+
end
|
36
|
+
def get_password(service, username)
|
37
|
+
raise NotImplementedError
|
38
|
+
end
|
39
|
+
def delete_password(service, username)
|
40
|
+
raise NotImplementedError
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# keyring: System keyring abstraction library
|
2
|
+
# License: MIT (http://www.opensource.org/licenses/mit-license.php)
|
3
|
+
|
4
|
+
# This is a keyring backend for the Apple Keychain
|
5
|
+
# http://en.wikipedia.org/wiki/Keychain_(Apple)
|
6
|
+
|
7
|
+
require 'open3'
|
8
|
+
|
9
|
+
class Keyring::Backend::MacosxKeychain < Keyring::Backend
|
10
|
+
register_implementation(self)
|
11
|
+
|
12
|
+
attr_accessor :security
|
13
|
+
def initialize
|
14
|
+
@security = '/usr/bin/security'
|
15
|
+
end
|
16
|
+
def supported?
|
17
|
+
File.exist?(@security) && `#{@security} -h`.include?('find-generic-password')
|
18
|
+
end
|
19
|
+
def priority
|
20
|
+
1
|
21
|
+
end
|
22
|
+
|
23
|
+
def security_command(operation)
|
24
|
+
"#{operation}-generic-password"
|
25
|
+
end
|
26
|
+
|
27
|
+
def set_password(service, username, password)
|
28
|
+
cmd = [
|
29
|
+
@security,
|
30
|
+
security_command('add'),
|
31
|
+
'-s', service,
|
32
|
+
'-a', username,
|
33
|
+
# FIXME: password in command line, sad panda!
|
34
|
+
'-w', password,
|
35
|
+
'-U',
|
36
|
+
]
|
37
|
+
system(*cmd)
|
38
|
+
if !$?.success?
|
39
|
+
raise
|
40
|
+
end
|
41
|
+
end
|
42
|
+
def get_password(service, username)
|
43
|
+
password = nil
|
44
|
+
cmd = [
|
45
|
+
@security,
|
46
|
+
security_command('find'),
|
47
|
+
'-s', service,
|
48
|
+
'-a', username,
|
49
|
+
'-g',
|
50
|
+
# '-w',
|
51
|
+
]
|
52
|
+
Open3.popen3(*cmd) do |stdin, stdout, stderr, wait_thr|
|
53
|
+
stderr.each do |line|
|
54
|
+
if line =~ /\Apassword: (.*)/
|
55
|
+
pw = $1
|
56
|
+
if pw == ''
|
57
|
+
password = pw
|
58
|
+
elsif pw =~ /\A"(.*)"\z/
|
59
|
+
password = $1
|
60
|
+
elsif pw =~ /\A0x(\h+)/
|
61
|
+
password = [$1].pack("H*")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
# security exits with 44 if the entry does not exist. We just want to return
|
66
|
+
# nil rather than raise an exception in that case.
|
67
|
+
if ![0,44].include?(wait_thr.value.exitstatus)
|
68
|
+
raise
|
69
|
+
end
|
70
|
+
end
|
71
|
+
password
|
72
|
+
end
|
73
|
+
def delete_password(service, username)
|
74
|
+
cmd = [
|
75
|
+
@security,
|
76
|
+
security_command('delete'),
|
77
|
+
'-s', service,
|
78
|
+
'-a', username,
|
79
|
+
]
|
80
|
+
Open3.popen3(*cmd) do |stdin, stdout, stderr, wait_thr|
|
81
|
+
case wait_thr.value.exitstatus
|
82
|
+
when 0
|
83
|
+
return true
|
84
|
+
when 44
|
85
|
+
return false
|
86
|
+
else
|
87
|
+
raise
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# keyring: System keyring abstraction library
|
2
|
+
# License: MIT (http://www.opensource.org/licenses/mit-license.php)
|
3
|
+
|
4
|
+
# Stores the keyring in-memory. Useful when you don't need permanant storage.
|
5
|
+
|
6
|
+
class Keyring::Backend::Memory < Keyring::Backend
|
7
|
+
register_implementation(self)
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@keyring = {}
|
11
|
+
end
|
12
|
+
def supported?
|
13
|
+
true
|
14
|
+
end
|
15
|
+
def priority
|
16
|
+
0.1
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_password(service, username)
|
20
|
+
@keyring[service] && @keyring[service][username]
|
21
|
+
end
|
22
|
+
def set_password(service, username, password)
|
23
|
+
@keyring[service] ||= {}
|
24
|
+
@keyring[service][username] = password
|
25
|
+
end
|
26
|
+
def delete_password(service, username)
|
27
|
+
@keyring[service] && @keyring[service].delete(username)
|
28
|
+
end
|
29
|
+
end
|