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.
- data/Gemfile +4 -0
- data/bin/file_broadcaster.rb +56 -0
- data/bin/file_receiver.rb +62 -0
- data/bin/omf_keygen +21 -0
- data/bin/{monitor_topic.rb → omf_monitor_topic} +21 -8
- data/bin/omf_send_create +118 -0
- data/bin/{send_request.rb → omf_send_request} +12 -7
- data/example/engine_alt.rb +23 -24
- data/example/ls_app.yaml +21 -0
- data/lib/omf_common.rb +73 -12
- data/lib/omf_common/auth.rb +15 -0
- data/lib/omf_common/auth/certificate.rb +174 -0
- data/lib/omf_common/auth/certificate_store.rb +72 -0
- data/lib/omf_common/auth/ssh_pub_key_convert.rb +80 -0
- data/lib/omf_common/comm.rb +66 -9
- data/lib/omf_common/comm/amqp/amqp_communicator.rb +40 -13
- data/lib/omf_common/comm/amqp/amqp_file_transfer.rb +259 -0
- data/lib/omf_common/comm/amqp/amqp_topic.rb +14 -21
- data/lib/omf_common/comm/local/local_communicator.rb +31 -2
- data/lib/omf_common/comm/local/local_topic.rb +19 -3
- data/lib/omf_common/comm/topic.rb +48 -34
- data/lib/omf_common/comm/xmpp/communicator.rb +19 -10
- data/lib/omf_common/comm/xmpp/topic.rb +22 -81
- data/lib/omf_common/default_logging.rb +11 -0
- data/lib/omf_common/eventloop.rb +14 -0
- data/lib/omf_common/eventloop/em.rb +39 -6
- data/lib/omf_common/eventloop/local_evl.rb +15 -0
- data/lib/omf_common/exec_app.rb +29 -15
- data/lib/omf_common/message.rb +53 -5
- data/lib/omf_common/message/json/json_message.rb +149 -39
- data/lib/omf_common/message/xml/message.rb +112 -39
- data/lib/omf_common/protocol/6.0.rnc +5 -1
- data/lib/omf_common/protocol/6.0.rng +12 -0
- data/lib/omf_common/version.rb +1 -1
- data/omf_common.gemspec +7 -2
- data/test/fixture/omf_test.cert.pem +15 -0
- data/test/fixture/omf_test.pem +15 -0
- data/test/fixture/omf_test.pub +1 -0
- data/test/fixture/omf_test.pub.pem +6 -0
- data/test/omf_common/auth/certificate_spec.rb +113 -0
- data/test/omf_common/auth/ssh_pub_key_convert_spec.rb +13 -0
- data/test/omf_common/comm/topic_spec.rb +175 -0
- data/test/omf_common/comm/xmpp/communicator_spec.rb +15 -16
- data/test/omf_common/comm/xmpp/topic_spec.rb +63 -10
- data/test/omf_common/comm_spec.rb +66 -9
- data/test/omf_common/message/xml/message_spec.rb +43 -13
- data/test/omf_common/message_spec.rb +14 -0
- data/test/test_helper.rb +25 -0
- metadata +78 -15
- data/bin/send_create.rb +0 -94
@@ -37,5 +37,16 @@ module OmfCommon
|
|
37
37
|
def warn(*args, &block)
|
38
38
|
logger.warn(*args, &block)
|
39
39
|
end
|
40
|
+
|
41
|
+
# Log a warning message for deprecated methods
|
42
|
+
def warn_deprecation(deprecated_name, *suggest_names)
|
43
|
+
logger.warn "[DEPRECATION] '#{deprecated_name}' is deprecated. Please use '#{suggest_names.join(', ')}' instead."
|
44
|
+
end
|
45
|
+
|
46
|
+
def warn_removed(deprecated_name)
|
47
|
+
define_method(deprecated_name) do |*args, &block|
|
48
|
+
logger.warn "[DEPRECATION] '#{deprecated_name}' is deprecated and not supported. Please do not use it."
|
49
|
+
end
|
50
|
+
end
|
40
51
|
end
|
41
52
|
end
|
data/lib/omf_common/eventloop.rb
CHANGED
@@ -84,7 +84,21 @@ module OmfCommon
|
|
84
84
|
def on_stop(&block)
|
85
85
|
warn "Missing implementation 'on_stop'"
|
86
86
|
end
|
87
|
+
|
88
|
+
# Calling 'block' when having trapped an INT signal
|
89
|
+
#
|
90
|
+
def on_int_signal(&block)
|
91
|
+
# trap(:INT)
|
92
|
+
warn "Missing implementation 'on_int_signal'"
|
93
|
+
end
|
87
94
|
|
95
|
+
# Calling 'block' when having trapped a TERM signal
|
96
|
+
#
|
97
|
+
def on_term_signal(&block)
|
98
|
+
# trap(:TERM) {}
|
99
|
+
warn "Missing implementation 'on_term_signal'"
|
100
|
+
end
|
101
|
+
|
88
102
|
private
|
89
103
|
def initialize(opts = {}, &block)
|
90
104
|
#run(&block) if block
|
@@ -25,15 +25,43 @@ module OmfCommon
|
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
+
# Call 'block' in the context of a separate thread.
|
29
|
+
#
|
30
|
+
def defer(&block)
|
31
|
+
raise "Can't handle 'defer' registration before the EM is up" unless EM.reactor_running?
|
32
|
+
EM.defer do
|
33
|
+
begin
|
34
|
+
block.call()
|
35
|
+
rescue => ex
|
36
|
+
error "Exception '#{ex}'"
|
37
|
+
debug "#{ex}\n\t#{ex.backtrace.join("\n\t")}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
28
42
|
# Periodically call block every interval_sec
|
29
43
|
#
|
30
44
|
# @param [Float] interval in sec
|
31
45
|
def every(interval_sec, &block)
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
46
|
+
# to allow canceling the periodic timer we need to
|
47
|
+
# hand back a reference to it which responds to 'cancel'
|
48
|
+
# As this is getting rather complex when allowing for
|
49
|
+
# registration before the EM is up and running, we simply throw
|
50
|
+
# and exception at this time.
|
51
|
+
raise "Can't handle 'every' registration before the EM is up" unless EM.reactor_running?
|
52
|
+
# if EM.reactor_running?
|
53
|
+
# EM.add_periodic_timer(interval_sec, &block)
|
54
|
+
# else
|
55
|
+
# @deferred << lambda do
|
56
|
+
# EM.add_periodic_timer(interval_sec, &block)
|
57
|
+
# end
|
58
|
+
# end
|
59
|
+
EM.add_periodic_timer(interval_sec) do
|
60
|
+
begin
|
61
|
+
block.call()
|
62
|
+
rescue => ex
|
63
|
+
error "Exception '#{ex}'"
|
64
|
+
debug "#{ex}\n\t#{ex.backtrace.join("\n\t")}"
|
37
65
|
end
|
38
66
|
end
|
39
67
|
end
|
@@ -43,7 +71,12 @@ module OmfCommon
|
|
43
71
|
@deferred.each { |proc| proc.call }
|
44
72
|
@deferred = nil
|
45
73
|
if block
|
46
|
-
|
74
|
+
begin
|
75
|
+
block.arity == 0 ? block.call : block.call(self)
|
76
|
+
rescue => ex
|
77
|
+
error "While executing run block - #{ex}"
|
78
|
+
error ex.backtrace.join("\n\t")
|
79
|
+
end
|
47
80
|
end
|
48
81
|
end
|
49
82
|
end
|
@@ -31,6 +31,21 @@ module OmfCommon
|
|
31
31
|
@tasks << [Time.now + interval_sec, block, :periodic => interval_sec]
|
32
32
|
end
|
33
33
|
|
34
|
+
# Call 'block' in the context of a separate thread.
|
35
|
+
#
|
36
|
+
def defer(&block)
|
37
|
+
@logger.note("DEFER")
|
38
|
+
Thread.new do
|
39
|
+
begin
|
40
|
+
block.call()
|
41
|
+
rescue => ex
|
42
|
+
@logger.error "Exception '#{ex}'"
|
43
|
+
@logger.debug ex.backtract.join("\n\t")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
|
34
49
|
def stop
|
35
50
|
@running = false
|
36
51
|
end
|
data/lib/omf_common/exec_app.rb
CHANGED
@@ -32,7 +32,7 @@ require 'fcntl'
|
|
32
32
|
# Borrows from Open3
|
33
33
|
#
|
34
34
|
class ExecApp
|
35
|
-
|
35
|
+
|
36
36
|
# Holds the pids for all active apps
|
37
37
|
@@all_apps = Hash.new
|
38
38
|
|
@@ -69,25 +69,27 @@ class ExecApp
|
|
69
69
|
#
|
70
70
|
# Run an application 'cmd' in a separate thread and monitor
|
71
71
|
# its stdout. Also send status reports to the 'observer' by
|
72
|
-
# calling its "
|
72
|
+
# calling its "call(eventType, appId, message")"
|
73
73
|
#
|
74
74
|
# @param id ID of application (used for reporting)
|
75
75
|
# @param observer Observer of application's progress
|
76
76
|
# @param cmd Command path and args
|
77
77
|
# @param map_std_err_to_out If true report stderr as stdin [false]
|
78
78
|
#
|
79
|
-
def initialize(id,
|
79
|
+
def initialize(id, cmd, map_std_err_to_out = false, working_directory = nil, &observer)
|
80
80
|
|
81
81
|
@id = id
|
82
82
|
@observer = observer
|
83
83
|
@@all_apps[id] = self
|
84
|
+
@exit_status = nil
|
85
|
+
@threads = []
|
84
86
|
|
85
87
|
pw = IO::pipe # pipe[0] for read, pipe[1] for write
|
86
88
|
pr = IO::pipe
|
87
89
|
pe = IO::pipe
|
88
90
|
|
89
91
|
logger.debug "Starting application '#{id}' - cmd: '#{cmd}'"
|
90
|
-
@observer.
|
92
|
+
@observer.call(:STARTED, id, cmd)
|
91
93
|
@pid = fork {
|
92
94
|
# child will remap pipes to std and exec cmd
|
93
95
|
pw[1].close
|
@@ -103,6 +105,7 @@ class ExecApp
|
|
103
105
|
pe[1].close
|
104
106
|
|
105
107
|
begin
|
108
|
+
Dir.chdir working_directory if working_directory
|
106
109
|
exec(cmd)
|
107
110
|
rescue => ex
|
108
111
|
cmd = cmd.join(' ') if cmd.kind_of?(Array)
|
@@ -118,23 +121,31 @@ class ExecApp
|
|
118
121
|
monitor_pipe(:stdout, pr[0])
|
119
122
|
monitor_pipe(map_std_err_to_out ? :stdout : :stderr, pe[0])
|
120
123
|
# Create thread which waits for application to exit
|
121
|
-
Thread.new(id, @pid) do |id, pid|
|
124
|
+
@threads << Thread.new(id, @pid) do |id, pid|
|
122
125
|
ret = Process.waitpid(pid)
|
123
|
-
|
126
|
+
@exit_status = $?.exitstatus
|
124
127
|
@@all_apps.delete(@id)
|
125
128
|
# app finished
|
126
|
-
if (
|
127
|
-
s = "OK"
|
129
|
+
if (@exit_status == 0) || @clean_exit
|
128
130
|
logger.debug "Application '#{id}' finished"
|
129
131
|
else
|
130
|
-
|
131
|
-
logger.debug "Application '#{id}' failed (code=#{status})"
|
132
|
+
logger.debug "Application '#{id}' failed (code=#{@exit_status})"
|
132
133
|
end
|
133
|
-
@observer.on_app_event("DONE.#{s}", @id, "status: #{status}")
|
134
134
|
end
|
135
135
|
@stdin = pw[1]
|
136
|
+
|
137
|
+
# wait for done in yet another thread
|
138
|
+
Thread.new do
|
139
|
+
@threads.each {|t| t.join }
|
140
|
+
if (@exit_status == 0) || @clean_exit
|
141
|
+
s = "OK"
|
142
|
+
else
|
143
|
+
s = "ERROR"
|
144
|
+
end
|
145
|
+
@observer.call("DONE.#{s}", @id, "status: #{@exit_status}")
|
146
|
+
end
|
136
147
|
end
|
137
|
-
|
148
|
+
|
138
149
|
private
|
139
150
|
|
140
151
|
#
|
@@ -145,16 +156,19 @@ class ExecApp
|
|
145
156
|
# @param pipe Pipe to read from
|
146
157
|
#
|
147
158
|
def monitor_pipe(name, pipe)
|
148
|
-
Thread.new() do
|
159
|
+
@threads << Thread.new() do
|
149
160
|
begin
|
150
161
|
while true do
|
151
162
|
s = pipe.readline.chomp
|
152
|
-
|
163
|
+
#puts "#{name}: #{s}"
|
164
|
+
@observer.call(name.to_s.upcase, @id, s)
|
153
165
|
end
|
154
166
|
rescue EOFError
|
155
167
|
# do nothing
|
156
|
-
|
168
|
+
#puts "++++ STOP MONITORING #{name}"
|
169
|
+
rescue => err
|
157
170
|
logger.error "monitorApp(#{@id}): #{err}"
|
171
|
+
logger.debug "#{err}\n\t#{err.backtrace.join("\n\t")}"
|
158
172
|
ensure
|
159
173
|
pipe.close
|
160
174
|
end
|
data/lib/omf_common/message.rb
CHANGED
@@ -26,9 +26,10 @@ module OmfCommon
|
|
26
26
|
}
|
27
27
|
}
|
28
28
|
@@message_class = nil
|
29
|
+
@@authenticate_messages = false
|
29
30
|
|
30
31
|
def self.create(type, properties, body = {})
|
31
|
-
@@message_class.create(type, properties, body)
|
32
|
+
@@message_class.create(type, properties || {}, body)
|
32
33
|
end
|
33
34
|
|
34
35
|
def self.create_inform_message(itype = nil, properties = {}, body = {})
|
@@ -36,10 +37,19 @@ module OmfCommon
|
|
36
37
|
create(:inform, properties, body)
|
37
38
|
end
|
38
39
|
|
39
|
-
#
|
40
|
+
# Return true if all messages will be authenticated, return false otherwise
|
40
41
|
#
|
41
|
-
def self.
|
42
|
-
@@
|
42
|
+
def self.authenticate?
|
43
|
+
@@authenticate_messages
|
44
|
+
end
|
45
|
+
|
46
|
+
# Parse message from 'str' and pass it to 'block'.
|
47
|
+
# If authnetication is on, the message will only be handed
|
48
|
+
# to 'block' if the source of the message can be authenticated.
|
49
|
+
#
|
50
|
+
def self.parse(str, content_type = nil, &block)
|
51
|
+
raise ArgumentError, 'Need message handling block' unless block
|
52
|
+
@@message_class.parse(str, content_type, &block)
|
43
53
|
end
|
44
54
|
|
45
55
|
def self.init(opts = {})
|
@@ -60,6 +70,7 @@ module OmfCommon
|
|
60
70
|
else
|
61
71
|
raise "Missing provider class info - :constructor"
|
62
72
|
end
|
73
|
+
@@authenticate_messages = opts[:authenticate] if opts[:authenticate]
|
63
74
|
end
|
64
75
|
|
65
76
|
OMF_CORE_READ.each do |pname|
|
@@ -116,7 +127,15 @@ module OmfCommon
|
|
116
127
|
raise NotImplementedError
|
117
128
|
end
|
118
129
|
|
130
|
+
def properties
|
131
|
+
raise NotImplementedError
|
132
|
+
end
|
133
|
+
|
119
134
|
def has_properties?
|
135
|
+
not properties.empty?
|
136
|
+
end
|
137
|
+
|
138
|
+
def guard?
|
120
139
|
raise NotImplementedError
|
121
140
|
end
|
122
141
|
|
@@ -138,11 +157,32 @@ module OmfCommon
|
|
138
157
|
self.class.create_inform_message(itype, properties, body)
|
139
158
|
end
|
140
159
|
|
160
|
+
# Fetch inform type
|
161
|
+
#
|
162
|
+
# When no format provided, return the value as it is.
|
163
|
+
#
|
164
|
+
# @param [Symbol] format to render itype, valid formats: :ruby, :frcp
|
165
|
+
#
|
166
|
+
def itype(format = nil)
|
167
|
+
if format && !_get_core(:itype).nil?
|
168
|
+
case format.to_sym
|
169
|
+
when :ruby
|
170
|
+
_get_core(:itype).to_s.downcase.gsub(/\./, '_')
|
171
|
+
when :frcp
|
172
|
+
_get_core(:itype).to_s.upcase.gsub(/_/, '.')
|
173
|
+
else
|
174
|
+
raise ArgumentError, "Unknown format '#{format}'. Please use ':ruby, :frcp' instead."
|
175
|
+
end
|
176
|
+
else
|
177
|
+
_get_core(:itype)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
141
181
|
def to_s
|
142
182
|
raise NotImplementedError
|
143
183
|
end
|
144
184
|
|
145
|
-
def marshall
|
185
|
+
def marshall(include_cert = false)
|
146
186
|
raise NotImplementedError
|
147
187
|
end
|
148
188
|
|
@@ -171,6 +211,14 @@ module OmfCommon
|
|
171
211
|
def _set_property(name, value, ns = nil)
|
172
212
|
raise NotImplementedError
|
173
213
|
end
|
214
|
+
|
215
|
+
def _set_core(key, value)
|
216
|
+
raise NotImplementedError
|
217
|
+
end
|
218
|
+
|
219
|
+
def _get_core(key)
|
220
|
+
raise NotImplementedError
|
221
|
+
end
|
174
222
|
end
|
175
223
|
|
176
224
|
end
|
@@ -1,42 +1,107 @@
|
|
1
1
|
|
2
2
|
require 'json'
|
3
|
+
require 'omf_common/auth'
|
4
|
+
require 'json/jwt'
|
3
5
|
|
4
6
|
module OmfCommon
|
5
7
|
class Message
|
6
8
|
class Json
|
7
9
|
class Message < OmfCommon::Message
|
8
|
-
|
10
|
+
|
11
|
+
# This maps properties in the internal representation of
|
12
|
+
# a message to names used for the JSON message
|
13
|
+
#
|
14
|
+
@@key2json_key = {
|
15
|
+
operation: :op,
|
16
|
+
res_id: :rid
|
17
|
+
}
|
9
18
|
|
10
19
|
def self.create(type, properties, body = {})
|
11
|
-
if type == :request
|
20
|
+
if type == :request
|
12
21
|
unless properties.kind_of?(Array)
|
13
22
|
raise "Expected array, but got #{properties.class} for request message"
|
14
23
|
end
|
15
24
|
properties = {select: properties}
|
16
25
|
elsif not properties.kind_of?(Hash)
|
17
26
|
raise "Expected hash, but got #{properties.class}"
|
18
|
-
end
|
27
|
+
end
|
19
28
|
content = body.merge({
|
20
|
-
|
29
|
+
op: type,
|
21
30
|
mid: SecureRandom.uuid,
|
22
|
-
|
31
|
+
props: properties
|
23
32
|
})
|
24
33
|
self.new(content)
|
25
34
|
end
|
26
|
-
|
35
|
+
|
27
36
|
def self.create_inform_message(itype = nil, properties = {}, body = {})
|
28
37
|
body[:itype] = itype if itype
|
29
38
|
create(:inform, properties, body)
|
30
39
|
end
|
31
|
-
|
40
|
+
|
32
41
|
# Create and return a message by parsing 'str'
|
33
42
|
#
|
34
|
-
def self.parse(str)
|
35
|
-
|
36
|
-
|
37
|
-
|
43
|
+
def self.parse(str, content_type, &block)
|
44
|
+
#puts "CT>> #{content_type}"
|
45
|
+
case content_type.to_s
|
46
|
+
when 'jwt'
|
47
|
+
content = parse_jwt(str, &block)
|
48
|
+
when 'text/json'
|
49
|
+
content = JSON.parse(str, :symbolize_names => true)
|
50
|
+
else
|
51
|
+
warn "Received message with unknown content type '#{content_type}'"
|
52
|
+
end
|
53
|
+
#puts "CTTT>> #{content}::#{content.class}"
|
54
|
+
msg = content ? new(content) : nil
|
55
|
+
block.call(msg) if msg
|
56
|
+
msg
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.parse_jwt(jwt_string)
|
60
|
+
key_or_secret = :skip_verification
|
61
|
+
# Code lifted from 'json-jwt-0.4.3/lib/json/jwt.rb'
|
62
|
+
case jwt_string.count('.')
|
63
|
+
when 2 # JWT / JWS
|
64
|
+
header, claims, signature = jwt_string.split('.', 3).collect do |segment|
|
65
|
+
UrlSafeBase64.decode64 segment.to_s
|
66
|
+
end
|
67
|
+
header, claims = [header, claims].collect do |json|
|
68
|
+
#MultiJson.load(json).with_indifferent_access
|
69
|
+
JSON.parse(json, :symbolize_names => true)
|
70
|
+
end
|
71
|
+
signature_base_string = jwt_string.split('.')[0, 2].join('.')
|
72
|
+
jwt = JSON::JWT.new claims
|
73
|
+
jwt.header = header
|
74
|
+
jwt.signature = signature
|
75
|
+
|
76
|
+
# NOTE:
|
77
|
+
# Some JSON libraries generates wrong format of JSON (spaces between keys and values etc.)
|
78
|
+
# So we need to use raw base64 strings for signature verification.
|
79
|
+
unless src = claims[:iss]
|
80
|
+
warn "JWT: Message is missing :iss element"
|
81
|
+
return nil
|
82
|
+
end
|
83
|
+
if cert_pem = claims[:crt]
|
84
|
+
# let's the credential store take care of it
|
85
|
+
OmfCommon::Auth::CertificateStore.instance.register_x509(cert_pem, src)
|
86
|
+
end
|
87
|
+
unless cert = OmfCommon::Auth::CertificateStore.instance.cert_for(src)
|
88
|
+
warn "JWT: Can't find cert for issuer '#{src}'"
|
89
|
+
return nil
|
90
|
+
end
|
91
|
+
|
92
|
+
unless cert.verify_cert
|
93
|
+
warn "JWT: Invalid certificate '#{cert.to_s}', NOT signed by root certificate."
|
94
|
+
end
|
95
|
+
|
96
|
+
#puts ">>> #{cert.to_x509.public_key}::#{signature_base_string}"
|
97
|
+
jwt.verify signature_base_string, cert.to_x509.public_key #unless key_or_secret == :skip_verification
|
98
|
+
JSON.parse(claims[:cnt], :symbolize_names => true)
|
99
|
+
else
|
100
|
+
warn('JWT: Invalid Format. JWT should include 2 or 3 dots.')
|
101
|
+
return nil
|
102
|
+
end
|
38
103
|
end
|
39
|
-
|
104
|
+
|
40
105
|
def each_property(&block)
|
41
106
|
@properties.each do |k, v|
|
42
107
|
#unless INTERNAL_PROPS.include?(k.to_sym)
|
@@ -44,16 +109,21 @@ module OmfCommon
|
|
44
109
|
#end
|
45
110
|
end
|
46
111
|
end
|
47
|
-
|
112
|
+
|
113
|
+
def properties
|
114
|
+
@properties
|
115
|
+
end
|
116
|
+
|
117
|
+
|
48
118
|
def has_properties?
|
49
119
|
not @properties.empty?
|
50
120
|
end
|
51
|
-
|
121
|
+
|
52
122
|
def valid?
|
53
123
|
true # don't do schema verification , yet
|
54
124
|
end
|
55
|
-
|
56
|
-
# Loop over all the unbound (sent without a value) properties
|
125
|
+
|
126
|
+
# Loop over all the unbound (sent without a value) properties
|
57
127
|
# of a request message.
|
58
128
|
#
|
59
129
|
def each_unbound_request_property(&block)
|
@@ -66,9 +136,9 @@ module OmfCommon
|
|
66
136
|
block.call(el)
|
67
137
|
end
|
68
138
|
end
|
69
|
-
end
|
70
|
-
|
71
|
-
# Loop over all the bound (sent with a value) properties
|
139
|
+
end
|
140
|
+
|
141
|
+
# Loop over all the bound (sent with a value) properties
|
72
142
|
# of a request message.
|
73
143
|
#
|
74
144
|
def each_bound_request_property(&block)
|
@@ -83,47 +153,87 @@ module OmfCommon
|
|
83
153
|
end
|
84
154
|
end
|
85
155
|
end
|
86
|
-
end
|
87
|
-
|
88
|
-
|
156
|
+
end
|
157
|
+
|
158
|
+
|
89
159
|
def to_s
|
90
160
|
"JsonMessage: #{@content.inspect}"
|
91
161
|
end
|
92
|
-
|
93
|
-
|
94
|
-
|
162
|
+
|
163
|
+
# Marshall message into a string to be shipped across the network.
|
164
|
+
# Depending on authentication setting, the message will be signed as
|
165
|
+
# well, or maybe even dropped.
|
166
|
+
#
|
167
|
+
# @param [Topic] topic for which to marshall
|
168
|
+
#
|
169
|
+
def marshall(topic)
|
170
|
+
#puts "MARSHALL: #{@content.inspect} - #{@properties.to_hash.inspect}"
|
171
|
+
raise "Missing SRC declaration in #{@content}" unless @content[:src]
|
172
|
+
if @content[:src].is_a? OmfCommon::Comm::Topic
|
173
|
+
@content[:src] = @content[:src].id
|
174
|
+
end
|
175
|
+
#raise 'local/local' if @content[:src].id.match 'local:/local'
|
176
|
+
#puts @content.inspect
|
177
|
+
payload = @content.to_json
|
178
|
+
if self.class.authenticate?
|
179
|
+
src = @content[:src]
|
180
|
+
cert = OmfCommon::Auth::CertificateStore.instance.cert_for(src)
|
181
|
+
if cert && cert.can_sign?
|
182
|
+
debug "Found cert for '#{src} - #{cert}"
|
183
|
+
msg = {cnt: payload, iss: src}
|
184
|
+
unless @certOnTopic[k = [topic, src]]
|
185
|
+
# first time for this src on this topic, so let's send the cert along
|
186
|
+
msg[:crt] = cert.to_pem_compact
|
187
|
+
#ALWAYS ADD CERT @certOnTopic[k] = Time.now
|
188
|
+
end
|
189
|
+
#:RS256, :RS384, :RS512
|
190
|
+
p = JSON::JWT.new(msg).sign(cert.key , :RS256).to_s
|
191
|
+
#puts "SIGNED>> #{msg}"
|
192
|
+
return ['jwt', p]
|
193
|
+
end
|
194
|
+
end
|
195
|
+
['text/json', payload]
|
95
196
|
end
|
96
|
-
|
97
|
-
private
|
197
|
+
|
198
|
+
private
|
98
199
|
def initialize(content)
|
99
200
|
debug "Create message: #{content.inspect}"
|
100
|
-
|
101
|
-
unless op = content[:operation]
|
201
|
+
unless op = content[:op]
|
102
202
|
raise "Missing message type (:operation)"
|
103
203
|
end
|
104
|
-
content
|
105
|
-
|
204
|
+
@content = {}
|
205
|
+
content[:op] = op.to_sym # needs to be symbol
|
206
|
+
if src = content[:src]
|
207
|
+
content[:src] = OmfCommon.comm.create_topic(src)
|
208
|
+
end
|
209
|
+
content.each {|k,v| _set_core(k, v)}
|
210
|
+
@properties = content[:props] || []
|
106
211
|
#@properties = Hashie::Mash.new(content[:properties])
|
212
|
+
@authenticate = self.class.authenticate?
|
213
|
+
# keep track if we sent local certs on a topic. Should do this the first time
|
214
|
+
@certOnTopic = {}
|
107
215
|
end
|
108
|
-
|
216
|
+
|
109
217
|
def _set_core(key, value)
|
110
|
-
@content[key] = value
|
218
|
+
@content[(@@key2json_key[key] || key).to_sym] = value
|
111
219
|
end
|
112
220
|
|
113
221
|
def _get_core(key)
|
114
|
-
@content[key]
|
222
|
+
@content[@@key2json_key[key] || key]
|
115
223
|
end
|
116
|
-
|
117
|
-
def _set_property(key, value)
|
224
|
+
|
225
|
+
def _set_property(key, value, ns = nil)
|
226
|
+
warn "Can't handle namespaces yet" if ns
|
118
227
|
@properties[key] = value
|
119
228
|
end
|
120
229
|
|
121
|
-
def _get_property(key)
|
230
|
+
def _get_property(key, ns = nil)
|
231
|
+
warn "Can't handle namespaces yet" if ns
|
122
232
|
#puts key
|
123
233
|
@properties[key]
|
124
234
|
end
|
125
|
-
|
235
|
+
|
126
236
|
end # class
|
127
237
|
end
|
128
238
|
end
|
129
|
-
end
|
239
|
+
end
|