mirror of https://github.com/yandex/gixy
Merge 8974595fa1
into 625a25db46
commit
95fc240764
|
@ -98,7 +98,7 @@ def main():
|
||||||
_init_logger(args.debug)
|
_init_logger(args.debug)
|
||||||
|
|
||||||
path = os.path.expanduser(args.nginx_file)
|
path = os.path.expanduser(args.nginx_file)
|
||||||
if not os.path.isfile(path):
|
if path != '-' and not os.path.exists(path):
|
||||||
sys.stderr.write('Please specify path to Nginx configuration.\n\n')
|
sys.stderr.write('Please specify path to Nginx configuration.\n\n')
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
@ -150,7 +150,13 @@ def main():
|
||||||
config.set_for(name, options)
|
config.set_for(name, options)
|
||||||
|
|
||||||
with Gixy(config=config) as yoda:
|
with Gixy(config=config) as yoda:
|
||||||
yoda.audit(path)
|
if path == '-':
|
||||||
|
with os.fdopen(sys.stdin.fileno(), 'r') as fdata:
|
||||||
|
yoda.audit('<stdin>', fdata, is_stdin=True)
|
||||||
|
else:
|
||||||
|
with open(path, mode='r') as fdata:
|
||||||
|
yoda.audit(path, fdata, is_stdin=False)
|
||||||
|
|
||||||
formatted = formatters()[config.output_format]().format(yoda)
|
formatted = formatters()[config.output_format]().format(yoda)
|
||||||
if args.output_file:
|
if args.output_file:
|
||||||
with open(config.output_file, 'w') as f:
|
with open(config.output_file, 'w') as f:
|
||||||
|
|
|
@ -1,25 +1,32 @@
|
||||||
|
import os
|
||||||
|
import logging
|
||||||
|
|
||||||
import gixy
|
import gixy
|
||||||
from gixy.core.plugins_manager import PluginsManager
|
from gixy.core.plugins_manager import PluginsManager
|
||||||
from gixy.core.context import get_context, pop_context, push_context, purge_context
|
from gixy.core.context import get_context, pop_context, push_context, purge_context
|
||||||
from gixy.parser.nginx_parser import NginxParser
|
from gixy.parser.nginx_parser import NginxParser
|
||||||
from gixy.core.config import Config
|
from gixy.core.config import Config
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Manager(object):
|
class Manager(object):
|
||||||
def __init__(self, config=None):
|
def __init__(self, config=None):
|
||||||
self.root = None
|
self.root = None
|
||||||
self.parser = None
|
|
||||||
self.auditor = None
|
|
||||||
self.config = config or Config()
|
self.config = config or Config()
|
||||||
|
self.auditor = PluginsManager(config=self.config)
|
||||||
self.stats = {gixy.severity.UNSPECIFIED: 0,
|
self.stats = {gixy.severity.UNSPECIFIED: 0,
|
||||||
gixy.severity.LOW: 0,
|
gixy.severity.LOW: 0,
|
||||||
gixy.severity.MEDIUM: 0,
|
gixy.severity.MEDIUM: 0,
|
||||||
gixy.severity.HIGH: 0}
|
gixy.severity.HIGH: 0}
|
||||||
|
|
||||||
def audit(self, file_path):
|
def audit(self, file_path, file_data, is_stdin=False):
|
||||||
self.auditor = PluginsManager(config=self.config)
|
LOG.debug("Audit config file: {fname}".format(fname=file_path))
|
||||||
self.parser = NginxParser(file_path, allow_includes=self.config.allow_includes)
|
parser = NginxParser(
|
||||||
self.root = self.parser.parse(file_path)
|
cwd=os.path.dirname(file_path) if not is_stdin else '',
|
||||||
|
allow_includes=self.config.allow_includes)
|
||||||
|
self.root = parser.parse(content=file_data.read(), path_info=file_path)
|
||||||
|
|
||||||
push_context(self.root)
|
push_context(self.root)
|
||||||
self._audit_recursive(self.root.children)
|
self._audit_recursive(self.root.children)
|
||||||
|
|
||||||
|
|
|
@ -12,26 +12,32 @@ LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class NginxParser(object):
|
class NginxParser(object):
|
||||||
def __init__(self, file_path, allow_includes=True):
|
def __init__(self, cwd='', allow_includes=True):
|
||||||
self.base_file_path = file_path
|
self.cwd = cwd
|
||||||
self.cwd = os.path.dirname(file_path)
|
|
||||||
self.configs = {}
|
self.configs = {}
|
||||||
self.is_dump = False
|
self.is_dump = False
|
||||||
self.allow_includes = allow_includes
|
self.allow_includes = allow_includes
|
||||||
self.directives = {}
|
self.directives = {}
|
||||||
|
self.parser = raw_parser.RawParser()
|
||||||
self._init_directives()
|
self._init_directives()
|
||||||
|
|
||||||
def parse(self, file_path, root=None):
|
def parse_file(self, path, root=None):
|
||||||
LOG.debug("Parse file: {}".format(file_path))
|
LOG.debug("Parse file: {}".format(path))
|
||||||
|
content = open(path).read()
|
||||||
|
return self.parse(content=content, root=root, path_info=path)
|
||||||
|
|
||||||
|
def parse(self, content, root=None, path_info=None):
|
||||||
if not root:
|
if not root:
|
||||||
root = block.Root()
|
root = block.Root()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
parser = raw_parser.RawParser()
|
parsed = self.parser.parse(content)
|
||||||
parsed = parser.parse(file_path)
|
|
||||||
except ParseException as e:
|
except ParseException as e:
|
||||||
LOG.error('Failed to parse config "{file}": {error}'.format(file=file_path, error=str(e)))
|
error_msg = 'char {char} (line:{line}, col:{col})'.format(char=e.loc, line=e.lineno, col=e.col)
|
||||||
|
if path_info:
|
||||||
|
LOG.error('Failed to parse config "{file}": {error}'.format(file=path_info, error=error_msg))
|
||||||
|
else:
|
||||||
|
LOG.error('Failed to parse config: {error}'.format(error=error_msg))
|
||||||
return root
|
return root
|
||||||
|
|
||||||
if len(parsed) and parsed[0].getName() == 'file_delimiter':
|
if len(parsed) and parsed[0].getName() == 'file_delimiter':
|
||||||
|
@ -108,7 +114,7 @@ class NginxParser(object):
|
||||||
for file_path in glob.iglob(path):
|
for file_path in glob.iglob(path):
|
||||||
include = block.IncludeBlock('include', [file_path])
|
include = block.IncludeBlock('include', [file_path])
|
||||||
parent.append(include)
|
parent.append(include)
|
||||||
self.parse(file_path, include)
|
self.parse_file(file_path, include)
|
||||||
|
|
||||||
if not file_path:
|
if not file_path:
|
||||||
LOG.warning("File not found: {}".format(path))
|
LOG.warning("File not found: {}".format(path))
|
||||||
|
|
|
@ -22,17 +22,15 @@ class RawParser(object):
|
||||||
"""
|
"""
|
||||||
A class that parses nginx configuration with pyparsing
|
A class that parses nginx configuration with pyparsing
|
||||||
"""
|
"""
|
||||||
|
def parse(self, data):
|
||||||
def __init__(self):
|
|
||||||
self._script = None
|
|
||||||
|
|
||||||
def parse(self, file_path):
|
|
||||||
"""
|
"""
|
||||||
Returns the parsed tree.
|
Returns the parsed tree.
|
||||||
"""
|
"""
|
||||||
content = open(file_path).read()
|
content = data.strip()
|
||||||
|
if not content:
|
||||||
|
return []
|
||||||
|
|
||||||
return self.script.parseString(content, parseAll=True)
|
return self.script.parseString(content, parseAll=True)
|
||||||
# return self.script.parseFile(file_path, parseAll=True)
|
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def script(self):
|
def script(self):
|
||||||
|
|
|
@ -1,17 +1,13 @@
|
||||||
from nose.tools import assert_equals, assert_is_instance, assert_is_not_none, assert_is_none, assert_true, assert_false
|
from nose.tools import assert_equals, assert_is_instance, assert_is_not_none, assert_is_none, assert_true, assert_false
|
||||||
import mock
|
|
||||||
from six import StringIO
|
|
||||||
from six.moves import builtins
|
|
||||||
from gixy.parser.nginx_parser import NginxParser
|
from gixy.parser.nginx_parser import NginxParser
|
||||||
from gixy.directives.block import *
|
from gixy.directives.block import *
|
||||||
|
|
||||||
# TODO(buglloc): what about include block?
|
# TODO(buglloc): what about include block?
|
||||||
|
|
||||||
|
|
||||||
def _get_parsed(config):
|
def _get_parsed(config):
|
||||||
with mock.patch('%s.open' % builtins.__name__) as mock_open:
|
root = NginxParser(cwd='', allow_includes=False).parse(config)
|
||||||
mock_open.return_value = StringIO(config)
|
return root.children[0]
|
||||||
root = NginxParser('/foo/bar', allow_includes=False).parse('/foo/bar')
|
|
||||||
return root.children[0]
|
|
||||||
|
|
||||||
|
|
||||||
def test_block():
|
def test_block():
|
||||||
|
|
|
@ -1,15 +1,11 @@
|
||||||
from nose.tools import assert_equals, assert_is_instance, assert_false, assert_true
|
from nose.tools import assert_equals, assert_is_instance, assert_false, assert_true
|
||||||
import mock
|
|
||||||
from six import StringIO
|
|
||||||
from six.moves import builtins
|
|
||||||
from gixy.parser.nginx_parser import NginxParser
|
from gixy.parser.nginx_parser import NginxParser
|
||||||
from gixy.directives.directive import *
|
from gixy.directives.directive import *
|
||||||
|
|
||||||
|
|
||||||
def _get_parsed(config):
|
def _get_parsed(config):
|
||||||
with mock.patch('%s.open' % builtins.__name__) as mock_open:
|
root = NginxParser(cwd='', allow_includes=False).parse(config)
|
||||||
mock_open.return_value = StringIO(config)
|
return root.children[0]
|
||||||
return NginxParser('/foo/bar', allow_includes=False).parse('/foo/bar').children[0]
|
|
||||||
|
|
||||||
|
|
||||||
def test_directive():
|
def test_directive():
|
||||||
|
|
|
@ -1,16 +1,11 @@
|
||||||
from nose.tools import assert_is_instance, assert_equal
|
from nose.tools import assert_is_instance, assert_equal
|
||||||
import mock
|
|
||||||
from six import StringIO
|
|
||||||
from six.moves import builtins
|
|
||||||
from gixy.parser.nginx_parser import NginxParser
|
from gixy.parser.nginx_parser import NginxParser
|
||||||
from gixy.directives.directive import *
|
from gixy.directives.directive import *
|
||||||
from gixy.directives.block import *
|
from gixy.directives.block import *
|
||||||
|
|
||||||
|
|
||||||
def _parse(config):
|
def _parse(config):
|
||||||
with mock.patch('%s.open' % builtins.__name__) as mock_open:
|
return NginxParser(cwd='', allow_includes=False).parse(config)
|
||||||
mock_open.return_value = StringIO(config)
|
|
||||||
return NginxParser('/foo/bar', allow_includes=False).parse('/foo/bar')
|
|
||||||
|
|
||||||
|
|
||||||
def test_directive():
|
def test_directive():
|
||||||
|
|
|
@ -498,7 +498,5 @@ add_header X-Blank-Comment blank;
|
||||||
|
|
||||||
|
|
||||||
def assert_config(config, expected):
|
def assert_config(config, expected):
|
||||||
with mock.patch('%s.open' % builtins.__name__) as mock_open:
|
actual = RawParser().parse(config)
|
||||||
mock_open.return_value = StringIO(config)
|
assert_equals(actual.asList(), expected)
|
||||||
actual = RawParser().parse('/foo/bar')
|
|
||||||
assert_equals(actual.asList(), expected)
|
|
||||||
|
|
|
@ -81,7 +81,7 @@ def yoda_provider(plugin, plugin_options=None):
|
||||||
def check_configuration(plugin, config_path, test_config):
|
def check_configuration(plugin, config_path, test_config):
|
||||||
plugin_options = parse_plugin_options(config_path)
|
plugin_options = parse_plugin_options(config_path)
|
||||||
with yoda_provider(plugin, plugin_options) as yoda:
|
with yoda_provider(plugin, plugin_options) as yoda:
|
||||||
yoda.audit(config_path)
|
yoda.audit(config_path, open(config_path, mode='r'))
|
||||||
results = RawFormatter().format(yoda)
|
results = RawFormatter().format(yoda)
|
||||||
|
|
||||||
assert_equals(len(results), 1, 'Should have one report')
|
assert_equals(len(results), 1, 'Should have one report')
|
||||||
|
@ -102,7 +102,7 @@ def check_configuration(plugin, config_path, test_config):
|
||||||
|
|
||||||
def check_configuration_fp(plugin, config_path, test_config):
|
def check_configuration_fp(plugin, config_path, test_config):
|
||||||
with yoda_provider(plugin) as yoda:
|
with yoda_provider(plugin) as yoda:
|
||||||
yoda.audit(config_path)
|
yoda.audit(config_path, open(config_path, mode='r'))
|
||||||
results = RawFormatter().format(yoda)
|
results = RawFormatter().format(yoda)
|
||||||
|
|
||||||
assert_equals(len(results), 0,
|
assert_equals(len(results), 0,
|
||||||
|
|
Loading…
Reference in New Issue