Permalink
Browse files

director/agent: add configurable encryption support

Change-Id: Ia505f0e1eef29139c41c89f6c1d594b36a7d6fb9
  • Loading branch information...
1 parent e6690a4 commit 1f2d34e847d2bd361dd3cd0ba95d35ea0adba7d0 @skaar skaar committed with olegshaldybin Mar 13, 2012
Showing with 455 additions and 14 deletions.
  1. +5 −0 agent/Gemfile
  2. +22 −1 agent/Gemfile.lock
  3. +15 −0 agent/Guardfile
  4. +2 −0 agent/lib/agent.rb
  5. +10 −0 agent/lib/agent/bootstrap.rb
  6. +5 −1 agent/lib/agent/config.rb
  7. +78 −0 agent/lib/agent/handler.rb
  8. +1 −1 agent/lib/agent/version.rb
  9. +1 −1 agent/spec/functional/agent_controller_spec.rb
  10. +17 −0 agent/spec/unit/bootstrap_spec.rb
  11. +170 −0 agent/spec/unit/handler_spec.rb
  12. BIN agent/vendor/cache/bosh_encryption-0.0.3.gem
  13. BIN agent/vendor/cache/ffi-1.0.11.gem
  14. BIN agent/vendor/cache/gibberish-1.2.0.gem
  15. BIN agent/vendor/cache/guard-1.0.0.gem
  16. BIN agent/vendor/cache/guard-bundler-0.1.3.gem
  17. BIN agent/vendor/cache/guard-rspec-0.6.0.gem
  18. BIN agent/vendor/cache/ruby_gntp-0.3.4.gem
  19. BIN agent/vendor/cache/thor-0.14.6.gem
  20. BIN agent/vendor/cache/yajl-ruby-0.8.1.gem
  21. BIN agent/vendor/cache/yajl-ruby-1.1.0.gem
  22. +1 −0 director/Gemfile
  23. +7 −1 director/Gemfile.lock
  24. +1 −1 director/Guardfile
  25. +1 −0 director/lib/director.rb
  26. +7 −0 director/lib/director/agent_client.rb
  27. +20 −0 director/lib/director/client.rb
  28. +45 −0 director/spec/unit/agent_client_spec.rb
  29. +33 −0 director/spec/unit/client_spec.rb
  30. BIN director/vendor/cache/bosh_encryption-0.0.3.gem
  31. BIN director/vendor/cache/gibberish-1.2.0.gem
  32. BIN director/vendor/cache/yajl-ruby-0.8.2.gem
  33. BIN director/vendor/cache/yajl-ruby-1.1.0.gem
  34. +2 −2 encryption/Gemfile.lock
  35. +8 −4 encryption/lib/encryption/encryption_handler.rb
  36. +1 −1 encryption/lib/encryption/version.rb
  37. +1 −0 spec/Gemfile
  38. +2 −1 spec/Gemfile.lock
  39. BIN spec/vendor/cache/yajl-ruby-0.7.9.gem
  40. BIN spec/vendor/cache/yajl-ruby-1.1.0.gem
View
@@ -12,8 +12,13 @@ gem "thin"
gem "sinatra"
gem "rack-test"
gem "sigar", ">=0.7.2"
+gem "bosh_encryption", ">=0.0.3"
group :development do
+ gem "guard"
+ gem "guard-bundler"
+ gem "guard-rspec"
+ gem "ruby_gntp"
gem "ruby-debug", :platforms => :ruby_18
gem "ruby-debug19", :platforms => :ruby_19
end
View
@@ -12,6 +12,10 @@ GEM
json (~> 1.6.5)
ruby-atmos-pure (~> 1.0.5)
uuidtools (~> 2.1.2)
+ bosh_encryption (0.0.3)
+ gibberish (~> 1.2.0)
+ uuidtools (~> 2.1.2)
+ yajl-ruby
builder (3.0.0)
ci_reporter (1.6.3)
builder (>= 2.1.2)
@@ -20,6 +24,16 @@ GEM
daemons (1.1.5)
diff-lcs (1.1.3)
eventmachine (0.12.10)
+ ffi (1.0.11)
+ gibberish (1.2.0)
+ guard (1.0.0)
+ ffi (>= 0.5.0)
+ thor (~> 0.14.6)
+ guard-bundler (0.1.3)
+ bundler (>= 1.0.0)
+ guard (>= 0.2.2)
+ guard-rspec (0.6.0)
+ guard (>= 0.10.0)
httpclient (2.2.4)
json (1.6.5)
json_pure (1.6.4)
@@ -71,6 +85,7 @@ GEM
ruby-hmac (0.4.0)
ruby_core_source (0.1.5)
archive-tar-minitar (>= 0.5.2)
+ ruby_gntp (0.3.4)
sigar (0.7.2)
simplecov (0.4.2)
simplecov-html (~> 0.4.4)
@@ -85,17 +100,22 @@ GEM
daemons (>= 1.0.9)
eventmachine (>= 0.12.6)
rack (>= 1.0.0)
+ thor (0.14.6)
tilt (1.3.3)
uuidtools (2.1.2)
xml-simple (1.1.1)
- yajl-ruby (0.8.1)
+ yajl-ruby (1.1.0)
PLATFORMS
ruby
DEPENDENCIES
blobstore_client (~> 0.3.11)
+ bosh_encryption (>= 0.0.3)
ci_reporter
+ guard
+ guard-bundler
+ guard-rspec
monit_api
nats (= 0.4.22.beta.4)
netaddr
@@ -106,6 +126,7 @@ DEPENDENCIES
rspec
ruby-debug
ruby-debug19
+ ruby_gntp
sigar (>= 0.7.2)
simplecov
simplecov-rcov
View
@@ -0,0 +1,15 @@
+# Copyright (c) 2009-2012 VMware, Inc.
+
+guard :bundler, :notify => false do
+ watch("Gemfile")
+end
+
+group :unit_tests do
+ guard :rspec, :version => 2, :cli => "--color --format nested --fail-fast",
+ :all_after_pass => false, :spec_paths => %w(spec/unit) do
+ watch("spec/spec_helper.rb") { "spec/unit" }
+ watch("lib/agent.rb") { "spec/unit" }
+ watch(%r{^spec/.+_spec\.rb})
+ watch(%r{^lib/agent/(.+)\.rb}) { |m| "spec/unit/#{m[1]}_spec.rb" }
+ end
+end
View
@@ -14,6 +14,8 @@ module Bosh
require "monit_api"
require "fileutils"
+require "encryption/encryption_handler"
+
require "agent/ext"
require "agent/version"
@@ -36,6 +36,7 @@ def configure
update_iptables
update_passwords
update_agent_id
+ update_credentials
update_hostname
update_mbus
update_blobstore
@@ -98,6 +99,15 @@ def update_agent_id
Bosh::Agent::Config.agent_id = @settings["agent_id"]
end
+ def update_credentials
+ env = @settings["env"]
+ if env && bosh_env = env["bosh"]
+ if bosh_env["credentials"]
+ Bosh::Agent::Config.credentials = bosh_env["credentials"]
+ end
+ end
+ end
+
def update_hostname
agent_id = @settings['agent_id']
@@ -28,7 +28,8 @@ class << self
:state,
:sshd_monitor_interval,
:sshd_start_delay,
- :sshd_monitor_enabled
+ :sshd_monitor_enabled,
+ :credentials
]
CONFIG_OPTIONS.each do |option|
@@ -81,6 +82,9 @@ def setup(config)
end
@settings_file = File.join(@base_dir, 'bosh', 'settings.json')
+
+ @credentials = config["credentials"]
+
@settings = {}
@state = State.new(File.join(@base_dir, "bosh", "state.yml"))
View
@@ -1,6 +1,7 @@
module Bosh::Agent
class Handler
+ attr_accessor :nats
attr_reader :processors
def self.start
@@ -31,6 +32,10 @@ def initialize
@nats_fail_count = 0
+ @credentials = Config.credentials
+ @sessions = {}
+ @session_reply_map = {}
+
find_message_processors
end
@@ -128,8 +133,18 @@ def handle_message(json)
return
end
+ unless msg["reply_to"]
+ @logger.info("Missing reply_to in: #{msg}")
+ return
+ end
+
@logger.info("Message: #{msg.inspect}")
+ if @credentials
+ msg = decrypt(msg)
+ return if msg.nil?
+ end
+
reply_to = msg['reply_to']
method = msg['method']
args = msg['arguments']
@@ -187,6 +202,11 @@ def handle_get_task(reply_to, agent_task_id)
def publish(reply_to, payload, &blk)
@logger.info("reply_to: #{reply_to}: payload: #{payload.inspect}")
+
+ if @credentials
+ payload = encrypt(reply_to, payload)
+ end
+
@nats.publish(reply_to, Yajl::Encoder.encode(payload), blk)
end
@@ -257,6 +277,64 @@ def handle_shutdown(reply_to)
}
end
+ def lookup_encryption_handler(arg)
+ if arg[:session_id]
+ message_session_id = arg[:session_id]
+ @sessions[message_session_id] ||= Bosh::EncryptionHandler.new(@agent_id, @credentials)
+ encryption_handler = @sessions[message_session_id]
+ return encryption_handler
+ elsif arg[:reply_to]
+ reply_to = arg[:reply_to]
+ @session_reply_map[reply_to]
+ end
+ end
+
+ def decrypt(msg)
+ [ "session_id", "encrypted_data" ].each do |key|
+ unless msg.key?(key)
+ @logger.info("Missing #{key} in #{msg}")
+ return
+ end
+ end
+
+ message_session_id = msg["session_id"]
+ reply_to = msg["reply_to"]
+
+ encryption_handler = lookup_encryption_handler(:session_id => message_session_id)
+
+ # save message handler for the reply
+ @session_reply_map[reply_to] = encryption_handler
+
+ # Log exceptions from the EncryptionHandler, but stay quiet on the wire.
+ begin
+ msg = encryption_handler.decrypt(msg["encrypted_data"])
+ rescue Bosh::EncryptionHandler::CryptError => e
+ log_encryption_error(e)
+ return
+ end
+
+ msg["reply_to"] = reply_to
+
+ @logger.info("Decrypted Message: #{msg}")
+ msg
+ end
+
+ def log_encryption_error(e)
+ @logger.info("Encrypton Error: #{e.inspect} #{e.backtrace.join('\n')}")
+ end
+
+ def encrypt(reply_to, payload)
+ encryption_handler = lookup_encryption_handler(:reply_to => reply_to)
+ session_id = encryption_handler.session_id
+
+ payload = {
+ "session_id" => session_id,
+ "encrypted_data" => encryption_handler.encrypt(payload)
+ }
+
+ payload
+ end
+
end
# Built-in message handlers
@@ -1,6 +1,6 @@
module Bosh
module Agent
- VERSION = "0.4.8"
+ VERSION = "0.5.1"
BOSH_PROTOCOL = "1"
end
end
@@ -25,7 +25,7 @@ def app
def agent_call(method, args=[])
post "/agent", {}, {
"CONTENT_TYPE" => "application/json",
- :input => Yajl::Encoder.encode({ "method" => method, "arguments" => args })
+ :input => Yajl::Encoder.encode({"reply_to" => "http_client", "method" => method, "arguments" => args })
}
end
@@ -21,6 +21,23 @@
@processor.stub(:mem_total).and_return(3951616)
end
+ it "should updat credentials" do
+ @processor.load_settings
+ @processor.update_credentials
+ Bosh::Agent::Config.credentials.should == nil
+
+ new_settings = complete_settings
+ new_settings["env"] ||= {}
+ new_settings["env"]["bosh"] ||= {}
+ new_settings["env"]["bosh"]["credentials"] = {"crypt_key"=>"crypt_key", "sign_key"=>"sign_key"}
+
+ Bosh::Agent::Config.infrastructure.stub!(:load_settings).and_return(new_settings)
+
+ @processor.load_settings
+ @processor.update_credentials
+ Bosh::Agent::Config.credentials.should == {"crypt_key"=>"crypt_key", "sign_key"=>"sign_key"}
+ end
+
it "should not setup iptables without settings" do
@processor.load_settings
@processor.stub!(:iptables).and_raise(Bosh::Agent::Error)
Oops, something went wrong.

0 comments on commit 1f2d34e

Please sign in to comment.