Merge "Enable signature verification for events"
This commit is contained in:
commit
dcada9c8d8
@ -109,20 +109,25 @@ class DatabaseDispatcher(dispatcher.MeterDispatcherBase,
|
|||||||
|
|
||||||
event_list = []
|
event_list = []
|
||||||
for ev in events:
|
for ev in events:
|
||||||
try:
|
if publisher_utils.verify_signature(
|
||||||
event_list.append(
|
ev, self.conf.publisher.telemetry_secret):
|
||||||
models.Event(
|
try:
|
||||||
message_id=ev['message_id'],
|
event_list.append(
|
||||||
event_type=ev['event_type'],
|
models.Event(
|
||||||
generated=timeutils.normalize_time(
|
message_id=ev['message_id'],
|
||||||
timeutils.parse_isotime(ev['generated'])),
|
event_type=ev['event_type'],
|
||||||
traits=[models.Trait(
|
generated=timeutils.normalize_time(
|
||||||
name, dtype,
|
timeutils.parse_isotime(ev['generated'])),
|
||||||
models.Trait.convert_value(dtype, value))
|
traits=[models.Trait(
|
||||||
for name, dtype, value in ev['traits']],
|
name, dtype,
|
||||||
raw=ev.get('raw', {}))
|
models.Trait.convert_value(dtype, value))
|
||||||
)
|
for name, dtype, value in ev['traits']],
|
||||||
except Exception:
|
raw=ev.get('raw', {}))
|
||||||
LOG.exception(_LE("Error processing event and it will be "
|
)
|
||||||
"dropped: %s"), ev)
|
except Exception:
|
||||||
|
LOG.exception(_LE("Error processing event and it will be "
|
||||||
|
"dropped: %s"), ev)
|
||||||
|
else:
|
||||||
|
LOG.warning(_LW(
|
||||||
|
'event signature invalid, discarding event: %s'), ev)
|
||||||
self.event_conn.record_events(event_list)
|
self.event_conn.record_events(event_list)
|
||||||
|
@ -19,7 +19,7 @@ from oslo_log import log
|
|||||||
import requests
|
import requests
|
||||||
|
|
||||||
from ceilometer import dispatcher
|
from ceilometer import dispatcher
|
||||||
from ceilometer.i18n import _, _LE
|
from ceilometer.i18n import _, _LE, _LW
|
||||||
from ceilometer.publisher import utils as publisher_utils
|
from ceilometer.publisher import utils as publisher_utils
|
||||||
|
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
@ -132,13 +132,19 @@ class HttpDispatcher(dispatcher.MeterDispatcherBase,
|
|||||||
events = [events]
|
events = [events]
|
||||||
|
|
||||||
for event in events:
|
for event in events:
|
||||||
res = None
|
if publisher_utils.verify_signature(
|
||||||
try:
|
event, self.conf.publisher.telemetry_secret):
|
||||||
res = requests.post(self.event_target, data=event,
|
res = None
|
||||||
headers=self.headers, timeout=self.timeout)
|
try:
|
||||||
res.raise_for_status()
|
res = requests.post(self.event_target, data=event,
|
||||||
except Exception:
|
headers=self.headers,
|
||||||
error_code = res.status_code if res else 'unknown'
|
timeout=self.timeout)
|
||||||
LOG.exception(_LE('Status Code: %{code}s. Failed to dispatch '
|
res.raise_for_status()
|
||||||
'event: %{event}s'),
|
except Exception:
|
||||||
{'code': error_code, 'event': event})
|
error_code = res.status_code if res else 'unknown'
|
||||||
|
LOG.exception(_LE('Status Code: %{code}s. Failed to'
|
||||||
|
'dispatch event: %{event}s'),
|
||||||
|
{'code': error_code, 'event': event})
|
||||||
|
else:
|
||||||
|
LOG.warning(_LW(
|
||||||
|
'event signature invalid, discarding event: %s'), event)
|
||||||
|
@ -36,11 +36,35 @@ class TestDispatcherDB(base.BaseTestCase):
|
|||||||
def test_event_conn(self):
|
def test_event_conn(self):
|
||||||
event = event_models.Event(uuid.uuid4(), 'test',
|
event = event_models.Event(uuid.uuid4(), 'test',
|
||||||
datetime.datetime(2012, 7, 2, 13, 53, 40),
|
datetime.datetime(2012, 7, 2, 13, 53, 40),
|
||||||
[], {}).serialize()
|
[], {})
|
||||||
|
event = utils.message_from_event(event,
|
||||||
|
self.CONF.publisher.telemetry_secret)
|
||||||
with mock.patch.object(self.dispatcher.event_conn,
|
with mock.patch.object(self.dispatcher.event_conn,
|
||||||
'record_events') as record_events:
|
'record_events') as record_events:
|
||||||
self.dispatcher.record_events(event)
|
self.dispatcher.record_events(event)
|
||||||
self.assertTrue(record_events.called)
|
self.assertEqual(1, len(record_events.call_args_list[0][0][0]))
|
||||||
|
|
||||||
|
@mock.patch('ceilometer.publisher.utils.verify_signature')
|
||||||
|
def test_event_with_bad_signature(self, mocked_verify):
|
||||||
|
event = event_models.Event(uuid.uuid4(), 'test',
|
||||||
|
datetime.datetime(2012, 7, 2, 13, 53, 40),
|
||||||
|
[], {}).serialize()
|
||||||
|
|
||||||
|
def _fake_verify(ev, secret):
|
||||||
|
if ev.get('message_signature') == 'bad_signature':
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
mocked_verify.side_effect = _fake_verify
|
||||||
|
with mock.patch.object(self.dispatcher.event_conn,
|
||||||
|
'record_events') as record_events:
|
||||||
|
event['message_signature'] = 'bad_signature'
|
||||||
|
self.dispatcher.record_events(event)
|
||||||
|
self.assertEqual([], record_events.call_args_list[0][0][0])
|
||||||
|
del event['message_signature']
|
||||||
|
event['message_signature'] = utils.compute_signature(
|
||||||
|
event, self.CONF.publisher.telemetry_secret)
|
||||||
|
self.dispatcher.record_events(event)
|
||||||
|
self.assertEqual(1, len(record_events.call_args_list[1][0][0]))
|
||||||
|
|
||||||
def test_valid_message(self):
|
def test_valid_message(self):
|
||||||
msg = {'counter_name': 'test',
|
msg = {'counter_name': 'test',
|
||||||
|
@ -136,7 +136,9 @@ class TestEventDispatcherHttp(base.BaseTestCase):
|
|||||||
|
|
||||||
event = event_models.Event(uuid.uuid4(), 'test',
|
event = event_models.Event(uuid.uuid4(), 'test',
|
||||||
datetime.datetime(2012, 7, 2, 13, 53, 40),
|
datetime.datetime(2012, 7, 2, 13, 53, 40),
|
||||||
[], {}).serialize()
|
[], {})
|
||||||
|
event = utils.message_from_event(event,
|
||||||
|
self.CONF.publisher.telemetry_secret)
|
||||||
|
|
||||||
with mock.patch.object(requests, 'post') as post:
|
with mock.patch.object(requests, 'post') as post:
|
||||||
dispatcher.record_events(event)
|
dispatcher.record_events(event)
|
||||||
@ -149,8 +151,9 @@ class TestEventDispatcherHttp(base.BaseTestCase):
|
|||||||
|
|
||||||
event = event_models.Event(uuid.uuid4(), 'test',
|
event = event_models.Event(uuid.uuid4(), 'test',
|
||||||
datetime.datetime(2012, 7, 2, 13, 53, 40),
|
datetime.datetime(2012, 7, 2, 13, 53, 40),
|
||||||
[], {}).serialize()
|
[], {})
|
||||||
|
event = utils.message_from_event(event,
|
||||||
|
self.CONF.publisher.telemetry_secret)
|
||||||
with mock.patch('ceilometer.dispatcher.http.LOG',
|
with mock.patch('ceilometer.dispatcher.http.LOG',
|
||||||
mock.MagicMock()) as LOG:
|
mock.MagicMock()) as LOG:
|
||||||
dispatcher.record_events(event)
|
dispatcher.record_events(event)
|
||||||
@ -162,8 +165,9 @@ class TestEventDispatcherHttp(base.BaseTestCase):
|
|||||||
|
|
||||||
event = event_models.Event(uuid.uuid4(), 'test',
|
event = event_models.Event(uuid.uuid4(), 'test',
|
||||||
datetime.datetime(2012, 7, 2, 13, 53, 40),
|
datetime.datetime(2012, 7, 2, 13, 53, 40),
|
||||||
[], {}).serialize()
|
[], {})
|
||||||
|
event = utils.message_from_event(event,
|
||||||
|
self.CONF.publisher.telemetry_secret)
|
||||||
with mock.patch.object(requests, 'post') as post:
|
with mock.patch.object(requests, 'post') as post:
|
||||||
dispatcher.record_events(event)
|
dispatcher.record_events(event)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user