diff --git a/README.md b/README.md index 8e99473..bf09e47 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # PHP-FPM Zabbix Template with Auto Discovery and Multiple Pools -![Zabbix versions](https://img.shields.io/badge/Zabbix_versions-5.0,_4.4,_4.2,_4.0-green.svg?style=flat) ![PHP](https://img.shields.io/badge/PHP-5.3.3+-blue.svg?style=flat) ![PHP7](https://img.shields.io/badge/PHP7-supported-green.svg?style=flat) ![LLD](https://img.shields.io/badge/LLD-yes-green.svg?style=flat) ![ISPConfig](https://img.shields.io/badge/ISPConfig-supported-green.svg?style=flat) [![Build Status](https://travis-ci.com/rvalitov/zabbix-php-fpm.svg?branch=master)](https://travis-ci.com/rvalitov/zabbix-php-fpm) [![CodeFactor](https://www.codefactor.io/repository/github/rvalitov/zabbix-php-fpm/badge)](https://www.codefactor.io/repository/github/rvalitov/zabbix-php-fpm) +![Zabbix versions](https://img.shields.io/badge/Zabbix_versions-5.0,_4.4,_4.2,_4.0-green.svg?style=flat) ![PHP](https://img.shields.io/badge/PHP-5.3.3+-blue.svg?style=flat) ![PHP7](https://img.shields.io/badge/PHP7-supported-green.svg?style=flat) ![LLD](https://img.shields.io/badge/LLD-yes-green.svg?style=flat) ![ISPConfig](https://img.shields.io/badge/ISPConfig-supported-green.svg?style=flat) ![Apache](https://img.shields.io/badge/Apache-tested-green.svg?style=flat) ![nginx](https://img.shields.io/badge/Nginx-tested-green.svg?style=flat) [![Build Status](https://travis-ci.com/rvalitov/zabbix-php-fpm.svg?branch=master)](https://travis-ci.com/rvalitov/zabbix-php-fpm) [![CodeFactor](https://www.codefactor.io/repository/github/rvalitov/zabbix-php-fpm/badge)](https://www.codefactor.io/repository/github/rvalitov/zabbix-php-fpm) ![Banner](https://github.com/rvalitov/zabbix-php-fpm/wiki/media/repository-open-graph-template.png) @@ -144,4 +144,6 @@ Please refer to [Wiki](https://github.com/rvalitov/zabbix-php-fpm/wiki/Testing-a - **Debian** 10, 9 - **Ubuntu** 18 Bionic, 16 Xenial, 14 Trusty - **CentOS** 7 -- **ISPConfig** v.3.1.14p2 +- [**Apache** web server](https://httpd.apache.org/) +- [**NGINX** web server](https://www.nginx.com/) +- [**ISPConfig**](https://www.ispconfig.org/) 3.1.14p2, 3.1.15p3 diff --git a/ispconfig/nginx.patch b/ispconfig/nginx.patch new file mode 100644 index 0000000..9e736a3 --- /dev/null +++ b/ispconfig/nginx.patch @@ -0,0 +1,11 @@ +--- ../conf/nginx_vhost.conf.master 2020-08-05 22:13:51.469316718 +0300 ++++ nginx_vhost.conf.master 2020-08-05 22:39:44.744479903 +0300 +@@ -164,7 +164,7 @@ + alias /usr/share/awstats/icon; + } + +- location ~ \.php$ { ++ location ~ (\.php|^/php-fpm-status)$ { + try_files @php; + } + diff --git a/ispconfig/nginx_vhost.conf.master b/ispconfig/nginx_vhost.conf.master new file mode 100644 index 0000000..77ac8ec --- /dev/null +++ b/ispconfig/nginx_vhost.conf.master @@ -0,0 +1,376 @@ +server { + listen :; + + listen []:; + + + listen [::]:; + + + listen : ssl{tmpl_if name='enable_http2' op='==' value='y'} http2{/tmpl_if}{tmpl_if name='enable_spdy' op='==' value='y'} spdy{/tmpl_if}; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + # ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS'; + # ssl_prefer_server_ciphers on; + + listen []: ssl{tmpl_if name='enable_http2' op='==' value='y'} http2{/tmpl_if}{tmpl_if name='enable_spdy' op='==' value='y'} spdy{/tmpl_if}; + + + listen [::]: ssl{tmpl_if name='enable_http2' op='==' value='y'} http2{/tmpl_if}{tmpl_if name='enable_spdy' op='==' value='y'} spdy{/tmpl_if}; + + ssl_certificate ; + ssl_certificate_key ; + + + server_name ; + + root ; + + + + if ($scheme != "https") { + rewrite ^ https://$http_host$request_uri? permanent; + } + + + + if ($http_host "") { + rewrite ^ $scheme://$request_uri? permanent; + } + + + if ($http_host "") { + rewrite ^ $scheme://$request_uri? permanent; + } + + + if ($http_host "") { + rewrite ^(.*)$ $2 ; + } + + + + + if ($http_host != "") { rewrite ^(.*)$ $2 ; } + + + location / { + proxy_pass ; + rewrite ^/(.*) /$1; + + + + } + + + + index index.html index.htm index.php index.cgi index.pl index.xhtml; + + + location ~ \.shtml$ { + ssi on; + } + + + + error_page 400 /error/400.html; + error_page 401 /error/401.html; + error_page 403 /error/403.html; + error_page 404 /error/404.html; + error_page 405 /error/405.html; + error_page 500 /error/500.html; + error_page 502 /error/502.html; + error_page 503 /error/503.html; + recursive_error_pages on; + location = /error/400.html { + + internal; + } + location = /error/401.html { + + internal; + } + location = /error/403.html { + + internal; + } + location = /error/404.html { + + internal; + } + location = /error/405.html { + + internal; + } + location = /error/500.html { + + internal; + } + location = /error/502.html { + + internal; + } + location = /error/503.html { + + internal; + } + + + + error_log /var/log/ispconfig/httpd//error.log; + access_log /var/log/ispconfig/httpd//access.log combined; + + + error_log /var/log/ispconfig/httpd//error.log; + access_log /var/log/ispconfig/httpd//access.log anonymized; + + + ## Disable .htaccess and other hidden files + location ~ /\. { + deny all; + } + + ## Allow access for .well-known/acme-challenge + location ^~ /.well-known/acme-challenge/ { + access_log off; + log_not_found off; + auth_basic off; + root /usr/local/ispconfig/interface/acme/; + autoindex off; + index index.html; + try_files $uri $uri/ =404; + } + + location = /favicon.ico { + log_not_found off; + access_log off; + expires max; + add_header Cache-Control "public, must-revalidate, proxy-revalidate"; + } + + location = /robots.txt { + allow all; + log_not_found off; + access_log off; + } + + location /stats/ { + + index index.html index.php; + auth_basic "Members Only"; + auth_basic_user_file ; + } + + location ^~ /awstats-icon { + alias /usr/share/awstats/icon; + } + + location ~ (\.php|^/php-fpm-status)$ { + try_files @php; + } + + + location @php { + try_files $uri =404; + include /etc/nginx/fastcgi_params; + + fastcgi_pass 127.0.0.1:; + + + fastcgi_pass unix:; + + fastcgi_index index.php; + + fastcgi_param DOCUMENT_ROOT ; + fastcgi_param HOME ; + fastcgi_param SCRIPT_FILENAME $fastcgi_script_name; + + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + + #fastcgi_param PATH_INFO $fastcgi_script_name; + fastcgi_intercept_errors on; + } + + + location @php { + try_files $uri =404; + include /etc/nginx/fastcgi_params; + fastcgi_pass unix:/var/run/hhvm/hhvm..sock; + fastcgi_index index.php; + + fastcgi_param DOCUMENT_ROOT ; + fastcgi_param HOME ; + fastcgi_param SCRIPT_FILENAME $fastcgi_script_name; + + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + + #fastcgi_param PATH_INFO $fastcgi_script_name; + fastcgi_intercept_errors on; + error_page 500 501 502 503 = @phpfallback; + } + + location @phpfallback { + try_files $uri =404; + include /etc/nginx/fastcgi_params; + + fastcgi_pass 127.0.0.1:; + + + fastcgi_pass unix:; + + fastcgi_index index.php; + + fastcgi_param DOCUMENT_ROOT ; + fastcgi_param HOME ; + fastcgi_param SCRIPT_FILENAME $fastcgi_script_name; + + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + + #fastcgi_param PATH_INFO $fastcgi_script_name; + fastcgi_intercept_errors on; + } + + + location @php { + deny all; + } + + + + + location /cgi-bin/ { + try_files $uri =404; + include /etc/nginx/fastcgi_params; + root ; + gzip off; + fastcgi_pass unix:/var/run/fcgiwrap.socket; + fastcgi_index index.cgi; + + fastcgi_param DOCUMENT_ROOT ; + fastcgi_param HOME ; + fastcgi_param SCRIPT_FILENAME $fastcgi_script_name; + + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + + fastcgi_intercept_errors on; + } + + + + + + + + + + + + pagespeed on; + pagespeed FileCachePath /var/ngx_pagespeed_cache; + pagespeed FetchHttps enable,allow_self_signed; + + + # let's speed up PageSpeed by storing it in the super duper fast memcached + pagespeed MemcachedThreads 1; + pagespeed MemcachedServers "localhost:11211"; + + # Filter settings + pagespeed RewriteLevel CoreFilters; + pagespeed EnableFilters collapse_whitespace,remove_comments; + + # Ensure requests for pagespeed optimized resources go to the pagespeed + # handler and no extraneous headers get set. + location ~ "\.pagespeed\.([a-z]\.)?[a-z]{2}\.[^.]{10}\.[^.]+" { + add_header "" ""; + access_log off; + } + location ~ "^/ngx_pagespeed_static/" { + access_log off; + } + location ~ "^/ngx_pagespeed_beacon$" { + access_log off; + } + location /ngx_pagespeed_statistics { + allow 127.0.0.1; + deny all; + access_log off; + } + location /ngx_pagespeed_global_statistics { + allow 127.0.0.1; + deny all; + access_log off; + } + location /ngx_pagespeed_message { + allow 127.0.0.1; + deny all; + access_log off; + } + location /pagespeed_console { + allow 127.0.0.1; + deny all; + access_log off; + } + + + + location { ##merge## + auth_basic "Members Only"; + auth_basic_user_file .htpasswd; + + location ~ \.php$ { + try_files @php; + } + } + + +} + + +server { + listen :80; + + listen []:80; + + + + listen :443 ssl; + + listen []:443 ssl; + + ssl_certificate ; + ssl_certificate_key ; + + + server_name ; + + + + if ($http_host "") { + rewrite ^ $scheme://$request_uri? permanent; + } + + + ## no redirect for acme + location ^~ /.well-known/acme-challenge/ { + access_log off; + log_not_found off; + root /usr/local/ispconfig/interface/acme/; + autoindex off; + index index.html; + try_files $uri $uri/ =404; + } + + location / { + rewrite ^ $request_uri? ; + } + + + location / { + proxy_pass ; + rewrite ^/(.*) /$1; + + + + } + +} + diff --git a/ispconfig/ispconfig.patch b/ispconfig/php-fpm.patch similarity index 100% rename from ispconfig/ispconfig.patch rename to ispconfig/php-fpm.patch diff --git a/tests/all.sh b/tests/all.sh index 1c1bf93..db58c11 100644 --- a/tests/all.sh +++ b/tests/all.sh @@ -562,6 +562,23 @@ testZabbixGetVersion() { printSuccess "${FUNCNAME[0]}" } +testNonRootUserPrivilegesDiscovery() { + #Run the script under non root user + DATA=$(sudo -u zabbix "/etc/zabbix/zabbix_php_fpm_discovery.sh") + IS_OK=$(echo "$DATA" | grep -F 'Insufficient privileges') + assertNotNull "The discovery script must not work for non root user" "$IS_OK" + printSuccess "${FUNCNAME[0]}" +} + +testNonRootUserPrivilegesStatus() { + #Run the script under non root user + assertNotNull "Test socket is not defined" "$TEST_SOCKET" + DATA=$(sudo -u zabbix "/etc/zabbix/zabbix_php_fpm_status.sh" "$TEST_SOCKET" "/php-fpm-status") + IS_OK=$(echo "$DATA" | grep -F 'Insufficient privileges') + assertNotNull "The status script must not work for non root user" "$IS_OK" + printSuccess "${FUNCNAME[0]}" +} + testPHPIsRunning() { IS_OK=$(sudo ps ax | grep -F "php-fpm: pool " | grep -F -v "grep" | head -n1) assertNotNull "No running PHP-FPM instances found" "$IS_OK" diff --git a/zabbix/zabbix_php_fpm_discovery.sh b/zabbix/zabbix_php_fpm_discovery.sh index f2954ea..4fa9b73 100644 --- a/zabbix/zabbix_php_fpm_discovery.sh +++ b/zabbix/zabbix_php_fpm_discovery.sh @@ -136,6 +136,12 @@ if [[ ! -d "$CACHE_ROOT" ]]; then exit 1 fi +USER_ID=$(id -u) +if [[ $USER_ID -ne 0 ]]; then + echo "Insufficient privileges. This script must be run under 'root' user or with 'sudo'." + exit 1 +fi + function createCacheDirectory() { if [[ ! -d "$CACHE_DIRECTORY" ]]; then mkdir "$CACHE_DIRECTORY" @@ -237,6 +243,7 @@ function UpdatePoolInCache() { local ITEM_POOL_TYPE # shellcheck disable=SC2016 ITEM_POOL_TYPE=$(echo "$CACHE_ITEM" | ${S_AWK} '{print $3}') + if [[ $ITEM_NAME == "$POOL_NAME" && $ITEM_SOCKET == "$POOL_SOCKET" ]] || [[ -z $ITEM_POOL_TYPE ]]; then PrintDebug "Pool $POOL_NAME $POOL_SOCKET is in cache, deleting..." #Deleting the pool first @@ -726,7 +733,6 @@ EOF ARG_ID=$((ARG_ID + 1)) shift 1 done - PrintDebug "Current user is $ACTIVE_USER" PrintDebug "Status path to be used: $STATUS_PATH" @@ -789,6 +795,7 @@ PrintDebug "Processing pools" PARALLEL_TASKS=0 TASK_LIST=() LAST_PENDING_ITEM=${PENDING_LIST[${#PENDING_LIST[@]} - 1]} + for POOL_ITEM in "${PENDING_LIST[@]}"; do # shellcheck disable=SC2016 POOL_NAME=$(echo "$POOL_ITEM" | $S_AWK '{print $1}') diff --git a/zabbix/zabbix_php_fpm_status.sh b/zabbix/zabbix_php_fpm_status.sh index dcb6018..b4669c9 100644 --- a/zabbix/zabbix_php_fpm_status.sh +++ b/zabbix/zabbix_php_fpm_status.sh @@ -20,6 +20,12 @@ if [[ ! -x $S_GREP ]]; then exit 1 fi +USER_ID=$(id -u) +if [[ $USER_ID -ne 0 ]]; then + echo "Insufficient privileges. This script must be run under 'root' user or with 'sudo'." + exit 1 +fi + if [[ -z $1 ]] || [[ -z $2 ]]; then $S_CAT <