exec_sandbox 0.1.2 → 0.1.3
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/Gemfile +1 -1
- data/Gemfile.lock +13 -13
- data/VERSION +1 -1
- data/exec_sandbox.gemspec +5 -5
- data/lib/exec_sandbox/sandbox.rb +14 -0
- data/lib/exec_sandbox/users.rb +30 -3
- data/spec/exec_sandbox/sandbox_spec.rb +20 -0
- data/spec/exec_sandbox/users_spec.rb +73 -0
- metadata +20 -20
data/Gemfile
CHANGED
@@ -2,7 +2,7 @@ source :rubygems
|
|
2
2
|
# Add dependencies required to use your gem here.
|
3
3
|
# Example:
|
4
4
|
# gem 'activesupport', '>= 2.3.5'
|
5
|
-
gem 'ffi', '>= 1.0.
|
5
|
+
gem 'ffi', '>= 1.0.11'
|
6
6
|
|
7
7
|
# Add dependencies to develop your gem here.
|
8
8
|
# Include everything needed to run rake, tests, features, etc.
|
data/Gemfile.lock
CHANGED
@@ -2,26 +2,26 @@ GEM
|
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
4
|
diff-lcs (1.1.3)
|
5
|
-
ffi (1.0.
|
5
|
+
ffi (1.0.11)
|
6
6
|
git (1.2.5)
|
7
7
|
jeweler (1.6.4)
|
8
8
|
bundler (~> 1.0)
|
9
9
|
git (>= 1.2.5)
|
10
10
|
rake
|
11
|
-
json (1.6.
|
12
|
-
rake (0.9.2)
|
11
|
+
json (1.6.3)
|
12
|
+
rake (0.9.2.2)
|
13
13
|
rcov (0.9.11)
|
14
|
-
rdoc (3.
|
14
|
+
rdoc (3.12)
|
15
15
|
json (~> 1.4)
|
16
|
-
rspec (2.
|
17
|
-
rspec-core (~> 2.
|
18
|
-
rspec-expectations (~> 2.
|
19
|
-
rspec-mocks (~> 2.
|
20
|
-
rspec-core (2.
|
21
|
-
rspec-expectations (2.
|
16
|
+
rspec (2.7.0)
|
17
|
+
rspec-core (~> 2.7.0)
|
18
|
+
rspec-expectations (~> 2.7.0)
|
19
|
+
rspec-mocks (~> 2.7.0)
|
20
|
+
rspec-core (2.7.1)
|
21
|
+
rspec-expectations (2.7.0)
|
22
22
|
diff-lcs (~> 1.1.2)
|
23
|
-
rspec-mocks (2.
|
24
|
-
yard (0.7.
|
23
|
+
rspec-mocks (2.7.0)
|
24
|
+
yard (0.7.4)
|
25
25
|
yard-rspec (0.1)
|
26
26
|
yard
|
27
27
|
|
@@ -30,7 +30,7 @@ PLATFORMS
|
|
30
30
|
|
31
31
|
DEPENDENCIES
|
32
32
|
bundler (>= 1.0.21)
|
33
|
-
ffi (>= 1.0.
|
33
|
+
ffi (>= 1.0.11)
|
34
34
|
jeweler (>= 1.6.4)
|
35
35
|
rcov
|
36
36
|
rdoc (>= 3.10)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.3
|
data/exec_sandbox.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "exec_sandbox"
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.3"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Victor Costan"]
|
12
|
-
s.date = "2011-
|
12
|
+
s.date = "2011-12-20"
|
13
13
|
s.description = "Temporary users and groups, rlimits"
|
14
14
|
s.email = "costan@gmail.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -56,7 +56,7 @@ Gem::Specification.new do |s|
|
|
56
56
|
s.specification_version = 3
|
57
57
|
|
58
58
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
59
|
-
s.add_runtime_dependency(%q<ffi>, [">= 1.0.
|
59
|
+
s.add_runtime_dependency(%q<ffi>, [">= 1.0.11"])
|
60
60
|
s.add_development_dependency(%q<rdoc>, [">= 3.10"])
|
61
61
|
s.add_development_dependency(%q<rspec>, [">= 2.6.0"])
|
62
62
|
s.add_development_dependency(%q<yard>, [">= 0.7.2"])
|
@@ -65,7 +65,7 @@ Gem::Specification.new do |s|
|
|
65
65
|
s.add_development_dependency(%q<jeweler>, [">= 1.6.4"])
|
66
66
|
s.add_development_dependency(%q<rcov>, [">= 0"])
|
67
67
|
else
|
68
|
-
s.add_dependency(%q<ffi>, [">= 1.0.
|
68
|
+
s.add_dependency(%q<ffi>, [">= 1.0.11"])
|
69
69
|
s.add_dependency(%q<rdoc>, [">= 3.10"])
|
70
70
|
s.add_dependency(%q<rspec>, [">= 2.6.0"])
|
71
71
|
s.add_dependency(%q<yard>, [">= 0.7.2"])
|
@@ -75,7 +75,7 @@ Gem::Specification.new do |s|
|
|
75
75
|
s.add_dependency(%q<rcov>, [">= 0"])
|
76
76
|
end
|
77
77
|
else
|
78
|
-
s.add_dependency(%q<ffi>, [">= 1.0.
|
78
|
+
s.add_dependency(%q<ffi>, [">= 1.0.11"])
|
79
79
|
s.add_dependency(%q<rdoc>, [">= 3.10"])
|
80
80
|
s.add_dependency(%q<rspec>, [">= 2.6.0"])
|
81
81
|
s.add_dependency(%q<yard>, [">= 0.7.2"])
|
data/lib/exec_sandbox/sandbox.rb
CHANGED
@@ -6,6 +6,9 @@ class Sandbox
|
|
6
6
|
# The path to the sandbox's working directory.
|
7
7
|
attr_reader :path
|
8
8
|
|
9
|
+
# The un-privileged user that execs sandboxed binaries.
|
10
|
+
attr_reader :user_name
|
11
|
+
|
9
12
|
# Empty sandbox.
|
10
13
|
#
|
11
14
|
# @param [String] admin the name of a user who will be able to peek into the
|
@@ -142,6 +145,17 @@ class Sandbox
|
|
142
145
|
def finalize
|
143
146
|
close
|
144
147
|
end
|
148
|
+
|
149
|
+
# Removes temporary users created by old sandboxes.
|
150
|
+
#
|
151
|
+
# Sandboxes usually clean up after themselves. For the rare circumstances
|
152
|
+
# where that doesn't happen (VM crash, Ctrl+C, SIGKILL), this method finds and
|
153
|
+
# cleans up the temporary users created for sandboxing.
|
154
|
+
#
|
155
|
+
# @return [Array<String>] the names of the deleted users
|
156
|
+
def self.cleanup
|
157
|
+
Users.destroy_temps
|
158
|
+
end
|
145
159
|
end # module ExecSandbox::Sandbox
|
146
160
|
|
147
161
|
# Creates a sandbox, yields it, and destroys it.
|
data/lib/exec_sandbox/users.rb
CHANGED
@@ -8,6 +8,8 @@ module ExecSandbox
|
|
8
8
|
module Users
|
9
9
|
# Creates an unprivileged user.
|
10
10
|
#
|
11
|
+
# @param [String] prefix used at the beginning of temporary user names to
|
12
|
+
# help identify the application that created the users
|
11
13
|
# @return [String] the user's name
|
12
14
|
def self.temp(prefix = 'xsbx.rb')
|
13
15
|
loop do
|
@@ -81,10 +83,12 @@ module Users
|
|
81
83
|
|
82
84
|
else # Linux
|
83
85
|
if group_id
|
84
|
-
command = ['useradd', '--gid', group_id.to_s,
|
85
|
-
|
86
|
+
command = ['useradd', '--gid', group_id.to_s, '--no-user-group',
|
87
|
+
'--no-create-home', '--system',
|
88
|
+
'--comment', 'exec_sandbox.rb temporary user', user_name]
|
86
89
|
else
|
87
|
-
command = ['useradd', '--no-create-home',
|
90
|
+
command = ['useradd', '--user-group', '--no-create-home', '--system',
|
91
|
+
'--comment', 'exec_sandbox.rb temporary user', user_name]
|
88
92
|
end
|
89
93
|
unless Kernel.system(*command)
|
90
94
|
raise RuntimeError, "User creation failed at #{command.inspect}!"
|
@@ -151,6 +155,29 @@ module Users
|
|
151
155
|
end
|
152
156
|
end # RUBY_PLATFORM
|
153
157
|
end
|
158
|
+
|
159
|
+
# Finds users whose names match a String or Regexp pattern.
|
160
|
+
#
|
161
|
+
# @param [String] pattern matched against user names using ===
|
162
|
+
# @return [Array<String>] names of users
|
163
|
+
def self.named(pattern)
|
164
|
+
users = []
|
165
|
+
Etc.passwd do |user|
|
166
|
+
users << user.name if pattern === user.name
|
167
|
+
end
|
168
|
+
users
|
169
|
+
end
|
170
|
+
|
171
|
+
# Destroys users created by temp.
|
172
|
+
#
|
173
|
+
# @param [String] prefix match the prefix given to temp
|
174
|
+
# @return [Array<String>] names of users that were deleted
|
175
|
+
def self.destroy_temps(prefix = 'xsbx.rb')
|
176
|
+
# Matches the names created by temp.
|
177
|
+
pattern = /^#{prefix}\-[0-9a-f]+\.[0-9a-f]+\.[0-9a-f]+$/
|
178
|
+
# Each returns the collection that it iterates over.
|
179
|
+
self.named(pattern).each { |name| destroy name }
|
180
|
+
end
|
154
181
|
end # module ExecSandbox::Users
|
155
182
|
|
156
183
|
end # namespace ExecSandbox
|
@@ -154,4 +154,24 @@ describe ExecSandbox::Sandbox do
|
|
154
154
|
end
|
155
155
|
end
|
156
156
|
end
|
157
|
+
|
158
|
+
describe '#cleanup' do
|
159
|
+
describe 'in a system with an open sandbox' do
|
160
|
+
before do
|
161
|
+
@all_users = ExecSandbox::Users.named(/.*/).sort
|
162
|
+
|
163
|
+
@sandbox = ExecSandbox.open
|
164
|
+
@removed = ExecSandbox::Sandbox.cleanup
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'should not remove the sandbox user' do
|
168
|
+
ExecSandbox::Users.named(/.*/).sort.should == @all_users
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'should return an array with the sandbox user' do
|
172
|
+
@removed.should == [@sandbox.user_name]
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
end
|
157
177
|
end
|
@@ -3,6 +3,7 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
|
3
3
|
describe ExecSandbox::Users do
|
4
4
|
let(:test_user) { 'exec_sandbox_rspec' }
|
5
5
|
let(:test_group) { Etc.getgrgid(Etc.getpwnam(Etc.getlogin).gid).name }
|
6
|
+
let(:current_user) { Etc.getlogin }
|
6
7
|
|
7
8
|
describe '#temp' do
|
8
9
|
before { @user_name = ExecSandbox::Users.temp 'exsbx.rspec' }
|
@@ -122,4 +123,76 @@ describe ExecSandbox::Users do
|
|
122
123
|
end
|
123
124
|
end
|
124
125
|
end
|
126
|
+
|
127
|
+
describe '#named' do
|
128
|
+
describe 'with non-matching RegExp' do
|
129
|
+
it 'should not return any user' do
|
130
|
+
ExecSandbox::Users.named(/exec_sandbox_rspec/).should be_empty
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
describe 'with non-matching String' do
|
135
|
+
it 'should not return any user' do
|
136
|
+
ExecSandbox::Users.named(/exec_sandbox_rspec/).should be_empty
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
describe 'with the name of the current user' do
|
141
|
+
it 'should return the current user' do
|
142
|
+
ExecSandbox::Users.named(current_user).should == [current_user]
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
describe 'with RegExp matching one user' do
|
147
|
+
before do
|
148
|
+
ExecSandbox::Users.create test_user, test_group
|
149
|
+
end
|
150
|
+
after do
|
151
|
+
ExecSandbox::Users.destroy test_user
|
152
|
+
end
|
153
|
+
it 'should return that one user' do
|
154
|
+
ExecSandbox::Users.named(/exec.sandbox.rspe/).should ==
|
155
|
+
['exec_sandbox_rspec']
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
describe '#destroy_temps' do
|
161
|
+
let(:temp_prefix) { 'exsbx.rspec' }
|
162
|
+
|
163
|
+
before do
|
164
|
+
@all_users = ExecSandbox::Users.named(/.*/).sort
|
165
|
+
end
|
166
|
+
|
167
|
+
describe 'in a system with no temps' do
|
168
|
+
before do
|
169
|
+
@removed = ExecSandbox::Users.destroy_temps temp_prefix
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'should not remove any users' do
|
173
|
+
ExecSandbox::Users.named(/.*/).sort.should == @all_users
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'should return an empty array' do
|
177
|
+
@removed.should be_empty
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
describe 'in a system with two temps' do
|
182
|
+
before do
|
183
|
+
@temp1 = ExecSandbox::Users.temp temp_prefix
|
184
|
+
@temp2 = ExecSandbox::Users.temp temp_prefix
|
185
|
+
|
186
|
+
@removed = ExecSandbox::Users.destroy_temps temp_prefix
|
187
|
+
end
|
188
|
+
|
189
|
+
it 'should only remove the two temps' do
|
190
|
+
ExecSandbox::Users.named(/.*/).sort.should == @all_users
|
191
|
+
end
|
192
|
+
|
193
|
+
it 'should return the two temps' do
|
194
|
+
@removed.sort.should == [@temp1, @temp2].sort
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
125
198
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: exec_sandbox
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,22 +9,22 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-
|
12
|
+
date: 2011-12-20 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ffi
|
16
|
-
requirement: &
|
16
|
+
requirement: &15824600 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 1.0.
|
21
|
+
version: 1.0.11
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *15824600
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rdoc
|
27
|
-
requirement: &
|
27
|
+
requirement: &15824120 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '3.10'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *15824120
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rspec
|
38
|
-
requirement: &
|
38
|
+
requirement: &15823640 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: 2.6.0
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *15823640
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: yard
|
49
|
-
requirement: &
|
49
|
+
requirement: &15823160 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: 0.7.2
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *15823160
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: yard-rspec
|
60
|
-
requirement: &
|
60
|
+
requirement: &15822680 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0.1'
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *15822680
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: bundler
|
71
|
-
requirement: &
|
71
|
+
requirement: &15822200 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: 1.0.21
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *15822200
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: jeweler
|
82
|
-
requirement: &
|
82
|
+
requirement: &15821720 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: 1.6.4
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *15821720
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: rcov
|
93
|
-
requirement: &
|
93
|
+
requirement: &15821240 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ! '>='
|
@@ -98,7 +98,7 @@ dependencies:
|
|
98
98
|
version: '0'
|
99
99
|
type: :development
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *15821240
|
102
102
|
description: Temporary users and groups, rlimits
|
103
103
|
email: costan@gmail.com
|
104
104
|
executables: []
|
@@ -150,7 +150,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
150
150
|
version: '0'
|
151
151
|
segments:
|
152
152
|
- 0
|
153
|
-
hash: -
|
153
|
+
hash: -3240483873242314683
|
154
154
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
155
155
|
none: false
|
156
156
|
requirements:
|