omf_common 6.0.0 → 6.0.2.pre.1

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.
Files changed (50) hide show
  1. data/Gemfile +4 -0
  2. data/bin/file_broadcaster.rb +56 -0
  3. data/bin/file_receiver.rb +62 -0
  4. data/bin/omf_keygen +21 -0
  5. data/bin/{monitor_topic.rb → omf_monitor_topic} +21 -8
  6. data/bin/omf_send_create +118 -0
  7. data/bin/{send_request.rb → omf_send_request} +12 -7
  8. data/example/engine_alt.rb +23 -24
  9. data/example/ls_app.yaml +21 -0
  10. data/lib/omf_common.rb +73 -12
  11. data/lib/omf_common/auth.rb +15 -0
  12. data/lib/omf_common/auth/certificate.rb +174 -0
  13. data/lib/omf_common/auth/certificate_store.rb +72 -0
  14. data/lib/omf_common/auth/ssh_pub_key_convert.rb +80 -0
  15. data/lib/omf_common/comm.rb +66 -9
  16. data/lib/omf_common/comm/amqp/amqp_communicator.rb +40 -13
  17. data/lib/omf_common/comm/amqp/amqp_file_transfer.rb +259 -0
  18. data/lib/omf_common/comm/amqp/amqp_topic.rb +14 -21
  19. data/lib/omf_common/comm/local/local_communicator.rb +31 -2
  20. data/lib/omf_common/comm/local/local_topic.rb +19 -3
  21. data/lib/omf_common/comm/topic.rb +48 -34
  22. data/lib/omf_common/comm/xmpp/communicator.rb +19 -10
  23. data/lib/omf_common/comm/xmpp/topic.rb +22 -81
  24. data/lib/omf_common/default_logging.rb +11 -0
  25. data/lib/omf_common/eventloop.rb +14 -0
  26. data/lib/omf_common/eventloop/em.rb +39 -6
  27. data/lib/omf_common/eventloop/local_evl.rb +15 -0
  28. data/lib/omf_common/exec_app.rb +29 -15
  29. data/lib/omf_common/message.rb +53 -5
  30. data/lib/omf_common/message/json/json_message.rb +149 -39
  31. data/lib/omf_common/message/xml/message.rb +112 -39
  32. data/lib/omf_common/protocol/6.0.rnc +5 -1
  33. data/lib/omf_common/protocol/6.0.rng +12 -0
  34. data/lib/omf_common/version.rb +1 -1
  35. data/omf_common.gemspec +7 -2
  36. data/test/fixture/omf_test.cert.pem +15 -0
  37. data/test/fixture/omf_test.pem +15 -0
  38. data/test/fixture/omf_test.pub +1 -0
  39. data/test/fixture/omf_test.pub.pem +6 -0
  40. data/test/omf_common/auth/certificate_spec.rb +113 -0
  41. data/test/omf_common/auth/ssh_pub_key_convert_spec.rb +13 -0
  42. data/test/omf_common/comm/topic_spec.rb +175 -0
  43. data/test/omf_common/comm/xmpp/communicator_spec.rb +15 -16
  44. data/test/omf_common/comm/xmpp/topic_spec.rb +63 -10
  45. data/test/omf_common/comm_spec.rb +66 -9
  46. data/test/omf_common/message/xml/message_spec.rb +43 -13
  47. data/test/omf_common/message_spec.rb +14 -0
  48. data/test/test_helper.rb +25 -0
  49. metadata +78 -15
  50. data/bin/send_create.rb +0 -94
@@ -9,7 +9,6 @@ require 'omf_common/message/xml/relaxng_schema'
9
9
  module OmfCommon
10
10
  class Message
11
11
  class XML
12
-
13
12
  # @example To create a valid omf message, e.g. a 'create' message:
14
13
  #
15
14
  # Message.create(:create,
@@ -47,12 +46,46 @@ class XML
47
46
  new(content)
48
47
  end
49
48
 
50
- def parse(xml)
49
+ def parse(xml, content_type = "text/xml", &block)
50
+ raise ArgumentError, 'Need message handling block' unless block
51
+
52
+ content_type ||= "text/xml" # Since by default parent class pass in nil object
53
+ raise ArgumentError, "Unknown content type: #{content_type}" unless content_type =~ /xml/
51
54
  raise ArgumentError, 'Can not parse an empty XML into OMF message' if xml.nil? || xml.empty?
52
55
 
53
56
  xml_node = Nokogiri::XML(xml).root
54
57
 
55
- self.create(xml_node.name.to_sym).tap do |message|
58
+ if xml_node.name.to_sym == :env # envelope
59
+ cert = xml_node.element_children.find { |v| v.element_name == 'cert' }.content
60
+ sig = xml_node.element_children.find { |v| v.element_name == 'sig' }.content
61
+ iss = xml_node.element_children.find { |v| v.element_name == 'iss' }.content
62
+ xml_node = xml_node.element_children.find { |v| v.element_name =~ /create|request|configure|release|inform/ }
63
+
64
+ if self.authenticate?
65
+ existing_cert = OmfCommon::Auth::CertificateStore.instance.cert_for(iss)
66
+
67
+ if existing_cert
68
+ cert = existing_cert
69
+ else
70
+ OmfCommon::Auth::CertificateStore.instance.register_x509(cert, iss)
71
+ cert = OmfCommon::Auth::CertificateStore.instance.cert_for(iss)
72
+ end
73
+
74
+ unless cert.verify_cert
75
+ warn "Invalid certificate '#{cert.to_s}', NOT signed by root certificate."
76
+ return nil
77
+ end
78
+
79
+ canonicalised_xml_node = fix_canonicalised_xml(xml_node.canonicalize)
80
+
81
+ unless cert.to_x509.public_key.verify(OpenSSL::Digest::SHA256.new(canonicalised_xml_node), Base64.decode64(sig), canonicalised_xml_node)
82
+ warn "Verfication failed #{canonicalised_xml_node} #{OpenSSL::Digest::SHA256.new(canonicalised_xml_node)}"
83
+ return nil
84
+ end
85
+ end
86
+ end
87
+
88
+ parsed_msg = self.create(xml_node.name.to_sym).tap do |message|
56
89
  message.xml = xml_node
57
90
 
58
91
  message.send(:_set_core, :mid, message.xml.attr('mid'))
@@ -82,6 +115,8 @@ class XML
82
115
  MPMessage.inject(Time.now.to_f, message.operation.to_s, message.mid, message.cid, message.to_s.gsub("\n",''))
83
116
  end
84
117
  end
118
+ block.call(parsed_msg)
119
+ parsed_msg
85
120
  end
86
121
  end
87
122
 
@@ -90,17 +125,50 @@ class XML
90
125
  OmfCommon::Comm::XMPP::Topic.create(r_id)
91
126
  end
92
127
 
93
- def itype
94
- @content.itype.to_s.upcase.gsub(/_/, '.') unless @content.itype.nil?
95
- end
96
-
97
128
  def marshall
98
129
  build_xml
99
- @xml.to_xml
130
+
131
+ if self.class.authenticate?
132
+ src = @content[:src]
133
+ src = src.address if src.is_a?(OmfCommon::Comm::Topic)
134
+ cert = OmfCommon::Auth::CertificateStore.instance.cert_for(src)
135
+ if cert && cert.can_sign?
136
+ debug "Found cert for '#{src} - #{cert}"
137
+ signature_node = Niceogiri::XML::Node.new(:sig)
138
+
139
+ canonicalised_xml = self.class.fix_canonicalised_xml(@xml.canonicalize)
140
+
141
+ signature = Base64.encode64(cert.key.sign(OpenSSL::Digest::SHA256.new(canonicalised_xml), canonicalised_xml)).encode('utf-8')
142
+ signature_node.add_child(signature)
143
+
144
+ @envelope = Niceogiri::XML::Node.new(:env, nil, OMF_NAMESPACE)
145
+ @envelope.add_child(@xml)
146
+ @envelope.add_child(signature_node)
147
+
148
+ iss_node = Niceogiri::XML::Node.new(:iss)
149
+ iss_node.add_child(src)
150
+ @envelope.add_child(iss_node)
151
+
152
+ #unless @certOnTopic[k = [topic, src]]
153
+ # first time for this src on this topic, so let's send the cert along
154
+ cert_node = Niceogiri::XML::Node.new(:cert)
155
+ cert_node.add_child(cert.to_pem_compact)
156
+ @envelope.add_child(cert_node)
157
+ #ALWAYS ADD CERT @certOnTopic[k] = Time.now
158
+ #end
159
+ ['text/xml', @envelope]
160
+ else
161
+ error "Missing cert for #{src}"
162
+ ['text/xml', nil]
163
+ end
164
+ else
165
+ ['text/xml', @xml]
166
+ end
100
167
  end
101
168
 
102
- alias_method :to_xml, :marshall
103
- alias_method :to_s, :marshall
169
+ def to_s
170
+ @content
171
+ end
104
172
 
105
173
  def build_xml
106
174
  @xml = Niceogiri::XML::Node.new(self.operation.to_s, nil, OMF_NAMESPACE)
@@ -118,25 +186,30 @@ class XML
118
186
  @xml.add_child(guard_node) if _get_core(:guard)
119
187
 
120
188
  (OMF_CORE_READ - [:mid, :guard, :operation]).each do |attr|
121
- attr_value = self.send(attr)
189
+ attr_value = case attr
190
+ when :itype
191
+ self.itype(:frcp)
192
+ when :src
193
+ self.src.is_a?(OmfCommon::Comm::Topic) ? self.src.address : self.src
194
+ else
195
+ self.send(attr)
196
+ end
122
197
 
123
198
  next unless attr_value
124
199
 
125
200
  add_element(attr, attr_value) unless (self.operation != :release && attr == :res_id)
126
201
  end
127
202
 
128
- self.properties.each { |k, v| add_property(k, v) }
203
+ self.properties.each { |k, v| add_property(k, v) unless k == 'certificate'}
129
204
  self.guard.each { |k, v| add_property(k, v, :guard) } if _get_core(:guard)
130
205
 
131
- #digest = OpenSSL::Digest::SHA512.new(@xml.canonicalize)
132
-
133
- #add_element(:digest, digest)
134
206
  @xml
135
207
  end
136
208
 
137
209
  # Construct a property xml node
138
210
  #
139
211
  def add_property(key, value = nil, add_to = :props)
212
+ key = escape_key(key)
140
213
  if !default_props_ns.empty? && add_to == :props
141
214
  key_node = Niceogiri::XML::Node.new(key, nil, default_props_ns)
142
215
  else
@@ -162,6 +235,7 @@ class XML
162
235
  when Hash
163
236
  [].tap do |array|
164
237
  value.each_pair do |k, v|
238
+ k = escape_key(k)
165
239
  n = Niceogiri::XML::Node.new(k, nil, OMF_NAMESPACE)
166
240
  n.write_attr('type', ruby_type_2_prop_type(v.class))
167
241
 
@@ -191,33 +265,13 @@ class XML
191
265
  if key.nil?
192
266
  string_value(value)
193
267
  else
268
+ key = escape_key(key)
194
269
  n = Niceogiri::XML::Node.new(key, nil, OMF_NAMESPACE)
195
270
  n.add_child(string_value(value))
196
271
  end
197
272
  end
198
273
  end
199
274
 
200
- # Generate SHA1 of canonicalised xml and write into the ID attribute of the message
201
- #
202
- def sign
203
- write_attr('mid', SecureRandom.uuid)
204
- write_attr('ts', Time.now.utc.to_i)
205
- canonical_msg = self.canonicalize
206
-
207
- #priv_key = OmfCommon::Key.instance.private_key
208
- #digest = OpenSSL::Digest::SHA512.new(canonical_msg)
209
-
210
- #signature = Base64.encode64(priv_key.sign(digest, canonical_msg)).encode('utf-8') if priv_key
211
- #write_attr('digest', digest)
212
- #write_attr('signature', signature) if signature
213
-
214
- if OmfCommon::Measure.enabled?
215
- MPMessage.inject(Time.now.to_f, operation.to_s, mid, cid, self.to_s.gsub("\n",''))
216
- @@mid_list << mid
217
- end
218
- self
219
- end
220
-
221
275
  # Validate against relaxng schema
222
276
  #
223
277
  def valid?
@@ -236,6 +290,7 @@ class XML
236
290
  # Short cut for adding xml node
237
291
  #
238
292
  def add_element(key, value = nil, &block)
293
+ key = escape_key(key)
239
294
  key_node = Niceogiri::XML::Node.new(key)
240
295
  @xml.add_child(key_node)
241
296
  if block
@@ -310,7 +365,7 @@ class XML
310
365
  end
311
366
 
312
367
  def has_properties?
313
- @content.properties.empty?
368
+ !@content.properties.empty?
314
369
  end
315
370
 
316
371
  def guard?
@@ -350,9 +405,8 @@ class XML
350
405
  # end
351
406
  #end
352
407
 
353
- alias_method :read_property, :[]
354
-
355
408
  alias_method :write_property, :[]=
409
+ alias_method :read_property, :[]
356
410
 
357
411
  private
358
412
 
@@ -360,6 +414,11 @@ class XML
360
414
  @content = content
361
415
  @content.mid = SecureRandom.uuid
362
416
  @content.ts = Time.now.utc.to_i
417
+ if (src = content[:src])
418
+ @content.src = OmfCommon.comm.create_topic(src)
419
+ end
420
+ # keep track if we sent local certs on a topic. Should do this the first time
421
+ @certOnTopic = {}
363
422
  end
364
423
 
365
424
  def _set_core(key, value)
@@ -394,6 +453,16 @@ class XML
394
453
  end
395
454
  end
396
455
 
456
+ def escape_key(key)
457
+ key = key.to_s
458
+ if key =~ /\W+/
459
+ warn "Due to the limitation of XML messages, please only use word character (a-z A-Z 0-9 _) in your property names. Offending characters will be replaced with underscore(_)."
460
+ key = key.gsub(/\W+/, '_')
461
+ else
462
+ key
463
+ end
464
+ end
465
+
397
466
  # Get string of a value object, escape if object is string
398
467
  def string_value(value)
399
468
  if value.kind_of? String
@@ -403,6 +472,10 @@ class XML
403
472
  end
404
473
  value
405
474
  end
475
+
476
+ def self.fix_canonicalised_xml(str)
477
+ str.gsub(/\n +/, '').gsub(/ xmlns=\"\"/, '')
478
+ end
406
479
  end
407
480
  end
408
481
  end
@@ -1,6 +1,6 @@
1
1
  default namespace = "http://schema.mytestbed.net/omf/6.0/protocol"
2
2
 
3
- start = (create | configure | request | release | inform)
3
+ start = (create | configure | request | release | inform | env)
4
4
 
5
5
  common_elements = attribute mid { text }?
6
6
  & element ts { text }
@@ -36,3 +36,7 @@ inform = element inform {
36
36
  & element cid { text }?
37
37
  & element itype { "CREATION.OK" | "CREATION.FAILED" | "STATUS" | "RELEASED" | "ERROR" | "WARN" }
38
38
  }
39
+
40
+ env = element env {
41
+ create | configure | request | release | inform
42
+ }
@@ -7,6 +7,7 @@
7
7
  <ref name="request"/>
8
8
  <ref name="release"/>
9
9
  <ref name="inform"/>
10
+ <ref name="env"/>
10
11
  </choice>
11
12
  </start>
12
13
  <define name="common_elements">
@@ -125,4 +126,15 @@
125
126
  </interleave>
126
127
  </element>
127
128
  </define>
129
+ <define name="env">
130
+ <element name="env">
131
+ <choice>
132
+ <ref name="create"/>
133
+ <ref name="configure"/>
134
+ <ref name="request"/>
135
+ <ref name="release"/>
136
+ <ref name="inform"/>
137
+ </choice>
138
+ </element>
139
+ </define>
128
140
  </grammar>
@@ -1,4 +1,4 @@
1
1
  module OmfCommon
2
- VERSION = "6.0.0"
2
+ VERSION = "6.0.2.pre.1"
3
3
  PROTOCOL_VERSION = "6.0"
4
4
  end
data/omf_common.gemspec CHANGED
@@ -17,16 +17,21 @@ Gem::Specification.new do |s|
17
17
 
18
18
  s.files = `git ls-files`.split("\n")
19
19
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.executables = ["omf_monitor_topic","omf_send_request", "omf_send_create"]
21
21
  s.require_paths = ["lib"]
22
22
 
23
23
  # specify any dependencies here; for example:
24
24
  s.add_development_dependency "minitest", "~> 3.2"
25
25
  s.add_development_dependency "em-minitest-spec", "~> 1.1.1"
26
26
  s.add_development_dependency "simplecov"
27
+ s.add_development_dependency "pry"
28
+ s.add_development_dependency "mocha"
29
+
27
30
  s.add_runtime_dependency "eventmachine", "~> 0.12.10"
28
31
  s.add_runtime_dependency "blather", "= 0.8.1"
29
32
  s.add_runtime_dependency "logging", "~> 1.7.1"
30
33
  s.add_runtime_dependency "hashie", "~> 1.2.0"
31
- s.add_runtime_dependency "oml4r", "~> 2.8.0"
34
+ s.add_runtime_dependency "oml4r", "~> 2.9.1"
35
+ #s.add_runtime_dependency "json-jwt", "~> 0.5.2"
36
+ #s.add_runtime_dependency "amqp", "~> 1.0.1"
32
37
  end
@@ -0,0 +1,15 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIICWDCCAcGgAwIBAgIJAIZg2YXVVvPIMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
3
+ BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
4
+ aWRnaXRzIFB0eSBMdGQwHhcNMTMwNDIzMDQyOTE5WhcNMjMwNDIxMDQyOTE5WjBF
5
+ MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
6
+ ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
7
+ gQC24IfY2Kat2C35gw+X1fM8NI7CJ5DvT19BoDjQviXy8RhBl4fCTNVBvYYzgZXC
8
+ zVcTi4nAgJFbxvHMBeORmSWih5s3E/zllPWVmRstxGqscqoshjSnnU32p6HBXHEB
9
+ 0zuZsO/8Ff2+L0Q1QX9XhFntrJsyeiOk2fstz5AXovL6iQIDAQABo1AwTjAdBgNV
10
+ HQ4EFgQUeXgde/SzFMMdPj0Sv7nGKlE0LoEwHwYDVR0jBBgwFoAUeXgde/SzFMMd
11
+ Pj0Sv7nGKlE0LoEwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAgLs56
12
+ W7MpT9gc+/QGPt1FEIHqGGGwS/FuxQJEJnrnI0MpCf+2dqAlOwTKQDh+QB8558YO
13
+ cdGqgrFKPJSVvIaqow9OStOqn+PpyhBgfrDMkKMCdmN3yW4JeytAM+z5pV44YtTw
14
+ GBlr4kQzF0y3V1oo1+Ck1F1n+CARt2knmi3zAQ==
15
+ -----END CERTIFICATE-----
@@ -0,0 +1,15 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIICXQIBAAKBgQC24IfY2Kat2C35gw+X1fM8NI7CJ5DvT19BoDjQviXy8RhBl4fC
3
+ TNVBvYYzgZXCzVcTi4nAgJFbxvHMBeORmSWih5s3E/zllPWVmRstxGqscqoshjSn
4
+ nU32p6HBXHEB0zuZsO/8Ff2+L0Q1QX9XhFntrJsyeiOk2fstz5AXovL6iQIDAQAB
5
+ AoGBALJb/mJBux6mTwChEJ43rskzQWCfEj40nWT2DTOZoI13Ev81+NRJ91vsqmyl
6
+ oBikCJ8pYqp7OknWmJEx1Sd1xDs/jsb6AUfNsfJALtE54Cq2iEWBU3Q4BTuT1meE
7
+ Fyvqww9YoFZIaYHvyDWYTH2B8eYrswSt4nCpKmr9eb/cBplhAkEA42Fl+aYUv2A6
8
+ 7EGFe+1OT9ctLZeEGPBIWuWIma6vj4+iM6Zn1rmsoqx3qsrjsIVUxpmmH5RvrJOY
9
+ Vq0WvqDwxQJBAM3lJ3lzs5fLEjzk/obiU6PJFq6BCFUTVtbjaRe8uN450fBEm+0M
10
+ pOacio2jDhA21ayHE+yAfZ2h0V+WXSvHNvUCQDV2JBTjoMMybAg6i5kMvbn1/NBY
11
+ bJ20eT6t80U3Fl4pxlhgis+ozlddN7G3jHtnjfw4CiAotW0dMtdGUS+3BYUCQD3a
12
+ YYly4LjxIIF6qZwL0eSaPF4gFUi5jpTvrFqdL0xTQmZTtiP4cHF3BYiXO1pTns09
13
+ pxadYx8/xY5ZtZO5PSECQQCwGIGrXQnT6FVpuJFRIl1m0rglbXEHy1x8xRYaQNJX
14
+ 7cUKcQaIXoroQ43TQnkIcIK7Q11EFomrJBTTL7icpgfU
15
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1 @@
1
+ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC24IfY2Kat2C35gw+X1fM8NI7CJ5DvT19BoDjQviXy8RhBl4fCTNVBvYYzgZXCzVcTi4nAgJFbxvHMBeORmSWih5s3E/zllPWVmRstxGqscqoshjSnnU32p6HBXHEB0zuZsO/8Ff2+L0Q1QX9XhFntrJsyeiOk2fstz5AXovL6iQ==
@@ -0,0 +1,6 @@
1
+ -----BEGIN PUBLIC KEY-----
2
+ MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC24IfY2Kat2C35gw+X1fM8NI7C
3
+ J5DvT19BoDjQviXy8RhBl4fCTNVBvYYzgZXCzVcTi4nAgJFbxvHMBeORmSWih5s3
4
+ E/zllPWVmRstxGqscqoshjSnnU32p6HBXHEB0zuZsO/8Ff2+L0Q1QX9XhFntrJsy
5
+ eiOk2fstz5AXovL6iQIDAQAB
6
+ -----END PUBLIC KEY-----
@@ -0,0 +1,113 @@
1
+ require 'test_helper'
2
+
3
+ describe OmfCommon::Auth::Certificate do
4
+ before do
5
+ OmfCommon::Auth::CertificateStore.init
6
+
7
+ @root = OmfCommon::Auth::Certificate.create(nil, 'omf_ca', 'ca', 'omf')
8
+
9
+ OmfCommon::Auth::CertificateStore.instance.register(@root)
10
+ end
11
+
12
+ after do
13
+ OmfCommon::Auth::CertificateStore.reset
14
+ end
15
+
16
+ it "must create a self-signed root CA cert" do
17
+ @root.must_be_kind_of OmfCommon::Auth::Certificate
18
+ @root.address.must_be_nil
19
+ @root.subject.must_be_kind_of OpenSSL::X509::Name
20
+ @root.subject.to_s(OpenSSL::X509::Name::RFC2253).must_equal "CN=frcp//omf//frcp.ca.omf_ca"
21
+ @root.key.must_be_kind_of OpenSSL::PKey::RSA
22
+ @root.digest.must_be_kind_of OpenSSL::Digest::SHA1
23
+
24
+ cert = @root.to_x509
25
+ cert.must_be_kind_of OpenSSL::X509::Certificate
26
+
27
+ # It is self signed
28
+ cert.issuer.must_equal @root.subject
29
+ cert.verify(cert.public_key).must_equal true
30
+ end
31
+
32
+ it "must create an end-entity cert using root cert" do
33
+ lambda { @root.create_for }.must_raise ArgumentError
34
+
35
+ @entity = @root.create_for('my_addr', 'bob', 'my_resource', 'omf')
36
+ cert = @entity.to_x509
37
+
38
+ cert.issuer.must_equal @root.subject
39
+ cert.issuer.wont_equal cert.subject
40
+
41
+ cert.issuer.to_s(OpenSSL::X509::Name::RFC2253).must_equal "CN=frcp//omf//frcp.ca.omf_ca"
42
+ cert.subject.to_s(OpenSSL::X509::Name::RFC2253).must_equal "CN=frcp//omf//frcp.my_resource.bob"
43
+
44
+ cert.verify(@root.to_x509.public_key).must_equal true
45
+
46
+ @entity.verify_cert.must_equal true
47
+ end
48
+
49
+ it "must verify cert validity" do
50
+ @root.verify_cert.must_equal true
51
+ @root.create_for('my_addr', 'bob', 'my_resource', 'omf').verify_cert.must_equal true
52
+ end
53
+
54
+ describe "when init from an exisitng cert in pem format" do
55
+ before do
56
+ @private_folder = "#{File.dirname(__FILE__)}/../../fixture"
57
+ @cert = OmfCommon::Auth::Certificate.create_from_x509(File.read("#{@private_folder}/omf_test.cert.pem"))
58
+ @key = OpenSSL::PKey::RSA.new(File.read("#{@private_folder}/omf_test.pem"))
59
+ @pub_key = OpenSSL::PKey::RSA.new(File.read("#{@private_folder}/omf_test.pub.pem"))
60
+ end
61
+
62
+ it "must verify itself" do
63
+ # It is a self signed cert
64
+ @cert.subject.to_s(OpenSSL::X509::Name::RFC2253).must_equal "O=Internet Widgits Pty Ltd,ST=Some-State,C=AU"
65
+ @cert.to_x509.issuer.to_s(OpenSSL::X509::Name::RFC2253).must_equal "O=Internet Widgits Pty Ltd,ST=Some-State,C=AU"
66
+ @cert.verify_cert.must_equal true
67
+ end
68
+
69
+ it "must not have pirivate key initialised" do
70
+ @cert.can_sign?.must_equal false
71
+ end
72
+
73
+ it "must have a correct public key" do
74
+ @pub_key.public?.must_equal true
75
+ @pub_key.private?.must_equal false
76
+ @cert.to_x509.public_key.to_s.must_equal @pub_key.to_s
77
+ end
78
+
79
+ it "must have a correct private key associated" do
80
+ @key.public?.must_equal true
81
+ @key.private?.must_equal true
82
+ @cert.to_x509.check_private_key(@key).must_equal true
83
+ end
84
+ end
85
+
86
+ describe "when provided an existing public key" do
87
+ it "must generate a cert contains a converted public key" do
88
+ private_folder = "#{File.dirname(__FILE__)}/../../fixture"
89
+ pub_key = OpenSSL::PKey::RSA.new(File.read("#{private_folder}/omf_test.pub.pem"))
90
+
91
+ test_entity = @root.create_for('my_addr', 'bob', 'my_resource', 'omf', 365, pub_key)
92
+ test_entity.to_x509.public_key.to_s.must_equal pub_key.to_s
93
+ test_entity.can_sign?.must_equal false
94
+ test_entity.verify_cert.must_equal true
95
+ end
96
+ end
97
+
98
+ describe "when provided an existing public cert and I have a private key associated" do
99
+ it "must attach the private key into instance so it could sign messages" do
100
+ private_folder = "#{File.dirname(__FILE__)}/../../fixture"
101
+ key = OpenSSL::PKey::RSA.new(File.read("#{private_folder}/omf_test.pem"))
102
+ pub_key = OpenSSL::PKey::RSA.new(File.read("#{private_folder}/omf_test.pub.pem"))
103
+
104
+ x509_cert = @root.create_for('my_addr', 'bob', 'my_resource', 'omf', 365, pub_key).to_x509.to_s
105
+
106
+ # Now create an instance using this cert
107
+ test_entity = OmfCommon::Auth::Certificate.create_from_x509(x509_cert, key)
108
+ test_entity.to_x509.public_key.to_s.must_equal pub_key.to_s
109
+ test_entity.can_sign?.must_equal true
110
+ test_entity.to_x509.check_private_key(key).must_equal true
111
+ end
112
+ end
113
+ end