omf_common 6.0.7.1 → 6.0.8.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.
- checksums.yaml +14 -6
- data/bin/omf_cert.rb +175 -0
- data/example/auth_test.rb +76 -0
- data/lib/omf_common.rb +12 -1
- data/lib/omf_common/auth/certificate.rb +255 -72
- data/lib/omf_common/auth/certificate_store.rb +39 -15
- data/lib/omf_common/auth/jwt_authenticator.rb +69 -0
- data/lib/omf_common/auth/pdp/test_pdp.rb +21 -0
- data/lib/omf_common/comm.rb +8 -1
- data/lib/omf_common/comm/amqp/amqp_communicator.rb +7 -1
- data/lib/omf_common/comm/amqp/amqp_mp.rb +29 -0
- data/lib/omf_common/comm/amqp/amqp_topic.rb +4 -2
- data/lib/omf_common/comm/local/local_topic.rb +14 -14
- data/lib/omf_common/comm/xmpp/communicator.rb +14 -6
- data/lib/omf_common/comm/xmpp/xmpp_mp.rb +2 -2
- data/lib/omf_common/message.rb +27 -6
- data/lib/omf_common/message/json/json_message.rb +36 -21
- data/lib/omf_common/message/xml/message.rb +27 -21
- data/lib/omf_common/version.rb +8 -1
- data/omf_common.gemspec +4 -3
- data/test/fixture/alice-cert.pem +26 -0
- data/test/fixture/alice-key.pem +15 -0
- data/test/omf_common/auth/certificate_spec.rb +20 -41
- data/test/omf_common/auth/certificate_store_spec.rb +19 -21
- data/test/omf_common/comm/xmpp/communicator_spec.rb +4 -1
- data/test/omf_common/message/xml/message_spec.rb +2 -2
- metadata +66 -39
data/lib/omf_common/message.rb
CHANGED
@@ -32,6 +32,7 @@ module OmfCommon
|
|
32
32
|
}
|
33
33
|
@@message_class = nil
|
34
34
|
@@authenticate_messages = false
|
35
|
+
@@authorisation_hook = nil
|
35
36
|
|
36
37
|
def self.create(type, properties, body = {})
|
37
38
|
@@message_class.create(type, properties || {}, body)
|
@@ -49,15 +50,23 @@ module OmfCommon
|
|
49
50
|
end
|
50
51
|
|
51
52
|
# Parse message from 'str' and pass it to 'block'.
|
52
|
-
# If
|
53
|
-
# to 'block' if the source of the message can be
|
53
|
+
# If authentication is on, the message will only be handed
|
54
|
+
# to 'block' if the source of the message can be authorized.
|
54
55
|
#
|
55
56
|
def self.parse(str, content_type = nil, &block)
|
56
57
|
raise ArgumentError, 'Need message handling block' unless block
|
57
|
-
@@message_class.parse(str, content_type
|
58
|
+
@@message_class.parse(str, content_type) do |msg|
|
59
|
+
if @@authorisation_hook
|
60
|
+
# Hook will return message if it's authorized. Handing in
|
61
|
+
# dispatch block in case hook needs more time for authorization.
|
62
|
+
msg = @@authorisation_hook.authorize(msg, &block)
|
63
|
+
end
|
64
|
+
block.call(msg) if msg
|
65
|
+
end
|
58
66
|
end
|
59
67
|
|
60
68
|
def self.init(opts = {})
|
69
|
+
puts opts.inspect
|
61
70
|
if @@message_class
|
62
71
|
raise "Message provider already iniitalised"
|
63
72
|
end
|
@@ -75,9 +84,21 @@ module OmfCommon
|
|
75
84
|
else
|
76
85
|
raise "Missing provider class info - :constructor"
|
77
86
|
end
|
78
|
-
|
87
|
+
aopts = opts[:authenticate] || {}
|
88
|
+
@@authenticate_messages = opts[:authenticate] && !(aopts[:authenticate] == false)
|
89
|
+
if pdp_opts = (opts[:authenticate] || {})[:pdp]
|
90
|
+
require pdp_opts.delete(:require) if pdp_opts[:require]
|
91
|
+
unless pdp_constructor = pdp_opts.delete(:constructor)
|
92
|
+
raise "Missing PDP provider declaration."
|
93
|
+
end
|
94
|
+
|
95
|
+
pdp_class = pdp_constructor.split('::').inject(Object) {|c,n| c.const_get(n) }
|
96
|
+
@@authorisation_hook = pdp_class.new(pdp_opts)
|
97
|
+
end
|
79
98
|
end
|
80
99
|
|
100
|
+
attr_reader :issuer
|
101
|
+
|
81
102
|
OMF_CORE_READ.each do |pname|
|
82
103
|
define_method(pname.to_s) do |*args|
|
83
104
|
_get_core(pname)
|
@@ -109,7 +130,7 @@ module OmfCommon
|
|
109
130
|
#raise if name.to_sym == :itype
|
110
131
|
if ns
|
111
132
|
@props_ns ||= {}
|
112
|
-
@props_ns.merge(ns)
|
133
|
+
@props_ns.merge!(ns)
|
113
134
|
end
|
114
135
|
_set_property(name.to_sym, value, ns)
|
115
136
|
end
|
@@ -204,7 +225,7 @@ module OmfCommon
|
|
204
225
|
# Get all property namespace defs
|
205
226
|
def props_ns
|
206
227
|
@props_ns ||= {}
|
207
|
-
default_props_ns.merge(@props_ns)
|
228
|
+
default_props_ns.merge(@props_ns).stringify_keys
|
208
229
|
end
|
209
230
|
|
210
231
|
private
|
@@ -29,7 +29,7 @@ module OmfCommon
|
|
29
29
|
#properties = {select: properties}
|
30
30
|
properties = {}
|
31
31
|
req_props.each {|n| properties[n] = nil }
|
32
|
-
|
32
|
+
|
33
33
|
elsif not properties.kind_of?(Hash)
|
34
34
|
raise "Expected hash, but got #{properties.class}"
|
35
35
|
end
|
@@ -38,7 +38,8 @@ module OmfCommon
|
|
38
38
|
mid: SecureRandom.uuid,
|
39
39
|
props: properties
|
40
40
|
})
|
41
|
-
self.
|
41
|
+
issuer = self.authenticate? ? (body[:issuer] || body[:src]) : nil
|
42
|
+
self.new(content, issuer)
|
42
43
|
end
|
43
44
|
|
44
45
|
def self.create_inform_message(itype = nil, properties = {}, body = {})
|
@@ -46,22 +47,25 @@ module OmfCommon
|
|
46
47
|
create(:inform, properties, body)
|
47
48
|
end
|
48
49
|
|
49
|
-
# Create and
|
50
|
+
# Create and authenticate, if necessary a message and pass it
|
51
|
+
# on to 'block' if parsing (and authentication) is successful.
|
50
52
|
#
|
51
53
|
def self.parse(str, content_type, &block)
|
52
54
|
#puts "CT>> #{content_type}"
|
55
|
+
issuer = nil
|
53
56
|
case content_type.to_s
|
54
57
|
when 'jwt'
|
55
|
-
content = parse_jwt(str, &block)
|
58
|
+
content, issuer = parse_jwt(str, &block)
|
56
59
|
when 'text/json'
|
57
60
|
content = JSON.parse(str, :symbolize_names => true)
|
58
61
|
else
|
59
62
|
warn "Received message with unknown content type '#{content_type}'"
|
60
63
|
end
|
61
64
|
#puts "CTTT>> #{content}::#{content.class}"
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
+
if (content)
|
66
|
+
msg = new(content, issuer)
|
67
|
+
block.call(msg)
|
68
|
+
end
|
65
69
|
end
|
66
70
|
|
67
71
|
def self.parse_jwt(jwt_string)
|
@@ -84,16 +88,17 @@ module OmfCommon
|
|
84
88
|
# NOTE:
|
85
89
|
# Some JSON libraries generates wrong format of JSON (spaces between keys and values etc.)
|
86
90
|
# So we need to use raw base64 strings for signature verification.
|
87
|
-
unless
|
91
|
+
unless issuer = claims[:iss]
|
88
92
|
warn "JWT: Message is missing :iss element"
|
89
93
|
return nil
|
90
94
|
end
|
91
|
-
if
|
95
|
+
if ceat_pem = claims[:crt]
|
92
96
|
# let's the credential store take care of it
|
93
|
-
OmfCommon::Auth::
|
97
|
+
pem = "#{OmfCommon::Auth::Certificate::BEGIN_CERT}#{cert_pem}#{OmfCommon::Auth::Certificate::END_CERT}"
|
98
|
+
OmfCommon::Auth::CertificateStore.instance.register_x509(pem)
|
94
99
|
end
|
95
|
-
unless cert = OmfCommon::Auth::CertificateStore.instance.cert_for(
|
96
|
-
warn "JWT: Can't find cert for issuer '#{
|
100
|
+
unless cert = OmfCommon::Auth::CertificateStore.instance.cert_for(issuer)
|
101
|
+
warn "JWT: Can't find cert for issuer '#{issuer}'"
|
97
102
|
return nil
|
98
103
|
end
|
99
104
|
|
@@ -103,7 +108,7 @@ module OmfCommon
|
|
103
108
|
|
104
109
|
#puts ">>> #{cert.to_x509.public_key}::#{signature_base_string}"
|
105
110
|
jwt.verify signature_base_string, cert.to_x509.public_key #unless key_or_secret == :skip_verification
|
106
|
-
JSON.parse(claims[:cnt], :symbolize_names => true)
|
111
|
+
[JSON.parse(claims[:cnt], :symbolize_names => true), cert]
|
107
112
|
else
|
108
113
|
warn('JWT: Invalid Format. JWT should include 2 or 3 dots.')
|
109
114
|
return nil
|
@@ -180,17 +185,26 @@ module OmfCommon
|
|
180
185
|
if @content[:src].is_a? OmfCommon::Comm::Topic
|
181
186
|
@content[:src] = @content[:src].address
|
182
187
|
end
|
188
|
+
@content[:itype] = self.itype(:frcp)
|
189
|
+
|
183
190
|
#raise 'local/local' if @content[:src].id.match 'local:/local'
|
184
191
|
#puts @content.inspect
|
185
192
|
payload = @content.to_json
|
186
193
|
if self.class.authenticate?
|
187
|
-
|
188
|
-
|
194
|
+
unless issuer = self.issuer
|
195
|
+
raise "Missing ISSUER for '#{self}'"
|
196
|
+
end
|
197
|
+
if issuer.is_a? OmfCommon::Auth::CertificateStore
|
198
|
+
cert = issuer
|
199
|
+
issuer = cert.subject
|
200
|
+
else
|
201
|
+
cert = OmfCommon::Auth::CertificateStore.instance.cert_for(issuer)
|
202
|
+
end
|
189
203
|
if cert && cert.can_sign?
|
190
|
-
debug "Found cert for '#{
|
191
|
-
msg = {cnt: payload, iss:
|
192
|
-
unless @certOnTopic[k = [topic,
|
193
|
-
# first time for this
|
204
|
+
debug "Found cert for '#{issuer} - #{cert}"
|
205
|
+
msg = {cnt: payload, iss: issuer}
|
206
|
+
unless @certOnTopic[k = [topic, issuer]]
|
207
|
+
# first time for this issuer on this topic, so let's send the cert along
|
194
208
|
msg[:crt] = cert.to_pem_compact
|
195
209
|
#ALWAYS ADD CERT @certOnTopic[k] = Time.now
|
196
210
|
end
|
@@ -204,12 +218,13 @@ module OmfCommon
|
|
204
218
|
end
|
205
219
|
|
206
220
|
private
|
207
|
-
def initialize(content)
|
221
|
+
def initialize(content, issuer = nil)
|
208
222
|
debug "Create message: #{content.inspect}"
|
209
223
|
unless op = content[:op]
|
210
224
|
raise "Missing message type (:operation)"
|
211
225
|
end
|
212
226
|
@content = {}
|
227
|
+
@issuer = issuer
|
213
228
|
content[:op] = op.to_sym # needs to be symbol
|
214
229
|
if src = content[:src]
|
215
230
|
content[:src] = OmfCommon.comm.create_topic(src)
|
@@ -244,4 +259,4 @@ module OmfCommon
|
|
244
259
|
end # class
|
245
260
|
end
|
246
261
|
end
|
247
|
-
end
|
262
|
+
end
|
@@ -48,7 +48,9 @@ class XML
|
|
48
48
|
properties: properties
|
49
49
|
})
|
50
50
|
|
51
|
-
|
51
|
+
issuer = self.authenticate? ? (core_elements[:issuer] || core_elements[:src]) : nil
|
52
|
+
|
53
|
+
new(content, issuer)
|
52
54
|
end
|
53
55
|
|
54
56
|
def parse(xml, content_type = "text/xml", &block)
|
@@ -67,14 +69,10 @@ class XML
|
|
67
69
|
xml_node = xml_node.element_children.find { |v| v.element_name =~ /create|request|configure|release|inform/ }
|
68
70
|
|
69
71
|
if self.authenticate?
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
else
|
75
|
-
OmfCommon::Auth::CertificateStore.instance.register_x509(cert, iss)
|
76
|
-
cert = OmfCommon::Auth::CertificateStore.instance.cert_for(iss)
|
77
|
-
end
|
72
|
+
pem = "#{OmfCommon::Auth::Certificate::BEGIN_CERT}#{cert}#{OmfCommon::Auth::Certificate::END_CERT}"
|
73
|
+
cert = OmfCommon::Auth::Certificate.create_from_pem(pem)
|
74
|
+
cert.resource_id = iss
|
75
|
+
OmfCommon::Auth::CertificateStore.instance.register(cert)
|
78
76
|
|
79
77
|
if cert.nil?
|
80
78
|
warn "Missing certificate of '#{iss}'"
|
@@ -100,7 +98,7 @@ class XML
|
|
100
98
|
end
|
101
99
|
end
|
102
100
|
|
103
|
-
parsed_msg = self.create(xml_node.name.to_sym).tap do |message|
|
101
|
+
parsed_msg = self.create(xml_node.name.to_sym, {}, { issuer: cert }).tap do |message|
|
104
102
|
message.xml = xml_node
|
105
103
|
|
106
104
|
message.send(:_set_core, :mid, message.xml.attr('mid'))
|
@@ -112,9 +110,13 @@ class XML
|
|
112
110
|
|
113
111
|
if el.name == 'props'
|
114
112
|
message.read_element('props').first.element_children.each do |prop_node|
|
115
|
-
|
116
|
-
|
117
|
-
|
113
|
+
e_name = prop_node.element_name
|
114
|
+
|
115
|
+
if (ns_prefix = prop_node.namespace.prefix)
|
116
|
+
e_name = "#{ns_prefix}__#{e_name}"
|
117
|
+
end
|
118
|
+
|
119
|
+
message.send(:_set_property, e_name, message.reconstruct_data(prop_node))
|
118
120
|
end
|
119
121
|
end
|
120
122
|
|
@@ -126,8 +128,9 @@ class XML
|
|
126
128
|
end
|
127
129
|
end
|
128
130
|
|
129
|
-
if OmfCommon::Measure.enabled?
|
130
|
-
MPMessage.inject(Time.now.to_f, message.operation.to_s,
|
131
|
+
if OmfCommon::Measure.enabled?
|
132
|
+
MPMessage.inject(Time.now.to_f, message.content.operation.to_s,
|
133
|
+
message.content.mid, message.content.cid, message.content.to_s.gsub("\n",''))
|
131
134
|
end
|
132
135
|
end
|
133
136
|
block.call(parsed_msg)
|
@@ -145,8 +148,9 @@ class XML
|
|
145
148
|
|
146
149
|
if self.class.authenticate?
|
147
150
|
src = @content[:src]
|
151
|
+
issuer = @content[:issuer]
|
148
152
|
src = src.address if src.is_a?(OmfCommon::Comm::Topic)
|
149
|
-
cert = OmfCommon::Auth::CertificateStore.instance.cert_for(
|
153
|
+
cert = OmfCommon::Auth::CertificateStore.instance.cert_for(issuer)
|
150
154
|
if cert && cert.can_sign?
|
151
155
|
debug "Found cert for '#{src} - #{cert}"
|
152
156
|
signature_node = Niceogiri::XML::Node.new(:sig)
|
@@ -161,7 +165,7 @@ class XML
|
|
161
165
|
@envelope.add_child(signature_node)
|
162
166
|
|
163
167
|
iss_node = Niceogiri::XML::Node.new(:iss)
|
164
|
-
iss_node.add_child(
|
168
|
+
iss_node.add_child(issuer)
|
165
169
|
@envelope.add_child(iss_node)
|
166
170
|
|
167
171
|
#unless @certOnTopic[k = [topic, src]]
|
@@ -194,7 +198,7 @@ class XML
|
|
194
198
|
guard_node = Niceogiri::XML::Node.new(:guard)
|
195
199
|
|
196
200
|
props_ns.each do |k, v|
|
197
|
-
props_node.add_namespace_definition(k
|
201
|
+
props_node.add_namespace_definition(k, v.to_s)
|
198
202
|
end
|
199
203
|
|
200
204
|
@xml.add_child(props_node)
|
@@ -225,8 +229,8 @@ class XML
|
|
225
229
|
#
|
226
230
|
def add_property(key, value = nil, add_to = :props)
|
227
231
|
key = escape_key(key)
|
228
|
-
if !
|
229
|
-
key_node = Niceogiri::XML::Node.new(
|
232
|
+
if !props_ns.empty? && add_to == :props && key =~ /^(.+)__(.+)$/
|
233
|
+
key_node = Niceogiri::XML::Node.new($2, nil, { $1 => props_ns[$1] })
|
230
234
|
else
|
231
235
|
key_node = Niceogiri::XML::Node.new(key)
|
232
236
|
end
|
@@ -425,13 +429,15 @@ class XML
|
|
425
429
|
|
426
430
|
private
|
427
431
|
|
428
|
-
def initialize(content = {})
|
432
|
+
def initialize(content = {}, issuer = nil)
|
429
433
|
@content = content
|
430
434
|
@content.mid = SecureRandom.uuid
|
431
435
|
@content.ts = Time.now.utc.to_i
|
432
436
|
if (src = content[:src])
|
433
437
|
@content.src = OmfCommon.comm.create_topic(src)
|
434
438
|
end
|
439
|
+
@issuer = issuer
|
440
|
+
@content.issuer = @issuer
|
435
441
|
# keep track if we sent local certs on a topic. Should do this the first time
|
436
442
|
@certOnTopic = {}
|
437
443
|
end
|
data/lib/omf_common/version.rb
CHANGED
@@ -4,6 +4,13 @@
|
|
4
4
|
# By downloading or using this software you accept the terms and the liability disclaimer in the License.
|
5
5
|
|
6
6
|
module OmfCommon
|
7
|
-
VERSION = "6.0.7.1"
|
8
7
|
PROTOCOL_VERSION = "6.0"
|
8
|
+
|
9
|
+
def self.version_of(name)
|
10
|
+
git_tag = `git describe --tags 2> /dev/null`
|
11
|
+
gem_v = Gem.loaded_specs[name].version.to_s rescue '0.0.0'
|
12
|
+
git_tag.empty? ? gem_v : git_tag.gsub(/-/, '.')
|
13
|
+
end
|
14
|
+
|
15
|
+
VERSION = version_of('omf_common')
|
9
16
|
end
|
data/omf_common.gemspec
CHANGED
@@ -21,7 +21,7 @@ Gem::Specification.new do |s|
|
|
21
21
|
s.require_paths = ["lib"]
|
22
22
|
|
23
23
|
# specify any dependencies here; for example:
|
24
|
-
s.add_development_dependency "minitest"
|
24
|
+
s.add_development_dependency "minitest"
|
25
25
|
s.add_development_dependency "em-minitest-spec", "~> 1.1.1"
|
26
26
|
s.add_development_dependency "simplecov"
|
27
27
|
s.add_development_dependency "pry"
|
@@ -33,6 +33,7 @@ Gem::Specification.new do |s|
|
|
33
33
|
s.add_runtime_dependency "hashie", "~> 1.2.0"
|
34
34
|
s.add_runtime_dependency "oml4r", "~> 2.9.5"
|
35
35
|
s.add_runtime_dependency "json", "~> 1.7.7"
|
36
|
-
|
37
|
-
|
36
|
+
s.add_runtime_dependency "json-jwt"
|
37
|
+
s.add_runtime_dependency "amqp"
|
38
|
+
s.add_runtime_dependency "uuidtools"
|
38
39
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIIB9zCCAWCgAwIBAgIBAzANBgkqhkiG9w0BAQQFADAmMSQwIgYDVQQDExtnZW5p
|
3
|
+
Ly9ncG8vL2djZi5hdXRob3JpdHkuc2EwHhcNMTEwNzI5MTYzODA5WhcNMTYwNzI3
|
4
|
+
MTYzODA5WjAkMSIwIAYDVQQDExlnZW5pLy9ncG8vL2djZi51c2VyLmFsaWNlMIGf
|
5
|
+
MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCYrkSvNd4wX8cNiSiaIl+nyryUWQLG
|
6
|
+
ktYvUedceefKqgYCDWqSPKeb7930NMYYIvw+P2Wumqh2dXiPuqsZSJ8cL0qIBQ5F
|
7
|
+
o9Ohc1sMltAbia0f0HB+nyZD32KOZYGZJk8EfJXANjxPXSppvvTUhZQr6Z61ieQx
|
8
|
+
UGGz/s8IPGILgwIDAQABozcwNTAzBgNVHREELDAqhih1cm46cHVibGljaWQ6SURO
|
9
|
+
K2dlbmk6Z3BvOmdjZit1c2VyK2FsaWNlMA0GCSqGSIb3DQEBBAUAA4GBAE1zoAWQ
|
10
|
+
ml19QdtB0qHXFTupZ2TMUFk/5edEwaB4fg++7qSIMI/4MVCRgcnhBi8yC3NMoBRe
|
11
|
+
w7GRXgUKlcWyB+B7vPvvqPu3xJq0D81jFc89pP/dnRqjXNVfd4GK/E2S3O6OYQys
|
12
|
+
JPknFdP40Xd8fikSS4X5L/YmCz6TBe1zDpC5
|
13
|
+
-----END CERTIFICATE-----
|
14
|
+
-----BEGIN CERTIFICATE-----
|
15
|
+
MIIB+zCCAWSgAwIBAgIBAzANBgkqhkiG9w0BAQQFADAmMSQwIgYDVQQDExtnZW5p
|
16
|
+
Ly9ncG8vL2djZi5hdXRob3JpdHkuc2EwHhcNMTEwNzI5MTYzODA5WhcNMTYwNzI3
|
17
|
+
MTYzODA5WjAmMSQwIgYDVQQDExtnZW5pLy9ncG8vL2djZi5hdXRob3JpdHkuc2Ew
|
18
|
+
gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANTDGRrP7EBZT377Jm+xAbdZPhEz
|
19
|
+
vJKGv/4a8ebUOxSw9TDd8IeQbNa9TCUWqnmRk/ZnC6tJ+2+OE84AhPSBtPDb/m4c
|
20
|
+
Ca/wS3f39Fh1SL9K5z0R67MLjymRxpDGsRyPPNwNAD/DmdDA3GnuAggzScuha6G1
|
21
|
+
baqzArmA3IA/it5PAgMBAAGjOTA3MDUGA1UdEQQuMCyGKnVybjpwdWJsaWNpZDpJ
|
22
|
+
RE4rZ2VuaTpncG86Z2NmK2F1dGhvcml0eStzYTANBgkqhkiG9w0BAQQFAAOBgQCc
|
23
|
+
cECf2ybDu3kjuMzkqDcbkjAU1dKoRro0FXmYl5Z/BiYWGlMu4qU5Hq+P2GgKBGg6
|
24
|
+
7FjqL3DwyFUvvxAS4xlS+vJI2WFJNbgoBsCRyalzrMM5hOV/U78/OMpvunO/j1Ug
|
25
|
+
bpSLcxQPHkWLU6VE73Pc1vc7LpJ8OUSbbF89WysG2A==
|
26
|
+
-----END CERTIFICATE-----
|
@@ -0,0 +1,15 @@
|
|
1
|
+
-----BEGIN RSA PRIVATE KEY-----
|
2
|
+
MIICXQIBAAKBgQCYrkSvNd4wX8cNiSiaIl+nyryUWQLGktYvUedceefKqgYCDWqS
|
3
|
+
PKeb7930NMYYIvw+P2Wumqh2dXiPuqsZSJ8cL0qIBQ5Fo9Ohc1sMltAbia0f0HB+
|
4
|
+
nyZD32KOZYGZJk8EfJXANjxPXSppvvTUhZQr6Z61ieQxUGGz/s8IPGILgwIDAQAB
|
5
|
+
AoGAP+Td9XzTiObsBCwcA7TS1wMuu94sHTGh1Jev/LE/YT6Z2Q4IRT6A3e8ZsXLM
|
6
|
+
W5l4egxJ3zH1we0TEQMLSz9q5dkjqnl81w5pQdnGonZkFkkBmLQheak+U2BuVrte
|
7
|
+
umSF4NlEgF8wBRwAvMc6AJpANqB0HhKWWMVSh9GVNOAxo6ECQQDGEriUC0iUPaql
|
8
|
+
LqyctVCcsrCiDdxI1DnI0EpqfizbmaGlQvOlNqHwudHF7fzJ4pNZqD9YOwKywnoH
|
9
|
+
vHZeKBbrAkEAxVUfkv6dcr/fSsyVxRADwsUjgIGIRPV+iOF2/EAiijdJbDXKrxMd
|
10
|
+
rTO1acbUjqOkd3G0puUFNlYN40/RDC7nyQJAMJPc0uolhb3OAS7+RHyvZY7phQUT
|
11
|
+
NoVeGqMC7TU+uSjnnQlbifRpKQnZqcphSf4Yl0+NIY1vbvoFRapx+UupuwJBAKJp
|
12
|
+
LAJ8orOV7b6PYVj+lEnSnSSf97rh3pHkF10HoCXn2PtBzp6Hei5aV55Gch0v3CYe
|
13
|
+
pJOT/NU6wFVtFN4VINkCQQCkR8dAc6jSP80mERrVrMKDQGrtCPeX6tMdGme2+rWG
|
14
|
+
KghGKBTOmCecjh3lBh0f2bPUdMp4LtE+Y9zVMFhJ1Pkj
|
15
|
+
-----END RSA PRIVATE KEY-----
|
@@ -9,7 +9,7 @@ describe OmfCommon::Auth::Certificate do
|
|
9
9
|
before do
|
10
10
|
OmfCommon::Auth::CertificateStore.init
|
11
11
|
|
12
|
-
@root = OmfCommon::Auth::Certificate.
|
12
|
+
@root = OmfCommon::Auth::Certificate.create_root
|
13
13
|
|
14
14
|
OmfCommon::Auth::CertificateStore.instance.register(@root)
|
15
15
|
end
|
@@ -20,9 +20,12 @@ describe OmfCommon::Auth::Certificate do
|
|
20
20
|
|
21
21
|
it "must create a self-signed root CA cert" do
|
22
22
|
@root.must_be_kind_of OmfCommon::Auth::Certificate
|
23
|
-
|
23
|
+
|
24
|
+
@root.addresses.must_be_kind_of Hash
|
25
|
+
@root.addresses.must_equal({ email: "sa@acme.org", geni: "acme.org+authority+sa" })
|
26
|
+
|
24
27
|
@root.subject.must_be_kind_of OpenSSL::X509::Name
|
25
|
-
@root.subject.to_s(OpenSSL::X509::Name::RFC2253).must_equal "CN=
|
28
|
+
@root.subject.to_s(OpenSSL::X509::Name::RFC2253).must_equal "CN=sa,OU=Roadrunner,O=ACME,ST=CA,C=US"
|
26
29
|
@root.key.must_be_kind_of OpenSSL::PKey::RSA
|
27
30
|
@root.digest.must_be_kind_of OpenSSL::Digest::SHA1
|
28
31
|
|
@@ -35,16 +38,16 @@ describe OmfCommon::Auth::Certificate do
|
|
35
38
|
end
|
36
39
|
|
37
40
|
it "must create an end-entity cert using root cert" do
|
38
|
-
lambda { @root.
|
41
|
+
lambda { @root.create_for_resource }.must_raise ArgumentError
|
39
42
|
|
40
|
-
@entity = @root.
|
43
|
+
@entity = @root.create_for_resource('my_addr', 'my_resource')
|
41
44
|
cert = @entity.to_x509
|
42
45
|
|
43
46
|
cert.issuer.must_equal @root.subject
|
44
47
|
cert.issuer.wont_equal cert.subject
|
45
48
|
|
46
|
-
cert.issuer.to_s(OpenSSL::X509::Name::RFC2253).must_equal "CN=
|
47
|
-
cert.subject.to_s(OpenSSL::X509::Name::RFC2253).
|
49
|
+
cert.issuer.to_s(OpenSSL::X509::Name::RFC2253).must_equal "CN=sa,OU=Roadrunner,O=ACME,ST=CA,C=US"
|
50
|
+
cert.subject.to_s(OpenSSL::X509::Name::RFC2253).must_match /CN=my_addr\/type=my_resource\/uuid=.+,OU=Roadrunner,O=ACME,ST=CA,C=US/
|
48
51
|
|
49
52
|
cert.verify(@root.to_x509.public_key).must_equal true
|
50
53
|
|
@@ -55,7 +58,7 @@ describe OmfCommon::Auth::Certificate do
|
|
55
58
|
store = OpenSSL::X509::Store.new
|
56
59
|
store.add_cert(@root.to_x509)
|
57
60
|
|
58
|
-
@entity = @root.
|
61
|
+
@entity = @root.create_for_resource('my_addr', 'my_resource')
|
59
62
|
|
60
63
|
store.verify(@root.to_x509).must_equal true
|
61
64
|
store.verify(@entity.to_x509).must_equal true
|
@@ -63,13 +66,13 @@ describe OmfCommon::Auth::Certificate do
|
|
63
66
|
|
64
67
|
it "must verify cert validity" do
|
65
68
|
@root.verify_cert.must_equal true
|
66
|
-
@root.
|
69
|
+
@root.create_for_resource('my_addr', :my_resource).verify_cert.must_equal true
|
67
70
|
end
|
68
71
|
|
69
72
|
describe "when init from an exisitng cert in pem format" do
|
70
73
|
before do
|
71
74
|
@private_folder = "#{File.dirname(__FILE__)}/../../fixture"
|
72
|
-
@cert = OmfCommon::Auth::Certificate.
|
75
|
+
@cert = OmfCommon::Auth::Certificate.create_from_pem(File.read("#{@private_folder}/omf_test.cert.pem"))
|
73
76
|
@key = OpenSSL::PKey::RSA.new(File.read("#{@private_folder}/omf_test.pem"))
|
74
77
|
@pub_key = OpenSSL::PKey::RSA.new(File.read("#{@private_folder}/omf_test.pub.pem"))
|
75
78
|
end
|
@@ -98,43 +101,19 @@ describe OmfCommon::Auth::Certificate do
|
|
98
101
|
end
|
99
102
|
end
|
100
103
|
|
101
|
-
describe "when provided an existing
|
102
|
-
it "must
|
103
|
-
private_folder = "#{File.dirname(__FILE__)}/../../fixture"
|
104
|
-
pub_key = OpenSSL::PKey::RSA.new(File.read("#{private_folder}/omf_test.pub.pem"))
|
105
|
-
|
106
|
-
test_entity = @root.create_for('my_addr', 'bob', 'my_resource', 'omf', 365, pub_key)
|
107
|
-
test_entity.to_x509.public_key.to_s.must_equal pub_key.to_s
|
108
|
-
test_entity.can_sign?.must_equal false
|
109
|
-
test_entity.verify_cert.must_equal true
|
110
|
-
end
|
111
|
-
|
112
|
-
it "must generate a cert from SSH key too" do
|
113
|
-
private_folder = "#{File.dirname(__FILE__)}/../../fixture"
|
114
|
-
ssh_pub_key = File.read("#{private_folder}/omf_test.pub")
|
115
|
-
pub_key = OpenSSL::PKey::RSA.new(File.read("#{private_folder}/omf_test.pub.pem"))
|
116
|
-
lambda do
|
117
|
-
test_entity = @root.create_for('my_addr', 'bob', 'my_resource', 'omf', 365, 'bob')
|
118
|
-
end.must_raise ArgumentError
|
119
|
-
|
120
|
-
test_entity = @root.create_for('my_addr', 'bob', 'my_resource', 'omf', 365, ssh_pub_key)
|
121
|
-
test_entity.to_x509.public_key.to_s.must_equal pub_key.to_s
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
describe "when provided an existing public cert and I have a private key associated" do
|
126
|
-
it "must attach the private key into instance so it could sign messages" do
|
104
|
+
describe "when provided an existing cert with a private key attached" do
|
105
|
+
it "must parse it into a Certificate instance correctly" do
|
127
106
|
private_folder = "#{File.dirname(__FILE__)}/../../fixture"
|
128
|
-
key = OpenSSL::PKey::RSA.new(File.read("#{private_folder}/omf_test.pem"))
|
129
|
-
pub_key = OpenSSL::PKey::RSA.new(File.read("#{private_folder}/omf_test.pub.pem"))
|
130
107
|
|
131
|
-
x509_cert =
|
108
|
+
x509_cert = File.read("#{private_folder}/omf_test.cert.pem")
|
109
|
+
priv_key = File.read("#{private_folder}/omf_test.pem")
|
110
|
+
pub_key = File.read("#{private_folder}/omf_test.pub.pem")
|
132
111
|
|
133
112
|
# Now create an instance using this cert
|
134
|
-
test_entity = OmfCommon::Auth::Certificate.
|
113
|
+
test_entity = OmfCommon::Auth::Certificate.create_from_pem(x509_cert + priv_key)
|
135
114
|
test_entity.to_x509.public_key.to_s.must_equal pub_key.to_s
|
136
115
|
test_entity.can_sign?.must_equal true
|
137
|
-
test_entity.to_x509.check_private_key(
|
116
|
+
test_entity.to_x509.check_private_key(OpenSSL::PKey::RSA.new(priv_key)).must_equal true
|
138
117
|
end
|
139
118
|
end
|
140
119
|
end
|