arver 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,9 @@
1
+ === 0.1.4 2012-07-24
2
+
3
+ * Introducing the --refresh action to renew the luks key. You should always run this command, when receiving a new permission.
4
+ * Fixed a security bug in the padding algorithm, which might reveal the magnitude of the ammount of keys in a keyfile. Please run --garbage-collect to fix your old keys.
5
+ * Some code cleanup and improved tests.
6
+
1
7
  === 0.1.2 2012-05-01
2
8
 
3
9
  * Fixed bug in password dialog
@@ -1,6 +1,6 @@
1
- %w{singleton yaml fileutils active_support highline/import gpgme escape openssl}.each {|f| require f }
1
+ %w{singleton yaml fileutils rubygems active_support/secure_random highline/import gpgme escape openssl zlib}.each {|f| require f }
2
2
  $:.unshift(File.dirname(__FILE__)) unless
3
3
  $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
4
4
 
5
- %w{ gpg_key_manager luks_wrapper action initial_config_action create_action list_action gc_action adduser_action deluser_action info_action close_action open_action target_list command_wrapper ssh_command_wrapper log_levels io_logger log string bootstrap local_config config test_config_loader node_with_script_hooks partition_hierarchy_node host hostgroup tree partition test_partition key_generator key_saver keystore runtime_config key_info_action}.each {|f| require "arver/#{f}" }
5
+ %w{ gpg_key_manager luks_wrapper action initial_config_action refresh_action create_action list_action gc_action adduser_action deluser_action info_action close_action open_action target_list command_wrapper ssh_command_wrapper log_levels io_logger log string bootstrap local_config config test_config_loader node_with_script_hooks partition_hierarchy_node host hostgroup tree partition test_partition key_generator key_saver keystore runtime_config key_info_action}.each {|f| require "arver/#{f}" }
6
6
 
@@ -32,7 +32,7 @@ module Arver
32
32
  end
33
33
 
34
34
  def open_keystore
35
- self.keystore= Arver::Keystore.instance
35
+ self.keystore= Arver::Keystore.for( LocalConfig.instance.username )
36
36
  keystore.load
37
37
  end
38
38
 
@@ -31,19 +31,19 @@ module Arver
31
31
  # generate a key for the new user
32
32
  Arver::Log.debug( "generate_key (#{target_user},#{partition.path})" )
33
33
 
34
- newkey = generator.generate_key( target_user, partition )
34
+ newkey = generator.generate_key( partition )
35
35
 
36
36
  caller = Arver::LuksWrapper.addKey( slot_of_target_user.to_s, partition )
37
37
  caller.execute( key + "\n" + newkey )
38
38
 
39
39
  unless( caller.success? )
40
40
  Arver::Log.error( "Could not add user to #{partition.path} \n #{caller.output}" )
41
- generator.remove_key( target_user, partition )
41
+ generator.remove_key( partition )
42
42
  end
43
43
  end
44
44
 
45
45
  def post_action
46
- self.generator.dump
46
+ self.generator.dump( Keystore.for( target_user ) )
47
47
  end
48
48
  end
49
49
  end
@@ -65,6 +65,8 @@ module Arver
65
65
  "Add a user to target.") { |user| options[:action] = :adduser; options[:argument][:user] = user; }
66
66
  opts.on_tail( "-d USER TARGET", "--del-user USER TARGET", String,
67
67
  "Remove a user from target.") { |user| options[:action] = :deluser; options[:argument][:user] = user; }
68
+ opts.on_tail( "-r TARGET", "--refresh TARGET", String,
69
+ "Refresh the key on target." ) { |arg| options[:argument][:target] = arg; options[:action] = :refresh; }
68
70
  opts.on_tail( "-g", "--garbage-collect",
69
71
  "Expunge old keys." ) { options[:action] = :gc; }
70
72
  opts.on_tail( "-k TARGET", "--keys TARGET", String,
@@ -118,6 +120,7 @@ module Arver
118
120
  :info => Arver::InfoAction,
119
121
  :key_info => Arver::KeyInfoAction,
120
122
  :init => Arver::InitialConfigAction,
123
+ :refresh => Arver::RefreshAction,
121
124
  }
122
125
 
123
126
  action = (actions[ action ]).new( target_list )
@@ -19,9 +19,9 @@ module Arver
19
19
  Arver::Log.error( "config-dir "+path+" does not exist" )
20
20
  exit
21
21
  end
22
- @users= ( load_file( path+"/users" ) )
22
+ @users= ( load_file( File.join(path,'users') ) )
23
23
  tree.clear
24
- tree.from_hash( load_file( path+"/disks" ) )
24
+ tree.from_hash( load_file( File.join(path,'disks') ) )
25
25
  end
26
26
 
27
27
  def load_file( filename )
@@ -30,8 +30,8 @@ module Arver
30
30
 
31
31
  def save
32
32
  FileUtils.mkdir_p( path ) unless File.exists?( path )
33
- File.open( path+"/users", 'w' ) { |f| f.write( users.to_yaml ) }
34
- File.open( path+"/disks", 'w' ) { |f| f.write( tree.to_yaml ) }
33
+ File.open( File.join(path,'users'), 'w' ) { |f| f.write( users.to_yaml ) }
34
+ File.open( File.join(path,'disks'), 'w' ) { |f| f.write( tree.to_yaml ) }
35
35
  end
36
36
 
37
37
  def exists?( user )
@@ -17,18 +17,11 @@ module Arver
17
17
  end
18
18
 
19
19
  def execute_partition( partition )
20
- Arver::Log.info( "creating: "+partition.path )
21
-
22
20
  slot_of_user = Arver::Config.instance.slot( Arver::LocalConfig.instance.username )
23
- Arver::Log.debug( "generating a new key for partition #{partition.device} on #{partition.path}" )
24
-
25
- # checking if disk is not already LUKS formatted
26
- Arver::Log.debug( "checking if disk is already LUKS formatted." )
27
- Arver::Log.info( "!! if the next line reads 'Command failed' please ignore it! (sorry this will become more sane soon) !!" )
28
21
 
29
22
  caller = Arver::LuksWrapper.dump( partition )
30
23
  caller.execute
31
-
24
+
32
25
  if caller.output.include?('LUKS header information') then
33
26
  Arver::Log.warn( "VERY DANGEROUS: the partition #{partition.device} is already formatted with LUKS - returning (continue with --violence)" )
34
27
  Arver::Log.warn( "If you wish to integrate an existing disk into arver use --add-user #{Arver::LocalConfig.instance.username} instead." )
@@ -41,18 +34,20 @@ module Arver
41
34
  end
42
35
  end
43
36
 
44
- Arver::Log.trace( "starting key generation..." )
45
- key = self.generator.generate_key( Arver::LocalConfig.instance.username, partition )
37
+ Arver::Log.info( "creating: "+partition.path )
38
+
39
+ Arver::Log.debug( "generating a new key for partition #{partition.device} on #{partition.path}" )
40
+ key = self.generator.generate_key( partition )
46
41
  caller = Arver::LuksWrapper.create( slot_of_user.to_s, partition )
47
42
  caller.execute( key )
48
43
  unless( caller.success? )
49
44
  Arver::Log.error( "Could not create Partition!" )
50
- self.generator.remove_key( Arver::LocalConfig.instance.username, partition )
45
+ self.generator.remove_key( partition )
51
46
  end
52
47
  end
53
48
 
54
49
  def post_action
55
- self.generator.dump
50
+ self.generator.dump( self.keystore )
56
51
  end
57
52
  end
58
53
  end
@@ -4,26 +4,22 @@ module Arver
4
4
  @keys = {}
5
5
  end
6
6
 
7
- def generate_key( user, partition )
7
+ def generate_key( partition )
8
8
  key = ActiveSupport::SecureRandom.base64(192)
9
- add( user, partition, key )
10
- key
9
+ @keys[partition] = key
11
10
  end
12
11
 
13
- def add( user, partition, luks_key )
14
- @keys[user] ||= {}
15
- @keys[user][partition.path] = { :key => luks_key, :time => Time.now.to_f }
16
- end
17
-
18
- def remove_key( user, partition )
19
- @keys[user].delete( partition.path )
12
+ def remove_key( partition )
13
+ @keys.delete( partition )
20
14
  end
21
15
 
22
- def dump
23
- @keys.each do | user, user_keys |
24
- KeySaver.add( user, user_keys.to_yaml ) unless user_keys.empty?
16
+ def dump( keystore )
17
+ return if @keys.empty?
18
+ @keys.each do | partition, key |
19
+ keystore.add_luks_key( partition, key )
25
20
  end
26
21
  @keys = {}
22
+ keystore.save
27
23
  end
28
24
  end
29
25
  end
@@ -2,20 +2,40 @@ module Arver
2
2
  class KeySaver
3
3
 
4
4
  def self.save( user, key )
5
- filename = save_tmp( user, key )
6
- purge_keys(user)
7
- FileUtils.mv("#{tmp_key_path(user)}", "#{key_path(user)}")
8
- "#{key_path(user)}/#{filename}"
5
+ tmp_path = tmp_key_path( user )
6
+ back_path = backup_key_path( user )
7
+ path = key_path( user )
8
+ filename = save_to( user, key, tmp_path )
9
+ FileUtils.mv(path,back_path) if File.exists?(path)
10
+ FileUtils.mv(tmp_path,path)
11
+ FileUtils.rm_rf(back_path)
12
+ File.join(path,filename)
9
13
  end
10
14
 
11
15
  def self.add( user, key )
12
- filename = save_tmp( user, key )
13
- FileUtils.mkdir_p key_path(user) unless File.exists?( key_path(user) )
14
- FileUtils.mv( Dir.glob("#{tmp_key_path(user)}/*"), "#{key_path(user)}")
15
- "#{key_path(user)}/#{filename}"
16
+ path = key_path( user )
17
+ filename = save_to( user, key, path )
18
+ File.join(path,filename)
16
19
  end
17
20
 
18
- def self.save_tmp( user, key )
21
+ def self.deflate(string, level=6)
22
+ z = Zlib::Deflate.new(level)
23
+ dst = z.deflate(string, Zlib::FINISH)
24
+ z.close
25
+ dst
26
+ end
27
+
28
+ def self.inflate(string)
29
+ zstream = Zlib::Inflate.new
30
+ buf = zstream.inflate(string)
31
+ zstream.finish
32
+ zstream.close
33
+ buf
34
+ end
35
+
36
+ def self.save_to( user, key, path )
37
+ #compress the key before applying padding, so the size after encryption+compression by gpg is more stable...
38
+ key = deflate(key)
19
39
  unless GPGKeyManager.check_key_of( user )
20
40
  return
21
41
  end
@@ -34,9 +54,9 @@ module Arver
34
54
  end
35
55
  key_encrypted = encrypted.read
36
56
  unless( Arver::RuntimeConfig.instance.dry_run )
37
- FileUtils.mkdir_p tmp_key_path(user) unless File.exists?( tmp_key_path(user) )
38
- filename = "#{OpenSSL::Digest::SHA1.new(key_encrypted)}"
39
- File.open( "#{tmp_key_path(user)}/#{filename}", 'w' ) do |f|
57
+ FileUtils.mkdir_p path unless File.exists?( path )
58
+ filename = "#{OpenSSL::Digest::SHA256.new << key_encrypted}"
59
+ File.open( File.join("#{path}","#{filename}"), 'w' ) do |f|
40
60
  f.write key_encrypted
41
61
  end
42
62
  end
@@ -44,11 +64,15 @@ module Arver
44
64
  end
45
65
 
46
66
  def self.key_path( user )
47
- "#{config_path}/keys/#{user}"
67
+ File.join("#{config_path}","keys","#{user}")
68
+ end
69
+
70
+ def self.backup_key_path( user )
71
+ "#{key_path(user)}.bak"
48
72
  end
49
73
 
50
74
  def self.tmp_key_path( user )
51
- "#{config_path}/tmp/#{user}"
75
+ File.join("#{config_path}","tmp","#{user}")
52
76
  end
53
77
 
54
78
  def self.config_path
@@ -71,7 +95,7 @@ module Arver
71
95
  Dir.entries( key_path( user ) ).sort.each do | file |
72
96
  unless( file == "." || file == ".." )
73
97
  Arver::Log.trace( "Loading keyfile "+file )
74
- key_encrypted = File.open( key_path( user )+"/"+file )
98
+ key_encrypted = File.open( File.join( key_path( user ),file) )
75
99
  begin
76
100
  decrypted_txt = crypto.decrypt( key_encrypted, { :passphrase_callback => method( :passfunc ) } )
77
101
  rescue GPGME::Error => gpgerr
@@ -79,6 +103,11 @@ module Arver
79
103
  next
80
104
  end
81
105
  decrypted_key = substract_padding( decrypted_txt.read )
106
+ begin
107
+ decrypted_key = inflate( decrypted_key )
108
+ rescue Zlib::DataError
109
+ Log.write("You have an outdated key. Run garbage collect to update it.")
110
+ end
82
111
  decrypted += [ decrypted_key ];
83
112
  end
84
113
  end
@@ -87,13 +116,13 @@ module Arver
87
116
 
88
117
  def self.add_padding( key )
89
118
  marker = "--"+ActiveSupport::SecureRandom.base64( 82 )
90
- size = 450000
119
+ size = 200000
91
120
  padding_size = size - key.size
92
121
  if padding_size <= 0
93
122
  padding_size = 0
94
123
  Arver::Log.warn( "Warning: Your arver keys exceed the maximal padding size, therefore i can no longer disguise how many keys you possess.")
95
124
  end
96
- padding = ActiveSupport::SecureRandom.base64( padding_size )
125
+ padding = ActiveSupport::SecureRandom.base64( padding_size )[0..padding_size]
97
126
  marker +"\n"+ key + "\n" + marker + "\n" + padding
98
127
  end
99
128
 
@@ -1,14 +1,27 @@
1
1
  module Arver
2
2
  class Keystore
3
+ class << self
4
+ def for( username )
5
+ if username.empty?
6
+ Log.error("no user given, cannot create keystore")
7
+ return
8
+ end
9
+ @@keystores ||= {}
10
+ @@keystores[username] ||= Keystore.new( username )
11
+ end
3
12
 
4
- include Singleton
5
-
6
- attr_accessor :username
13
+ def reset
14
+ @@keystores = {}
15
+ end
16
+ end
17
+
18
+ attr_accessor :username, :loaded
7
19
 
8
- def initialize
20
+ def initialize( name )
9
21
  @keys = {}
10
22
  @key_versions = {}
11
- self.username= Arver::LocalConfig.instance.username
23
+ self.username= name
24
+ self.loaded = false
12
25
  end
13
26
 
14
27
  def load
@@ -18,10 +31,15 @@ module Arver
18
31
  load_luks_key(target,key)
19
32
  end
20
33
  end
34
+ self.loaded = true
21
35
  end
22
36
 
23
37
  def save
24
- KeySaver.save(username, @keys.to_yaml)
38
+ if loaded
39
+ KeySaver.save(username, @keys.to_yaml)
40
+ else
41
+ KeySaver.add(username, @keys.to_yaml)
42
+ end
25
43
  end
26
44
 
27
45
  def purge_keys
@@ -43,6 +61,7 @@ module Arver
43
61
  end
44
62
  else
45
63
  unless( @keys[partition] )
64
+ Log.debug("loding key in old format")
46
65
  @keys[partition] = { :key => new_key, :time => 0.0 }
47
66
  end
48
67
  end
@@ -31,8 +31,9 @@ module Arver
31
31
  def self.level( num )
32
32
  logger.level=( num )
33
33
  end
34
-
35
-
34
+ def flush
35
+ logger.flush
36
+ end
36
37
  end
37
38
  end
38
39
 
@@ -3,6 +3,9 @@ module Arver
3
3
  def self.addKey( key_slot, partition )
4
4
  Arver::SSHCommandWrapper.create( "cryptsetup", [ "--batch-mode", "--key-slot=#{key_slot}", "luksAddKey", partition.device_path ], partition.parent, true )
5
5
  end
6
+ def self.changeKey( key_slot, partition )
7
+ Arver::SSHCommandWrapper.create( "cryptsetup", [ "--batch-mode", "--key-slot=#{key_slot}", "luksChangeKey", partition.device_path ], partition.parent, true )
8
+ end
6
9
  def self.close( partition )
7
10
  Arver::SSHCommandWrapper.create( "cryptsetup", [ "luksClose", "#{partition.name}"], partition.parent, true )
8
11
  end
@@ -0,0 +1,46 @@
1
+ module Arver
2
+ class RefreshAction < Action
3
+
4
+ def initialize( target_list )
5
+ super( target_list )
6
+ self.open_keystore
7
+ self.new_key_generator
8
+ end
9
+
10
+ def pre_action
11
+ tl = ""
12
+ target_list.each { |t| tl += ( tl.empty? ? "": ", " )+t.name }
13
+ Arver::Log.info( "refresh was called with target(s) #{tl}" )
14
+ end
15
+
16
+ def verify?( partition )
17
+ unless Arver::RuntimeConfig.instance.ask_password
18
+ return load_key( partition )
19
+ end
20
+ self.key= ask("Enter the password for the volume: #{partition.device}") {|q| q.echo = false}
21
+ true
22
+ end
23
+
24
+ def execute_partition( partition )
25
+ Arver::Log.info( "Generating a new key for partition #{partition.device}" )
26
+
27
+ slot_of_user = Arver::Config.instance.slot( Arver::LocalConfig.instance.username )
28
+ newkey = generator.generate_key( partition )
29
+
30
+ caller = Arver::LuksWrapper.changeKey( slot_of_user.to_s, partition )
31
+ caller.execute( key + "\n" + newkey )
32
+
33
+ unless( caller.success? )
34
+ Arver::Log.error( "Warning: i believe that i could not change the key on #{partition.path}, therefore i kept the old one!" )
35
+ Arver::Log.error( "Maybe the version of cryptsetup on that host does not yet support the luksChangeKey command. " )
36
+ Arver::Log.error( "Please verify that the old one still works. If the changeKey did in fact succeed, the plaintext key would now be: #{key}" )
37
+ Arver::Log.debug( "The output was: #{caller.output}" )
38
+ generator.remove_key( partition )
39
+ end
40
+ end
41
+
42
+ def post_action
43
+ self.generator.dump( self.keystore )
44
+ end
45
+ end
46
+ end
@@ -15,7 +15,8 @@ module TestConfigLoader
15
15
 
16
16
  def load_test_config
17
17
  Arver::LocalConfig.instance.config_dir= "spec/data"
18
+ Arver::LocalConfig.instance.username= "test"
18
19
  config = Arver::Config.instance
19
20
  config.load
20
21
  end
21
- end
22
+ end
@@ -1,3 +1,3 @@
1
1
  module Arver
2
- VERSION = '0.1.3'
2
+ VERSION = '0.1.4'
3
3
  end
@@ -1,7 +1,7 @@
1
1
  .\" generated with Ronn/v0.7.3
2
2
  .\" http://github.com/rtomayko/ronn/tree/0.7.3
3
3
  .
4
- .TH "ARVER" "5" "April 2012" "" ""
4
+ .TH "ARVER" "5" "July 2012" "" ""
5
5
  .
6
6
  .SH "NAME"
7
7
  \fBarver\fR \- LUKS on the loose
@@ -58,6 +58,10 @@ Adds permissions for USER on all targeted disks\.
58
58
  Removes permissions for USER on all targeted disks\.
59
59
  .
60
60
  .TP
61
+ \fB\-r\fR, \fB\-\-refresh TARGET\fR
62
+ Refresh the key on the target\.
63
+ .
64
+ .TP
61
65
  \fB\-i\fR, \fB\-\-info TARGET\fR
62
66
  Display the LUKS configuration of all targeted disks\.
63
67
  .
@@ -325,6 +329,22 @@ $ arver \-\-close TARGET
325
329
  .P
326
330
  For this action you can define hooks as well\. See \fBDisks\fR and \fBAction Open\fR for details\.
327
331
  .
332
+ .SH "Information about targets"
333
+ To gather various information about the different targets you can invoke
334
+ .
335
+ .IP "" 4
336
+ .
337
+ .nf
338
+
339
+ $ arver \-i TARGET
340
+ .
341
+ .fi
342
+ .
343
+ .IP "" 0
344
+ .
345
+ .P
346
+ Which will display you the current configuration of all devices, as well as different parameters of the LUKS device and slot usage\.
347
+ .
328
348
  .SH "Managing users"
329
349
  To add another user to one of the disks you need to have the public key of that user\. Just import his key into your gpg keyring\.
330
350
  .
@@ -351,7 +371,7 @@ For this command to work, you have to trust the gpg key of USERNAME\. See \fBman
351
371
  \fBarver\fR will create a random password for the specific user and add it to the user\-slot on the targeted disks\. Furthermore, the password is encrypted with the public key of the specific user and stored in the data storage under \fBarverdata/keys/USERNAME/\fR\.
352
372
  .
353
373
  .P
354
- For the other user to receive those new privileges he has to copy the new keys to his own \fBarverdata\fR\. So if you use a version controll system you should now commit the new keys\.
374
+ You now need to pass the new keyfile to the other user\. So if you use a version controll system you should now commit the new keys\. The other user should follow the paragraph \fBreceiving new keys\fR\.
355
375
  .
356
376
  .P
357
377
  If you are migrating from an existing LUKS infrastructure and want to add an initial user to the LUKS device, you will need to use the \fB\-\-ask\-password\fR option, to provide an existing password\.
@@ -378,30 +398,30 @@ By design it is not possible to know who has access to which disks by just looki
378
398
  .P
379
399
  You can however display the targets \fBinformation\fR to see which slots are used\. But to do this you need access to the server and the \fBusers\fR config\.
380
400
  .
381
- .SH "Information about targets"
382
- To gather various information about the different targets you can invoke
401
+ .SH "Receiving new Keys"
402
+ If you have been granted permission to a certain disk, the first thing you need to do, is to integrate the new keyfile in your arverdata\. If your group uses a version controll system, you can just pull the arverdata\. Otherwise you copy the received file into \fBarverdata/keys/USERNAME/\fR\.
403
+ .
404
+ .P
405
+ Important: The next thing you really should do, is to call
383
406
  .
384
407
  .IP "" 4
385
408
  .
386
409
  .nf
387
410
 
388
- $ arver \-i TARGET
411
+ $ arver \-\-refresh TARGET
389
412
  .
390
413
  .fi
391
414
  .
392
415
  .IP "" 0
393
416
  .
394
417
  .P
395
- Which will display you the current configuration of all devices, as well as different parameters of the LUKS device and slot usage\.
396
- .
397
- .SH "Garbage collection"
398
- As you might add and remove users to disks or reset access to disks the amount of generated key files with random passwords might grow and not all might be needed anymore\. Furthermore it is likely that due to various actions it might be obvious or at least reconstructable to which devices a certain user might have access\.
418
+ This will replace the actual luks key on the target once more with a fresh random key and also collect all your keys into one file\. Replacing the key is important to ensure, that the user who sent you the key, cannot record the actual luks key he sent you and use it as a backdoor in the future\.
399
419
  .
400
420
  .P
401
- To address this problem \fBarver\fR provides a garbage collection process, which will rearrange all your own keyfiles\. (Only your own as you are not able to read the others key files\.)
421
+ If you use a version controll system to store your \fBarverdata\fR you should commit the new key\.
402
422
  .
403
423
  .P
404
- You can do that by invoking the following command:
424
+ If you use an old cryptsetup version refresh might not work\. In that case you cannot replace the luks key\. Another problem in that case is, that it might become obvious or at least reconstructable to which devices you have access\. To counter this problem, do a garbage collection, which will collect all keys into one keyfile, with:
405
425
  .
406
426
  .IP "" 4
407
427
  .
metadata CHANGED
@@ -1,145 +1,138 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: arver
3
- version: !ruby/object:Gem::Version
4
- hash: 29
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.4
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 1
9
- - 3
10
- version: 0.1.3
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - o
14
9
  - andreas
15
10
  - mh
16
11
  autorequire:
17
12
  bindir: bin
18
13
  cert_chain: []
19
-
20
- date: 2012-06-13 00:00:00 Z
21
- dependencies:
22
- - !ruby/object:Gem::Dependency
14
+ date: 2012-07-24 00:00:00.000000000 Z
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
23
17
  name: gpgme
24
- requirement: &id001 !ruby/object:Gem::Requirement
18
+ requirement: !ruby/object:Gem::Requirement
25
19
  none: false
26
- requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- hash: 15
30
- segments:
31
- - 2
32
- - 0
33
- - 0
20
+ requirements:
21
+ - - ! '>='
22
+ - !ruby/object:Gem::Version
34
23
  version: 2.0.0
35
24
  type: :runtime
36
25
  prerelease: false
37
- version_requirements: *id001
38
- - !ruby/object:Gem::Dependency
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ none: false
28
+ requirements:
29
+ - - ! '>='
30
+ - !ruby/object:Gem::Version
31
+ version: 2.0.0
32
+ - !ruby/object:Gem::Dependency
39
33
  name: escape
40
- requirement: &id002 !ruby/object:Gem::Requirement
34
+ requirement: !ruby/object:Gem::Requirement
41
35
  none: false
42
- requirements:
43
- - - ">="
44
- - !ruby/object:Gem::Version
45
- hash: 23
46
- segments:
47
- - 0
48
- - 0
49
- - 4
36
+ requirements:
37
+ - - ! '>='
38
+ - !ruby/object:Gem::Version
50
39
  version: 0.0.4
51
40
  type: :runtime
52
41
  prerelease: false
53
- version_requirements: *id002
54
- - !ruby/object:Gem::Dependency
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: 0.0.4
48
+ - !ruby/object:Gem::Dependency
55
49
  name: activesupport
56
- requirement: &id003 !ruby/object:Gem::Requirement
50
+ requirement: !ruby/object:Gem::Requirement
57
51
  none: false
58
- requirements:
52
+ requirements:
59
53
  - - <
60
- - !ruby/object:Gem::Version
61
- hash: 7
62
- segments:
63
- - 3
64
- - 0
65
- - 0
54
+ - !ruby/object:Gem::Version
66
55
  version: 3.0.0
67
56
  type: :runtime
68
57
  prerelease: false
69
- version_requirements: *id003
70
- - !ruby/object:Gem::Dependency
58
+ version_requirements: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - <
62
+ - !ruby/object:Gem::Version
63
+ version: 3.0.0
64
+ - !ruby/object:Gem::Dependency
71
65
  name: highline
72
- requirement: &id004 !ruby/object:Gem::Requirement
66
+ requirement: !ruby/object:Gem::Requirement
73
67
  none: false
74
- requirements:
75
- - - ">="
76
- - !ruby/object:Gem::Version
77
- hash: 11
78
- segments:
79
- - 1
80
- - 6
81
- - 2
68
+ requirements:
69
+ - - ! '>='
70
+ - !ruby/object:Gem::Version
82
71
  version: 1.6.2
83
72
  type: :runtime
84
73
  prerelease: false
85
- version_requirements: *id004
86
- - !ruby/object:Gem::Dependency
74
+ version_requirements: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ! '>='
78
+ - !ruby/object:Gem::Version
79
+ version: 1.6.2
80
+ - !ruby/object:Gem::Dependency
87
81
  name: cucumber
88
- requirement: &id005 !ruby/object:Gem::Requirement
82
+ requirement: !ruby/object:Gem::Requirement
89
83
  none: false
90
- requirements:
91
- - - ">="
92
- - !ruby/object:Gem::Version
93
- hash: 51
94
- segments:
95
- - 0
96
- - 10
97
- - 2
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
98
87
  version: 0.10.2
99
88
  type: :development
100
89
  prerelease: false
101
- version_requirements: *id005
102
- - !ruby/object:Gem::Dependency
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ! '>='
94
+ - !ruby/object:Gem::Version
95
+ version: 0.10.2
96
+ - !ruby/object:Gem::Dependency
103
97
  name: rspec
104
- requirement: &id006 !ruby/object:Gem::Requirement
98
+ requirement: !ruby/object:Gem::Requirement
105
99
  none: false
106
- requirements:
107
- - - ">="
108
- - !ruby/object:Gem::Version
109
- hash: 27
110
- segments:
111
- - 2
112
- - 5
113
- - 0
100
+ requirements:
101
+ - - ! '>='
102
+ - !ruby/object:Gem::Version
114
103
  version: 2.5.0
115
104
  type: :development
116
105
  prerelease: false
117
- version_requirements: *id006
118
- - !ruby/object:Gem::Dependency
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ! '>='
110
+ - !ruby/object:Gem::Version
111
+ version: 2.5.0
112
+ - !ruby/object:Gem::Dependency
119
113
  name: rake
120
- requirement: &id007 !ruby/object:Gem::Requirement
114
+ requirement: !ruby/object:Gem::Requirement
121
115
  none: false
122
- requirements:
123
- - - ">="
124
- - !ruby/object:Gem::Version
125
- hash: 63
126
- segments:
127
- - 0
128
- - 9
129
- - 2
116
+ requirements:
117
+ - - ! '>='
118
+ - !ruby/object:Gem::Version
130
119
  version: 0.9.2
131
120
  type: :development
132
121
  prerelease: false
133
- version_requirements: *id007
134
- description: Arver helps you to manage a large amount of crypted devices easily and safe amongst a certain amount of members
122
+ version_requirements: !ruby/object:Gem::Requirement
123
+ none: false
124
+ requirements:
125
+ - - ! '>='
126
+ - !ruby/object:Gem::Version
127
+ version: 0.9.2
128
+ description: Arver helps you to manage a large amount of crypted devices easily and
129
+ safe amongst a certain amount of members
135
130
  email: arver@lists.immerda.ch
136
- executables:
131
+ executables:
137
132
  - arver
138
133
  extensions: []
139
-
140
134
  extra_rdoc_files: []
141
-
142
- files:
135
+ files:
143
136
  - lib/arver.rb
144
137
  - lib/arver/action.rb
145
138
  - lib/arver/adduser_action.rb
@@ -170,6 +163,7 @@ files:
170
163
  - lib/arver/open_action.rb
171
164
  - lib/arver/partition.rb
172
165
  - lib/arver/partition_hierarchy_node.rb
166
+ - lib/arver/refresh_action.rb
173
167
  - lib/arver/runtime_config.rb
174
168
  - lib/arver/ssh_command_wrapper.rb
175
169
  - lib/arver/string.rb
@@ -184,38 +178,29 @@ files:
184
178
  - bin/arver
185
179
  homepage: https://github.com/arver/arver
186
180
  licenses: []
187
-
188
181
  post_install_message:
189
182
  rdoc_options: []
190
-
191
- require_paths:
183
+ require_paths:
192
184
  - lib
193
- required_ruby_version: !ruby/object:Gem::Requirement
185
+ required_ruby_version: !ruby/object:Gem::Requirement
194
186
  none: false
195
- requirements:
196
- - - ">="
197
- - !ruby/object:Gem::Version
198
- hash: 3
199
- segments:
187
+ requirements:
188
+ - - ! '>='
189
+ - !ruby/object:Gem::Version
190
+ version: '0'
191
+ segments:
200
192
  - 0
201
- version: "0"
202
- required_rubygems_version: !ruby/object:Gem::Requirement
193
+ hash: 4241994790696947
194
+ required_rubygems_version: !ruby/object:Gem::Requirement
203
195
  none: false
204
- requirements:
205
- - - ">="
206
- - !ruby/object:Gem::Version
207
- hash: 23
208
- segments:
209
- - 1
210
- - 3
211
- - 6
196
+ requirements:
197
+ - - ! '>='
198
+ - !ruby/object:Gem::Version
212
199
  version: 1.3.6
213
200
  requirements: []
214
-
215
- rubyforge_project: "[none]"
201
+ rubyforge_project: ! '[none]'
216
202
  rubygems_version: 1.8.24
217
203
  signing_key:
218
204
  specification_version: 3
219
205
  summary: Open crypted devices automatically
220
206
  test_files: []
221
-