capbac 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 88589fad2be4f62d09eea046bd902057b259be959578d08c67e35a5d1b9877a0
4
+ data.tar.gz: e7e7be8ba72bb20186cbfe2babfa742451aa514100e04e3097acb7b2dac3b2f6
5
+ SHA512:
6
+ metadata.gz: e05d719e53998961edb131743604d86a1dc2b8e9e7671258cc54ee8e6ddaf0bf958215ab51d8370198abc6ae7e00ac57fd7df387269db844b328bab90bb121e0
7
+ data.tar.gz: 3a6356425474be7a70af3be13e65dcdc05a644f3cf2e0734ae4f2758208f484424b2976271de58ff7facb010c0eb6143a1288eb9717812aded00b3eefb763560
@@ -0,0 +1,16 @@
1
+ [package]
2
+ name = "capbac-ruby"
3
+ version = "0.2.0"
4
+ authors = ["Kirill Chernyshov <delaguardo@gmail.com>"]
5
+ edition = "2018"
6
+
7
+ [lib]
8
+ crate-type = ["cdylib"]
9
+
10
+ [dependencies]
11
+ rutie = "0.6.1"
12
+ url = "2.1"
13
+ openssl = "0.10"
14
+ lazy_static = "1"
15
+ protobuf = "~2"
16
+ capbac = "0.2.0"
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2020 Xapix GmbH
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,35 @@
1
+ # Capbac
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/capbac`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'capbac'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install capbac
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/capbac.
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'thermite/tasks'
4
+
5
+ project_dir = File.dirname(File.dirname(__FILE__))
6
+ Thermite::Tasks.new(cargo_project_path: project_dir, ruby_project_path: project_dir)
7
+ task default: %w[thermite:build]
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rutie'
4
+ require 'capbac/trust_checker'
5
+ require 'capbac/pubs'
6
+ require 'capbac/exceptions'
7
+
8
+ Rutie.new(:capbac_ruby).init 'Init_capbac', __dir__
@@ -0,0 +1,10 @@
1
+ module CapBAC
2
+ class BadSign < StandardError; end
3
+ class Expired < StandardError; end
4
+ class Untrusted < StandardError; end
5
+ class BadInvoker < StandardError; end
6
+ class BadIssuer < StandardError; end
7
+ class UnknownPub < StandardError; end
8
+ class BadURL < StandardError; end
9
+ class Malformed < StandardError; end
10
+ end
@@ -0,0 +1,5 @@
1
+ module CapBAC
2
+ class Pubs
3
+ def get(id); end
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module CapBAC
2
+ class TrustChecker
3
+ def trusted?(id); end
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ module CapBAC
2
+ VERSION = '0.2.0'.freeze
3
+ end
@@ -0,0 +1,431 @@
1
+ #[macro_use] extern crate rutie;
2
+ #[macro_use] extern crate lazy_static;
3
+
4
+ use rutie::{Module, Class, RString, Object, AnyObject, Array,
5
+ Fixnum, Hash, Symbol, VM, Boolean, GC, VerifiedObject};
6
+ use capbac::{CertificateBlueprint, InvokeBlueprint};
7
+ use url::Url;
8
+ use openssl::pkey::{PKey, Public};
9
+ use openssl::ec::EcKey;
10
+ use protobuf::{Message};
11
+ use std::fmt;
12
+
13
+ class!(URI);
14
+
15
+ impl VerifiedObject for URI {
16
+ fn is_correct_type<T: Object>(object: &T) -> bool {
17
+ object.class().ancestors().iter()
18
+ .any(|class| *class == Class::from_existing("URI"))
19
+ }
20
+
21
+ fn error_message() -> &'static str {
22
+ "Error converting to URI"
23
+ }
24
+ }
25
+
26
+ impl fmt::Display for URI {
27
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
28
+ let s = self.send("to_s", &vec![]).try_convert_to::<RString>().unwrap().to_string();
29
+ write!(f, "{}", s)
30
+ }
31
+ }
32
+
33
+ impl From<&Url> for URI {
34
+ fn from(url: &Url) -> Self {
35
+ Class::from_existing("URI").send("parse", &vec![RString::new_utf8(&url.clone().to_string()).to_any_object()]).try_convert_to::<URI>().unwrap()
36
+ }
37
+ }
38
+
39
+ impl From<URI> for Url {
40
+ fn from(uri: URI) -> Self {
41
+ Url::parse(&uri.to_string()).unwrap()
42
+ }
43
+ }
44
+
45
+ fn options_to_cert_blueprint(options: Hash) -> CertificateBlueprint {
46
+ let subject = options
47
+ .at(&Symbol::new("subject"))
48
+ .try_convert_to::<URI>();
49
+
50
+ if let Err(ref _error) = subject {
51
+ VM::raise(Class::from_existing("ArgumentError"), "Subject must be an instance of URI");
52
+ }
53
+
54
+ let subject = Url::from(subject.unwrap());
55
+
56
+ let capability = options
57
+ .at(&Symbol::new("capability"))
58
+ .try_convert_to::<RString>();
59
+
60
+ if let Err(ref _error) = capability {
61
+ VM::raise(Class::from_existing("ArgumentError"), "Capability must be a string");
62
+ }
63
+
64
+ let capability = capability
65
+ .unwrap().to_string()
66
+ .into_bytes();
67
+
68
+ let exp = match options.at(&Symbol::new("exp")).try_convert_to::<Fixnum>() {
69
+ Ok(x) => Some(x.to_i64() as u64),
70
+ _ => None
71
+ };
72
+
73
+ CertificateBlueprint {
74
+ subject,
75
+ capability,
76
+ exp
77
+ }
78
+ }
79
+
80
+ fn array_to_cert(array: Array) -> capbac::proto::Certificate {
81
+ let mut cert_content: Vec<u8> = Vec::new();
82
+ for n in array.into_iter() {
83
+ let n = n.try_convert_to::<Fixnum>();
84
+
85
+ if let Err(ref error) = n {
86
+ VM::raise(error.class(), &error.to_string());
87
+ }
88
+
89
+ cert_content.push(n.unwrap().to_i64() as u8);
90
+ }
91
+ let mut cert = capbac::proto::Certificate::new();
92
+ cert.merge_from_bytes(&cert_content).unwrap();
93
+ cert
94
+ }
95
+
96
+ fn options_to_invoke_blueprint(options: Hash) -> InvokeBlueprint {
97
+
98
+ let cert_content = options
99
+ .at(&Symbol::new("cert"))
100
+ .try_convert_to::<Array>();
101
+
102
+ if let Err(ref _error) = cert_content {
103
+ VM::raise(Class::from_existing("ArgumentError"), "Certificate must be an array");
104
+ }
105
+
106
+ let cert = array_to_cert(cert_content.unwrap());
107
+
108
+ let action = options
109
+ .at(&Symbol::new("action"))
110
+ .try_convert_to::<RString>();
111
+
112
+ if let Err(ref _error) = action {
113
+ VM::raise(Class::from_existing("ArgumentError"), "Action must be a string");
114
+ }
115
+
116
+ let action = action
117
+ .unwrap().to_string()
118
+ .into_bytes();
119
+
120
+ let exp = match options.at(&Symbol::new("exp")).try_convert_to::<Fixnum>() {
121
+ Ok(x) => Some(x.to_i64() as u64),
122
+ _ => None
123
+ };
124
+
125
+ InvokeBlueprint {
126
+ cert,
127
+ action,
128
+ exp
129
+ }
130
+ }
131
+
132
+ wrappable_struct!(capbac::Holder, HolderWrapper, HOLDER_WRAPPER);
133
+
134
+ class!(Holder);
135
+
136
+ methods!(
137
+ Holder,
138
+ itself,
139
+
140
+ fn ruby_holder_new(me: URI, sk: Array) -> AnyObject {
141
+ if let Err(ref error) = me {
142
+ VM::raise(error.class(), &error.to_string());
143
+ }
144
+
145
+ if let Err(ref error) = sk {
146
+ VM::raise(error.class(), &error.to_string());
147
+ }
148
+
149
+ let me = Url::parse(&me.unwrap().to_string());
150
+
151
+ if let Err(ref error) = me {
152
+ VM::raise(Class::from_existing("ArgumentError"), &error.to_string())
153
+ }
154
+
155
+ let mut sk_content: Vec<u8> = Vec::new();
156
+ for n in sk.unwrap().into_iter() {
157
+ let n = n.try_convert_to::<Fixnum>();
158
+
159
+ if let Err(ref error) = n {
160
+ VM::raise(error.class(), &error.to_string());
161
+ }
162
+
163
+ sk_content.push(n.unwrap().to_i64() as u8);
164
+ }
165
+
166
+ let holder = capbac::Holder::new(me.unwrap(), PKey::private_key_from_pkcs8(&sk_content).unwrap().ec_key().unwrap());
167
+
168
+ Class::from_existing("CapBAC")
169
+ .get_nested_class("Holder")
170
+ .wrap_data(holder, &*HOLDER_WRAPPER)
171
+ }
172
+
173
+ fn ruby_holder_forge(options: Hash) -> Array {
174
+ if let Err(ref _error) = options {
175
+ VM::raise(Class::from_existing("ArgumentError"), "Options must be a hash");
176
+ }
177
+
178
+ let options = options_to_cert_blueprint(options.unwrap());
179
+
180
+ let holder = itself.get_data(&*HOLDER_WRAPPER);
181
+ let cert = holder.forge(options).unwrap();
182
+
183
+ let mut res = Array::new();
184
+ for item in cert.write_to_bytes().unwrap().iter() {
185
+ res.push(Fixnum::new(i64::from(*item)));
186
+ };
187
+ res
188
+ }
189
+
190
+ fn ruby_holder_delegate(cert: Array, options: Hash) -> Array {
191
+ if let Err(ref _error) = options {
192
+ VM::raise(Class::from_existing("ArgumentError"), "Options must be a hash");
193
+ }
194
+
195
+ let options = options_to_cert_blueprint(options.unwrap());
196
+ let holder = itself.get_data(&*HOLDER_WRAPPER);
197
+ let cert = array_to_cert(cert.unwrap());
198
+
199
+ let cert = holder.delegate(cert, options).unwrap();
200
+ let mut res = Array::new();
201
+ for item in cert.write_to_bytes().unwrap().iter() {
202
+ res.push(Fixnum::new(i64::from(*item)));
203
+ };
204
+ res
205
+ }
206
+
207
+ fn ruby_holder_invoke(options: Hash) -> Array {
208
+ if let Err(ref _error) = options {
209
+ VM::raise(Class::from_existing("ArgumentError"), "Options must be a hash");
210
+ }
211
+
212
+ let options = options_to_invoke_blueprint(options.unwrap());
213
+ let holder = itself.get_data(&*HOLDER_WRAPPER);
214
+
215
+ let invocation = holder.invoke(options).unwrap();
216
+ let mut res = Array::new();
217
+ for item in invocation.write_to_bytes().unwrap().iter() {
218
+ res.push(Fixnum::new(i64::from(*item)));
219
+ };
220
+ res
221
+ }
222
+ );
223
+
224
+ pub struct IntValidator {
225
+ trust_checker: AnyObject,
226
+ pubs: AnyObject,
227
+ }
228
+
229
+ impl IntValidator {
230
+ fn new(trust_checker: AnyObject, pubs: AnyObject) -> Self {
231
+ IntValidator {
232
+ trust_checker,
233
+ pubs
234
+ }
235
+ }
236
+ }
237
+
238
+ impl capbac::TrustChecker for IntValidator {
239
+ fn is_trusted(&self, id: &Url) -> bool {
240
+ let args = vec![URI::from(id).to_any_object()];
241
+ self.trust_checker
242
+ .send("trusted?", &args)
243
+ .try_convert_to::<Boolean>()
244
+ .unwrap_or(Boolean::new(false))
245
+ .to_bool()
246
+ }
247
+ }
248
+
249
+ impl capbac::Pubs for IntValidator {
250
+ fn get(&self, id: &Url) -> Option<EcKey<Public>> {
251
+ let res = self.pubs.send("get", &vec![URI::from(id).to_any_object()]).try_convert_to::<Array>();
252
+ if let Err(ref _error) = res {
253
+ return None
254
+ }
255
+ let mut pk_content: Vec<u8> = Vec::new();
256
+ for n in res.unwrap().into_iter() {
257
+ let n = n.try_convert_to::<Fixnum>();
258
+
259
+ if let Err(ref error) = n {
260
+ VM::raise(error.class(), &error.to_string());
261
+ }
262
+
263
+ pk_content.push(n.unwrap().to_i64() as u8);
264
+ }
265
+ Some(PKey::public_key_from_der(&pk_content).unwrap().ec_key().unwrap())
266
+ }
267
+ }
268
+
269
+ wrappable_struct!(IntValidator, IntValidatorWrapper, INT_VALIDATOR_WRAPPER, mark(data) {
270
+ GC::mark(&data.trust_checker);
271
+ GC::mark(&data.pubs);
272
+ });
273
+
274
+ class!(Validator);
275
+
276
+ methods!(
277
+ Validator,
278
+ itself,
279
+
280
+ fn ruby_validator_new(trust_checker: AnyObject, pubs: AnyObject) -> AnyObject {
281
+ let validator = IntValidator::new(trust_checker.unwrap(), pubs.unwrap());
282
+
283
+ Class::from_existing("CapBAC")
284
+ .get_nested_class("Validator")
285
+ .wrap_data(validator, &*INT_VALIDATOR_WRAPPER)
286
+ }
287
+
288
+ fn ruby_validator_validate_cert(cert: Array, now: Fixnum) -> Boolean {
289
+ if let Err(ref error) = cert {
290
+ VM::raise(error.class(), &error.to_string());
291
+ }
292
+
293
+ if let Err(ref error) = now {
294
+ VM::raise(error.class(), &error.to_string());
295
+ }
296
+
297
+ let mut cert_content: Vec<u8> = Vec::new();
298
+ for n in cert.unwrap().into_iter() {
299
+ let n = n.try_convert_to::<Fixnum>();
300
+
301
+ if let Err(ref error) = n {
302
+ VM::raise(error.class(), &error.to_string());
303
+ }
304
+
305
+ cert_content.push(n.unwrap().to_i64() as u8);
306
+ }
307
+ let mut cert = capbac::proto::Certificate::new();
308
+ cert.merge_from_bytes(&cert_content).unwrap();
309
+
310
+ let now = now.unwrap().to_i64() as u64;
311
+
312
+ let x = itself.get_data(&*INT_VALIDATOR_WRAPPER);
313
+ let validator = capbac::Validator::new(x, x);
314
+
315
+ match validator.validate_cert(&cert, now) {
316
+ Result::Ok(_) => Boolean::new(true),
317
+ Err(x) => {
318
+ let capbac_class = Class::from_existing("CapBAC");
319
+ match x {
320
+ capbac::ValidateError::Malformed { .. } => {
321
+ VM::raise(capbac_class.get_nested_class("Malformed"), &format!("{}", x))
322
+ },
323
+ capbac::ValidateError::BadURL { .. } => {
324
+ VM::raise(capbac_class.get_nested_class("BadURL"), &format!("{}", x))
325
+ },
326
+ capbac::ValidateError::UnknownPub { .. } => {
327
+ VM::raise(capbac_class.get_nested_class("UnknownPub"), &format!("{}", x))
328
+ },
329
+ capbac::ValidateError::BadIssuer { .. } => {
330
+ VM::raise(capbac_class.get_nested_class("BadIssuer"), &format!("{}", x))
331
+ },
332
+ capbac::ValidateError::BadInvoker { .. } => {
333
+ VM::raise(capbac_class.get_nested_class("BadInvoker"), &format!("{}", x))
334
+ },
335
+ capbac::ValidateError::Untrusted { .. } => {
336
+ VM::raise(capbac_class.get_nested_class("Untrusted"), &format!("{}", x))
337
+ },
338
+ capbac::ValidateError::Expired => {
339
+ VM::raise(capbac_class.get_nested_class("Expired"), &format!("{}", x))
340
+ }
341
+ capbac::ValidateError::BadSign => {
342
+ VM::raise(capbac_class.get_nested_class("BadSign"), &format!("{}", x))
343
+ }
344
+ }
345
+ Boolean::new(false)
346
+ }
347
+ }
348
+ }
349
+
350
+ fn ruby_validator_validate_invocation(invocation: Array, now: Fixnum) -> Boolean {
351
+ if let Err(ref error) = invocation {
352
+ VM::raise(error.class(), &error.to_string());
353
+ }
354
+
355
+ if let Err(ref error) = now {
356
+ VM::raise(error.class(), &error.to_string());
357
+ }
358
+
359
+ let mut invocation_content: Vec<u8> = Vec::new();
360
+ for n in invocation.unwrap().into_iter() {
361
+ let n = n.try_convert_to::<Fixnum>();
362
+
363
+ if let Err(ref error) = n {
364
+ VM::raise(error.class(), &error.to_string());
365
+ }
366
+
367
+ invocation_content.push(n.unwrap().to_i64() as u8);
368
+ }
369
+ let mut invocation = capbac::proto::Invocation::new();
370
+ invocation.merge_from_bytes(&invocation_content).unwrap();
371
+
372
+ let now = now.unwrap().to_i64() as u64;
373
+
374
+ let x = itself.get_data(&*INT_VALIDATOR_WRAPPER);
375
+ let validator = capbac::Validator::new(x, x);
376
+
377
+ match validator.validate_invocation(&invocation, now) {
378
+ Result::Ok(_) => Boolean::new(true),
379
+ Err(x) => {
380
+ let capbac_class = Class::from_existing("CapBAC");
381
+ match x {
382
+ capbac::ValidateError::Malformed { .. } => {
383
+ VM::raise(capbac_class.get_nested_class("Malformed"), &format!("{}", x))
384
+ },
385
+ capbac::ValidateError::BadURL { .. } => {
386
+ VM::raise(capbac_class.get_nested_class("BadURL"), &format!("{}", x))
387
+ },
388
+ capbac::ValidateError::UnknownPub { .. } => {
389
+ VM::raise(capbac_class.get_nested_class("UnknownPub"), &format!("{}", x))
390
+ },
391
+ capbac::ValidateError::BadIssuer { .. } => {
392
+ VM::raise(capbac_class.get_nested_class("BadIssuer"), &format!("{}", x))
393
+ },
394
+ capbac::ValidateError::BadInvoker { .. } => {
395
+ VM::raise(capbac_class.get_nested_class("BadInvoker"), &format!("{}", x))
396
+ },
397
+ capbac::ValidateError::Untrusted { .. } => {
398
+ VM::raise(capbac_class.get_nested_class("Untrusted"), &format!("{}", x))
399
+ },
400
+ capbac::ValidateError::Expired => {
401
+ VM::raise(capbac_class.get_nested_class("Expired"), &format!("{}", x))
402
+ }
403
+ capbac::ValidateError::BadSign => {
404
+ VM::raise(capbac_class.get_nested_class("BadSign"), &format!("{}", x))
405
+ }
406
+ }
407
+ Boolean::new(false)
408
+ }
409
+ }
410
+
411
+ }
412
+ );
413
+
414
+ #[allow(non_snake_case)]
415
+ #[no_mangle]
416
+ pub extern "C" fn Init_capbac() {
417
+ Module::from_existing("CapBAC").define(|itself| {
418
+ itself.define_nested_class("Holder", None).define(|itself| {
419
+ itself.def_self("new", ruby_holder_new);
420
+ itself.def("forge", ruby_holder_forge);
421
+ itself.def("delegate", ruby_holder_delegate);
422
+ itself.def("invoke", ruby_holder_invoke);
423
+ });
424
+
425
+ itself.define_nested_class("Validator", None).define(|itself| {
426
+ itself.def_self("new", ruby_validator_new);
427
+ itself.def("validate_cert", ruby_validator_validate_cert);
428
+ itself.def("validate_invocation", ruby_validator_validate_invocation);
429
+ });
430
+ });
431
+ }
metadata ADDED
@@ -0,0 +1,137 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: capbac
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Kirill Chernyshov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-07-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thermite
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rutie
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.0.3
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.0.3
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 13.0.1
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 13.0.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.87.1
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.87.1
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubygems-tasks
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.2.5
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.2.5
97
+ description:
98
+ email: delaguardo@gmail.com
99
+ executables: []
100
+ extensions:
101
+ - ext/Rakefile
102
+ extra_rdoc_files: []
103
+ files:
104
+ - Cargo.toml
105
+ - LICENSE
106
+ - README.md
107
+ - ext/Rakefile
108
+ - lib/capbac.rb
109
+ - lib/capbac/exceptions.rb
110
+ - lib/capbac/pubs.rb
111
+ - lib/capbac/trust_checker.rb
112
+ - lib/capbac/version.rb
113
+ - src/lib.rs
114
+ homepage: http://capbac.org
115
+ licenses:
116
+ - MIT
117
+ metadata: {}
118
+ post_install_message:
119
+ rdoc_options: []
120
+ require_paths:
121
+ - lib
122
+ required_ruby_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ required_rubygems_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ requirements: []
133
+ rubygems_version: 3.1.2
134
+ signing_key:
135
+ specification_version: 4
136
+ summary: Ruby implementation for Capability-based Access Control model
137
+ test_files: []