mxc 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/mxc.rb ADDED
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mxc/version'
4
+ require 'mxc/error'
5
+ require 'mxc/configuration'
6
+ require 'mxc/native'
7
+ require 'mxc/preflight'
8
+ require 'mxc/startup_failure'
9
+ require 'mxc/chunk'
10
+ require 'mxc/result'
11
+ require 'mxc/backend'
12
+ require 'mxc/availability'
13
+ require 'mxc/process'
14
+ require 'mxc/windows_arguments'
15
+ require 'mxc/sandbox'
16
+
17
+ # Runs commands in sandboxes through Microsoft's MXC.
18
+ #
19
+ # result = MXC.run("python3 build.py", readable: "app/skills", writable: "tmp/out", timeout: 30)
20
+ # result.stdout
21
+ module MXC
22
+ @availability = {}
23
+ @availability_lock = Mutex.new
24
+
25
+ class << self
26
+ # Returns the global Configuration.
27
+ def config
28
+ @config ||= Configuration.new
29
+ end
30
+
31
+ # Yields the global Configuration to change the defaults every sandbox starts from.
32
+ #
33
+ # MXC.configure do |config|
34
+ # config.timeout = 60
35
+ # end
36
+ def configure
37
+ yield config
38
+ end
39
+
40
+ # Returns a new Sandbox, optionally configured with the same keywords as Sandbox.new.
41
+ def sandbox(**)
42
+ Sandbox.new(**)
43
+ end
44
+
45
+ # Runs +command+ in a new sandbox and returns its Result. Takes the command the same
46
+ # way as Sandbox#run, one String for the shell or a program and its arguments, and the
47
+ # same keywords as Sandbox.new. A block receives each Chunk of output as it arrives.
48
+ #
49
+ # MXC.run("python3 build.py", readable: "app/skills", timeout: 30)
50
+ # MXC.run("python3", "convert.py", params[:filename], readable: "app/skills")
51
+ def run(*command, **, &)
52
+ sandbox(**).run(*command, &)
53
+ end
54
+
55
+ # Starts +command+ in a new sandbox and returns its Process. Takes the command the
56
+ # same way as Sandbox#run, and the same keywords as Sandbox.new.
57
+ #
58
+ # MXC.spawn("python3", "-i", "-q", timeout: 60)
59
+ def spawn(*command, **)
60
+ sandbox(**).spawn(*command)
61
+ end
62
+
63
+ # Returns true when this host can start a sandbox with +backend+.
64
+ #
65
+ # The answer comes from starting one real sandbox, once per backend and process.
66
+ def supported?(backend: config.backend)
67
+ availability(backend:).supported?
68
+ end
69
+
70
+ # Returns the Availability of +backend+ on this host, with the reason and remediation
71
+ # when it is unsupported. Pass <tt>refresh: true</tt> to probe the host again.
72
+ def availability(backend: config.backend, refresh: false)
73
+ backend = Sandbox.backend_name(backend)
74
+ @availability_lock.synchronize do
75
+ @availability.delete(backend) if refresh
76
+ @availability[backend] ||= Availability.probe(backend)
77
+ end
78
+ end
79
+
80
+ # Returns the sandbox backends MXC finds on this host, as Backend objects.
81
+ def backends
82
+ Native.backend_attributes.map { |attributes| Backend.new(**attributes) }
83
+ end
84
+
85
+ # Returns true when this host supports +capability+ with the configured backend.
86
+ #
87
+ # +capability+ is <tt>:network</tt> for unrestricted network access,
88
+ # <tt>:network_policy</tt> for host allow-lists, or any capability a Backend reports.
89
+ def supports?(capability)
90
+ return false unless supported?
91
+
92
+ case capability
93
+ when :network then Preflight.problem(network: true).nil?
94
+ when :network_policy then Preflight.problem(network: { allow: [] }).nil? && proxy_enforcement?
95
+ else configured_backends.any? { |backend| backend.supports?(capability) }
96
+ end
97
+ end
98
+
99
+ private
100
+
101
+ def proxy_enforcement?
102
+ !Preflight.linux? || configured_backends.any? { |backend| backend.supports?(:proxy_enforcement) }
103
+ end
104
+
105
+ def configured_backends
106
+ backends.select { |backend| config.backend == :auto || backend.name == config.backend }
107
+ end
108
+ end
109
+ end
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mxc
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Carmine Paolino
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: rb_sys
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: 0.9.130
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: 0.9.130
26
+ description: An unofficial Ruby binding to Microsoft's MXC. Run commands in Bubblewrap,
27
+ Seatbelt or Windows ProcessContainer sandboxes with filesystem, network, environment
28
+ and timeout policies.
29
+ email:
30
+ - carmine@paolino.me
31
+ executables: []
32
+ extensions:
33
+ - ext/mxc/extconf.rb
34
+ extra_rdoc_files: []
35
+ files:
36
+ - Cargo.lock
37
+ - Cargo.toml
38
+ - LICENSE
39
+ - NOTICE
40
+ - README.md
41
+ - ext/mxc/Cargo.toml
42
+ - ext/mxc/build.rs
43
+ - ext/mxc/extconf.rb
44
+ - ext/mxc/src/lib.rs
45
+ - ext/mxc/src/proxy.rs
46
+ - lib/mxc.rb
47
+ - lib/mxc/availability.rb
48
+ - lib/mxc/backend.rb
49
+ - lib/mxc/chunk.rb
50
+ - lib/mxc/configuration.rb
51
+ - lib/mxc/error.rb
52
+ - lib/mxc/native.rb
53
+ - lib/mxc/preflight.rb
54
+ - lib/mxc/process.rb
55
+ - lib/mxc/result.rb
56
+ - lib/mxc/sandbox.rb
57
+ - lib/mxc/startup_failure.rb
58
+ - lib/mxc/version.rb
59
+ - lib/mxc/windows_arguments.rb
60
+ homepage: https://crmne.github.io/mxc/
61
+ licenses:
62
+ - MIT
63
+ metadata:
64
+ homepage_uri: https://crmne.github.io/mxc/
65
+ source_code_uri: https://github.com/crmne/mxc
66
+ bug_tracker_uri: https://github.com/crmne/mxc/issues
67
+ changelog_uri: https://github.com/crmne/mxc/releases
68
+ funding_uri: https://github.com/sponsors/crmne
69
+ rubygems_mfa_required: 'true'
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: 3.2.0
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubygems_version: 4.0.20
85
+ specification_version: 4
86
+ summary: Run untrusted commands in OS sandboxes from Ruby, through Microsoft's MXC.
87
+ test_files: []