omf_common 6.0.7.1 → 6.0.8.pre.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|