Skip to content
This repository was archived by the owner on Sep 17, 2021. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
c9222ef
Merge pull request #1 from Netflix/develop
itsnotapt Jul 1, 2016
08d3f81
Reports on missing policies for S3.
Jul 1, 2016
73c0471
Add support for custom watchers and auditors
May 17, 2016
ce98b4f
Add new watchers
Apr 7, 2016
34037fc
Auditor dependency and link support
May 17, 2016
d75b0ce
Merge branch 'develop' of github.com:crruthe/security_monkey into dev…
Oct 6, 2016
5932a90
Fixed a few urls.
Oct 6, 2016
d54af80
Merge pull request #425 from crruthe/fix-urls
Oct 11, 2016
37df5b2
Added "route53domains:getdomaindetail" to permissions doc.
Oct 7, 2016
9bc1b79
OS X Install doc updates for El Capitan and higher.
Sep 30, 2016
46e94e2
Fix for ARN parsing of cloudfront ARNs.
Oct 13, 2016
86bff92
Changed the module name from elb to elasticsearch_service
Oct 14, 2016
17e96f2
Merge pull request #428 from nagwww/develop
mikegrima Oct 14, 2016
68ada98
Merge pull request #424 from mikegrima/installdoc_fix
Oct 17, 2016
47abb21
Merge pull request #426 from mikegrima/r53domains_permfix
Oct 17, 2016
774e7aa
Merge pull request #427 from mikegrima/cloudfront_arn
Oct 17, 2016
98547b1
Removed s3 ARN check for ElasticSearch Service.
Oct 17, 2016
acf0929
Merge pull request #431 from mikegrima/es-fix
Oct 17, 2016
24561bc
Resolve conflicts between develop and auditor_dependencies
Oct 14, 2016
8aa5e93
Fix for _find_dependent_monitors
Sep 22, 2016
b13c558
Added support for SSO OneLogin (#420)
itsnotapt Oct 18, 2016
05ba38a
Fixing bug where SSO arguments weren't passed along for branded sso. …
Oct 27, 2016
061262e
Add pagination for whitelist and ignore list (#432) 📖
robertoriv Oct 27, 2016
c15bea3
Quick fix - sudo python setup.py install (#438) 📌
AngeloCiffa Nov 8, 2016
19cca1d
Merge branch 'auditor_dependencies' of git://github.com/Bridgewater/s…
Nov 8, 2016
385ae45
Updating config_recorder to use iter_account_region instead of hardco…
Nov 8, 2016
2f7c9e6
Merge branch 'Bridgewater-auditor_dependencies' into develop
Nov 8, 2016
1f42816
feature/docker (#433) 🐳
Nov 10, 2016
6848e71
Add support for custom account metadata (#408) 📃
zollman Nov 15, 2016
c4772c6
Replacing botor lib with Netflix cloudaux. (#439) 🌪
Nov 15, 2016
714e46e
Auditor ChangeItems now receive ARN (#441) 🔨
Nov 15, 2016
6e6917c
Adding/moving badges on README.rst
Nov 15, 2016
c515af5
[secmonkey] Adds exception logging listener for appscheduler
Sep 12, 2016
4a4bc13
Fix exception logging in store_exception
Sep 22, 2016
5f7ecc9
Updating record_exception decorator to pop relevant kwargs before cal…
Nov 16, 2016
26f322a
Views now sort configs for the web ui.
Nov 16, 2016
e40cc8a
Adding optional arg to record_exception decorator
Nov 16, 2016
4b948f8
Adding index to region. Dropping unused item.cloud. (#442) 📇
Nov 17, 2016
eb9288b
Merge pull request #448 from Bridgewater/7876_store_exception_bug
mikegrima Nov 17, 2016
7f8c7f7
Merge pull request #444 from Bridgewater/7871_appscheduler_logging
mikegrima Nov 17, 2016
37393df
Moved test & onelogin requirements to the setup.py extras_require sec…
Nov 18, 2016
6f1e49b
[secmonkey] Fix item 'first_seen' query (#446) 👓
zollman Nov 18, 2016
798676e
[secmonkey] Refactor rdsdbcluster array params (#447) 📶
zollman Nov 18, 2016
99d5c9e
Make misfire grace time and reporter start time configurable (#445) 🕰 🔥
zollman Nov 18, 2016
43e40de
Removing reference to the removed item.cloud field.
scriptsrc Nov 18, 2016
fd464bd
[WIP] Coverage (#451) 👖👕
Nov 18, 2016
ca1f52a
Adding coveralls badge to README.rst
Nov 18, 2016
3184ef3
Organizing badges into master/dev branches
Nov 18, 2016
3da5d10
Adding tests for the policydiff module. (#452) 💉
Nov 20, 2016
a088c7e
Refactoring s3 watcher to use Netflix CloudAux (#449) ⛈🌪
Nov 21, 2016
ea952b0
Fixing two policy diff cases. (#453) 🛁
Nov 21, 2016
0c78315
Updated S3 Permissions to reflect latest changes to cloudaux.
Nov 29, 2016
375b367
Merge pull request #454 from mikegrima/s3_permissions
mikegrima Nov 29, 2016
508aa67
[secmonkey] Add dashboard (#455) 📈
zollman Dec 1, 2016
11896c7
Increase issue note size (#456) 🎵
zollman Dec 1, 2016
3cfc540
Preparation for v0.8.0
Dec 2, 2016
7a40260
S3 Analytics support (#460)
mikegrima Dec 3, 2016
18b9685
Added cloudtrail multiregion audit check (#459) 🗺
nagwww Dec 3, 2016
587f460
New S3 Permissions and Auditor Fixes (#461)
mikegrima Dec 5, 2016
499e638
Fixing IAM Role/IAM User auditors for new cloudaux format. (#462)
Dec 5, 2016
fa49ddb
Updating ephemerals for IAM User. (#463)
Dec 5, 2016
e861f36
Moving the Search page back to default and creating a hyperlink to th…
Dec 5, 2016
31de86f
Add support for filtering by item score. (#467) 💯
Dec 7, 2016
1c32af8
Further fixing the IAM User auditor to work with the new IAM User for…
Dec 7, 2016
83ecbb1
Potentially fixing the kms principal-service problem. Issue #468 (#471)
Dec 7, 2016
3174acd
Added cloudtrail status to watcher. Generates an audit issue when clo…
nagwww Dec 8, 2016
a3dde82
Updating KMS Auditor to extract AWS account IDs from the condition bl…
Dec 8, 2016
0371c89
Updating UI Reports Dropdown (#473) ☔
Dec 8, 2016
265ac92
Adding cloudtrail:gettrailstatus to docs (#474)
Dec 8, 2016
ff0517c
Update aws_accounts.json (#476)
Dec 9, 2016
4042ecd
Fixing manage.py::amazon_accounts() and adding delete_unjustified_iss…
Dec 29, 2016
a83fea9
Making gunicorn an optional import to help support dev on Windows. (#…
Dec 29, 2016
da8c81e
Fixing a couple dart warnings. (#481)
Dec 29, 2016
3b4da13
Replacing Flask-Security with Flask-Security-Fork. Removing some expl…
Dec 30, 2016
198ed04
Fixes issue 477. Replaces explicit check for {} with a simple bool ch…
Dec 31, 2016
5933eba
Bumping jinja2 to >= 2.8.1. We should not be impacted by the format s…
Jan 4, 2017
0ef6596
Robertoriv feature/check assume role from unknown (#485)
Jan 4, 2017
00ce338
Adds upgraded setuptools to Dockerfile. Fixes (#486) (#487)
hyperbolist Jan 4, 2017
8b0c4cd
Fixing a bug where we stopped raising an issue when we could not obta…
Jan 5, 2017
46b7309
Adding ephemeral to rds db instance. Should fix issue #421. (#490)
Jan 5, 2017
1ad95ef
Adding a new RDS DB Cluster ephemeral (#491)
Jan 5, 2017
d21c5d7
Updating S3 Auditor to use ARN class (#492)
Jan 5, 2017
4fae5af
Fixing typo in dart files. This fixes the web UI.
Jan 5, 2017
eb3faa5
Refactoring to work with new Flask-WTF. Closes Issue #494. (#495) ಠ_ಠ
Jan 10, 2017
7a662de
Initial attempt at Win10 development instructions (#493) 💻
Jan 10, 2017
4ef5024
Bumping cloudaux to 1.0.7
scriptsrc Jan 13, 2017
3d0e1d5
Updating changelog in preparation of v0.8.0 release
Jan 13, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
<td>{{auditoritem.issue}}</td>
<td>{{auditoritem.account}}</td>
<td>{{auditoritem.technology}}</td>
<td><a href="#/issues/-/{{url_encode(auditoritem.technology)}}/{{url_encode(auditoritem.account)}}/-/True/{{url_encode(auditoritem.issue)}}/1/25">{{auditoritem.count}}</a></td>
<td><a href="#/issues/-/{{url_encode(auditoritem.technology)}}/{{url_encode(auditoritem.account)}}/-/-/True/{{url_encode(auditoritem.issue)}}/1/25">{{auditoritem.count}}</a></td>
<td ng-if="auditoritem.disabled==true"><b>TRUE</b></td>
<td ng-if="auditoritem.disabled==false">false</td>
<td ng-if="us.hasRole('Justify')">
Expand Down
7 changes: 4 additions & 3 deletions docs/development.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ Sample Watcher structure::
# Look up relevant items, convert to list of SampleItem's, return list

class SampleItem(ChangeItem):
def __init__(self, account=None, name=None, config={}):
def __init__(self, account=None, name=None, region=None, config={}):
super(SampleItem, self).__init__(
index=IAMGroup.index,
region='universal',
index=Sample.index,
region=region,
account=account,
name=name,
new_config=config)
Expand Down Expand Up @@ -153,3 +153,4 @@ Typically, if an audit issue is dependent on another one, a the two should be li
.. image:: images/linked_issue.png

This can be achieved by the `Auditor <../../security_monkey/auditor.py>`_ link_to_support_item_issues() method.

27 changes: 7 additions & 20 deletions manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,16 @@ def drop_db():
@manager.option('-a', '--accounts', dest='accounts', type=unicode, default=u'all')
def run_change_reporter(accounts):
""" Runs Reporter """
account_names = __parse_accounts__(accounts)
account_names = _parse_accounts(accounts)
sm_run_change_reporter(account_names)


@manager.option('-a', '--accounts', dest='accounts', type=unicode, default=u'all')
@manager.option('-m', '--monitors', dest='monitors', type=unicode, default=u'all')
def find_changes(accounts, monitors):
""" Runs watchers """
monitor_names = __parse_tech_names__(monitors)
account_names = __parse_accounts__(accounts)
monitor_names = _parse_tech_names(monitors)
account_names = _parse_accounts(accounts)
sm_find_changes(account_names, monitor_names)


Expand All @@ -66,8 +66,8 @@ def find_changes(accounts, monitors):
@manager.option('-r', '--send_report', dest='send_report', type=bool, default=False)
def audit_changes(accounts, monitors, send_report):
""" Runs auditors """
monitor_names = __parse_tech_names__(monitors)
account_names = __parse_accounts__(accounts)
monitor_names = _parse_tech_names(monitors)
account_names = _parse_accounts(accounts)
sm_audit_changes(account_names, monitor_names, send_report)


Expand All @@ -76,8 +76,8 @@ def audit_changes(accounts, monitors, send_report):
@manager.option('-o', '--outputfolder', dest='outputfolder', type=unicode, default=u'backups')
def backup_config_to_json(accounts, monitors, outputfolder):
""" Saves the most current item revisions to a json file. """
monitor_names = __parse_tech_names__(monitors)
account_names = __parse_accounts__(accounts)
monitor_names = _parse_tech_names(monitors)
account_names = _parse_accounts(accounts)
sm_backup_config_to_json(account_names, monitor_names, outputfolder)


Expand Down Expand Up @@ -199,19 +199,6 @@ def create_user(email, role):
db.session.add(user)
db.session.commit()

def __parse_tech_names__(tech_str):
if tech_str == 'all':
return watcher_registry.keys()
else:
return tech_str.split(',')

def __parse_accounts__(account_str):
if account_str == 'all':
accounts = Account.query.filter(Account.third_party==False).filter(Account.active==True).all()
accounts = [account.name for account in accounts]
return accounts
else:
return account_str.split(',')

def _parse_tech_names(tech_str):
if tech_str == 'all':
Expand Down
2 changes: 1 addition & 1 deletion migrations/versions/ad23a56abf25_.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

# revision identifiers, used by Alembic.
revision = 'ad23a56abf25'
down_revision = '0ae4ef82b244'
down_revision = '1a863bd1acb1'

from alembic import op
import sqlalchemy as sa
Expand Down
4 changes: 2 additions & 2 deletions security_monkey/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ def decorated_function(*args, **kwargs):
try:
(role, regions) = get_regions(account, service_name)
except Exception as e:
exc = BotoConnectionIssue(str(e), index, account, None)
exc = BotoConnectionIssue(str(e), index, account.name, None)
exception_map[(index, account)] = exc
return item_list, exception_map

Expand All @@ -142,7 +142,7 @@ def decorated_function(*args, **kwargs):
itm, exc = f(*args, **kwargs)
item_list.extend(itm)
exception_map.update(exc)
return item_list, exception_map
return item_list, exception_map
return decorated_function
return decorator

Expand Down
2 changes: 1 addition & 1 deletion security_monkey/jirasync.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def add_or_update_issue(self, issue, technology, account, count):
jql = 'project={0} and summary~"{1}"'.format(self.project, summary_search)
issues = self.client.search_issues(jql)

url = "{0}/#/issues/-/{1}/{2}/-/True/{3}/1/25".format(self.url, technology, account, urllib.quote(issue, ''))
url = "{0}/#/issues/-/{1}/{2}/-/-/True/{3}/1/25".format(self.url, technology, account, urllib.quote(issue, ''))
timezone = time.tzname[time.localtime().tm_isdst]
description = ("This ticket was automatically created by Security Monkey. DO NOT EDIT SUMMARY OR BELOW THIS LINE\n"
"Number of issues: {0}\n"
Expand Down
6 changes: 3 additions & 3 deletions security_monkey/monitors.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ def __init__(self, watcher_class, accounts, debug=False):
self.watcher = watcher_class(accounts=accounts, debug=debug)
self.auditors = []
self.audit_tier = 0

for auditor_class in auditor_registry[self.watcher.index]:
self.auditors.append(auditor_class(accounts=accounts, debug=debug))

def get_monitors(accounts, monitor_names, debug=False):
"""
Returns a list of monitors which apply to one or more of the accounts.
Returns a list of monitors in the correct audit order which apply to one or
more of the accounts.
"""
requested_mons = []
for monitor_name in monitor_names:
Expand All @@ -32,8 +34,6 @@ def get_monitors(accounts, monitor_names, debug=False):

return requested_mons

return requested_mons

def get_monitors_and_dependencies(accounts, monitor_names, debug=False):
"""
Returns a list of monitors in the correct audit order which apply to one or
Expand Down
4 changes: 3 additions & 1 deletion security_monkey/scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ def find_changes(accounts, monitor_names, debug=True):
audit_changes(accounts, monitor_names, False, debug)
db.session.close()


def audit_changes(accounts, monitor_names, send_report, debug=True):
monitors = get_monitors_and_dependencies(accounts, monitor_names, debug)
for monitor in monitors:
Expand Down Expand Up @@ -112,7 +113,8 @@ def setup_scheduler():
auditors = []
for monitor in rep.get_watchauditors(account):
auditors.extend(monitor.auditors)
scheduler.add_cron_job(audit_changes, hour=10, day_of_week="mon-fri", args=[auditors, True])
scheduler.add_cron_job(_audit_changes, hour=10, day_of_week="mon-fri", args=[auditors, True])


# Clear out old exceptions:
scheduler.add_cron_job(_clear_old_exceptions, hour=3, minute=0)
Expand Down
1 change: 1 addition & 0 deletions security_monkey/tests/test_elasticsearch_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@

mock_query = MockAccountQuery()


class ElasticSearchServiceTestCase(SecurityMonkeyTestCase):
def setUp(self):
self.es_items = [
Expand Down
5 changes: 3 additions & 2 deletions security_monkey/watchers/cloud_trail.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,18 +100,19 @@ def slurp(self):
# Utilizing home_region here ensures a single, unique entry
# for each CloudTrail resource
item = CloudTrailItem(
region=home_region, account=account, name=name, config=item_config)
region=home_region, account=account, name=name, arn=trail.get('TrailARN'), config=item_config)
item_list.append(item)

return item_list, exception_map


class CloudTrailItem(ChangeItem):

def __init__(self, account=None, region=None, name=None, config={}):
def __init__(self, account=None, region=None, name=None, arn=None, config={}):
super(CloudTrailItem, self).__init__(
index=CloudTrail.index,
region=region,
account=account,
name=name,
arn=arn,
new_config=config)
6 changes: 4 additions & 2 deletions security_monkey/watchers/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,18 +94,20 @@ def slurp(self):
}

item = ConfigItem(
region=region.name, account=account, name=name, config=item_config)
region=region.name, account=account, name=name,
arn=config_rule.get('ConfigRuleArn'), config=item_config)
item_list.append(item)

return item_list, exception_map


class ConfigItem(ChangeItem):

def __init__(self, account=None, region=None, name=None, config={}):
def __init__(self, account=None, region=None, name=None, arn=None, config={}):
super(ConfigItem, self).__init__(
index=Config.index,
region=region,
account=account,
name=name,
arn=arn,
new_config=config)
95 changes: 45 additions & 50 deletions security_monkey/watchers/config_recorder.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,27 +20,43 @@


"""

from security_monkey.watcher import Watcher
from security_monkey.watcher import ChangeItem
from security_monkey.constants import TROUBLE_REGIONS
from security_monkey.exceptions import BotoConnectionIssue
from security_monkey import app
from boto.ec2 import regions
from security_monkey.decorators import record_exception, iter_account_region


class ConfigRecorder(Watcher):
index = 'configrecorder'
i_am_singular = 'Config Recorder'
i_am_plural = 'Config Recorders'

# TODO: Replace hardcoded region with `get_available_regions` after next boto3 release
# Specific PR here: https://github.com/boto/boto3/pull/531/files
# AWS Config currently only supports the following regions
regions = ["us-east-1", "us-west-1", "us-west-2", "eu-west-1", "eu-central-1",
"ap-northeast-1", "ap-southeast-1", "ap-southeast-2", "sa-east-1"]


def __init__(self, accounts=None, debug=False):
super(ConfigRecorder, self).__init__(accounts=accounts, debug=debug)


@record_exception(source="configrecorder")
def describe_configuration_recorders(self, **kwargs):
from security_monkey.common.sts_connect import connect
config_service = connect(kwargs['account_name'], 'boto3.config.client',
region=kwargs['region'])
response = self.wrap_aws_rate_limited_call(config_service.describe_configuration_recorders)
config_recorders = response.get('ConfigurationRecorders', [])

return [recorder for recorder in config_recorders if not self.check_ignore_list(recorder.get('name'))]


def slurp(self):
"""
:returns: item_list - list of AWS Config recorders.
Expand All @@ -49,56 +65,35 @@ def slurp(self):
"""
self.prep_for_slurp()

item_list = []
exception_map = {}
from security_monkey.common.sts_connect import connect
for account in self.accounts:
for region in regions():
# TODO: Replace hardcoded region with `get_available_regions` after next boto3 release
# Specific PR here:
# https://github.com/boto/boto3/pull/531/files
if region.name in self.regions:
app.logger.debug(
"Checking {}/{}/{}".format(self.index, account, region.name))

try:
config_service = connect(
account, 'boto3.config.client', region=region)

response = self.wrap_aws_rate_limited_call(
config_service.describe_configuration_recorders
)

config_recorders = response.get(
'ConfigurationRecorders', [])
except Exception as e:
app.logger.debug("Exception found: {}".format(e))
if region.name not in TROUBLE_REGIONS:
exc = BotoConnectionIssue(
str(e), self.index, account, region.name)
self.slurp_exception(
(self.index, account, region.name), exc, exception_map)
continue
app.logger.debug("Found {} {}.".format(
len(config_recorders), self.i_am_plural))

for recorder in config_recorders:
name = recorder.get('name')

if self.check_ignore_list(name):
continue

item_config = {
'name': name,
'role_arn': recorder.get('roleARN'),
'recording_group': recorder.get('recordingGroup')
}

item = ConfigRecorderItem(
region=region.name, account=account, name=name, config=item_config)
item_list.append(item)

return item_list, exception_map
@iter_account_region(index=self.index, accounts=self.accounts, service_name='config')
def slurp_items(**kwargs):
item_list = []
exception_map = {}

app.logger.debug("Checking {}/{}/{}".format(self.index,
kwargs['account_name'],
kwargs['region']))

config_recorders = self.describe_configuration_recorders(**kwargs)
if config_recorders:
app.logger.debug("Found {} {}.".format(len(config_recorders), self.i_am_plural))

for recorder in config_recorders:
name = recorder.get('name')

item_config = {
'name': name,
'role_arn': recorder.get('roleARN'),
'recording_group': recorder.get('recordingGroup')
}

item = ConfigRecorderItem(region=kwargs['region'],
account=kwargs['account_name'],
name=name, config=item_config)
item_list.append(item)

return item_list, exception_map
return slurp_items()


class ConfigRecorderItem(ChangeItem):
Expand Down
2 changes: 1 addition & 1 deletion security_monkey/watchers/kms.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ def slurp_items(**kwargs):

name = "{alias} ({key_id})".format(alias=alias, key_id=key_id)

item = KMSMasterKey(region=kwargs['account_name'], account=kwargs['account_name'], name=name, arn=config.get('Arn'), config=dict(config))
item = KMSMasterKey(region=kwargs['region'], account=kwargs['account_name'], name=name, arn=config.get('Arn'), config=dict(config))
item_list.append(item)

return item_list, exception_map
Expand Down
5 changes: 3 additions & 2 deletions security_monkey/watchers/lambda_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def slurp_items(**kwargs):

item = LambdaFunctionItem(region=kwargs['region'],
account=kwargs['account_name'],
name=name, config=dict(config))
name=name, arn=lambda_function.get('FunctionArn'), config=dict(config))

item_list.append(item)

Expand All @@ -106,10 +106,11 @@ def slurp_items(**kwargs):

class LambdaFunctionItem(ChangeItem):

def __init__(self, region=None, account=None, name=None, config={}):
def __init__(self, region=None, account=None, name=None, arn=None, config={}):
super(LambdaFunctionItem, self).__init__(
index=LambdaFunction.index,
region=region,
account=account,
name=name,
arn=arn,
new_config=config)
Loading