From a21d887dbe45ef4f1df284e57ac0a7689e49dd79 Mon Sep 17 00:00:00 2001 From: Bernd Eidenschink Date: Thu, 11 May 2017 16:07:28 +0200 Subject: [PATCH 01/11] Fix typo "$host" holds the described value, not "$http" --- docs/en/plugins/hostspoofing.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/en/plugins/hostspoofing.md b/docs/en/plugins/hostspoofing.md index 1447f0b..a751ae3 100644 --- a/docs/en/plugins/hostspoofing.md +++ b/docs/en/plugins/hostspoofing.md @@ -10,7 +10,7 @@ Spoofing of this header, may leads to a variety of problems, from phishing to SS Most of the time it's a result of using `$http_host` variable instead of `$host`. And they are quite different: - * `$http` - host in this order of precedence: host name from the request line, or host name from the “Host” request header field, or the server name matching a request; + * `$host` - host in this order of precedence: host name from the request line, or host name from the “Host” request header field, or the server name matching a request; * `$http_host` - "Host" request header. Config sample: @@ -29,4 +29,4 @@ Luckily, all is quite obvious: ## Additional info * [Host of Troubles Vulnerabilities](https://hostoftroubles.com/) - * [Practical HTTP Host header attacks](http://www.skeletonscribe.net/2013/05/practical-http-host-header-attacks.html) \ No newline at end of file + * [Practical HTTP Host header attacks](http://www.skeletonscribe.net/2013/05/practical-http-host-header-attacks.html) From 746c255ab227649ed1971f4aa6f69b44fc8edc4e Mon Sep 17 00:00:00 2001 From: Jason Novinger Date: Thu, 11 May 2017 15:10:23 -0500 Subject: [PATCH 02/11] Minor grammar fix "doesn't" --> "don't" --- docs/en/plugins/addheaderredefinition.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/plugins/addheaderredefinition.md b/docs/en/plugins/addheaderredefinition.md index 8eef0c4..5fe5742 100644 --- a/docs/en/plugins/addheaderredefinition.md +++ b/docs/en/plugins/addheaderredefinition.md @@ -1,6 +1,6 @@ # [add_header_redefinition] Redefining of response headers by "add_header" directive -Unfortunately, many people doesn't know how the inheritance of directives works. Most often this leads to misuse of the `add_header` directive while trying to add a new response header on the nested level. +Unfortunately, many people don't know how the inheritance of directives works. Most often this leads to misuse of the `add_header` directive while trying to add a new response header on the nested level. This feature is mentioned in Nginx [docs](http://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header): > There could be several `add_header` directives. These directives are inherited from the previous level if and only if there are no `add_header` directives defined on the current level. From f7de6bf6ffeed979f9c8ad1b10609bf2c7f10181 Mon Sep 17 00:00:00 2001 From: Andrew Krasichkov Date: Thu, 11 May 2017 23:35:36 +0300 Subject: [PATCH 03/11] Added tox to dev dependencies --- requirements.dev.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/requirements.dev.txt b/requirements.dev.txt index 3696f8e..ea9085e 100644 --- a/requirements.dev.txt +++ b/requirements.dev.txt @@ -1,4 +1,5 @@ nose>=1.3.7 mock>=2.0.0 coverage>=4.3 -flake8>=3.2 \ No newline at end of file +flake8>=3.2 +tox>=2.7.0 \ No newline at end of file From 8486606456577d456d1939bb18cea7fc0f9c7a74 Mon Sep 17 00:00:00 2001 From: Andrew Krasichkov Date: Fri, 12 May 2017 19:40:14 +0300 Subject: [PATCH 04/11] Better error message for "if" directive --- gixy/directives/block.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gixy/directives/block.py b/gixy/directives/block.py index e55b725..0dd2651 100644 --- a/gixy/directives/block.py +++ b/gixy/directives/block.py @@ -141,7 +141,7 @@ class IfBlock(Block): # if ($request_method = POST) self.variable, self.operand, self.value = args else: - raise Exception('Unknown "if" definition') + raise Exception('Unknown "if" definition, args: {}'.format(repr(args))) def __str__(self): return '{} ({}) {{'.format(self.name, ' '.join(self.args)) From 75b0e33546d4a61855a9ff28d09e0ff839b495ef Mon Sep 17 00:00:00 2001 From: Tommy Brunn Date: Fri, 12 May 2017 10:41:39 +0200 Subject: [PATCH 05/11] Add Dockerfile --- Dockerfile | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..55c33b7 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +FROM alpine:3.5 + +RUN apk add --no-cache python py-pip ca-certificates && \ + pip install --upgrade setuptools + +ADD . /src + +WORKDIR /src + +RUN python setup.py install + +ENTRYPOINT ["gixy"] \ No newline at end of file From ff42a521c4ca178c06c3ee9552d25d022f7def3c Mon Sep 17 00:00:00 2001 From: Tommy Brunn Date: Fri, 12 May 2017 11:06:08 +0200 Subject: [PATCH 06/11] Add trailing newline --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 55c33b7..28a6e44 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,4 +9,4 @@ WORKDIR /src RUN python setup.py install -ENTRYPOINT ["gixy"] \ No newline at end of file +ENTRYPOINT ["gixy"] From 85d075e3ec0b092b0590aa509c0e5dbcb3ff950c Mon Sep 17 00:00:00 2001 From: Tommy Brunn Date: Sat, 13 May 2017 11:28:26 +0200 Subject: [PATCH 07/11] Rebase docker image on python:2.7-alpine --- Dockerfile | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 28a6e44..ef7066e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,12 +1,9 @@ -FROM alpine:3.5 - -RUN apk add --no-cache python py-pip ca-certificates && \ - pip install --upgrade setuptools +FROM python:2.7-alpine ADD . /src WORKDIR /src -RUN python setup.py install +RUN python2 setup.py install ENTRYPOINT ["gixy"] From 3fcc7f7eae4c04016dcaedec2241ed0b647bd2f7 Mon Sep 17 00:00:00 2001 From: Andrew Krasichkov Date: Sat, 13 May 2017 13:23:49 +0300 Subject: [PATCH 08/11] Added dockerignore --- .dockerignore | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..5d9df55 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,57 @@ +# Byte-compiled / optimized / DLL files +**/__pycache__/ +**/*.py[cod] + +# C extensions +***/*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +cover + +# Translations +**/*.mo +**/*.pot + +# PyBuilder +target/ + +venv/ +venv3/ +.idea/ + +# 100% unnecessary for docker image +.* +*.md +docs +rpm +Dockerfile From 7d182dbdbac77cfdf863875de3ac9a62118cc8fa Mon Sep 17 00:00:00 2001 From: Andrew Krasichkov Date: Sat, 13 May 2017 13:39:21 +0300 Subject: [PATCH 09/11] Added editorconfig --- .editorconfig | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..abd7688 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,19 @@ +root = true + +[*] +end_of_file = lf +insert_final_newline = true + +[*.{py,j2}] +charset = utf-8 + +[*.py] +indent_style = space +indent_size = 4 + +[Makefile] +indent_style = tab + +[.travis.yml] +indent_style = space +indent_size = 2 From 26b2ead72c3be89333a29baec3d0aa000b768327 Mon Sep 17 00:00:00 2001 From: Andrew Krasichkov Date: Fri, 12 May 2017 19:43:42 +0300 Subject: [PATCH 10/11] Added new test cases for "if" directive parsing --- tests/parser/test_raw_parser.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/parser/test_raw_parser.py b/tests/parser/test_raw_parser.py index e4d55f7..a34d8c4 100644 --- a/tests/parser/test_raw_parser.py +++ b/tests/parser/test_raw_parser.py @@ -225,11 +225,14 @@ if (!-e "/var/data/$dataset") { return 503; } -if ($https_or_slb = (by_slb|https)) { +if ($https_or_slb = (by_\(sl\)b|https)) { } if ($host ~* (lori|rage2)\.yandex\.(ru|ua|com|com\.tr)) { set $x_frame_options ALLOW; +} + +if ($request_filename ~* ^.*?/(\d+_)([^/]+)$) { } ''' @@ -253,11 +256,13 @@ if ($host ~* (lori|rage2)\.yandex\.(ru|ua|com|com\.tr)) { ['if', ['!-e', '/var/data/$dataset'], [ ['return', '503'] ]], - ['if', ['$https_or_slb', '=', '(by_slb|https)'], [ + ['if', ['$https_or_slb', '=', '(by_\(sl\)b|https)'], [ ]], ['if', ['$host', '~*', '(lori|rage2)\.yandex\.(ru|ua|com|com\.tr)'], [ ['set', '$x_frame_options', 'ALLOW'] ]], + ['if', ['$request_filename', '~*', '^.*?/(\d+_)([^/]+)$'], [ + ]] ] assert_config(config, expected) From 625a25db46b6fec2c67575883929b8733da00937 Mon Sep 17 00:00:00 2001 From: Andrew Krasichkov Date: Fri, 12 May 2017 19:46:47 +0300 Subject: [PATCH 11/11] Another workaround for "if" directive parsing with unquoted regex --- gixy/parser/raw_parser.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/gixy/parser/raw_parser.py b/gixy/parser/raw_parser.py index e2fdd59..0463a19 100644 --- a/gixy/parser/raw_parser.py +++ b/gixy/parser/raw_parser.py @@ -1,4 +1,3 @@ -import re import logging from cached_property import cached_property @@ -31,9 +30,7 @@ class RawParser(object): """ Returns the parsed tree. """ - # Temporary, dirty hack :( content = open(file_path).read() - content = re.sub(r'(if\s.+)\)\)(\s*\{)?$', '\\1) )\\2', content, flags=re.MULTILINE) return self.script.parseString(content, parseAll=True) # return self.script.parseFile(file_path, parseAll=True) @@ -61,10 +58,15 @@ class RawParser(object): Keyword("=") | Keyword("~*") | Keyword("~") | (Literal("-") + (Literal("f") | Literal("d") | Literal("e") | Literal("x"))))) - condition = ( + condition_body = ( (if_modifier + Optional(space) + value) | (variable + Optional(space + if_modifier + Optional(space) + value)) ) + # This ugly workaround needed to parse unquoted regex with nested parentheses + # pyparsing.nestedExpr doesn't work in some rare cases like: ($http_user_agent ~* \( ) + # so we capture all content between parentheses and then parse it:) + # TODO(buglloc): may be use something better? + condition = Regex(r'\(.*\)').setParseAction(lambda s, l, t: condition_body.parseString(t[0][1:-1])) # rules include = ( @@ -114,9 +116,7 @@ class RawParser(object): if_block << ( Keyword("if") + - Suppress("(") + Group(condition) + - Suppress(")") + Group( left_bracket + Optional(sub_block) +