Netflix/security_monkey

Unable to store ACM certificate that contains UpdatedAt field

pdallegrave opened this issue · 1 comments

Please make sure that you have checked the boxes:

Description of issue:

find_changes script is not able to process ACM certificates that contain the "UpdatedAt" key under "RenewalSummary".

This occurs since the key contains a datetime.datetime() object that is not properly parsed by watchers/acm.py slurp() method.

For each certificate the method converts the datetime object into a ISO formatted string for several keys, but "UpdateAt" conversion is not present.

Error message:

2019-06-19 17:04:08,537 ERROR: [X] Database error processing cleaning up session. [in /usr/local/src/security_monkey/security_monkey/task_scheduler/tasks.py:205]
Traceback (most recent call last):
  File "/usr/local/src/security_monkey/security_monkey/task_scheduler/tasks.py", line 199, in manual_run_change_finder
    find_changes(account, tech)
  File "/usr/local/src/security_monkey/security_monkey/task_scheduler/tasks.py", line 240, in find_changes
    cw.save()
  File "/usr/local/src/security_monkey/security_monkey/watcher.py", line 502, in save
    item.save(self.datastore)
  File "/usr/local/src/security_monkey/security_monkey/watcher.py", line 655, in save
    source_watcher=self.watcher)
  File "/usr/local/src/security_monkey/security_monkey/datastore.py", line 666, in store
    db.session.commit()
  File "build/bdist.linux-x86_64/egg/sqlalchemy/orm/scoping.py", line 162, in do
    return getattr(self.registry(), name)(*args, **kwargs)
  File "build/bdist.linux-x86_64/egg/sqlalchemy/orm/session.py", line 1026, in commit
    self.transaction.commit()
  File "build/bdist.linux-x86_64/egg/sqlalchemy/orm/session.py", line 493, in commit
    self._prepare_impl()
  File "build/bdist.linux-x86_64/egg/sqlalchemy/orm/session.py", line 472, in _prepare_impl
    self.session.flush()
  File "build/bdist.linux-x86_64/egg/sqlalchemy/orm/session.py", line 2451, in flush
    self._flush(objects)
  File "build/bdist.linux-x86_64/egg/sqlalchemy/orm/session.py", line 2589, in _flush
    transaction.rollback(_capture_exception=True)
  File "build/bdist.linux-x86_64/egg/sqlalchemy/util/langhelpers.py", line 68, in __exit__
    compat.reraise(exc_type, exc_value, exc_tb)
  File "build/bdist.linux-x86_64/egg/sqlalchemy/orm/session.py", line 2549, in _flush
    flush_context.execute()
  File "build/bdist.linux-x86_64/egg/sqlalchemy/orm/unitofwork.py", line 422, in execute
    rec.execute(self)
  File "build/bdist.linux-x86_64/egg/sqlalchemy/orm/unitofwork.py", line 589, in execute
    uow,
  File "build/bdist.linux-x86_64/egg/sqlalchemy/orm/persistence.py", line 245, in save_obj
    insert,
  File "build/bdist.linux-x86_64/egg/sqlalchemy/orm/persistence.py", line 1120, in _emit_insert_statements
    statement, params
  File "build/bdist.linux-x86_64/egg/sqlalchemy/engine/base.py", line 988, in execute
    return meth(self, multiparams, params)
  File "build/bdist.linux-x86_64/egg/sqlalchemy/sql/elements.py", line 287, in _execute_on_connection
    return connection._execute_clauseelement(self, multiparams, params)
  File "build/bdist.linux-x86_64/egg/sqlalchemy/engine/base.py", line 1107, in _execute_clauseelement
    distilled_params,
  File "build/bdist.linux-x86_64/egg/sqlalchemy/engine/base.py", line 1182, in _execute_context
    e, util.text_type(statement), parameters, None, None
  File "build/bdist.linux-x86_64/egg/sqlalchemy/engine/base.py", line 1466, in _handle_dbapi_exception
    util.raise_from_cause(sqlalchemy_exception, exc_info)
  File "build/bdist.linux-x86_64/egg/sqlalchemy/util/compat.py", line 383, in raise_from_cause
    reraise(type(exception), exception, tb=exc_tb, cause=cause)
  File "build/bdist.linux-x86_64/egg/sqlalchemy/engine/base.py", line 1179, in _execute_context
    context = constructor(dialect, self, conn, *args)
  File "build/bdist.linux-x86_64/egg/sqlalchemy/engine/default.py", line 735, in _init_compiled
    for key in compiled_params
  File "build/bdist.linux-x86_64/egg/sqlalchemy/engine/default.py", line 735, in <genexpr>
    for key in compiled_params
  File "build/bdist.linux-x86_64/egg/sqlalchemy/sql/sqltypes.py", line 2241, in process
    serialized = json_serializer(value)
  File "/usr/lib/python2.7/json/__init__.py", line 244, in dumps
    return _default_encoder.encode(obj)
  File "/usr/lib/python2.7/json/encoder.py", line 207, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python2.7/json/encoder.py", line 270, in iterencode
    return _iterencode(o, 0)
  File "/usr/lib/python2.7/json/encoder.py", line 184, in default
    raise TypeError(repr(o) + " is not JSON serializable")
StatementError: (exceptions.TypeError) datetime.datetime(2019, 6, 5, 12, 37, 23, tzinfo=tzlocal()) is not JSON serializable

The problem can be solved by adding the following code at line 100 in acm/py file:

if config.get('RenewalSummary').get('UpdatedAt'):
    config.get('RenewalSummary').update({'UpdatedAt': config.get('RenewalSummary').get(
                                'UpdatedAt').astimezone(tzutc()).isoformat()})