arver 0.1.5 → 0.1.9

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: eeb29f1cdc8ba4b8fd5a05791fe282f1a016440253f0b3591c95e30f573343f5
4
+ data.tar.gz: d41505b368abe1d3aa20c3fdf0ed13c3e382aadeb18e9b000778f156279dce0d
5
+ SHA512:
6
+ metadata.gz: f63236b680841a83333b3fce1c6a6c379e0a35820554f016821f1aff3998011c844655a883cd5f0514481b20618490aec95d005f320cfa57472b9f95585c73ff
7
+ data.tar.gz: 5734e53e093a97465751ae5e9cd95cee18f9565337ea94208f7eea9448c7a32f79b53aa1f92a8e82f0ac4a88127ca13fd91ca6e9838f5b7aaa284a4b05ea8e91
data/CHANGELOG.textile CHANGED
@@ -1,3 +1,11 @@
1
+ === 0.1.9 2022-01-29
2
+
3
+ * Add a new --open-systemd to support opening disks at startup. This mode is compatible with systemd-ask-password which is used to open disks in the initrd.
4
+
5
+ === 0.1.7 2018-09-01
6
+
7
+ * Updated gems to work with 2.5.1
8
+
1
9
  === 0.1.4 2012-07-24
2
10
 
3
11
  * Introducing the --refresh action to renew the luks key. You should always run this command, when receiving a new permission.
data/README.textile CHANGED
@@ -46,7 +46,6 @@ contains an arver package we recommend installation by your package manager.
46
46
  The following ruby gems are required for arver:
47
47
 
48
48
  * gpgme 2
49
- * activesupport 2
50
49
  * escape
51
50
  * highline
52
51
 
@@ -68,6 +67,10 @@ h1. Limitations
68
67
 
69
68
  h2. Known Issues
70
69
 
70
+ It is strongly advised not to set any 'encrypt-to' option in your gnupgp.conf.
71
+ Otherwise, when you issue a key to another person, you can still decrypt it
72
+ yourself, since gpg always encrypts it to this additional recipient.
73
+
71
74
  h3. GPGME and gpg-agent
72
75
 
73
76
  If arver asks you multiple times for the password, you might consider to use
data/lib/arver/action.rb CHANGED
@@ -54,7 +54,11 @@ module Arver
54
54
  end
55
55
 
56
56
  def load_key( partition )
57
- self.key= keystore.luks_key( partition )
57
+ if Arver::RuntimeConfig.instance.global_key_path
58
+ self.key= keystore.luks_key_for_path( Arver::RuntimeConfig.instance.global_key_path )
59
+ else
60
+ self.key= keystore.luks_key( partition )
61
+ end
58
62
 
59
63
  if( key.nil? )
60
64
  Arver::Log.error( "No permission on #{partition.path}. Skipping." )
@@ -7,7 +7,7 @@ class Arver::Bootstrap
7
7
 
8
8
  return true if options[:action] == :init
9
9
 
10
- unless local.username.present?
10
+ if "#{local.username}".empty?
11
11
  Arver::Log.error( "No user defined" )
12
12
  return false
13
13
  end
@@ -32,6 +32,7 @@ class Arver::Bootstrap
32
32
  rtc.violence = options[:violence]
33
33
  rtc.test_mode = options[:test_mode]
34
34
  rtc.trust_all = options[:trust_all]
35
+ rtc.global_key_path = options[:global_key_path]
35
36
  end
36
37
  end
37
38
  end
data/lib/arver/cli.rb CHANGED
@@ -34,6 +34,8 @@ module Arver
34
34
  "Show this help message.") { Arver::Log.write opts; return }
35
35
  opts.on("--ask-password",
36
36
  "Ask for an existing LUKS password when adding a new user.") { options[:ask_password] = true }
37
+ opts.on("--set-key KEYNAME", String,
38
+ "Manuall choose a key to use. The KEYNAME is in the format /LOCATION/MACHINE/DISK.") { |arg| options[:global_key_path] = arg }
37
39
  opts.on("-t", "--trust-all",
38
40
  "Use untrusted GPG Keys.") { options[:trust_all] = true }
39
41
  opts.on("--force",
@@ -57,6 +59,8 @@ module Arver
57
59
  opts.separator "Actions:"
58
60
  opts.on_tail( "-o TARGET", "--open TARGET", String,
59
61
  "Open target." ) { |arg| options[:argument][:target] = arg; options[:action] = :open; }
62
+ opts.on_tail( "--systemd-open TARGET", String,
63
+ "Open target during boot via systemd-asskpasswd." ) { |arg| options[:argument][:target] = arg; options[:action] = :systemd_open; }
60
64
  opts.on_tail( "-c TARGET", "--close TARGET", String,
61
65
  "Close target." ) { |arg| options[:argument][:target] = arg; options[:action] = :close; }
62
66
  opts.on_tail( "--create TARGET", String,
@@ -75,6 +79,8 @@ module Arver
75
79
  "LUKS info about a target.") { |arg| options[:argument][:target] = arg; options[:action] = :info; }
76
80
  opts.on_tail( "-l", "--list-targets",
77
81
  "List targets." ) { options[:action] = :list; }
82
+ opts.on_tail( "--dump-key TARGET", String,
83
+ "Dump raw luks passphrase." ) { |arg| options[:argument][:target] = arg; options[:action] = :dump; }
78
84
  opts.on_tail( "--init",
79
85
  "Setup a sample configuration." ) { options[:action] = :init; }
80
86
 
@@ -114,6 +120,7 @@ module Arver
114
120
  :gc => Arver::GCAction,
115
121
  :create => Arver::CreateAction,
116
122
  :open => Arver::OpenAction,
123
+ :systemd_open => Arver::SystemdOpenAction,
117
124
  :close => Arver::CloseAction,
118
125
  :adduser => Arver::AdduserAction,
119
126
  :deluser => Arver::DeluserAction,
@@ -121,6 +128,7 @@ module Arver
121
128
  :key_info => Arver::KeyInfoAction,
122
129
  :init => Arver::InitialConfigAction,
123
130
  :refresh => Arver::RefreshAction,
131
+ :dump => Arver::DumpKeyAction,
124
132
  }
125
133
 
126
134
  action = (actions[ action ]).new( target_list )
@@ -1,8 +1,7 @@
1
1
  module Arver
2
2
  class CommandWrapper
3
-
4
3
  attr_accessor :command, :arguments_array, :return_value, :output
5
-
4
+
6
5
  def self.create( cmd, args = [] )
7
6
  c = CommandWrapper.new
8
7
  c.command= cmd
@@ -10,8 +9,12 @@ module Arver
10
9
  c
11
10
  end
12
11
 
13
- # copy from shellwords.rb
14
12
  def shellescape(str)
13
+ CommandWrapper.shellescape(str)
14
+ end
15
+
16
+ # copy from shellwords.rb
17
+ def self.shellescape(str)
15
18
  str = str.to_s
16
19
 
17
20
  # An empty argument will be skipped, so return empty quotes.
data/lib/arver/config.rb CHANGED
@@ -15,17 +15,22 @@ module Arver
15
15
  end
16
16
 
17
17
  def load
18
- if( ! File.exists?( path ) )
19
- Arver::Log.error( "config-dir "+path+" does not exist" )
20
- exit
18
+ if !File.directory?(path)
19
+ Arver::Log.error("config "+path+" does not exist")
20
+ exit 1
21
21
  end
22
- @users= ( load_file( File.join(path,'users') ) )
22
+ @users = load_file(File.join(path,'users')) || {}
23
+
23
24
  tree.clear
24
- tree.from_hash( load_file( File.join(path,'disks') ) )
25
+ tree.from_hash(load_file(File.join(path,'disks')))
25
26
  end
26
27
 
27
28
  def load_file( filename )
28
- YAML.load( File.read(filename) ) if File.exists?( filename )
29
+ if !File.exists?(filename)
30
+ Arver::Log.error("missing config #{filename}")
31
+ exit 1
32
+ end
33
+ YAML.load(File.read(filename))
29
34
  end
30
35
 
31
36
  def save
@@ -35,7 +40,7 @@ module Arver
35
40
  end
36
41
 
37
42
  def exists?( user )
38
- ! users[user].nil?
43
+ !users[user].nil?
39
44
  end
40
45
 
41
46
  def gpg_key user
@@ -45,6 +50,13 @@ module Arver
45
50
  def slot user
46
51
  users[user]['slot'] if exists?(user)
47
52
  end
53
+
54
+ def user_at(slot)
55
+ users.each do |name, conf|
56
+ return name if slot == conf['slot']
57
+ end
58
+ 'unknown'
59
+ end
48
60
 
49
61
  def == other
50
62
  return tree == other.tree && users == other.users if other.is_a?(Arver::Config)
@@ -0,0 +1,29 @@
1
+ module Arver
2
+ class DumpKeyAction < Action
3
+ def initialize(target_list)
4
+ super(target_list)
5
+ self.open_keystore
6
+ end
7
+
8
+ def verify?(partition)
9
+ load_key(partition)
10
+ end
11
+
12
+ def execute_partition( partition )
13
+ Arver::Log.info("key for #{partition.path}:")
14
+ Arver::Log.info(key)
15
+ end
16
+
17
+ def pre_host( host )
18
+ end
19
+
20
+ def pre_partition( partition )
21
+ end
22
+
23
+ def post_partition( partition )
24
+ end
25
+
26
+ def post_host( host )
27
+ end
28
+ end
29
+ end
data/lib/arver/host.rb CHANGED
@@ -2,7 +2,7 @@ module Arver
2
2
  class Host
3
3
 
4
4
  attr_accessor :port, :username
5
- attr_writer :address
5
+ attr_writer :address, :boot_address
6
6
 
7
7
  include Arver::PartitionHierarchyNode
8
8
  include Arver::NodeWithScriptHooks
@@ -25,21 +25,33 @@ module Arver
25
25
  self.name
26
26
  end
27
27
 
28
+ def boot_address
29
+ return @boot_address unless @boot_address.nil?
30
+ address
31
+ end
32
+
28
33
  def port
29
34
  return @port unless @port.nil?
30
35
  '22'
31
36
  end
32
37
 
33
38
  def username
34
- return @username unless @username.nil?
35
- 'root'
39
+ case @username
40
+ when nil
41
+ 'root'
42
+ when '#arveruser'
43
+ Arver::LocalConfig.instance.username
44
+ else
45
+ @username
46
+ end
36
47
  end
37
48
 
38
49
  def to_yaml
39
50
  yaml = ""
40
- yaml += "'address': '"+address+"'\n" unless @address.nil?
41
- yaml += "'port': '"+port+"'\n" unless @port.nil?
42
- yaml += "'username': '"+username+"'\n" unless @username.nil?
51
+ yaml += "'address': '"+@address+"'\n" unless @address.nil?
52
+ yaml += "'boot_address': '"+@boot_address+"'\n" unless @boot_address.nil?
53
+ yaml += "'port': '"+@port+"'\n" unless @port.nil?
54
+ yaml += "'username': '"+@username+"'\n" unless @username.nil?
43
55
  yaml += script_hooks_to_yaml
44
56
  yaml += super
45
57
  end
@@ -55,6 +67,10 @@ module Arver
55
67
  self.address = data
56
68
  next
57
69
  end
70
+ if( name == "boot_address" )
71
+ self.boot_address = data
72
+ next
73
+ end
58
74
  if( name == "username" )
59
75
  self.username= data
60
76
  next
@@ -3,6 +3,7 @@ module Arver
3
3
  def initialize( target_list )
4
4
  super( target_list )
5
5
  self.open_keystore
6
+ Arver::Log.info("Warning: existence of a keyslot is not a guarantee that the user can access it")
6
7
  end
7
8
 
8
9
  def pre_host( host )
@@ -10,13 +11,44 @@ module Arver
10
11
  end
11
12
 
12
13
  def execute_partition(partition)
13
- info = {}
14
- (caller = Arver::LuksWrapper.dump(partition)).execute
15
- caller.output.each_line do |line|
16
- next unless line =~ /^[A-Z].*: .*$/
17
- info.store(*line.split(':',2).collect{|f| f.strip })
14
+ cmd = Arver::LuksWrapper.dump(partition)
15
+ cmd.execute
16
+ info = cmd.output
17
+ info =~ /Version:[\s]+(\d)/
18
+ version = $1
19
+ slots = []
20
+
21
+ head = " #{sprintf("%0-10s",partition.name[0...10])} :"+
22
+ " #{sprintf("%0-30s",partition.device_path[0...30])}"
23
+
24
+ if version != '1' && version != '2'
25
+ Arver::Log.info("#{head} : Unsupported luks version")
26
+ return
27
+ end
28
+
29
+ if version == '1'
30
+ info.each_line do |line|
31
+ if line =~ /Key Slot (\d): ENABLED/
32
+ slots << Integer($1)
33
+ end
34
+ end
35
+ else
36
+ keyslots = []
37
+ start = false
38
+ info.each_line do |line|
39
+ if line =~ /Keyslots:/
40
+ start = true
41
+ next
42
+ end
43
+ next unless start
44
+ break unless line =~ /^\s/
45
+ if line =~ /[\s]+(\d): luks2/
46
+ slots << Integer($1)
47
+ end
48
+ end
18
49
  end
19
- Arver::Log.info(" #{sprintf("%0-20s",partition.name.first(20))}: #{sprintf("%0-40s",partition.device_path.first(40))}: Slots: #{(0..7).map{|i| info["Key Slot #{i}"] == 'ENABLED' ? 'X' : '_'}.join}; LUKSv#{info['Version']}; Cypher: #{info['Cipher name']}:#{info['Cipher mode']}:#{info['Hash spec']}; UUID=#{info['UUID']}")
50
+ slots = slots.map{|s| "#{Config.instance.user_at(s)}(#{s})"}.join(",")
51
+ Arver::Log.info("#{head} : #{slots}")
20
52
  end
21
53
  end
22
54
  end
@@ -1,3 +1,5 @@
1
+ require 'securerandom'
2
+
1
3
  module Arver
2
4
  class KeyGenerator
3
5
  def initialize
@@ -5,7 +7,7 @@ module Arver
5
7
  end
6
8
 
7
9
  def generate_key( partition )
8
- key = ActiveSupport::SecureRandom.base64(192)
10
+ key = SecureRandom.base64(192)
9
11
  @keys[partition] = key
10
12
  end
11
13
 
@@ -1,3 +1,5 @@
1
+ require 'securerandom'
2
+
1
3
  module Arver
2
4
  class KeySaver
3
5
 
@@ -37,6 +39,7 @@ module Arver
37
39
  #compress the key before applying padding, so the size after encryption+compression by gpg is more stable...
38
40
  key = deflate(key)
39
41
  unless GPGKeyManager.check_key_of( user )
42
+ Arver::Log.error( "Error no key for #{user}" )
40
43
  return
41
44
  end
42
45
  gpg_key = GPGKeyManager.key_of( user )
@@ -115,19 +118,19 @@ module Arver
115
118
  end
116
119
 
117
120
  def self.add_padding( key )
118
- marker = "--"+ActiveSupport::SecureRandom.base64( 82 )
121
+ marker = "--"+SecureRandom.base64( 82 )
119
122
  size = 200000
120
123
  padding_size = size - key.size
121
124
  if padding_size <= 0
122
125
  padding_size = 0
123
126
  Arver::Log.warn( "Warning: Your arver keys exceed the maximal padding size, therefore i can no longer disguise how many keys you possess.")
124
127
  end
125
- padding = ActiveSupport::SecureRandom.base64( padding_size )[0..padding_size]
128
+ padding = SecureRandom.base64( padding_size )[0..padding_size]
126
129
  marker +"\n"+ key + "\n" + marker + "\n" + padding
127
130
  end
128
131
 
129
132
  def self.substract_padding( key )
130
- if( key.starts_with? '--- ' )
133
+ if key[0...4] == "--- "
131
134
  Arver::Log.warn( "Warning: you are using deprecated unpadded keyfiles. Please run garbage collect!" )
132
135
  return key
133
136
  end
@@ -15,23 +15,23 @@ module Arver
15
15
  end
16
16
  end
17
17
 
18
- attr_accessor :username, :loaded
18
+ attr_reader :username, :loaded
19
19
 
20
20
  def initialize( name )
21
21
  @keys = {}
22
22
  @key_versions = {}
23
- self.username= name
24
- self.loaded = false
23
+ @username = name
24
+ @loaded = false
25
25
  end
26
26
 
27
27
  def load
28
28
  flush_keys
29
- KeySaver.read( self.username ).each do | loaded |
29
+ KeySaver.read(username).each do | loaded |
30
30
  YAML.load( loaded ).each do | target, key |
31
31
  load_luks_key(target,key)
32
32
  end
33
33
  end
34
- self.loaded = true
34
+ @loaded = true
35
35
  end
36
36
 
37
37
  def save
@@ -51,9 +51,13 @@ module Arver
51
51
  end
52
52
 
53
53
  def luks_key(partition)
54
- @keys[partition.path][:key] unless ! @keys[partition.path]
54
+ luks_key_for_path(partition.path)
55
55
  end
56
56
 
57
+ def luks_key_for_path(path)
58
+ @keys[path][:key] unless ! @keys[path]
59
+ end
60
+
57
61
  def load_luks_key(partition, new_key)
58
62
  if( new_key.kind_of? Hash )
59
63
  if( ! @keys[partition] || @keys[partition][:time] <= new_key[:time] )
@@ -1,5 +1,3 @@
1
- require 'active_support/core_ext'
2
-
3
1
  module Arver
4
2
  module PartitionHierarchyNode
5
3
 
@@ -72,7 +70,7 @@ module Arver
72
70
  def find( name )
73
71
  found = []
74
72
  self.each_node do | node |
75
- found += [ node ] if ( node.name == name || node.path.ends_with?( name ) )
73
+ found += [ node ] if (node.name == name || node.path =~ /#{name}$/)
76
74
  end
77
75
  found
78
76
  end
@@ -5,7 +5,7 @@ module Arver
5
5
 
6
6
  include Singleton
7
7
 
8
- attr_accessor :test_mode, :dry_run, :force, :violence, :ask_password, :trust_all
8
+ attr_accessor :test_mode, :dry_run, :force, :violence, :ask_password, :trust_all, :global_key_path
9
9
 
10
10
  instance.test_mode= false
11
11
  instance.dry_run= false
@@ -1,20 +1,29 @@
1
1
  module Arver
2
2
  class SSHCommandWrapper < CommandWrapper
3
-
4
- attr_accessor :host, :user, :port, :as_root
5
-
6
- def self.create( cmd, args, host, as_root = false )
3
+ attr_accessor :host, :user, :port, :as_root, :on_boot
4
+
5
+ def self.create( cmd, args, host, as_root = false, on_boot = false)
7
6
  c = SSHCommandWrapper.new
8
7
  c.host= host
9
8
  c.as_root= as_root
10
9
  c.command= cmd
11
10
  c.arguments_array= args
11
+ c.on_boot = on_boot
12
12
  c
13
13
  end
14
-
14
+
15
15
  def escaped_command
16
- sudo = if as_root && host.username != "root" then "sudo" else "" end
17
- "ssh -p #{shellescape(host.port)} #{shellescape(host.username)}@#{shellescape(host.address)} #{sudo} #{super}"
16
+ addr = (on_boot ? host.boot_address : nil) || host.address
17
+ user = on_boot ? 'root' : host.username
18
+ port = on_boot ? '22' : host.port
19
+ sudo = if as_root && on_boot && host.username != "root" then "sudo" else "" end
20
+ "ssh -p #{shellescape(port)} #{shellescape(user)}@#{shellescape(addr)} #{sudo} #{super}"
21
+ end
22
+
23
+ def self.is_system_running?(partition)
24
+ wr = Arver::SSHCommandWrapper.create("systemctl", ["is-system-running"], partition.parent, true, true)
25
+ wr.execute
26
+ wr.success? && !['initializing','starting'].include?(wr.output.chomp)
18
27
  end
19
28
  end
20
29
  end
@@ -0,0 +1,83 @@
1
+ require 'tmpdir'
2
+
3
+ module Arver
4
+ class SystemdOpenAction < Action
5
+ def initialize( target_list )
6
+ super( target_list )
7
+ self.open_keystore
8
+ end
9
+
10
+ def verify?( partition )
11
+ if(Arver::SSHCommandWrapper.is_system_running?(partition))
12
+ Arver::Log.error( "#{partition.parent.name} already up. Use normal open, skipping." )
13
+ return false
14
+ end
15
+ return false unless load_key( partition )
16
+ true
17
+ end
18
+
19
+ def get_socket(host, partid)
20
+ # Check which partitions are waiting for a password
21
+ # see https://www.freedesktop.org/wiki/Software/systemd/PasswordAgents/
22
+ files_exec = Arver::SSHCommandWrapper.create("ls", ["/run/systemd/ask-password/ask.*"], host, true, true)
23
+ files_exec.execute
24
+ files = files_exec.output.split("\n")
25
+
26
+ # Find the socket for the partition we want to open
27
+ files.each do |f|
28
+ f_exec = Arver::SSHCommandWrapper.create("cat", [f], host, true, true)
29
+ f_exec.execute
30
+ ask_file = f_exec.output
31
+ if ask_file =~ /#{partid}/
32
+ ask_file =~ /Socket=(.*)/
33
+ return $1
34
+ end
35
+ end
36
+ nil
37
+ end
38
+
39
+ def execute_partition( partition )
40
+ Arver::Log.info( "opening: "+partition.path )
41
+ socket = nil
42
+ partid = nil
43
+ host = partition.parent
44
+
45
+ # Find the uuid of this partition
46
+ partid_exec = Arver::SSHCommandWrapper.create("blkid", ["/dev/#{partition.device}"], host, true, true)
47
+ partid_exec.execute
48
+ partid = partid_exec.output.chomp.gsub(/.* UUID=\"([^"]+)\" .*/,'\1')
49
+ unless partid =~ /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/
50
+ puts "Could not get uuid of disk"
51
+ throw( :abort_action )
52
+ end
53
+
54
+ socket = get_socket(host, partid)
55
+ if socket.nil?
56
+ puts "Disk is not waiting to be opened"
57
+ throw( :abort_action )
58
+ end
59
+
60
+ # Upload password-agent binary and supply password to the correct socket
61
+ binary = File.join(ROOT_DIR, "vendor", "password-agent")
62
+ unless File.exists?(binary)
63
+ puts "This gem is missing the native password-agent binary"
64
+ throw( :abort_action )
65
+ end
66
+ # This is an epic hack to have a binary with exec permission
67
+ # initrd does not have chmod, so we copy an existing binary and override it
68
+ r = Arver::SSHCommandWrapper.create("cp", ["/bin/true", "/run/password-agent"], host, true, true).execute
69
+ r = Arver::SSHCommandWrapper.create("cat", ["- > /run/password-agent"], host, true, true)
70
+ r.execute(File.read(binary))
71
+ unless r.success?
72
+ puts "Could not upload password-agent"
73
+ throw( :abort_action )
74
+ end
75
+
76
+ # Pass password
77
+ a = Arver::SSHCommandWrapper.create("/run/password-agent", [socket], host, true, true)
78
+ a.execute(key)
79
+
80
+ # Cannot check if it worked, since if it did, the server rebooted
81
+ end
82
+ end
83
+ end
@@ -16,6 +16,7 @@ module TestConfigLoader
16
16
  def load_test_config
17
17
  Arver::LocalConfig.instance.config_dir= "spec/data"
18
18
  Arver::LocalConfig.instance.username= "test"
19
+ Arver::RuntimeConfig.instance.trust_all = true
19
20
  config = Arver::Config.instance
20
21
  config.load
21
22
  end
data/lib/arver/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Arver
2
- VERSION = '0.1.5'
2
+ VERSION = '0.1.9'
3
3
  end
data/lib/arver.rb CHANGED
@@ -1,6 +1,7 @@
1
- %w{singleton yaml fileutils rubygems active_support/secure_random highline/import gpgme openssl zlib}.each {|f| require f }
1
+ %w{singleton yaml fileutils rubygems highline/import gpgme 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 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}" }
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 systemd_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 dump_key_action }.each {|f| require "arver/#{f}" }
6
6
 
7
+ ROOT_DIR = File.expand_path('../..',__FILE__)
data/man/arver.5 CHANGED
@@ -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" "July 2012" "" ""
4
+ .TH "ARVER" "5" "January 2022" "" ""
5
5
  .
6
6
  .SH "NAME"
7
7
  \fBarver\fR \- LUKS on the loose
@@ -46,6 +46,10 @@ Creates LUKS partitions for \fBarver\fR on all targeted disks\.
46
46
  Opens all targeted disks\.
47
47
  .
48
48
  .TP
49
+ \fB\-\-systemd\-open TARGET\fR
50
+ Same as above, but supplying password to systemd ask\-password, used during system startup\.
51
+ .
52
+ .TP
49
53
  \fB\-\-close TARGET\fR
50
54
  Closes all targeted disks\.
51
55
  .
@@ -193,15 +197,16 @@ The \fBdisks\fR file contains the following hash tree in yaml notation:
193
197
  \'disk2\' :
194
198
  \'device\' : \'sdb1\'
195
199
  \'host2\':
196
- \'address\': \'host2\.example\.com\'
197
- \'port\' : \'2222\'
198
- \'mails\' :
200
+ \'address\' : \'host2\.example\.com\'
201
+ \'port\' : \'2222\'
202
+ \'username\': \'hans\'
203
+ \'mails\' :
199
204
  \'device\' : \'nonraid/mails\'
200
205
  \'pre_open\': \'pre_open_disk_script\.sh\'
201
206
  \'hostgroup2\':
202
207
  \'host3\':
203
208
  \'address\' : \'host3\.example\.com\'
204
- \'username\': \'foo\'
209
+ \'username\': \'#arveruser\'
205
210
  \'secure\' :
206
211
  \'device\' : \'storage/secure\'
207
212
  .
@@ -235,6 +240,19 @@ will present you the tree of the various targets in your \fBdisks\fR configurati
235
240
  \fBhost1\fR, \fBhost2\fR and \fBhost3\fR are identifiers for different hosts\. These host\- objects can contain multiple disks and can have further information such as the \fBaddress\fR of the host or the ssh\-\fBport\fR number if the ssh daemon is not running on the standart port\.
236
241
  .
237
242
  .P
243
+ \fBusername\fR defines the ssh login\-user\. By default it is \fBroot\fR\. To always use the same username as arver (as defined by \fB\-u\fR or in \fB\.arver\fR) set the username to \fB#arveruser\fR\. If the user is not \fBroot\fR, the actual LUKS commands will be executed via \fBsudo\fR and you need the following entry in your sudoers file on this machine (assuming the user is in the admin group):
244
+ .
245
+ .IP "" 4
246
+ .
247
+ .nf
248
+
249
+ %admin ALL=NOPASSWD: /usr/bin/test, /sbin/cryptsetup
250
+ .
251
+ .fi
252
+ .
253
+ .IP "" 0
254
+ .
255
+ .P
238
256
  You can also add script hooks to any host or disk\. Those will be run during the \fBopen\fR and \fBclose\fR actions at the appropriate time\. The possible options are: \fBpre_open\fR, \fBpre_close\fR, \fBpost_open\fR and \fBpost_close\fR\.
239
257
  .
240
258
  .P
@@ -313,6 +331,22 @@ Those scripts have to be present at the actual host\.
313
331
  .P
314
332
  If you don\'t have a key for any of the disks that you wish to open it will be skipped (along with its script hooks)\.
315
333
  .
334
+ .P
335
+ Arver can also open a disk that is waiting for a password by systemd\-ask\-password\. Typically this is happening during startup of a physical system, e\.g\., within the initrd\. For that there is a special mode called:
336
+ .
337
+ .IP "" 4
338
+ .
339
+ .nf
340
+
341
+ $ arver \-\-systemd\-open TARGET
342
+ .
343
+ .fi
344
+ .
345
+ .IP "" 0
346
+ .
347
+ .P
348
+ Note, due to the provided api by systemd, there is unfortunately no indication if the command suceeded\. Typically unlocking the last pending disk automatically continues booting the server\. In case the inird ssh has a differen hostname or address than the acutal system, there is an optional \fBboot_address\fR config in the disks configuration, to override the default one\. This mode expects ssh to be on port 22 and user root\.
349
+ .
316
350
  .SH "Action Close"
317
351
  Closing luks devices is simply done by invoking
318
352
  .
@@ -436,6 +470,32 @@ $ arver \-g
436
470
  .P
437
471
  If you use a version controll system to store your \fBarverdata\fR you should do this always before commiting the \fBarverdata\fR\.
438
472
  .
473
+ .SH "Migrating keys"
474
+ If you want to move a disk to a different server or a server to a different location, there is currently no nice way of doing this\. You can however apply the following workaround, after you moved/renamed a disk in the config file:
475
+ .
476
+ .IP "" 4
477
+ .
478
+ .nf
479
+
480
+ $ arver \-\-set\-key /OLD_LOCATION/OLD_MACHINE/OLD_NAME \-\-refresh NEW_NAME
481
+ .
482
+ .fi
483
+ .
484
+ .IP "" 0
485
+ .
486
+ .P
487
+ For example after moving \fBa_disk\fR from \fBa_server\fR at \fBa_location\fR to \fBsome_server\fR at \fBsome_location\fR in the config, you can restore your access with:
488
+ .
489
+ .IP "" 4
490
+ .
491
+ .nf
492
+
493
+ $ arver \-\-set\-key /a_location/a_server/a_disk \-\-refresh /some_location/some_server/a_disk
494
+ .
495
+ .fi
496
+ .
497
+ .IP "" 0
498
+ .
439
499
  .SH "SEE ALSO"
440
500
  \fBcryptsetup\fR(8)\. \fBgnupg\fR(7)\.
441
501
  .
Binary file
metadata CHANGED
@@ -1,122 +1,98 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: arver
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
5
- prerelease:
4
+ version: 0.1.9
6
5
  platform: ruby
7
6
  authors:
8
7
  - o
9
8
  - andreas
10
9
  - mh
11
- autorequire:
10
+ autorequire:
12
11
  bindir: bin
13
12
  cert_chain: []
14
- date: 2012-07-25 00:00:00.000000000 Z
13
+ date: 2022-01-29 00:00:00.000000000 Z
15
14
  dependencies:
16
15
  - !ruby/object:Gem::Dependency
17
16
  name: gpgme
18
17
  requirement: !ruby/object:Gem::Requirement
19
- none: false
20
18
  requirements:
21
- - - ! '>='
19
+ - - ">="
22
20
  - !ruby/object:Gem::Version
23
21
  version: 2.0.0
24
22
  type: :runtime
25
23
  prerelease: false
26
24
  version_requirements: !ruby/object:Gem::Requirement
27
- none: false
28
25
  requirements:
29
- - - ! '>='
26
+ - - ">="
30
27
  - !ruby/object:Gem::Version
31
28
  version: 2.0.0
32
- - !ruby/object:Gem::Dependency
33
- name: activesupport
34
- requirement: !ruby/object:Gem::Requirement
35
- none: false
36
- requirements:
37
- - - <
38
- - !ruby/object:Gem::Version
39
- version: 3.0.0
40
- type: :runtime
41
- prerelease: false
42
- version_requirements: !ruby/object:Gem::Requirement
43
- none: false
44
- requirements:
45
- - - <
46
- - !ruby/object:Gem::Version
47
- version: 3.0.0
48
29
  - !ruby/object:Gem::Dependency
49
30
  name: highline
50
31
  requirement: !ruby/object:Gem::Requirement
51
- none: false
52
32
  requirements:
53
- - - ! '>='
33
+ - - ">="
54
34
  - !ruby/object:Gem::Version
55
35
  version: 1.6.2
56
36
  type: :runtime
57
37
  prerelease: false
58
38
  version_requirements: !ruby/object:Gem::Requirement
59
- none: false
60
39
  requirements:
61
- - - ! '>='
40
+ - - ">="
62
41
  - !ruby/object:Gem::Version
63
42
  version: 1.6.2
64
43
  - !ruby/object:Gem::Dependency
65
44
  name: cucumber
66
45
  requirement: !ruby/object:Gem::Requirement
67
- none: false
68
46
  requirements:
69
- - - ! '>='
47
+ - - ">="
70
48
  - !ruby/object:Gem::Version
71
49
  version: 0.10.2
72
50
  type: :development
73
51
  prerelease: false
74
52
  version_requirements: !ruby/object:Gem::Requirement
75
- none: false
76
53
  requirements:
77
- - - ! '>='
54
+ - - ">="
78
55
  - !ruby/object:Gem::Version
79
56
  version: 0.10.2
80
57
  - !ruby/object:Gem::Dependency
81
58
  name: rspec
82
59
  requirement: !ruby/object:Gem::Requirement
83
- none: false
84
60
  requirements:
85
- - - ! '>='
61
+ - - ">="
86
62
  - !ruby/object:Gem::Version
87
63
  version: 2.5.0
88
64
  type: :development
89
65
  prerelease: false
90
66
  version_requirements: !ruby/object:Gem::Requirement
91
- none: false
92
67
  requirements:
93
- - - ! '>='
68
+ - - ">="
94
69
  - !ruby/object:Gem::Version
95
70
  version: 2.5.0
96
71
  - !ruby/object:Gem::Dependency
97
72
  name: rake
98
73
  requirement: !ruby/object:Gem::Requirement
99
- none: false
100
74
  requirements:
101
- - - ! '>='
75
+ - - ">="
102
76
  - !ruby/object:Gem::Version
103
77
  version: 0.9.2
104
78
  type: :development
105
79
  prerelease: false
106
80
  version_requirements: !ruby/object:Gem::Requirement
107
- none: false
108
81
  requirements:
109
- - - ! '>='
82
+ - - ">="
110
83
  - !ruby/object:Gem::Version
111
84
  version: 0.9.2
112
- description: Arver helps you to manage a large amount of crypted devices easily and
113
- safe amongst a certain amount of members
85
+ description: Arver helps you to share access to LUKS devices easily and safely in
86
+ a team
114
87
  email: arver@lists.immerda.ch
115
88
  executables:
116
89
  - arver
117
90
  extensions: []
118
91
  extra_rdoc_files: []
119
92
  files:
93
+ - CHANGELOG.textile
94
+ - README.textile
95
+ - bin/arver
120
96
  - lib/arver.rb
121
97
  - lib/arver/action.rb
122
98
  - lib/arver/adduser_action.rb
@@ -127,6 +103,7 @@ files:
127
103
  - lib/arver/config.rb
128
104
  - lib/arver/create_action.rb
129
105
  - lib/arver/deluser_action.rb
106
+ - lib/arver/dump_key_action.rb
130
107
  - lib/arver/gc_action.rb
131
108
  - lib/arver/gpg_key_manager.rb
132
109
  - lib/arver/host.rb
@@ -151,40 +128,34 @@ files:
151
128
  - lib/arver/runtime_config.rb
152
129
  - lib/arver/ssh_command_wrapper.rb
153
130
  - lib/arver/string.rb
131
+ - lib/arver/systemd_open_action.rb
154
132
  - lib/arver/target_list.rb
155
133
  - lib/arver/test_config_loader.rb
156
134
  - lib/arver/test_partition.rb
157
135
  - lib/arver/tree.rb
158
136
  - lib/arver/version.rb
159
- - README.textile
160
- - CHANGELOG.textile
161
137
  - man/arver.5
162
- - bin/arver
163
- homepage: https://github.com/arver/arver
138
+ - vendor/password-agent
139
+ homepage: https://code.immerda.ch/immerda/apps/arver
164
140
  licenses: []
165
- post_install_message:
141
+ metadata: {}
142
+ post_install_message:
166
143
  rdoc_options: []
167
144
  require_paths:
168
145
  - lib
169
146
  required_ruby_version: !ruby/object:Gem::Requirement
170
- none: false
171
147
  requirements:
172
- - - ! '>='
148
+ - - ">="
173
149
  - !ruby/object:Gem::Version
174
- version: '0'
175
- segments:
176
- - 0
177
- hash: 947642704890013429
150
+ version: '2.2'
178
151
  required_rubygems_version: !ruby/object:Gem::Requirement
179
- none: false
180
152
  requirements:
181
- - - ! '>='
153
+ - - ">="
182
154
  - !ruby/object:Gem::Version
183
155
  version: 1.3.6
184
156
  requirements: []
185
- rubyforge_project: ! '[none]'
186
- rubygems_version: 1.8.24
187
- signing_key:
188
- specification_version: 3
189
- summary: Open crypted devices automatically
157
+ rubygems_version: 3.1.2
158
+ signing_key:
159
+ specification_version: 4
160
+ summary: LUKS for groups
190
161
  test_files: []