Skip to content

Commit

Permalink
Merge pull request #608 from 0xdabbad00/spiper-support_komand
Browse files Browse the repository at this point in the history
Komand support added
  • Loading branch information
jacknagz authored Feb 27, 2018
2 parents d9763f6 + b010778 commit 4a43f09
Show file tree
Hide file tree
Showing 8 changed files with 166 additions and 3 deletions.
3 changes: 3 additions & 0 deletions conf/outputs.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
"aws-s3": {
"sample-bucket": "sample.bucket.name"
},
"komand": [
"sample-integration"
],
"pagerduty": [
"sample-integration"
],
Expand Down
3 changes: 2 additions & 1 deletion docs/source/outputs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Out of the box, StreamAlert supports:

* **AWS Lambda**
* **AWS S3**
* **Komand**
* **PagerDuty**
* **Phantom**
* **Slack**
Expand All @@ -31,7 +32,7 @@ Configuration
Adding a new configuration for a currently supported service is handled using ``manage.py``:

- ``python manage.py output new --service <SERVICE_NAME>``
- ``<SERVICE_NAME>`` above should be one of the following supported service identifiers: ``aws-lambda``, ``aws-s3``, ``pagerduty``, ``phantom``, or ``slack``
- ``<SERVICE_NAME>`` above should be one of the following supported service identifiers: ``aws-lambda``, ``aws-s3``, ``komand``, ``pagerduty``, ``phantom``, or ``slack``

For example:
- ``python manage.py output new --service slack``
Expand Down
2 changes: 1 addition & 1 deletion docs/source/rules.rst
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ outputs

``outputs`` define where the alert should be sent to if the return value of a rule is ``True``. Your rule(s) must define at least one output.

StreamAlert supports sending alerts to PagerDuty, Slack, Amazon S3 and Phantom.
StreamAlert supports sending alerts to PagerDuty, Slack, Amazon S3, Komand and Phantom.

An alert can be sent to multiple destinations.

Expand Down
2 changes: 1 addition & 1 deletion manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ def _add_output_subparser(subparsers):
output_parser.add_argument(
'--service',
choices=[
'aws-firehose', 'aws-lambda', 'aws-s3', 'jira', 'pagerduty', 'pagerduty-v2',
'aws-firehose', 'aws-lambda', 'aws-s3', 'jira', 'komand', 'pagerduty', 'pagerduty-v2',
'pagerduty-incident', 'phantom', 'slack', 'github'
],
required=True,
Expand Down
77 changes: 77 additions & 0 deletions stream_alert/alert_processor/outputs/komand.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
"""
Copyright 2017-present, Airbnb Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
from collections import OrderedDict

from stream_alert.alert_processor import LOGGER
from stream_alert.alert_processor.outputs.output_base import (
OutputDispatcher,
OutputProperty,
StreamAlertOutput
)


@StreamAlertOutput
class KomandOutput(OutputDispatcher):
"""KomandOutput handles all alert dispatching for Komand"""
__service__ = 'komand'

@classmethod
def get_user_defined_properties(cls):
"""Get properties that must be asssigned by the user when configuring a new Komand
output. This should be sensitive or unique information for this use-case that needs
to come from the user.
Every output should return a dict that contains a 'descriptor' with a description of the
integration being configured.
Returns:
OrderedDict: Contains various OutputProperty items
"""
return OrderedDict([
('descriptor',
OutputProperty(description='a short and unique descriptor for this '
'Komand integration')),
('komand_auth_token',
OutputProperty(description='the auth token for this Komand integration. '
'Example: 00000000-0000-0000-0000-000000000000',
mask_input=True,
cred_requirement=True)),
('url',
OutputProperty(description='the endpoint url for this Komand integration. '
'Example: https://YOUR-KOMAND-HOST.com/v2/triggers/GUID/events',
mask_input=True,
cred_requirement=True))
])

def dispatch(self, **kwargs):
"""Send alert to Komand
Args:
**kwargs: consists of any combination of the following items:
descriptor (str): Service descriptor (ie: slack channel, pd integration)
alert (dict): Alert relevant to the triggered rule
"""
creds = self._load_creds(kwargs['descriptor'])
if not creds:
return self._log_status(False)

headers = {'Authorization': creds['komand_auth_token']}

LOGGER.debug('sending alert to Komand')

resp = self._post_request(creds['url'], {'data': kwargs['alert']}, headers, False)
success = self._check_http_response(resp)
return self._log_status(success)
7 changes: 7 additions & 0 deletions stream_alert_cli/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,13 @@ def setup_outputs(self, alert):
lambda_function = parts[-1]
helpers.create_lambda_function(lambda_function,
self.region)
elif service == 'komand':
output_name = '{}/{}'.format(service, descriptor)
creds = {'komand_auth_token': '00000000-0000-0000-0000-000000000000',
'url': 'komand.foo.bar'}
helpers.put_mock_creds(output_name, creds, self.secrets_bucket,
self.region, self.kms_alias)

elif service == 'pagerduty':
output_name = '{}/{}'.format(service, descriptor)
creds = {'service_key': '247b97499078a015cc6c586bc0a92de6'}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"""
Copyright 2017-present, Airbnb Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
# pylint: disable=protected-access,attribute-defined-outside-init
from mock import patch
from moto import mock_s3, mock_kms
from nose.tools import assert_false, assert_true

from stream_alert.alert_processor.outputs.komand import KomandOutput
from stream_alert_cli.helpers import put_mock_creds
from tests.unit.stream_alert_alert_processor import CONFIG, FUNCTION_NAME, KMS_ALIAS, REGION
from tests.unit.stream_alert_alert_processor.helpers import get_alert, remove_temp_secrets


@mock_s3
@mock_kms
@patch('stream_alert.alert_processor.outputs.output_base.OutputDispatcher.MAX_RETRY_ATTEMPTS', 1)
class TestKomandutput(object):
"""Test class for KomandOutput"""
DESCRIPTOR = 'unit_test_komand'
SERVICE = 'komand'
CREDS = {'url': 'http://komand.foo.bar',
'komand_auth_token': 'mocked_auth_token'}

def setup(self):
"""Setup before each method"""
self._dispatcher = KomandOutput(REGION, FUNCTION_NAME, CONFIG)
remove_temp_secrets()
output_name = self._dispatcher.output_cred_name(self.DESCRIPTOR)
put_mock_creds(output_name, self.CREDS, self._dispatcher.secrets_bucket, REGION, KMS_ALIAS)

@patch('logging.Logger.info')
@patch('requests.post')
def test_dispatch_existing_container(self, post_mock, log_mock):
"""KomandOutput - Dispatch Success"""
post_mock.return_value.status_code = 200

assert_true(self._dispatcher.dispatch(descriptor=self.DESCRIPTOR,
alert=get_alert()))

log_mock.assert_called_with('Successfully sent alert to %s', self.SERVICE)

@patch('logging.Logger.error')
@patch('requests.post')
def test_dispatch_container_failure(self, post_mock, log_mock):
"""KomandOutput - Dispatch Failure"""
post_mock.return_value.status_code = 400
json_error = {'message': 'error message', 'errors': ['error1']}
post_mock.return_value.json.return_value = json_error

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

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

@patch('logging.Logger.error')
def test_dispatch_bad_descriptor(self, log_error_mock):
"""KomandOutput - Dispatch Failure, Bad Descriptor"""
assert_false(self._dispatcher.dispatch(descriptor='bad_descriptor',
alert=get_alert()))

log_error_mock.assert_called_with('Failed to send alert to %s', self.SERVICE)
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ def test_output_loading():
'aws-s3',
'github',
'jira',
'komand',
'pagerduty',
'pagerduty-v2',
'pagerduty-incident',
Expand Down

0 comments on commit 4a43f09

Please sign in to comment.