diff --git a/.travis.yml b/.travis.yml index b1fc37160..3aec4e5b6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,7 +36,7 @@ before_script: - python setup.py develop - pip install .[tests] - pip install coveralls - - python manage.py db upgrade + - monkey db upgrade script: - sh env_tests/test_dart.sh diff --git a/README.md b/README.md index 3f8feee66..59112ecac 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Security Monkey Security Monkey monitors your [AWS and GCP accounts](https://medium.com/@Netflix_Techblog/netflix-security-monkey-on-google-cloud-platform-gcp-f221604c0cc7) for policy changes and alerts on insecure configurations. It provides a single UI to browse and search through all of your accounts, regions, and cloud services. The monkey remembers previous states and can show you exactly what changed, and when. -Security Monkey can be extended with [custom account types](plugins.md), custom watchers, custom auditors, and [custom alerters](docs/misc.md#custom-alerters). +Security Monkey can be extended with [custom account types](docs/plugins.md), [custom watchers](docs/development.md#adding-a-watcher), [custom auditors](docs/development.md#adding-an-auditor), and [custom alerters](docs/misc.md#custom-alerters). It works on CPython 2.7. It is known to work on Ubuntu Linux and OS X. diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 000000000..f23708f4b --- /dev/null +++ b/docker/README.md @@ -0,0 +1,12 @@ +Docker local development +======================== + +Project resources +----------------- + +- [Docker documentation](../docs/docker.md) +- [Development documentation](../docs/development.md) +- [OSX Develepment Setup](../docs/dev_setup_osx.md) +- [Windows Develepment Setup](../docs/dev_setup_windows.md) +- [Ubuntu Develepment Setup](../docs/dev_setup_ubuntu.md) + diff --git a/docker/README.rst b/docker/README.rst deleted file mode 100644 index 04d86b4e2..000000000 --- a/docker/README.rst +++ /dev/null @@ -1,9 +0,0 @@ -************************ -Docker local development -************************ - -Project resources -================= - -- `Docker documentation `_ -- `Development documentation `_ diff --git a/docker/api-init.sh b/docker/api-init.sh index b33e6a258..f82e7e379 100755 --- a/docker/api-init.sh +++ b/docker/api-init.sh @@ -15,9 +15,9 @@ mkdir -p /var/log/security_monkey/ touch "/var/log/security_monkey/security_monkey-deploy.log" cd /usr/local/src/security_monkey -python manage.py db upgrade +python security_monkey/manage.py db upgrade -cat < Admin + monkey create_user Admin The first argument is the email address of the new user. The second parameter is the role and must be one of [anonymous, View, Comment, Justify, Admin]. @@ -210,7 +211,7 @@ Start the Security Monkey API This starts the REST API that the Angular application will communicate with. : - python manage.py runserver + monkey runserver Launch Dartium from within WebStorm =================================== @@ -247,17 +248,17 @@ Manually Run the Account Watchers Run the watchers to put some data in the database. : cd ~/security_monkey/ - python manage.py run_change_reporter all + monkey run_change_reporter all You can also run an individual watcher: - python manage.py find_changes -a all -m all - python manage.py find_changes -a all -m iamrole - python manage.py find_changes -a "My Test Account" -m iamgroup + monkey find_changes -a all -m all + monkey find_changes -a all -m iamrole + monkey find_changes -a "My Test Account" -m iamgroup You can run the auditors against the items currently in the database: - python manage.py audit_changes -a all -m redshift --send_report=False + monkey audit_changes -a all -m redshift --send_report=False Next Steps ========== diff --git a/docs/dev_setup_windows.md b/docs/dev_setup_windows.md index b75fddbbb..8ecee34c7 100644 --- a/docs/dev_setup_windows.md +++ b/docs/dev_setup_windows.md @@ -153,7 +153,7 @@ With your virtualenv activated, this will install the security\_monkey python mo We should be able to run manage.py to see usage information: - python manage.py + monkey ### Setup a development DB @@ -175,7 +175,7 @@ If you leave the DB paramaters at their default, you'll need to modify config-lo Install the security\_monkey DB tables: - python manage.py db upgrade + monkey db upgrade FYI - Navicat is a great tool for exploring the DB. @@ -184,14 +184,14 @@ Add Amazon Accounts This will add Amazon owned AWS accounts to security monkey. : - python manage.py amazon_accounts + monkey amazon_accounts Add a user account ------------------ This will add a user account that can be used later to login to the web ui: - python manage.py create\_user Admin + monkey create\_user Admin The first argument is the email address of the new user. The second parameter is the role and must be one of [anonymous, View, Comment, Justify, Admin]. @@ -200,7 +200,7 @@ Start the Security Monkey API This starts the REST API that the Angular application will communicate with. : - python manage.py runserver + monkey runserver ### Dart Development @@ -252,17 +252,17 @@ Manually Run the Account Watchers Run the watchers to put some data in the database. : cd ~/Github/security_monkey/ - python manage.py run_change_reporter all + monkey run_change_reporter all You can also run an individual watcher: - python manage.py find_changes -a all -m all - python manage.py find_changes -a all -m iamrole - python manage.py find_changes -a "My Test Account" -m iamgroup + monkey find_changes -a all -m all + monkey find_changes -a all -m iamrole + monkey find_changes -a "My Test Account" -m iamgroup You can run the auditors against the items currently in the database: - python manage.py audit_changes -a all -m redshift --send_report=False + monkey audit_changes -a all -m redshift --send_report=False Next Steps ---------- diff --git a/docs/docker.md b/docs/docker.md index 3c6a91466..299984f00 100644 --- a/docs/docker.md +++ b/docs/docker.md @@ -27,7 +27,7 @@ On a fresh database instance, various initial configuration must be run such as Before you bring the containers up, you need to add an AWS account for the scheduler to monitor: - $ python manage.py add_account_aws --number $account --name $name -r SecurityMonkey + $ monkey add_account_aws --number $account --name $name -r SecurityMonkey Now that the database is setup, you can start up the remaining containers (Security Monkey, nginx, and the scheduler) via: @@ -64,11 +64,11 @@ You can get a shell thanks to the docker-compose.shell.yml override: This allows you to access SecurityMonkey code, and run manual configurations such as: - $ python manage.py create_user admin@example.com Admin + $ monkey create_user admin@example.com Admin and/or: - $ python manage.py add_account_aws --number $account --name $name -r SecurityMonkey + $ monkey add_account_aws --number $account --name $name -r SecurityMonkey This container is useful for local development. It is not required otherwise. diff --git a/docs/jirasync.md b/docs/jirasync.md index 6e4e7f164..f2f7e62eb 100644 --- a/docs/jirasync.md +++ b/docs/jirasync.md @@ -29,7 +29,7 @@ To use JIRA sync, you will need to create a YAML configuration file, specifying To use JIRA sync, set the environment variable `SECURITY_MONKEY_JIRA_SYNC` to the location of the YAML configuration file. This file will be loaded once when the application starts. If set, JIRA sync will run for each account after the auditors run. You can also manually run a sync through `manage.py`. -`python manage.py sync_jira` +`monkey sync_jira` Details ------- diff --git a/docs/misc.md b/docs/misc.md index a23fbc301..c1f8cc7e7 100644 --- a/docs/misc.md +++ b/docs/misc.md @@ -11,13 +11,13 @@ For instance when you change a whitelist or add a 3rd party account, configurati In this case, you can force an audit by running: ~~~~ {.sourceCode .bash} -python manage.py audit_changes -m s3 +monkey audit_changes -m s3 ~~~~ For an email by adding `-r True`: ~~~~ {.sourceCode .bash} -python manage.py audit_changes -m s3 -r True +monkey audit_changes -m s3 -r True ~~~~ Scheduler Hacking @@ -66,7 +66,7 @@ On the next full audit, the score for the configured check method will be replac If no account pattern scores match the account, the override score it will default to the generic override score configured. -Audit override scores may also be set up though the [Command line interface](../manage.py) functions add\_override\_score (for a single score) and add\_override\_scores (from a csv file) +Audit override scores may also be set up though the [Command line interface](../security_monkey/manage.py) functions `add_override_score` (for a single score) and `add_override_scores` (from a csv file) *Note:*: diff --git a/docs/nginx_install.md b/docs/nginx_install.md index d2384ae71..aa7e6c8fe 100644 --- a/docs/nginx_install.md +++ b/docs/nginx_install.md @@ -27,9 +27,10 @@ The Python process Run Security Monkey as usual, but this time make it listen to a local port and host. E.G: - python manage.py run_api_server + monkey run_api_server -In PHP, when you edit a file, the changes are immediately visible. In Python, the whole code is often loaded in memory for performance reasons. This means you have to restart the Python process to see the changes effect. Having a separate process let you do this without having to restart the server. +If using the flask server in debug mode (`monkey runserver`), the python code will be reloaded when any file is changed. +However, in production we use gunicorn (`monkey run_api_server`) which does not reload. This means you have to restart the Python process to see the changes effect. Having a separate process let you do this without having to restart the server. Nginx ----- diff --git a/docs/quickstart.md b/docs/quickstart.md index 84d0a6b8f..d3377f302 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -129,7 +129,7 @@ For an explanation of the configuration options, see [options](options.md). Security Monkey uses Flask-Migrate (Alembic) to keep database tables up to date. To create the tables, run this command: cd /usr/local/src/security_monkey/ - python manage.py db upgrade + monkey db upgrade Populate Security Monkey with Accounts -------------------------------------- @@ -138,20 +138,20 @@ Populate Security Monkey with Accounts This will add Amazon owned AWS accounts to security monkey. : - python manage.py amazon_accounts + monkey amazon_accounts ### Add Your AWS/GCP Accounts You'll need to add at least one account before starting the scheduler. It's easiest to add them from the command line, but it can also be done through the web UI. : - python manage.py add_account_aws + monkey add_account_aws usage: manage.py add_account_aws [-h] -n NAME [--thirdparty] [--active] [--notes NOTES] --id IDENTIFIER [--update-existing] [--canonical_id CANONICAL_ID] [--s3_name S3_NAME] [--role_name ROLE_NAME] - python manage.py add_account_gcp + monkey add_account_gcp usage: manage.py add_account_gcp [-h] -n NAME [--thirdparty] [--active] [--notes NOTES] --id IDENTIFIER [--update-existing] [--creds_file CREDS_FILE] @@ -160,7 +160,7 @@ You'll need to add at least one account before starting the scheduler. It's easi Users can be created on the command line or by registering in the web UI: - $ python manage.py create_user "you@youremail.com" "Admin" + $ monkey create_user "you@youremail.com" "Admin" > Password: > Confirm Password: diff --git a/docs/userguide.md b/docs/userguide.md index ceb04dc77..92962d8ca 100644 --- a/docs/userguide.md +++ b/docs/userguide.md @@ -53,14 +53,14 @@ The first run will occur in 15 minutes. You can monitor all the log files in /va **Note: You can also add accounts via the command line with manage.py**: - $ python manage.py add_account_aws --number 12345678910 --name account_foo + $ monkey add_account_aws --number 12345678910 --name account_foo Successfully added account account_foo If an account with the same number already exists, this will do nothing, unless you pass `--force`, in which case, it will override the existing account: - $ python manage.py add_account_aws --number 12345678910 --name account_foo + $ monkey add_account_aws --number 12345678910 --name account_foo An account with id 12345678910 already exists - $ python manage.py add_account_aws --number 12345678910 --name account_foo --active false --force + $ monkey add_account_aws --number 12345678910 --name account_foo --active false --force Successfully added account account_foo Now What? diff --git a/docs/using_supervisor.md b/docs/using_supervisor.md index 61de5fef8..2ec3d5655 100644 --- a/docs/using_supervisor.md +++ b/docs/using_supervisor.md @@ -7,29 +7,35 @@ Create a configuration file named security\_monkey.conf under /etc/supervisor/co # Control Startup/Shutdown: # sudo supervisorctl - + [program:securitymonkey] user=www-data - environment=PYTHONPATH='/usr/local/src/security_monkey/',SECURITY_MONKEY_SETTINGS="/usr/local/src/secmonkey-config/env-config/config-local.py" autostart=true autorestart=true - command=python /usr/local/src/security_monkey/manage.py run_api_server - + environment=PYTHONPATH='/usr/local/src/security_monkey/',PATH="/usr/local/src/security_monkey/venv/bin:%(ENV_PATH)s" + command=monkey run_api_server + [program:securitymonkeyscheduler] user=www-data autostart=true autorestart=true directory=/usr/local/src/security_monkey/ - environment=PYTHONPATH='/usr/local/src/security_monkey/',SECURITY_MONKEY_SETTINGS="/usr/local/src/secmonkey-config/env-config/config-local.py" - command=python /usr/local/src/security_monkey/manage.py start_scheduler + environment=PYTHONPATH='/usr/local/src/security_monkey/',PATH="/usr/local/src/security_monkey/venv/bin:%(ENV_PATH)s" + command=monkey start_scheduler -The 4 first entries are just boiler plate to get you started, you can copy them verbatim. +The 3 first entries are just boiler plate to get you started, you can copy them verbatim. -The last one define one (you can have many) process supervisor should manage. +The fourth line enables the `virtualenv` created in /usr/local/src/security_monkey/venv/. + +The fifth line defines one process supervisor should manage. It means it will run the command: - python manage.py run_api_server + monkey run_api_server + +which translates to: + + python security_monkey/manage.py run_api_server In the directory, with the environment and the user you defined. @@ -47,4 +53,4 @@ Then you can manage the process by running: It will start a shell from were you can start/stop/restart the service -You can read all errors that might occurs from /tmp/securitymonkey.log. +It's common for supervisor to log to `/var/log/supervisor/` and security_monkey is often configured to log to `/var/log/security_monkey`. \ No newline at end of file diff --git a/generate_docs.py b/generate_docs.py deleted file mode 100644 index dad155453..000000000 --- a/generate_docs.py +++ /dev/null @@ -1,262 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -""" -sphinx-autopackage-script - -This script parses a directory tree looking for python modules and packages and -creates ReST files appropriately to create code documentation with Sphinx. -It also creates a modules index (named modules.). -""" - -# Copyright 2008 Société des arts technologiques (SAT), http://www.sat.qc.ca/ -# Copyright 2010 Thomas Waldmann -# All rights reserved. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - - -import os -import optparse - - -# automodule options -OPTIONS = ['members', - 'undoc-members', - # 'inherited-members', # disabled because there's a bug in sphinx - 'show-inheritance', - ] - -INIT = '__init__.py' - -def makename(package, module): - """Join package and module with a dot.""" - # Both package and module can be None/empty. - if package: - name = package - if module: - name += '.' + module - else: - name = module - return name - -def write_file(name, text, opts): - """Write the output file for module/package .""" - if opts.dryrun: - return - fname = os.path.join(opts.destdir, "%s.%s" % (name, opts.suffix)) - if not opts.force and os.path.isfile(fname): - print 'File %s already exists, skipping.' % fname - else: - print 'Creating file %s.' % fname - f = open(fname, 'w') - f.write(text) - f.close() - -def format_heading(level, text): - """Create a heading of [1, 2 or 3 supported].""" - underlining = ['=', '-', '~', ][level-1] * len(text) - return '%s\n%s\n\n' % (text, underlining) - -def format_directive(module, package=None): - """Create the automodule directive and add the options.""" - directive = '.. automodule:: %s\n' % makename(package, module) - for option in OPTIONS: - directive += ' :%s:\n' % option - return directive - -def create_module_file(package, module, opts): - """Build the text of the file and write the file.""" - text = format_heading(1, '%s Module' % module) - text += format_heading(2, ':mod:`%s` Module' % module) - text += format_directive(module, package) - write_file(makename(package, module), text, opts) - -def create_package_file(root, master_package, subroot, py_files, opts, subs): - """Build the text of the file and write the file.""" - package = os.path.split(root)[-1] - text = format_heading(1, '%s Package' % package) - # add each package's module - for py_file in py_files: - if shall_skip(os.path.join(root, py_file)): - continue - is_package = py_file == INIT - py_file = os.path.splitext(py_file)[0] - py_path = makename(subroot, py_file) - if is_package: - heading = ':mod:`%s` Package' % package - else: - heading = ':mod:`%s` Module' % py_file - text += format_heading(2, heading) - text += format_directive(is_package and subroot or py_path, master_package) - text += '\n' - - # build a list of directories that are packages (they contain an INIT file) - subs = [sub for sub in subs if os.path.isfile(os.path.join(root, sub, INIT))] - # if there are some package directories, add a TOC for theses subpackages - if subs: - text += format_heading(2, 'Subpackages') - text += '.. toctree::\n\n' - for sub in subs: - text += ' %s.%s\n' % (makename(master_package, subroot), sub) - text += '\n' - - write_file(makename(master_package, subroot), text, opts) - -def create_modules_toc_file(master_package, modules, opts, name='modules'): - """ - Create the module's index. - """ - text = format_heading(1, '%s Modules' % opts.header) - text += '.. toctree::\n' - text += ' :maxdepth: %s\n\n' % opts.maxdepth - - modules.sort() - prev_module = '' - for module in modules: - # look if the module is a subpackage and, if yes, ignore it - if module.startswith(prev_module + '.'): - continue - prev_module = module - text += ' %s\n' % module - - write_file(name, text, opts) - -def shall_skip(module): - """ - Check if we want to skip this module. - """ - # skip it, if there is nothing (or just \n or \r\n) in the file - return os.path.getsize(module) < 3 - -def recurse_tree(path, excludes, opts): - """ - Look for every file in the directory tree and create the corresponding - ReST files. - """ - # use absolute path for root, as relative paths like '../../foo' cause - # 'if "/." in root ...' to filter out *all* modules otherwise - path = os.path.abspath(path) - # check if the base directory is a package and get is name - if INIT in os.listdir(path): - package_name = path.split(os.path.sep)[-1] - else: - package_name = None - - toc = [] - tree = os.walk(path, False) - for root, subs, files in tree: - # keep only the Python script files - py_files = sorted([f for f in files if os.path.splitext(f)[1] == '.py']) - if INIT in py_files: - py_files.remove(INIT) - py_files.insert(0, INIT) - # remove hidden ('.') and private ('_') directories - subs = sorted([sub for sub in subs if sub[0] not in ['.', '_']]) - # check if there are valid files to process - # TODO: could add check for windows hidden files - if "/." in root or "/_" in root \ - or not py_files \ - or is_excluded(root, excludes): - continue - if INIT in py_files: - # we are in package ... - if (# ... with subpackage(s) - subs - or - # ... with some module(s) - len(py_files) > 1 - or - # ... with a not-to-be-skipped INIT file - not shall_skip(os.path.join(root, INIT)) - ): - subroot = root[len(path):].lstrip(os.path.sep).replace(os.path.sep, '.') - create_package_file(root, package_name, subroot, py_files, opts, subs) - toc.append(makename(package_name, subroot)) - elif root == path: - # if we are at the root level, we don't require it to be a package - for py_file in py_files: - if not shall_skip(os.path.join(path, py_file)): - module = os.path.splitext(py_file)[0] - create_module_file(package_name, module, opts) - toc.append(makename(package_name, module)) - - # create the module's index - if not opts.notoc: - create_modules_toc_file(package_name, toc, opts) - -def normalize_excludes(rootpath, excludes): - """ - Normalize the excluded directory list: - * must be either an absolute path or start with rootpath, - * otherwise it is joined with rootpath - * with trailing slash - """ - sep = os.path.sep - f_excludes = [] - for exclude in excludes: - if not os.path.isabs(exclude) and not exclude.startswith(rootpath): - exclude = os.path.join(rootpath, exclude) - if not exclude.endswith(sep): - exclude += sep - f_excludes.append(exclude) - return f_excludes - -def is_excluded(root, excludes): - """ - Check if the directory is in the exclude list. - - Note: by having trailing slashes, we avoid common prefix issues, like - e.g. an exlude "foo" also accidentally excluding "foobar". - """ - sep = os.path.sep - if not root.endswith(sep): - root += sep - for exclude in excludes: - if root.startswith(exclude): - return True - return False - -def main(): - """ - Parse and check the command line arguments. - """ - parser = optparse.OptionParser(usage="""usage: %prog [options] [exclude paths, ...] - -Note: By default this script will not overwrite already created files.""") - parser.add_option("-n", "--doc-header", action="store", dest="header", help="Documentation Header (default=Project)", default="Project") - parser.add_option("-d", "--dest-dir", action="store", dest="destdir", help="Output destination directory", default="") - parser.add_option("-s", "--suffix", action="store", dest="suffix", help="module suffix (default=txt)", default="txt") - parser.add_option("-m", "--maxdepth", action="store", dest="maxdepth", help="Maximum depth of submodules to show in the TOC (default=4)", type="int", default=4) - parser.add_option("-r", "--dry-run", action="store_true", dest="dryrun", help="Run the script without creating the files") - parser.add_option("-f", "--force", action="store_true", dest="force", help="Overwrite all the files") - parser.add_option("-t", "--no-toc", action="store_true", dest="notoc", help="Don't create the table of content file") - (opts, args) = parser.parse_args() - if not args: - parser.error("package path is required.") - else: - rootpath, excludes = args[0], args[1:] - if os.path.isdir(rootpath): - # check if the output destination is a valid directory - if opts.destdir and os.path.isdir(opts.destdir): - excludes = normalize_excludes(rootpath, excludes) - recurse_tree(rootpath, excludes, opts) - else: - print '%s is not a valid output destination directory.' % opts.destdir - else: - print '%s is not a valid directory.' % rootpath - - -if __name__ == '__main__': - main() - diff --git a/migrations/versions/b8ccf5b8089b_.py b/migrations/versions/b8ccf5b8089b_.py index eac8cde1d..ce36df97d 100644 --- a/migrations/versions/b8ccf5b8089b_.py +++ b/migrations/versions/b8ccf5b8089b_.py @@ -14,7 +14,7 @@ from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker -from manage import fetch_aws_canonical_ids +from security_monkey.manage import fetch_aws_canonical_ids Session = sessionmaker() Base = declarative_base() diff --git a/manage.py b/security_monkey/manage.py similarity index 91% rename from manage.py rename to security_monkey/manage.py index cad9cd7e6..ecddf6ea3 100644 --- a/manage.py +++ b/security_monkey/manage.py @@ -94,8 +94,7 @@ def delete_unjustified_issues(accounts, monitors): monitor_names = _parse_tech_names(monitors) account_names = _parse_accounts(accounts) from security_monkey.datastore import ItemAudit - # ItemAudit.query.filter_by(justified=False).delete() - issues = ItemAudit.query.filter_by(justified=False).all() + issues = ItemAudit.query.filter_by(ItemAudit.justified==False).all() for issue in issues: del issue.sub_items[:] db.session.delete(issue) @@ -187,37 +186,6 @@ def amazon_accounts(): store_exception("manager-amazon-accounts", None, e) -# DEPRECATED: -# @manager.option('-u', '--number', dest='number', type=unicode, required=True) -# @manager.option('-a', '--active', dest='active', type=bool, default=True) -# @manager.option('-t', '--thirdparty', dest='third_party', type=bool, default=False) -# @manager.option('-n', '--name', dest='name', type=unicode, required=True) -# @manager.option('-s', '--s3name', dest='s3_name', type=unicode, default=u'') -# @manager.option('-o', '--notes', dest='notes', type=unicode, default=u'') -# @manager.option('-y', '--type', dest='account_type', type=unicode, default=u'AWS') -# @manager.option('-r', '--rolename', dest='role_name', type=unicode, default=u'SecurityMonkey') -# @manager.option('-f', '--force', dest='force', help='Override existing accounts', action='store_true') -# def add_account(number, third_party, name, s3_name, active, notes, account_type, role_name, force): -# from security_monkey.account_manager import account_registry -# account_manager = account_registry.get(account_type)() -# account = account_manager.lookup_account_by_identifier(number) -# if account: -# from security_monkey.common.audit_issue_cleanup import clean_account_issues -# clean_account_issues(account) -# -# if force: -# account_manager.update(account.id, account_type, name, active, -# third_party, notes, number, -# custom_fields={ 's3_name': s3_name, 'role_name': role_name }) -# else: -# app.logger.info('Account with id {} already exists'.format(number)) -# else: -# account_manager.create(account_type, name, active, third_party, notes, number, -# custom_fields={ 's3_name': s3_name, 'role_name': role_name }) -# -# db.session.close() - - @manager.command @manager.option('-e', '--email', dest='email', type=unicode, required=True) @manager.option('-r', '--role', dest='role', type=str, required=True) @@ -319,13 +287,14 @@ def add_override_score(tech_name, method, auditor, score, disabled, pattern_scor score = 0 query = ItemAuditScore.query.filter(ItemAuditScore.technology == tech_name) - query = query.filter(ItemAuditScore.method == method + ' (' + auditor + ')') + method_str = "{method} ({auditor})".format(method=method, auditor=auditor) + query = query.filter(ItemAuditScore.method == method_str) entry = query.first() if not entry: entry = ItemAuditScore() entry.technology = tech_name - entry.method = method + ' (' + auditor + ')' + entry.method = method_str entry.score = score entry.disabled = disabled @@ -563,7 +532,7 @@ def clean_stale_issues(): class APIServer(Command): - def __init__(self, host='127.0.0.1', port=app.config.get('API_PORT'), workers=6): + def __init__(self, host='127.0.0.1', port=app.config.get('API_PORT'), workers=12): self.address = "{}:{}".format(host, port) self.workers = workers @@ -647,10 +616,14 @@ def handle(self, app, *args, **kwargs): return -1 -if __name__ == "__main__": +def main(): from security_monkey.account_manager import account_registry for name, account_manager in account_registry.items(): manager.add_command("add_account_%s" % name.lower(), AddAccount(account_manager())) manager.add_command("run_api_server", APIServer()) manager.run() + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/security_monkey/tests/interface/test_manager.py b/security_monkey/tests/interface/test_manager.py index c1c42537c..cf0b6441d 100644 --- a/security_monkey/tests/interface/test_manager.py +++ b/security_monkey/tests/interface/test_manager.py @@ -24,7 +24,7 @@ from security_monkey import db from security_monkey.tests import SecurityMonkeyTestCase -from manage import clear_expired_exceptions +from security_monkey.manage import clear_expired_exceptions import datetime diff --git a/security_monkey/tests/utilities/test_s3_canonical.py b/security_monkey/tests/utilities/test_s3_canonical.py index 693e812c1..bb4bb112a 100644 --- a/security_monkey/tests/utilities/test_s3_canonical.py +++ b/security_monkey/tests/utilities/test_s3_canonical.py @@ -19,7 +19,7 @@ """ import unittest -from manage import fetch_aws_canonical_ids, AddAccount, manager +from security_monkey.manage import fetch_aws_canonical_ids, AddAccount, manager from security_monkey import db from security_monkey.common.s3_canonical import get_canonical_ids from security_monkey.datastore import AccountType, Account, ExceptionLogs, AccountTypeCustomValues diff --git a/setup.py b/setup.py index 42769e72d..325779617 100644 --- a/setup.py +++ b/setup.py @@ -68,5 +68,10 @@ 'freezegun>=0.3.7', 'mixer==5.5.7' ] + }, + entry_points={ + 'console_scripts': [ + 'monkey = security_monkey.manage:main', + ], } ) diff --git a/supervisor/security_monkey.conf b/supervisor/security_monkey.conf index faf70e0e3..b8105e916 100644 --- a/supervisor/security_monkey.conf +++ b/supervisor/security_monkey.conf @@ -10,7 +10,7 @@ user=www-data autostart=true autorestart=true environment=PYTHONPATH='/usr/local/src/security_monkey/',PATH="/usr/local/src/security_monkey/venv/bin:%(ENV_PATH)s" -command=python /usr/local/src/security_monkey/manage.py run_api_server +command=monkey run_api_server [program:securitymonkeyscheduler] user=www-data @@ -18,4 +18,4 @@ autostart=true autorestart=true directory=/usr/local/src/security_monkey/ environment=PYTHONPATH='/usr/local/src/security_monkey/',PATH="/usr/local/src/security_monkey/venv/bin:%(ENV_PATH)s" -command=python /usr/local/src/security_monkey/manage.py start_scheduler +command=monkey start_scheduler