security 0.0.1

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.
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,18 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ security (0.0.1)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ rake (0.9.2.2)
10
+ rspec (0.6.4)
11
+
12
+ PLATFORMS
13
+ ruby
14
+
15
+ DEPENDENCIES
16
+ rake (~> 0.9.2)
17
+ rspec (~> 0.6.1)
18
+ security!
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2012 Mattt Thompson (http://mattt.me/)
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,24 @@
1
+ # Security
2
+ **Library for interacting with the Mac OS X Keychain**
3
+
4
+ > This library currently only implements the necessary commands for password management for [Cupertino](https://github.com/mattt/cupertino). As such, some methods are stubbed out to raise `NotImplementedError`.
5
+
6
+ ## Usage
7
+
8
+ ```ruby
9
+ Security::Keychain::default_keychain.filename #=> "/Users/johnnyappleseed/Library/Keychains/login.keychain"
10
+
11
+ Security::InternetPassword.find(server: "itunesconnect.apple.com").password #=> "p4ssw0rd"
12
+ ```
13
+
14
+ ## Contact
15
+
16
+ Mattt Thompson
17
+
18
+ - http://github.com/mattt
19
+ - http://twitter.com/mattt
20
+ - m@mattt.me
21
+
22
+ ## License
23
+
24
+ Security is available under the MIT license. See the LICENSE file for more info.
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler"
2
+ Bundler.setup
3
+
4
+ gemspec = eval(File.read("security.gemspec"))
5
+
6
+ task :build => "#{gemspec.full_name}.gem"
7
+
8
+ file "#{gemspec.full_name}.gem" => gemspec.files + ["security.gemspec"] do
9
+ system "gem build security.gemspec"
10
+ end
data/lib/security.rb ADDED
@@ -0,0 +1,7 @@
1
+ module Security
2
+ VERSION = "0.0.1"
3
+ end
4
+
5
+ require 'security/keychain'
6
+ require 'security/certificate'
7
+ require 'security/password'
@@ -0,0 +1,19 @@
1
+ module Security
2
+ class Certificate
3
+ private_class_method :new
4
+
5
+ def delete!
6
+ raise NotImplementedError
7
+ end
8
+
9
+ def verified?
10
+ raise NotImplementedError
11
+ end
12
+
13
+ class << self
14
+ def find
15
+ raise NotImplementedError
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,61 @@
1
+ module Security
2
+ class Keychain
3
+ DOMAINS = [:user, :system, :common, :dynamic]
4
+
5
+ attr_reader :filename
6
+
7
+ def initialize(filename)
8
+ @filename = filename
9
+ end
10
+
11
+ def info
12
+ system %{security show-keychain-info "#{@filename}"}
13
+ end
14
+
15
+ def lock
16
+ system %{security lock-keychain "#{@filename}"}
17
+ end
18
+
19
+ def unlock(password)
20
+ system %{security unlock-keychain -p #{password} "#{@filename}"}
21
+ end
22
+
23
+ def delete
24
+ system %{security delete-keychain "#{@filename}"}
25
+ end
26
+
27
+ class << self
28
+ def create(filename, password)
29
+ raise NotImplementedError
30
+ end
31
+
32
+ def list(domain = :user)
33
+ raise ArgumentError "Invalid domain #{domain}, expected one of: #{DOMAINS}" unless DOMAINS.include?(domain)
34
+
35
+ keychains_from_command('list-keychains', domain)
36
+ end
37
+
38
+ def lock
39
+ system %{security lock-keychain -a}
40
+ end
41
+
42
+ def unlock(password)
43
+ system %{security unlock-keychain -p #{password}}
44
+ end
45
+
46
+ def default_keychain
47
+ keychains_from_command('default-keychain').first
48
+ end
49
+
50
+ def login_keychain
51
+ keychains_from_command('login-keychain').first
52
+ end
53
+
54
+ private
55
+
56
+ def keychains_from_command(command, *args)
57
+ `security #{[command, *args].compact.join(' ')}`.split(/\n/).collect{|line| new(line.strip.gsub(/^\"|\"$/, ""))}
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,101 @@
1
+ module Security
2
+ class Password
3
+ attr_reader :keychain, :attributes, :password
4
+
5
+ private_class_method :new
6
+
7
+ def initialize(keychain, attributes, password)
8
+ @keychain = Keychain.new(keychain)
9
+ @attributes = attributes
10
+ @password = password
11
+ end
12
+
13
+ class << self
14
+ private
15
+
16
+ def password_from_output(output)
17
+ return nil if /^security\: / === output
18
+
19
+ keychain, attributes, password = nil, {}, nil
20
+ output.split(/\n/).each do |line|
21
+ case line
22
+ when /^keychain\: \"(.+)\"/
23
+ keychain = $1
24
+ when /\"(\w{4})\".+\=\"(.+)\"/
25
+ attributes[$1] = $2
26
+ when /^password\: \"(.+)\"/
27
+ password = $1
28
+ end
29
+ end
30
+
31
+ new(keychain, attributes, password)
32
+ end
33
+
34
+ def flags_for_options(options = {})
35
+ flags = options.dup
36
+ flags[:a] ||= options.delete(:account)
37
+ flags[:c] ||= options.delete(:creator)
38
+ flags[:C] ||= options.delete(:type)
39
+ flags[:D] ||= options.delete(:kind)
40
+ flags[:G] ||= options.delete(:value)
41
+ flags[:j] ||= options.delete(:comment)
42
+ flags[:s] ||= options.delete(:service) || options.delete(:server)
43
+
44
+ flags.delete_if{|k,v| v.nil?}.collect{|k, v| "-#{k} #{v}".strip}.join(" ")
45
+ end
46
+ end
47
+ end
48
+
49
+ class GenericPassword < Password
50
+ class << self
51
+ def add(account, service, password, options = {})
52
+ options[:a] = account
53
+ options[:s] = service
54
+ options[:w] = password
55
+
56
+ system "security add-generic-password #{flags_for_options(options)}"
57
+ end
58
+
59
+ def find(options)
60
+ options[:g] = ''
61
+
62
+ password_from_output(`security 2>&1 find-generic-password #{flags_for_options(options)}`)
63
+ end
64
+
65
+ def delete(options)
66
+ system "security delete-generic-password #{flags_for_options(options)}"
67
+ end
68
+ end
69
+ end
70
+
71
+ class InternetPassword < Password
72
+ class << self
73
+ def add(account, server, password, options = {})
74
+ options[:a] = account
75
+ options[:s] = server
76
+ options[:w] = password
77
+
78
+ system "security add-internet-password #{flags_for_options(options)}"
79
+ end
80
+
81
+ def find(options)
82
+ options[:g] = ''
83
+
84
+ password_from_output(`security 2>&1 find-internet-password #{flags_for_options(options)}`)
85
+ end
86
+
87
+ def delete(options)
88
+ system "security delete-internet-password #{flags_for_options(options)}"
89
+ end
90
+
91
+ private
92
+
93
+ def flags_for_options(options = {})
94
+ options[:p] ||= options.delete(:path)
95
+ options[:P] ||= options.delete(:port)
96
+ options[:r] ||= options.delete(:protocol)
97
+ super(options)
98
+ end
99
+ end
100
+ end
101
+ end
data/security.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "security"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "security"
7
+ s.authors = ["Mattt Thompson"]
8
+ s.email = "m@mattt.me"
9
+ s.homepage = "http://mattt.me"
10
+ s.version = Security::VERSION
11
+ s.platform = Gem::Platform::RUBY
12
+ s.summary = "Security"
13
+ s.description = "Library for interacting with the Mac OS X Keychain"
14
+
15
+ s.add_development_dependency "rspec", "~> 0.6.1"
16
+ s.add_development_dependency "rake", "~> 0.9.2"
17
+
18
+ s.files = Dir["./**/*"].reject { |file| file =~ /\.\/(bin|log|pkg|script|spec|test|vendor)/ }
19
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
+ s.require_paths = ["lib"]
22
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: security
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Mattt Thompson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-21 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: &70220282679320 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.6.1
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70220282679320
25
+ - !ruby/object:Gem::Dependency
26
+ name: rake
27
+ requirement: &70220282678600 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 0.9.2
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70220282678600
36
+ description: Library for interacting with the Mac OS X Keychain
37
+ email: m@mattt.me
38
+ executables: []
39
+ extensions: []
40
+ extra_rdoc_files: []
41
+ files:
42
+ - ./Gemfile
43
+ - ./Gemfile.lock
44
+ - ./lib/security/certificate.rb
45
+ - ./lib/security/keychain.rb
46
+ - ./lib/security/password.rb
47
+ - ./lib/security.rb
48
+ - ./LICENSE
49
+ - ./Rakefile
50
+ - ./README.md
51
+ - ./security.gemspec
52
+ homepage: http://mattt.me
53
+ licenses: []
54
+ post_install_message:
55
+ rdoc_options: []
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ! '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ segments:
65
+ - 0
66
+ hash: -4232387281816222953
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ! '>='
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ segments:
74
+ - 0
75
+ hash: -4232387281816222953
76
+ requirements: []
77
+ rubyforge_project:
78
+ rubygems_version: 1.8.15
79
+ signing_key:
80
+ specification_version: 3
81
+ summary: Security
82
+ test_files: []