Class: LittleGhost::Sandbox::Capabilities

Inherits:
Object
  • Object
show all
Defined in:
lib/little_ghost/sandbox/capabilities.rb

Overview

Describes the operations, network modes, and isolation mechanism a Sandbox backend implements. process_spawn permits child creation, process_spawn_denial means the backend can prohibit it for one session, and process_tree_ownership means descendants remain owned through cleanup. Capabilities are immutable and safe to expose to tools, but are not a security certification of the surrounding deployment.

Constant Summary collapse

DEFAULT_FEATURES =

:nodoc:

%i[filesystem_read filesystem_list process_execute].freeze
NETWORK_MODES =

:nodoc:

%i[inherit none allowlist].freeze
ALIASES =

:nodoc:

{ # :nodoc:
  read: :filesystem_read,
  list: :filesystem_list,
  write: :filesystem_write,
  replace: :filesystem_replace,
  execute: :process_execute,
  spawn: :process_spawn
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(features: DEFAULT_FEATURES, network_modes: [:inherit], isolation: :none) ⇒ Capabilities

Builds a capability report from feature names and supported network modes. isolation is descriptive and does not itself grant an operation or establish a complete trust boundary.

Raises:

  • (ArgumentError)


28
29
30
31
32
33
34
35
36
# File 'lib/little_ghost/sandbox/capabilities.rb', line 28

def initialize(features: DEFAULT_FEATURES, network_modes: [:inherit], isolation: :none)
  @features = Array(features).map(&:to_sym).uniq.freeze
  @network_modes = Array(network_modes).map(&:to_sym).uniq.freeze
  invalid_modes = @network_modes - NETWORK_MODES
  raise ArgumentError, "unsupported network modes: #{invalid_modes.to_a.join(", ")}" unless invalid_modes.empty?

  @isolation = isolation.to_sym
  freeze
end

Instance Attribute Details

#featuresObject (readonly)

Operation names implemented by the backend.



39
40
41
# File 'lib/little_ghost/sandbox/capabilities.rb', line 39

def features
  @features
end

#isolationObject (readonly)

Descriptive isolation mechanism, such as :none or :container.



43
44
45
# File 'lib/little_ghost/sandbox/capabilities.rb', line 43

def isolation
  @isolation
end

#network_modesObject (readonly)

Network modes the backend can enforce.



41
42
43
# File 'lib/little_ghost/sandbox/capabilities.rb', line 41

def network_modes
  @network_modes
end

Class Method Details

.normalize(feature) ⇒ Object

:nodoc:



23
# File 'lib/little_ghost/sandbox/capabilities.rb', line 23

def self.normalize(feature) = ALIASES.fetch(feature.to_sym, feature.to_sym) # :nodoc:

Instance Method Details

#intersect(other) ⇒ Object

Produces a capability set no broader than both operands.



59
60
61
62
63
64
65
# File 'lib/little_ghost/sandbox/capabilities.rb', line 59

def intersect(other)
  self.class.new(
    features: features & other.features,
    network_modes: network_modes & other.network_modes,
    isolation:
  )
end

#supports?(feature, value = nil) ⇒ Boolean Also known as: include?

Indicates whether feature is available. For :network, value selects the requested mode.

Returns:

  • (Boolean)


47
48
49
50
51
52
53
# File 'lib/little_ghost/sandbox/capabilities.rb', line 47

def supports?(feature, value = nil)
  feature = self.class.normalize(feature)
  return network_modes.include?(value.to_sym) if feature == :network && value
  return !network_modes.empty? if feature == :network

  features.include?(feature)
end