-
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
[core] drop sns publish for lambda invoke #225
[core] drop sns publish for lambda invoke #225
Conversation
…or of direct lambda invocation to the alert processor
* Optionally create an SNS topic for receiving metric alarms * Optionall accept an existing SNS topic to receive metric alarms * Update documentation on usage * Unit tests
…lways go to $LATEST lambda
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.
A couple inline comments
data) | ||
return | ||
|
||
if response['ResponseMetadata']['HTTPStatusCode'] != 202: |
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.
Is this block slightly repetitive to the preceding one?
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 be more specific? What's repetitive about it (and are you referring to the try/except above?)?
If so, I think an HTTP response of non-202 could possibly occur even if there is no ClientError occurred during invocation. I could also be off on that.. We could also add FunctionError
to this error logging.
stream_alert/alert_processor/main.py
Outdated
continue | ||
|
||
status_values.extend(run(loaded_sns_message, region, function_name, config)) | ||
# Yield back the current status to the caller |
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 this comment be a little more descriptive?
stream_alert/alert_processor/main.py
Outdated
} | ||
} | ||
} | ||
|
||
region [string]: the AWS region being used |
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.
let's update this to: The AWS region of the currently executing Lambda function
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.
This will be awesome!
if not set(alert['metadata'].keys()) == metadata_keys: | ||
LOGGER.error('The value of the \'metadata\' key must be a map (dict) ' | ||
'that contains the following keys: %s', | ||
', '.join('\'{}\''.format(key) for key in metadata_keys)) |
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.
All of these comparisons in this file test for set equality (the keys must match the hard-coded set), but the errors messages say it must contain such and such keys.
Just to mitigate potential confusion, can we either update the error messages to indicate it must contain exactly the required keys, or else update the tests to check for a set inclusion instead of equality?
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.
@austinbyers making the logger messages indication that only those keys should be included. would rather have a strict validation of input instead of a loose validation.
LOGGER.error('The value of the \'%s\' key within \'%s\' must be ' | ||
'a string (str).', entry, key) | ||
valid = False | ||
continue |
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.
This is redundant (at the end of the inner for loop)
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.
thanks! removed.
LOGGER.error('The value of each entry in the \'outputs\' list ' | ||
'must be a string (str).') | ||
valid = False | ||
continue |
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.
Redundant
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.
thanks! removed.
LOGGER.error('The value of the \'%s\' key must be a string (str), not %s', | ||
key, type(alert['metadata'][key])) | ||
valid = False | ||
continue |
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.
Technically redundant, but if you want to keep this one to be consistent with all the other checks, that's fine
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.
thanks! removed for brevity.
stream_alert/alert_processor/main.py
Outdated
LOGGER.error('An error occurred while decoding message to JSON: %s', err) | ||
continue | ||
# Return the current list of statuses back to the caller | ||
return [status for status in run(event, region, function_name, config)] |
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.
Would return list(run(event, region, function_name, config))
do the trick?
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.
same effect yes. I'll update with explicit list casting.
resource "aws_sns_topic_subscription" "input_topic_subscriptions" { | ||
count = "${length(var.input_sns_topics)}" | ||
topic_arn = "${element(var.input_sns_topics, count.index)}" | ||
endpoint = "${aws_lambda_function.streamalert_rule_processor.arn}:production" | ||
protocol = "lambda" | ||
} | ||
|
||
// Lambda Permission: Allow SNS to invoke the Rule Processor |
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'm confused - how did we not have this before? SNS is currently alerting the rule processor just fine...
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.
We had it, it just moved into this file from 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.
👍
invalid_metadata_non_string['metadata']['type'] = 4.5 | ||
|
||
# Test with invalid metadata non-string value | ||
assert_false(validate_alert(invalid_metadata_non_string)) |
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 we break each of these up into smaller unit tests? Each assert
condition with a comment should be its own self-contained test.
import json | ||
import logging | ||
import sys | ||
|
||
import boto3 | ||
from botocore.exceptions import ClientError | ||
|
||
_SNS_MAX_SIZE = (256*1024) |
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 is still a maximum Lambda invocation size (6MB for asynchronous requests), but I don't think we'll be anywhere close to that limit. Just something to keep in mind
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.
Adding a comment to the PR body for a future consideration.
@jacknagz @austinbyers PTAL at new commit and comments |
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.
Thanks for doing this!
stream_alert/alert_processor/main.py
Outdated
LOGGER.error('An error occurred while decoding message to JSON: %s', err) | ||
continue | ||
# Return the current list of statuses back to the caller | ||
return list(status for status in run(event, region, function_name, config)) |
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.
You can simplify this further:
return list(run(event, region, function_name, config))
list
will automatically transform the generator into a list by iterating through it; you don't have to manually iterate
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.
ah sorry overlooked that bit.
resource "aws_sns_topic_subscription" "input_topic_subscriptions" { | ||
count = "${length(var.input_sns_topics)}" | ||
topic_arn = "${element(var.input_sns_topics, count.index)}" | ||
endpoint = "${aws_lambda_function.streamalert_rule_processor.arn}:production" | ||
protocol = "lambda" | ||
} | ||
|
||
// Lambda Permission: Allow SNS to invoke the Rule Processor |
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.
👍
'"metadata": {"source": {"service": "payload_service_01", ' \ | ||
'"entity": "payload_entity_01"}, "rule_name": "test_rule_01", ' \ | ||
'"type": "payload_type_01", "log": "payload_data_01", ' \ | ||
'"outputs": "rule.outputs_01"}}') |
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.
You don't need the line continuation markers (\
) (this is discouraged by Google Python style guide); Python has implicit string joining.
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.
not in py 2 :) you need to wrap in parenths for that to be effective, but I can add that
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.
Oh yes, you always need the parens (in both py2 and py3). Good catch
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.
@austinbyers fixed in latest commit.. as a param in a function call it looks like it doesn't need to be encapsulated
d0de948
to
5c54db5
Compare
to @austinbyers
cc @jacknagz , @airbnb/dashed-maintainers
size: large
resolves: #189
Why
Changes in collab branch with @jacknagz
event
parameter of the lambda handler.Fixes
pip
as a module broke the CLI logging. The fix is in this commit and is described here.To consider: