-
Notifications
You must be signed in to change notification settings - Fork 334
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[lambda][output][cli] modular outputs refactor #97
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good start!
|
||
|
||
class OutputBase(object): | ||
"""StreamOutputBase is the base class to handle routing alters to outputs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
StreamOutputBase should be OutputBase in this comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: routing alerts*
I would add some more background on how to use this base class, along with going into the class variables just below this comment. Also describe the public methods and attributes available
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed base name and fixed typo. working on documentation also
alert [dict]: The alert relevant to the triggered rule | ||
""" | ||
creds = self._load_creds(descriptor) | ||
message = "StreamAlert Rule Triggered - {}".format(rule_name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: no need for double quotes
""" | ||
creds = self._load_creds(descriptor) | ||
message = "StreamAlert Rule Triggered - {}".format(rule_name) | ||
values_json = json.dumps({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit 2: double quote usage in this variable
|
||
Args: | ||
cred_location [string]: tmp path on disk to to store the encrypted blob | ||
descriptor [string]: service destination (ie: slack channel, pd integration) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a Returns:
description here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added.
""" | ||
LOGGER.error('unable to send alert for service %s', self.__service__) | ||
|
||
def push_creds_to_s3(self, user_input): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't this be in the cli
library?
return resp and (200 <= resp.getcode() <= 299) | ||
|
||
@classmethod | ||
def get_user_defined_properties(cls): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you add more background on usage here?
pass | ||
|
||
@classmethod | ||
def get_default_properties(cls): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also add usage here, what should the orderdict contain?
|
||
def dispatch(self, descriptor, rule_name, alert): | ||
"""Send alerts to the given service. This base class just | ||
logs an error if not implemented on the inheriting class |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as mentioned in the class declaration, we should enforce it with ABC
cred_requirement=True)) | ||
]) | ||
|
||
def dispatch(self, descriptor, _, alert): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we just use kwargs instead of negating certain positional arguments with _
?
url = os.path.join(creds['url']) | ||
|
||
slack_message = json.dumps({'text': '```{}```'.format( | ||
json.dumps(alert, indent=4) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work! I love the generic base class for outputs, that's exactly what I envisioned.
Overall:
- Use
logging.exception
when appropriate - Be careful that the docstring exactly matches the actual arguments and return types
stream_alert/alert_processor/main.py
Outdated
|
||
def run(self, alerts): | ||
"""Send an Alert to its described outputs. | ||
logging.error('an error occurred while decoding message to JSON: %s', err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use logging.exception
(which is basically a wrapper around logging.error
that automatically adds the exception context). Also use the LOGGER
object?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes to all this - good catches
stream_alert/alert_processor/main.py
Outdated
def run(self, alerts): | ||
"""Send an Alert to its described outputs. | ||
logging.error('an error occurred while decoding message to JSON: %s', err) | ||
return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we not want to bubble this error all the way up so that the Lambda invocation fails?
stream_alert/alert_processor/main.py
Outdated
Group alerts into a dictionary by their rule name, with | ||
an array of alerts as the value. | ||
if not 'default' in alert: | ||
logging.info('malformed alert: %s', alert) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logging.warn
stream_alert/alert_processor/main.py
Outdated
{ | ||
'default': [alert] | ||
} | ||
Args: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The args docstring (alerts
) does not match the actual arguments (message
, context
)
stream_alert/alert_processor/main.py
Outdated
try: | ||
output_dispatcher.dispatch(descriptor, rule_name, alert) | ||
except BaseException as err: | ||
LOGGER.error('an error occurred while sending alert to %s: %s', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LOGGER.exception('an error occurred while sending alert to %s', service)
The exception context will be logged automatically
stream_alert_cli/outputs.py
Outdated
if service in config and props['descriptor'].value in config[service]: | ||
LOGGER_CLI.error('this descriptor is already configured for %s. ' | ||
'please select a new and unique descriptor', service) | ||
return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return False
?
stream_alert_cli/package.py
Outdated
@@ -19,9 +19,9 @@ | |||
import base64 | |||
import hashlib | |||
import os | |||
import pip |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe pip
is a non-standard package (doesn't come with Python), so it would actually go after boto3.
Not sure though
return user_input(requested_info, mask) | ||
else: | ||
while not response: | ||
response = getpass(prompt=prompt) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
++ for hidden credential input 🔑
terraform/main.tf
Outdated
// export AWS_SECRET_ACCESS_KEY="secret-key" | ||
// export AWS_DEFAULT_REGION="region" | ||
// export AWS_SECRET_ACCESS_KEY="secret-key" | ||
// export AWS_DEFAULT_REGION="region" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Align the exports. Also, why not put the region into the provider
block? Then you could make it a terraform variable. The only reason the access key isn't a variable is to discourage people from saving it on disk
{ | ||
"Action": [ | ||
"s3:GetObject", | ||
"s3:ListBucket" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you actually need s3:ListBucket
. Unless you're literally paginating over all the items in the bucket, GetObject
should suffice
ce59f49
to
9c913d2
Compare
…n of new services and configuring integrations from the cli
…ode in the main handler
… the lambda function itself
…thod implementation enforcement
ac587cc
to
cacfd95
Compare
[cli] restricting colon characters along with spaces in user input for service descriptors [cli] migrating some code from the runner to the new outputs file for the cli [rules][testing] updating rules to conform to new outputs configuration style. also updating tests to go with this change [lambda][alert] remove encrypted_credentials folder [tf] fix bug in streamalert.secrets iam policy [lambda][rule] send a single alert to SNS without wrapping in a list [lambda] bug fixes: make it work * load the outputs.json config * package in the conf directory * load the conf * read s3 buckets from the conf * fix bugs in request helper * more [lambda][output] masking slack url during input and restricting the use of colons (:) in unmasked input [lambda][output][cli] fixing various nits
cacfd95
to
3afa054
Compare
to @airbnb/streamalert-maintainers
size: large
resolves: #6
Changes
stream_alert_cli.py
can now configure new integrations for supported servicesaws-s3
,slack
,pagerduty
,phantom
OutputBase
class handles all shared operations for each servicesOutputBase
(such asSlackOutput
) are designed to handle service-specific takes such as dispatching the actual alertoutputs.json
file in root config is currently an empty json map, but is used to house all new output configurations added by the user through the cliencrypted_credentials
directory is deprecated and will be going away in a future commitWhy