diff --git a/.github/workflows/autotest-bunkerized-nginx.yml b/.github/workflows/autotest-bunkerized-nginx.yml index 503104d..f34c7d7 100644 --- a/.github/workflows/autotest-bunkerized-nginx.yml +++ b/.github/workflows/autotest-bunkerized-nginx.yml @@ -24,5 +24,3 @@ jobs: exit-code: '1' ignore-unfixed: true severity: 'UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL' - skip-dirs: '/usr/lib/go' - diff --git a/confs/global/api-temp.conf b/confs/global/api-temp.conf index bdf46ae..a68ca55 100644 --- a/confs/global/api-temp.conf +++ b/confs/global/api-temp.conf @@ -7,10 +7,11 @@ location ~ ^%API_URI% { rewrite_by_lua_block { - local api = require "api" - local api_uri = "%API_URI%" + local api = require "api" + local api_whitelist_ip = {%API_WHITELIST_IP%} + local api_uri = "%API_URI%" - if api.is_api_call(api_uri) then + if api.is_api_call(api_uri, api_whitelist_ip) then ngx.header.content_type = 'text/plain' if api.do_api_call(api_uri) then ngx.log(ngx.NOTICE, "[API] API call " .. ngx.var.request_uri .. " successfull from " .. ngx.var.remote_addr) diff --git a/confs/global/api.conf b/confs/global/api.conf index 86aae9d..e306120 100644 --- a/confs/global/api.conf +++ b/confs/global/api.conf @@ -1,9 +1,10 @@ rewrite_by_lua_block { - local api = require "api" - local api_uri = "%API_URI%" + local api = require "api" + local api_whitelist_ip = {%API_WHITELIST_IP%} + local api_uri = "%API_URI%" - if api.is_api_call(api_uri) then + if api.is_api_call(api_uri, api_whitelist_ip) then ngx.header.content_type = 'text/plain' if api.do_api_call(api_uri) then ngx.log(ngx.NOTICE, "[API] API call " .. ngx.var.request_uri .. " successfull from " .. ngx.var.remote_addr) diff --git a/entrypoint/global-config.sh b/entrypoint/global-config.sh index 1ec0a41..a55051e 100644 --- a/entrypoint/global-config.sh +++ b/entrypoint/global-config.sh @@ -242,6 +242,8 @@ if [ "$USE_API" = "yes" ] ; then echo "[*] Generated API URI : $API_URI" fi replace_in_file "/etc/nginx/api.conf" "%API_URI%" "$API_URI" + list=$(spaces_to_lua "$API_WHITELIST_IP") + replace_in_file "/etc/nginx/api.conf" "%API_WHITELIST_IP%" "$list" else replace_in_file "/etc/nginx/nginx.conf" "%USE_API%" "" fi diff --git a/entrypoint/lua.sh b/entrypoint/lua.sh index fd49586..fc4eb1f 100644 --- a/entrypoint/lua.sh +++ b/entrypoint/lua.sh @@ -45,9 +45,3 @@ if [ "$(has_value USE_CROWDSEC yes)" != "" ] ; then replace_in_file "/usr/local/lib/lua/crowdsec/crowdsec.conf" "%CROWDSEC_HOST%" "$CROWDSEC_HOST" replace_in_file "/usr/local/lib/lua/crowdsec/crowdsec.conf" "%CROWDSEC_KEY%" "$CROWDSEC_KEY" fi - -# Whitelist IP for API -if [ "$USE_API" = "yes" ] ; then - list=$(spaces_to_lua "$API_WHITELIST_IP") - replace_in_file "/usr/local/lib/lua/api.lua" "%API_WHITELIST_IP%" "$list" -fi diff --git a/entrypoint/nginx-temp.sh b/entrypoint/nginx-temp.sh index 4547e97..c254481 100644 --- a/entrypoint/nginx-temp.sh +++ b/entrypoint/nginx-temp.sh @@ -13,6 +13,8 @@ if [ "$(has_value AUTO_LETS_ENCRYPT yes)" != "" ] || [ "$SWARM_MODE" = "yes" ] ; if [ "$SWARM_MODE" = "yes" ] ; then replace_in_file "/tmp/nginx-temp.conf" "%USE_API%" "include /tmp/api.conf;" replace_in_file "/tmp/api.conf" "%API_URI%" "$API_URI" + list=$(spaces_to_lua "$API_WHITELIST_IP") + replace_in_file "/tmp/api.conf" "%API_WHITELIST_IP%" "$list" else replace_in_file "/tmp/nginx-temp.conf" "%USE_API%" "" fi diff --git a/examples/crowdsec/docker-compose.yml b/examples/crowdsec/docker-compose.yml index ccca0b5..50dda62 100644 --- a/examples/crowdsec/docker-compose.yml +++ b/examples/crowdsec/docker-compose.yml @@ -3,7 +3,7 @@ version: '3' services: mywww: - image: debug + image: bunkerity/bunkerized-nginx restart: always # mandatory for crowdsec : # you need to redirect Docker logs to the syslog server diff --git a/examples/hardened/docker-compose.yml b/examples/hardened/docker-compose.yml new file mode 100644 index 0000000..fea338f --- /dev/null +++ b/examples/hardened/docker-compose.yml @@ -0,0 +1,42 @@ +version: '3' + +services: + + mywww: + image: bunkerity/bunkerized-nginx + # dropping all capabilities + cap_drop: + - ALL + # root fs as RO + read_only: true + # mandatory directories as RW + tmpfs: + - /tmp:mode=770,uid=0,gid=101 + restart: always + ports: + - 80:8080 + - 443:8443 + # bunkerized-nginx runs as an unprivileged user with UID/GID 101 + # don't forget to edit the permissions of the files and folders accordingly + volumes: + - nginx_conf:/etc/nginx + - ./web-files:/www:ro + - ./letsencrypt:/etc/letsencrypt + environment: + - SERVER_NAME=www.website.com # replace with your domain + - AUTO_LETS_ENCRYPT=yes + - REDIRECT_HTTP_TO_HTTPS=yes + - DISABLE_DEFAULT_SERVER=yes + - USE_CLIENT_CACHE=yes + - USE_GZIP=yes + - REMOTE_PHP=myphp + - REMOTE_PHP_PATH=/app + + myphp: + image: php:fpm + restart: always + volumes: + - ./web-files:/app + +volumes: + nginx_conf: diff --git a/examples/hardened/web-files/index.php b/examples/hardened/web-files/index.php new file mode 100644 index 0000000..61d3ee1 --- /dev/null +++ b/examples/hardened/web-files/index.php @@ -0,0 +1,5 @@ + diff --git a/examples/syslog/docker-compose.yml b/examples/syslog/docker-compose.yml new file mode 100644 index 0000000..b566ffd --- /dev/null +++ b/examples/syslog/docker-compose.yml @@ -0,0 +1,80 @@ +version: '3' + +services: + + mywww: + image: bunkerity/bunkerized-nginx + restart: always + logging: + driver: syslog + options: + syslog-address: "udp://10.10.10.254:514" + depends_on: + - mysyslog + - myapp1 + - myapp2 + ports: + - 80:8080 + - 443:8443 + # bunkerized-nginx runs as an unprivileged user with UID/GID 101 + # don't forget to edit the permissions of the files and folders accordingly + volumes: + - ./web-files:/www:ro + - ./letsencrypt:/etc/letsencrypt + environment: + - SERVER_NAME=app1.website.com app2.website.com # replace with your domains + - MULTISITE=yes + - AUTO_LETS_ENCRYPT=yes + - REDIRECT_HTTP_TO_HTTPS=yes + - DISABLE_DEFAULT_SERVER=yes + - USE_CLIENT_CACHE=yes + - USE_GZIP=yes + - USE_CROWDSEC=yes + - CROWDSEC_HOST=http://mycrowdsec:8080 + - CROWDSEC_KEY= # you need to generate it (see bouncer_key.sh) + - app1.website.com_REMOTE_PHP=myapp1 + - app1.website.com_REMOTE_PHP_PATH=/app + - app2.website.com_REMOTE_PHP=myapp2 + - app2.website.com_REMOTE_PHP_PATH=/app + networks: + net0: + net1: + net2: + + mysyslog: + image: balabit/syslog-ng + restart: always + volumes: + - ./syslog-ng.conf:/etc/syslog-ng/syslog-ng.conf + - ./log:/var/log + networks: + net0: + ipv4_address: 10.10.10.254 + + myapp1: + image: php:fpm + restart: always + volumes: + - ./web-files/app1.website.com:/app + networks: + - net1 + + myapp2: + image: php:fpm + restart: always + volumes: + - ./web-files/app2.website.com:/app + networks: + - net2 + +networks: + net0: + ipam: + driver: default + config: + - subnet: 10.10.10.0/24 + net1: + net2: + +volumes: + nginx_logs: diff --git a/examples/syslog/syslog-ng.conf b/examples/syslog/syslog-ng.conf new file mode 100644 index 0000000..9609387 --- /dev/null +++ b/examples/syslog/syslog-ng.conf @@ -0,0 +1,18 @@ +@version: 3.31 + +source s_net { + udp( + ip("0.0.0.0") + ); +}; + +template t_imp { + template("$MSG\n"); + template_escape(no); +}; + +destination d_file { + file("/var/log/nginx.log" template(t_imp)); +}; + +log { source(s_net); destination(d_file); }; diff --git a/examples/syslog/web-files/app1.website.com/index.php b/examples/syslog/web-files/app1.website.com/index.php new file mode 100644 index 0000000..e5e25c9 --- /dev/null +++ b/examples/syslog/web-files/app1.website.com/index.php @@ -0,0 +1,5 @@ + diff --git a/examples/syslog/web-files/app2.website.com/index.php b/examples/syslog/web-files/app2.website.com/index.php new file mode 100644 index 0000000..69971d5 --- /dev/null +++ b/examples/syslog/web-files/app2.website.com/index.php @@ -0,0 +1,5 @@ + diff --git a/lua/api.lua b/lua/api.lua index e181cef..4f6d9a4 100644 --- a/lua/api.lua +++ b/lua/api.lua @@ -1,20 +1,19 @@ -local M = {} -local api_list = {} -local api_whitelist_ip = {%API_WHITELIST_IP%} -local iputils = require "resty.iputils" -local whitelist = iputils.parse_cidrs(api_whitelist_ip) +local M = {} +M.api_list = {} +local iputils = require "resty.iputils" -api_list["^/ping$"] = function () +M.api_list["^/ping$"] = function () return true end -api_list["^/reload$"] = function () +M.api_list["^/reload$"] = function () return os.execute("/usr/sbin/nginx -s reload") == 0 end -function M.is_api_call (api_uri) +function M.is_api_call (api_uri, api_whitelist_ip) + local whitelist = iputils.parse_cidrs(api_whitelist_ip) if iputils.ip_in_cidrs(ngx.var.remote_addr, whitelist) and ngx.var.request_uri:sub(1, #api_uri) .. "/" == api_uri .. "/" then - for uri, code in pairs(api_list) do + for uri, code in pairs(M.api_list) do if string.match(ngx.var.request_uri:sub(#api_uri + 1), uri) then return true end @@ -24,7 +23,7 @@ function M.is_api_call (api_uri) end function M.do_api_call (api_uri) - for uri, code in pairs(api_list) do + for uri, code in pairs(M.api_list) do if string.match(ngx.var.request_uri:sub(#api_uri + 1), uri) then return code() end