nofxx-nanite 0.4.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. data/LICENSE +201 -0
  2. data/README.rdoc +430 -0
  3. data/Rakefile +76 -0
  4. data/TODO +24 -0
  5. data/bin/nanite-admin +65 -0
  6. data/bin/nanite-agent +79 -0
  7. data/bin/nanite-mapper +50 -0
  8. data/lib/nanite.rb +74 -0
  9. data/lib/nanite/actor.rb +71 -0
  10. data/lib/nanite/actor_registry.rb +26 -0
  11. data/lib/nanite/admin.rb +138 -0
  12. data/lib/nanite/agent.rb +258 -0
  13. data/lib/nanite/amqp.rb +54 -0
  14. data/lib/nanite/cluster.rb +236 -0
  15. data/lib/nanite/config.rb +111 -0
  16. data/lib/nanite/console.rb +39 -0
  17. data/lib/nanite/daemonize.rb +13 -0
  18. data/lib/nanite/dispatcher.rb +92 -0
  19. data/lib/nanite/identity.rb +16 -0
  20. data/lib/nanite/job.rb +104 -0
  21. data/lib/nanite/local_state.rb +34 -0
  22. data/lib/nanite/log.rb +66 -0
  23. data/lib/nanite/log/formatter.rb +39 -0
  24. data/lib/nanite/mapper.rb +310 -0
  25. data/lib/nanite/mapper_proxy.rb +67 -0
  26. data/lib/nanite/packets.rb +365 -0
  27. data/lib/nanite/pid_file.rb +52 -0
  28. data/lib/nanite/reaper.rb +38 -0
  29. data/lib/nanite/security/cached_certificate_store_proxy.rb +24 -0
  30. data/lib/nanite/security/certificate.rb +55 -0
  31. data/lib/nanite/security/certificate_cache.rb +66 -0
  32. data/lib/nanite/security/distinguished_name.rb +34 -0
  33. data/lib/nanite/security/encrypted_document.rb +46 -0
  34. data/lib/nanite/security/rsa_key_pair.rb +53 -0
  35. data/lib/nanite/security/secure_serializer.rb +68 -0
  36. data/lib/nanite/security/signature.rb +46 -0
  37. data/lib/nanite/security/static_certificate_store.rb +35 -0
  38. data/lib/nanite/security_provider.rb +47 -0
  39. data/lib/nanite/serializer.rb +52 -0
  40. data/lib/nanite/state.rb +164 -0
  41. data/lib/nanite/streaming.rb +125 -0
  42. data/lib/nanite/util.rb +58 -0
  43. data/spec/actor_registry_spec.rb +60 -0
  44. data/spec/actor_spec.rb +77 -0
  45. data/spec/agent_spec.rb +240 -0
  46. data/spec/cached_certificate_store_proxy_spec.rb +34 -0
  47. data/spec/certificate_cache_spec.rb +49 -0
  48. data/spec/certificate_spec.rb +27 -0
  49. data/spec/cluster_spec.rb +485 -0
  50. data/spec/dispatcher_spec.rb +136 -0
  51. data/spec/distinguished_name_spec.rb +24 -0
  52. data/spec/encrypted_document_spec.rb +21 -0
  53. data/spec/job_spec.rb +251 -0
  54. data/spec/local_state_spec.rb +112 -0
  55. data/spec/packet_spec.rb +220 -0
  56. data/spec/rsa_key_pair_spec.rb +33 -0
  57. data/spec/secure_serializer_spec.rb +41 -0
  58. data/spec/serializer_spec.rb +107 -0
  59. data/spec/signature_spec.rb +30 -0
  60. data/spec/spec_helper.rb +33 -0
  61. data/spec/static_certificate_store_spec.rb +30 -0
  62. data/spec/util_spec.rb +63 -0
  63. metadata +131 -0
@@ -0,0 +1,220 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ class TestPacket < Nanite::Packet
4
+ @@cls_attr = "ignore"
5
+ def initialize(attr1)
6
+ @attr1 = attr1
7
+ end
8
+ end
9
+
10
+ describe "Packet: Base class" do
11
+
12
+ before(:all) do
13
+ end
14
+
15
+ it "should be an abstract class" do
16
+ lambda { Nanite::Packet.new }.should raise_error(NotImplementedError, "Nanite::Packet is an abstract class.")
17
+ end
18
+
19
+ it "should know how to dump itself to JSON" do
20
+ packet = TestPacket.new(1)
21
+ packet.should respond_to(:to_json)
22
+ end
23
+
24
+ it "should dump the class name in 'json_class' JSON key" do
25
+ packet = TestPacket.new(42)
26
+ packet.to_json().should =~ /\"json_class\":\"TestPacket\"/
27
+ end
28
+
29
+ it "should dump instance variables in 'data' JSON key" do
30
+ packet = TestPacket.new(188)
31
+ packet.to_json().should =~ /\"data\":\{\"attr1\":188\}/
32
+ end
33
+
34
+ it "should not dump class variables" do
35
+ packet = TestPacket.new(382)
36
+ packet.to_json().should_not =~ /cls_attr/
37
+ end
38
+
39
+ it "should store instance variables in 'data' JSON key as JSON object" do
40
+ packet = TestPacket.new(382)
41
+ packet.to_json().should =~ /\"data\":\{[\w:"]+\}/
42
+ end
43
+
44
+ it "should remove '@' from instance variables" do
45
+ packet = TestPacket.new(2)
46
+ packet.to_json().should_not =~ /@attr1/
47
+ packet.to_json().should =~ /attr1/
48
+ end
49
+ end
50
+
51
+
52
+ describe "Packet: FileStart" do
53
+ it "should dump/load as JSON objects" do
54
+ packet = Nanite::FileStart.new('foo.txt', 'somewhere/foo.txt', '0xdeadbeef')
55
+ packet2 = JSON.parse(packet.to_json)
56
+ packet.filename.should == packet2.filename
57
+ packet.dest.should == packet2.dest
58
+ packet.token.should == packet2.token
59
+ end
60
+
61
+ it "should dump/load as Marshalled ruby objects" do
62
+ packet = Nanite::FileStart.new('foo.txt', 'somewhere/foo.txt', '0xdeadbeef')
63
+ packet2 = Marshal.load(Marshal.dump(packet))
64
+ packet.filename.should == packet2.filename
65
+ packet.dest.should == packet2.dest
66
+ packet.token.should == packet2.token
67
+ end
68
+ end
69
+
70
+
71
+ describe "Packet: FileEnd" do
72
+ it "should dump/load as JSON objects" do
73
+ packet = Nanite::FileEnd.new('0xdeadbeef', 'metadata')
74
+ packet2 = JSON.parse(packet.to_json)
75
+ packet.meta.should == packet2.meta
76
+ packet.token.should == packet2.token
77
+ end
78
+
79
+ it "should dump/load as Marshalled ruby objects" do
80
+ packet = Nanite::FileEnd.new('0xdeadbeef', 'metadata')
81
+ packet2 = Marshal.load(Marshal.dump(packet))
82
+ packet.meta.should == packet2.meta
83
+ packet.token.should == packet2.token
84
+ end
85
+ end
86
+
87
+
88
+ describe "Packet: FileChunk" do
89
+ it "should dump/load as JSON objects" do
90
+ packet = Nanite::FileChunk.new('chunk','0xdeadbeef')
91
+ packet2 = JSON.parse(packet.to_json)
92
+ packet.chunk.should == packet2.chunk
93
+ packet.token.should == packet2.token
94
+ end
95
+
96
+ it "should dump/load as Marshalled ruby objects" do
97
+ packet = Nanite::FileChunk.new('chunk','0xdeadbeef')
98
+ packet2 = Marshal.load(Marshal.dump(packet))
99
+ packet.chunk.should == packet2.chunk
100
+ packet.token.should == packet2.token
101
+ end
102
+ end
103
+
104
+
105
+ describe "Packet: Request" do
106
+ it "should dump/load as JSON objects" do
107
+ packet = Nanite::Request.new('/some/foo', 'payload', :from => 'from', :token => '0xdeadbeef', :reply_to => 'reply_to')
108
+ packet2 = JSON.parse(packet.to_json)
109
+ packet.type.should == packet2.type
110
+ packet.payload.should == packet2.payload
111
+ packet.from.should == packet2.from
112
+ packet.token.should == packet2.token
113
+ packet.reply_to.should == packet2.reply_to
114
+ end
115
+
116
+ it "should dump/load as Marshalled ruby objects" do
117
+ packet = Nanite::Request.new('/some/foo', 'payload', :from => 'from', :token => '0xdeadbeef', :reply_to => 'reply_to')
118
+ packet2 = Marshal.load(Marshal.dump(packet))
119
+ packet.type.should == packet2.type
120
+ packet.payload.should == packet2.payload
121
+ packet.from.should == packet2.from
122
+ packet.token.should == packet2.token
123
+ packet.reply_to.should == packet2.reply_to
124
+ end
125
+ end
126
+
127
+
128
+ describe "Packet: Result" do
129
+ it "should dump/load as JSON objects" do
130
+ packet = Nanite::Result.new('0xdeadbeef', 'to', 'results', 'from')
131
+ packet2 = JSON.parse(packet.to_json)
132
+ packet.token.should == packet2.token
133
+ packet.to.should == packet2.to
134
+ packet.results.should == packet2.results
135
+ packet.from.should == packet2.from
136
+ end
137
+
138
+ it "should dump/load as Marshalled ruby objects" do
139
+ packet = Nanite::Result.new('0xdeadbeef', 'to', 'results', 'from')
140
+ packet2 = Marshal.load(Marshal.dump(packet))
141
+ packet.token.should == packet2.token
142
+ packet.to.should == packet2.to
143
+ packet.results.should == packet2.results
144
+ packet.from.should == packet2.from
145
+ end
146
+ end
147
+
148
+
149
+ describe "Packet: IntermediateMessage" do
150
+ it "should dump/load as JSON objects" do
151
+ packet = Nanite::IntermediateMessage.new('0xdeadbeef', 'to', 'from', 'messagekey', 'message')
152
+ packet2 = JSON.parse(packet.to_json)
153
+ packet.token.should == packet2.token
154
+ packet.to.should == packet2.to
155
+ packet.from.should == packet2.from
156
+ packet.messagekey.should == packet2.messagekey
157
+ packet.message.should == packet2.message
158
+ end
159
+
160
+ it "should dump/load as Marshalled ruby objects" do
161
+ packet = Nanite::IntermediateMessage.new('0xdeadbeef', 'to', 'from', 'messagekey', 'message')
162
+ packet2 = Marshal.load(Marshal.dump(packet))
163
+ packet.token.should == packet2.token
164
+ packet.to.should == packet2.to
165
+ packet.from.should == packet2.from
166
+ packet.messagekey.should == packet2.messagekey
167
+ packet.message.should == packet2.message
168
+ end
169
+ end
170
+
171
+
172
+ describe "Packet: Register" do
173
+ it "should dump/load as JSON objects" do
174
+ packet = Nanite::Register.new('0xdeadbeef', ['/foo/bar', '/nik/qux'], 0.8, ['foo'])
175
+ packet2 = JSON.parse(packet.to_json)
176
+ packet.identity.should == packet2.identity
177
+ packet.services.should == packet2.services
178
+ packet.status.should == packet2.status
179
+ end
180
+
181
+ it "should dump/load as Marshalled ruby objects" do
182
+ packet = Nanite::Register.new('0xdeadbeef', ['/foo/bar', '/nik/qux'], 0.8, ['foo'])
183
+ packet2 = Marshal.load(Marshal.dump(packet))
184
+ packet.identity.should == packet2.identity
185
+ packet.services.should == packet2.services
186
+ packet.status.should == packet2.status
187
+ end
188
+ end
189
+
190
+
191
+ describe "Packet: UnRegister" do
192
+ it "should dump/load as JSON objects" do
193
+ packet = Nanite::UnRegister.new('0xdeadbeef')
194
+ packet2 = JSON.parse(packet.to_json)
195
+ packet.identity.should == packet2.identity
196
+ end
197
+
198
+ it "should dump/load as Marshalled ruby objects" do
199
+ packet = Nanite::UnRegister.new('0xdeadbeef')
200
+ packet2 = Marshal.load(Marshal.dump(packet))
201
+ packet.identity.should == packet2.identity
202
+ end
203
+ end
204
+
205
+
206
+ describe "Packet: Ping" do
207
+ it "should dump/load as JSON objects" do
208
+ packet = Nanite::Ping.new('0xdeadbeef', 0.8)
209
+ packet2 = JSON.parse(packet.to_json)
210
+ packet.identity.should == packet2.identity
211
+ packet.status.should == packet2.status
212
+ end
213
+
214
+ it "should dump/load as Marshalled ruby objects" do
215
+ packet = Nanite::Ping.new('0xdeadbeef', 0.8)
216
+ packet2 = Marshal.load(Marshal.dump(packet))
217
+ packet.identity.should == packet2.identity
218
+ packet.status.should == packet2.status
219
+ end
220
+ end
@@ -0,0 +1,33 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe Nanite::RsaKeyPair do
4
+
5
+ before(:all) do
6
+ @pair = Nanite::RsaKeyPair.new
7
+ end
8
+
9
+ it 'should create a private and a public keys' do
10
+ @pair.has_private?.should be_true
11
+ end
12
+
13
+ it 'should strip out private key in to_public' do
14
+ @pair.to_public.has_private?.should be_false
15
+ end
16
+
17
+ it 'should save' do
18
+ filename = File.join(File.dirname(__FILE__), "key.pem")
19
+ @pair.save(filename)
20
+ File.size(filename).should be > 0
21
+ File.delete(filename)
22
+ end
23
+
24
+ it 'should load' do
25
+ filename = File.join(File.dirname(__FILE__), "key.pem")
26
+ @pair.save(filename)
27
+ key = Nanite::RsaKeyPair.load(filename)
28
+ File.delete(filename)
29
+ key.should_not be_nil
30
+ key.data.should == @pair.data
31
+ end
32
+
33
+ end
@@ -0,0 +1,41 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ module Nanite
4
+
5
+ # Add the ability to compare pings for test purposes
6
+ class Ping
7
+ def ==(other)
8
+ @status == other.status && @identity == other.identity
9
+ end
10
+ end
11
+
12
+ end
13
+
14
+ describe Nanite::SecureSerializer do
15
+
16
+ include SpecHelpers
17
+
18
+ before(:all) do
19
+ @certificate, @key = issue_cert
20
+ @store = Nanite::StaticCertificateStore.new(@certificate, @certificate)
21
+ @identity = "id"
22
+ @data = Nanite::Ping.new("Test", 0.5)
23
+ end
24
+
25
+ it 'should raise when not initialized' do
26
+ lambda { Nanite::SecureSerializer.dump(@data) }.should raise_error
27
+ end
28
+
29
+ it 'should deserialize signed data' do
30
+ Nanite::SecureSerializer.init(@identity, @certificate, @key, @store, false)
31
+ data = Nanite::SecureSerializer.dump(@data)
32
+ Nanite::SecureSerializer.load(data).should == @data
33
+ end
34
+
35
+ it 'should deserialize encrypted data' do
36
+ Nanite::SecureSerializer.init(@identity, @certificate, @key, @store, true)
37
+ data = Nanite::SecureSerializer.dump(@data)
38
+ Nanite::SecureSerializer.load(data).should == @data
39
+ end
40
+
41
+ end
@@ -0,0 +1,107 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe Nanite::Serializer do
4
+
5
+ describe "Format" do
6
+
7
+ it "supports JSON format" do
8
+ [ :json, "json" ].each do |format|
9
+ serializer = Nanite::Serializer.new(format)
10
+ serializer.instance_eval { @serializers.first }.should == JSON
11
+ end
12
+ end
13
+
14
+ it "supports Marshal format" do
15
+ [ :marshal, "marshal" ].each do |format|
16
+ serializer = Nanite::Serializer.new(format)
17
+ serializer.instance_eval { @serializers.first }.should == Marshal
18
+ end
19
+ end
20
+
21
+ it "supports YAML format" do
22
+ [ :yaml, "yaml" ].each do |format|
23
+ serializer = Nanite::Serializer.new(format)
24
+ serializer.instance_eval { @serializers.first }.should == YAML
25
+ end
26
+ end
27
+
28
+ it "should default to Marshal format if not specified" do
29
+ serializer = Nanite::Serializer.new
30
+ serializer.instance_eval { @serializers.first }.should == Marshal
31
+ serializer = Nanite::Serializer.new(nil)
32
+ serializer.instance_eval { @serializers.first }.should == Marshal
33
+ end
34
+
35
+ end # Format
36
+
37
+ describe "Serialization of Packet" do
38
+
39
+ it "should cascade through available serializers" do
40
+ serializer = Nanite::Serializer.new
41
+ serializer.should_receive(:cascade_serializers).with(:dump, "hello")
42
+ serializer.dump("hello")
43
+ end
44
+
45
+ it "should try all three supported formats (JSON, Marshal, YAML)" do
46
+ JSON.should_receive(:dump).with("hello").and_raise(StandardError)
47
+ Marshal.should_receive(:dump).with("hello").and_raise(StandardError)
48
+ YAML.should_receive(:dump).with("hello").and_raise(StandardError)
49
+
50
+ lambda { Nanite::Serializer.new.dump("hello") }.should raise_error(Nanite::Serializer::SerializationError)
51
+ end
52
+
53
+ it "should raise SerializationError if packet could not be serialized" do
54
+ JSON.should_receive(:dump).with("hello").and_raise(StandardError)
55
+ Marshal.should_receive(:dump).with("hello").and_raise(StandardError)
56
+ YAML.should_receive(:dump).with("hello").and_raise(StandardError)
57
+
58
+ serializer = Nanite::Serializer.new
59
+ lambda { serializer.dump("hello") }.should raise_error(Nanite::Serializer::SerializationError)
60
+ end
61
+
62
+ it "should return serialized packet" do
63
+ serialized_packet = mock("Packet")
64
+ Marshal.should_receive(:dump).with("hello").and_return(serialized_packet)
65
+
66
+ serializer = Nanite::Serializer.new(:marshal)
67
+ serializer.dump("hello").should == serialized_packet
68
+ end
69
+
70
+ end # Serialization of Packet
71
+
72
+ describe "De-Serialization of Packet" do
73
+
74
+ it "should cascade through available serializers" do
75
+ serializer = Nanite::Serializer.new
76
+ serializer.should_receive(:cascade_serializers).with(:load, "olleh")
77
+ serializer.load("olleh")
78
+ end
79
+
80
+ it "should try all three supported formats (JSON, Marshal, YAML)" do
81
+ JSON.should_receive(:load).with("olleh").and_raise(StandardError)
82
+ Marshal.should_receive(:load).with("olleh").and_raise(StandardError)
83
+ YAML.should_receive(:load).with("olleh").and_raise(StandardError)
84
+
85
+ lambda { Nanite::Serializer.new.load("olleh") }.should raise_error(Nanite::Serializer::SerializationError)
86
+ end
87
+
88
+ it "should raise SerializationError if packet could not be de-serialized" do
89
+ JSON.should_receive(:load).with("olleh").and_raise(StandardError)
90
+ Marshal.should_receive(:load).with("olleh").and_raise(StandardError)
91
+ YAML.should_receive(:load).with("olleh").and_raise(StandardError)
92
+
93
+ serializer = Nanite::Serializer.new
94
+ lambda { serializer.load("olleh") }.should raise_error(Nanite::Serializer::SerializationError)
95
+ end
96
+
97
+ it "should return de-serialized packet" do
98
+ deserialized_packet = mock("Packet")
99
+ Marshal.should_receive(:load).with("olleh").and_return(deserialized_packet)
100
+
101
+ serializer = Nanite::Serializer.new(:marshal)
102
+ serializer.load("olleh").should == deserialized_packet
103
+ end
104
+
105
+ end # De-Serialization of Packet
106
+
107
+ end # Nanite::Serializer
@@ -0,0 +1,30 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe Nanite::Signature do
4
+
5
+ include SpecHelpers
6
+
7
+ before(:all) do
8
+ @test_data = "Test Data"
9
+ @cert, @key = issue_cert
10
+ @sig = Nanite::Signature.new(@test_data, @cert, @key)
11
+ end
12
+
13
+ it 'should create signed data' do
14
+ @sig.to_s.should_not be_empty
15
+ end
16
+
17
+ it 'should verify the signature' do
18
+ cert2, key2 = issue_cert
19
+
20
+ @sig.should be_a_match(@cert)
21
+ @sig.should_not be_a_match(cert2)
22
+ end
23
+
24
+ it 'should load from serialized signature' do
25
+ sig2 = Nanite::Signature.from_data(@sig.data)
26
+ sig2.should_not be_nil
27
+ sig2.should be_a_match(@cert)
28
+ end
29
+
30
+ end
@@ -0,0 +1,33 @@
1
+ $TESTING=true
2
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
3
+
4
+ require 'rubygems'
5
+ require 'spec'
6
+ require 'nanite'
7
+
8
+ module SpecHelpers
9
+
10
+ # Initialize logger so it writes to file instead of STDOUT
11
+ Nanite::Log.init('test', File.join(File.dirname(__FILE__)))
12
+
13
+ # Create test certificate
14
+ def issue_cert
15
+ test_dn = { 'C' => 'US',
16
+ 'ST' => 'California',
17
+ 'L' => 'Santa Barbara',
18
+ 'O' => 'Nanite',
19
+ 'OU' => 'Certification Services',
20
+ 'CN' => 'Nanite test' }
21
+ dn = Nanite::DistinguishedName.new(test_dn)
22
+ key = Nanite::RsaKeyPair.new
23
+ [ Nanite::Certificate.new(key, dn, dn), key ]
24
+ end
25
+
26
+ def run_in_em(stop_event_loop = true)
27
+ EM.run do
28
+ yield
29
+ EM.stop_event_loop if stop_event_loop
30
+ end
31
+ end
32
+
33
+ end