Class: Ironclad::Cache::Keyctl

Inherits:
Object
  • Object
show all
Defined in:
lib/ironclad/cache/keyctl.rb

Overview

Linux kernel keyring via keyctl, stored in the user keyring (@u): it persists across this user's sessions and clears on reboot, at which point a miss simply re-seeds from the source.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.available?Boolean

Returns:

  • (Boolean)


11
12
13
14
15
# File 'lib/ironclad/cache/keyctl.rb', line 11

def self.available?
  ENV['PATH'].to_s.split(File::PATH_SEPARATOR).any? do |dir|
    File.executable?(File.join(dir, 'keyctl'))
  end
end

Instance Method Details

#read(name) ⇒ Object



17
18
19
20
21
22
23
24
25
# File 'lib/ironclad/cache/keyctl.rb', line 17

def read(name)
  id, _error, status = Open3.capture3(
    'keyctl', 'search', '@u', 'user', name
  )
  return unless status.success?

  out, _error, status = Open3.capture3('keyctl', 'pipe', id.chomp)
  status.success? ? out : nil
end

#write(name, key) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/ironclad/cache/keyctl.rb', line 27

def write(name, key)
  # `keyctl padd` creates the key with the kernel's default permissions
  # and offers no way to set them at creation, so changing them afterwards
  # needs setattr, which only a possessor has. @u grants the owning user
  # link permission, so linking it into @s first guarantees possession.
  Open3.capture3('keyctl', 'link', '@u', '@s')

  id, error, status = Open3.capture3(
    'keyctl', 'padd', 'user', name, '@u', stdin_data: key
  )
  return warn_failure(error, "cache #{name}") unless status.success?

  # possessor 0x3f (all), user 0x2f (view, read, write, search, setattr),
  # group and other none. A caller that does not possess the key gets only
  # the user byte, which has to cover every operation performed here.
  _out, error, status = Open3.capture3(
    'keyctl', 'setperm', id.chomp, '0x3f2f0000'
  )
  return warn_failure(error, "set permissions on #{name}") unless status.success?

  true
end