right_agent 0.5.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 (147) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +78 -0
  3. data/Rakefile +86 -0
  4. data/lib/right_agent.rb +66 -0
  5. data/lib/right_agent/actor.rb +163 -0
  6. data/lib/right_agent/actor_registry.rb +76 -0
  7. data/lib/right_agent/actors/agent_manager.rb +189 -0
  8. data/lib/right_agent/agent.rb +735 -0
  9. data/lib/right_agent/agent_config.rb +403 -0
  10. data/lib/right_agent/agent_identity.rb +209 -0
  11. data/lib/right_agent/agent_tags_manager.rb +213 -0
  12. data/lib/right_agent/audit_formatter.rb +107 -0
  13. data/lib/right_agent/broker_client.rb +683 -0
  14. data/lib/right_agent/command.rb +30 -0
  15. data/lib/right_agent/command/agent_manager_commands.rb +134 -0
  16. data/lib/right_agent/command/command_client.rb +136 -0
  17. data/lib/right_agent/command/command_constants.rb +42 -0
  18. data/lib/right_agent/command/command_io.rb +128 -0
  19. data/lib/right_agent/command/command_parser.rb +87 -0
  20. data/lib/right_agent/command/command_runner.rb +105 -0
  21. data/lib/right_agent/command/command_serializer.rb +63 -0
  22. data/lib/right_agent/console.rb +65 -0
  23. data/lib/right_agent/core_payload_types.rb +42 -0
  24. data/lib/right_agent/core_payload_types/cookbook.rb +61 -0
  25. data/lib/right_agent/core_payload_types/cookbook_position.rb +46 -0
  26. data/lib/right_agent/core_payload_types/cookbook_repository.rb +116 -0
  27. data/lib/right_agent/core_payload_types/cookbook_sequence.rb +70 -0
  28. data/lib/right_agent/core_payload_types/dev_repositories.rb +90 -0
  29. data/lib/right_agent/core_payload_types/event_categories.rb +38 -0
  30. data/lib/right_agent/core_payload_types/executable_bundle.rb +138 -0
  31. data/lib/right_agent/core_payload_types/login_policy.rb +72 -0
  32. data/lib/right_agent/core_payload_types/login_user.rb +62 -0
  33. data/lib/right_agent/core_payload_types/planned_volume.rb +94 -0
  34. data/lib/right_agent/core_payload_types/recipe_instantiation.rb +60 -0
  35. data/lib/right_agent/core_payload_types/repositories_bundle.rb +50 -0
  36. data/lib/right_agent/core_payload_types/right_script_attachment.rb +95 -0
  37. data/lib/right_agent/core_payload_types/right_script_instantiation.rb +73 -0
  38. data/lib/right_agent/core_payload_types/secure_document.rb +66 -0
  39. data/lib/right_agent/core_payload_types/secure_document_location.rb +63 -0
  40. data/lib/right_agent/core_payload_types/software_repository_instantiation.rb +61 -0
  41. data/lib/right_agent/daemonize.rb +35 -0
  42. data/lib/right_agent/dispatcher.rb +348 -0
  43. data/lib/right_agent/enrollment_result.rb +217 -0
  44. data/lib/right_agent/exceptions.rb +30 -0
  45. data/lib/right_agent/ha_broker_client.rb +1278 -0
  46. data/lib/right_agent/idempotent_request.rb +140 -0
  47. data/lib/right_agent/log.rb +418 -0
  48. data/lib/right_agent/monkey_patches.rb +29 -0
  49. data/lib/right_agent/monkey_patches/amqp_patch.rb +274 -0
  50. data/lib/right_agent/monkey_patches/ruby_patch.rb +49 -0
  51. data/lib/right_agent/monkey_patches/ruby_patch/array_patch.rb +29 -0
  52. data/lib/right_agent/monkey_patches/ruby_patch/darwin_patch.rb +24 -0
  53. data/lib/right_agent/monkey_patches/ruby_patch/linux_patch.rb +24 -0
  54. data/lib/right_agent/monkey_patches/ruby_patch/linux_patch/file_patch.rb +30 -0
  55. data/lib/right_agent/monkey_patches/ruby_patch/object_patch.rb +49 -0
  56. data/lib/right_agent/monkey_patches/ruby_patch/singleton_patch.rb +46 -0
  57. data/lib/right_agent/monkey_patches/ruby_patch/string_patch.rb +107 -0
  58. data/lib/right_agent/monkey_patches/ruby_patch/windows_patch.rb +32 -0
  59. data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/file_patch.rb +90 -0
  60. data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/process_patch.rb +63 -0
  61. data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/stdio_patch.rb +27 -0
  62. data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/time_patch.rb +55 -0
  63. data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/win32ole_patch.rb +34 -0
  64. data/lib/right_agent/multiplexer.rb +91 -0
  65. data/lib/right_agent/operation_result.rb +270 -0
  66. data/lib/right_agent/packets.rb +637 -0
  67. data/lib/right_agent/payload_formatter.rb +104 -0
  68. data/lib/right_agent/pid_file.rb +159 -0
  69. data/lib/right_agent/platform.rb +319 -0
  70. data/lib/right_agent/platform/darwin.rb +227 -0
  71. data/lib/right_agent/platform/linux.rb +268 -0
  72. data/lib/right_agent/platform/windows.rb +1204 -0
  73. data/lib/right_agent/scripts/agent_controller.rb +522 -0
  74. data/lib/right_agent/scripts/agent_deployer.rb +379 -0
  75. data/lib/right_agent/scripts/common_parser.rb +153 -0
  76. data/lib/right_agent/scripts/log_level_manager.rb +193 -0
  77. data/lib/right_agent/scripts/stats_manager.rb +256 -0
  78. data/lib/right_agent/scripts/usage.rb +58 -0
  79. data/lib/right_agent/secure_identity.rb +92 -0
  80. data/lib/right_agent/security.rb +32 -0
  81. data/lib/right_agent/security/cached_certificate_store_proxy.rb +63 -0
  82. data/lib/right_agent/security/certificate.rb +102 -0
  83. data/lib/right_agent/security/certificate_cache.rb +89 -0
  84. data/lib/right_agent/security/distinguished_name.rb +56 -0
  85. data/lib/right_agent/security/encrypted_document.rb +84 -0
  86. data/lib/right_agent/security/rsa_key_pair.rb +76 -0
  87. data/lib/right_agent/security/signature.rb +86 -0
  88. data/lib/right_agent/security/static_certificate_store.rb +69 -0
  89. data/lib/right_agent/sender.rb +937 -0
  90. data/lib/right_agent/serialize.rb +29 -0
  91. data/lib/right_agent/serialize/message_pack.rb +102 -0
  92. data/lib/right_agent/serialize/secure_serializer.rb +131 -0
  93. data/lib/right_agent/serialize/secure_serializer_initializer.rb +47 -0
  94. data/lib/right_agent/serialize/serializable.rb +135 -0
  95. data/lib/right_agent/serialize/serializer.rb +149 -0
  96. data/lib/right_agent/stats_helper.rb +731 -0
  97. data/lib/right_agent/subprocess.rb +38 -0
  98. data/lib/right_agent/tracer.rb +124 -0
  99. data/right_agent.gemspec +60 -0
  100. data/spec/actor_registry_spec.rb +81 -0
  101. data/spec/actor_spec.rb +99 -0
  102. data/spec/agent_config_spec.rb +226 -0
  103. data/spec/agent_identity_spec.rb +75 -0
  104. data/spec/agent_spec.rb +571 -0
  105. data/spec/broker_client_spec.rb +961 -0
  106. data/spec/command/agent_manager_commands_spec.rb +51 -0
  107. data/spec/command/command_io_spec.rb +93 -0
  108. data/spec/command/command_parser_spec.rb +79 -0
  109. data/spec/command/command_runner_spec.rb +72 -0
  110. data/spec/command/command_serializer_spec.rb +51 -0
  111. data/spec/core_payload_types/dev_repositories_spec.rb +64 -0
  112. data/spec/core_payload_types/executable_bundle_spec.rb +59 -0
  113. data/spec/core_payload_types/login_user_spec.rb +98 -0
  114. data/spec/core_payload_types/right_script_attachment_spec.rb +65 -0
  115. data/spec/core_payload_types/spec_helper.rb +23 -0
  116. data/spec/dispatcher_spec.rb +372 -0
  117. data/spec/enrollment_result_spec.rb +53 -0
  118. data/spec/ha_broker_client_spec.rb +1673 -0
  119. data/spec/idempotent_request_spec.rb +136 -0
  120. data/spec/log_spec.rb +177 -0
  121. data/spec/monkey_patches/amqp_patch_spec.rb +100 -0
  122. data/spec/monkey_patches/eventmachine_spec.rb +62 -0
  123. data/spec/monkey_patches/string_patch_spec.rb +99 -0
  124. data/spec/multiplexer_spec.rb +48 -0
  125. data/spec/operation_result_spec.rb +171 -0
  126. data/spec/packets_spec.rb +418 -0
  127. data/spec/platform/platform_spec.rb +60 -0
  128. data/spec/results_mock.rb +45 -0
  129. data/spec/secure_identity_spec.rb +50 -0
  130. data/spec/security/cached_certificate_store_proxy_spec.rb +56 -0
  131. data/spec/security/certificate_cache_spec.rb +71 -0
  132. data/spec/security/certificate_spec.rb +49 -0
  133. data/spec/security/distinguished_name_spec.rb +46 -0
  134. data/spec/security/encrypted_document_spec.rb +55 -0
  135. data/spec/security/rsa_key_pair_spec.rb +55 -0
  136. data/spec/security/signature_spec.rb +66 -0
  137. data/spec/security/static_certificate_store_spec.rb +52 -0
  138. data/spec/sender_spec.rb +887 -0
  139. data/spec/serialize/message_pack_spec.rb +131 -0
  140. data/spec/serialize/secure_serializer_spec.rb +102 -0
  141. data/spec/serialize/serializable_spec.rb +90 -0
  142. data/spec/serialize/serializer_spec.rb +174 -0
  143. data/spec/spec.opts +2 -0
  144. data/spec/spec_helper.rb +77 -0
  145. data/spec/stats_helper_spec.rb +681 -0
  146. data/spec/tracer_spec.rb +114 -0
  147. metadata +320 -0
@@ -0,0 +1,29 @@
1
+ #
2
+ # Copyright (c) 2009-2011 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ SERIALIZE_BASE_DIR = File.join(File.dirname(__FILE__), 'serialize')
24
+
25
+ require File.normalize_path(File.join(SERIALIZE_BASE_DIR, 'message_pack'))
26
+ require File.normalize_path(File.join(SERIALIZE_BASE_DIR, 'secure_serializer'))
27
+ require File.normalize_path(File.join(SERIALIZE_BASE_DIR, 'secure_serializer_initializer'))
28
+ require File.normalize_path(File.join(SERIALIZE_BASE_DIR, 'serializable'))
29
+ require File.normalize_path(File.join(SERIALIZE_BASE_DIR, 'serializer'))
@@ -0,0 +1,102 @@
1
+ #
2
+ # Copyright (c) 2009-2011 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ require 'rubygems'
24
+ require 'msgpack'
25
+
26
+ # Extend MessagePack to conform to load/dump interface of other serializers like JSON
27
+ # and to create internal class objects when they are encountered when unserializing
28
+ module MessagePack
29
+
30
+ # Unserialize data and generate any msgpack_class objects within
31
+ #
32
+ # === Parameters
33
+ # data(String):: MessagePack string to unserialize
34
+ #
35
+ # === Return
36
+ # obj(Object):: Unserialized object
37
+ def self.load(data)
38
+ create(unpack(data))
39
+ end
40
+
41
+ # Create any msgpack_class objects nested within the unserialized data by calling
42
+ # their associated msgpack_create method
43
+ #
44
+ # === Parameters
45
+ # object(Object):: Unserialized object that may contain other objects that need to be created
46
+ #
47
+ # === Return
48
+ # object(Object):: Fully unserialized object
49
+ #
50
+ # === Raises
51
+ # ArgumentError:: If object to be created does not have a msgpack_create method
52
+ def self.create(object)
53
+ if object.is_a?(Hash)
54
+ object.each { |k, v| object[k] = create(v) if v.is_a?(Hash) || v.is_a?(Array) }
55
+ if klass_name = object['msgpack_class']
56
+ klass = deep_const_get(klass_name)
57
+ raise ArgumentError, "#{klass_name} missing msgpack_create method" unless klass.respond_to?(:msgpack_create)
58
+ object = klass.msgpack_create(object)
59
+ end
60
+ elsif object.is_a?(Array)
61
+ object = object.map { |v| v.is_a?(Hash) || v.is_a?(Array) ? create(v) : v }
62
+ end
63
+ object
64
+ end
65
+
66
+ # Serialize object
67
+ # Any non-standard objects must have an associated to_msgpack instance method
68
+ #
69
+ # === Parameters
70
+ # object(Object):: Object to be serialized
71
+ #
72
+ # === Return
73
+ # (String):: Serialized object
74
+ def self.dump(object)
75
+ pack(object)
76
+ end
77
+
78
+ protected
79
+
80
+ # Return the constant located at the specified path
81
+ #
82
+ # === Parameters
83
+ # path(String):: Absolute namespace path that is of the form ::A::B::C or A::B::C,
84
+ # with A always being at the top level
85
+ #
86
+ # === Return
87
+ # (Object):: Constant at the end of the path
88
+ #
89
+ # === Raises
90
+ # ArgumentError:: If there is no constant at the given path
91
+ def self.deep_const_get(path)
92
+ path = path.to_s
93
+ path.split(/::/).inject(Object) do |p, c|
94
+ case
95
+ when c.empty? then p
96
+ when p.const_defined?(c) then p.const_get(c)
97
+ else raise ArgumentError, "Cannot find const #{path}"
98
+ end
99
+ end
100
+ end
101
+
102
+ end # MessagePack
@@ -0,0 +1,131 @@
1
+ #
2
+ # Copyright (c) 2009-2011 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ module RightScale
24
+
25
+ # Serializer implementation which secures messages by using
26
+ # X.509 certificate signing
27
+ class SecureSerializer
28
+
29
+ class MissingCertificate < Exception; end
30
+ class InvalidSignature < Exception; end
31
+
32
+ # Initialize serializer, must be called prior to using it
33
+ #
34
+ # === Parameters
35
+ # serializer(Serializer):: Object serializer
36
+ # identity(String):: Serialized identity associated with serialized messages
37
+ # cert(String):: Certificate used to sign and decrypt serialized messages
38
+ # key(RsaKeyPair):: Private key corresponding to specified cert
39
+ # store(Object):: Certificate store exposing certificates used for
40
+ # encryption (get_recipients) and signature validation (get_signer)
41
+ # encrypt(Boolean):: true if data should be signed and encrypted, otherwise
42
+ # just signed, true by default
43
+ def self.init(serializer, identity, cert, key, store, encrypt = true)
44
+ @identity = identity
45
+ @cert = cert
46
+ @key = key
47
+ @store = store
48
+ @encrypt = encrypt
49
+ @serializer = serializer
50
+ end
51
+
52
+ # Was serializer initialized?
53
+ def self.initialized?
54
+ @identity && @cert && @key && @store
55
+ end
56
+
57
+ # Serialize, sign, and encrypt message
58
+ # Sign and encrypt using X.509 certificate
59
+ #
60
+ # === Parameters
61
+ # obj(Object):: Object to be serialized and encrypted
62
+ # encrypt(Boolean|nil):: true if object should be signed and encrypted,
63
+ # false if just signed, nil means use class setting
64
+ #
65
+ # === Return
66
+ # (String):: MessagePack serialized and optionally encrypted object
67
+ #
68
+ # === Raise
69
+ # Exception:: If certificate identity, certificate store, certificate, or private key missing
70
+ def self.dump(obj, encrypt = nil)
71
+ raise "Missing certificate identity" unless @identity
72
+ raise "Missing certificate" unless @cert
73
+ raise "Missing certificate key" unless @key
74
+ raise "Missing certificate store" unless @store || !@encrypt
75
+ must_encrypt = encrypt.nil? ? @encrypt : encrypt
76
+ serialize_format = if obj.respond_to?(:send_version) && obj.send_version >= 12
77
+ @serializer.format
78
+ else
79
+ :json
80
+ end
81
+ encode_format = serialize_format == :json ? :pem : :der
82
+ msg = @serializer.dump(obj, serialize_format)
83
+ if must_encrypt
84
+ certs = @store.get_recipients(obj)
85
+ if certs
86
+ msg = EncryptedDocument.new(msg, certs).encrypted_data(encode_format)
87
+ else
88
+ target = obj.target_for_encryption if obj.respond_to?(:target_for_encryption)
89
+ Log.warning("No certs available for object #{obj.class} being sent to #{target.inspect}\n") if target
90
+ end
91
+ end
92
+ sig = Signature.new(msg, @cert, @key).data(encode_format)
93
+ @serializer.dump({'id' => @identity, 'data' => msg, 'signature' => sig, 'encrypted' => !certs.nil?}, serialize_format)
94
+ end
95
+
96
+ # Decrypt, authorize signature, and unserialize message
97
+ # Use x.509 certificate store for decrypting and validating signature
98
+ #
99
+ # === Parameters
100
+ # msg(String):: Serialized and optionally encrypted object using MessagePack or JSON
101
+ #
102
+ # === Return
103
+ # (Object):: Unserialized object
104
+ #
105
+ # === Raise
106
+ # Exception:: If certificate store, certificate, or private key missing
107
+ # MissingCertificate:: If could not find certificate for message signer
108
+ # InvalidSignature:: If message signature check failed for message
109
+ def self.load(msg)
110
+ raise "Missing certificate store" unless @store
111
+ raise "Missing certificate" unless @cert || !@encrypt
112
+ raise "Missing certificate key" unless @key || !@encrypt
113
+
114
+ msg = @serializer.load(msg)
115
+ sig = Signature.from_data(msg['signature'])
116
+ certs = @store.get_signer(msg['id'])
117
+ raise MissingCertificate.new("Could not find a certificate for signer #{msg['id']}") unless certs
118
+
119
+ certs = [ certs ] unless certs.respond_to?(:any?)
120
+ raise InvalidSignature.new("Failed signature check for signer #{msg['id']}") unless certs.any? { |c| sig.match?(c) }
121
+
122
+ data = msg['data']
123
+ if data && @encrypt && msg['encrypted']
124
+ data = EncryptedDocument.from_data(data).decrypted_data(@key, @cert)
125
+ end
126
+ @serializer.load(data) if data
127
+ end
128
+
129
+ end # SecureSerializer
130
+
131
+ end # RightScale
@@ -0,0 +1,47 @@
1
+ #
2
+ # Copyright (c) 2009-2011 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ module RightScale
24
+
25
+ # Helper class used to initialize secure serializer for agents
26
+ class SecureSerializerInitializer
27
+
28
+ # Initialize serializer
29
+ #
30
+ # === Parameters
31
+ # agent_type(String):: Agent type used to build filename of certificate and key
32
+ # agent_id(String):: Serialized agent identity
33
+ #
34
+ # === Return
35
+ # true:: Always return true
36
+ def self.init(agent_type, agent_id)
37
+ cert = Certificate.load(AgentConfig.certs_file("#{agent_type}.cert"))
38
+ key = RsaKeyPair.load(AgentConfig.certs_file("#{agent_type}.key"))
39
+ mapper_cert = Certificate.load(AgentConfig.certs_file("mapper.cert"))
40
+ store = StaticCertificateStore.new(mapper_cert, mapper_cert)
41
+ SecureSerializer.init(Serializer.new, agent_id, cert, key, store)
42
+ true
43
+ end
44
+
45
+ end
46
+
47
+ end
@@ -0,0 +1,135 @@
1
+ #
2
+ # Copyright (c) 2009-2011 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #
23
+
24
+ module RightScale
25
+
26
+ # MessagePack and JSON serializable types that are sent to and from agents
27
+ module Serializable
28
+
29
+ def self.included(base)
30
+ base.extend ClassMethods
31
+ base.send(:include, InstanceMethods)
32
+ end
33
+
34
+ module ClassMethods
35
+
36
+ # Called when deserializing MessagePack to create object
37
+ #
38
+ # === Parameters
39
+ # o(Hash):: Unserialized object data
40
+ #
41
+ # === Return
42
+ # (Object):: Unserialized object
43
+ def msgpack_create(o)
44
+ new(*o['data'])
45
+ end
46
+
47
+ # Called by JSON serializer to create object
48
+ #
49
+ # === Parameters
50
+ # o(Hash):: Unserialized object data
51
+ #
52
+ # === Return
53
+ # (Object):: Unserialized object
54
+ def json_create(o)
55
+ new(*o['data'])
56
+ end
57
+
58
+ end
59
+
60
+ module InstanceMethods
61
+
62
+ # Called by MessagePack serializer to serialise object's members
63
+ #
64
+ # === Parameters
65
+ # *a(Array):: Pass-through to Hash's 'to_msgpack' method
66
+ #
67
+ # === Return
68
+ # (String):: MessagePack representation
69
+ def to_msgpack(*a)
70
+ {
71
+ 'msgpack_class' => self.class.name,
72
+ 'data' => serialized_members
73
+ }.to_msgpack(*a)
74
+ end
75
+
76
+ # Called by JSON serializer to serialise object's members
77
+ #
78
+ # === Parameters
79
+ # *a(Array):: Pass-through to Hash's 'to_json' method
80
+ #
81
+ # === Return
82
+ # (String):: JSON representation
83
+ def to_json(*a)
84
+ {
85
+ 'json_class' => self.class.name,
86
+ 'data' => serialized_members
87
+ }.to_json(*a)
88
+ end
89
+
90
+ # Implement in serializable class and return array of fields
91
+ # that should be given to constructor when deserializing
92
+ #
93
+ # === Raise
94
+ # RuntimeError:: Always raised. Override in heir.
95
+ def serialized_members
96
+ raise NotImplemented.new("Must be implemented by #{self.class.name}")
97
+ end
98
+
99
+ # Use serialized members to compare two serializable instances
100
+ #
101
+ # === Parameters
102
+ # other(Serializable):: Other instance to compare self to
103
+ #
104
+ # === Return
105
+ # true:: If both serializable have identical serialized fields
106
+ # false:: Otherwise
107
+ def ==(other)
108
+ return false unless other.respond_to?(:serialized_members)
109
+ self.serialized_members == other.serialized_members
110
+ end
111
+
112
+ end
113
+
114
+ end
115
+
116
+ class SerializationHelper
117
+
118
+ # Symbolize keys of hash, use when retrieving hashes that use symbols
119
+ # for keys as JSON and MessagePack serialization will produce strings instead
120
+ #
121
+ # === Parameters
122
+ # hash(Hash):: Hash whose keys are to be symbolized
123
+ #
124
+ # === Return
125
+ # (Hash):: Hash with same values but symbol keys
126
+ def self.symbolize_keys(hash)
127
+ hash.inject({}) do |h, (key, value)|
128
+ h[(key.to_sym rescue key) || key] = value
129
+ h
130
+ end
131
+ end
132
+
133
+ end # Serializable
134
+
135
+ end # RightScale