cap2 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +7 -0
- data/README.md +88 -0
- data/Rakefile +11 -0
- data/ext/cap2/cap2.c +149 -0
- data/ext/cap2/extconf.rb +23 -0
- data/lib/cap2.rb +82 -0
- data/lib/cap2/entity.rb +31 -0
- data/lib/cap2/file.rb +11 -0
- data/lib/cap2/process.rb +11 -0
- data/lib/cap2/version.rb +3 -0
- data/spec/cap2_spec.rb +119 -0
- data/spec/file_spec.rb +6 -0
- data/spec/process_spec.rb +5 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/support/entity.rb +38 -0
- metadata +64 -0
data/LICENSE
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
Copyright (C) 2012 Lewis Marshall
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
4
|
+
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
Cap2
|
2
|
+
====
|
3
|
+
|
4
|
+
Cap2 is a Ruby library for managing the POSIX 1003.1e capabilities available in Linux kernels. These capabilities are a partitioning of the all powerful root privilege into a set of distinct privileges. See capabilites(7) for more information.
|
5
|
+
|
6
|
+
Installation
|
7
|
+
------------
|
8
|
+
|
9
|
+
To install this library, you will need to be running Linux and have the libcap2 library and header files installed.
|
10
|
+
|
11
|
+
### Install libcap2
|
12
|
+
|
13
|
+
#### Ubuntu
|
14
|
+
|
15
|
+
```
|
16
|
+
$ sudo apt-get install libcap2 libcap-dev
|
17
|
+
```
|
18
|
+
|
19
|
+
#### From source
|
20
|
+
|
21
|
+
```
|
22
|
+
$ curl -O http://ftp.de.debian.org/debian/pool/main/libc/libcap2/libcap2_2.22.orig.tar.gz
|
23
|
+
$ tar xzf libcap2_2.22.orig.tar.gz
|
24
|
+
$ cd libcap2-2.22
|
25
|
+
$ make
|
26
|
+
$ sudo make install
|
27
|
+
```
|
28
|
+
|
29
|
+
### Install the gem
|
30
|
+
|
31
|
+
```
|
32
|
+
$ gem install cap2
|
33
|
+
```
|
34
|
+
|
35
|
+
Querying Capabilities
|
36
|
+
---------------------
|
37
|
+
|
38
|
+
### Processes
|
39
|
+
|
40
|
+
Suppose a process with pid 1000 exists with the following capabilities:
|
41
|
+
|
42
|
+
```
|
43
|
+
Permitted - CAP_CHOWN, CAP_LEASE
|
44
|
+
Effective - CAP_CHOWN
|
45
|
+
Inheritable - CAP_LEASE
|
46
|
+
```
|
47
|
+
|
48
|
+
Then:
|
49
|
+
|
50
|
+
```
|
51
|
+
process = Cap2.process(1000) # => #<Cap2::Process>
|
52
|
+
|
53
|
+
process.permitted?(:chown) # => true
|
54
|
+
process.permitted?(:lease) # => true
|
55
|
+
process.permitted?(:fowner) # => false
|
56
|
+
|
57
|
+
process.effective?(:chown) # => true
|
58
|
+
process.effective?(:lease) # => false
|
59
|
+
|
60
|
+
process.inheritable?(:chown) # => false
|
61
|
+
process.inheritable?(:lease) # => true
|
62
|
+
```
|
63
|
+
|
64
|
+
### Files
|
65
|
+
|
66
|
+
Suppose the file "/tmp/cap_test" exists with the following capabilities:
|
67
|
+
|
68
|
+
```
|
69
|
+
Permitted - CAP_CHOWN, CAP_LEASE
|
70
|
+
Effective - CAP_CHOWN
|
71
|
+
Inheritable - CAP_LEASE
|
72
|
+
```
|
73
|
+
|
74
|
+
Then:
|
75
|
+
|
76
|
+
```
|
77
|
+
file = Cap2.file('/tmp/cap_test') # => #<Cap2::File>
|
78
|
+
|
79
|
+
file.permitted?(:chown) # => true
|
80
|
+
file.permitted?(:lease) # => true
|
81
|
+
file.permitted?(:fowner) # => false
|
82
|
+
|
83
|
+
file.effective?(:chown) # => true
|
84
|
+
file.effective?(:lease) # => false
|
85
|
+
|
86
|
+
file.inheritable?(:chown) # => false
|
87
|
+
file.inheritable?(:lease) # => true
|
88
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'rake/extensiontask'
|
2
|
+
|
3
|
+
Rake::ExtensionTask.new('cap2')
|
4
|
+
|
5
|
+
require 'rspec/core'
|
6
|
+
require 'rspec/core/rake_task'
|
7
|
+
|
8
|
+
desc 'Run all specs in the spec directory'
|
9
|
+
RSpec::Core::RakeTask.new(:spec => [:clobber, :compile]) do |t|
|
10
|
+
t.pattern = FileList['spec/**/*_spec.rb']
|
11
|
+
end
|
data/ext/cap2/cap2.c
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include <errno.h>
|
3
|
+
#include <sys/capability.h>
|
4
|
+
|
5
|
+
static VALUE cap2_has_cap(cap_t cap_d, cap_flag_t set, cap_value_t cap) {
|
6
|
+
cap_flag_value_t flag_value = CAP_CLEAR;
|
7
|
+
|
8
|
+
cap_get_flag(cap_d, cap, set, &flag_value);
|
9
|
+
|
10
|
+
return flag_value == CAP_SET ? Qtrue : Qfalse;
|
11
|
+
}
|
12
|
+
|
13
|
+
static VALUE cap2_pid_has_cap(VALUE self, VALUE pid, VALUE set, VALUE cap) {
|
14
|
+
cap_t cap_d;
|
15
|
+
VALUE result;
|
16
|
+
|
17
|
+
int p = FIX2INT(pid);
|
18
|
+
|
19
|
+
cap_d = cap_get_pid(p);
|
20
|
+
|
21
|
+
if (cap_d == NULL) {
|
22
|
+
rb_raise(
|
23
|
+
rb_eRuntimeError,
|
24
|
+
"Failed to get capabilities for proccess %d: (%s)\n",
|
25
|
+
p, strerror(errno)
|
26
|
+
);
|
27
|
+
}
|
28
|
+
|
29
|
+
set = FIX2INT(set);
|
30
|
+
cap = FIX2INT(cap);
|
31
|
+
|
32
|
+
result = cap2_has_cap(
|
33
|
+
cap_d,
|
34
|
+
(cap_flag_t) set,
|
35
|
+
(cap_value_t) cap
|
36
|
+
);
|
37
|
+
|
38
|
+
cap_free(cap_d);
|
39
|
+
|
40
|
+
return result;
|
41
|
+
}
|
42
|
+
|
43
|
+
static VALUE cap2_file_has_cap(VALUE self, VALUE filename, VALUE set, VALUE cap) {
|
44
|
+
cap_t cap_d;
|
45
|
+
VALUE result;
|
46
|
+
|
47
|
+
char *f = StringValueCStr(filename);
|
48
|
+
|
49
|
+
cap_d = cap_get_file(f);
|
50
|
+
|
51
|
+
if (cap_d == NULL && errno != ENODATA) {
|
52
|
+
rb_raise(
|
53
|
+
rb_eRuntimeError,
|
54
|
+
"Failed to get capabilities for file %s: (%s)\n",
|
55
|
+
f, strerror(errno)
|
56
|
+
);
|
57
|
+
}
|
58
|
+
|
59
|
+
set = FIX2INT(set);
|
60
|
+
cap = FIX2INT(cap);
|
61
|
+
|
62
|
+
result = cap2_has_cap(
|
63
|
+
cap_d,
|
64
|
+
(cap_flag_t) set,
|
65
|
+
(cap_value_t) cap
|
66
|
+
);
|
67
|
+
|
68
|
+
cap_free(cap_d);
|
69
|
+
|
70
|
+
return result;
|
71
|
+
}
|
72
|
+
|
73
|
+
#define SetsHashSet(key,val) \
|
74
|
+
rb_hash_aset(sets_hash, rb_str_new2(key), INT2FIX(val))
|
75
|
+
|
76
|
+
#define CapsHashSet(key,val) \
|
77
|
+
rb_hash_aset(caps_hash, rb_str_new2(key), INT2FIX(val))
|
78
|
+
|
79
|
+
void Init_cap2(void) {
|
80
|
+
VALUE rb_mCap2;
|
81
|
+
|
82
|
+
// sets_hash and caps_hash act as maps between lower cased
|
83
|
+
// names of capabilities (e.g. 'dac_override') and the CAP_
|
84
|
+
// constants defined in linux/capability.h and
|
85
|
+
// sys/capability.h (e.g. CAP_DAC_OVERRIDE). They are
|
86
|
+
// assigned to Cap2::SETS and Cap2::CAPS respectively.
|
87
|
+
VALUE sets_hash, caps_hash;
|
88
|
+
|
89
|
+
rb_mCap2 = rb_define_module("Cap2");
|
90
|
+
|
91
|
+
sets_hash = rb_hash_new();
|
92
|
+
SetsHashSet("permitted", CAP_PERMITTED);
|
93
|
+
SetsHashSet("effective", CAP_EFFECTIVE);
|
94
|
+
SetsHashSet("inheritable", CAP_INHERITABLE);
|
95
|
+
rb_define_const(rb_mCap2, "SETS", sets_hash);
|
96
|
+
|
97
|
+
caps_hash = rb_hash_new();
|
98
|
+
CapsHashSet("chown", CAP_CHOWN);
|
99
|
+
CapsHashSet("dac_override", CAP_DAC_OVERRIDE);
|
100
|
+
CapsHashSet("dac_read_search", CAP_DAC_READ_SEARCH);
|
101
|
+
CapsHashSet("fowner", CAP_FOWNER);
|
102
|
+
CapsHashSet("fsetid", CAP_FSETID);
|
103
|
+
CapsHashSet("kill", CAP_KILL);
|
104
|
+
CapsHashSet("setgid", CAP_SETGID);
|
105
|
+
CapsHashSet("setuid", CAP_SETUID);
|
106
|
+
CapsHashSet("setpcap", CAP_SETPCAP);
|
107
|
+
CapsHashSet("linux_immutable", CAP_LINUX_IMMUTABLE);
|
108
|
+
CapsHashSet("net_bind_service", CAP_NET_BIND_SERVICE);
|
109
|
+
CapsHashSet("net_broadcast", CAP_NET_BROADCAST);
|
110
|
+
CapsHashSet("net_admin", CAP_NET_ADMIN);
|
111
|
+
CapsHashSet("net_raw", CAP_NET_RAW);
|
112
|
+
CapsHashSet("ipc_lock", CAP_IPC_LOCK);
|
113
|
+
CapsHashSet("ipc_owner", CAP_IPC_OWNER);
|
114
|
+
CapsHashSet("sys_module", CAP_SYS_MODULE);
|
115
|
+
CapsHashSet("sys_rawio", CAP_SYS_RAWIO);
|
116
|
+
CapsHashSet("sys_chroot", CAP_SYS_CHROOT);
|
117
|
+
CapsHashSet("sys_ptrace", CAP_SYS_PTRACE);
|
118
|
+
CapsHashSet("sys_pacct", CAP_SYS_PACCT);
|
119
|
+
CapsHashSet("sys_admin", CAP_SYS_ADMIN);
|
120
|
+
CapsHashSet("sys_boot", CAP_SYS_BOOT);
|
121
|
+
CapsHashSet("sys_nice", CAP_SYS_NICE);
|
122
|
+
CapsHashSet("sys_resource", CAP_SYS_RESOURCE);
|
123
|
+
CapsHashSet("sys_time", CAP_SYS_TIME);
|
124
|
+
CapsHashSet("sys_tty_config", CAP_SYS_TTY_CONFIG);
|
125
|
+
CapsHashSet("mknod", CAP_MKNOD);
|
126
|
+
CapsHashSet("lease", CAP_LEASE);
|
127
|
+
CapsHashSet("audit_write", CAP_AUDIT_WRITE);
|
128
|
+
CapsHashSet("audit_control", CAP_AUDIT_CONTROL);
|
129
|
+
CapsHashSet("setfcap", CAP_SETFCAP);
|
130
|
+
CapsHashSet("mac_override", CAP_MAC_OVERRIDE);
|
131
|
+
CapsHashSet("mac_admin", CAP_MAC_ADMIN);
|
132
|
+
CapsHashSet("syslog", CAP_SYSLOG);
|
133
|
+
CapsHashSet("wake_alarm", CAP_WAKE_ALARM);
|
134
|
+
rb_define_const(rb_mCap2, "CAPS", caps_hash);
|
135
|
+
|
136
|
+
rb_define_module_function(
|
137
|
+
rb_mCap2,
|
138
|
+
"pid_has_cap?",
|
139
|
+
cap2_pid_has_cap,
|
140
|
+
3
|
141
|
+
);
|
142
|
+
|
143
|
+
rb_define_module_function(
|
144
|
+
rb_mCap2,
|
145
|
+
"file_has_cap?",
|
146
|
+
cap2_file_has_cap,
|
147
|
+
3
|
148
|
+
);
|
149
|
+
}
|
data/ext/cap2/extconf.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
|
3
|
+
unless have_header('sys/capability.h')
|
4
|
+
abort <<-EOS
|
5
|
+
-----
|
6
|
+
ERROR
|
7
|
+
-----
|
8
|
+
sys/capability.h is missing. You should install the libcap2 header files
|
9
|
+
|
10
|
+
EOS
|
11
|
+
end
|
12
|
+
|
13
|
+
unless have_library('cap')
|
14
|
+
abort <<-EOS
|
15
|
+
-----
|
16
|
+
ERROR
|
17
|
+
-----
|
18
|
+
libcap is missing. You should install the libcap2 library
|
19
|
+
|
20
|
+
EOS
|
21
|
+
end
|
22
|
+
|
23
|
+
create_makefile('cap2')
|
data/lib/cap2.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'cap2.so'
|
2
|
+
require 'cap2/entity'
|
3
|
+
require 'cap2/process'
|
4
|
+
require 'cap2/file'
|
5
|
+
|
6
|
+
module Cap2
|
7
|
+
# = Cap2
|
8
|
+
#
|
9
|
+
# Cap2 is a module for querying the POSIX 1003.1e capabilities
|
10
|
+
# available in Linux kernels. These capabilities are a
|
11
|
+
# partitioning of the all powerful root privilege into a set
|
12
|
+
# of distinct privileges.
|
13
|
+
class << self
|
14
|
+
# A wrapper function around the native Cap2.pid_has_cap?
|
15
|
+
# and Cap2.file_has_cap?. Returns true if the given
|
16
|
+
# capability is enabled in the given set for the given pid /
|
17
|
+
# filename.
|
18
|
+
#
|
19
|
+
# @param [String, Fixnum] pid_or_filename
|
20
|
+
# When a Fixnum, query the capabilities for the process
|
21
|
+
# with this value. When a String, query for the file
|
22
|
+
# with a filename of this value.
|
23
|
+
#
|
24
|
+
# @param [Symbol] set
|
25
|
+
# One of :permitted, :effective or :inheritable.
|
26
|
+
#
|
27
|
+
# @param [Symbol] cap
|
28
|
+
# A lower cased name of a capability, without the 'CAP_'
|
29
|
+
# prefix. For example, :chown would query the CAP_CHOWN
|
30
|
+
# capability
|
31
|
+
def has_capability?(pid_or_filename, set, cap)
|
32
|
+
# See ext/cap2/cap2.c for the definition of SETS and CAPS
|
33
|
+
set = SETS[set.to_s]
|
34
|
+
cap = CAPS[cap.to_s]
|
35
|
+
|
36
|
+
case pid_or_filename
|
37
|
+
when Fixnum
|
38
|
+
pid_has_cap?(pid_or_filename, set, cap)
|
39
|
+
when String
|
40
|
+
file_has_cap?(pid_or_filename, set, cap)
|
41
|
+
else
|
42
|
+
raise ArgumentError, "wrong argument type, expected Fixnum or String, got #{pid_or_filename.class}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns a Cap2::Process initialized with the given pid,
|
47
|
+
# defaulting to the current pid.
|
48
|
+
def process(pid = ::Process.pid)
|
49
|
+
check_pid! pid
|
50
|
+
|
51
|
+
Process.new(pid)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns a Cap2::File initialized with the given filename
|
55
|
+
def file(filename)
|
56
|
+
check_file! filename
|
57
|
+
|
58
|
+
File.new(filename)
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
# Check that a process with the given pid exists by sending
|
63
|
+
# a 0 signal to the process via Process.kill
|
64
|
+
def check_pid!(pid)
|
65
|
+
::Process.kill(0, pid)
|
66
|
+
rescue Exception => e
|
67
|
+
if Errno::ESRCH === e
|
68
|
+
raise ProcessNotFound
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Check that a file exists with the given filename
|
73
|
+
def check_file!(filename)
|
74
|
+
unless ::File.exists?(filename)
|
75
|
+
raise FileNotFound
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class ProcessNotFound < StandardError; end
|
81
|
+
class FileNotFound < StandardError; end
|
82
|
+
end
|
data/lib/cap2/entity.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
module Cap2
|
2
|
+
class Entity
|
3
|
+
# = Entity
|
4
|
+
#
|
5
|
+
# A superclass for the Cap2::Process and Cap2::File
|
6
|
+
# classes providing convenience methods for querying
|
7
|
+
# permitted, effective and inheritable capabilities.
|
8
|
+
#
|
9
|
+
# Each method takes a capability argument, a lower
|
10
|
+
# cased name of a capability, without the 'CAP_' prefix.
|
11
|
+
# For example, :chown would query the CAP_CHOWN capability.
|
12
|
+
|
13
|
+
def permitted?(capability)
|
14
|
+
has?(:permitted, capability)
|
15
|
+
end
|
16
|
+
|
17
|
+
def effective?(capability)
|
18
|
+
has?(:effective, capability)
|
19
|
+
end
|
20
|
+
|
21
|
+
def inheritable?(capability)
|
22
|
+
has?(:inheritable, capability)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
def has?(set, cap)
|
27
|
+
Cap2.has_capability?(@entity_id, set, cap)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
data/lib/cap2/file.rb
ADDED
data/lib/cap2/process.rb
ADDED
data/lib/cap2/version.rb
ADDED
data/spec/cap2_spec.rb
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Cap2 do
|
4
|
+
describe '.has_capability?' do
|
5
|
+
context 'for processes' do
|
6
|
+
context 'when the given process does not have the given capability' do
|
7
|
+
it { should_not have_capability(
|
8
|
+
Process.pid, :permitted, :dac_override) }
|
9
|
+
end
|
10
|
+
|
11
|
+
context 'when the given process does have the given capability' do
|
12
|
+
it { should have_capability(
|
13
|
+
1, :permitted, :dac_override) }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'for files' do
|
18
|
+
let(:file) { Tempfile.new('cap-test') }
|
19
|
+
|
20
|
+
context 'when the given file does not have the given capability' do
|
21
|
+
it { should_not have_capability(
|
22
|
+
file.path, :permitted, :dac_override) }
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'when the given file does have the given capability' do
|
26
|
+
before(:each) do
|
27
|
+
system %{sudo setcap "cap_dac_override+p" #{file.path}}
|
28
|
+
end
|
29
|
+
|
30
|
+
it { should have_capability(
|
31
|
+
file.path, :permitted, :dac_override) }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '.process' do
|
37
|
+
let(:process) { double 'process' }
|
38
|
+
|
39
|
+
before(:each) do
|
40
|
+
Cap2::Process.stub(:new => process)
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'called without a pid' do
|
44
|
+
it 'should initialize a Cap2::Process with the current pid' do
|
45
|
+
Cap2::Process.should_receive(:new).with(Process.pid)
|
46
|
+
Cap2.process
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should return the new Cap2::Process' do
|
50
|
+
Cap2.process.should == process
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'called with a pid' do
|
55
|
+
let(:pid) { double 'pid' }
|
56
|
+
|
57
|
+
context "when a process with the given pid doesn't exist" do
|
58
|
+
before(:each) do
|
59
|
+
Process.stub(:kill).with(0, pid).and_raise(Errno::ESRCH)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should raise a Cap2::ProcessNotFound' do
|
63
|
+
expect { Cap2.process(pid) }.to \
|
64
|
+
raise_error(Cap2::ProcessNotFound)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'when a process with the given pid does exist' do
|
69
|
+
before(:each) do
|
70
|
+
Process.stub(:kill).with(0, pid).and_return(1)
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should initialize a Cap2::Process with the pid' do
|
74
|
+
Cap2::Process.should_receive(:new).with(pid)
|
75
|
+
Cap2.process(pid)
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'should return the new Cap2::Process' do
|
79
|
+
Cap2.process(pid).should == process
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe '.file' do
|
86
|
+
let(:file) { double 'file' }
|
87
|
+
let(:filename) { double 'filename' }
|
88
|
+
|
89
|
+
before(:each) do
|
90
|
+
Cap2::File.stub(:new => file)
|
91
|
+
end
|
92
|
+
|
93
|
+
context "when the file doesn't exist" do
|
94
|
+
before(:each) do
|
95
|
+
File.stub(:exists?).with(filename).and_return(false)
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'should raise a Cap2::FileNotFound error' do
|
99
|
+
expect { Cap2.file(filename) }.to \
|
100
|
+
raise_error(Cap2::FileNotFound)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
context 'when the file does exist' do
|
105
|
+
before(:each) do
|
106
|
+
File.stub(:exists?).with(filename).and_return(true)
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'should initialize a Cap2::File with the filename' do
|
110
|
+
Cap2::File.should_receive(:new).with(filename)
|
111
|
+
Cap2.file(filename)
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'should return the new Cap2::File' do
|
115
|
+
Cap2.file(filename).should == file
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
data/spec/file_spec.rb
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
#
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
|
+
|
8
|
+
require 'cap2'
|
9
|
+
require 'tempfile'
|
10
|
+
require 'support/entity'
|
11
|
+
|
12
|
+
RSpec.configure do |config|
|
13
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
14
|
+
config.run_all_when_everything_filtered = true
|
15
|
+
config.filter_run :focus
|
16
|
+
|
17
|
+
# Run specs in random order to surface order dependencies. If you find an
|
18
|
+
# order dependency and want to debug it, you can fix the order by providing
|
19
|
+
# the seed, which is printed after each run.
|
20
|
+
# --seed 1234
|
21
|
+
config.order = 'random'
|
22
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
shared_examples_for 'an entity' do
|
4
|
+
let(:entity_id) { double 'entity id' }
|
5
|
+
let(:capability) { double 'capability' }
|
6
|
+
|
7
|
+
subject { described_class.new(entity_id) }
|
8
|
+
|
9
|
+
describe '#permitted?' do
|
10
|
+
it 'should call Cap2.has_capability? correctly' do
|
11
|
+
Cap2.
|
12
|
+
should_receive(:has_capability?).
|
13
|
+
with(entity_id, :permitted, capability)
|
14
|
+
|
15
|
+
subject.permitted?(capability)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#effective?' do
|
20
|
+
it 'should call Cap2.has_capability? correctly' do
|
21
|
+
Cap2.
|
22
|
+
should_receive(:has_capability?).
|
23
|
+
with(entity_id, :effective, capability)
|
24
|
+
|
25
|
+
subject.effective?(capability)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#inheritable?' do
|
30
|
+
it 'should call Cap2.has_capability? correctly' do
|
31
|
+
Cap2.
|
32
|
+
should_receive(:has_capability?).
|
33
|
+
with(entity_id, :inheritable, capability)
|
34
|
+
|
35
|
+
subject.inheritable?(capability)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cap2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Lewis Marshall
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-08-18 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: ! " Cap2 is a Ruby library for managing the POSIX 1003.1e capabilities\n
|
15
|
+
\ available in Linux kernels.\n \n These capabilities are a partitioning
|
16
|
+
of the all powerful root\n privilege into a set of distinct privileges.\n \n
|
17
|
+
\ See capabilites(7) for more information.\n"
|
18
|
+
email:
|
19
|
+
- lewismarshall86@gmail.com
|
20
|
+
executables: []
|
21
|
+
extensions:
|
22
|
+
- ext/cap2/extconf.rb
|
23
|
+
extra_rdoc_files: []
|
24
|
+
files:
|
25
|
+
- README.md
|
26
|
+
- Rakefile
|
27
|
+
- LICENSE
|
28
|
+
- ext/cap2/extconf.rb
|
29
|
+
- ext/cap2/cap2.c
|
30
|
+
- lib/cap2.rb
|
31
|
+
- lib/cap2/process.rb
|
32
|
+
- lib/cap2/entity.rb
|
33
|
+
- lib/cap2/version.rb
|
34
|
+
- lib/cap2/file.rb
|
35
|
+
- spec/support/entity.rb
|
36
|
+
- spec/process_spec.rb
|
37
|
+
- spec/cap2_spec.rb
|
38
|
+
- spec/spec_helper.rb
|
39
|
+
- spec/file_spec.rb
|
40
|
+
homepage: https://github.com/lmars/cap2
|
41
|
+
licenses: []
|
42
|
+
post_install_message:
|
43
|
+
rdoc_options: []
|
44
|
+
require_paths:
|
45
|
+
- lib
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
none: false
|
48
|
+
requirements:
|
49
|
+
- - ! '>='
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ! '>='
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '0'
|
58
|
+
requirements: []
|
59
|
+
rubyforge_project:
|
60
|
+
rubygems_version: 1.8.23
|
61
|
+
signing_key:
|
62
|
+
specification_version: 3
|
63
|
+
summary: A Ruby library for managing Linux file and process capabilities
|
64
|
+
test_files: []
|