Soft merge branch 'dev' into branch '1.6'

This commit is contained in:
Théophile Diot 2024-06-27 17:45:03 +01:00
commit c88acff516
No known key found for this signature in database
GPG key ID: FA995104A0BA376A
9 changed files with 77 additions and 52 deletions

View file

@ -95,7 +95,7 @@ jobs:
# Build cached image
- name: Build image
if: inputs.CACHE == true
uses: docker/build-push-action@31159d49c0d4756269a0940a750801a1ea5d7003 # v6.1.0
uses: docker/build-push-action@15560696de535e4014efeff63c48f16952e52dd1 # v6.2.0
with:
context: .
file: ${{ inputs.DOCKERFILE }}
@ -108,7 +108,7 @@ jobs:
# Build non-cached image
- name: Build image
if: inputs.CACHE != true
uses: docker/build-push-action@31159d49c0d4756269a0940a750801a1ea5d7003 # v6.1.0
uses: docker/build-push-action@15560696de535e4014efeff63c48f16952e52dd1 # v6.2.0
with:
context: .
file: ${{ inputs.DOCKERFILE }}

View file

@ -97,7 +97,7 @@ jobs:
# Build testing package image
- name: Build package image
if: inputs.RELEASE == 'testing' || inputs.RELEASE == 'dev' || inputs.RELEASE == 'ui' || inputs.RELEASE == '1.6'
uses: docker/build-push-action@31159d49c0d4756269a0940a750801a1ea5d7003 # v6.1.0
uses: docker/build-push-action@15560696de535e4014efeff63c48f16952e52dd1 # v6.2.0
with:
context: .
load: true
@ -109,7 +109,7 @@ jobs:
# Build non-testing package image
- name: Build package image
if: inputs.RELEASE != 'testing' && inputs.RELEASE != 'dev' && inputs.RELEASE != 'ui' && inputs.RELEASE != '1.6'
uses: docker/build-push-action@31159d49c0d4756269a0940a750801a1ea5d7003 # v6.1.0
uses: docker/build-push-action@15560696de535e4014efeff63c48f16952e52dd1 # v6.2.0
with:
context: .
load: true
@ -145,7 +145,7 @@ jobs:
images: ghcr.io/bunkerity/${{ inputs.LINUX }}-tests:${{ inputs.RELEASE }}
- name: Build test image
if: inputs.TEST == true
uses: docker/build-push-action@31159d49c0d4756269a0940a750801a1ea5d7003 # v6.1.0
uses: docker/build-push-action@15560696de535e4014efeff63c48f16952e52dd1 # v6.2.0
with:
context: .
file: tests/linux/Dockerfile-${{ inputs.LINUX }}

View file

@ -70,7 +70,7 @@ jobs:
images: bunkerity/${{ inputs.IMAGE }}
# Build and push
- name: Build and push
uses: docker/build-push-action@31159d49c0d4756269a0940a750801a1ea5d7003 # v6.1.0
uses: docker/build-push-action@15560696de535e4014efeff63c48f16952e52dd1 # v6.2.0
with:
context: .
file: ${{ inputs.DOCKERFILE }}

View file

@ -6,15 +6,15 @@ BunkerWeb comes with a plugin system making it possible to easily add new featur
Here is the list of "official" plugins that we maintain (see the [bunkerweb-plugins](https://github.com/bunkerity/bunkerweb-plugins) repository for more information) :
| Name | Version | Description | Link |
| :------------: | :-----: | :------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------: |
| Name | Version | Description | Link |
| :------------: | :-----: | :------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------: |
| **ClamAV** | 1.5 | Automatically scans uploaded files with the ClamAV antivirus engine and denies the request when a file is detected as malicious. | [bunkerweb-plugins/clamav](https://github.com/bunkerity/bunkerweb-plugins/tree/main/clamav) |
| **Coraza** | 1.5 | Inspect requests using a the Coraza WAF (alternative of ModSecurity). | [bunkerweb-plugins/coraza](https://github.com/bunkerity/bunkerweb-plugins/tree/main/coraza) |
| **Coraza** | 1.5 | Inspect requests using a the Coraza WAF (alternative of ModSecurity). | [bunkerweb-plugins/coraza](https://github.com/bunkerity/bunkerweb-plugins/tree/main/coraza) |
| **CrowdSec** | 1.5 | CrowdSec bouncer for BunkerWeb. | [bunkerweb-plugins/crowdsec](https://github.com/bunkerity/bunkerweb-plugins/tree/main/crowdsec) |
| **Discord** | 1.5 | Send security notifications to a Discord channel using a Webhook. | [bunkerweb-plugins/discord](https://github.com/bunkerity/bunkerweb-plugins/tree/main/discord) |
| **Slack** | 1.5 | Send security notifications to a Slack channel using a Webhook. | [bunkerweb-plugins/slack](https://github.com/bunkerity/bunkerweb-plugins/tree/main/slack) |
| **Discord** | 1.5 | Send security notifications to a Discord channel using a Webhook. | [bunkerweb-plugins/discord](https://github.com/bunkerity/bunkerweb-plugins/tree/main/discord) |
| **Slack** | 1.5 | Send security notifications to a Slack channel using a Webhook. | [bunkerweb-plugins/slack](https://github.com/bunkerity/bunkerweb-plugins/tree/main/slack) |
| **VirusTotal** | 1.5 | Automatically scans uploaded files with the VirusTotal API and denies the request when a file is detected as malicious. | [bunkerweb-plugins/virustotal](https://github.com/bunkerity/bunkerweb-plugins/tree/main/virustotal) |
| **WebHook** | 1.5 | Send security notifications to a custom HTTP endpoint using a Webhook. | [bunkerweb-plugins/webhook](https://github.com/bunkerity/bunkerweb-plugins/tree/main/webhook) |
| **WebHook** | 1.5 | Send security notifications to a custom HTTP endpoint using a Webhook. | [bunkerweb-plugins/webhook](https://github.com/bunkerity/bunkerweb-plugins/tree/main/webhook) |
## How to use a plugin
@ -322,29 +322,29 @@ A file named **plugin.json** and written at the root of the plugin folder must c
Here are the details of the fields :
| Field | Mandatory | Type | Description |
| :-----------: | :-------: | :----: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id` | yes | string | Internal ID for the plugin : must be unique among other plugins (including "core" ones) and contain only lowercase chars. |
| `name` | yes | string | Name of your plugin. |
| `description` | yes | string | Description of your plugin. |
| `version` | yes | string | Version of your plugin. |
| `stream` | yes | string | Information about stream support : `no`, `yes` or `partial`.
| `settings` | yes | dict | List of the settings of your plugin. |
| `jobs` | no | list | List of the jobs of your plugin. |
| Field | Mandatory | Type | Description |
| :-----------: | :-------: | :----: | :------------------------------------------------------------------------------------------------------------------------ |
| `id` | yes | string | Internal ID for the plugin : must be unique among other plugins (including "core" ones) and contain only lowercase chars. |
| `name` | yes | string | Name of your plugin. |
| `description` | yes | string | Description of your plugin. |
| `version` | yes | string | Version of your plugin. |
| `stream` | yes | string | Information about stream support : `no`, `yes` or `partial`. |
| `settings` | yes | dict | List of the settings of your plugin. |
| `jobs` | no | list | List of the jobs of your plugin. |
Each setting has the following fields (the key is the ID of the settings used in a configuration) :
| Field | Mandatory | Type | Description |
| :--------: | :-------: | :----: | :----------------------------------------------------------- |
| `context` | yes | string | Context of the setting : `multisite` or `global`. |
| `default` | yes | string | The default value of the setting. |
| `help` | yes | string | Help text about the plugin (shown in web UI). |
| `id` | yes | string | Internal ID used by the web UI for HTML elements. |
| `label` | yes | string | Label shown by the web UI. |
| `regex` | yes | string | The regex used to validate the value provided by the user. |
| `type` | yes | string | The type of the field : `text`, `check`, `select` or `password`. |
| `multiple` | no | string | Unique ID to group multiple settings with numbers as suffix. |
| `select` | no | list | List of possible string values when `type` is `select`. |
| Field | Mandatory | Type | Description |
| :--------: | :-------: | :----: | :--------------------------------------------------------------- |
| `context` | yes | string | Context of the setting : `multisite` or `global`. |
| `default` | yes | string | The default value of the setting. |
| `help` | yes | string | Help text about the plugin (shown in web UI). |
| `id` | yes | string | Internal ID used by the web UI for HTML elements. |
| `label` | yes | string | Label shown by the web UI. |
| `regex` | yes | string | The regex used to validate the value provided by the user. |
| `type` | yes | string | The type of the field : `text`, `check`, `select` or `password`. |
| `multiple` | no | string | Unique ID to group multiple settings with numbers as suffix. |
| `select` | no | list | List of possible string values when `type` is `select`. |
Each job has the following fields :
@ -431,15 +431,15 @@ return myplugin
The declared functions are automatically called during specific contexts. Here are the details of each function :
| Function | Context | Description | Return value |
| :------: | :--------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `init` | [init_by_lua](https://github.com/openresty/lua-nginx-module#init_by_lua) | Called when NGINX just started or received a reload order. the typical use case is to prepare any data that will be used by your plugin. | `ret`, `msg`<ul><li>`ret` (boolean) : true if no error or else false</li><li>`msg` (string) : success or error message</li></ul>|
| `set` | [set_by_lua](https://github.com/openresty/lua-nginx-module#set_by_lua) | Called before each request received by the server.The typical use case is for computing before access phase. | `ret`, `msg`<ul><li>`ret` (boolean) : true if no error or else false</li><li>`msg` (string) : success or error message</li></ul>|
| `access` | [access_by_lua](https://github.com/openresty/lua-nginx-module#access_by_lua) | Called on each request received by the server. The typical use case is to do the security checks here and deny the request if needed. | `ret`, `msg`,`status`,`redirect`<ul><li>`ret` (boolean) : true if no error or else false</li><li>`msg` (string) : success or error message</li><li>`status` (number) : interrupt current process and return [HTTP status](https://github.com/openresty/lua-nginx-module#http-status-constants)</li><li>`redirect` (URL) : if set will redirect to given URL</li></ul> |
| `log` | [log_by_lua](https://github.com/openresty/lua-nginx-module#log_by_lua) | Called when a request has finished (and before it gets logged to the access logs). The typical use case is to make stats or compute counters for example. | `ret`, `msg`<ul><li>`ret` (boolean) : true if no error or else false</li><li>`msg` (string) : success or error message</li></ul> |
| `log_default` | [log_by_lua](https://github.com/openresty/lua-nginx-module#log_by_lua) | Same as `log` but only called on the default server. | `ret`, `msg`<ul><li>`ret` (boolean) : true if no error or else false</li><li>`msg` (string) : success or error message</li></ul> |
| `preread` | [preread_by_lua](https://github.com/openresty/stream-lua-nginx-module#preread_by_lua_block) | Similar to the `access` function but for stream mode. | `ret`, `msg`,`status`<ul><li>`ret` (boolean) : true if no error or else false</li><li>`msg` (string) : success or error message</li><li>`status` (number) : interrupt current process and return [status](https://github.com/openresty/lua-nginx-module#http-status-constants)</li></ul> |
| `log_stream` | [log_by_lua](https://github.com/openresty/stream-lua-nginx-module#log_by_lua_block) | Similar to the `log` function but for stream mode. | `ret`, `msg`<ul><li>`ret` (boolean) : true if no error or else false</li><li>`msg` (string) : success or error message</li></ul> |
| Function | Context | Description | Return value |
| :-----------: | :-----------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `init` | [init_by_lua](https://github.com/openresty/lua-nginx-module#init_by_lua) | Called when NGINX just started or received a reload order. the typical use case is to prepare any data that will be used by your plugin. | `ret`, `msg`<ul><li>`ret` (boolean) : true if no error or else false</li><li>`msg` (string) : success or error message</li></ul> |
| `set` | [set_by_lua](https://github.com/openresty/lua-nginx-module#set_by_lua) | Called before each request received by the server.The typical use case is for computing before access phase. | `ret`, `msg`<ul><li>`ret` (boolean) : true if no error or else false</li><li>`msg` (string) : success or error message</li></ul> |
| `access` | [access_by_lua](https://github.com/openresty/lua-nginx-module#access_by_lua) | Called on each request received by the server. The typical use case is to do the security checks here and deny the request if needed. | `ret`, `msg`,`status`,`redirect`<ul><li>`ret` (boolean) : true if no error or else false</li><li>`msg` (string) : success or error message</li><li>`status` (number) : interrupt current process and return [HTTP status](https://github.com/openresty/lua-nginx-module#http-status-constants)</li><li>`redirect` (URL) : if set will redirect to given URL</li></ul> |
| `log` | [log_by_lua](https://github.com/openresty/lua-nginx-module#log_by_lua) | Called when a request has finished (and before it gets logged to the access logs). The typical use case is to make stats or compute counters for example. | `ret`, `msg`<ul><li>`ret` (boolean) : true if no error or else false</li><li>`msg` (string) : success or error message</li></ul> |
| `log_default` | [log_by_lua](https://github.com/openresty/lua-nginx-module#log_by_lua) | Same as `log` but only called on the default server. | `ret`, `msg`<ul><li>`ret` (boolean) : true if no error or else false</li><li>`msg` (string) : success or error message</li></ul> |
| `preread` | [preread_by_lua](https://github.com/openresty/stream-lua-nginx-module#preread_by_lua_block) | Similar to the `access` function but for stream mode. | `ret`, `msg`,`status`<ul><li>`ret` (boolean) : true if no error or else false</li><li>`msg` (string) : success or error message</li><li>`status` (number) : interrupt current process and return [status](https://github.com/openresty/lua-nginx-module#http-status-constants)</li></ul> |
| `log_stream` | [log_by_lua](https://github.com/openresty/stream-lua-nginx-module#log_by_lua_block) | Similar to the `log` function but for stream mode. | `ret`, `msg`<ul><li>`ret` (boolean) : true if no error or else false</li><li>`msg` (string) : success or error message</li></ul> |
#### Libraries

View file

@ -74,11 +74,16 @@ server {
.. nonce_script
.. "'; style-src 'nonce-"
.. nonce_style
.. "'; base-uri 'none'; img-src 'self' data:; font-src 'self' data:; require-trusted-types-for 'script';"
.. "'; frame-ancestors 'none'; base-uri 'none'; img-src 'self' data:; font-src 'self' data:; require-trusted-types-for 'script';"
-- Remove server header
ngx.header["Server"] = nil
-- Override HSTS header
if ngx.var.scheme == "https" then
ngx.header["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains; preload"
end
-- Render template
render("index.html", {
nonce_style = nonce_style,

View file

@ -70,6 +70,7 @@ function antibot:header()
.. self.ctx.bw.antibot_nonce_script
.. "'",
["style-src"] = "'self' 'nonce-" .. self.ctx.bw.antibot_nonce_style .. "'",
["frame-ancestors"] = "'none'",
["require-trusted-types-for"] = "'script'",
}
if self.session_data.type == "recaptcha" then

View file

@ -89,16 +89,30 @@ function errors:render_template(code)
local nonce_script = rand(16)
local nonce_style = rand(16)
-- Override headers
local header = "Content-Security-Policy"
if self.variables["CONTENT_SECURITY_POLICY_REPORT_ONLY"] == "yes" then
header = header .. "-Report-Only"
end
ngx.header[header] = "default-src 'none'; form-action 'self'; script-src 'strict-dynamic' 'nonce-"
-- Override CSP header
--luacheck: ignore 631
ngx.header["Content-Security-Policy"] = "default-src 'none'; script-src http: https: 'unsafe-inline' 'strict-dynamic' 'nonce-"
.. nonce_script
.. "' 'unsafe-inline' http: https:; img-src 'self' data:; style-src 'self' 'nonce-"
.. "'; style-src 'nonce-"
.. nonce_style
.. "'; font-src 'self' data:; base-uri 'self'; require-trusted-types-for 'script';"
--luacheck: ignore 631
.. "'; frame-ancestors 'none'; base-uri 'none'; img-src 'self' data:; font-src 'self' data:; require-trusted-types-for 'script';"
-- Remove server header
ngx.header["Server"] = nil
-- Override HSTS header
local ssl
if self.ctx.bw and self.ctx.bw.https_configured == "yes" then
ssl = true
else
ssl = ngx.var.scheme == "https"
end
if ssl then
ngx.header["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains; preload"
end
-- Render template
render("error.html", {

View file

@ -80,7 +80,7 @@ end
function headers:header()
-- Override upstream headers if needed
local ngx_header = ngx.header
local ssl = self.ctx.bw.scheme == "https"
local ssl = self.ctx.bw.https_configured == "yes"
for variable, header in pairs(self.all_headers) do
if
ngx_header[header] == nil

View file

@ -20,13 +20,18 @@ location / {
local nonce_style = rand(16)
-- Override CSP header
ngx.header["Content-Security-Policy"] = "default-src 'none'; form-action 'self'; img-src 'self' data:; style-src 'self' 'nonce-"
ngx.header["Content-Security-Policy"] = "default-src 'none'; frame-ancestors 'none'; form-action 'self'; img-src 'self' data:; style-src 'self' 'nonce-"
.. nonce_style
.. "'; font-src 'self' data:; base-uri 'self'; require-trusted-types-for 'script';"
-- Remove server header
ngx.header["Server"] = nil
-- Override HSTS header
if ngx.var.scheme == "https" then
ngx.header["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains; preload"
end
-- Render template
render("default.html", {
nonce_style = nonce_style,