Class: LittleGhost::Sandbox::NetworkPolicy

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

Overview

Declares outbound connectivity for sandbox-launched processes. A network policy does not apply to providers or arbitrary Ruby tools in the host.

Constant Summary collapse

MODES =

:nodoc:

%i[inherit none allowlist].freeze
INSPECTION_MODES =

:nodoc:

%i[connect http].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(mode:, allow: [], inspection: :connect, gateway: nil, authorizer: nil, forward_headers: [], mutation_headers: []) ⇒ NetworkPolicy

Builds an outbound policy. Enforcement remains the configured gateway's responsibility.

Raises:



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/little_ghost/sandbox/network_policy.rb', line 23

def initialize(mode:, allow: [], inspection: :connect, gateway: nil, authorizer: nil, forward_headers: [], mutation_headers: [])
  mode = mode.to_sym
  inspection = inspection.to_sym
  raise PolicyError, "network mode must be :inherit, :none, or :allowlist" unless MODES.include?(mode)
  unless INSPECTION_MODES.include?(inspection)
    raise PolicyError, "network inspection must be :connect or :http"
  end
  if mode != :allowlist && (!Array(allow).empty? || gateway || authorizer || !Array(forward_headers).empty? || !Array(mutation_headers).empty?)
    raise PolicyError, "network allow, gateway, authorizer, and header policy require mode :allowlist"
  end
  if inspection == :http && mode != :allowlist
    raise PolicyError, "HTTP inspection requires mode :allowlist"
  end
  if inspection == :http && !authorizer
    raise PolicyError, "HTTP inspection requires an authorizer"
  end
  if mode == :allowlist && Array(allow).empty?
    raise PolicyError, "network mode :allowlist requires at least one exact destination"
  end

  @mode = mode
  @allow = Array(allow).map { |endpoint| normalize_endpoint(endpoint) }.uniq.freeze
  @inspection = inspection
  @gateway = gateway
  @authorizer = authorizer
  @forward_headers = Array(forward_headers).map { |name| normalize_header_name(name) }.uniq.freeze
  @mutation_headers = Array(mutation_headers).map { |name| normalize_header_name(name) }.uniq.freeze
  freeze
end

Instance Attribute Details

#allowObject (readonly)

Normalized endpoints accepted by an allowlist gateway.



56
57
58
# File 'lib/little_ghost/sandbox/network_policy.rb', line 56

def allow
  @allow
end

#authorizerObject (readonly)

Trusted request authorizer used by HTTP inspection, when supplied.



62
63
64
# File 'lib/little_ghost/sandbox/network_policy.rb', line 62

def authorizer
  @authorizer
end

#forward_headersObject (readonly)

Header names the gateway may pass to an HTTP authorizer.



64
65
66
# File 'lib/little_ghost/sandbox/network_policy.rb', line 64

def forward_headers
  @forward_headers
end

#gatewayObject (readonly)

Explicit gateway declaration, when supplied.



60
61
62
# File 'lib/little_ghost/sandbox/network_policy.rb', line 60

def gateway
  @gateway
end

#inspectionObject (readonly)

Inspection level requested from the gateway.



58
59
60
# File 'lib/little_ghost/sandbox/network_policy.rb', line 58

def inspection
  @inspection
end

#modeObject (readonly)

Connectivity mode: :inherit, :none, or :allowlist.



54
55
56
# File 'lib/little_ghost/sandbox/network_policy.rb', line 54

def mode
  @mode
end

#mutation_headersObject (readonly)

Header names an HTTP authorizer may set on an upstream request.



66
67
68
# File 'lib/little_ghost/sandbox/network_policy.rb', line 66

def mutation_headers
  @mutation_headers
end

Class Method Details

.coerce(value) ⇒ Object

Returns value unchanged or converts a mode or Hash to a policy.

Raises:



12
13
14
15
16
17
18
19
# File 'lib/little_ghost/sandbox/network_policy.rb', line 12

def self.coerce(value)
  return nil if value.nil?
  return value if value.is_a?(self)
  return new(mode: value) if value.is_a?(Symbol) || value.is_a?(String)
  raise PolicyError, "network policy must be a mode, Hash, or Sandbox::NetworkPolicy" unless value.is_a?(Hash)

  new(**value.transform_keys(&:to_sym))
end

Instance Method Details

#==(other) ⇒ Object Also known as: eql?

Policies compare by their normalized enforcement declaration.



76
77
78
79
80
81
# File 'lib/little_ghost/sandbox/network_policy.rb', line 76

def ==(other)
  other.is_a?(self.class) &&
    [mode, allow, inspection, gateway, authorizer, forward_headers, mutation_headers] ==
      [other.mode, other.allow, other.inspection, other.gateway, other.authorizer,
        other.forward_headers, other.mutation_headers]
end

#allowlist?Boolean

Indicates that outbound traffic must pass an allowlist gateway.

Returns:

  • (Boolean)


73
# File 'lib/little_ghost/sandbox/network_policy.rb', line 73

def allowlist? = mode == :allowlist

#hashObject

Hashes the normalized enforcement declaration.



86
# File 'lib/little_ghost/sandbox/network_policy.rb', line 86

def hash = [mode, allow, inspection, gateway, authorizer, forward_headers, mutation_headers].hash

#inherit?Boolean

Indicates unrestricted backend-provided connectivity.

Returns:

  • (Boolean)


69
70
# File 'lib/little_ghost/sandbox/network_policy.rb', line 69

def inherit? = mode == :inherit
# Indicates that outbound connectivity must be disabled.

#none?Boolean

Indicates that outbound connectivity must be disabled.

Returns:

  • (Boolean)


71
72
# File 'lib/little_ghost/sandbox/network_policy.rb', line 71

def none? = mode == :none
# Indicates that outbound traffic must pass an allowlist gateway.