security 0.1.0 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f878a3070c6bc072f8bf7e0dfe17a8db85dec7b32685353498a642ea76c95176
4
+ data.tar.gz: '02093024c12b425b231eadbe56963433929e1844870dedeab1fda5f31b1c4a2b'
5
+ SHA512:
6
+ metadata.gz: 7afe1f89bd8fda3701c8f31bb80b669107debea3ed191250a19d091fca665bc7b4572311f42b99a744b9a9c3a86657ca1d813420016fe07059bc4643a163c3de
7
+ data.tar.gz: eacec975d67c63faef11e7b20d4bd2c361d2daa5607ff7852fb2410bb0e71ba8e0926d75d2b158f733f423290648ca33ca91f522022ef987de64e41b2e16eea5
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
- source :rubygems
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
2
4
 
3
5
  gemspec
data/Gemfile.lock CHANGED
@@ -1,18 +1,58 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- security (0.1.0)
4
+ security (0.1.5)
5
5
 
6
6
  GEM
7
- remote: http://rubygems.org/
7
+ remote: https://rubygems.org/
8
8
  specs:
9
- rake (0.9.2.2)
10
- rspec (0.6.4)
9
+ ast (2.4.2)
10
+ diff-lcs (1.4.4)
11
+ parallel (1.20.1)
12
+ parser (3.0.0.0)
13
+ ast (~> 2.4.1)
14
+ rainbow (3.0.0)
15
+ rake (12.3.3)
16
+ regexp_parser (2.1.1)
17
+ rexml (3.2.4)
18
+ rspec (3.10.0)
19
+ rspec-core (~> 3.10.0)
20
+ rspec-expectations (~> 3.10.0)
21
+ rspec-mocks (~> 3.10.0)
22
+ rspec-core (3.10.1)
23
+ rspec-support (~> 3.10.0)
24
+ rspec-expectations (3.10.1)
25
+ diff-lcs (>= 1.2.0, < 2.0)
26
+ rspec-support (~> 3.10.0)
27
+ rspec-github (2.3.1)
28
+ rspec-core (~> 3.0)
29
+ rspec-mocks (3.10.2)
30
+ diff-lcs (>= 1.2.0, < 2.0)
31
+ rspec-support (~> 3.10.0)
32
+ rspec-support (3.10.2)
33
+ rubocop (1.12.0)
34
+ parallel (~> 1.10)
35
+ parser (>= 3.0.0.0)
36
+ rainbow (>= 2.2.2, < 4.0)
37
+ regexp_parser (>= 1.8, < 3.0)
38
+ rexml
39
+ rubocop-ast (>= 1.2.0, < 2.0)
40
+ ruby-progressbar (~> 1.7)
41
+ unicode-display_width (>= 1.4.0, < 3.0)
42
+ rubocop-ast (1.4.1)
43
+ parser (>= 2.7.1.5)
44
+ ruby-progressbar (1.11.0)
45
+ unicode-display_width (2.0.0)
11
46
 
12
47
  PLATFORMS
13
- ruby
48
+ x86_64-darwin-19
14
49
 
15
50
  DEPENDENCIES
16
- rake (~> 0.9.2)
17
- rspec (~> 0.6.1)
51
+ rake (~> 12.3, >= 12.3.3)
52
+ rspec
53
+ rspec-github
54
+ rubocop
18
55
  security!
56
+
57
+ BUNDLED WITH
58
+ 2.2.8
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012 Mattt Thompson (http://mattt.me/)
1
+ Copyright (c) 2012 2021 The Fastlane Community Contributors
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,24 +1,27 @@
1
1
  # Security
2
- **Library for interacting with the Mac OS X Keychain**
3
2
 
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`.
3
+ [![Build Status][build status badge]][build status]
4
+ [![Gem](https://img.shields.io/gem/v/security.svg?style=flat)](https://rubygems.org/gems/security)
5
+ [![License](https://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://github.com/fastlane-community/security/blob/main/LICENSE.md)
6
+
7
+ **A library for interacting with the macOS Keychain**
8
+
9
+ > This library provides only a subset of `security` subcommands,
10
+ > and is not intended for general use.
5
11
 
6
12
  ## Usage
7
13
 
8
14
  ```ruby
9
- Security::Keychain::default_keychain.filename #=> "/Users/johnnyappleseed/Library/Keychains/login.keychain"
15
+ require 'security'
16
+
17
+ Security::Keychain::default_keychain.filename #=> "/Users/jappleseed/Library/Keychains/login.keychain"
10
18
 
11
19
  Security::InternetPassword.find(server: "itunesconnect.apple.com").password #=> "p4ssw0rd"
12
20
  ```
13
21
 
14
- ## Contact
15
-
16
- Mattt Thompson
17
-
18
- - http://github.com/mattt
19
- - http://twitter.com/mattt
20
- - m@mattt.me
21
-
22
22
  ## License
23
23
 
24
- Security is available under the MIT license. See the LICENSE file for more info.
24
+ MIT
25
+
26
+ [build status]: https://github.com/mattt/Security/actions?query=workflow%3ACI
27
+ [build status badge]: https://github.com/mattt/Security/workflows/CI/badge.svg
data/Rakefile CHANGED
@@ -1,10 +1,10 @@
1
- require "bundler"
2
- Bundler.setup
1
+ # frozen_string_literal: true
3
2
 
4
- gemspec = eval(File.read("security.gemspec"))
3
+ require 'bundler'
4
+ Bundler.setup
5
5
 
6
- task :build => "#{gemspec.full_name}.gem"
6
+ require 'bundler/gem_tasks'
7
7
 
8
- file "#{gemspec.full_name}.gem" => gemspec.files + ["security.gemspec"] do
9
- system "gem build security.gemspec"
8
+ task :default do
9
+ system 'rake -T'
10
10
  end
data/lib/security.rb CHANGED
@@ -1,7 +1,6 @@
1
- module Security
2
- VERSION = "0.1.0"
3
- end
1
+ # frozen_string_literal: true
4
2
 
3
+ require 'security/version'
5
4
  require 'security/keychain'
6
5
  require 'security/certificate'
7
6
  require 'security/password'
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Security
4
+ # :nodoc:
2
5
  class Certificate
3
6
  private_class_method :new
4
7
 
@@ -16,4 +19,4 @@ module Security
16
19
  end
17
20
  end
18
21
  end
19
- end
22
+ end
@@ -1,6 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'shellwords'
4
+
1
5
  module Security
6
+ # :nodoc:
2
7
  class Keychain
3
- DOMAINS = [:user, :system, :common, :dynamic]
8
+ DOMAINS = %i[user system common dynamic].freeze
4
9
 
5
10
  attr_reader :filename
6
11
 
@@ -9,19 +14,19 @@ module Security
9
14
  end
10
15
 
11
16
  def info
12
- system %{security show-keychain-info "#{@filename}"}
17
+ system %(security show-keychain-info #{@filename.shellescape})
13
18
  end
14
19
 
15
20
  def lock
16
- system %{security lock-keychain "#{@filename}"}
21
+ system %(security lock-keychain #{@filename.shellescape})
17
22
  end
18
23
 
19
24
  def unlock(password)
20
- system %{security unlock-keychain -p #{password} "#{@filename}"}
25
+ system %(security unlock-keychain -p #{password.shellescape} #{@filename.shellescape})
21
26
  end
22
27
 
23
28
  def delete
24
- system %{security delete-keychain "#{@filename}"}
29
+ system %(security delete-keychain #{@filename.shellescape})
25
30
  end
26
31
 
27
32
  class << self
@@ -32,30 +37,30 @@ module Security
32
37
  def list(domain = :user)
33
38
  raise ArgumentError "Invalid domain #{domain}, expected one of: #{DOMAINS}" unless DOMAINS.include?(domain)
34
39
 
35
- keychains_from_command('list-keychains', domain)
40
+ keychains_from_output(`security list-keychains -d #{domain}`)
36
41
  end
37
42
 
38
43
  def lock
39
- system %{security lock-keychain -a}
44
+ system %(security lock-keychain -a)
40
45
  end
41
46
 
42
47
  def unlock(password)
43
- system %{security unlock-keychain -p #{password}}
48
+ system %(security unlock-keychain -p #{password.shellescape})
44
49
  end
45
50
 
46
51
  def default_keychain
47
- keychains_from_command('default-keychain').first
52
+ keychains_from_output(`security default-keychain`).first
48
53
  end
49
54
 
50
55
  def login_keychain
51
- keychains_from_command('login-keychain').first
56
+ keychains_from_output(`security login-keychain`).first
52
57
  end
53
58
 
54
59
  private
55
60
 
56
- def keychains_from_command(command, *args)
57
- `security #{[command, *args].compact.join(' ')}`.split(/\n/).collect{|line| new(line.strip.gsub(/^\"|\"$/, ""))}
61
+ def keychains_from_output(output)
62
+ output.split(/\n/).collect { |line| new(line.strip.gsub(/^"|"$/, '')) }
58
63
  end
59
- end
64
+ end
60
65
  end
61
66
  end
@@ -1,4 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'shellwords'
4
+
1
5
  module Security
6
+ # :nodoc:
2
7
  class Password
3
8
  attr_reader :keychain, :attributes, :password
4
9
 
@@ -7,24 +12,30 @@ module Security
7
12
  def initialize(keychain, attributes, password)
8
13
  @keychain = Keychain.new(keychain)
9
14
  @attributes = attributes
10
- @password = password
15
+ @password = password
11
16
  end
12
17
 
13
18
  class << self
14
19
  private
15
20
 
16
21
  def password_from_output(output)
17
- return nil if /^security\: / === output
22
+ return nil if output.match?(/^security: /)
18
23
 
19
- keychain, attributes, password = nil, {}, nil
24
+ keychain = nil
25
+ attributes = {}
26
+ password = nil
20
27
  output.split(/\n/).each do |line|
21
28
  case line
22
- when /^keychain\: \"(.+)\"/
23
- keychain = $1
24
- when /\"(\w{4})\".+\=\"(.+)\"/
25
- attributes[$1] = $2
26
- when /^password\: \"(.+)\"/
27
- password = $1
29
+ when /^keychain: "(.+)"/
30
+ keychain = Regexp.last_match(1)
31
+ when /"(\w{4})".+="(.+)"/
32
+ attributes[Regexp.last_match(1)] = Regexp.last_match(2)
33
+ when /"(\w{4})"<blob>=0x([[:xdigit:]]+)/
34
+ attributes[Regexp.last_match(1)] = decode_hex_blob(Regexp.last_match(2))
35
+ when /^password: "(.+)"/
36
+ password = Regexp.last_match(1)
37
+ when /^password: 0x([[:xdigit:]]+)/
38
+ password = decode_hex_blob(Regexp.last_match(1))
28
39
  end
29
40
  end
30
41
 
@@ -33,19 +44,23 @@ module Security
33
44
 
34
45
  def flags_for_options(options = {})
35
46
  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(" ")
47
+ flags[:a] ||= flags.delete(:account)
48
+ flags[:c] ||= flags.delete(:creator)
49
+ flags[:C] ||= flags.delete(:type)
50
+ flags[:D] ||= flags.delete(:kind)
51
+ flags[:G] ||= flags.delete(:value)
52
+ flags[:j] ||= flags.delete(:comment)
53
+
54
+ flags.delete_if { |_k, v| v.nil? }.collect { |k, v| "-#{k} #{v.shellescape}".strip }.join(' ')
55
+ end
56
+
57
+ def decode_hex_blob(string)
58
+ [string].pack('H*').force_encoding('UTF-8')
45
59
  end
46
60
  end
47
61
  end
48
62
 
63
+ # :nodoc:
49
64
  class GenericPassword < Password
50
65
  class << self
51
66
  def add(service, account, password, options = {})
@@ -57,31 +72,35 @@ module Security
57
72
  end
58
73
 
59
74
  def find(options)
60
- options[:g] = ''
61
-
62
- password_from_output(`security 2>&1 find-generic-password #{flags_for_options(options)}`)
75
+ password_from_output(`security 2>&1 find-generic-password -g #{flags_for_options(options)}`)
63
76
  end
64
77
 
65
78
  def delete(options)
66
79
  system "security delete-generic-password #{flags_for_options(options)}"
67
80
  end
81
+
82
+ private
83
+
84
+ def flags_for_options(options = {})
85
+ options[:s] ||= options.delete(:service)
86
+ super(options)
87
+ end
68
88
  end
69
89
  end
70
90
 
91
+ # :nodoc:
71
92
  class InternetPassword < Password
72
93
  class << self
73
94
  def add(server, account, password, options = {})
74
95
  options[:a] = account
75
96
  options[:s] = server
76
97
  options[:w] = password
77
-
98
+
78
99
  system "security add-internet-password #{flags_for_options(options)}"
79
100
  end
80
101
 
81
102
  def find(options)
82
- options[:g] = ''
83
-
84
- password_from_output(`security 2>&1 find-internet-password #{flags_for_options(options)}`)
103
+ password_from_output(`security 2>&1 find-internet-password -g #{flags_for_options(options)}`)
85
104
  end
86
105
 
87
106
  def delete(options)
@@ -91,6 +110,7 @@ module Security
91
110
  private
92
111
 
93
112
  def flags_for_options(options = {})
113
+ options[:s] ||= options.delete(:server)
94
114
  options[:p] ||= options.delete(:path)
95
115
  options[:P] ||= options.delete(:port)
96
116
  options[:r] ||= options.delete(:protocol)
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :nodoc:
4
+ module Security
5
+ VERSION = '0.1.5'
6
+ end
data/security.gemspec CHANGED
@@ -1,22 +1,26 @@
1
- # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path("../lib", __FILE__)
3
- require "security"
1
+ # frozen_string_literal: true
2
+
3
+ $LOAD_PATH.push File.expand_path('lib', __dir__)
4
+ require 'security'
4
5
 
5
6
  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"
7
+ s.name = 'security'
8
+ s.authors = ['Josh Holtz', 'Mattt']
9
+ s.email = 'me@joshholtz.com'
10
+ s.homepage = 'https://github.com/fastlane-community/security'
10
11
  s.version = Security::VERSION
11
12
  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"
13
+ s.license = 'MIT'
14
+ s.summary = 'Interact with the macOS Keychain'
17
15
 
18
- s.files = Dir["./**/*"].reject { |file| file =~ /\.\/(bin|log|pkg|script|spec|test|vendor)/ }
16
+ s.files = Dir['./**/*'].reject { |file| file =~ %r{\./(bin|log|pkg|script|spec|test|vendor)} }
19
17
  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"]
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
19
+ s.require_paths = ['lib']
20
+ s.required_ruby_version = '>= 2.4.0'
21
+
22
+ s.add_development_dependency 'rake', '~> 12.3', '>= 12.3.3'
23
+ s.add_development_dependency 'rspec'
24
+ s.add_development_dependency 'rspec-github'
25
+ s.add_development_dependency 'rubocop'
22
26
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Certificate do
4
+ describe '#find' do
5
+ it 'should raise NotImplementedError' do
6
+ expect { Certificate.find }.to raise_error(NotImplementedError)
7
+ end
8
+ end
9
+
10
+ describe '#initialize' do
11
+ it 'should raise NoMethodError' do
12
+ expect { Certificate.new }.to raise_error(NoMethodError, /private method/)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tempfile'
4
+
5
+ describe Keychain do
6
+ describe '#login_keychain' do
7
+ subject { Keychain.login_keychain }
8
+
9
+ it 'should be located in the user home directory' do
10
+ expect(subject.filename).to be == File.expand_path('~/Library/Keychains/login.keychain-db')
11
+ end
12
+ end
13
+
14
+ describe '#create' do
15
+ let(:password) { 'p4ssw0rd!' }
16
+
17
+ it 'should raise NotImplementedError' do
18
+ Tempfile.open('example.keychain-db') do |tmp|
19
+ expect { Keychain.create(tmp.path, password) }.to raise_error(NotImplementedError)
20
+ end
21
+ end
22
+ end
23
+
24
+ describe '#list' do
25
+ describe 'when passing no arguments' do
26
+ it 'should list keychains in user domain' do
27
+ expect(Keychain.list).to satisfy { |keychains|
28
+ keychains.map(&:filename) == Keychain.list(:user).map(&:filename)
29
+ }
30
+ end
31
+ end
32
+
33
+ describe 'when passing a valid domain' do
34
+ it 'should not raise an error' do
35
+ expect { Keychain.list(:user) }.not_to raise_error
36
+ expect { Keychain.list(:system) }.not_to raise_error
37
+ expect { Keychain.list(:common) }.not_to raise_error
38
+ expect { Keychain.list(:dynamic) }.not_to raise_error
39
+ end
40
+ end
41
+
42
+ describe 'when passing an invalid domain' do
43
+ it 'should raise an error' do
44
+ expect { Keychain.list(:invalid) }.to raise_error(NoMethodError) # FIXME
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe GenericPassword do
4
+ let(:keychain) { Keychain.login_keychain } # FIXME: we should create a temporary keychain for tests
5
+
6
+ describe '#add' do
7
+ let(:service) { 'com.example.service' }
8
+ let(:account) { 'jappleseed' }
9
+ let(:password) { 'p4ssw0rd!' }
10
+ let(:comment) { 'Some comment' }
11
+
12
+ around(:example) do |example|
13
+ GenericPassword.add(service, account, password, comment: comment)
14
+ example.run
15
+ GenericPassword.delete({ service: service, account: account })
16
+ end
17
+
18
+ it 'should be added to the keychain' do
19
+ entry = GenericPassword.find({ account: account })
20
+ expect(entry.keychain.filename).to be == keychain.filename
21
+ expect(entry.attributes).to include({
22
+ 'acct' => account,
23
+ 'svce' => service,
24
+ 'icmt' => comment
25
+ })
26
+ expect(entry.password).to be == password
27
+ end
28
+ end
29
+ end
30
+
31
+ describe InternetPassword do
32
+ let(:keychain) { Keychain.login_keychain } # FIXME: we should create a temporary keychain for tests
33
+
34
+ describe '#add' do
35
+ let(:server) { 'example.com' }
36
+ let(:account) { 'jappleseed@example.com' }
37
+
38
+ describe 'ascii password' do
39
+ let(:password) { 'p4ssw0rd!' }
40
+ let(:comment) { 'Some comment' }
41
+
42
+ around(:example) do |example|
43
+ InternetPassword.add(server, account, password, comment: comment)
44
+ example.run
45
+ InternetPassword.delete({ server: server, account: account })
46
+ end
47
+
48
+ it 'should be added to the keychain' do
49
+ entry = InternetPassword.find({ account: account })
50
+ expect(entry.keychain.filename).to be == keychain.filename
51
+ expect(entry.attributes).to include({
52
+ 'acct' => account,
53
+ 'srvr' => server,
54
+ 'icmt' => comment
55
+ })
56
+ expect(entry.password).to be == password
57
+ end
58
+ end
59
+
60
+ describe 'ascii password with backslash' do
61
+ let(:password) { 'p4ssw\0rd!' }
62
+
63
+ around(:example) do |example|
64
+ InternetPassword.add(server, account, password)
65
+ example.run
66
+ InternetPassword.delete({ server: server, account: account })
67
+ end
68
+
69
+ it 'should be added to the keychain' do
70
+ entry = InternetPassword.find({ account: account })
71
+ expect(entry.keychain.filename).to be == keychain.filename
72
+ expect(entry.attributes).to include({
73
+ 'acct' => account,
74
+ 'srvr' => server
75
+ })
76
+ expect(entry.password).to be == password
77
+ end
78
+ end
79
+
80
+ describe 'non-ascii password' do
81
+ let(:password) { '•••p4ssw0rd!••' }
82
+ let(:comment) { '•••Some comment•••' }
83
+
84
+ around(:example) do |example|
85
+ InternetPassword.add(server, account, password, comment: comment)
86
+ example.run
87
+ InternetPassword.delete({ server: server, account: account })
88
+ end
89
+
90
+ it 'should be added to the keychain' do
91
+ entry = InternetPassword.find({ account: account })
92
+ expect(entry.keychain.filename).to be == keychain.filename
93
+ expect(entry.attributes).to include({
94
+ 'acct' => account,
95
+ 'srvr' => server,
96
+ 'icmt' => comment
97
+ })
98
+ expect(entry.password).to be == password
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../lib/security'
4
+
5
+ # rubocop:disable Style/MixinUsage
6
+ include Security
7
+ # rubocop:enable Style/MixinUsage
8
+
9
+ # This file was generated by the `rspec --init` command. Conventionally, all
10
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
11
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
12
+ # this file to always be loaded, without a need to explicitly require it in any
13
+ # files.
14
+ #
15
+ # Given that it is always loaded, you are encouraged to keep this file as
16
+ # light-weight as possible. Requiring heavyweight dependencies from this file
17
+ # will add to the boot time of your test suite on EVERY test run, even for an
18
+ # individual file that may not need all of that loaded. Instead, consider making
19
+ # a separate helper file that requires the additional dependencies and performs
20
+ # the additional setup, and require it from the spec files that actually need
21
+ # it.
22
+ #
23
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
24
+ RSpec.configure do |config|
25
+ # rspec-expectations config goes here. You can use an alternate
26
+ # assertion/expectation library such as wrong or the stdlib/minitest
27
+ # assertions if you prefer.
28
+ config.expect_with :rspec do |expectations|
29
+ # This option will default to `true` in RSpec 4. It makes the `description`
30
+ # and `failure_message` of custom matchers include text for helper methods
31
+ # defined using `chain`, e.g.:
32
+ # be_bigger_than(2).and_smaller_than(4).description
33
+ # # => "be bigger than 2 and smaller than 4"
34
+ # ...rather than:
35
+ # # => "be bigger than 2"
36
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
37
+ end
38
+
39
+ # rspec-mocks config goes here. You can use an alternate test double
40
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
41
+ config.mock_with :rspec do |mocks|
42
+ # Prevents you from mocking or stubbing a method that does not exist on
43
+ # a real object. This is generally recommended, and will default to
44
+ # `true` in RSpec 4.
45
+ mocks.verify_partial_doubles = true
46
+ end
47
+
48
+ # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
49
+ # have no way to turn it off -- the option exists only for backwards
50
+ # compatibility in RSpec 3). It causes shared context metadata to be
51
+ # inherited by the metadata hash of host groups and examples, rather than
52
+ # triggering implicit auto-inclusion in groups with matching metadata.
53
+ config.shared_context_metadata_behavior = :apply_to_host_groups
54
+
55
+ # The settings below are suggested to provide a good initial experience
56
+ # with RSpec, but feel free to customize to your heart's content.
57
+ # # This allows you to limit a spec run to individual examples or groups
58
+ # # you care about by tagging them with `:focus` metadata. When nothing
59
+ # # is tagged with `:focus`, all examples get run. RSpec also provides
60
+ # # aliases for `it`, `describe`, and `context` that include `:focus`
61
+ # # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
62
+ # config.filter_run_when_matching :focus
63
+ #
64
+ # # Allows RSpec to persist some state between runs in order to support
65
+ # # the `--only-failures` and `--next-failure` CLI options. We recommend
66
+ # # you configure your source control system to ignore this file.
67
+ # config.example_status_persistence_file_path = "spec/examples.txt"
68
+ #
69
+ # # Limits the available syntax to the non-monkey patched syntax that is
70
+ # # recommended. For more details, see:
71
+ # # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
72
+ # # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
73
+ # # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
74
+ # config.disable_monkey_patching!
75
+ #
76
+ # # This setting enables warnings. It's recommended, but in some cases may
77
+ # # be too noisy due to issues in dependencies.
78
+ # config.warnings = true
79
+ #
80
+ # # Many RSpec users commonly either run the entire suite or an individual
81
+ # # file, and it's useful to allow more verbose output when running an
82
+ # # individual spec file.
83
+ # if config.files_to_run.one?
84
+ # # Use the documentation formatter for detailed output,
85
+ # # unless a formatter has already been configured
86
+ # # (e.g. via a command-line flag).
87
+ # config.default_formatter = "doc"
88
+ # end
89
+ #
90
+ # # Print the 10 slowest examples and example groups at the
91
+ # # end of the spec run, to help surface which specs are running
92
+ # # particularly slow.
93
+ # config.profile_examples = 10
94
+ #
95
+ # # Run specs in random order to surface order dependencies. If you find an
96
+ # # order dependency and want to debug it, you can fix the order by providing
97
+ # # the seed, which is printed after each run.
98
+ # # --seed 1234
99
+ # config.order = :random
100
+ #
101
+ # # Seed global randomization in this process using the `--seed` CLI option.
102
+ # # Setting this allows you to use `--seed` to deterministically reproduce
103
+ # # test failures related to randomization by passing the same `--seed` value
104
+ # # as the one that triggered the failure.
105
+ # Kernel.srand config.seed
106
+ end
metadata CHANGED
@@ -1,82 +1,124 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: security
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
5
- prerelease:
4
+ version: 0.1.5
6
5
  platform: ruby
7
6
  authors:
8
- - Mattt Thompson
9
- autorequire:
7
+ - Josh Holtz
8
+ - Mattt
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-07-21 00:00:00.000000000Z
12
+ date: 2021-03-25 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '12.3'
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 12.3.3
24
+ type: :development
25
+ prerelease: false
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ requirements:
28
+ - - "~>"
29
+ - !ruby/object:Gem::Version
30
+ version: '12.3'
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 12.3.3
14
34
  - !ruby/object:Gem::Dependency
15
35
  name: rspec
16
- requirement: &70146585209620 !ruby/object:Gem::Requirement
17
- none: false
36
+ requirement: !ruby/object:Gem::Requirement
18
37
  requirements:
19
- - - ~>
38
+ - - ">="
20
39
  - !ruby/object:Gem::Version
21
- version: 0.6.1
40
+ version: '0'
22
41
  type: :development
23
42
  prerelease: false
24
- version_requirements: *70146585209620
43
+ version_requirements: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
25
48
  - !ruby/object:Gem::Dependency
26
- name: rake
27
- requirement: &70146585208880 !ruby/object:Gem::Requirement
28
- none: false
49
+ name: rspec-github
50
+ requirement: !ruby/object:Gem::Requirement
29
51
  requirements:
30
- - - ~>
52
+ - - ">="
31
53
  - !ruby/object:Gem::Version
32
- version: 0.9.2
54
+ version: '0'
33
55
  type: :development
34
56
  prerelease: false
35
- version_requirements: *70146585208880
36
- description: Library for interacting with the Mac OS X Keychain
37
- email: m@mattt.me
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rubocop
64
+ requirement: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ type: :development
70
+ prerelease: false
71
+ version_requirements: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ description:
77
+ email: me@joshholtz.com
38
78
  executables: []
39
79
  extensions: []
40
80
  extra_rdoc_files: []
41
81
  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:
82
+ - "./Gemfile"
83
+ - "./Gemfile.lock"
84
+ - "./LICENSE.md"
85
+ - "./README.md"
86
+ - "./Rakefile"
87
+ - "./lib/security.rb"
88
+ - "./lib/security/certificate.rb"
89
+ - "./lib/security/keychain.rb"
90
+ - "./lib/security/password.rb"
91
+ - "./lib/security/version.rb"
92
+ - "./security.gemspec"
93
+ - spec/certificate_spec.rb
94
+ - spec/keychain_spec.rb
95
+ - spec/password_spec.rb
96
+ - spec/spec_helper.rb
97
+ homepage: https://github.com/fastlane-community/security
98
+ licenses:
99
+ - MIT
100
+ metadata: {}
101
+ post_install_message:
55
102
  rdoc_options: []
56
103
  require_paths:
57
104
  - lib
58
105
  required_ruby_version: !ruby/object:Gem::Requirement
59
- none: false
60
106
  requirements:
61
- - - ! '>='
107
+ - - ">="
62
108
  - !ruby/object:Gem::Version
63
- version: '0'
64
- segments:
65
- - 0
66
- hash: -2439538555440614710
109
+ version: 2.4.0
67
110
  required_rubygems_version: !ruby/object:Gem::Requirement
68
- none: false
69
111
  requirements:
70
- - - ! '>='
112
+ - - ">="
71
113
  - !ruby/object:Gem::Version
72
114
  version: '0'
73
- segments:
74
- - 0
75
- hash: -2439538555440614710
76
115
  requirements: []
77
- rubyforge_project:
78
- rubygems_version: 1.8.15
79
- signing_key:
80
- specification_version: 3
81
- summary: Security
82
- test_files: []
116
+ rubygems_version: 3.0.3
117
+ signing_key:
118
+ specification_version: 4
119
+ summary: Interact with the macOS Keychain
120
+ test_files:
121
+ - spec/certificate_spec.rb
122
+ - spec/keychain_spec.rb
123
+ - spec/password_spec.rb
124
+ - spec/spec_helper.rb