-
Notifications
You must be signed in to change notification settings - Fork 187
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
Replace batcher with S3 inventory #131
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.
a handful of comments but LGTM!
- mypy lambda_functions rules *.py --disallow-untyped-defs --ignore-missing-imports --warn-unused-ignores | ||
- bandit -r . # Configuration in .bandit | ||
- sphinx-build -W docs/source docs/build | ||
- tests/ci_tests.sh |
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 idea!
cli/__init__.py
Outdated
@@ -0,0 +1,2 @@ | |||
"""BinaryAlert release version""" | |||
VERSION = '1.1.0' |
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 think the proper way to version is to use the dunder __version__
attribute. Reference: https://www.python.org/dev/peps/pep-0396/
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, good call! 📞
cli/config.py
Outdated
try: | ||
self.carbon_black_url = get_input('CarbonBlack URL', self.carbon_black_url) | ||
break | ||
except InvalidConfigError as error: |
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.
It looks list there are a handful of places where you catch InvalidConfigError
when calling get_input
.. however, get_input
would never raise this exception 🤔 . am I missing something?
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 property assignment self.carbon_black_url = ...
goes through a setter method with validation logic
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.
right yeah sorry I realized that after I left this comment - feel free to ignore :)
cli/config.py
Outdated
except InvalidConfigError as error: | ||
print('ERROR: {}'.format(error)) | ||
|
||
while True: # Get name prefix. |
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.
couldn't the get_input
function also take optional values that are acceptable (and a description of what should be entered) and do the looping? just wondering because it appears you repeat this same logic a bunch when calling this method
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 idea! Yeah, the looping logic always annoyed me. It's a little weird, because there are different use cases and validation paths, but I managed to get the loop into get_input
like you suggested
InvalidConfigError: If any config variable has an invalid value. | ||
""" | ||
# Go through the internal setters which have the validation logic. | ||
self.aws_account_id = self.aws_account_id |
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 was super confused by this, but cool idea!
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.
If it's confusing, we could actually remove this validation check, it isn't really necessary
cli/config.py
Outdated
break | ||
else: | ||
print('ERROR: Please enter exactly "yes" or "no"') | ||
self.enable_carbon_black_downloader = 1 if enable_downloader == 'yes' else 0 |
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 assume there's a reason for the int here instead of a boolean value? hcl limitation?
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.
cli/exceptions.py
Outdated
|
||
class ManagerError(Exception): | ||
"""Top-level exception for Manager errors.""" | ||
pass |
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.
pass
is unnecessary when a docstring is use in an exception (pro tip: omitting it may improve your test coverage 😉 )
cli/manager.py
Outdated
inv_prefix = 'inventory/{}/EntireBucketDaily'.format(bucket.name) | ||
|
||
# Check for each day, starting today, up to 8 days ago | ||
for days_ago in range(0, 9): |
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 0 here I don't think.. also is the days
range something that could be configurable? I'm thinking it the case that you have a bucket that hasn't had new objects added in a while (so 2 weeks).. it could still have a valid manifest for the objects that exist, outside of this 8 day range.
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 point - range(9)
is exactly the same thing, change made.
S3 inventory runs every single day, regardless of whether new objects were added (tested and confirmed). In fact, I'm going to reduce this to 3 days (there should be at most 48 hours between successive inventory reports)
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.
sounds good! thanks for clarifying :)
|
||
DISPATCH_SOURCE = os.path.join(LAMBDA_DIR, 'dispatcher', 'main.py') | ||
DISPATCH_ZIPFILE = 'lambda_dispatcher' | ||
Libraries are installed in the package root and source code is installed to mirror the repo |
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.
++
to: @ryandeivert
cc: @airbnb/binaryalert-maintainers
size: large
resolves: #18
resolves: #46
resolves: #120
Background
The batcher function for retroactive analysis is error-prone (especially timeouts), can run for a very long time, and can be invoked multiple times, essentially DOSing your BinaryAlert deployment.
Changes
Lambda Functions
if __package__
import logicTerraform
CLI
purge_queue
: Purge the analyzer queue, immediately stopping any retroactive analysisretro_fast
: Add all objects from the latest S3 inventory manifest onto the analysis queueretro_slow
: Enumerate the bucket manually (like the batcher did before)deploy
command no longer starts a retroactive scanmanage.py
script has been separated into different components incli/
Tests
.travis.yml
have been moved to a standalone scripttests/ci_tests.sh
. This makes it easier for contributors to test their changes in exactly the same way that Travis willtests/
from coverage measurement. Adding unit tests artificially inflated the coverage measure due to the extra lines of code.Testing
Note that reading from the inventory (
retro_fast
) enqueues objects many times faster than enumerating them manually. It takes about 80 seconds to enumerate a million objects (with 32 processes on my laptop). This means a multi-million-object bucket will take a few minutes to enqueue for retroactive analysis, but IMO this is much better (and cheaper) than running the batcher Lambda function for several hours.Reviewers
Apologies: this change is bigger than I intended - the CLI was becoming painfully difficult to manage. Most of
cli/config.py
andcli/manager.py
(and their unit tests) are unchanged, except for the addition of inventory / queueing logic.