Skip to content

Commit

Permalink
Merge pull request airbnb#505 from airbnb/javier-streamalert-phantom-…
Browse files Browse the repository at this point in the history
…backoff

[output] Backoff support in phantom output
  • Loading branch information
javuto authored Dec 5, 2017
2 parents f856bd8 + a3f9097 commit 1c00060
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 8 deletions.
23 changes: 15 additions & 8 deletions stream_alert/alert_processor/outputs/phantom.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from stream_alert.alert_processor.outputs.output_base import (
OutputDispatcher,
OutputProperty,
OutputRequestFailure,
StreamAlertOutput
)

Expand Down Expand Up @@ -80,11 +81,14 @@ def _check_container_exists(cls, rule_name, container_url, headers):
'_filter_name': '"{}"'.format(rule_name),
'page_size': 1
}
resp = cls._get_request(container_url, params, headers, False)
if not cls._check_http_response(resp):
try:
resp = cls._get_request_retry(container_url, params, headers, False)
except OutputRequestFailure:
return False

response = resp.json()
if not response:
return False

# If the count == 0 then we know there are no containers with this name and this
# will evaluate to False. Otherwise there is at least one item in the list
Expand Down Expand Up @@ -114,12 +118,14 @@ def _setup_container(cls, rule_name, rule_description, base_url, headers):

# Try to use the rule_description from the rule as the container description
ph_container = {'name': rule_name, 'description': rule_description}
resp = cls._post_request(container_url, ph_container, headers, False)

if not cls._check_http_response(resp):
try:
resp = cls._post_request_retry(container_url, ph_container, headers, False)
except OutputRequestFailure:
return False

response = resp.json()
if not response:
return False

return response and response.get('id')

Expand Down Expand Up @@ -151,8 +157,9 @@ def dispatch(self, **kwargs):
'name': 'Phantom Artifact',
'label': 'Alert'}
artifact_url = os.path.join(creds['url'], self.ARTIFACT_ENDPOINT)
resp = self._post_request(artifact_url, artifact, headers, False)

success = self._check_http_response(resp)
try:
success = self._post_request_retry(artifact_url, artifact, headers, False)
except OutputRequestFailure:
success = False

return self._log_status(success)
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

@mock_s3
@mock_kms
@patch('stream_alert.alert_processor.outputs.output_base.OutputDispatcher.MAX_RETRY_ATTEMPTS', 1)
class TestPhantomOutput(object):
"""Test class for PhantomOutput"""
DESCRIPTOR = 'unit_test_phantom'
Expand Down Expand Up @@ -113,6 +114,24 @@ def test_dispatch_check_container_error(self, post_mock, get_mock, log_mock):

log_mock.assert_called_with('Failed to send alert to %s', self.SERVICE)

@patch('logging.Logger.error')
@patch('requests.get')
@patch('requests.post')
def test_dispatch_check_container_no_response(self, post_mock, get_mock, log_mock):
"""PhantomOutput - Dispatch Failure, No Response Container Check"""
# _check_container_exists
get_mock.return_value.status_code = 200
get_mock.return_value.json.return_value = {}
# _setup_container
post_mock.return_value.status_code = 200
post_mock.return_value.json.return_value = {}

assert_false(self._dispatcher.dispatch(descriptor=self.DESCRIPTOR,
rule_name='rule_name',
alert=get_alert()))

log_mock.assert_called_with('Failed to send alert to %s', self.SERVICE)

@patch('logging.Logger.error')
@patch('requests.get')
@patch('requests.post')
Expand Down

0 comments on commit 1c00060

Please sign in to comment.