Class: Microsandbox::NetworkPolicy

Inherits:
Object
  • Object
show all
Defined in:
lib/microsandbox/network.rb

Overview

A sandbox network policy: composed profiles, a terminal preset, or a custom set of allow/deny Rules with per-direction default actions and bulk domain denials.

Pass to Sandbox.create via network: — a NetworkPolicy, an Array of profile names ([:public, :host]), a single profile or preset name (String/Symbol), or a plain Hash with the same keys as NetworkPolicy.custom.

Profiles (runtime v0.6.7) compose: :public (public internet), :private (LAN/private ranges), :host (the host machine/gateway). Any non-empty combination automatically allows gateway DNS. The default policy — public internet only — equals from_profiles(:public).

Mirrors NetworkPolicy / Network in the official Python/Node/Go SDKs.

Examples:

profiles

Sandbox.create("b", image: "alpine", network: [:public, :private])
Sandbox.create("b", image: "alpine", network: :none)
Sandbox.create("b", image: "alpine", network: NetworkPolicy.from_profiles(:host))

custom

policy = Microsandbox::NetworkPolicy.custom(
  default_egress: :deny,
  rules: [
    Microsandbox::Rule.allow_dns,
    Microsandbox::Rule.allow(destination: "api.openai.com", protocol: :tcp, port: "443"),
  ],
  deny_domain_suffixes: [".ads.example"],
)
Sandbox.create("b", image: "alpine", network: policy)

Constant Summary collapse

PROFILES =

Composable profile names (runtime v0.6.7).

%w[public private host].freeze
PRESET_ALIASES =

Canonical preset names keyed by every accepted alias. Only the terminal presets survive v0.6.7; the removed ones get migration guidance in canonical_preset.

{
  "none" => "none", "disabled" => "none", "disable" => "none", "airgapped" => "none",
  "all" => "allow_all", "allow_all" => "allow_all", "allow-all" => "allow_all"
}.freeze
REMOVED_PRESETS =

Removed v0.6.6 preset spellings → the exact profile replacement, used to build actionable migration errors. (public_only expanded to precisely from_profiles(:public), non_local to from_profiles(:public, :private) — the replacements are rule-for-rule equivalent.)

{
  "public_only" => "network: [:public] (or NetworkPolicy.from_profiles(:public); " \
    "this is still the default policy)",
  "public-only" => "network: [:public]",
  "non_local" => "network: [:public, :private] " \
    "(or NetworkPolicy.from_profiles(:public, :private))",
  "non-local" => "network: [:public, :private]",
  "nonlocal" => "network: [:public, :private]"
}.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(wire) ⇒ NetworkPolicy

Returns a new instance of NetworkPolicy.



395
396
397
# File 'lib/microsandbox/network.rb', line 395

def initialize(wire)
  @wire = wire
end

Class Method Details

.allow_allNetworkPolicy

Returns permit all traffic.

Returns:



182
# File 'lib/microsandbox/network.rb', line 182

def allow_all = preset("allow_all")

.coerce(network) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Coerce a user-facing network: value into a normalized wire Hash.



217
218
219
220
221
222
223
224
225
226
227
228
229
# File 'lib/microsandbox/network.rb', line 217

def coerce(network)
  case network
  when NetworkPolicy then network.to_h
  when Array then from_profiles(*network).to_h
  when String, Symbol then coerce_name(network)
  when Hash then from_hash(network)
  else
    raise ArgumentError,
      "network: expects profile(s) (:public/:private/:host, or an Array of them), " \
      "a preset (:none/:allow_all), a Microsandbox::NetworkPolicy, or a Hash " \
      "(got #{network.class})"
  end
end

.custom(default_egress: :deny, default_ingress: :allow, rules: [], deny_domains: [], deny_domain_suffixes: []) ⇒ NetworkPolicy

Build a custom policy — an ordered rule list with per-direction default actions. A custom policy stands on its own; to start from a profile base, use the Hash form passed to Sandbox.create (profiles: composes with rules:/deny lists). A terminal preset: stays exclusive with custom rules/defaults, mirroring the official SDKs. Custom policies need an explicit Rule.allow_dns if the sandbox should resolve names.

Parameters:

  • default_egress (:deny, :allow, nil) (defaults to: :deny)

    fall-through for unmatched outbound traffic (default :deny)

  • default_ingress (:deny, :allow, nil) (defaults to: :allow)

    fall-through for unmatched inbound traffic (default :allow)

  • rules (Array<Hash>) (defaults to: [])

    ordered Rules (first match wins per direction)

  • deny_domains (Array<String>) (defaults to: [])

    exact domains to deny egress to (prepended, so they outrank later allow rules)

  • deny_domain_suffixes (Array<String>) (defaults to: [])

    domain suffixes to deny

Returns:



205
206
207
208
209
210
211
212
213
# File 'lib/microsandbox/network.rb', line 205

def custom(default_egress: :deny, default_ingress: :allow, rules: [],
  deny_domains: [], deny_domain_suffixes: [])
  h = {}
  h["default_egress"] = action_str(default_egress) unless default_egress.nil?
  h["default_ingress"] = action_str(default_ingress) unless default_ingress.nil?
  h["rules"] = Array(rules).map { |r| normalize_rule(r) }
  add_deny_lists(h, deny_domains, deny_domain_suffixes)
  new(h)
end

.from_profiles(*profiles) ⇒ NetworkPolicy

Compose a policy from network profiles (:public, :private, :host). Order and duplicates don't matter — the runtime expands the set into a canonical rule list plus a gateway-DNS allow. An empty set is a valid deny-egress/allow-ingress policy with no rules (and no DNS).

Returns:



167
168
169
170
171
172
173
174
175
176
# File 'lib/microsandbox/network.rb', line 167

def from_profiles(*profiles)
  list = normalize_profiles(profiles)
  if list.empty?
    # Same semantics as the runtime's from_profiles([]) — expressed as an
    # explicit empty custom policy so the wire needs no empty-array case.
    custom(default_egress: :deny, default_ingress: :allow, rules: [])
  else
    new("profiles" => list)
  end
end

.noneNetworkPolicy

Returns block all network access.

Returns:



179
# File 'lib/microsandbox/network.rb', line 179

def none = preset("none")

.preset(name) ⇒ NetworkPolicy

Returns a bare preset policy (:none or :allow_all).

Returns:



185
186
187
# File 'lib/microsandbox/network.rb', line 185

def preset(name)
  new("preset" => canonical_preset(name))
end

Instance Method Details

#inspectObject



404
405
406
# File 'lib/microsandbox/network.rb', line 404

def inspect
  "#<Microsandbox::NetworkPolicy #{@wire.inspect}>"
end

#to_hHash

Returns the normalized wire representation.

Returns:

  • (Hash)

    the normalized wire representation



400
401
402
# File 'lib/microsandbox/network.rb', line 400

def to_h
  @wire
end