Skip to content

Commit

Permalink
Don't crash when receiving unknown configuration variables
Browse files Browse the repository at this point in the history
Instead of crashing if the monkey deserializes an unknown configuration
variable, send an error message to the current monkey server and keep on
working.

fixes guardicore#26
  • Loading branch information
Fak3 committed Sep 27, 2016
1 parent 569a9b0 commit bfea4fa
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 3 deletions.
1 change: 0 additions & 1 deletion chaos_monkey/__init__.py

This file was deleted.

9 changes: 8 additions & 1 deletion chaos_monkey/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ def _cast_by_example(value, example):

class Configuration(object):
def from_dict(self, data):
"""
Get a dict of config variables, set known variables as attributes on self.
Return dict of unknown variables encountered.
"""
unknown_variables = {}
for key, value in data.items():
if key.startswith('_'):
continue
Expand All @@ -55,9 +60,11 @@ def from_dict(self, data):
try:
default_value = getattr(Configuration, key)
except AttributeError:
raise
unknown_variables[key] = value
continue

setattr(self, key, _cast_by_example(value, default_value))
return unknown_variables

def as_dict(self):
result = {}
Expand Down
19 changes: 18 additions & 1 deletion chaos_monkey/control.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,31 @@ def load_control_config():
return

try:
WormConfiguration.from_dict(reply.json().get('config'))
unknown_variables = WormConfiguration.from_dict(reply.json().get('config'))
LOG.info("New configuration was loaded from server: %r" % (WormConfiguration.as_dict(),))
except Exception, exc:
# we don't continue with default conf here because it might be dangerous
LOG.error("Error parsing JSON reply from control server %s (%s): %s",
WormConfiguration.current_server, reply._content, exc)
raise Exception("Couldn't load from from server's configuration, aborting. %s" % exc)

if unknown_variables:
ControlClient.send_config_error()

@staticmethod
def send_config_error():
if not WormConfiguration.current_server:
return
try:
requests.patch("https://%s/api/monkey/%s" % (WormConfiguration.current_server, GUID),
data=json.dumps({'config_error': True}),
headers={'content-type': 'application/json'},
verify=False,
proxies=ControlClient.proxies)
except Exception, exc:
LOG.warn("Error connecting to control server %s: %s", WormConfiguration.current_server, exc)
return {}

@staticmethod
def check_for_stop():
ControlClient.load_control_config()
Expand Down
2 changes: 2 additions & 0 deletions chaos_monkey/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ psutil
PyInstaller
ecdsa
netifaces
mock
nose
2 changes: 2 additions & 0 deletions monkey_island/cc/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ def patch(self, guid):
update['$set']['config'] = monkey_json['config']
if 'tunnel' in monkey_json:
update['$set']['tunnel'] = monkey_json['tunnel']
if 'config_error' in monkey_json:
update['$set']['config_error'] = monkey_json['config_error']

return mongo.db.monkey.update({"guid": guid}, update, upsert=False)

Expand Down

0 comments on commit bfea4fa

Please sign in to comment.