trocla 0.2.3 → 0.3.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 +4 -4
- data/.travis.yml +2 -1
- data/CHANGELOG.md +9 -0
- data/Gemfile +18 -1
- data/README.md +5 -0
- data/bin/trocla +16 -12
- data/ext/redhat/rubygem-trocla.spec +6 -4
- data/lib/VERSION +2 -2
- data/lib/trocla.rb +24 -4
- data/lib/trocla/formats.rb +11 -0
- data/lib/trocla/formats/bcrypt.rb +2 -1
- data/lib/trocla/formats/x509.rb +1 -0
- data/lib/trocla/store.rb +6 -0
- data/lib/trocla/stores/moneta.rb +4 -0
- data/lib/trocla/util.rb +4 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/trocla/formats/x509_spec.rb +6 -4
- data/spec/trocla/util_spec.rb +8 -0
- data/spec/trocla_spec.rb +190 -103
- data/trocla.gemspec +35 -35
- metadata +3 -3
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 0fe321c3e5f61203499ad978f32fef9b9617bf54
         | 
| 4 | 
            +
              data.tar.gz: 276a6191e0342e7d26c185a06b383f357483b300
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: cda445d5bab3d8b96a56990b2b9e447869a44e02bb4f28ca9d29ffce8578aa1e1cb4d5dedb7bec0e0102cc42416fed6361f1c9ea276c2b9fa2b1b7e1ab99698a
         | 
| 7 | 
            +
              data.tar.gz: a59f1905c9877eda6ff3614b84f50e6598c75be420ba78c4e324f0b5c6c72584efda35a711477c35571aeac804de4e8f6ff1a3de80e3f2f220a825ce0d52056d
         | 
    
        data/.travis.yml
    CHANGED
    
    
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,5 +1,14 @@ | |
| 1 1 | 
             
            # Changelog
         | 
| 2 2 |  | 
| 3 | 
            +
            ## to 0.3.0
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            * Add open method to be able to immediately close a trocla store after using it - thanks martinpfeiffer
         | 
| 6 | 
            +
            * Add typesafe charset - thanks hggh
         | 
| 7 | 
            +
            * Support cost option for bcrypt
         | 
| 8 | 
            +
            * address concurrency corner cases, when 2 concurrent threads or even processes
         | 
| 9 | 
            +
              are currently calculating the same (expensive) format.
         | 
| 10 | 
            +
            * parse additional options on cli (#39 & #46) - thanks fe80
         | 
| 11 | 
            +
             | 
| 3 12 | 
             
            ## to 0.2.3
         | 
| 4 13 |  | 
| 5 14 | 
             
            1. Add extended CA validity profiles
         | 
    
        data/Gemfile
    CHANGED
    
    | @@ -3,12 +3,22 @@ source "http://rubygems.org" | |
| 3 3 | 
             
            # Example:
         | 
| 4 4 | 
             
            #   gem "activesupport", ">= 2.3.5"
         | 
| 5 5 |  | 
| 6 | 
            +
            if RUBY_VERSION.to_f <= 2.2
         | 
| 7 | 
            +
              gem 'rack', '< 2.0'
         | 
| 8 | 
            +
            end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            if RUBY_VERSION.to_f < 2.1
         | 
| 11 | 
            +
              gem 'nokogiri', '< 1.7'
         | 
| 12 | 
            +
            end
         | 
| 13 | 
            +
             | 
| 6 14 | 
             
            if RUBY_VERSION.to_f > 1.8
         | 
| 7 15 | 
             
              gem "moneta"
         | 
| 8 16 | 
             
              gem "highline"
         | 
| 9 17 | 
             
            else
         | 
| 10 18 | 
             
              gem "moneta", "~> 0.7.20"
         | 
| 11 19 | 
             
              gem "highline", "~> 1.6.2"
         | 
| 20 | 
            +
              gem 'rake', '< 11'
         | 
| 21 | 
            +
              gem 'git', '< 1.3'
         | 
| 12 22 | 
             
            end
         | 
| 13 23 |  | 
| 14 24 | 
             
            if defined?(RUBY_ENGINE) && (RUBY_ENGINE == 'jruby')
         | 
| @@ -22,7 +32,14 @@ group :development do | |
| 22 32 | 
             
              if RUBY_VERSION.to_f > 1.8
         | 
| 23 33 | 
             
                gem "rspec"
         | 
| 24 34 | 
             
                gem "rdoc"
         | 
| 25 | 
            -
                 | 
| 35 | 
            +
                if RUBY_VERSION.to_f < 2.2
         | 
| 36 | 
            +
                  gem 'jeweler', '< 2.2'
         | 
| 37 | 
            +
                else
         | 
| 38 | 
            +
                  gem "jeweler"
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
                if RUBY_VERSION.to_f < 2.0
         | 
| 41 | 
            +
                  gem 'public_suffix', '~> 1.4.6'
         | 
| 42 | 
            +
                end
         | 
| 26 43 | 
             
              else
         | 
| 27 44 | 
             
                gem "rspec", "~> 2.4"
         | 
| 28 45 | 
             
                gem "rdoc", "~> 3.8"
         | 
    
        data/README.md
    CHANGED
    
    | @@ -168,6 +168,11 @@ options to work properly. These are documented here: | |
| 168 168 | 
             
            Password hashes for PostgreSQL servers. Requires the option `username` to be set
         | 
| 169 169 | 
             
            to the username to which the password will be assigned.
         | 
| 170 170 |  | 
| 171 | 
            +
            ### bcrypt
         | 
| 172 | 
            +
             | 
| 173 | 
            +
            You are able to tune the [cost factor of bcrypt](https://github.com/codahale/bcrypt-ruby#cost-factors) by passing the option `cost`.
         | 
| 174 | 
            +
            Note: ruby bcrypt does not support a [cost > 31](https://github.com/codahale/bcrypt-ruby/blob/master/lib/bcrypt/password.rb#L45).
         | 
| 175 | 
            +
             | 
| 171 176 | 
             
            ### x509
         | 
| 172 177 |  | 
| 173 178 | 
             
            This format takes a set of additional options. Required are:
         | 
    
        data/bin/trocla
    CHANGED
    
    | @@ -47,18 +47,20 @@ OptionParser.new do |opts| | |
| 47 47 | 
             
            end.parse!
         | 
| 48 48 |  | 
| 49 49 | 
             
            def create(options)
         | 
| 50 | 
            -
              Trocla.new(options.delete(:config_file)).password(
         | 
| 50 | 
            +
              [ Trocla.new(options.delete(:config_file)).password(
         | 
| 51 51 | 
             
                options.delete(:trocla_key),
         | 
| 52 52 | 
             
                options.delete(:trocla_format),
         | 
| 53 53 | 
             
                options.merge(YAML.load(options.delete(:other_options).shift.to_s)||{})
         | 
| 54 | 
            -
              )
         | 
| 54 | 
            +
              ) , 0 ]
         | 
| 55 55 | 
             
            end
         | 
| 56 56 |  | 
| 57 57 | 
             
            def get(options)
         | 
| 58 | 
            -
              Trocla.new(options.delete(:config_file)).get_password(
         | 
| 58 | 
            +
              res = Trocla.new(options.delete(:config_file)).get_password(
         | 
| 59 59 | 
             
                options.delete(:trocla_key),
         | 
| 60 | 
            -
                options.delete(:trocla_format)
         | 
| 60 | 
            +
                options.delete(:trocla_format),
         | 
| 61 | 
            +
                options.merge(YAML.load(options.delete(:other_options).shift.to_s)||{})
         | 
| 61 62 | 
             
              )
         | 
| 63 | 
            +
              [ res, res.nil? ? 1 : 0 ]
         | 
| 62 64 | 
             
            end
         | 
| 63 65 | 
             
            def set(options)
         | 
| 64 66 | 
             
              if options.delete(:ask_password)
         | 
| @@ -67,7 +69,7 @@ def set(options) | |
| 67 69 | 
             
                pwd2 = ask('Repeat password: ') { |q| q.echo = 'x' }.to_s
         | 
| 68 70 | 
             
                unless password == pwd2
         | 
| 69 71 | 
             
                  STDERR.puts 'Passwords did not match, exiting!'
         | 
| 70 | 
            -
                   | 
| 72 | 
            +
                  return [ nil, 1 ]
         | 
| 71 73 | 
             
                end
         | 
| 72 74 | 
             
              else
         | 
| 73 75 | 
             
                password = options.delete(:password) || STDIN.read.chomp
         | 
| @@ -78,29 +80,29 @@ def set(options) | |
| 78 80 | 
             
              value = if no_format
         | 
| 79 81 | 
             
                password
         | 
| 80 82 | 
             
              else
         | 
| 81 | 
            -
                trocla.formats(format).format(password, options.delete(:other_options).shift.to_s)
         | 
| 83 | 
            +
                trocla.formats(format).format(password, (YAML.load(options.delete(:other_options).shift.to_s)||{}))
         | 
| 82 84 | 
             
              end
         | 
| 83 85 | 
             
              trocla.set_password(
         | 
| 84 86 | 
             
                options.delete(:trocla_key),
         | 
| 85 87 | 
             
                format,
         | 
| 86 88 | 
             
                value
         | 
| 87 89 | 
             
              )
         | 
| 88 | 
            -
              ''
         | 
| 90 | 
            +
              [ '', 0 ]
         | 
| 89 91 | 
             
            end
         | 
| 90 92 |  | 
| 91 93 | 
             
            def reset(options)
         | 
| 92 | 
            -
              Trocla.new(options.delete(:config_file)).reset_password(
         | 
| 94 | 
            +
              [ Trocla.new(options.delete(:config_file)).reset_password(
         | 
| 93 95 | 
             
                options.delete(:trocla_key),
         | 
| 94 96 | 
             
                options.delete(:trocla_format),
         | 
| 95 97 | 
             
                options.merge(YAML.load(options.delete(:other_options).shift.to_s)||{})
         | 
| 96 | 
            -
              )
         | 
| 98 | 
            +
              ), 0 ]
         | 
| 97 99 | 
             
            end
         | 
| 98 100 |  | 
| 99 101 | 
             
            def delete(options)
         | 
| 100 | 
            -
              Trocla.new(options.delete(:config_file)).delete_password(
         | 
| 102 | 
            +
              [ Trocla.new(options.delete(:config_file)).delete_password(
         | 
| 101 103 | 
             
                options.delete(:trocla_key),
         | 
| 102 104 | 
             
                options.delete(:trocla_format)
         | 
| 103 | 
            -
              )
         | 
| 105 | 
            +
              ), 0 ]
         | 
| 104 106 | 
             
            end
         | 
| 105 107 |  | 
| 106 108 | 
             
            def formats(options)
         | 
| @@ -125,7 +127,8 @@ if (action=ARGV.shift) && actions.include?(action) | |
| 125 127 | 
             
                options[:other_options] = ARGV
         | 
| 126 128 | 
             
                check_format(options[:trocla_format]) unless ['delete','formats'].include?(action)
         | 
| 127 129 | 
             
                begin
         | 
| 128 | 
            -
                   | 
| 130 | 
            +
                  result, excode = send(action,options)
         | 
| 131 | 
            +
                  if result
         | 
| 129 132 | 
             
                    puts result.is_a?(String) ? result : result.inspect
         | 
| 130 133 | 
             
                  end
         | 
| 131 134 | 
             
                rescue Exception => e
         | 
| @@ -136,6 +139,7 @@ if (action=ARGV.shift) && actions.include?(action) | |
| 136 139 | 
             
                  raise e if options[:trace]
         | 
| 137 140 | 
             
                  exit 1
         | 
| 138 141 | 
             
                end
         | 
| 142 | 
            +
                exit excode.nil? ? 0 : excode
         | 
| 139 143 | 
             
            else
         | 
| 140 144 | 
             
                STDERR.puts "Please supply one of the following actions: #{actions.join(', ')}"
         | 
| 141 145 | 
             
                STDERR.puts "Use #{$0} --help to get a list of options for these actions"
         | 
| @@ -2,7 +2,7 @@ | |
| 2 2 | 
             
            %global gem_name trocla
         | 
| 3 3 |  | 
| 4 4 | 
             
            Name: rubygem-%{gem_name}
         | 
| 5 | 
            -
            Version: 0. | 
| 5 | 
            +
            Version: 0.3.0
         | 
| 6 6 | 
             
            Release: 1%{?dist}
         | 
| 7 7 | 
             
            Summary: Trocla a simple password generator and storage
         | 
| 8 8 | 
             
            Group: Development/Languages
         | 
| @@ -74,9 +74,11 @@ chmod a+x %{buildroot}%{gem_instdir}/bin/%{gem_name} | |
| 74 74 |  | 
| 75 75 | 
             
            cat <<EOF > %{buildroot}/%{_sysconfdir}/%{gem_name}rc.yaml
         | 
| 76 76 | 
             
            ---
         | 
| 77 | 
            -
             | 
| 78 | 
            -
             | 
| 79 | 
            -
             | 
| 77 | 
            +
            store: :moneta
         | 
| 78 | 
            +
            store_options:
         | 
| 79 | 
            +
              adapter: :YAML
         | 
| 80 | 
            +
              adapter_options:
         | 
| 81 | 
            +
                :file: '%{_sharedstatedir}/%{gem_name}/%{gem_name}_data.yaml'
         | 
| 80 82 | 
             
            EOF
         | 
| 81 83 |  | 
| 82 84 | 
             
            # Run the test suite
         | 
    
        data/lib/VERSION
    CHANGED
    
    
    
        data/lib/trocla.rb
    CHANGED
    
    | @@ -13,6 +13,17 @@ class Trocla | |
| 13 13 | 
             
                end
         | 
| 14 14 | 
             
              end
         | 
| 15 15 |  | 
| 16 | 
            +
              def self.open(config_file=nil)
         | 
| 17 | 
            +
                trocla = Trocla.new(config_file)
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                if block_given?
         | 
| 20 | 
            +
                  yield trocla
         | 
| 21 | 
            +
                  trocla.close
         | 
| 22 | 
            +
                else
         | 
| 23 | 
            +
                  trocla
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
             | 
| 16 27 | 
             
              def password(key,format,options={})
         | 
| 17 28 | 
             
                # respect a default profile, but let the
         | 
| 18 29 | 
             
                # profiles win over the default options
         | 
| @@ -35,10 +46,15 @@ class Trocla | |
| 35 46 | 
             
                elsif !options['random'] && plain_pwd.nil?
         | 
| 36 47 | 
             
                  raise "Password must be present as plaintext if you don't want a random password"
         | 
| 37 48 | 
             
                end
         | 
| 38 | 
            -
                 | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 49 | 
            +
                pwd = self.formats(format).format(plain_pwd,options)
         | 
| 50 | 
            +
                # it's possible that meanwhile another thread/process was faster in
         | 
| 51 | 
            +
                # formating the password. But we want todo that second lookup
         | 
| 52 | 
            +
                # only for expensive formats
         | 
| 53 | 
            +
                if self.formats(format).expensive?
         | 
| 54 | 
            +
                  get_password(key,format,options) || set_password(key, format, pwd, options)
         | 
| 55 | 
            +
                else
         | 
| 56 | 
            +
                  set_password(key, format, pwd, options)
         | 
| 57 | 
            +
                end
         | 
| 42 58 | 
             
              end
         | 
| 43 59 |  | 
| 44 60 | 
             
              def get_password(key, format, options={})
         | 
| @@ -78,6 +94,10 @@ class Trocla | |
| 78 94 | 
             
                @config ||= read_config
         | 
| 79 95 | 
             
              end
         | 
| 80 96 |  | 
| 97 | 
            +
              def close
         | 
| 98 | 
            +
                store.close
         | 
| 99 | 
            +
              end
         | 
| 100 | 
            +
             | 
| 81 101 | 
             
              private
         | 
| 82 102 | 
             
              def store
         | 
| 83 103 | 
             
                @store ||= build_store
         | 
    
        data/lib/trocla/formats.rb
    CHANGED
    
    | @@ -8,6 +8,17 @@ class Trocla::Formats | |
| 8 8 | 
             
                def render(output,render_options={})
         | 
| 9 9 | 
             
                  output
         | 
| 10 10 | 
             
                end
         | 
| 11 | 
            +
                def expensive?
         | 
| 12 | 
            +
                  self.class.expensive?
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
                class << self
         | 
| 15 | 
            +
                  def expensive(is_expensive)
         | 
| 16 | 
            +
                    @expensive = is_expensive
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
                  def expensive?
         | 
| 19 | 
            +
                    @expensive == true
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
                end
         | 
| 11 22 | 
             
              end
         | 
| 12 23 |  | 
| 13 24 | 
             
              class << self
         | 
| @@ -1,6 +1,7 @@ | |
| 1 1 | 
             
            class Trocla::Formats::Bcrypt < Trocla::Formats::Base
         | 
| 2 | 
            +
              expensive true
         | 
| 2 3 | 
             
              require 'bcrypt'
         | 
| 3 4 | 
             
              def format(plain_password,options={})
         | 
| 4 | 
            -
                BCrypt::Password.create(plain_password).to_s
         | 
| 5 | 
            +
                BCrypt::Password.create(plain_password, :cost => options['cost']||BCrypt::Engine.cost).to_s
         | 
| 5 6 | 
             
              end
         | 
| 6 7 | 
             
            end
         | 
    
        data/lib/trocla/formats/x509.rb
    CHANGED
    
    | @@ -1,5 +1,6 @@ | |
| 1 1 | 
             
            require 'openssl'
         | 
| 2 2 | 
             
            class Trocla::Formats::X509 < Trocla::Formats::Base
         | 
| 3 | 
            +
              expensive true
         | 
| 3 4 | 
             
              def format(plain_password,options={})
         | 
| 4 5 |  | 
| 5 6 | 
             
                if plain_password.match(/-----BEGIN RSA PRIVATE KEY-----.*-----END RSA PRIVATE KEY-----.*-----BEGIN CERTIFICATE-----.*-----END CERTIFICATE-----/m)
         | 
    
        data/lib/trocla/store.rb
    CHANGED
    
    | @@ -6,6 +6,12 @@ class Trocla::Store | |
| 6 6 | 
             
                @trocla = trocla
         | 
| 7 7 | 
             
              end
         | 
| 8 8 |  | 
| 9 | 
            +
              # closes the store
         | 
| 10 | 
            +
              # when called do whatever "closes" your
         | 
| 11 | 
            +
              # store, e.g. close database connections.
         | 
| 12 | 
            +
              def close
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
             | 
| 9 15 | 
             
              # should return value for key & format
         | 
| 10 16 | 
             
              # returns nil if nothing or a nil value
         | 
| 11 17 | 
             
              # was found.
         | 
    
        data/lib/trocla/stores/moneta.rb
    CHANGED
    
    
    
        data/lib/trocla/util.rb
    CHANGED
    
    | @@ -24,6 +24,7 @@ class Trocla | |
| 24 24 | 
             
                        'numeric'      => numeric,
         | 
| 25 25 | 
             
                        'hexadecimal'  => hexadecimal,
         | 
| 26 26 | 
             
                        'consolesafe'  => consolesafe,
         | 
| 27 | 
            +
                        'typesafe'     => typesafe,
         | 
| 27 28 | 
             
                      }
         | 
| 28 29 | 
             
                      h.each { |k, v| h[k] = v.uniq }
         | 
| 29 30 | 
             
                    end
         | 
| @@ -50,6 +51,9 @@ class Trocla | |
| 50 51 | 
             
                  def numeric
         | 
| 51 52 | 
             
                    @numeric ||= ('0'..'9').to_a
         | 
| 52 53 | 
             
                  end
         | 
| 54 | 
            +
                  def typesafe
         | 
| 55 | 
            +
                    @typesafe ||= ('a'..'x').to_a - ['i'] - ['l'] + ('A'..'X').to_a - ['I'] - ['L'] + ('1'..'9').to_a
         | 
| 56 | 
            +
                  end
         | 
| 53 57 | 
             
                  def special_chars
         | 
| 54 58 | 
             
                    @special_chars ||= "*()&![]{}-".split(//)
         | 
| 55 59 | 
             
                  end
         | 
    
        data/spec/spec_helper.rb
    CHANGED
    
    | @@ -282,3 +282,9 @@ end | |
| 282 282 | 
             
            def remove_yaml_store
         | 
| 283 283 | 
             
              File.unlink(trocla_yaml_file)
         | 
| 284 284 | 
             
            end
         | 
| 285 | 
            +
            class Trocla::Formats::Sleep < Trocla::Formats::Base
         | 
| 286 | 
            +
              def format(plain_password,options={})
         | 
| 287 | 
            +
                sleep options['sleep'] ||= 0
         | 
| 288 | 
            +
                (options['sleep'] + 1 ).times.collect{ plain_password }.join(' ')
         | 
| 289 | 
            +
              end
         | 
| 290 | 
            +
            end
         | 
| @@ -242,12 +242,12 @@ describe "Trocla::Format::X509" do | |
| 242 242 | 
             
                  expect(valid_cert.issuer.to_s).to eq(ca2.subject.to_s)
         | 
| 243 243 | 
             
                  expect((Date.parse(valid_cert.not_after.localtime.to_s) - Date.today).to_i).to eq(365)
         | 
| 244 244 | 
             
                  # workaround broken openssl
         | 
| 245 | 
            -
                  if %x{openssl version}  | 
| 246 | 
            -
                    expect(verify([@ca,ca2],valid_cert)).to be true
         | 
| 247 | 
            -
                  else
         | 
| 245 | 
            +
                  if Gem::Version.new(%x{openssl version}.split(' ')[1]) < Gem::Version.new('1.0.2')
         | 
| 248 246 | 
             
                    skip_for(:engine => 'ruby',:reason => 'NameConstraints verification is broken on older openssl versions https://rt.openssl.org/Ticket/Display.html?id=3562') do
         | 
| 249 247 | 
             
                      expect(verify([@ca,ca2],valid_cert)).to be true
         | 
| 250 248 | 
             
                    end
         | 
| 249 | 
            +
                  else
         | 
| 250 | 
            +
                    expect(verify([@ca,ca2],valid_cert)).to be true
         | 
| 251 251 | 
             
                  end
         | 
| 252 252 |  | 
| 253 253 | 
             
                  false_cert_str = @trocla.password('myfalseexamplecert','x509', {
         | 
| @@ -311,7 +311,9 @@ describe "Trocla::Format::X509" do | |
| 311 311 | 
             
                  # https://stackoverflow.com/questions/13747212/determine-key-size-from-public-key-pem-format
         | 
| 312 312 | 
             
                  expect(cert.public_key.n.num_bytes * 8).to eq(2048)
         | 
| 313 313 | 
             
                  expect(verify(@ca,cert)).to be true
         | 
| 314 | 
            -
                   | 
| 314 | 
            +
                  skip_for(:engine => 'jruby',:reason => 'subjectAltName represenation is broken in jruby-openssl -> https://github.com/jruby/jruby-openssl/pull/123') do
         | 
| 315 | 
            +
                    expect(cert.extensions.find{|e| e.oid == 'subjectAltName' }.value).to eq('DNS:www.test, DNS:test, DNS:test1, DNS:test2, DNS:test3')
         | 
| 316 | 
            +
                  end
         | 
| 315 317 |  | 
| 316 318 | 
             
                  expect(cert.extensions.find{|e| e.oid == 'basicConstraints' }.value).to eq('CA:FALSE')
         | 
| 317 319 | 
             
                  ku = cert.extensions.find{|e| e.oid == 'keyUsage' }.value
         | 
    
        data/spec/trocla/util_spec.rb
    CHANGED
    
    | @@ -36,6 +36,14 @@ describe "Trocla::Util" do | |
| 36 36 | 
             
                end
         | 
| 37 37 | 
             
              end
         | 
| 38 38 |  | 
| 39 | 
            +
              describe :typesafe_generator do
         | 
| 40 | 
            +
                10.times.each do |i|
         | 
| 41 | 
            +
                  it "creates random typesafe password #{i}" do
         | 
| 42 | 
            +
                    expect(Trocla::Util.random_str(12, 'typesafe')).to match(/^[1-9a-hj-km-xA-HJ-KM-X]{12}$/)
         | 
| 43 | 
            +
                  end
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
             | 
| 39 47 | 
             
              describe :salt do
         | 
| 40 48 | 
             
                10.times.each do |i|
         | 
| 41 49 | 
             
                  it "contains only characters and numbers #{i}" do
         | 
    
        data/spec/trocla_spec.rb
    CHANGED
    
    | @@ -4,144 +4,231 @@ describe "Trocla" do | |
| 4 4 |  | 
| 5 5 | 
             
              before(:each) do
         | 
| 6 6 | 
             
                expect_any_instance_of(Trocla).to receive(:read_config).and_return(test_config)
         | 
| 7 | 
            -
                @trocla = Trocla.new
         | 
| 8 7 | 
             
              end
         | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
                   | 
| 8 | 
            +
              context 'in normal usage with' do
         | 
| 9 | 
            +
                before(:each) do
         | 
| 10 | 
            +
                  @trocla = Trocla.new
         | 
| 11 | 
            +
                  @trocla.password('init','plain')
         | 
| 13 12 | 
             
                end
         | 
| 14 13 |  | 
| 15 | 
            -
                 | 
| 16 | 
            -
                   | 
| 17 | 
            -
             | 
| 14 | 
            +
                describe "password" do
         | 
| 15 | 
            +
                  it "generates random passwords by default" do
         | 
| 16 | 
            +
                    expect(@trocla.password('random1','plain')).not_to eq(@trocla.password('random2','plain'))
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  it "generates passwords of length #{default_config['options']['length']}" do
         | 
| 20 | 
            +
                    expect(@trocla.password('random1','plain').length).to eq(default_config['options']['length'])
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  Trocla::Formats.all.each do |format|
         | 
| 24 | 
            +
                    describe "#{format} password format" do
         | 
| 25 | 
            +
                      it "retursn a password hashed in the #{format} format" do
         | 
| 26 | 
            +
                        expect(@trocla.password('some_test',format,format_options[format])).not_to be_empty
         | 
| 27 | 
            +
                      end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                      it "returns the same hashed for the #{format} format on multiple invocations" do
         | 
| 30 | 
            +
                        expect(round1=@trocla.password('some_test',format,format_options[format])).not_to be_empty
         | 
| 31 | 
            +
                        expect(@trocla.password('some_test',format,format_options[format])).to eq(round1)
         | 
| 32 | 
            +
                      end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                      it "also stores the plain password by default" do
         | 
| 35 | 
            +
                        pwd = @trocla.password('some_test','plain')
         | 
| 36 | 
            +
                        expect(pwd).not_to be_empty
         | 
| 37 | 
            +
                        expect(pwd.length).to eq(16)
         | 
| 38 | 
            +
                      end
         | 
| 39 | 
            +
                    end
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                  Trocla::Formats.all.reject{|f| f == 'plain' }.each do |format|
         | 
| 43 | 
            +
                    it "raises an exception if not a random password is asked but plain password is not present for format #{format}" do
         | 
| 44 | 
            +
                      expect{@trocla.password('not_random',format, 'random' => false)}.to raise_error(/Password must be present as plaintext/)
         | 
| 45 | 
            +
                    end
         | 
| 46 | 
            +
                  end
         | 
| 18 47 |  | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 48 | 
            +
                  describe 'with profiles' do
         | 
| 49 | 
            +
                    it 'raises an exception on unknown profile' do
         | 
| 50 | 
            +
                      expect{@trocla.password('no profile known','plain',
         | 
| 51 | 
            +
                        'profiles' => 'unknown_profile') }.to raise_error(/No such profile unknown_profile defined/)
         | 
| 23 52 | 
             
                    end
         | 
| 24 53 |  | 
| 25 | 
            -
                    it  | 
| 26 | 
            -
                       | 
| 27 | 
            -
                      expect( | 
| 54 | 
            +
                    it 'takes a profile and merge its options' do
         | 
| 55 | 
            +
                      pwd = @trocla.password('some_test','plain', 'profiles' => 'rootpw')
         | 
| 56 | 
            +
                      expect(pwd).not_to be_empty
         | 
| 57 | 
            +
                      expect(pwd.length).to eq(32)
         | 
| 58 | 
            +
                      expect(pwd).to_not match(/[={}\[\]\?%\*()&!]+/)
         | 
| 28 59 | 
             
                    end
         | 
| 29 60 |  | 
| 30 | 
            -
                    it  | 
| 31 | 
            -
                      pwd = @trocla.password(' | 
| 61 | 
            +
                    it 'is possible to combine profiles but first profile wins' do
         | 
| 62 | 
            +
                      pwd = @trocla.password('some_test1','plain', 'profiles' => ['rootpw','login'])
         | 
| 63 | 
            +
                      expect(pwd).not_to be_empty
         | 
| 64 | 
            +
                      expect(pwd.length).to eq(32)
         | 
| 65 | 
            +
                      expect(pwd).not_to match(/[={}\[\]\?%\*()&!]+/)
         | 
| 66 | 
            +
                    end
         | 
| 67 | 
            +
                    it 'is possible to combine profiles but first profile wins 2' do
         | 
| 68 | 
            +
                      pwd = @trocla.password('some_test2','plain', 'profiles' => ['login','mysql'])
         | 
| 32 69 | 
             
                      expect(pwd).not_to be_empty
         | 
| 33 70 | 
             
                      expect(pwd.length).to eq(16)
         | 
| 71 | 
            +
                      expect(pwd).not_to match(/[={}\[\]\?%\*()&!]+/)
         | 
| 72 | 
            +
                    end
         | 
| 73 | 
            +
                    it 'is possible to combine profiles but first profile wins 3' do
         | 
| 74 | 
            +
                      pwd = @trocla.password('some_test3','plain', 'profiles' => ['mysql','login'])
         | 
| 75 | 
            +
                      expect(pwd).not_to be_empty
         | 
| 76 | 
            +
                      expect(pwd.length).to eq(32)
         | 
| 77 | 
            +
                      expect(pwd).to match(/[+%\/@=\?_.,:]+/)
         | 
| 34 78 | 
             
                    end
         | 
| 35 79 | 
             
                  end
         | 
| 36 80 | 
             
                end
         | 
| 37 81 |  | 
| 38 | 
            -
                 | 
| 39 | 
            -
                  it " | 
| 40 | 
            -
                    expect | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 82 | 
            +
                describe "set_password" do
         | 
| 83 | 
            +
                  it "resets hashed passwords on a new plain password" do
         | 
| 84 | 
            +
                    expect(@trocla.password('set_test','mysql')).not_to be_empty
         | 
| 85 | 
            +
                    expect(@trocla.get_password('set_test','mysql')).not_to be_nil
         | 
| 86 | 
            +
                    expect(old_plain=@trocla.password('set_test','mysql')).not_to be_empty
         | 
| 43 87 |  | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
                    expect{@trocla.password('no profile known','plain',
         | 
| 47 | 
            -
                      'profiles' => 'unknown_profile') }.to raise_error(/No such profile unknown_profile defined/)
         | 
| 88 | 
            +
                    expect(@trocla.set_password('set_test','plain','foobar')).not_to eq(old_plain)
         | 
| 89 | 
            +
                    expect(@trocla.get_password('set_test','mysql')).to be_nil
         | 
| 48 90 | 
             
                  end
         | 
| 49 91 |  | 
| 50 | 
            -
                  it  | 
| 51 | 
            -
                     | 
| 52 | 
            -
                    expect( | 
| 53 | 
            -
                    expect( | 
| 54 | 
            -
                    expect(pwd).to_not match(/[={}\[\]\?%\*()&!]+/)
         | 
| 55 | 
            -
                  end
         | 
| 92 | 
            +
                  it "otherwise updates only the hash" do
         | 
| 93 | 
            +
                    expect(mysql = @trocla.password('set_test2','mysql')).not_to be_empty
         | 
| 94 | 
            +
                    expect(md5crypt = @trocla.password('set_test2','md5crypt')).not_to be_empty
         | 
| 95 | 
            +
                    expect(plain = @trocla.get_password('set_test2','plain')).not_to be_empty
         | 
| 56 96 |  | 
| 57 | 
            -
             | 
| 58 | 
            -
                     | 
| 59 | 
            -
                    expect( | 
| 60 | 
            -
                    expect( | 
| 61 | 
            -
                    expect(pwd).not_to match(/[={}\[\]\?%\*()&!]+/)
         | 
| 62 | 
            -
                  end
         | 
| 63 | 
            -
                  it 'is possible to combine profiles but first profile wins 2' do
         | 
| 64 | 
            -
                    pwd = @trocla.password('some_test','plain', 'profiles' => ['login','mysql'])
         | 
| 65 | 
            -
                    expect(pwd).not_to be_empty
         | 
| 66 | 
            -
                    expect(pwd.length).to eq(16)
         | 
| 67 | 
            -
                    expect(pwd).not_to match(/[={}\[\]\?%\*()&!]+/)
         | 
| 68 | 
            -
                  end
         | 
| 69 | 
            -
                  it 'is possible to combine profiles but first profile wins 3' do
         | 
| 70 | 
            -
                    pwd = @trocla.password('some_test','plain', 'profiles' => ['mysql','login'])
         | 
| 71 | 
            -
                    expect(pwd).not_to be_empty
         | 
| 72 | 
            -
                    expect(pwd.length).to eq(32)
         | 
| 73 | 
            -
                    expect(pwd).to match(/[+%\/@=\?_.,:]+/)
         | 
| 97 | 
            +
                    expect(new_mysql = @trocla.set_password('set_test2','mysql','foo')).not_to eql(mysql)
         | 
| 98 | 
            +
                    expect(@trocla.get_password('set_test2','mysql')).to eq(new_mysql)
         | 
| 99 | 
            +
                    expect(@trocla.get_password('set_test2','md5crypt')).to eq(md5crypt)
         | 
| 100 | 
            +
                    expect(@trocla.get_password('set_test2','plain')).to eq(plain)
         | 
| 74 101 | 
             
                  end
         | 
| 75 102 | 
             
                end
         | 
| 76 | 
            -
              end
         | 
| 77 | 
            -
             | 
| 78 | 
            -
              describe "set_password" do
         | 
| 79 | 
            -
                it "resets hashed passwords on a new plain password" do
         | 
| 80 | 
            -
                  expect(@trocla.password('set_test','mysql')).not_to be_empty
         | 
| 81 | 
            -
                  expect(@trocla.get_password('set_test','mysql')).not_to be_nil
         | 
| 82 | 
            -
                  expect(old_plain=@trocla.password('set_test','mysql')).not_to be_empty
         | 
| 83 103 |  | 
| 84 | 
            -
             | 
| 85 | 
            -
                   | 
| 86 | 
            -
             | 
| 104 | 
            +
                describe "reset_password" do
         | 
| 105 | 
            +
                  it "resets a password" do
         | 
| 106 | 
            +
                    plain1 = @trocla.password('reset_pwd','plain')
         | 
| 107 | 
            +
                    plain2 = @trocla.reset_password('reset_pwd','plain')
         | 
| 87 108 |  | 
| 88 | 
            -
             | 
| 89 | 
            -
                   | 
| 90 | 
            -
                  expect(md5crypt = @trocla.password('set_test2','md5crypt')).not_to be_empty
         | 
| 91 | 
            -
                  expect(plain = @trocla.get_password('set_test2','plain')).not_to be_empty
         | 
| 109 | 
            +
                    expect(plain1).not_to eq(plain2)
         | 
| 110 | 
            +
                  end
         | 
| 92 111 |  | 
| 93 | 
            -
                   | 
| 94 | 
            -
             | 
| 95 | 
            -
             | 
| 96 | 
            -
                  expect(@trocla.get_password('set_test2','plain')).to eq(plain)
         | 
| 97 | 
            -
                end
         | 
| 98 | 
            -
              end
         | 
| 112 | 
            +
                  it "does not reset other formats" do
         | 
| 113 | 
            +
                    expect(mysql = @trocla.password('reset_pwd2','mysql')).not_to be_empty
         | 
| 114 | 
            +
                    expect(md5crypt1 = @trocla.password('reset_pwd2','md5crypt')).not_to be_empty
         | 
| 99 115 |  | 
| 100 | 
            -
             | 
| 101 | 
            -
             | 
| 102 | 
            -
                  plain1 = @trocla.password('reset_pwd','plain')
         | 
| 103 | 
            -
                  plain2 = @trocla.reset_password('reset_pwd','plain')
         | 
| 116 | 
            +
                    expect(md5crypt2 = @trocla.reset_password('reset_pwd2','md5crypt')).not_to be_empty
         | 
| 117 | 
            +
                    expect(md5crypt2).not_to eq(md5crypt1)
         | 
| 104 118 |  | 
| 105 | 
            -
             | 
| 119 | 
            +
                    expect(@trocla.get_password('reset_pwd2','mysql')).to eq(mysql)
         | 
| 120 | 
            +
                  end
         | 
| 106 121 | 
             
                end
         | 
| 107 122 |  | 
| 108 | 
            -
                 | 
| 109 | 
            -
                   | 
| 110 | 
            -
             | 
| 111 | 
            -
             | 
| 112 | 
            -
                  expect(md5crypt2 = @trocla.reset_password('reset_pwd2','md5crypt')).not_to be_empty
         | 
| 113 | 
            -
                  expect(md5crypt2).not_to eq(md5crypt1)
         | 
| 123 | 
            +
                describe "delete_password" do
         | 
| 124 | 
            +
                  it "deletes all passwords if no format is given" do
         | 
| 125 | 
            +
                    expect(@trocla.password('delete_test1','mysql')).not_to be_nil
         | 
| 126 | 
            +
                    expect(@trocla.get_password('delete_test1','plain')).not_to be_nil
         | 
| 114 127 |  | 
| 115 | 
            -
             | 
| 116 | 
            -
             | 
| 117 | 
            -
             | 
| 128 | 
            +
                    @trocla.delete_password('delete_test1')
         | 
| 129 | 
            +
                    expect(@trocla.get_password('delete_test1','plain')).to be_nil
         | 
| 130 | 
            +
                    expect(@trocla.get_password('delete_test1','mysql')).to be_nil
         | 
| 131 | 
            +
                  end
         | 
| 118 132 |  | 
| 119 | 
            -
             | 
| 120 | 
            -
             | 
| 121 | 
            -
             | 
| 122 | 
            -
                  expect(@trocla.get_password('delete_test1','plain')).not_to be_nil
         | 
| 133 | 
            +
                  it "deletes only a given format" do
         | 
| 134 | 
            +
                    expect(@trocla.password('delete_test2','mysql')).not_to be_nil
         | 
| 135 | 
            +
                    expect(@trocla.get_password('delete_test2','plain')).not_to be_nil
         | 
| 123 136 |  | 
| 124 | 
            -
             | 
| 125 | 
            -
             | 
| 126 | 
            -
             | 
| 127 | 
            -
             | 
| 137 | 
            +
                    @trocla.delete_password('delete_test2','plain')
         | 
| 138 | 
            +
                    expect(@trocla.get_password('delete_test2','plain')).to be_nil
         | 
| 139 | 
            +
                    expect(@trocla.get_password('delete_test2','mysql')).not_to be_nil
         | 
| 140 | 
            +
                  end
         | 
| 128 141 |  | 
| 129 | 
            -
             | 
| 130 | 
            -
             | 
| 131 | 
            -
             | 
| 142 | 
            +
                  it "deletes only a given non-plain format" do
         | 
| 143 | 
            +
                    expect(@trocla.password('delete_test3','mysql')).not_to be_nil
         | 
| 144 | 
            +
                    expect(@trocla.get_password('delete_test3','plain')).not_to be_nil
         | 
| 132 145 |  | 
| 133 | 
            -
             | 
| 134 | 
            -
             | 
| 135 | 
            -
             | 
| 146 | 
            +
                    @trocla.delete_password('delete_test3','mysql')
         | 
| 147 | 
            +
                    expect(@trocla.get_password('delete_test3','mysql')).to be_nil
         | 
| 148 | 
            +
                    expect(@trocla.get_password('delete_test3','plain')).not_to be_nil
         | 
| 149 | 
            +
                  end
         | 
| 136 150 | 
             
                end
         | 
| 137 151 |  | 
| 138 | 
            -
                 | 
| 139 | 
            -
                   | 
| 140 | 
            -
             | 
| 152 | 
            +
                context 'concurrent access' do
         | 
| 153 | 
            +
                  context 'on expensive flagged formats' do
         | 
| 154 | 
            +
                    before(:each) do
         | 
| 155 | 
            +
                      expect(Trocla::Formats).to receive(:[]).with('sleep').at_least(:once).and_return(Trocla::Formats::Sleep)
         | 
| 156 | 
            +
                      expect(Trocla::Formats::Sleep).to receive(:expensive?).at_least(:once).and_return(true)
         | 
| 157 | 
            +
                      expect(Trocla::Formats).to receive(:available?).with('sleep').at_least(:once).and_return(true)
         | 
| 158 | 
            +
                    end
         | 
| 159 | 
            +
                    it 'should not overwrite a value if it takes longer' do
         | 
| 160 | 
            +
                      t1 = Thread.new{ @trocla.password('threadpwd','sleep','sleep' => 4) }
         | 
| 161 | 
            +
                      t2 = Thread.new{ @trocla.password('threadpwd','sleep','sleep' => 1) }
         | 
| 162 | 
            +
                      pwd1 = t1.value
         | 
| 163 | 
            +
                      pwd2 = t2.value
         | 
| 164 | 
            +
                      real_value = @trocla.password('threadpwd','sleep')
         | 
| 165 | 
            +
                      # as t2 finished first this should win
         | 
| 166 | 
            +
                      expect(pwd1).to eql(pwd2)
         | 
| 167 | 
            +
                      expect(real_value).to eql(pwd1)
         | 
| 168 | 
            +
                      expect(real_value).to eql(pwd2)
         | 
| 169 | 
            +
                    end
         | 
| 170 | 
            +
                  end
         | 
| 171 | 
            +
                  context 'on inexpensive flagged formats' do
         | 
| 172 | 
            +
                    before(:each) do
         | 
| 173 | 
            +
                      expect(Trocla::Formats).to receive(:[]).with('sleep').at_least(:once).and_return(Trocla::Formats::Sleep)
         | 
| 174 | 
            +
                      expect(Trocla::Formats::Sleep).to receive(:expensive?).at_least(:once).and_return(false)
         | 
| 175 | 
            +
                      expect(Trocla::Formats).to receive(:available?).with('sleep').at_least(:once).and_return(true)
         | 
| 176 | 
            +
                    end
         | 
| 177 | 
            +
                    it 'should not overwrite a value if it takes longer' do
         | 
| 178 | 
            +
                      t1 = Thread.new{ @trocla.password('threadpwd_inexp','sleep','sleep' => 4) }
         | 
| 179 | 
            +
                      t2 = Thread.new{ @trocla.password('threadpwd_inexp','sleep','sleep' => 1) }
         | 
| 180 | 
            +
                      pwd1 = t1.value
         | 
| 181 | 
            +
                      pwd2 = t2.value
         | 
| 182 | 
            +
                      real_value = @trocla.password('threadpwd_inexp','sleep')
         | 
| 183 | 
            +
                      # as t2 finished first but the format is inexpensive it gets overwritten
         | 
| 184 | 
            +
                      expect(pwd1).not_to eql(pwd2)
         | 
| 185 | 
            +
                      expect(real_value).to eql(pwd1)
         | 
| 186 | 
            +
                      expect(real_value).not_to eql(pwd2)
         | 
| 187 | 
            +
                    end
         | 
| 188 | 
            +
                  end
         | 
| 189 | 
            +
                  context 'real world example' do
         | 
| 190 | 
            +
                    it 'should store the quicker one' do
         | 
| 191 | 
            +
                      t1 = Thread.new{ @trocla.password('threadpwd_real','bcrypt','cost' => 17) }
         | 
| 192 | 
            +
                      t2 = Thread.new{ @trocla.password('threadpwd_real','bcrypt') }
         | 
| 193 | 
            +
                      pwd1 = t1.value
         | 
| 194 | 
            +
                      pwd2 = t2.value
         | 
| 195 | 
            +
                      real_value = @trocla.password('threadpwd_real','bcrypt')
         | 
| 196 | 
            +
                      # t2 should still win but both should be the same
         | 
| 197 | 
            +
                      expect(pwd1).to eql(pwd2)
         | 
| 198 | 
            +
                      expect(real_value).to eql(pwd1)
         | 
| 199 | 
            +
                      expect(real_value).to eql(pwd2)
         | 
| 200 | 
            +
                    end
         | 
| 201 | 
            +
                    it 'should store the quicker one test 2' do
         | 
| 202 | 
            +
                      t1 = Thread.new{ @trocla.password('my_shiny_selfsigned_ca', 'x509', {
         | 
| 203 | 
            +
                        'CN'        => 'This is my self-signed certificate',
         | 
| 204 | 
            +
                        'become_ca' => false,
         | 
| 205 | 
            +
                      }) }
         | 
| 206 | 
            +
                      t2 = Thread.new{ @trocla.password('my_shiny_selfsigned_ca', 'x509', {
         | 
| 207 | 
            +
                        'CN'        => 'This is my self-signed certificate',
         | 
| 208 | 
            +
                        'become_ca' => false,
         | 
| 209 | 
            +
                      }) }
         | 
| 210 | 
            +
                      cert1 = t1.value
         | 
| 211 | 
            +
                      cert2 = t2.value
         | 
| 212 | 
            +
                      real_value = @trocla.password('my_shiny_selfsigned_ca','x509')
         | 
| 213 | 
            +
                      # t2 should still win but both should be the same
         | 
| 214 | 
            +
                      expect(cert1).to eql(cert2)
         | 
| 215 | 
            +
                      expect(real_value).to eql(cert1)
         | 
| 216 | 
            +
                      expect(real_value).to eql(cert2)
         | 
| 217 | 
            +
                    end
         | 
| 218 | 
            +
                  end
         | 
| 219 | 
            +
                end
         | 
| 141 220 |  | 
| 142 | 
            -
             | 
| 143 | 
            -
             | 
| 144 | 
            -
             | 
| 221 | 
            +
              end
         | 
| 222 | 
            +
              context 'with .open' do
         | 
| 223 | 
            +
                it 'closes the connection with a block' do
         | 
| 224 | 
            +
                  expect_any_instance_of(Trocla::Stores::Memory).to receive(:close)
         | 
| 225 | 
            +
                  Trocla.open{|t|
         | 
| 226 | 
            +
                    t.password('plain_open','plain')
         | 
| 227 | 
            +
                  }
         | 
| 228 | 
            +
                end
         | 
| 229 | 
            +
                it 'keeps the connection without a block' do
         | 
| 230 | 
            +
                  expect_any_instance_of(Trocla::Stores::Memory).not_to receive(:close)
         | 
| 231 | 
            +
                  Trocla.open.password('plain_open','plain')
         | 
| 145 232 | 
             
                end
         | 
| 146 233 | 
             
              end
         | 
| 147 234 |  | 
    
        data/trocla.gemspec
    CHANGED
    
    | @@ -2,19 +2,19 @@ | |
| 2 2 | 
             
            # DO NOT EDIT THIS FILE DIRECTLY
         | 
| 3 3 | 
             
            # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
         | 
| 4 4 | 
             
            # -*- encoding: utf-8 -*-
         | 
| 5 | 
            -
            # stub: trocla 0. | 
| 5 | 
            +
            # stub: trocla 0.3.0 ruby lib
         | 
| 6 6 |  | 
| 7 7 | 
             
            Gem::Specification.new do |s|
         | 
| 8 | 
            -
              s.name = "trocla"
         | 
| 9 | 
            -
              s.version = "0. | 
| 8 | 
            +
              s.name = "trocla".freeze
         | 
| 9 | 
            +
              s.version = "0.3.0"
         | 
| 10 10 |  | 
| 11 | 
            -
              s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
         | 
| 12 | 
            -
              s.require_paths = ["lib"]
         | 
| 13 | 
            -
              s.authors = ["mh"]
         | 
| 14 | 
            -
              s.date = " | 
| 15 | 
            -
              s.description = "Trocla helps you to generate random passwords and to store them in various formats (plain, MD5, bcrypt) for later retrival."
         | 
| 16 | 
            -
              s.email = "mh+trocla@immerda.ch"
         | 
| 17 | 
            -
              s.executables = ["trocla"]
         | 
| 11 | 
            +
              s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
         | 
| 12 | 
            +
              s.require_paths = ["lib".freeze]
         | 
| 13 | 
            +
              s.authors = ["mh".freeze]
         | 
| 14 | 
            +
              s.date = "2017-08-04"
         | 
| 15 | 
            +
              s.description = "Trocla helps you to generate random passwords and to store them in various formats (plain, MD5, bcrypt) for later retrival.".freeze
         | 
| 16 | 
            +
              s.email = "mh+trocla@immerda.ch".freeze
         | 
| 17 | 
            +
              s.executables = ["trocla".freeze]
         | 
| 18 18 | 
             
              s.extra_rdoc_files = [
         | 
| 19 19 | 
             
                "LICENSE.txt",
         | 
| 20 20 | 
             
                "README.md"
         | 
| @@ -64,39 +64,39 @@ Gem::Specification.new do |s| | |
| 64 64 | 
             
                "spec/trocla_spec.rb",
         | 
| 65 65 | 
             
                "trocla.gemspec"
         | 
| 66 66 | 
             
              ]
         | 
| 67 | 
            -
              s.homepage = "https://tech.immerda.ch/2011/12/trocla-get-hashed-passwords-out-of-puppet-manifests/"
         | 
| 68 | 
            -
              s.licenses = ["GPLv3"]
         | 
| 69 | 
            -
              s.rubygems_version = "2. | 
| 70 | 
            -
              s.summary = "Trocla a simple password generator and storage"
         | 
| 67 | 
            +
              s.homepage = "https://tech.immerda.ch/2011/12/trocla-get-hashed-passwords-out-of-puppet-manifests/".freeze
         | 
| 68 | 
            +
              s.licenses = ["GPLv3".freeze]
         | 
| 69 | 
            +
              s.rubygems_version = "2.6.11".freeze
         | 
| 70 | 
            +
              s.summary = "Trocla a simple password generator and storage".freeze
         | 
| 71 71 |  | 
| 72 72 | 
             
              if s.respond_to? :specification_version then
         | 
| 73 73 | 
             
                s.specification_version = 4
         | 
| 74 74 |  | 
| 75 75 | 
             
                if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
         | 
| 76 | 
            -
                  s.add_runtime_dependency(%q<moneta | 
| 77 | 
            -
                  s.add_runtime_dependency(%q<highline | 
| 78 | 
            -
                  s.add_runtime_dependency(%q<bcrypt | 
| 79 | 
            -
                  s.add_development_dependency(%q<rspec | 
| 80 | 
            -
                  s.add_development_dependency(%q<rdoc | 
| 81 | 
            -
                  s.add_development_dependency(%q<jeweler | 
| 82 | 
            -
                  s.add_development_dependency(%q<rspec-pending_for | 
| 76 | 
            +
                  s.add_runtime_dependency(%q<moneta>.freeze, [">= 0"])
         | 
| 77 | 
            +
                  s.add_runtime_dependency(%q<highline>.freeze, [">= 0"])
         | 
| 78 | 
            +
                  s.add_runtime_dependency(%q<bcrypt>.freeze, [">= 0"])
         | 
| 79 | 
            +
                  s.add_development_dependency(%q<rspec>.freeze, [">= 0"])
         | 
| 80 | 
            +
                  s.add_development_dependency(%q<rdoc>.freeze, [">= 0"])
         | 
| 81 | 
            +
                  s.add_development_dependency(%q<jeweler>.freeze, [">= 0"])
         | 
| 82 | 
            +
                  s.add_development_dependency(%q<rspec-pending_for>.freeze, [">= 0"])
         | 
| 83 83 | 
             
                else
         | 
| 84 | 
            -
                  s.add_dependency(%q<moneta | 
| 85 | 
            -
                  s.add_dependency(%q<highline | 
| 86 | 
            -
                  s.add_dependency(%q<bcrypt | 
| 87 | 
            -
                  s.add_dependency(%q<rspec | 
| 88 | 
            -
                  s.add_dependency(%q<rdoc | 
| 89 | 
            -
                  s.add_dependency(%q<jeweler | 
| 90 | 
            -
                  s.add_dependency(%q<rspec-pending_for | 
| 84 | 
            +
                  s.add_dependency(%q<moneta>.freeze, [">= 0"])
         | 
| 85 | 
            +
                  s.add_dependency(%q<highline>.freeze, [">= 0"])
         | 
| 86 | 
            +
                  s.add_dependency(%q<bcrypt>.freeze, [">= 0"])
         | 
| 87 | 
            +
                  s.add_dependency(%q<rspec>.freeze, [">= 0"])
         | 
| 88 | 
            +
                  s.add_dependency(%q<rdoc>.freeze, [">= 0"])
         | 
| 89 | 
            +
                  s.add_dependency(%q<jeweler>.freeze, [">= 0"])
         | 
| 90 | 
            +
                  s.add_dependency(%q<rspec-pending_for>.freeze, [">= 0"])
         | 
| 91 91 | 
             
                end
         | 
| 92 92 | 
             
              else
         | 
| 93 | 
            -
                s.add_dependency(%q<moneta | 
| 94 | 
            -
                s.add_dependency(%q<highline | 
| 95 | 
            -
                s.add_dependency(%q<bcrypt | 
| 96 | 
            -
                s.add_dependency(%q<rspec | 
| 97 | 
            -
                s.add_dependency(%q<rdoc | 
| 98 | 
            -
                s.add_dependency(%q<jeweler | 
| 99 | 
            -
                s.add_dependency(%q<rspec-pending_for | 
| 93 | 
            +
                s.add_dependency(%q<moneta>.freeze, [">= 0"])
         | 
| 94 | 
            +
                s.add_dependency(%q<highline>.freeze, [">= 0"])
         | 
| 95 | 
            +
                s.add_dependency(%q<bcrypt>.freeze, [">= 0"])
         | 
| 96 | 
            +
                s.add_dependency(%q<rspec>.freeze, [">= 0"])
         | 
| 97 | 
            +
                s.add_dependency(%q<rdoc>.freeze, [">= 0"])
         | 
| 98 | 
            +
                s.add_dependency(%q<jeweler>.freeze, [">= 0"])
         | 
| 99 | 
            +
                s.add_dependency(%q<rspec-pending_for>.freeze, [">= 0"])
         | 
| 100 100 | 
             
              end
         | 
| 101 101 | 
             
            end
         | 
| 102 102 |  | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: trocla
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.3.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - mh
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 11 | 
            +
            date: 2017-08-04 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: moneta
         | 
| @@ -181,7 +181,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 181 181 | 
             
                  version: '0'
         | 
| 182 182 | 
             
            requirements: []
         | 
| 183 183 | 
             
            rubyforge_project: 
         | 
| 184 | 
            -
            rubygems_version: 2. | 
| 184 | 
            +
            rubygems_version: 2.6.11
         | 
| 185 185 | 
             
            signing_key: 
         | 
| 186 186 | 
             
            specification_version: 4
         | 
| 187 187 | 
             
            summary: Trocla a simple password generator and storage
         |