precommit + update services mode and filters

* remove simple mode for current version
* fix input filtering and services modal
This commit is contained in:
Jordan Blasenhauer 2024-05-03 11:43:42 +02:00
parent 2df047a18c
commit b1945e1be0
11 changed files with 459 additions and 1330 deletions

View file

@ -1,129 +1,129 @@
{
"name": "medium",
"description": "Generic settings template with high security level required for your web service. False positives will certainly appear without any custom edit.",
"steps": [
"name": "medium",
"description": "Generic settings template with high security level required for your web service. False positives will certainly appear without any custom edit.",
"steps": [
{
"name": "Server configuration",
"description": "Configure your server name and reverse proxy settings. Don't forget to add the corresponding DNS A entry pointing to your BunkerWeb IP.",
"settings": {
"SERVER_NAME": "www.example.com",
"USE_REVERSE_PROXY": "yes",
"REVERSE_PROXY_HOST": "http://my-upstream-server:8080",
"REVERSE_PROXY_URL": "/",
"REVERSE_PROXY_INTERCEPT_ERRORS": "yes",
"REVERSE_PROXY_WS": "no",
"REVERSE_PROXY_CUSTOM_HOST": "",
"REVERSE_PROXY_HEADERS": "Accept-Encoding ''",
"SERVE_FILES": "no"
}
},
{
"name": "HTTPS",
"description": "Enable/disable and configure HTTPS for your service.",
"settings": {
"AUTO_LETS_ENCRYPT": "yes",
"SSL_PROTOCOLS": "TLSv1.3"
}
},
{
"name": "HTTP configuration",
"description": "Miscellaneous settings related to HTTP protocol.",
"settings": {
"DENY_HTTP_STATUS": "444",
"USE_GZIP": "yes",
"USE_BROTLI": "yes",
"ALLOWED_METHODS": "GET|POST|HEAD",
"MAX_SIZES": "10m",
"COOKIE_FLAGS": "* HttpOnly SameSite=Lax",
"CONTENT_SECURITY_POLICY": "object-src 'none'; form-action 'self'; frame-ancestors 'self';",
"X_FRAME_OPTIONS": "SAMEORIGIN",
"PERMISSIONS_POLICY": "accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), cross-origin-isolated=(), display-capture=(), document-domain=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(), geolocation=(), gyroscope=(), hid=(), idle-detection=(), magnetometer=(), microphone=(), midi=(), navigation-override=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), serial=(), usb=(), web-share=(), xr-spatial-tracking=()",
"FEATURE_POLICY": "accelerometer 'none'; ambient-light-sensor 'none'; autoplay 'none'; battery 'none'; camera 'none'; display-capture 'none'; document-domain 'none'; encrypted-media 'none'; execution-while-not-rendered 'none'; execution-while-out-of-viewport 'none'; fullscreen 'none'; geolocation 'none'; gyroscope 'none'; layout-animation 'none'; legacy-image-formats 'none'; magnetometer 'none'; microphone 'none'; midi 'none'; navigation-override 'none'; payment 'none'; picture-in-picture 'none'; publickey-credentials-get 'none'; speaker-selection 'none'; sync-xhr 'none'; unoptimized-images 'none'; unsized-media 'none'; usb 'none'; screen-wake-lock 'none'; web-share 'none'; xr-spatial-tracking 'none';"
}
},
{
"name": "Bad behavior",
"description": "Configure automatic bans when detecting bad behaviors on your web service.",
"settings": {
"USE_BAD_BEHAVIOR": "yes",
"BAD_BEHAVIOR_STATUS_CODES": "400 401 403 404 405 429 444",
"BAD_BEHAVIOR_BAN_TIME": "86400",
"BAD_BEHAVIOR_THRESHOLD": "5",
"BAD_BEHAVIOR_COUNT_TIME": "60"
}
},
{
"name": "Limit",
"description": "Configure requests and connections limits on your web service.",
"settings": {
"USE_LIMIT_CONN": "yes",
"LIMIT_CONN_MAX_HTTP1": "10",
"LIMIT_CONN_MAX_HTTP2": "100",
"USE_LIMIT_REQ": "yes",
"LIMIT_REQ_URL": "/",
"LIMIT_REQ_RATE": "2r/s"
}
},
{
"name": "DNSBL",
"description": "Enable/disable DNSBL protection. Might generate false positives especially if you have a worldwide audience.",
"settings": {
"USE_DNSBL": "yes"
}
},
{
"name": "Country",
"description": "Configure allowed countries to reach out your web service. Recommended if you protect a restricted area such as extranet or administration panel.",
"settings": {
"WHITELIST_COUNTRY": ""
}
},
{
"name": "Antibot",
"description": "Enable/disable and configure antibot protection globally on your web service.",
"settings": {
"USE_ANTIBOT": "captcha",
"ANTIBOT_TIME_RESOLVE": "120",
"ANTIBOT_TIME_VALID": "86400",
"ANTIBOT_RECAPTCHA_SCORE": "0.7",
"ANTIBOT_RECAPTCHA_SITEKEY": "",
"ANTIBOT_RECAPTCHA_SECRET": "",
"ANTIBOT_HCAPTCHA_SITEKEY": "",
"ANTIBOT_HCAPTCHA_SECRET": "",
"ANTIBOT_TURNSTILE_SITEKEY": "",
"ANTIBOT_TURNSTILE_SECRET": ""
}
},
{
"name": "CORS",
"description": "Configure Cross-Origin Resource Sharing (CORS) to allow/deny external requests to your web service.",
"settings": {
"USE_CORS": "yes",
"CORS_ALLOW_ORIGIN": ""
}
},
{
"name": "Reverse scan",
"description": "Configure reverse scan of client to detect open proxy or datacenter connections.",
"settings": {
"USE_REVERSE_SCAN": "yes",
"REVERSE_SCAN_PORTS": "22 80 443 3128 8000 8080"
}
},
{
"name": "ModSecurity",
"description": "Enable/disable and configure ModSecurity on your web service.",
"settings": {
"USE_MODSECURITY": "yes",
"MODSECURITY_CRS_VERSION": "4"
},
"configs": [
{
"name": "Server configuration",
"description": "Configure your server name and reverse proxy settings. Don't forget to add the corresponding DNS A entry pointing to your BunkerWeb IP.",
"settings": {
"SERVER_NAME": "www.example.com",
"USE_REVERSE_PROXY": "yes",
"REVERSE_PROXY_HOST": "http://my-upstream-server:8080",
"REVERSE_PROXY_URL": "/",
"REVERSE_PROXY_INTERCEPT_ERRORS": "yes",
"REVERSE_PROXY_WS": "no",
"REVERSE_PROXY_CUSTOM_HOST": "",
"REVERSE_PROXY_HEADERS": "Accept-Encoding ''",
"SERVE_FILES": "no"
}
},
{
"name": "HTTPS",
"description": "Enable/disable and configure HTTPS for your service.",
"settings": {
"AUTO_LETS_ENCRYPT": "yes",
"SSL_PROTOCOLS": "TLSv1.3"
}
},
{
"name": "HTTP configuration",
"description": "Miscellaneous settings related to HTTP protocol.",
"settings": {
"DENY_HTTP_STATUS": "444",
"USE_GZIP": "yes",
"USE_BROTLI": "yes",
"ALLOWED_METHODS": "GET|POST|HEAD",
"MAX_SIZES": "10m",
"COOKIE_FLAGS": "* HttpOnly SameSite=Lax",
"CONTENT_SECURITY_POLICY": "object-src 'none'; form-action 'self'; frame-ancestors 'self';",
"X_FRAME_OPTIONS": "SAMEORIGIN",
"PERMISSIONS_POLICY": "accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), cross-origin-isolated=(), display-capture=(), document-domain=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(), geolocation=(), gyroscope=(), hid=(), idle-detection=(), magnetometer=(), microphone=(), midi=(), navigation-override=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), serial=(), usb=(), web-share=(), xr-spatial-tracking=()",
"FEATURE_POLICY": "accelerometer 'none'; ambient-light-sensor 'none'; autoplay 'none'; battery 'none'; camera 'none'; display-capture 'none'; document-domain 'none'; encrypted-media 'none'; execution-while-not-rendered 'none'; execution-while-out-of-viewport 'none'; fullscreen 'none'; geolocation 'none'; gyroscope 'none'; layout-animation 'none'; legacy-image-formats 'none'; magnetometer 'none'; microphone 'none'; midi 'none'; navigation-override 'none'; payment 'none'; picture-in-picture 'none'; publickey-credentials-get 'none'; speaker-selection 'none'; sync-xhr 'none'; unoptimized-images 'none'; unsized-media 'none'; usb 'none'; screen-wake-lock 'none'; web-share 'none'; xr-spatial-tracking 'none';"
}
},
{
"name": "Bad behavior",
"description": "Configure automatic bans when detecting bad behaviors on your web service.",
"settings": {
"USE_BAD_BEHAVIOR": "yes",
"BAD_BEHAVIOR_STATUS_CODES": "400 401 403 404 405 429 444",
"BAD_BEHAVIOR_BAN_TIME": "86400",
"BAD_BEHAVIOR_THRESHOLD": "5",
"BAD_BEHAVIOR_COUNT_TIME": "60"
}
},
{
"name": "Limit",
"description": "Configure requests and connections limits on your web service.",
"settings": {
"USE_LIMIT_CONN": "yes",
"LIMIT_CONN_MAX_HTTP1": "10",
"LIMIT_CONN_MAX_HTTP2": "100",
"USE_LIMIT_REQ": "yes",
"LIMIT_REQ_URL": "/",
"LIMIT_REQ_RATE": "2r/s"
}
},
{
"name": "DNSBL",
"description": "Enable/disable DNSBL protection. Might generate false positives especially if you have a worldwide audience.",
"settings": {
"USE_DNSBL": "yes"
}
},
{
"name": "Country",
"description": "Configure allowed countries to reach out your web service. Recommended if you protect a restricted area such as extranet or administration panel.",
"settings": {
"WHITELIST_COUNTRY": ""
}
},
{
"name": "Antibot",
"description": "Enable/disable and configure antibot protection globally on your web service.",
"settings": {
"USE_ANTIBOT": "captcha",
"ANTIBOT_TIME_RESOLVE": "120",
"ANTIBOT_TIME_VALID": "86400",
"ANTIBOT_RECAPTCHA_SCORE": "0.7",
"ANTIBOT_RECAPTCHA_SITEKEY": "",
"ANTIBOT_RECAPTCHA_SECRET": "",
"ANTIBOT_HCAPTCHA_SITEKEY": "",
"ANTIBOT_HCAPTCHA_SECRET": "",
"ANTIBOT_TURNSTILE_SITEKEY": "",
"ANTIBOT_TURNSTILE_SECRET": ""
}
},
{
"name": "CORS",
"description": "Configure Cross-Origin Resource Sharing (CORS) to allow/deny external requests to your web service.",
"settings": {
"USE_CORS": "yes",
"CORS_ALLOW_ORIGIN": ""
}
},
{
"name": "Reverse scan",
"description": "Configure reverse scan of client to detect open proxy or datacenter connections.",
"settings": {
"USE_REVERSE_SCAN": "yes",
"REVERSE_SCAN_PORTS": "22 80 443 3128 8000 8080"
}
},
{
"name": "ModSecurity",
"description": "Enable/disable and configure ModSecurity on your web service.",
"settings": {
"USE_MODSECURITY": "yes",
"MODSECURITY_CRS_VERSION": "4"
},
"configs": [
{
"name": "template-high",
"type": "modsec-crs",
"data": "SecAction \"id:900000,phase:1,pass,t:none,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.2.0',setvar:tx.blocking_paranoia_level=4\""
}
]
"name": "template-high",
"type": "modsec-crs",
"data": "SecAction \"id:900000,phase:1,pass,t:none,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.2.0',setvar:tx.blocking_paranoia_level=4\""
}
]
}
]
}
]
}

View file

@ -1,111 +1,111 @@
{
"name": "low",
"description": "Generic settings template with low security level to avoid false positives and get started with BunkerWeb.",
"steps": [
"name": "low",
"description": "Generic settings template with low security level to avoid false positives and get started with BunkerWeb.",
"steps": [
{
"name": "Server configuration",
"description": "Configure your server name and reverse proxy settings. Don't forget to add the corresponding DNS A entry pointing to your BunkerWeb IP.",
"settings": {
"SERVER_NAME": "www.example.com",
"USE_REVERSE_PROXY": "yes",
"REVERSE_PROXY_HOST": "http://my-upstream-server:8080",
"REVERSE_PROXY_URL": "/",
"REVERSE_PROXY_INTERCEPT_ERRORS": "no",
"REVERSE_PROXY_WS": "yes",
"REVERSE_PROXY_CUSTOM_HOST": "",
"REVERSE_PROXY_HEADERS": "Accept-Encoding ''"
}
},
{
"name": "HTTPS",
"description": "Enable/disable HTTPS for your service.",
"settings": {
"AUTO_LETS_ENCRYPT": "yes"
}
},
{
"name": "HTTP configuration",
"description": "Miscellaneous settings related to HTTP protocol.",
"settings": {
"USE_GZIP": "yes",
"USE_BROTLI": "yes",
"ALLOWED_METHODS": "GET|POST|HEAD|PUT|PATCH|OPTIONS|DELETE",
"MAX_SIZES": "50m",
"COOKIE_FLAGS": "* SameSite=Lax",
"CONTENT_SECURITY_POLICY": "",
"X_FRAME_OPTIONS": "",
"PERMISSIONS_POLICY": "",
"FEATURE_POLICY": "",
"KEEP_UPSTREAM_HEADERS": "*"
}
},
{
"name": "Bad behavior",
"description": "Configure automatic bans when detecting bad behaviors on your web service.",
"settings": {
"USE_BAD_BEHAVIOR": "yes",
"BAD_BEHAVIOR_STATUS_CODES": "400 401 403 405 429 444",
"BAD_BEHAVIOR_BAN_TIME": "3600",
"BAD_BEHAVIOR_THRESHOLD": "20",
"BAD_BEHAVIOR_COUNT_TIME": "60"
}
},
{
"name": "Limit",
"description": "Configure requests and connections limits on your web service.",
"settings": {
"USE_LIMIT_CONN": "yes",
"LIMIT_CONN_MAX_HTTP1": 20,
"LIMIT_CONN_MAX_HTTP2": 200,
"USE_LIMIT_REQ": "yes",
"LIMIT_REQ_URL": "/",
"LIMIT_REQ_RATE": "5r/s"
}
},
{
"name": "DNSBL",
"description": "Enable/disable DNSBL protection. Might generate false positives especially if you have a worldwide audience.",
"settings": {
"USE_DNSBL": "no"
}
},
{
"name": "Country",
"description": "Configure allowed countries to reach out your web service. Recommended if you protect a restricted area such as extranet or administration panel.",
"settings": {
"WHITELIST_COUNTRY": ""
}
},
{
"name": "Antibot",
"description": "Enable/disable and configure antibot protection globally on your web service.",
"settings": {
"USE_ANTIBOT": "no",
"ANTIBOT_TIME_RESOLVE": "120",
"ANTIBOT_TIME_VALID": "86400",
"ANTIBOT_RECAPTCHA_SCORE": "0.7",
"ANTIBOT_RECAPTCHA_SITEKEY": "",
"ANTIBOT_RECAPTCHA_SECRET": "",
"ANTIBOT_HCAPTCHA_SITEKEY": "",
"ANTIBOT_HCAPTCHA_SECRET": "",
"ANTIBOT_TURNSTILE_SITEKEY": "",
"ANTIBOT_TURNSTILE_SECRET": ""
}
},
{
"name": "ModSecurity",
"description": "Enable/disable and configure ModSecurity on your web service.",
"settings": {
"USE_MODSECURITY": "yes"
},
"configs": [
{
"name": "Server configuration",
"description": "Configure your server name and reverse proxy settings. Don't forget to add the corresponding DNS A entry pointing to your BunkerWeb IP.",
"settings": {
"SERVER_NAME": "www.example.com",
"USE_REVERSE_PROXY": "yes",
"REVERSE_PROXY_HOST": "http://my-upstream-server:8080",
"REVERSE_PROXY_URL": "/",
"REVERSE_PROXY_INTERCEPT_ERRORS": "no",
"REVERSE_PROXY_WS": "yes",
"REVERSE_PROXY_CUSTOM_HOST": "",
"REVERSE_PROXY_HEADERS": "Accept-Encoding ''"
}
},
{
"name": "HTTPS",
"description": "Enable/disable HTTPS for your service.",
"settings": {
"AUTO_LETS_ENCRYPT": "yes"
}
},
{
"name": "HTTP configuration",
"description": "Miscellaneous settings related to HTTP protocol.",
"settings": {
"USE_GZIP": "yes",
"USE_BROTLI": "yes",
"ALLOWED_METHODS": "GET|POST|HEAD|PUT|PATCH|OPTIONS|DELETE",
"MAX_SIZES": "50m",
"COOKIE_FLAGS": "* SameSite=Lax",
"CONTENT_SECURITY_POLICY": "",
"X_FRAME_OPTIONS": "",
"PERMISSIONS_POLICY": "",
"FEATURE_POLICY": "",
"KEEP_UPSTREAM_HEADERS": "*"
}
},
{
"name": "Bad behavior",
"description": "Configure automatic bans when detecting bad behaviors on your web service.",
"settings": {
"USE_BAD_BEHAVIOR": "yes",
"BAD_BEHAVIOR_STATUS_CODES": "400 401 403 405 429 444",
"BAD_BEHAVIOR_BAN_TIME": "3600",
"BAD_BEHAVIOR_THRESHOLD": "20",
"BAD_BEHAVIOR_COUNT_TIME": "60"
}
},
{
"name": "Limit",
"description": "Configure requests and connections limits on your web service.",
"settings": {
"USE_LIMIT_CONN": "yes",
"LIMIT_CONN_MAX_HTTP1": 20,
"LIMIT_CONN_MAX_HTTP2": 200,
"USE_LIMIT_REQ": "yes",
"LIMIT_REQ_URL": "/",
"LIMIT_REQ_RATE": "5r/s"
}
},
{
"name": "DNSBL",
"description": "Enable/disable DNSBL protection. Might generate false positives especially if you have a worldwide audience.",
"settings": {
"USE_DNSBL": "no"
}
},
{
"name": "Country",
"description": "Configure allowed countries to reach out your web service. Recommended if you protect a restricted area such as extranet or administration panel.",
"settings": {
"WHITELIST_COUNTRY": ""
}
},
{
"name": "Antibot",
"description": "Enable/disable and configure antibot protection globally on your web service.",
"settings": {
"USE_ANTIBOT": "no",
"ANTIBOT_TIME_RESOLVE": "120",
"ANTIBOT_TIME_VALID": "86400",
"ANTIBOT_RECAPTCHA_SCORE": "0.7",
"ANTIBOT_RECAPTCHA_SITEKEY": "",
"ANTIBOT_RECAPTCHA_SECRET": "",
"ANTIBOT_HCAPTCHA_SITEKEY": "",
"ANTIBOT_HCAPTCHA_SECRET": "",
"ANTIBOT_TURNSTILE_SITEKEY": "",
"ANTIBOT_TURNSTILE_SECRET": ""
}
},
{
"name": "ModSecurity",
"description": "Enable/disable and configure ModSecurity on your web service.",
"settings": {
"USE_MODSECURITY": "yes"
},
"configs": [
{
"name": "template-low",
"type": "modsec-crs",
"description": "Override ModSecurity CRS settings.",
"data": "SecAction \"id:900110,phase:1,nolog,pass,t:none,setvar:tx.inbound_anomaly_score_threshold=7,setvar:tx.outbound_anomaly_score_threshold=4\""
}
]
"name": "template-low",
"type": "modsec-crs",
"description": "Override ModSecurity CRS settings.",
"data": "SecAction \"id:900110,phase:1,nolog,pass,t:none,setvar:tx.inbound_anomaly_score_threshold=7,setvar:tx.outbound_anomaly_score_threshold=4\""
}
]
}
]
}
]
}

View file

@ -1,110 +1,110 @@
{
"name": "medium",
"description": "Generic settings template with medium security level aimed for average web service in production. False positives may appear depending on your environment.",
"steps": [
{
"name": "Server configuration",
"description": "Configure your server name and reverse proxy settings. Don't forget to add the corresponding DNS A entry pointing to your BunkerWeb IP.",
"settings": {
"SERVER_NAME": "www.example.com",
"USE_REVERSE_PROXY": "yes",
"REVERSE_PROXY_HOST": "http://my-upstream-server:8080",
"REVERSE_PROXY_URL": "/",
"REVERSE_PROXY_INTERCEPT_ERRORS": "yes",
"REVERSE_PROXY_WS": "no",
"REVERSE_PROXY_CUSTOM_HOST": "",
"REVERSE_PROXY_HEADERS": "Accept-Encoding ''"
}
},
{
"name": "HTTPS",
"description": "Enable/disable HTTPS for your service.",
"settings": {
"AUTO_LETS_ENCRYPT": "yes"
}
},
{
"name": "HTTP configuration",
"description": "Miscellaneous settings related to HTTP protocol.",
"settings": {
"USE_GZIP": "yes",
"USE_BROTLI": "yes",
"ALLOWED_METHODS": "GET|POST|HEAD",
"MAX_SIZES": "10m",
"COOKIE_FLAGS": "* HttpOnly SameSite=Lax",
"CONTENT_SECURITY_POLICY": "object-src 'none'; form-action 'self'; frame-ancestors 'self';",
"X_FRAME_OPTIONS": "SAMEORIGIN",
"PERMISSIONS_POLICY": "accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), cross-origin-isolated=(), display-capture=(), document-domain=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(), geolocation=(), gyroscope=(), hid=(), idle-detection=(), magnetometer=(), microphone=(), midi=(), navigation-override=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), serial=(), usb=(), web-share=(), xr-spatial-tracking=()",
"FEATURE_POLICY": "accelerometer 'none'; ambient-light-sensor 'none'; autoplay 'none'; battery 'none'; camera 'none'; display-capture 'none'; document-domain 'none'; encrypted-media 'none'; execution-while-not-rendered 'none'; execution-while-out-of-viewport 'none'; fullscreen 'none'; geolocation 'none'; gyroscope 'none'; layout-animation 'none'; legacy-image-formats 'none'; magnetometer 'none'; microphone 'none'; midi 'none'; navigation-override 'none'; payment 'none'; picture-in-picture 'none'; publickey-credentials-get 'none'; speaker-selection 'none'; sync-xhr 'none'; unoptimized-images 'none'; unsized-media 'none'; usb 'none'; screen-wake-lock 'none'; web-share 'none'; xr-spatial-tracking 'none';"
}
},
{
"name": "Bad behavior",
"description": "Configure automatic bans when detecting bad behaviors on your web service.",
"settings": {
"USE_BAD_BEHAVIOR": "yes",
"BAD_BEHAVIOR_STATUS_CODES": "400 401 403 404 405 429 444",
"BAD_BEHAVIOR_BAN_TIME": "86400",
"BAD_BEHAVIOR_THRESHOLD": "10",
"BAD_BEHAVIOR_COUNT_TIME": "60"
}
},
{
"name": "Limit",
"description": "Configure requests and connections limits on your web service.",
"settings": {
"USE_LIMIT_CONN": "yes",
"LIMIT_CONN_MAX_HTTP1": "10",
"LIMIT_CONN_MAX_HTTP2": "100",
"USE_LIMIT_REQ": "yes",
"LIMIT_REQ_URL": "/",
"LIMIT_REQ_RATE": "2r/s"
}
},
{
"name": "DNSBL",
"description": "Enable/disable DNSBL protection. Might generate false positives especially if you have a worldwide audience.",
"settings": {
"USE_DNSBL": "yes"
}
},
{
"name": "Country",
"description": "Configure allowed countries to reach out your web service. Recommended if you protect a restricted area such as extranet or administration panel.",
"settings": {
"WHITELIST_COUNTRY": ""
}
},
{
"name": "Antibot",
"description": "Enable/disable and configure antibot protection globally on your web service.",
"settings": {
"USE_ANTIBOT": "javascript",
"ANTIBOT_TIME_RESOLVE": "120",
"ANTIBOT_TIME_VALID": "86400",
"ANTIBOT_RECAPTCHA_SCORE": "0.7",
"ANTIBOT_RECAPTCHA_SITEKEY": "",
"ANTIBOT_RECAPTCHA_SECRET": "",
"ANTIBOT_HCAPTCHA_SITEKEY": "",
"ANTIBOT_HCAPTCHA_SECRET": "",
"ANTIBOT_TURNSTILE_SITEKEY": "",
"ANTIBOT_TURNSTILE_SECRET": ""
}
},
{
"name": "CORS",
"description": "Configure Cross-Origin Resource Sharing (CORS) to allow/deny external requests to your web service.",
"settings": {
"USE_CORS": "no",
"CORS_ALLOW_ORIGIN": "*"
}
},
{
"name": "ModSecurity",
"description": "Enable/disable and configure ModSecurity on your web service.",
"settings": {
"USE_MODSECURITY": "yes"
}
}
]
}
"name": "medium",
"description": "Generic settings template with medium security level aimed for average web service in production. False positives may appear depending on your environment.",
"steps": [
{
"name": "Server configuration",
"description": "Configure your server name and reverse proxy settings. Don't forget to add the corresponding DNS A entry pointing to your BunkerWeb IP.",
"settings": {
"SERVER_NAME": "www.example.com",
"USE_REVERSE_PROXY": "yes",
"REVERSE_PROXY_HOST": "http://my-upstream-server:8080",
"REVERSE_PROXY_URL": "/",
"REVERSE_PROXY_INTERCEPT_ERRORS": "yes",
"REVERSE_PROXY_WS": "no",
"REVERSE_PROXY_CUSTOM_HOST": "",
"REVERSE_PROXY_HEADERS": "Accept-Encoding ''"
}
},
{
"name": "HTTPS",
"description": "Enable/disable HTTPS for your service.",
"settings": {
"AUTO_LETS_ENCRYPT": "yes"
}
},
{
"name": "HTTP configuration",
"description": "Miscellaneous settings related to HTTP protocol.",
"settings": {
"USE_GZIP": "yes",
"USE_BROTLI": "yes",
"ALLOWED_METHODS": "GET|POST|HEAD",
"MAX_SIZES": "10m",
"COOKIE_FLAGS": "* HttpOnly SameSite=Lax",
"CONTENT_SECURITY_POLICY": "object-src 'none'; form-action 'self'; frame-ancestors 'self';",
"X_FRAME_OPTIONS": "SAMEORIGIN",
"PERMISSIONS_POLICY": "accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), cross-origin-isolated=(), display-capture=(), document-domain=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(), geolocation=(), gyroscope=(), hid=(), idle-detection=(), magnetometer=(), microphone=(), midi=(), navigation-override=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), serial=(), usb=(), web-share=(), xr-spatial-tracking=()",
"FEATURE_POLICY": "accelerometer 'none'; ambient-light-sensor 'none'; autoplay 'none'; battery 'none'; camera 'none'; display-capture 'none'; document-domain 'none'; encrypted-media 'none'; execution-while-not-rendered 'none'; execution-while-out-of-viewport 'none'; fullscreen 'none'; geolocation 'none'; gyroscope 'none'; layout-animation 'none'; legacy-image-formats 'none'; magnetometer 'none'; microphone 'none'; midi 'none'; navigation-override 'none'; payment 'none'; picture-in-picture 'none'; publickey-credentials-get 'none'; speaker-selection 'none'; sync-xhr 'none'; unoptimized-images 'none'; unsized-media 'none'; usb 'none'; screen-wake-lock 'none'; web-share 'none'; xr-spatial-tracking 'none';"
}
},
{
"name": "Bad behavior",
"description": "Configure automatic bans when detecting bad behaviors on your web service.",
"settings": {
"USE_BAD_BEHAVIOR": "yes",
"BAD_BEHAVIOR_STATUS_CODES": "400 401 403 404 405 429 444",
"BAD_BEHAVIOR_BAN_TIME": "86400",
"BAD_BEHAVIOR_THRESHOLD": "10",
"BAD_BEHAVIOR_COUNT_TIME": "60"
}
},
{
"name": "Limit",
"description": "Configure requests and connections limits on your web service.",
"settings": {
"USE_LIMIT_CONN": "yes",
"LIMIT_CONN_MAX_HTTP1": "10",
"LIMIT_CONN_MAX_HTTP2": "100",
"USE_LIMIT_REQ": "yes",
"LIMIT_REQ_URL": "/",
"LIMIT_REQ_RATE": "2r/s"
}
},
{
"name": "DNSBL",
"description": "Enable/disable DNSBL protection. Might generate false positives especially if you have a worldwide audience.",
"settings": {
"USE_DNSBL": "yes"
}
},
{
"name": "Country",
"description": "Configure allowed countries to reach out your web service. Recommended if you protect a restricted area such as extranet or administration panel.",
"settings": {
"WHITELIST_COUNTRY": ""
}
},
{
"name": "Antibot",
"description": "Enable/disable and configure antibot protection globally on your web service.",
"settings": {
"USE_ANTIBOT": "javascript",
"ANTIBOT_TIME_RESOLVE": "120",
"ANTIBOT_TIME_VALID": "86400",
"ANTIBOT_RECAPTCHA_SCORE": "0.7",
"ANTIBOT_RECAPTCHA_SITEKEY": "",
"ANTIBOT_RECAPTCHA_SECRET": "",
"ANTIBOT_HCAPTCHA_SITEKEY": "",
"ANTIBOT_HCAPTCHA_SECRET": "",
"ANTIBOT_TURNSTILE_SITEKEY": "",
"ANTIBOT_TURNSTILE_SECRET": ""
}
},
{
"name": "CORS",
"description": "Configure Cross-Origin Resource Sharing (CORS) to allow/deny external requests to your web service.",
"settings": {
"USE_CORS": "no",
"CORS_ALLOW_ORIGIN": "*"
}
},
{
"name": "ModSecurity",
"description": "Enable/disable and configure ModSecurity on your web service.",
"settings": {
"USE_MODSECURITY": "yes"
}
}
]
}

View file

@ -155,7 +155,7 @@ try:
SEND_FILE_MAX_AGE_DEFAULT=86400,
SCRIPT_NONCE=sha256(urandom(32)).hexdigest(),
DB=db,
UI_TEMPLATES=get_ui_templates()
UI_TEMPLATES=get_ui_templates(),
)
except FileNotFoundError as e:
app.logger.error(repr(e), e.filename)
@ -173,6 +173,7 @@ csrf.init_app(app)
LOG_RX = re_compile(r"^(?P<date>\d+/\d+/\d+\s\d+:\d+:\d+)\s\[(?P<level>[a-z]+)\]\s\d+#\d+:\s(?P<message>[^\n]+)$")
REVERSE_PROXY_PATH = re_compile(r"^(?P<host>https?://.{1,255}(:((6553[0-5])|(655[0-2]\d)|(65[0-4]\d{2})|(6[0-4]\d{3})|([1-5]\d{4})|([0-5]{0,5})|(\d{1,4})))?)$")
def get_ui_data():
ui_data = "Error"
while ui_data == "Error":

View file

@ -3,6 +3,7 @@ from glob import glob
from os import sep
from os.path import join
def get_ui_templates():
ui_templates = []
for template_file in glob(join(sep, "usr", "share", "bunkerweb", "templates", "*.json")):
@ -10,10 +11,7 @@ def get_ui_templates():
ui_template = {}
with open(template_file, "r") as f:
bw_template = loads(f.read())
ui_template = {
"name": bw_template["name"],
"description": bw_template["description"]
}
ui_template = {"name": bw_template["name"], "description": bw_template["description"]}
ui_template["steps"] = []
for bw_step in bw_template["steps"]:
ui_step = {}
@ -21,10 +19,7 @@ def get_ui_templates():
ui_step["description"] = bw_step["description"]
ui_step["settings"] = []
for setting, value in bw_step["settings"].items():
ui_setting = {
"setting_id": setting,
"value": value
}
ui_setting = {"setting_id": setting, "value": value}
ui_step["settings"].append(ui_setting)
ui_template["steps"].append(ui_step)
ui_templates.append(ui_template)
@ -33,4 +28,4 @@ def get_ui_templates():
# TODO: log
pass
# print(ui_templates, flush=True)
return ui_templates
return ui_templates

View file

@ -6,8 +6,6 @@ import {
CheckNoMatchFilter,
showInvalid,
SettingsAdvanced,
SettingsSimple,
SettingsSwitch,
} from "./utils/settings.js";
class SettingsService {
@ -24,12 +22,6 @@ class SettingsService {
this.settingsMultiple,
"services",
);
this.simpleSettings = new SettingsSimple(
document.querySelector("[data-simple][data-services-modal-form]"),
this.settingsMultiple,
"services",
);
this.initSettingsService();
}
@ -117,133 +109,6 @@ class SettingsService {
forceEnabled,
emptyServerName,
);
// Click on right security level dropdown btn
// This will fire security level event listener
this.simpleSettings.updateData(
action,
oldServName,
operation,
settings,
forceEnabled,
setMethodUI,
emptyServerName,
);
const modeBtn = document.querySelector(
"button[data-toggle-settings-mode-btn]",
);
const mode = modeBtn.getAttribute("data-toggle-settings-mode-btn");
if (action === "new") {
mode !== "simple" ? modeBtn.click() : null;
document
.querySelector(
`button[data-setting-select-dropdown-btn="security-level"][value="standard"]`,
)
.click();
document
.querySelector(
`button[data-setting-select-dropdown-btn="security-level"][value="custom"]`,
)
.setAttribute("disabled", "true");
} else {
mode !== "advanced" ? modeBtn.click() : null;
document
.querySelector(
`button[data-setting-select-dropdown-btn="security-level"][value="custom"]`,
)
.removeAttribute("disabled");
document
.querySelector(
`button[data-setting-select-dropdown-btn="security-level"][value="custom"]`,
)
.click();
}
}
} catch (err) {}
// security level
try {
if (
e.target
.closest("button")
.getAttribute("data-setting-select-dropdown-btn") ==
"security-level"
) {
// get current common values
const action = this.simpleSettings.currAction;
const oldServName = this.simpleSettings.oldServName;
const operation = this.simpleSettings.operation;
const forceEnabled = this.simpleSettings.forceEnabled;
const setMethodUI = this.simpleSettings.setMethodUI;
const emptyServerName = this.simpleSettings.emptyServerName;
// get custom security level settings of service if custom choose
const value = e.target.closest("button").getAttribute("value");
// mainSettings is the settings of the service
let mainSettings;
// Try to get settings in a valid format
try {
mainSettings = JSON.parse(
document
.querySelector(`[data-old-name][data-value="${oldServName}"]`)
.closest("[data-services-service]")
.getAttribute("data-settings"),
);
} catch (err) {}
try {
if (!settings) {
mainSettings = JSON.parse(
document
.querySelector(`[data-old-name][data-value="${oldServName}"]`)
.closest("[data-services-service]")
.getAttribute("data-settings")
.replaceAll(`'`, `"`),
);
}
} catch (err) {}
// In case we want a security level, we need to get the settings of the security level
// In order to filter and merge both to avoid overriding disabled settings (method != ui|default)
let compareSettings = null;
if (value !== "custom") {
// Try to get settings in a valid format
try {
compareSettings = JSON.parse(
document
.querySelector(`input#security-level-${value}`)
.getAttribute("data-settings"),
);
} catch (err) {}
try {
if (!compareSettings) {
compareSettings = JSON.parse(
document
.querySelector(`input#security-level-${value}`)
.getAttribute("data-settings")
.replaceAll(`'`, `"`),
);
}
} catch (err) {}
}
// No main settings if new
if (action === "new") {
mainSettings = JSON.parse(JSON.stringify(compareSettings));
compareSettings = null;
}
this.simpleSettings.setSimple(
action,
oldServName,
operation,
mainSettings,
compareSettings,
setMethodUI,
forceEnabled,
emptyServerName,
true,
);
}
} catch (err) {}
});
@ -260,9 +125,6 @@ class ServiceModal {
"[data-services-tabs-select-header]",
]);
this.modalCard = this.modal.querySelector("[data-services-modal-card]");
this.switchModeBtn = this.modal.querySelector(
"[data-toggle-settings-mode-btn]",
);
//modal forms
this.formNewEdit = this.modal.querySelector(
"[data-advanced][data-services-modal-form]",
@ -270,9 +132,7 @@ class ServiceModal {
this.formDelete = this.modal.querySelector(
"[data-services-modal-form-delete]",
);
this.simpleForm = this.modal.querySelector(
"[data-simple][data-services-modal-form]",
);
//container
this.container = document.querySelector("main");
this.currAction = "";
@ -370,10 +230,9 @@ class ServiceModal {
this.setCardViewportHeight(action === "delete" ? false : true);
this.setHeaderActionsVisible(action === "delete" ? false : true);
this.SetSelectTabsVisible(action === "delete" ? false : true);
this.setModeVisible(action);
this.resetFilterSettings();
if (action === "edit" || action === "new" || action === "clone") {
this.formNewEdit.classList.remove("hidden");
this.simpleForm.classList.remove("hidden");
const oldNameValue = action === "edit" ? oldServName : "";
@ -401,6 +260,20 @@ class ServiceModal {
this.openModal();
}
resetFilterSettings() {
// Reset select
const selectTypeAll = document
.querySelector("#filter-type[data-services-setting-select-dropdown]")
.querySelector(
'button[value="all"][data-services-setting-select-dropdown-btn="type"]',
);
selectTypeAll.click();
const inpKeyword = this.modal.querySelector("input#settings-filter");
inpKeyword.value = "";
// dispatch event input
inpKeyword.dispatchEvent(new Event("input"));
}
setIsDraft(isDraft, method) {
const draftVal = isDraft ? "yes" : "no";
@ -437,18 +310,12 @@ class ServiceModal {
this.modal
.querySelector("[data-toggle-draft-btn]")
.classList.remove("hidden");
this.modal
.querySelector("[data-toggle-settings-mode-btn]")
.classList.remove("hidden");
}
if (!setVisible) {
this.modal
.querySelector("[data-toggle-draft-btn]")
.classList.add("hidden");
this.modal
.querySelector("[data-toggle-settings-mode-btn]")
.classList.add("hidden");
}
}
@ -464,29 +331,8 @@ class ServiceModal {
}
}
switchMode(mode) {
if (mode === "advanced") {
this.formNewEdit.classList.remove("hidden");
this.simpleForm.classList.add("hidden");
}
if (mode === "simple") {
this.formNewEdit.classList.add("hidden");
this.simpleForm.classList.remove("hidden");
}
}
setModeVisible(action) {
if (action === "new" || action === "clone" || action === "edit") {
this.switchModeBtn.classList.remove("hidden");
} else {
this.switchModeBtn.classList.add("hidden");
}
}
hideForms() {
this.formNewEdit.classList.add("hidden");
this.simpleForm.classList.add("hidden");
this.formDelete.classList.add("hidden");
}
@ -842,13 +688,6 @@ const setFilterGlobal = new FilterSettings(
const settings = new SettingsService();
const switchSettings = new SettingsSwitch(
document.querySelector("[data-toggle-settings-mode-btn]"),
document.querySelector("main"),
["advanced", "simple"],
"services",
);
const checkServiceModalKeyword = new CheckNoMatchFilter(
document.querySelector("input#settings-filter"),
"input",

File diff suppressed because it is too large Load diff

View file

@ -31,19 +31,6 @@
<path d="M21.721 12.752a9.711 9.711 0 0 0-.945-5.003 12.754 12.754 0 0 1-4.339 2.708 18.991 18.991 0 0 1-.214 4.772 17.165 17.165 0 0 0 5.498-2.477ZM14.634 15.55a17.324 17.324 0 0 0 .332-4.647c-.952.227-1.945.347-2.966.347-1.021 0-2.014-.12-2.966-.347a17.515 17.515 0 0 0 .332 4.647 17.385 17.385 0 0 0 5.268 0ZM9.772 17.119a18.963 18.963 0 0 0 4.456 0A17.182 17.182 0 0 1 12 21.724a17.18 17.18 0 0 1-2.228-4.605ZM7.777 15.23a18.87 18.87 0 0 1-.214-4.774 12.753 12.753 0 0 1-4.34-2.708 9.711 9.711 0 0 0-.944 5.004 17.165 17.165 0 0 0 5.498 2.477ZM21.356 14.752a9.765 9.765 0 0 1-7.478 6.817 18.64 18.64 0 0 0 1.988-4.718 18.627 18.627 0 0 0 5.49-2.098ZM2.644 14.752c1.682.971 3.53 1.688 5.49 2.099a18.64 18.64 0 0 0 1.988 4.718 9.765 9.765 0 0 1-7.478-6.816ZM13.878 2.43a9.755 9.755 0 0 1 6.116 3.986 11.267 11.267 0 0 1-3.746 2.504 18.63 18.63 0 0 0-2.37-6.49ZM12 2.276a17.152 17.152 0 0 1 2.805 7.121c-.897.23-1.837.353-2.805.353-.968 0-1.908-.122-2.805-.353A17.151 17.151 0 0 1 12 2.276ZM10.122 2.43a18.629 18.629 0 0 0-2.37 6.49 11.266 11.266 0 0 1-3.746-2.504 9.754 9.754 0 0 1 6.116-3.985Z" />
</svg>
</button>
<button data-toggle-settings-mode-btn="advanced"
class="transition hover:brightness-75 dark:hover:brightness-110 sm:ml-4 flex items-center border border-gray-700 dark:border-gray-300 dark:bg-slate-700 bg-gray-50/10 text-gray-800 rounded py-1 px-2 mt-1.5 sm:mt-0">
<p data-toggle-settings-mode="simple"
class="hidden dark:text-gray-100 mb-0 mr-2 pointer-events-none">Simple</p>
<p data-toggle-settings-mode="advanced"
class="dark:text-gray-100 mb-0 mr-2 pointer-events-none">Advanced</p>
<svg data-toggle-settings-mode="simple" class="hidden translate-y-0.5 w-5 h-5 fill-gray-700 stroke-white/0 dark:fill-gray-300 pointer-events-none" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path fill-rule="evenodd" d="M7.84 1.804A1 1 0 0 1 8.82 1h2.36a1 1 0 0 1 .98.804l.331 1.652a6.993 6.993 0 0 1 1.929 1.115l1.598-.54a1 1 0 0 1 1.186.447l1.18 2.044a1 1 0 0 1-.205 1.251l-1.267 1.113a7.047 7.047 0 0 1 0 2.228l1.267 1.113a1 1 0 0 1 .206 1.25l-1.18 2.045a1 1 0 0 1-1.187.447l-1.598-.54a6.993 6.993 0 0 1-1.929 1.115l-.33 1.652a1 1 0 0 1-.98.804H8.82a1 1 0 0 1-.98-.804l-.331-1.652a6.993 6.993 0 0 1-1.929-1.115l-1.598.54a1 1 0 0 1-1.186-.447l-1.18-2.044a1 1 0 0 1 .205-1.251l1.267-1.114a7.05 7.05 0 0 1 0-2.227L1.821 7.773a1 1 0 0 1-.206-1.25l1.18-2.045a1 1 0 0 1 1.187-.447l1.598.54A6.992 6.992 0 0 1 7.51 3.456l.33-1.652ZM10 13a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z" clip-rule="evenodd" />
</svg>
<svg data-toggle-settings-mode="advanced" class="translate-y-0.5 w-5 h-5 fill-gray-700 stroke-white/0 dark:fill-gray-300 pointer-events-none" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path fill-rule="evenodd" d="M8.34 1.804A1 1 0 0 1 9.32 1h1.36a1 1 0 0 1 .98.804l.295 1.473c.497.144.971.342 1.416.587l1.25-.834a1 1 0 0 1 1.262.125l.962.962a1 1 0 0 1 .125 1.262l-.834 1.25c.245.445.443.919.587 1.416l1.473.294a1 1 0 0 1 .804.98v1.361a1 1 0 0 1-.804.98l-1.473.295a6.95 6.95 0 0 1-.587 1.416l.834 1.25a1 1 0 0 1-.125 1.262l-.962.962a1 1 0 0 1-1.262.125l-1.25-.834a6.953 6.953 0 0 1-1.416.587l-.294 1.473a1 1 0 0 1-.98.804H9.32a1 1 0 0 1-.98-.804l-.295-1.473a6.957 6.957 0 0 1-1.416-.587l-1.25.834a1 1 0 0 1-1.262-.125l-.962-.962a1 1 0 0 1-.125-1.262l.834-1.25a6.957 6.957 0 0 1-.587-1.416l-1.473-.294A1 1 0 0 1 1 10.68V9.32a1 1 0 0 1 .804-.98l1.473-.295c.144-.497.342-.971.587-1.416l-.834-1.25a1 1 0 0 1 .125-1.262l.962-.962A1 1 0 0 1 5.38 3.03l1.25.834a6.957 6.957 0 0 1 1.416-.587l.294-1.473ZM13 10a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" clip-rule="evenodd" />
</svg>
</button>
</div>
<button class="-translate-y-1"
aria-label="close modal"
@ -57,7 +44,6 @@
</div>
{% include "services_modal_settings_advanced.html" %}
{% include "services_modal_settings_simple.html" %}
{% include "services_modal_delete.html" %}
</div>

View file

@ -1,156 +0,0 @@
{% set security_levels = ['standard', 'advanced', 'high', 'custom'] %}
{% set standard = {
"USE_ANTIBOT": {
"value": "javascript",
"method": "default"
},
"SERVER_NAME": {
"value": "test",
"method": "default"
},
"LIMIT_REQ_URL": {
"value": "/testfesf",
"method": "default"
},
"LIMIT_REQ_RATE": {
"value": "1r/s",
"method": "default"
},
"LIMIT_REQ_URL_1": {
"value": "/test",
"method": "default"
},
"LIMIT_REQ_RATE_1": {
"value": "3r/s",
"method": "default"
},
"CUSTOM_CONFIG_MODSEC_1" : {
"value": "test",
"method": "default",
"type" : "modsec",
"name" : "modsec 1"
},
"CUSTOM_CONFIG_MODSEC_2" : {
"value": "test 2",
"method": "default",
"type" : "modsec",
"name" : "modsec 2"
},
}%}
{% set advanced = {
"USE_ANTIBOT": {
"value": "no",
"method": "default"
},
}%}
{% set high = {
"USE_ANTIBOT": {
"value": "javascript",
"method": "default"
},
}%}
{# When multiple, setting_id need to be a setting that is part of a multiple to get all settings on the same group #}
{# On levels, we should set a list of dict with setting_id as key and value as value #}
{% set steps = [
{
"name" : "STEP 1 - STARTING UP",
"description" : "we need some information to get started.",
"settings" : [
{"plugin_id" : "security-level", "setting_id": "SECURITY_LEVEL", "title" : "DEFINE SECURITY LEVEL", "subtitle" : "This will determine default settings value for the next steps. You'll be allow to modify settings to match your case if needed.", "setting" : {'context': 'global', 'default': 'standard', 'help': 'Determine the default settings value. You can override them.', 'id': 'security-level', 'label': 'Security level', 'regex': '^(security_levels[0]|security_levels[1]|security_levels[2]|security_levels[3])$', 'type': 'select', 'select': [security_levels[0], security_levels[1], security_levels[2], security_levels[3]]} },
{"plugin_id" : "general", "setting_id": "SERVER_NAME", "title" : "DEFINE HOST", "subtitle" : "We need this to connect BunkerWeb to your application. You need to set your domain name."},
{"plugin_id" : "limit", "setting_id": "LIMIT_REQ_URL", "title" : "Define header", "subtitle" : "test header multiple rendering" },
],
"configs": []
},
{
"name" : "STEP 2 - ANTIBOT",
"description" : "Avoid spammer and bot to access your website.",
"settings" : [
{"plugin_id" : "antibot", "setting_id": "USE_ANTIBOT", "title" : "Define the type of your antibot", "subtitle" : "Javascript, Captcha or Cookie don't need additionnal settings to be fill. Recaptcha, Hcaptcha and Turnstile need secret key and site key delivered from providers." },
],
"configs": [
{"id" : "CUSTOM_CONFIG_MODSEC", "type" : "modsec", "name" : "modsecrules", "subtitle" : "This will determine the modsecurity rules to apply to this service."},
]
},
]
%}
{# Get setting for each settings on steps #}
{% for step in steps %}
{% for setting in step.get('settings') %}
{% for plugin in plugins %}
{% if setting["plugin_id"] == plugin["id"]%}
{% if setting.update({"setting" : plugin["settings"][setting["setting_id"]]})%}{%endif%}
{# Case multiple, get all settings on same group #}
{% set is_multiple = plugin["settings"][setting["setting_id"]].get("multiple", "") %}
{% if is_multiple %}
{% set multiples = {"multiples" : []}%}
{% for mult_setting, value in plugin["settings"].items() %}
{% if value.get("multiple", "") == is_multiple %}
{% set mult_value = value %}
{% if mult_value.update({"name" : mult_setting}) %}{%endif%}
{% if multiples["multiples"].append(mult_value) %}{%endif%}
{% endif %}
{% endfor %}
{% if setting.update(multiples)%}{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
<input type="hidden" id="security-level-{{security_levels[0]}}" data-settings="{{ standard }}" />
<input type="hidden" id="security-level-{{security_levels[1]}}" data-settings="{{ advanced }}" />
<input type="hidden" id="security-level-{{security_levels[2]}}" data-settings="{{ high }}" />
<!-- new and edit form -->
<form data-simple data-services-modal-form
class="!hidden w-full h-[90vh] overflow-auto flex flex-col justify-between"
id="form-simple-new"
method="POST">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input type="hidden" value="new" name="operation" />
<input type="hidden" value="" name="OLD_SERVER_NAME" />
<input type="hidden" value="no" name="is_draft" />
<input type="hidden" value="easy" name="mode" />
{% for step in steps %}
<div data-step="{{loop.index}}" class="flex flex-col {% if loop.index != 1 %} hidden {% endif %}">
<div class="flex flex-col w-full items-start mt-2">
<h2 class="ml-2 mr-1 text-xl transition duration-300 ease-in-out font-bold text-md uppercase dark:text-white/90 mb-0" data-simple-step>{{ step.get("name")}}</h2>
<p class="ml-2 mr-1 text-base dark:text-gray-300 mb-1" data-simple-description>{{ step.get("description")}}</p>
</div>
<div class="w-full min-w-[300px] my-1 sm:my-0">
<hr class="separator" />
</div>
{% set plugin_simple = step.get('settings') %}
{% set configs = step.get('configs') %}
{% include "settings_simple.html" %}
</div>
{% endfor %}
<!-- action button -->
<div class="w-full flex-col items-center justify-center flex mt-10">
<div class="flex justify-center">
<button data-services-modal-close
type="button"
class="close-btn mb-4 mr-3 text-base">Close</button>
<button data-simple-back
type="button"
disabled
class="info-btn mb-4 mr-3 text-base">Back</button>
<button data-simple-next type="button" class="mb-4 valid-btn">Continue</button>
<button data-services-modal-submit type="submit" class="hidden mb-4 valid-btn">Save</button>
</div>
<!-- end action button-->
<p data-services-modal-error-msg
class="hidden text-red-500 font-bold dark:opacity-80 mb-0 text-center"></p>
</div>
</form>

View file

@ -1,105 +0,0 @@
{% set current_endpoint = current_endpoint or url_for(request.endpoint)[1:].split("/")[-1].strip().replace('_', '-') %}
<!-- plugin item -->
<div class="w-full grid grid-cols-12">
{% for setting_simple in plugin_simple %}
{% set setting_input = { "name" : setting_simple.get('setting_id'), "multiples" : setting_simple.get("multiples", {}), "method" : setting_simple.get('setting').get("method", "default"), "help" : setting_simple.get('setting').get("help"), "label" : setting_simple.get('setting').get("label"), "id" : setting_simple.get('setting').get("id"), "type" : setting_simple.get('setting').get("type"), "default" : setting_simple.get('setting').get("default", "default"), "select" : setting_simple.get('setting').get("select"), "regex" : setting_simple.get('setting').get("regex"), "value" : setting_simple.get('setting').get("value"), "is_multiple" : True if setting_simple.get('setting').get("multiple", "") else False, "multiple_name" : setting_simple.get('setting').get('multiple') } %}
<div data-simple id="{{ setting_simple['plugin_id'] }}-simple"
class="w-full h-full px-1 mb-2 col-span-12 {% if not setting_input['is_multiple'] %} mt-2 md:col-span-6 {%else%} mt-4 {% endif %} grid grid-cols-12 h-full items-end">
<!-- title and desc -->
<div class="col-span-12" data-setting-header>
<div class="flex flex-col justify-start items-start">
<h5 class="sm:pl-3 sm:pr-2 mt-2 transition duration-300 ease-in-out font-bold text-base uppercase dark:text-white/90 mb-0">
{{ setting_simple['title'] }}
</h5>
<p class="max-w-[550px] sm:pl-3 sm:pr-2 text-sm dark:text-gray-300 mb-0">{{ setting_simple['subtitle'] }}</p>
</div>
</div>
{% if not setting_input.get('is_multiple') %}
<!-- end title and desc -->
<div class="w-full col-span-12">
<div data-setting-container data-{{ current_endpoint }}-type="{{ setting_input['type'] }}" data-{{ current_endpoint }}-context="{{ setting_input['context'] }}" class="relative mx-0 sm:mx-2 md:mx-3 lg:mx-4 my-2 col-span-12 md:my-3 md:col-span-6 2xl:my-3 2xl:col-span-4" id="form-edit-{{ current_endpoint }}-{{ setting_input["id"] }}">
{% include "setting_header.html" %}
{% include "setting_input.html" %}
{% include "setting_select.html" %}
{% include "setting_checkbox.html" %}
{% include "setting_invalid.html"%}
</div>
<!-- end plugin settings -->
</div>
<!-- end plugin settings not multiple -->
{% endif %}
{% if setting_input.get('is_multiple') %}
<!-- plugin multiple handler -->
<div data-multiple-handler="{{ setting_input['multiple_name'] }}"
class="flex items-center mx-4 mb-2 mt-5 col-span-12 ">
<h5 class="input-title max-w-[150px] sm:max-w-[350px]">{{ setting_simple['plugin_id'] }}</h5>
<button data-{{ attribute_name }}-multiple-add="{{ setting_input['multiple_name'] }}" type="button" class="ml-3 dark:brightness-90 inline-block px-3 py-1.5 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-green-500 hover:bg-green-500/80 focus:bg-green-500/80 leading-normal text-md ease-in tracking-tight-rem shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md">
Add
</button>
<button data-{{ attribute_name }}-multiple-toggle="{{ setting_input['multiple_name'] }}" type="button" class="ml-3 dark:brightness-90 inline-block px-3 py-1.5 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-sky-500 hover:bg-sky-500/80 focus:bg-sky-500/80 leading-normal text-md ease-in tracking-tight-rem shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md">
SHOW / HIDE
</button>
</div>
<!-- end plugin multiple handler-->
<!-- multiple settings -->
<div data-{{ attribute_name }}-settings-multiple="{{ setting_input['multiple_name'] }}_SCHEMA" class=" col-span-12 bg-gray-50 dark:bg-slate-900/30 hidden w-full mt-4 grid-cols-12 border dark:border-gray-700 rounded">
{% for setting in setting_input.get("multiples") %}
{% set setting_input = { "name" : setting.get("name"), "context" : setting.get("context"), "method" : setting.get("method", "default"), "help" : setting.get("help"), "label" : setting.get("label"), "id" : setting.get("id"), "type" : setting.get("type"), "default" : setting.get("default", "default"), "select" : setting.get("select"), "regex" : setting.get("regex"), "value" : setting.get("value", setting.get('default')), "is_multiple" : True} %}
<div data-setting-container="{{ setting_input['name'] }}_SCHEMA" data-{{ attribute_name }}-type="{{ setting_input['type'] }}" data-{{ attribute_name }}-context="{{ setting_input['context'] }}" class="relative mx-2 md:mx-3 my-2 md:my-3 col-span-12 md:col-span-6 2xl:col-span-4" id="form-edit-{{ attribute_name }}-{{ setting_input['id'] }}_SCHEMA">
<!-- title and info -->
{% include "setting_header.html" %}
{% include "setting_input.html" %}
{% include "setting_select.html" %}
{% include "setting_checkbox.html" %}
{% include "setting_invalid.html"%}
</div>
{% endfor %}
<div data-multiple-delete-container
class="col-span-12 flex justify-center my-4">
<button data-{{ attribute_name }}-multiple-delete="{{ setting_simple['plugin_id'] }}" type="button" class="ml-3 dark:brightness-90 inline-block px-3 py-1.5 font-bold text-center text-white uppercase align-middle transition-all rounded-lg cursor-pointer bg-red-500 hover:bg-red-500/80 focus:bg-red-500/80 leading-normal text-md ease-in tracking-tight-rem shadow-xs bg-150 bg-x-25 hover:-translate-y-px active:opacity-85 hover:shadow-md">
Remove
</button>
</div>
<!-- end plugin settings -->
</div>
<!-- end multiple settings -->
{% endif %}
</div>
{% endfor %}
<!-- custom configs -->
{% for config in configs %}
<div data-simple data-config-container
class="w-full h-full px-1 mt-4 mb-2 col-span-12 grid grid-cols-12 h-full items-end">
<!-- title and desc -->
<div class="col-span-12" data-setting-header>
<div class="flex flex-col justify-start items-start">
<h5 class="sm:pl-3 sm:pr-2 mt-2 transition duration-300 ease-in-out font-bold text-base uppercase dark:text-white/90 mb-0">
{{ config['title'] }}
</h5>
<p class="max-w-[550px] sm:pl-3 sm:pr-2 text-sm dark:text-gray-300 mb-0">{{ config['subtitle'] }}</p>
</div>
</div>
<div data-editor-container="{{config['id']}}_SCHEMA" data-default-type="{{config['type']}}" data-default-name="{{config['name']}}" class="hidden w-full col-span-12 px-4">
<div class="mb-2 flex flex-wrap justify-start items-center" >
<input disabled type="text"
name="CONFIG_NAME"
data-editor-filename
class="dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 sm:ml-1 max-w-40 focus:valid:border-green-500 focus:file:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-1.5 py-1 font-normal text-gray-700 transition-all placeholder:text-gray-500 disabled:bg-gray-400 dark:disabled:bg-gray-800 dark:disabled:border-gray-800 dark:disabled:text-gray-300 disabled:text-gray-700"
placeholder="{{config['name']}}"
required />
<p class="ml-1 mb-0 dark:text-white/80 text-gray-700/80 text-sm">
.conf
</p>
</div>
<textarea data-editor-input class="hidden"></textarea>
<!-- editor-->
<div data-editor class="text-base w-full h-50 overflow-hidden overflow-y-auto my-2 border border-gray-300 dark:border-slate-800">
</div>
<!-- editor-->
</div>
</div>
{% endfor %}
</div>

View file

@ -61,7 +61,8 @@ try:
log_info("Toggle modal checked, trying settings ...")
assert_button_click(DRIVER, "//button[@data-toggle-settings-mode-btn='simple']")
# simple mode
# assert_button_click(DRIVER, "//button[@data-toggle-settings-mode-btn='simple']")
log_info("Start trying combobox filter ...")
@ -270,19 +271,19 @@ try:
assert_button_click(DRIVER, "//button[@data-services-action='new']")
current_mode = DRIVER.execute_script("return document.querySelector('button[data-toggle-settings-mode-btn]').getAttribute('data-toggle-settings-mode-btn')")
if current_mode != "simple":
log_error(f"""Default mode for new service need to be simple and not {current_mode}...""")
exit(1)
# current_mode = DRIVER.execute_script("return document.querySelector('button[data-toggle-settings-mode-btn]').getAttribute('data-toggle-settings-mode-btn')")
# if current_mode != "simple":
# log_error(f"""Default mode for new service need to be simple and not {current_mode}...""")
# exit(1)
# Switch to advanced mode
DRIVER.execute_script("document.querySelector('button[data-toggle-settings-mode-btn]').click()")
# # Switch to advanced mode
# DRIVER.execute_script("document.querySelector('button[data-toggle-settings-mode-btn]').click()")
current_mode = DRIVER.execute_script("return document.querySelector('button[data-toggle-settings-mode-btn]').getAttribute('data-toggle-settings-mode-btn')")
# current_mode = DRIVER.execute_script("return document.querySelector('button[data-toggle-settings-mode-btn]').getAttribute('data-toggle-settings-mode-btn')")
if current_mode != "advanced":
log_error(f"""Switching mode needed to return advanced mode, but he have {current_mode}...""")
exit(1)
# if current_mode != "advanced":
# log_error(f"""Switching mode needed to return advanced mode, but he have {current_mode}...""")
# exit(1)
server_name_input = safe_get_element(DRIVER, By.XPATH, "//form[@data-services-modal-form and @data-advanced]//input[@id='SERVER_NAME']")
assert isinstance(server_name_input, WebElement), "Input is not a WebElement"