mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
Merge pull request #1276 from bunkerity/dev
Merge branch "dev' into branch "staging"
This commit is contained in:
commit
f7280ce7cf
173 changed files with 2155 additions and 1642 deletions
2
.github/workflows/beta.yml
vendored
2
.github/workflows/beta.yml
vendored
|
|
@ -133,7 +133,7 @@ jobs:
|
|||
versionrpm: ${{ steps.getversionrpm.outputs.versionrpm }}
|
||||
steps:
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Get VERSION
|
||||
id: getversion
|
||||
run: echo "version=$(cat src/VERSION | tr -d '\n')" >> "$GITHUB_OUTPUT"
|
||||
|
|
|
|||
6
.github/workflows/codeql.yml
vendored
6
.github/workflows/codeql.yml
vendored
|
|
@ -19,7 +19,7 @@ jobs:
|
|||
language: ["python", "javascript"]
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Set up Python 3.9
|
||||
uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
|
||||
if: matrix.language == 'python'
|
||||
|
|
@ -35,12 +35,12 @@ jobs:
|
|||
python -m pip install --no-cache-dir --require-hashes -r src/common/db/requirements.txt
|
||||
echo "CODEQL_PYTHON=$(which python)" >> $GITHUB_ENV
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # v3.25.8
|
||||
uses: github/codeql-action/init@23acc5c183826b7a8a97bce3cecc52db901f8251 # v3.25.10
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
config-file: ./.github/codeql.yml
|
||||
setup-python-dependencies: false
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # v3.25.8
|
||||
uses: github/codeql-action/analyze@23acc5c183826b7a8a97bce3cecc52db901f8251 # v3.25.10
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
|
|
|||
6
.github/workflows/container-build.yml
vendored
6
.github/workflows/container-build.yml
vendored
|
|
@ -45,7 +45,7 @@ jobs:
|
|||
steps:
|
||||
# Prepare
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Replace VERSION
|
||||
if: inputs.RELEASE == 'testing' || inputs.RELEASE == 'dev'
|
||||
run: ./misc/update-version.sh ${{ inputs.RELEASE }}
|
||||
|
|
@ -92,7 +92,7 @@ jobs:
|
|||
# Build cached image
|
||||
- name: Build image
|
||||
if: inputs.CACHE == true
|
||||
uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
|
||||
uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0
|
||||
with:
|
||||
context: .
|
||||
file: ${{ inputs.DOCKERFILE }}
|
||||
|
|
@ -105,7 +105,7 @@ jobs:
|
|||
# Build non-cached image
|
||||
- name: Build image
|
||||
if: inputs.CACHE != true
|
||||
uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
|
||||
uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0
|
||||
with:
|
||||
context: .
|
||||
file: ${{ inputs.DOCKERFILE }}
|
||||
|
|
|
|||
2
.github/workflows/create-arm.yml
vendored
2
.github/workflows/create-arm.yml
vendored
|
|
@ -33,7 +33,7 @@ jobs:
|
|||
steps:
|
||||
# Prepare
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Get ARM availabilities
|
||||
id: availabilities
|
||||
uses: scaleway/action-scw@be2696f261325a78354eda14988c80405f33e082
|
||||
|
|
|
|||
2
.github/workflows/dev-update-mmdb.yml
vendored
2
.github/workflows/dev-update-mmdb.yml
vendored
|
|
@ -12,7 +12,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.BUNKERBOT_TOKEN }}
|
||||
|
|
|
|||
4
.github/workflows/dev.yml
vendored
4
.github/workflows/dev.yml
vendored
|
|
@ -80,7 +80,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- id: set-matrix
|
||||
run: |
|
||||
tests=$(find ./tests/ui/ -name "*_page.py" -type f -printf "%f\n" | jq -c --raw-input --slurp 'split("\n")| .[0:-1]')
|
||||
|
|
@ -113,7 +113,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- id: set-matrix
|
||||
run: |
|
||||
tests=$(find ./tests/core/ -maxdepth 1 -mindepth 1 -type d -printf "%f\n" | jq -c --raw-input --slurp 'split("\n")| .[0:-1]')
|
||||
|
|
|
|||
2
.github/workflows/doc-to-pdf.yml
vendored
2
.github/workflows/doc-to-pdf.yml
vendored
|
|
@ -13,7 +13,7 @@ jobs:
|
|||
steps:
|
||||
# Prepare
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Install Python
|
||||
uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
|
||||
with:
|
||||
|
|
|
|||
8
.github/workflows/linux-build.yml
vendored
8
.github/workflows/linux-build.yml
vendored
|
|
@ -37,7 +37,7 @@ jobs:
|
|||
steps:
|
||||
# Prepare
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Replace VERSION
|
||||
if: inputs.RELEASE == 'testing' || inputs.RELEASE == 'dev' || inputs.RELEASE == 'ui'
|
||||
run: ./misc/update-version.sh ${{ inputs.RELEASE }}
|
||||
|
|
@ -94,7 +94,7 @@ jobs:
|
|||
# Build testing package image
|
||||
- name: Build package image
|
||||
if: inputs.RELEASE == 'testing' || inputs.RELEASE == 'dev' || inputs.RELEASE == 'ui'
|
||||
uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
|
||||
uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0
|
||||
with:
|
||||
context: .
|
||||
load: true
|
||||
|
|
@ -106,7 +106,7 @@ jobs:
|
|||
# Build non-testing package image
|
||||
- name: Build package image
|
||||
if: inputs.RELEASE != 'testing' && inputs.RELEASE != 'dev'
|
||||
uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
|
||||
uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0
|
||||
with:
|
||||
context: .
|
||||
load: true
|
||||
|
|
@ -142,7 +142,7 @@ jobs:
|
|||
images: ghcr.io/bunkerity/${{ inputs.LINUX }}-tests:${{ inputs.RELEASE }}
|
||||
- name: Build test image
|
||||
if: inputs.TEST == true
|
||||
uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
|
||||
uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0
|
||||
with:
|
||||
context: .
|
||||
file: tests/linux/Dockerfile-${{ inputs.LINUX }}
|
||||
|
|
|
|||
2
.github/workflows/push-doc.yml
vendored
2
.github/workflows/push-doc.yml
vendored
|
|
@ -18,7 +18,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.BUNKERBOT_TOKEN }}
|
||||
|
|
|
|||
4
.github/workflows/push-docker.yml
vendored
4
.github/workflows/push-docker.yml
vendored
|
|
@ -33,7 +33,7 @@ jobs:
|
|||
steps:
|
||||
# Prepare
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
|
||||
with:
|
||||
|
|
@ -70,7 +70,7 @@ jobs:
|
|||
images: bunkerity/${{ inputs.IMAGE }}
|
||||
# Build and push
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
|
||||
uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0
|
||||
with:
|
||||
context: .
|
||||
file: ${{ inputs.DOCKERFILE }}
|
||||
|
|
|
|||
2
.github/workflows/push-github.yml
vendored
2
.github/workflows/push-github.yml
vendored
|
|
@ -15,7 +15,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Checkout
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
# Get PDF doc
|
||||
- name: Get documentation
|
||||
if: inputs.VERSION != 'testing'
|
||||
|
|
|
|||
4
.github/workflows/push-packagecloud.yml
vendored
4
.github/workflows/push-packagecloud.yml
vendored
|
|
@ -40,9 +40,9 @@ jobs:
|
|||
steps:
|
||||
# Prepare
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Install ruby
|
||||
uses: ruby/setup-ruby@d5fb7a202fc07872cb44f00ba8e6197b70cb0c55 # v1.179.0
|
||||
uses: ruby/setup-ruby@ff740bc00a01b3a50fffc55a1071b1060eeae9dc # v1.180.0
|
||||
with:
|
||||
ruby-version: "3.0"
|
||||
- name: Install packagecloud
|
||||
|
|
|
|||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
|
|
@ -143,7 +143,7 @@ jobs:
|
|||
versionrpm: ${{ steps.getversionrpm.outputs.versionrpm }}
|
||||
steps:
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Get VERSION
|
||||
id: getversion
|
||||
run: echo "version=$(cat src/VERSION | tr -d '\n')" >> "$GITHUB_OUTPUT"
|
||||
|
|
|
|||
2
.github/workflows/rm-arm.yml
vendored
2
.github/workflows/rm-arm.yml
vendored
|
|
@ -21,7 +21,7 @@ jobs:
|
|||
steps:
|
||||
# Prepare
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Delete ARM VM
|
||||
uses: scaleway/action-scw@be2696f261325a78354eda14988c80405f33e082
|
||||
with:
|
||||
|
|
|
|||
4
.github/workflows/scorecards-analysis.yml
vendored
4
.github/workflows/scorecards-analysis.yml
vendored
|
|
@ -15,7 +15,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: "Run analysis"
|
||||
|
|
@ -25,6 +25,6 @@ jobs:
|
|||
results_format: sarif
|
||||
publish_results: true
|
||||
- name: "Upload SARIF results to code scanning"
|
||||
uses: github/codeql-action/upload-sarif@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # v3.25.8
|
||||
uses: github/codeql-action/upload-sarif@23acc5c183826b7a8a97bce3cecc52db901f8251 # v3.25.10
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
|
|
|||
2
.github/workflows/staging-create-infra.yml
vendored
2
.github/workflows/staging-create-infra.yml
vendored
|
|
@ -21,7 +21,7 @@ jobs:
|
|||
run: ssh-keygen -b 2048 -t rsa -f ~/.ssh/id_rsa -q -N "" && ssh-keygen -f ~/.ssh/id_rsa -y > ~/.ssh/id_rsa.pub && echo -e "Host *\n StrictHostKeyChecking no" > ~/.ssh/ssh_config
|
||||
if: inputs.TYPE != 'k8s'
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Install terraform
|
||||
uses: hashicorp/setup-terraform@651471c36a6092792c552e8b1bef71e592b462d8 # v3.1.1
|
||||
- name: Install kubectl
|
||||
|
|
|
|||
2
.github/workflows/staging-delete-infra.yml
vendored
2
.github/workflows/staging-delete-infra.yml
vendored
|
|
@ -20,7 +20,7 @@ jobs:
|
|||
steps:
|
||||
# Prepare
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Install terraform
|
||||
uses: hashicorp/setup-terraform@651471c36a6092792c552e8b1bef71e592b462d8 # v3.1.1
|
||||
- uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7
|
||||
|
|
|
|||
2
.github/workflows/staging-tests.yml
vendored
2
.github/workflows/staging-tests.yml
vendored
|
|
@ -25,7 +25,7 @@ jobs:
|
|||
steps:
|
||||
# Prepare
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Login to ghcr
|
||||
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
|
||||
with:
|
||||
|
|
|
|||
4
.github/workflows/staging.yml
vendored
4
.github/workflows/staging.yml
vendored
|
|
@ -91,7 +91,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- id: set-matrix
|
||||
run: |
|
||||
tests=$(find ./tests/core/ -maxdepth 1 -mindepth 1 -type d -printf "%f\n" | jq -c --raw-input --slurp 'split("\n")| .[0:-1]')
|
||||
|
|
@ -102,7 +102,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- id: set-matrix
|
||||
run: |
|
||||
tests=$(find ./tests/ui/ -name "*_page.py" -type f -printf "%f\n" | jq -c --raw-input --slurp 'split("\n")| .[0:-1]')
|
||||
|
|
|
|||
2
.github/workflows/test-core-linux.yml
vendored
2
.github/workflows/test-core-linux.yml
vendored
|
|
@ -16,7 +16,7 @@ jobs:
|
|||
steps:
|
||||
# Prepare
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Set up Python 3.12
|
||||
uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
|
||||
with:
|
||||
|
|
|
|||
2
.github/workflows/test-core.yml
vendored
2
.github/workflows/test-core.yml
vendored
|
|
@ -16,7 +16,7 @@ jobs:
|
|||
steps:
|
||||
# Prepare
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Login to ghcr
|
||||
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
|
||||
with:
|
||||
|
|
|
|||
2
.github/workflows/tests-ui-linux.yml
vendored
2
.github/workflows/tests-ui-linux.yml
vendored
|
|
@ -16,7 +16,7 @@ jobs:
|
|||
steps:
|
||||
# Prepare
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Set up Python 3.12
|
||||
uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
|
||||
with:
|
||||
|
|
|
|||
2
.github/workflows/tests-ui.yml
vendored
2
.github/workflows/tests-ui.yml
vendored
|
|
@ -15,7 +15,7 @@ jobs:
|
|||
steps:
|
||||
# Prepare
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Login to ghcr
|
||||
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
|
||||
with:
|
||||
|
|
|
|||
2
.github/workflows/ui.yml
vendored
2
.github/workflows/ui.yml
vendored
|
|
@ -67,7 +67,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- id: set-matrix
|
||||
run: |
|
||||
tests=$(find ./tests/ui/ -name "*_page.py" -type f -printf "%f\n" | jq -c --raw-input --slurp 'split("\n")| .[0:-1]')
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
- [FEATURE] Add experimental support of HTTP/3 (QUIC)
|
||||
- [FEATURE] Optimize the way the scheduler handles jobs and the way the jobs are executed
|
||||
- [FEATURE] Optimize the way the cache files are being refreshed from the database
|
||||
- [FEATURE] Add failover logic in case the NGINX configuration is not valid to fallback to the previous configuration and log the error to prevent the service from being stopped
|
||||
- [UI] Force HTTPS on setup wizard
|
||||
- [UI] Fallback to self-signed certificate when UI is installed with setup wizard and let's encrypt is not used
|
||||
- [UI] Add OVERRIDE_ADMIN_CREDS environment variable to allow overriding the default admin credentials even if an admin user already exists
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ In other words, the scheduler is the brain of BunkerWeb.
|
|||
## BunkerWeb Cloud
|
||||
|
||||
<p align="center">
|
||||
<img alt="Docker banner" src="https://github.com/bunkerity/bunkerweb/raw/v1.5.8/docs/assets/img/bunkerweb-cloud.svg" />
|
||||
<img alt="Docker banner" src="https://github.com/bunkerity/bunkerweb/raw/v1.5.8/docs/assets/img/bunkerweb-cloud.webp" />
|
||||
</p>
|
||||
|
||||
BunkerWeb Cloud is the easiest way to get started with BunkerWeb. It offers you a fully managed BunkerWeb service with no hassle. Think of a like a BunkerWeb-as-a-Service !
|
||||
|
|
|
|||
BIN
docs/assets/img/bunkerweb-cloud.webp
Normal file
BIN
docs/assets/img/bunkerweb-cloud.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
|
|
@ -3,7 +3,7 @@
|
|||
## BunkerWeb Cloud
|
||||
|
||||
<figure markdown>
|
||||
{ align=center, width="600" }
|
||||
{ align=center, width="600" }
|
||||
<figcaption>BunkerWeb Cloud</figcaption>
|
||||
</figure>
|
||||
|
||||
|
|
|
|||
|
|
@ -331,9 +331,9 @@ mkdocs-print-site-plugin==2.5.0 \
|
|||
--hash=sha256:48b3d41ae80384de72062b2712fce677f2e46d8364d9fe603ba837b0cf7156a4 \
|
||||
--hash=sha256:95dccc8d5cc8a59da67815a2d3304ef0101b065e363f2b9ac919c23d6196dd24
|
||||
# via -r requirements.in
|
||||
packaging==24.0 \
|
||||
--hash=sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5 \
|
||||
--hash=sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9
|
||||
packaging==24.1 \
|
||||
--hash=sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002 \
|
||||
--hash=sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124
|
||||
# via
|
||||
# mkdocs
|
||||
# typepy
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ Besides the HTTPS / SSL/TLS configuration, the following settings related to HTT
|
|||
| `AUTO_REDIRECT_HTTP_TO_HTTPS` | `yes` | When set to `yes`, will redirect every HTTP request to HTTPS only if BunkerWeb is configured with HTTPS. |
|
||||
| `SSL_PROTOCOLS` | `TLSv1.2 TLSv1.3` | List of supported SSL/TLS protocols when SSL is enabled. |
|
||||
| `HTTP2` | `yes` | When set to `yes`, will enable HTTP2 protocol support when using HTTPS. |
|
||||
| `HTTP3` | `no` | When set to `yes`, will enable HTTP3 protocol support when using HTTPS. |
|
||||
| `HTTP3` | `no` | When set to `yes`, will enable HTTP3 protocol support when using HTTPS. |
|
||||
| `HTTP3_ALT_SVC_PORT` | `443` | HTTP3 alternate service port. This value will be used as part of the Alt-Svc header. |
|
||||
| `LISTEN_HTTP` | `yes` | When set to `no`, BunkerWeb will not listen for HTTP requests. Useful if you want HTTPS only for example. |
|
||||
|
||||
|
|
@ -354,30 +354,26 @@ STREAM support :warning:
|
|||
|
||||
You can use the following settings to set up blacklisting :
|
||||
|
||||
| Setting | Default | Context | Multiple | Description |
|
||||
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | --------- | -------- | ------------------------------------------------------------------------------------------------ |
|
||||
| `USE_BLACKLIST` | `yes` | multisite | no | Activate blacklist feature. |
|
||||
| `BLACKLIST_IP` | | multisite | no | List of IP/network, separated with spaces, to block. |
|
||||
| `BLACKLIST_IP_URLS` | `https://www.dan.me.uk/torlist/?exit` | global | no | List of URLs, separated with spaces, containing bad IP/network to block. |
|
||||
| `BLACKLIST_RDNS_GLOBAL` | `yes` | multisite | no | Only perform RDNS blacklist checks on global IP addresses. |
|
||||
| `BLACKLIST_RDNS` | `.shodan.io .censys.io` | multisite | no | List of reverse DNS suffixes, separated with spaces, to block. |
|
||||
| `BLACKLIST_RDNS_URLS` | | global | no | List of URLs, separated with spaces, containing reverse DNS suffixes to block. |
|
||||
| `BLACKLIST_ASN` | | multisite | no | List of ASN numbers, separated with spaces, to block. |
|
||||
| `BLACKLIST_ASN_URLS` | | global | no | List of URLs, separated with spaces, containing ASN to block. |
|
||||
| `BLACKLIST_USER_AGENT` | | multisite | no | List of User-Agent (PCRE regex), separated with spaces, to block. |
|
||||
| `BLACKLIST_USER_AGENT_URLS` | `https://raw.githubusercontent.com/mitchellkrogza/nginx-ultimate-bad-bot-blocker/master/_generator_lists/bad-user-agents.list` | global | no | List of URLs, separated with spaces, containing bad User-Agent to block. |
|
||||
| `BLACKLIST_URI` | | multisite | no | List of URI (PCRE regex), separated with spaces, to block. |
|
||||
| `BLACKLIST_URI_URLS` | | global | no | List of URLs, separated with spaces, containing bad URI to block. |
|
||||
| `BLACKLIST_IGNORE_IP` | | multisite | no | List of IP/network, separated with spaces, to ignore in the blacklist. |
|
||||
| `BLACKLIST_IGNORE_IP_URLS` | | global | no | List of URLs, separated with spaces, containing IP/network to ignore in the blacklist. |
|
||||
| `BLACKLIST_IGNORE_RDNS` | | multisite | no | List of reverse DNS suffixes, separated with spaces, to ignore in the blacklist. |
|
||||
| `BLACKLIST_IGNORE_RDNS_URLS` | | global | no | List of URLs, separated with spaces, containing reverse DNS suffixes to ignore in the blacklist. |
|
||||
| `BLACKLIST_IGNORE_ASN` | | multisite | no | List of ASN numbers, separated with spaces, to ignore in the blacklist. |
|
||||
| `BLACKLIST_IGNORE_ASN_URLS` | | global | no | List of URLs, separated with spaces, containing ASN to ignore in the blacklist. |
|
||||
| `BLACKLIST_IGNORE_USER_AGENT` | | multisite | no | List of User-Agent (PCRE regex), separated with spaces, to ignore in the blacklist. |
|
||||
| `BLACKLIST_IGNORE_USER_AGENT_URLS` | | global | no | List of URLs, separated with spaces, containing User-Agent to ignore in the blacklist. |
|
||||
| `BLACKLIST_IGNORE_URI` | | multisite | no | List of URI (PCRE regex), separated with spaces, to ignore in the blacklist. |
|
||||
| `BLACKLIST_IGNORE_URI_URLS` | | global | no | List of URLs, separated with spaces, containing URI to ignore in the blacklist. |
|
||||
| Setting | Default | Context | Multiple | Description |
|
||||
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | --------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `USE_BLACKLIST` | `yes` | multisite | no | Activate blacklist feature. |
|
||||
| `BLACKLIST_IP` | | multisite | no | List of IP/network, separated with spaces, to block. |
|
||||
| `BLACKLIST_RDNS_GLOBAL` | `yes` | multisite | no | Only perform RDNS blacklist checks on global IP addresses. |
|
||||
| `BLACKLIST_RDNS` | `.shodan.io .censys.io` | multisite | no | List of reverse DNS suffixes, separated with spaces, to block. |
|
||||
| `BLACKLIST_ASN` | | multisite | no | List of ASN numbers, separated with spaces, to block. |
|
||||
| `BLACKLIST_ASN_URLS` | | global | no | List of URLs, separated with spaces, containing ASN to block. |
|
||||
| `BLACKLIST_USER_AGENT` | | multisite | no | List of User-Agent (PCRE regex), separated with spaces, to block. |
|
||||
| `BLACKLIST_URI` | | multisite | no | List of URI (PCRE regex), separated with spaces, to block. |
|
||||
| `BLACKLIST_IP_URLS` | `https://www.dan.me.uk/torlist/?exit` | global | no | List of URLs, separated with spaces, containing bad IP/network to block. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
| `BLACKLIST_RDNS_URLS` | | global | no | List of URLs, separated with spaces, containing reverse DNS suffixes to block. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
| `BLACKLIST_ASN_URLS` | | global | no | List of URLs, separated with spaces, containing ASN to block. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
| `BLACKLIST_USER_AGENT_URLS` | `https://raw.githubusercontent.com/mitchellkrogza/nginx-ultimate-bad-bot-blocker/master/_generator_lists/bad-user-agents.list` | global | no | List of URLs, separated with spaces, containing bad User-Agent to block. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
| `BLACKLIST_URI_URLS` | | global | no | List of URLs, separated with spaces, containing bad URI to block. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
| `BLACKLIST_IGNORE_IP_URLS` | | global | no | List of URLs, separated with spaces, containing IP/network to ignore in the blacklist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
| `BLACKLIST_IGNORE_RDNS_URLS` | | global | no | List of URLs, separated with spaces, containing reverse DNS suffixes to ignore in the blacklist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
| `BLACKLIST_IGNORE_ASN_URLS` | | global | no | List of URLs, separated with spaces, containing ASN to ignore in the blacklist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
| `BLACKLIST_IGNORE_USER_AGENT_URLS` | | global | no | List of URLs, separated with spaces, containing User-Agent to ignore in the blacklist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
| `BLACKLIST_IGNORE_URI_URLS` | | global | no | List of URLs, separated with spaces, containing URI to ignore in the blacklist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
|
||||
When using stream mode, only IP, RDNS and ASN checks will be done.
|
||||
|
||||
|
|
@ -387,20 +383,20 @@ STREAM support :warning:
|
|||
|
||||
You can use the following settings to set up greylisting :
|
||||
|
||||
| Setting | Default | Context | Multiple | Description |
|
||||
| -------------------------- | ------- | --------- | -------- | ---------------------------------------------------------------------------------------------- |
|
||||
| `USE_GREYLIST` | `no` | multisite | no | Activate greylist feature. |
|
||||
| `GREYLIST_IP` | | multisite | no | List of IP/network, separated with spaces, to put into the greylist. |
|
||||
| `GREYLIST_IP_URLS` | | global | no | List of URLs, separated with spaces, containing good IP/network to put into the greylist. |
|
||||
| `GREYLIST_RDNS_GLOBAL` | `yes` | multisite | no | Only perform RDNS greylist checks on global IP addresses. |
|
||||
| `GREYLIST_RDNS` | | multisite | no | List of reverse DNS suffixes, separated with spaces, to put into the greylist. |
|
||||
| `GREYLIST_RDNS_URLS` | | global | no | List of URLs, separated with spaces, containing reverse DNS suffixes to put into the greylist. |
|
||||
| `GREYLIST_ASN` | | multisite | no | List of ASN numbers, separated with spaces, to put into the greylist. |
|
||||
| `GREYLIST_ASN_URLS` | | global | no | List of URLs, separated with spaces, containing ASN to put into the greylist. |
|
||||
| `GREYLIST_USER_AGENT` | | multisite | no | List of User-Agent (PCRE regex), separated with spaces, to put into the greylist. |
|
||||
| `GREYLIST_USER_AGENT_URLS` | | global | no | List of URLs, separated with spaces, containing good User-Agent to put into the greylist. |
|
||||
| `GREYLIST_URI` | | multisite | no | List of URI (PCRE regex), separated with spaces, to put into the greylist. |
|
||||
| `GREYLIST_URI_URLS` | | global | no | List of URLs, separated with spaces, containing bad URI to put into the greylist. |
|
||||
| Setting | Default | Context | Multiple | Description |
|
||||
| -------------------------- | ------- | --------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `USE_GREYLIST` | `no` | multisite | no | Activate greylist feature. |
|
||||
| `GREYLIST_IP` | | multisite | no | List of IP/network, separated with spaces, to put into the greylist. |
|
||||
| `GREYLIST_RDNS_GLOBAL` | `yes` | multisite | no | Only perform RDNS greylist checks on global IP addresses. |
|
||||
| `GREYLIST_RDNS` | | multisite | no | List of reverse DNS suffixes, separated with spaces, to put into the greylist. |
|
||||
| `GREYLIST_ASN` | | multisite | no | List of ASN numbers, separated with spaces, to put into the greylist. |
|
||||
| `GREYLIST_USER_AGENT` | | multisite | no | List of User-Agent (PCRE regex), separated with spaces, to put into the greylist. |
|
||||
| `GREYLIST_URI` | | multisite | no | List of URI (PCRE regex), separated with spaces, to put into the greylist. |
|
||||
| `GREYLIST_IP_URLS` | | global | no | List of URLs, separated with spaces, containing good IP/network to put into the greylist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
| `GREYLIST_RDNS_URLS` | | global | no | List of URLs, separated with spaces, containing reverse DNS suffixes to put into the greylist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
| `GREYLIST_ASN_URLS` | | global | no | List of URLs, separated with spaces, containing ASN to put into the greylist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
| `GREYLIST_USER_AGENT_URLS` | | global | no | List of URLs, separated with spaces, containing good User-Agent to put into the greylist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
| `GREYLIST_URI_URLS` | | global | no | List of URLs, separated with spaces, containing bad URI to put into the greylist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
|
||||
When using stream mode, only IP, RDNS and ASN checks will be done.
|
||||
|
||||
|
|
@ -410,20 +406,20 @@ STREAM support :warning:
|
|||
|
||||
You can use the following settings to set up whitelisting :
|
||||
|
||||
| Setting | Default | Context | Multiple | Description |
|
||||
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | -------- | ---------------------------------------------------------------------------------- |
|
||||
| `USE_WHITELIST` | `yes` | multisite | no | Activate whitelist feature. |
|
||||
| `WHITELIST_IP` | `20.191.45.212 40.88.21.235 40.76.173.151 40.76.163.7 20.185.79.47 52.142.26.175 20.185.79.15 52.142.24.149 40.76.162.208 40.76.163.23 40.76.162.191 40.76.162.247 54.208.102.37 107.21.1.8` | multisite | no | List of IP/network, separated with spaces, to put into the whitelist. |
|
||||
| `WHITELIST_IP_URLS` | | global | no | List of URLs, separated with spaces, containing good IP/network to whitelist. |
|
||||
| `WHITELIST_RDNS_GLOBAL` | `yes` | multisite | no | Only perform RDNS whitelist checks on global IP addresses. |
|
||||
| `WHITELIST_RDNS` | `.google.com .googlebot.com .yandex.ru .yandex.net .yandex.com .search.msn.com .baidu.com .baidu.jp .crawl.yahoo.net .fwd.linkedin.com .twitter.com .twttr.com .discord.com` | multisite | no | List of reverse DNS suffixes, separated with spaces, to whitelist. |
|
||||
| `WHITELIST_RDNS_URLS` | | global | no | List of URLs, separated with spaces, containing reverse DNS suffixes to whitelist. |
|
||||
| `WHITELIST_ASN` | `32934` | multisite | no | List of ASN numbers, separated with spaces, to whitelist. |
|
||||
| `WHITELIST_ASN_URLS` | | global | no | List of URLs, separated with spaces, containing ASN to whitelist. |
|
||||
| `WHITELIST_USER_AGENT` | | multisite | no | List of User-Agent (PCRE regex), separated with spaces, to whitelist. |
|
||||
| `WHITELIST_USER_AGENT_URLS` | | global | no | List of URLs, separated with spaces, containing good User-Agent to whitelist. |
|
||||
| `WHITELIST_URI` | | multisite | no | List of URI (PCRE regex), separated with spaces, to whitelist. |
|
||||
| `WHITELIST_URI_URLS` | | global | no | List of URLs, separated with spaces, containing bad URI to whitelist. |
|
||||
| Setting | Default | Context | Multiple | Description |
|
||||
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `USE_WHITELIST` | `yes` | multisite | no | Activate whitelist feature. |
|
||||
| `WHITELIST_IP` | `20.191.45.212 40.88.21.235 40.76.173.151 40.76.163.7 20.185.79.47 52.142.26.175 20.185.79.15 52.142.24.149 40.76.162.208 40.76.163.23 40.76.162.191 40.76.162.247 54.208.102.37 107.21.1.8` | multisite | no | List of IP/network, separated with spaces, to put into the whitelist. |
|
||||
| `WHITELIST_RDNS_GLOBAL` | `yes` | multisite | no | Only perform RDNS whitelist checks on global IP addresses. |
|
||||
| `WHITELIST_RDNS` | `.google.com .googlebot.com .yandex.ru .yandex.net .yandex.com .search.msn.com .baidu.com .baidu.jp .crawl.yahoo.net .fwd.linkedin.com .twitter.com .twttr.com .discord.com` | multisite | no | List of reverse DNS suffixes, separated with spaces, to whitelist. |
|
||||
| `WHITELIST_ASN` | `32934` | multisite | no | List of ASN numbers, separated with spaces, to whitelist. |
|
||||
| `WHITELIST_USER_AGENT` | | multisite | no | List of User-Agent (PCRE regex), separated with spaces, to whitelist. |
|
||||
| `WHITELIST_URI` | | multisite | no | List of URI (PCRE regex), separated with spaces, to whitelist. |
|
||||
| `WHITELIST_IP_URLS` | | global | no | List of URLs, separated with spaces, containing good IP/network to whitelist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
| `WHITELIST_RDNS_URLS` | | global | no | List of URLs, separated with spaces, containing reverse DNS suffixes to whitelist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
| `WHITELIST_ASN_URLS` | | global | no | List of URLs, separated with spaces, containing ASN to whitelist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
| `WHITELIST_USER_AGENT_URLS` | | global | no | List of URLs, separated with spaces, containing good User-Agent to whitelist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
| `WHITELIST_URI_URLS` | | global | no | List of URLs, separated with spaces, containing bad URI to whitelist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
|
||||
When using stream mode, only IP, RDNS and ASN checks will be done.
|
||||
|
||||
|
|
|
|||
120
docs/settings.md
120
docs/settings.md
|
|
@ -140,30 +140,30 @@ STREAM support :warning:
|
|||
|
||||
Deny access based on internal and external IP/network/rDNS/ASN blacklists.
|
||||
|
||||
| Setting | Default | Context |Multiple| Description |
|
||||
|----------------------------------|------------------------------------------------------------------------------------------------------------------------------|---------|--------|------------------------------------------------------------------------------------------------|
|
||||
|`USE_BLACKLIST` |`yes` |multisite|no |Activate blacklist feature. |
|
||||
|`BLACKLIST_IP` | |multisite|no |List of IP/network, separated with spaces, to block. |
|
||||
|`BLACKLIST_RDNS` |`.shodan.io .censys.io` |multisite|no |List of reverse DNS suffixes, separated with spaces, to block. |
|
||||
|`BLACKLIST_RDNS_GLOBAL` |`yes` |multisite|no |Only perform RDNS blacklist checks on global IP addresses. |
|
||||
|`BLACKLIST_ASN` | |multisite|no |List of ASN numbers, separated with spaces, to block. |
|
||||
|`BLACKLIST_USER_AGENT` | |multisite|no |List of User-Agent (PCRE regex), separated with spaces, to block. |
|
||||
|`BLACKLIST_URI` | |multisite|no |List of URI (PCRE regex), separated with spaces, to block. |
|
||||
|`BLACKLIST_IGNORE_IP` | |multisite|no |List of IP/network, separated with spaces, to ignore in the blacklist. |
|
||||
|`BLACKLIST_IGNORE_RDNS` | |multisite|no |List of reverse DNS suffixes, separated with spaces, to ignore in the blacklist. |
|
||||
|`BLACKLIST_IGNORE_ASN` | |multisite|no |List of ASN numbers, separated with spaces, to ignore in the blacklist. |
|
||||
|`BLACKLIST_IGNORE_USER_AGENT` | |multisite|no |List of User-Agent (PCRE regex), separated with spaces, to ignore in the blacklist. |
|
||||
|`BLACKLIST_IGNORE_URI` | |multisite|no |List of URI (PCRE regex), separated with spaces, to ignore in the blacklist. |
|
||||
|`BLACKLIST_IP_URLS` |`https://www.dan.me.uk/torlist/?exit` |global |no |List of URLs, separated with spaces, containing bad IP/network to block. |
|
||||
|`BLACKLIST_RDNS_URLS` | |global |no |List of URLs, separated with spaces, containing reverse DNS suffixes to block. |
|
||||
|`BLACKLIST_ASN_URLS` | |global |no |List of URLs, separated with spaces, containing ASN to block. |
|
||||
|`BLACKLIST_USER_AGENT_URLS` |`https://raw.githubusercontent.com/mitchellkrogza/nginx-ultimate-bad-bot-blocker/master/_generator_lists/bad-user-agents.list`|global |no |List of URLs, separated with spaces, containing bad User-Agent to block. |
|
||||
|`BLACKLIST_URI_URLS` | |global |no |List of URLs, separated with spaces, containing bad URI to block. |
|
||||
|`BLACKLIST_IGNORE_IP_URLS` | |global |no |List of URLs, separated with spaces, containing IP/network to ignore in the blacklist. |
|
||||
|`BLACKLIST_IGNORE_RDNS_URLS` | |global |no |List of URLs, separated with spaces, containing reverse DNS suffixes to ignore in the blacklist.|
|
||||
|`BLACKLIST_IGNORE_ASN_URLS` | |global |no |List of URLs, separated with spaces, containing ASN to ignore in the blacklist. |
|
||||
|`BLACKLIST_IGNORE_USER_AGENT_URLS`| |global |no |List of URLs, separated with spaces, containing User-Agent to ignore in the blacklist. |
|
||||
|`BLACKLIST_IGNORE_URI_URLS` | |global |no |List of URLs, separated with spaces, containing URI to ignore in the blacklist. |
|
||||
| Setting | Default | Context |Multiple| Description |
|
||||
|----------------------------------|------------------------------------------------------------------------------------------------------------------------------|---------|--------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
|`USE_BLACKLIST` |`yes` |multisite|no |Activate blacklist feature. |
|
||||
|`BLACKLIST_IP` | |multisite|no |List of IP/network, separated with spaces, to block. |
|
||||
|`BLACKLIST_RDNS` |`.shodan.io .censys.io` |multisite|no |List of reverse DNS suffixes, separated with spaces, to block. |
|
||||
|`BLACKLIST_RDNS_GLOBAL` |`yes` |multisite|no |Only perform RDNS blacklist checks on global IP addresses. |
|
||||
|`BLACKLIST_ASN` | |multisite|no |List of ASN numbers, separated with spaces, to block. |
|
||||
|`BLACKLIST_USER_AGENT` | |multisite|no |List of User-Agent (PCRE regex), separated with spaces, to block. |
|
||||
|`BLACKLIST_URI` | |multisite|no |List of URI (PCRE regex), separated with spaces, to block. |
|
||||
|`BLACKLIST_IGNORE_IP` | |multisite|no |List of IP/network, separated with spaces, to ignore in the blacklist. |
|
||||
|`BLACKLIST_IGNORE_RDNS` | |multisite|no |List of reverse DNS suffixes, separated with spaces, to ignore in the blacklist. |
|
||||
|`BLACKLIST_IGNORE_ASN` | |multisite|no |List of ASN numbers, separated with spaces, to ignore in the blacklist. |
|
||||
|`BLACKLIST_IGNORE_USER_AGENT` | |multisite|no |List of User-Agent (PCRE regex), separated with spaces, to ignore in the blacklist. |
|
||||
|`BLACKLIST_IGNORE_URI` | |multisite|no |List of URI (PCRE regex), separated with spaces, to ignore in the blacklist. |
|
||||
|`BLACKLIST_IP_URLS` |`https://www.dan.me.uk/torlist/?exit` |global |no |List of URLs, separated with spaces, containing bad IP/network to block. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
|`BLACKLIST_RDNS_URLS` | |global |no |List of URLs, separated with spaces, containing reverse DNS suffixes to block. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
|`BLACKLIST_ASN_URLS` | |global |no |List of URLs, separated with spaces, containing ASN to block. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
|`BLACKLIST_USER_AGENT_URLS` |`https://raw.githubusercontent.com/mitchellkrogza/nginx-ultimate-bad-bot-blocker/master/_generator_lists/bad-user-agents.list`|global |no |List of URLs, separated with spaces, containing bad User-Agent to block. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
|`BLACKLIST_URI_URLS` | |global |no |List of URLs, separated with spaces, containing bad URI to block. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
|`BLACKLIST_IGNORE_IP_URLS` | |global |no |List of URLs, separated with spaces, containing IP/network to ignore in the blacklist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
|`BLACKLIST_IGNORE_RDNS_URLS` | |global |no |List of URLs, separated with spaces, containing reverse DNS suffixes to ignore in the blacklist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme.|
|
||||
|`BLACKLIST_IGNORE_ASN_URLS` | |global |no |List of URLs, separated with spaces, containing ASN to ignore in the blacklist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
|`BLACKLIST_IGNORE_USER_AGENT_URLS`| |global |no |List of URLs, separated with spaces, containing User-Agent to ignore in the blacklist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
|`BLACKLIST_IGNORE_URI_URLS` | |global |no |List of URLs, separated with spaces, containing URI to ignore in the blacklist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
|
||||
## Brotli
|
||||
|
||||
|
|
@ -287,20 +287,20 @@ STREAM support :warning:
|
|||
|
||||
Allow access while keeping security features based on internal and external IP/network/rDNS/ASN greylists.
|
||||
|
||||
| Setting |Default| Context |Multiple| Description |
|
||||
|--------------------------|-------|---------|--------|----------------------------------------------------------------------------------------------|
|
||||
|`USE_GREYLIST` |`no` |multisite|no |Activate greylist feature. |
|
||||
|`GREYLIST_IP` | |multisite|no |List of IP/network, separated with spaces, to put into the greylist. |
|
||||
|`GREYLIST_RDNS` | |multisite|no |List of reverse DNS suffixes, separated with spaces, to put into the greylist. |
|
||||
|`GREYLIST_RDNS_GLOBAL` |`yes` |multisite|no |Only perform RDNS greylist checks on global IP addresses. |
|
||||
|`GREYLIST_ASN` | |multisite|no |List of ASN numbers, separated with spaces, to put into the greylist. |
|
||||
|`GREYLIST_USER_AGENT` | |multisite|no |List of User-Agent (PCRE regex), separated with spaces, to put into the greylist. |
|
||||
|`GREYLIST_URI` | |multisite|no |List of URI (PCRE regex), separated with spaces, to put into the greylist. |
|
||||
|`GREYLIST_IP_URLS` | |global |no |List of URLs, separated with spaces, containing good IP/network to put into the greylist. |
|
||||
|`GREYLIST_RDNS_URLS` | |global |no |List of URLs, separated with spaces, containing reverse DNS suffixes to put into the greylist.|
|
||||
|`GREYLIST_ASN_URLS` | |global |no |List of URLs, separated with spaces, containing ASN to put into the greylist. |
|
||||
|`GREYLIST_USER_AGENT_URLS`| |global |no |List of URLs, separated with spaces, containing good User-Agent to put into the greylist. |
|
||||
|`GREYLIST_URI_URLS` | |global |no |List of URLs, separated with spaces, containing bad URI to put into the greylist. |
|
||||
| Setting |Default| Context |Multiple| Description |
|
||||
|--------------------------|-------|---------|--------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
|`USE_GREYLIST` |`no` |multisite|no |Activate greylist feature. |
|
||||
|`GREYLIST_IP` | |multisite|no |List of IP/network, separated with spaces, to put into the greylist. |
|
||||
|`GREYLIST_RDNS` | |multisite|no |List of reverse DNS suffixes, separated with spaces, to put into the greylist. |
|
||||
|`GREYLIST_RDNS_GLOBAL` |`yes` |multisite|no |Only perform RDNS greylist checks on global IP addresses. |
|
||||
|`GREYLIST_ASN` | |multisite|no |List of ASN numbers, separated with spaces, to put into the greylist. |
|
||||
|`GREYLIST_USER_AGENT` | |multisite|no |List of User-Agent (PCRE regex), separated with spaces, to put into the greylist. |
|
||||
|`GREYLIST_URI` | |multisite|no |List of URI (PCRE regex), separated with spaces, to put into the greylist. |
|
||||
|`GREYLIST_IP_URLS` | |global |no |List of URLs, separated with spaces, containing good IP/network to put into the greylist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
|`GREYLIST_RDNS_URLS` | |global |no |List of URLs, separated with spaces, containing reverse DNS suffixes to put into the greylist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme.|
|
||||
|`GREYLIST_ASN_URLS` | |global |no |List of URLs, separated with spaces, containing ASN to put into the greylist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
|`GREYLIST_USER_AGENT_URLS`| |global |no |List of URLs, separated with spaces, containing good User-Agent to put into the greylist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
|`GREYLIST_URI_URLS` | |global |no |List of URLs, separated with spaces, containing bad URI to put into the greylist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
|
||||
## Gzip
|
||||
|
||||
|
|
@ -516,14 +516,14 @@ STREAM support :warning:
|
|||
|
||||
Get real IP of clients when BunkerWeb is behind a reverse proxy / load balancer.
|
||||
|
||||
| Setting | Default | Context |Multiple| Description |
|
||||
|--------------------|-----------------------------------------|---------|--------|--------------------------------------------------------------------------------------------------------|
|
||||
|`USE_REAL_IP` |`no` |multisite|no |Retrieve the real IP of client. |
|
||||
|`USE_PROXY_PROTOCOL`|`no` |multisite|no |Enable PROXY protocol communication. |
|
||||
|`REAL_IP_FROM` |`192.168.0.0/16 172.16.0.0/12 10.0.0.0/8`|multisite|no |List of trusted IPs / networks, separated with spaces, where proxied requests come from. |
|
||||
|`REAL_IP_HEADER` |`X-Forwarded-For` |multisite|no |HTTP header containing the real IP or special value proxy_protocol for PROXY protocol. |
|
||||
|`REAL_IP_RECURSIVE` |`yes` |multisite|no |Perform a recursive search in the header container IP address. |
|
||||
|`REAL_IP_FROM_URLS` | |global |no |List of URLs containing trusted IPs / networks, separated with spaces, where proxied requests come from.|
|
||||
| Setting | Default | Context |Multiple| Description |
|
||||
|--------------------|-----------------------------------------|---------|--------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
|`USE_REAL_IP` |`no` |multisite|no |Retrieve the real IP of client. |
|
||||
|`USE_PROXY_PROTOCOL`|`no` |multisite|no |Enable PROXY protocol communication. |
|
||||
|`REAL_IP_FROM` |`192.168.0.0/16 172.16.0.0/12 10.0.0.0/8`|multisite|no |List of trusted IPs / networks, separated with spaces, where proxied requests come from. |
|
||||
|`REAL_IP_HEADER` |`X-Forwarded-For` |multisite|no |HTTP header containing the real IP or special value proxy_protocol for PROXY protocol. |
|
||||
|`REAL_IP_RECURSIVE` |`yes` |multisite|no |Perform a recursive search in the header container IP address. |
|
||||
|`REAL_IP_FROM_URLS` | |global |no |List of URLs containing trusted IPs / networks, separated with spaces, where proxied requests come from. Also supports file:// URLs and and auth basic using http://user:pass@url scheme.|
|
||||
|
||||
## Redirect
|
||||
|
||||
|
|
@ -676,17 +676,17 @@ STREAM support :warning:
|
|||
|
||||
Allow access based on internal and external IP/network/rDNS/ASN whitelists.
|
||||
|
||||
| Setting | Default | Context |Multiple| Description |
|
||||
|---------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|--------|----------------------------------------------------------------------------------|
|
||||
|`USE_WHITELIST` |`yes` |multisite|no |Activate whitelist feature. |
|
||||
|`WHITELIST_IP` |`20.191.45.212 40.88.21.235 40.76.173.151 40.76.163.7 20.185.79.47 52.142.26.175 20.185.79.15 52.142.24.149 40.76.162.208 40.76.163.23 40.76.162.191 40.76.162.247` |multisite|no |List of IP/network, separated with spaces, to put into the whitelist. |
|
||||
|`WHITELIST_RDNS` |`.google.com .googlebot.com .yandex.ru .yandex.net .yandex.com .search.msn.com .baidu.com .baidu.jp .crawl.yahoo.net .fwd.linkedin.com .twitter.com .twttr.com .discord.com`|multisite|no |List of reverse DNS suffixes, separated with spaces, to whitelist. |
|
||||
|`WHITELIST_RDNS_GLOBAL` |`yes` |multisite|no |Only perform RDNS whitelist checks on global IP addresses. |
|
||||
|`WHITELIST_ASN` |`32934` |multisite|no |List of ASN numbers, separated with spaces, to whitelist. |
|
||||
|`WHITELIST_USER_AGENT` | |multisite|no |List of User-Agent (PCRE regex), separated with spaces, to whitelist. |
|
||||
|`WHITELIST_URI` | |multisite|no |List of URI (PCRE regex), separated with spaces, to whitelist. |
|
||||
|`WHITELIST_IP_URLS` | |global |no |List of URLs, separated with spaces, containing good IP/network to whitelist. |
|
||||
|`WHITELIST_RDNS_URLS` | |global |no |List of URLs, separated with spaces, containing reverse DNS suffixes to whitelist.|
|
||||
|`WHITELIST_ASN_URLS` | |global |no |List of URLs, separated with spaces, containing ASN to whitelist. |
|
||||
|`WHITELIST_USER_AGENT_URLS`| |global |no |List of URLs, separated with spaces, containing good User-Agent to whitelist. |
|
||||
|`WHITELIST_URI_URLS` | |global |no |List of URLs, separated with spaces, containing bad URI to whitelist. |
|
||||
| Setting | Default | Context |Multiple| Description |
|
||||
|---------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|--------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
|`USE_WHITELIST` |`yes` |multisite|no |Activate whitelist feature. |
|
||||
|`WHITELIST_IP` |`20.191.45.212 40.88.21.235 40.76.173.151 40.76.163.7 20.185.79.47 52.142.26.175 20.185.79.15 52.142.24.149 40.76.162.208 40.76.163.23 40.76.162.191 40.76.162.247` |multisite|no |List of IP/network, separated with spaces, to put into the whitelist. |
|
||||
|`WHITELIST_RDNS` |`.google.com .googlebot.com .yandex.ru .yandex.net .yandex.com .search.msn.com .baidu.com .baidu.jp .crawl.yahoo.net .fwd.linkedin.com .twitter.com .twttr.com .discord.com`|multisite|no |List of reverse DNS suffixes, separated with spaces, to whitelist. |
|
||||
|`WHITELIST_RDNS_GLOBAL` |`yes` |multisite|no |Only perform RDNS whitelist checks on global IP addresses. |
|
||||
|`WHITELIST_ASN` |`32934` |multisite|no |List of ASN numbers, separated with spaces, to whitelist. |
|
||||
|`WHITELIST_USER_AGENT` | |multisite|no |List of User-Agent (PCRE regex), separated with spaces, to whitelist. |
|
||||
|`WHITELIST_URI` | |multisite|no |List of URI (PCRE regex), separated with spaces, to whitelist. |
|
||||
|`WHITELIST_IP_URLS` | |global |no |List of URLs, separated with spaces, containing good IP/network to whitelist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
|`WHITELIST_RDNS_URLS` | |global |no |List of URLs, separated with spaces, containing reverse DNS suffixes to whitelist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme.|
|
||||
|`WHITELIST_ASN_URLS` | |global |no |List of URLs, separated with spaces, containing ASN to whitelist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
|`WHITELIST_USER_AGENT_URLS`| |global |no |List of URLs, separated with spaces, containing good User-Agent to whitelist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
|`WHITELIST_URI_URLS` | |global |no |List of URLs, separated with spaces, containing bad URI to whitelist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme. |
|
||||
|
|
|
|||
|
|
@ -239,27 +239,40 @@
|
|||
|
||||
=== "SQLite"
|
||||
|
||||
1. **Remove the existing database file.**
|
||||
1. **Stop the Stack.**
|
||||
|
||||
```bash
|
||||
docker compose down
|
||||
```
|
||||
|
||||
2. **Remove the existing database file.**
|
||||
|
||||
```bash
|
||||
docker exec -u 0 -i <scheduler_container> rm -f /var/lib/bunkerweb/db.sqlite3
|
||||
```
|
||||
|
||||
2. **Restore the backup.**
|
||||
3. **Restore the backup.**
|
||||
|
||||
```bash
|
||||
docker exec -i -T <scheduler_container> sqlite3 /var/lib/bunkerweb/db.sqlite3 < /path/to/backup/directory/backup.sql
|
||||
```
|
||||
|
||||
=== "MySQL/MariaDB"
|
||||
|
||||
3. **Stop the Scheduler container.**
|
||||
4. **Fix permissions.**
|
||||
|
||||
```bash
|
||||
docker compose down <scheduler_container>
|
||||
docker exec -u 0 -i <scheduler_container> chown root:nginx /var/lib/bunkerweb/db.sqlite3
|
||||
docker exec -u 0 -i <scheduler_container> chmod 770 /var/lib/bunkerweb/db.sqlite3
|
||||
```
|
||||
|
||||
4. **Restore the backup.**
|
||||
=== "MySQL/MariaDB"
|
||||
|
||||
5. **Stop the Stack.**
|
||||
|
||||
```bash
|
||||
docker compose down
|
||||
```
|
||||
|
||||
6. **Restore the backup.**
|
||||
|
||||
```bash
|
||||
docker exec -e MYSQL_PWD=<your_password> -i -T <database_container> mysql -u <username> <database_name> < /path/to/backup/directory/backup.sql
|
||||
|
|
@ -267,25 +280,25 @@
|
|||
|
||||
=== "PostgreSQL"
|
||||
|
||||
5. **Stop the Scheduler container.**
|
||||
7. **Stop the Stack.**
|
||||
|
||||
```bash
|
||||
docker compose down <scheduler_container>
|
||||
docker compose down
|
||||
```
|
||||
|
||||
6. **Remove the existing database.**
|
||||
8. **Remove the existing database.**
|
||||
|
||||
```bash
|
||||
docker exec -i <database_container> dropdb -U <username> --force <database_name>
|
||||
```
|
||||
|
||||
7. **Recreate the database.**
|
||||
9. **Recreate the database.**
|
||||
|
||||
```bash
|
||||
docker exec -i <database_container> createdb -U <username> <database_name>
|
||||
```
|
||||
|
||||
8. **Restore the backup.**
|
||||
10. **Restore the backup.**
|
||||
|
||||
```bash
|
||||
docker exec -i -T <database_container> psql -U <username> -d <database_name> < /path/to/backup/directory/backup.sql
|
||||
|
|
@ -309,10 +322,9 @@
|
|||
...
|
||||
```
|
||||
|
||||
3. **Restart the containers**.
|
||||
3. **Start the containers**.
|
||||
|
||||
```bash
|
||||
docker compose down
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
|
|
@ -321,8 +333,7 @@
|
|||
4. **Stop the services**.
|
||||
|
||||
```bash
|
||||
systemctl stop bunkerweb
|
||||
systemctl stop bunkerweb-ui
|
||||
systemctl stop bunkerweb bunkerweb-ui
|
||||
```
|
||||
|
||||
5. **Restore the backup**.
|
||||
|
|
@ -330,8 +341,10 @@
|
|||
=== "SQLite"
|
||||
|
||||
```bash
|
||||
rm -f /var/lib/bunkerweb/db.sqlite3
|
||||
sqlite3 /var/lib/bunkerweb/db.sqlite3 < /path/to/backup/directory/backup.sql
|
||||
sudo rm -f /var/lib/bunkerweb/db.sqlite3
|
||||
sudo sqlite3 /var/lib/bunkerweb/db.sqlite3 < /path/to/backup/directory/backup.sql
|
||||
sudo chown root:nginx /var/lib/bunkerweb/db.sqlite3
|
||||
sudo chmod 770 /var/lib/bunkerweb/db.sqlite3
|
||||
```
|
||||
|
||||
=== "MySQL/MariaDB"
|
||||
|
|
|
|||
|
|
@ -125,6 +125,7 @@ services:
|
|||
- "bunkerweb.REVERSE_PROXY_URL=/admin"
|
||||
- "bunkerweb.REVERSE_PROXY_HOST=http://bw-ui:7000"
|
||||
- "bunkerweb.INTERCEPTED_ERROR_CODES=400 404 405 413 429 500 501 502 503 504"
|
||||
- "bunkerweb.GENERATE_SELF_SIGNED_SSL=yes"
|
||||
- bunkerweb.CUSTOM_CONF_MODSEC_CRS_ip-host=SecRuleRemoveById 920350
|
||||
|
||||
bw-db:
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@ services:
|
|||
- "bunkerweb.REVERSE_PROXY_URL=/admin"
|
||||
- "bunkerweb.REVERSE_PROXY_HOST=http://bw-ui:7000"
|
||||
- "bunkerweb.INTERCEPTED_ERROR_CODES=400 404 405 413 429 500 501 502 503 504"
|
||||
- "bunkerweb.GENERATE_SELF_SIGNED_SSL=yes"
|
||||
|
||||
bw-db:
|
||||
image: mariadb:11
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ services:
|
|||
- www.example.com_REVERSE_PROXY_URL=/admin
|
||||
- www.example.com_REVERSE_PROXY_HOST=http://bw-ui:7000
|
||||
- www.example.com_INTERCEPTED_ERROR_CODES=400 404 405 413 429 500 501 502 503 504
|
||||
- www.example.com_GENERATE_SELF_SIGNED_SSL=yes
|
||||
- www.example.com_CUSTOM_CONF_MODSEC_CRS_ip-host=SecRuleRemoveById 920350
|
||||
- app1.example.com_USE_REVERSE_PROXY=yes
|
||||
- app1.example.com_REVERSE_PROXY_URL=/
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ services:
|
|||
- www.example.com_REVERSE_PROXY_URL=/admin
|
||||
- www.example.com_REVERSE_PROXY_HOST=http://bw-ui:7000
|
||||
- www.example.com_INTERCEPTED_ERROR_CODES=400 404 405 413 429 500 501 502 503 504
|
||||
- www.example.com_GENERATE_SELF_SIGNED_SSL=yes
|
||||
- app1.example.com_USE_REVERSE_PROXY=yes
|
||||
- app1.example.com_REVERSE_PROXY_URL=/
|
||||
- app1.example.com_REVERSE_PROXY_HOST=http://app1:8080
|
||||
|
|
|
|||
|
|
@ -17,3 +17,4 @@ www.example.com_USE_REVERSE_PROXY=yes
|
|||
www.example.com_REVERSE_PROXY_URL=/admin
|
||||
www.example.com_REVERSE_PROXY_HOST=http://127.0.0.1:7000
|
||||
www.example.com_INTERCEPTED_ERROR_CODES=400 404 405 413 429 500 501 502 503 504
|
||||
www.example.com_GENERATE_SELF_SIGNED_SSL=yes
|
||||
|
|
|
|||
|
|
@ -18,4 +18,5 @@ www.example.com_USE_REVERSE_PROXY=yes
|
|||
www.example.com_REVERSE_PROXY_URL=/admin
|
||||
www.example.com_REVERSE_PROXY_HOST=http://127.0.0.1:7000
|
||||
www.example.com_INTERCEPTED_ERROR_CODES=400 404 405 413 429 500 501 502 503 504
|
||||
www.example.com_GENERATE_SELF_SIGNED_SSL=yes
|
||||
EXTERNAL_PLUGIN_URLS=https://github.com/bunkerity/bunkerweb-plugins/archive/refs/heads/dev.zip
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.3-alpine3.19@sha256:ef097620baf1272e38264207003b0982285da3236a20ed829bf6bbf1e85fe3cb as builder
|
||||
FROM python:3.12.4-alpine3.19@sha256:ef3397d09070efd36583e83d2619cf8006158641e5b6b629d4d92a9778f5aa1c as builder
|
||||
|
||||
# Export var for specific actions on linux/arm/v7
|
||||
ARG TARGETPLATFORM
|
||||
|
|
@ -31,7 +31,7 @@ COPY src/common/helpers helpers
|
|||
COPY src/common/settings.json settings.json
|
||||
COPY src/common/utils utils
|
||||
|
||||
FROM python:3.12.3-alpine3.19@sha256:ef097620baf1272e38264207003b0982285da3236a20ed829bf6bbf1e85fe3cb
|
||||
FROM python:3.12.4-alpine3.19@sha256:ef3397d09070efd36583e83d2619cf8006158641e5b6b629d4d92a9778f5aa1c
|
||||
|
||||
# Set default umask to prevent huge recursive chmod increasing the final image size
|
||||
RUN umask 027
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@ ssl_dhparam /etc/nginx/dhparam;
|
|||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
|
||||
{% endif %}
|
||||
|
||||
listen 0.0.0.0:{{ LISTEN_STREAM_PORT_SSL }} ssl {% if USE_UDP == "yes" %} udp {% endif %}{% if USE_PROXY_PROTOCOL == "yes" %} proxy_protocol {% endif %};
|
||||
listen 0.0.0.0:{{ LISTEN_STREAM_PORT_SSL }} ssl {% if USE_PROXY_PROTOCOL == "yes" %} proxy_protocol {% endif %};
|
||||
{% if USE_IPV6 == "yes" +%}
|
||||
listen [::]:{{ LISTEN_STREAM_PORT_SSL }} ssl {% if USE_UDP == "yes" %} udp {% endif %}{% if USE_PROXY_PROTOCOL == "yes" %} proxy_protocol {% endif %};
|
||||
listen [::]:{{ LISTEN_STREAM_PORT_SSL }} ssl {% if USE_PROXY_PROTOCOL == "yes" %} proxy_protocol {% endif %};
|
||||
{% endif %}
|
||||
|
||||
ssl_certificate_by_lua_block {
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@
|
|||
"BLACKLIST_IP_URLS": {
|
||||
"context": "global",
|
||||
"default": "https://www.dan.me.uk/torlist/?exit",
|
||||
"help": "List of URLs, separated with spaces, containing bad IP/network to block.",
|
||||
"help": "List of URLs, separated with spaces, containing bad IP/network to block. Also supports file:// URLs and and auth basic using http://user:pass@url scheme.",
|
||||
"id": "blacklist-ip-urls",
|
||||
"label": "Blacklist IP/network URLs",
|
||||
"regex": "^( *((https?:\\/\\/|file:\\/\\/\\/)[\\-\\w@:%.+~#=]+[\\-\\w\\(\\)!@:%+.~#?&\\/=$]*)(?!.*\\2(?!.)) *)*$",
|
||||
|
|
@ -125,7 +125,7 @@
|
|||
"BLACKLIST_RDNS_URLS": {
|
||||
"context": "global",
|
||||
"default": "",
|
||||
"help": "List of URLs, separated with spaces, containing reverse DNS suffixes to block.",
|
||||
"help": "List of URLs, separated with spaces, containing reverse DNS suffixes to block. Also supports file:// URLs and and auth basic using http://user:pass@url scheme.",
|
||||
"id": "blacklist-rdns-urls",
|
||||
"label": "Blacklist reverse DNS URLs",
|
||||
"regex": "^( *((https?:\\/\\/|file:\\/\\/\\/)[\\-\\w@:%.+~#=]+[\\-\\w\\(\\)!@:%+.~#?&\\/=$]*)(?!.*\\2(?!.)) *)*$",
|
||||
|
|
@ -134,7 +134,7 @@
|
|||
"BLACKLIST_ASN_URLS": {
|
||||
"context": "global",
|
||||
"default": "",
|
||||
"help": "List of URLs, separated with spaces, containing ASN to block.",
|
||||
"help": "List of URLs, separated with spaces, containing ASN to block. Also supports file:// URLs and and auth basic using http://user:pass@url scheme.",
|
||||
"id": "blacklist-asn-urls",
|
||||
"label": "Blacklist ASN URLs",
|
||||
"regex": "^( *((https?:\\/\\/|file:\\/\\/\\/)[\\-\\w@:%.+~#=]+[\\-\\w\\(\\)!@:%+.~#?&\\/=$]*)(?!.*\\2(?!.)) *)*$",
|
||||
|
|
@ -143,7 +143,7 @@
|
|||
"BLACKLIST_USER_AGENT_URLS": {
|
||||
"context": "global",
|
||||
"default": "https://raw.githubusercontent.com/mitchellkrogza/nginx-ultimate-bad-bot-blocker/master/_generator_lists/bad-user-agents.list",
|
||||
"help": "List of URLs, separated with spaces, containing bad User-Agent to block.",
|
||||
"help": "List of URLs, separated with spaces, containing bad User-Agent to block. Also supports file:// URLs and and auth basic using http://user:pass@url scheme.",
|
||||
"id": "blacklist-user-agent-urls",
|
||||
"label": "Blacklist User-Agent URLs",
|
||||
"regex": "^( *((https?:\\/\\/|file:\\/\\/\\/)[\\-\\w@:%.+~#=]+[\\-\\w\\(\\)!@:%+.~#?&\\/=$]*)(?!.*\\2(?!.)) *)*$",
|
||||
|
|
@ -152,7 +152,7 @@
|
|||
"BLACKLIST_URI_URLS": {
|
||||
"context": "global",
|
||||
"default": "",
|
||||
"help": "List of URLs, separated with spaces, containing bad URI to block.",
|
||||
"help": "List of URLs, separated with spaces, containing bad URI to block. Also supports file:// URLs and and auth basic using http://user:pass@url scheme.",
|
||||
"id": "blacklist-uri-urls",
|
||||
"label": "Blacklist URI URLs",
|
||||
"regex": "^( *((https?:\\/\\/|file:\\/\\/\\/)[\\-\\w@:%.+~#=]+[\\-\\w\\(\\)!@:%+.~#?&\\/=$]*)(?!.*\\2(?!.)) *)*$",
|
||||
|
|
@ -161,7 +161,7 @@
|
|||
"BLACKLIST_IGNORE_IP_URLS": {
|
||||
"context": "global",
|
||||
"default": "",
|
||||
"help": "List of URLs, separated with spaces, containing IP/network to ignore in the blacklist.",
|
||||
"help": "List of URLs, separated with spaces, containing IP/network to ignore in the blacklist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme.",
|
||||
"id": "blacklist-ignore-ip-urls",
|
||||
"label": "Blacklist ignore IP/network URLs",
|
||||
"regex": "^( *((https?:\\/\\/|file:\\/\\/\\/)[\\-\\w@:%.+~#=]+[\\-\\w\\(\\)!@:%+.~#?&\\/=$]*)(?!.*\\2(?!.)) *)*$",
|
||||
|
|
@ -170,7 +170,7 @@
|
|||
"BLACKLIST_IGNORE_RDNS_URLS": {
|
||||
"context": "global",
|
||||
"default": "",
|
||||
"help": "List of URLs, separated with spaces, containing reverse DNS suffixes to ignore in the blacklist.",
|
||||
"help": "List of URLs, separated with spaces, containing reverse DNS suffixes to ignore in the blacklist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme.",
|
||||
"id": "blacklist-ignore-rdns-urls",
|
||||
"label": "Blacklist ignore reverse DNS URLs",
|
||||
"regex": "^( *((https?:\\/\\/|file:\\/\\/\\/)[\\-\\w@:%.+~#=]+[\\-\\w\\(\\)!@:%+.~#?&\\/=$]*)(?!.*\\2(?!.)) *)*$",
|
||||
|
|
@ -179,7 +179,7 @@
|
|||
"BLACKLIST_IGNORE_ASN_URLS": {
|
||||
"context": "global",
|
||||
"default": "",
|
||||
"help": "List of URLs, separated with spaces, containing ASN to ignore in the blacklist.",
|
||||
"help": "List of URLs, separated with spaces, containing ASN to ignore in the blacklist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme.",
|
||||
"id": "blacklist-ignore-asn-urls",
|
||||
"label": "Blacklist ignore ASN URLs",
|
||||
"regex": "^( *((https?:\\/\\/|file:\\/\\/\\/)[\\-\\w@:%.+~#=]+[\\-\\w\\(\\)!@:%+.~#?&\\/=$]*)(?!.*\\2(?!.)) *)*$",
|
||||
|
|
@ -188,7 +188,7 @@
|
|||
"BLACKLIST_IGNORE_USER_AGENT_URLS": {
|
||||
"context": "global",
|
||||
"default": "",
|
||||
"help": "List of URLs, separated with spaces, containing User-Agent to ignore in the blacklist.",
|
||||
"help": "List of URLs, separated with spaces, containing User-Agent to ignore in the blacklist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme.",
|
||||
"id": "blacklist-ignore-user-agent-urls",
|
||||
"label": "Blacklist ignore User-Agent URLs",
|
||||
"regex": "^( *((https?:\\/\\/|file:\\/\\/\\/)[\\-\\w@:%.+~#=]+[\\-\\w\\(\\)!@:%+.~#?&\\/=$]*)(?!.*\\2(?!.)) *)*$",
|
||||
|
|
@ -197,7 +197,7 @@
|
|||
"BLACKLIST_IGNORE_URI_URLS": {
|
||||
"context": "global",
|
||||
"default": "",
|
||||
"help": "List of URLs, separated with spaces, containing URI to ignore in the blacklist.",
|
||||
"help": "List of URLs, separated with spaces, containing URI to ignore in the blacklist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme.",
|
||||
"id": "blacklist-ignore-uri-urls",
|
||||
"label": "Blacklist ignore URI URLs",
|
||||
"regex": "^( *((https?:\\/\\/|file:\\/\\/\\/)[\\-\\w@:%.+~#=]+[\\-\\w\\(\\)!@:%+.~#?&\\/=$]*)(?!.*\\2(?!.)) *)*$",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from contextlib import suppress
|
||||
from os import getenv, sep
|
||||
from os.path import join
|
||||
from pathlib import Path
|
||||
|
|
@ -21,8 +20,8 @@ LOGGER = setup_logger("CUSTOM-CERT", getenv("LOG_LEVEL", "INFO"))
|
|||
JOB = Job(LOGGER)
|
||||
|
||||
|
||||
def check_cert(cert_file: Union[Path, bytes], key_file: Union[Path, bytes], first_server: str) -> Tuple[bool, str]:
|
||||
with suppress(BaseException):
|
||||
def check_cert(cert_file: Union[Path, bytes], key_file: Union[Path, bytes], first_server: str) -> Tuple[bool, Union[str, BaseException]]:
|
||||
try:
|
||||
ret = False
|
||||
if not cert_file or not key_file:
|
||||
return False, "Both variables CUSTOM_SSL_CERT and CUSTOM_SSL_KEY have to be set to use custom certificates"
|
||||
|
|
@ -54,7 +53,8 @@ def check_cert(cert_file: Union[Path, bytes], key_file: Union[Path, bytes], firs
|
|||
LOGGER.error(f"Error while caching custom-key key.pem file : {err}")
|
||||
|
||||
return ret, ""
|
||||
return False, "exception"
|
||||
except BaseException as e:
|
||||
return False, e
|
||||
|
||||
|
||||
status = 0
|
||||
|
|
@ -112,8 +112,8 @@ try:
|
|||
|
||||
LOGGER.info(f"Checking certificate for {first_server} ...")
|
||||
need_reload, err = check_cert(cert_file, key_file, first_server)
|
||||
if err == "exception":
|
||||
LOGGER.exception(f"Exception while checking {first_server}'s certificate, skipping ...")
|
||||
if isinstance(err, BaseException):
|
||||
LOGGER.error(f"Exception while checking {first_server}'s certificate, skipping ... \n{err}")
|
||||
skipped_servers.append(first_server)
|
||||
continue
|
||||
elif err:
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@
|
|||
"GREYLIST_IP_URLS": {
|
||||
"context": "global",
|
||||
"default": "",
|
||||
"help": "List of URLs, separated with spaces, containing good IP/network to put into the greylist.",
|
||||
"help": "List of URLs, separated with spaces, containing good IP/network to put into the greylist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme.",
|
||||
"id": "greylist-ip-urls",
|
||||
"label": "Greylist IP/network URLs",
|
||||
"regex": "^( *((https?:\\/\\/|file:\\/\\/\\/)[\\-\\w@:%.+~#=]+[\\-\\w\\(\\)!@:%+.~#?&\\/=$]*)(?!.*\\2(?!.)) *)*$",
|
||||
|
|
@ -80,7 +80,7 @@
|
|||
"GREYLIST_RDNS_URLS": {
|
||||
"context": "global",
|
||||
"default": "",
|
||||
"help": "List of URLs, separated with spaces, containing reverse DNS suffixes to put into the greylist.",
|
||||
"help": "List of URLs, separated with spaces, containing reverse DNS suffixes to put into the greylist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme.",
|
||||
"id": "greylist-rdns-urls",
|
||||
"label": "Greylist reverse DNS URLs",
|
||||
"regex": "^( *((https?:\\/\\/|file:\\/\\/\\/)[\\-\\w@:%.+~#=]+[\\-\\w\\(\\)!@:%+.~#?&\\/=$]*)(?!.*\\2(?!.)) *)*$",
|
||||
|
|
@ -89,7 +89,7 @@
|
|||
"GREYLIST_ASN_URLS": {
|
||||
"context": "global",
|
||||
"default": "",
|
||||
"help": "List of URLs, separated with spaces, containing ASN to put into the greylist.",
|
||||
"help": "List of URLs, separated with spaces, containing ASN to put into the greylist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme.",
|
||||
"id": "greylist-asn-urls",
|
||||
"label": "Greylist ASN URLs",
|
||||
"regex": "^( *((https?:\\/\\/|file:\\/\\/\\/)[\\-\\w@:%.+~#=]+[\\-\\w\\(\\)!@:%+.~#?&\\/=$]*)(?!.*\\2(?!.)) *)*$",
|
||||
|
|
@ -98,7 +98,7 @@
|
|||
"GREYLIST_USER_AGENT_URLS": {
|
||||
"context": "global",
|
||||
"default": "",
|
||||
"help": "List of URLs, separated with spaces, containing good User-Agent to put into the greylist.",
|
||||
"help": "List of URLs, separated with spaces, containing good User-Agent to put into the greylist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme.",
|
||||
"id": "greylist-user-agent-urls",
|
||||
"label": "Greylist User-Agent URLs",
|
||||
"regex": "^( *((https?:\\/\\/|file:\\/\\/\\/)[\\-\\w@:%.+~#=]+[\\-\\w\\(\\)!@:%+.~#?&\\/=$]*)(?!.*\\2(?!.)) *)*$",
|
||||
|
|
@ -107,7 +107,7 @@
|
|||
"GREYLIST_URI_URLS": {
|
||||
"context": "global",
|
||||
"default": "",
|
||||
"help": "List of URLs, separated with spaces, containing bad URI to put into the greylist.",
|
||||
"help": "List of URLs, separated with spaces, containing bad URI to put into the greylist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme.",
|
||||
"id": "greylist-uri-urls",
|
||||
"label": "Greylist URI URLs",
|
||||
"regex": "^( *((https?:\\/\\/|file:\\/\\/\\/)[\\-\\w@:%.+~#=]+[\\-\\w\\(\\)!@:%+.~#?&\\/=$]*)(?!.*\\2(?!.)) *)*$",
|
||||
|
|
|
|||
25
src/common/core/jobs/jobs/failover-backup.py
Normal file
25
src/common/core/jobs/jobs/failover-backup.py
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from os import getenv, sep
|
||||
from os.path import join
|
||||
from sys import exit as sys_exit, path as sys_path
|
||||
from traceback import format_exc
|
||||
|
||||
for deps_path in [join(sep, "usr", "share", "bunkerweb", *paths) for paths in (("deps", "python"), ("utils",), ("db",))]:
|
||||
if deps_path not in sys_path:
|
||||
sys_path.append(deps_path)
|
||||
|
||||
from jobs import Job # type: ignore
|
||||
from logger import setup_logger # type: ignore
|
||||
|
||||
LOGGER = setup_logger("FAILOVER-BACKUP", getenv("LOG_LEVEL", "INFO"))
|
||||
status = 0
|
||||
|
||||
try:
|
||||
# Restoring the backup failover configuration
|
||||
JOB = Job(LOGGER)
|
||||
except:
|
||||
status = 2
|
||||
LOGGER.error(f"Exception while running failover-backup.py :\n{format_exc()}")
|
||||
|
||||
sys_exit(status)
|
||||
|
|
@ -84,8 +84,8 @@ try:
|
|||
for chunk in resp.iter_content(chunk_size=4 * 1024):
|
||||
if chunk:
|
||||
file_content.write(chunk)
|
||||
except RequestException:
|
||||
LOGGER.error(f"Error while downloading mmdb file from {mmdb_url}")
|
||||
except RequestException as e:
|
||||
LOGGER.error(f"Error while downloading mmdb file from {mmdb_url}: {e}")
|
||||
sys_exit(2)
|
||||
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -84,8 +84,8 @@ try:
|
|||
for chunk in resp.iter_content(chunk_size=4 * 1024):
|
||||
if chunk:
|
||||
file_content.write(chunk)
|
||||
except RequestException:
|
||||
LOGGER.error(f"Error while downloading mmdb file from {mmdb_url}")
|
||||
except RequestException as e:
|
||||
LOGGER.error(f"Error while downloading mmdb file from {mmdb_url}: {e}")
|
||||
sys_exit(2)
|
||||
|
||||
try:
|
||||
|
|
|
|||
87
src/common/core/jobs/jobs/update-check.py
Normal file
87
src/common/core/jobs/jobs/update-check.py
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from os import getenv, sep
|
||||
from os.path import join
|
||||
from sys import exit as sys_exit, path as sys_path
|
||||
from traceback import format_exc
|
||||
|
||||
for deps_path in [join(sep, "usr", "share", "bunkerweb", *paths) for paths in (("deps", "python"), ("utils",))]:
|
||||
if deps_path not in sys_path:
|
||||
sys_path.append(deps_path)
|
||||
|
||||
from requests import get
|
||||
|
||||
from common_utils import get_version # type: ignore
|
||||
from logger import setup_logger # type: ignore
|
||||
|
||||
LOGGER = setup_logger("UPDATE-CHECK", getenv("LOG_LEVEL", "INFO"))
|
||||
status = 0
|
||||
|
||||
try:
|
||||
|
||||
def get_latest_stable_release():
|
||||
response = get("https://api.github.com/repos/bunkerity/bunkerweb/releases", headers={"User-Agent": "BunkerWeb"}, timeout=3)
|
||||
response.raise_for_status()
|
||||
releases = response.json()
|
||||
|
||||
for release in releases:
|
||||
if not release["prerelease"]:
|
||||
return release
|
||||
return None
|
||||
|
||||
latest_release = get_latest_stable_release()
|
||||
|
||||
if not latest_release:
|
||||
status = 1
|
||||
LOGGER.error("Failed to fetch latest release information")
|
||||
sys_exit(status)
|
||||
|
||||
current_version = get_version()
|
||||
latest_version = latest_release["tag_name"].removeprefix("v")
|
||||
|
||||
if current_version != latest_version:
|
||||
# Version details
|
||||
latest_version_text = f"\033[1;92m{latest_version}\033[0m"
|
||||
current_version_text = f"\033[1;93m{current_version}\033[0m"
|
||||
release_notes_url = f"https://github.com/bunkerity/bunkerweb/releases/v{latest_version}"
|
||||
release_notes_url_text = f"\033[4;94m{release_notes_url}\033[0m"
|
||||
|
||||
# Centering based on the longest line length
|
||||
alert_message = "🚨 A NEW VERSION OF BUNKERWEB IS AVAILABLE! 🚨"
|
||||
latest_version_line = f"Latest Version: {latest_version_text}"
|
||||
current_version_line = f"Current Version: {current_version_text}"
|
||||
release_notes_url_line = f"Release Notes: {release_notes_url_text}"
|
||||
|
||||
# Determine the longest line length
|
||||
longest_line_length = max(
|
||||
len(alert_message),
|
||||
len(latest_version_line),
|
||||
len(current_version_line),
|
||||
len(release_notes_url_line),
|
||||
)
|
||||
|
||||
# Centering the lines within the box width
|
||||
alert_message_padded = alert_message.center(longest_line_length - 13)
|
||||
latest_version_padded = latest_version_line.center(longest_line_length)
|
||||
current_version_padded = current_version_line.center(longest_line_length)
|
||||
LOGGER.warning(
|
||||
(
|
||||
f"\n\033[1;91m{'*' * (longest_line_length - 5)}\n"
|
||||
f"\033[1;91m*{' ' * (longest_line_length - 7)}*\n"
|
||||
f"\033[1;91m* \033[1;97m{alert_message_padded}\033[0m \033[0;91m*\n"
|
||||
f"\033[1;91m*{' ' * (longest_line_length - 7)}*\n"
|
||||
f"\033[1;91m* \033[1;97m{latest_version_padded}\033[0;91m *\n"
|
||||
f"\033[1;91m* \033[1;97m{current_version_padded}\033[0;91m *\n"
|
||||
f"\033[1;91m*{' ' * (longest_line_length - 7)}*\n"
|
||||
f"\033[1;91m* \033[1;97m{release_notes_url_line}\033[0;91m *\n"
|
||||
f"\033[1;91m*{' ' * (longest_line_length - 7)}*\n"
|
||||
f"\033[1;91m{'*' * (longest_line_length - 5)}\033[0m"
|
||||
)
|
||||
)
|
||||
else:
|
||||
LOGGER.info(f"Latest version is already installed: {current_version}")
|
||||
except:
|
||||
status = 2
|
||||
LOGGER.error(f"Exception while running update-check.py :\n{format_exc()}")
|
||||
|
||||
sys_exit(status)
|
||||
|
|
@ -17,6 +17,18 @@
|
|||
"file": "mmdb-asn.py",
|
||||
"every": "day",
|
||||
"reload": true
|
||||
},
|
||||
{
|
||||
"name": "update-check",
|
||||
"file": "update-check.py",
|
||||
"every": "day",
|
||||
"reload": false
|
||||
},
|
||||
{
|
||||
"name": "failover-backup",
|
||||
"file": "failover-backup.py",
|
||||
"every": "once",
|
||||
"reload": false
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ try:
|
|||
if key not in ("version", "integration", "database_version", "is_pro"):
|
||||
data.pop(key, None)
|
||||
|
||||
db_config = JOB.db.get_config(methods=True, with_drafts=True)
|
||||
db_config = JOB.db.get_non_default_settings(methods=True, with_drafts=True)
|
||||
services = db_config.get("SERVER_NAME", {"value": ""})["value"].split(" ")
|
||||
multisite = db_config.get("MULTISITE", {"value": "no"})["value"] == "yes"
|
||||
|
||||
|
|
@ -85,7 +85,7 @@ try:
|
|||
|
||||
data["non_default_settings"] = {}
|
||||
for setting, setting_data in db_config.items():
|
||||
if isinstance(setting_data, dict) and setting_data["method"] != "default":
|
||||
if isinstance(setting_data, dict):
|
||||
for server in services:
|
||||
if setting.startswith(server + "_"):
|
||||
setting = setting[len(server) + 1 :] # noqa: E203
|
||||
|
|
|
|||
|
|
@ -1,35 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from os import getenv, sep
|
||||
from os.path import basename, join
|
||||
from sys import exit as sys_exit, path as sys_path
|
||||
from traceback import format_exc
|
||||
|
||||
for deps_path in [join(sep, "usr", "share", "bunkerweb", *paths) for paths in (("deps", "python"), ("utils",))]:
|
||||
if deps_path not in sys_path:
|
||||
sys_path.append(deps_path)
|
||||
|
||||
from requests import get
|
||||
|
||||
from common_utils import get_version # type: ignore
|
||||
from logger import setup_logger # type: ignore
|
||||
|
||||
LOGGER = setup_logger("UPDATE-CHECK", getenv("LOG_LEVEL", "INFO"))
|
||||
status = 0
|
||||
|
||||
try:
|
||||
current_version = f"v{get_version().strip()}"
|
||||
|
||||
response = get("https://github.com/bunkerity/bunkerweb/releases/latest", headers={"User-Agent": "BunkerWeb"}, allow_redirects=True, timeout=10)
|
||||
response.raise_for_status()
|
||||
|
||||
latest_version = basename(response.url)
|
||||
if current_version != latest_version:
|
||||
LOGGER.warning(f"* \n* \n* 🚨 A new version of BunkerWeb is available: {latest_version} (current: {current_version}) 🚨\n* \n* ")
|
||||
else:
|
||||
LOGGER.info(f"Latest version is already installed: {current_version}")
|
||||
except:
|
||||
status = 2
|
||||
LOGGER.error(f"Exception while running update-check.py :\n{format_exc()}")
|
||||
|
||||
sys_exit(status)
|
||||
|
|
@ -203,12 +203,6 @@
|
|||
"every": "once",
|
||||
"reload": false
|
||||
},
|
||||
{
|
||||
"name": "update-check",
|
||||
"file": "update-check.py",
|
||||
"every": "day",
|
||||
"reload": false
|
||||
},
|
||||
{
|
||||
"name": "anonymous-report",
|
||||
"file": "anonymous-report.py",
|
||||
|
|
|
|||
|
|
@ -96,7 +96,6 @@ def install_plugin(plugin_path: Path, db, preview: bool = True) -> bool:
|
|||
try:
|
||||
db = Database(LOGGER, sqlalchemy_string=getenv("DATABASE_URI"))
|
||||
db_metadata = db.get_metadata()
|
||||
db_config = db.get_config()
|
||||
current_date = datetime.now()
|
||||
pro_license_key = getenv("PRO_LICENSE_KEY", "").strip()
|
||||
|
||||
|
|
@ -111,6 +110,7 @@ try:
|
|||
headers = {"User-Agent": f"BunkerWeb/{data['version']}"}
|
||||
default_metadata = {
|
||||
"is_pro": False,
|
||||
"pro_license": pro_license_key,
|
||||
"pro_expire": None,
|
||||
"pro_status": "invalid",
|
||||
"pro_overlapped": False,
|
||||
|
|
@ -158,7 +158,7 @@ try:
|
|||
|
||||
# ? If we already checked today, skip the check and if the metadata is the same, skip the check
|
||||
if (
|
||||
pro_license_key == db_config["PRO_LICENSE_KEY"]
|
||||
pro_license_key == db_metadata.get("pro_license", "")
|
||||
and metadata.get("is_pro", False) == db_metadata["is_pro"]
|
||||
and db_metadata["last_pro_check"]
|
||||
and current_date.replace(hour=0, minute=0, second=0, microsecond=0) == db_metadata["last_pro_check"].replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@
|
|||
"REAL_IP_FROM_URLS": {
|
||||
"context": "global",
|
||||
"default": "",
|
||||
"help": "List of URLs containing trusted IPs / networks, separated with spaces, where proxied requests come from.",
|
||||
"help": "List of URLs containing trusted IPs / networks, separated with spaces, where proxied requests come from. Also supports file:// URLs and and auth basic using http://user:pass@url scheme.",
|
||||
"id": "real-ip-from-urls",
|
||||
"label": "Real IP from URLs",
|
||||
"regex": "^( *((https?:\\/\\/|file:\\/\\/\\/)[\\-\\w@:%.+~#=]+[\\-\\w\\(\\)!@:%+.~#?&\\/=$]*)(?!.*\\2(?!.)) *)*$",
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@
|
|||
"WHITELIST_IP_URLS": {
|
||||
"context": "global",
|
||||
"default": "",
|
||||
"help": "List of URLs, separated with spaces, containing good IP/network to whitelist.",
|
||||
"help": "List of URLs, separated with spaces, containing good IP/network to whitelist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme.",
|
||||
"id": "whitelist-ip-urls",
|
||||
"label": "Whitelist IP/network URLs",
|
||||
"regex": "^( *((https?:\\/\\/|file:\\/\\/\\/)[\\-\\w@:%.+~#=]+[\\-\\w\\(\\)!@:%+.~#?&\\/=$]*)(?!.*\\2(?!.)) *)*$",
|
||||
|
|
@ -80,7 +80,7 @@
|
|||
"WHITELIST_RDNS_URLS": {
|
||||
"context": "global",
|
||||
"default": "",
|
||||
"help": "List of URLs, separated with spaces, containing reverse DNS suffixes to whitelist.",
|
||||
"help": "List of URLs, separated with spaces, containing reverse DNS suffixes to whitelist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme.",
|
||||
"id": "whitelist-rdns-urls",
|
||||
"label": "Whitelist reverse DNS URLs",
|
||||
"regex": "^( *((https?:\\/\\/|file:\\/\\/\\/)[\\-\\w@:%.+~#=]+[\\-\\w\\(\\)!@:%+.~#?&\\/=$]*)(?!.*\\2(?!.)) *)*$",
|
||||
|
|
@ -89,7 +89,7 @@
|
|||
"WHITELIST_ASN_URLS": {
|
||||
"context": "global",
|
||||
"default": "",
|
||||
"help": "List of URLs, separated with spaces, containing ASN to whitelist.",
|
||||
"help": "List of URLs, separated with spaces, containing ASN to whitelist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme.",
|
||||
"id": "whitelist-asn-urls",
|
||||
"label": "Whitelist ASN URLs",
|
||||
"regex": "^( *((https?:\\/\\/|file:\\/\\/\\/)[\\-\\w@:%.+~#=]+[\\-\\w\\(\\)!@:%+.~#?&\\/=$]*)(?!.*\\2(?!.)) *)*$",
|
||||
|
|
@ -98,7 +98,7 @@
|
|||
"WHITELIST_USER_AGENT_URLS": {
|
||||
"context": "global",
|
||||
"default": "",
|
||||
"help": "List of URLs, separated with spaces, containing good User-Agent to whitelist.",
|
||||
"help": "List of URLs, separated with spaces, containing good User-Agent to whitelist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme.",
|
||||
"id": "whitelist-user-agent-urls",
|
||||
"label": "Whitelist User-Agent URLs",
|
||||
"regex": "^( *((https?:\\/\\/|file:\\/\\/\\/)[\\-\\w@:%.+~#=]+[\\-\\w\\(\\)!@:%+.~#?&\\/=$]*)(?!.*\\2(?!.)) *)*$",
|
||||
|
|
@ -107,7 +107,7 @@
|
|||
"WHITELIST_URI_URLS": {
|
||||
"context": "global",
|
||||
"default": "",
|
||||
"help": "List of URLs, separated with spaces, containing bad URI to whitelist.",
|
||||
"help": "List of URLs, separated with spaces, containing bad URI to whitelist. Also supports file:// URLs and and auth basic using http://user:pass@url scheme.",
|
||||
"id": "whitelist-uri-urls",
|
||||
"label": "Whitelist URI URLs",
|
||||
"regex": "^( *((https?:\\/\\/|file:\\/\\/\\/)[\\-\\w@:%.+~#=]+[\\-\\w\\(\\)!@:%+.~#?&\\/=$]*)(?!.*\\2(?!.)) *)*$",
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ from datetime import datetime
|
|||
from io import BytesIO
|
||||
from logging import Logger
|
||||
from os import _exit, getenv, listdir, sep
|
||||
from os.path import join
|
||||
from os.path import join as os_join
|
||||
from pathlib import Path
|
||||
from re import compile as re_compile
|
||||
from re import compile as re_compile, escape, search
|
||||
from sys import argv, path as sys_path
|
||||
from typing import Any, Dict, List, Literal, Optional, Set, Tuple, Union
|
||||
from time import sleep
|
||||
|
|
@ -33,14 +33,14 @@ from model import (
|
|||
Metadata,
|
||||
)
|
||||
|
||||
for deps_path in [join(sep, "usr", "share", "bunkerweb", *paths) for paths in (("deps", "python"), ("utils",))]:
|
||||
for deps_path in [os_join(sep, "usr", "share", "bunkerweb", *paths) for paths in (("deps", "python"), ("utils",))]:
|
||||
if deps_path not in sys_path:
|
||||
sys_path.append(deps_path)
|
||||
|
||||
from common_utils import bytes_hash # type: ignore
|
||||
|
||||
from pymysql import install_as_MySQLdb
|
||||
from sqlalchemy import create_engine, event, MetaData as sql_metadata, text, inspect
|
||||
from sqlalchemy import create_engine, event, MetaData as sql_metadata, join, select as db_select, text, inspect
|
||||
from sqlalchemy.engine import Engine
|
||||
from sqlalchemy.exc import (
|
||||
ArgumentError,
|
||||
|
|
@ -343,7 +343,7 @@ class Database:
|
|||
|
||||
return ""
|
||||
|
||||
def set_pro_metadata(self, data: Dict[Literal["is_pro", "pro_expire", "pro_status", "pro_overlapped", "pro_services"], Any] = {}) -> str:
|
||||
def set_pro_metadata(self, data: Dict[Literal["is_pro", "pro_license", "pro_expire", "pro_status", "pro_overlapped", "pro_services"], Any] = {}) -> str:
|
||||
"""Set the pro metadata values"""
|
||||
with self.__db_session() as session:
|
||||
if self.readonly:
|
||||
|
|
@ -396,10 +396,29 @@ class Database:
|
|||
try:
|
||||
if multisite:
|
||||
return session.query(Settings).filter_by(id=setting, context="multisite").first() is not None
|
||||
return session.query(Settings).filter_by(name=setting).first() is not None
|
||||
return session.query(Settings).filter_by(id=setting).first() is not None
|
||||
except (ProgrammingError, OperationalError):
|
||||
return False
|
||||
|
||||
def set_failover(self, value: bool = True) -> str:
|
||||
"""Set the failover value"""
|
||||
with self.__db_session() as session:
|
||||
if self.readonly:
|
||||
return "The database is read-only, the changes will not be saved"
|
||||
|
||||
try:
|
||||
metadata = session.query(Metadata).get(1)
|
||||
|
||||
if not metadata:
|
||||
return "The metadata are not set yet, try again"
|
||||
|
||||
metadata.failover = value
|
||||
session.commit()
|
||||
except BaseException as e:
|
||||
return str(e)
|
||||
|
||||
return ""
|
||||
|
||||
def initialize_db(self, version: str, integration: str = "Unknown") -> str:
|
||||
"""Initialize the database"""
|
||||
with self.__db_session() as session:
|
||||
|
|
@ -428,18 +447,20 @@ class Database:
|
|||
|
||||
return ""
|
||||
|
||||
def get_metadata(self) -> Dict[str, str]:
|
||||
def get_metadata(self) -> Dict[str, Any]:
|
||||
"""Get the metadata from the database"""
|
||||
data = {
|
||||
"version": "1.5.8",
|
||||
"integration": "unknown",
|
||||
"database_version": "Unknown",
|
||||
"is_pro": "no",
|
||||
"pro_license": "",
|
||||
"pro_expire": None,
|
||||
"pro_services": 0,
|
||||
"pro_overlapped": False,
|
||||
"pro_status": "invalid",
|
||||
"last_pro_check": None,
|
||||
"failover": False,
|
||||
"default": True,
|
||||
}
|
||||
with self.__db_session() as session:
|
||||
|
|
@ -454,11 +475,13 @@ class Database:
|
|||
Metadata.version,
|
||||
Metadata.integration,
|
||||
Metadata.is_pro,
|
||||
Metadata.pro_license,
|
||||
Metadata.pro_expire,
|
||||
Metadata.pro_services,
|
||||
Metadata.pro_overlapped,
|
||||
Metadata.pro_status,
|
||||
Metadata.last_pro_check,
|
||||
Metadata.failover,
|
||||
)
|
||||
.filter_by(id=1)
|
||||
.first()
|
||||
|
|
@ -469,11 +492,13 @@ class Database:
|
|||
"version": metadata.version,
|
||||
"integration": metadata.integration,
|
||||
"is_pro": metadata.is_pro,
|
||||
"pro_license": metadata.pro_license,
|
||||
"pro_expire": metadata.pro_expire,
|
||||
"pro_services": metadata.pro_services,
|
||||
"pro_overlapped": metadata.pro_overlapped,
|
||||
"pro_status": metadata.pro_status,
|
||||
"last_pro_check": metadata.last_pro_check,
|
||||
"failover": metadata.failover,
|
||||
"default": False,
|
||||
}
|
||||
)
|
||||
|
|
@ -1508,12 +1533,121 @@ class Database:
|
|||
|
||||
return message
|
||||
|
||||
def get_config(self, global_only: bool = False, methods: bool = False, with_drafts: bool = False) -> Dict[str, Any]:
|
||||
def get_non_default_settings(
|
||||
self,
|
||||
global_only: bool = False,
|
||||
methods: bool = False,
|
||||
with_drafts: bool = False,
|
||||
filtered_settings: Optional[Union[List[str], Set[str], Tuple[str]]] = None,
|
||||
*,
|
||||
original_config: Optional[Dict[str, Any]] = None,
|
||||
original_multisite: Optional[Set[str]] = None,
|
||||
) -> Dict[str, Any]:
|
||||
"""Get the config from the database"""
|
||||
filtered_settings = set(filtered_settings or [])
|
||||
|
||||
if filtered_settings and not global_only:
|
||||
filtered_settings.update(("SERVER_NAME", "MULTISITE"))
|
||||
|
||||
with self.__db_session() as session:
|
||||
config = original_config or {}
|
||||
multisite = original_multisite or set()
|
||||
|
||||
# Define the join operation
|
||||
j = join(Settings, Global_values, Settings.id == Global_values.setting_id)
|
||||
|
||||
# Define the select statement
|
||||
stmt = (
|
||||
db_select(Settings.id.label("setting_id"), Settings.context, Settings.multiple, Global_values.value, Global_values.suffix, Global_values.method)
|
||||
.select_from(j)
|
||||
.order_by(Settings.order)
|
||||
)
|
||||
|
||||
if filtered_settings:
|
||||
stmt = stmt.where(Settings.id.in_(filtered_settings))
|
||||
|
||||
# Execute the query and fetch all results
|
||||
results = session.execute(stmt).fetchall()
|
||||
|
||||
for global_value in results:
|
||||
setting_id = global_value.setting_id + (f"_{global_value.suffix}" if global_value.multiple and global_value.suffix > 0 else "")
|
||||
config[setting_id] = global_value.value if not methods else {"value": global_value.value, "global": True, "method": global_value.method}
|
||||
if global_value.context == "multisite":
|
||||
multisite.add(setting_id)
|
||||
|
||||
services = session.query(Services).with_entities(Services.id, Services.is_draft)
|
||||
|
||||
if not with_drafts:
|
||||
services = services.filter_by(is_draft=False)
|
||||
|
||||
servers = ""
|
||||
for service in services:
|
||||
if not global_only:
|
||||
config[f"{service.id}_IS_DRAFT"] = "yes" if service.is_draft else "no"
|
||||
if methods:
|
||||
config[f"{service.id}_IS_DRAFT"] = {"value": config[f"{service.id}_IS_DRAFT"], "global": False, "method": "default"}
|
||||
for key in multisite:
|
||||
config[f"{service.id}_{key}"] = config[key]
|
||||
servers += f"{service.id} "
|
||||
servers = servers.strip()
|
||||
|
||||
config["SERVER_NAME"] = servers if not methods else {"value": servers, "global": True, "method": "default"}
|
||||
|
||||
if not global_only and (config.get("MULTISITE", {"value": "no"})["value"] == "yes" if methods else config.get("MULTISITE", "no") == "yes"):
|
||||
# Define the join operation
|
||||
j = join(Services, Services_settings, Services.id == Services_settings.service_id)
|
||||
j = j.join(Settings, Settings.id == Services_settings.setting_id)
|
||||
|
||||
# Define the select statement
|
||||
stmt = (
|
||||
db_select(
|
||||
Services.id.label("service_id"),
|
||||
Settings.id.label("setting_id"),
|
||||
Settings.multiple,
|
||||
Services_settings.value,
|
||||
Services_settings.suffix,
|
||||
Services_settings.method,
|
||||
)
|
||||
.select_from(j)
|
||||
.order_by(Services.id, Settings.order)
|
||||
)
|
||||
|
||||
if not with_drafts:
|
||||
stmt = stmt.where(Services.is_draft == False) # noqa: E712
|
||||
|
||||
if filtered_settings:
|
||||
stmt = stmt.where(Settings.id.in_(filtered_settings))
|
||||
|
||||
# Execute the query and fetch all results
|
||||
results = session.execute(stmt).fetchall()
|
||||
|
||||
for result in results:
|
||||
value = result.value
|
||||
|
||||
if result.setting_id == "SERVER_NAME" and not search(r"^" + escape(result.service_id) + r"( |$)", value):
|
||||
split = set(value.split(" "))
|
||||
split.discard(result.service_id)
|
||||
value = result.service_id + " " + " ".join(split)
|
||||
|
||||
config[f"{result.service_id}_{result.setting_id}" + (f"_{result.suffix}" if result.multiple and result.suffix else "")] = (
|
||||
value if not methods else {"value": value, "global": False, "method": result.method}
|
||||
)
|
||||
|
||||
return config
|
||||
|
||||
def get_config(
|
||||
self,
|
||||
global_only: bool = False,
|
||||
methods: bool = False,
|
||||
with_drafts: bool = False,
|
||||
filtered_settings: Optional[Union[List[str], Set[str], Tuple[str]]] = None,
|
||||
) -> Dict[str, Any]:
|
||||
"""Get the config from the database"""
|
||||
with self.__db_session() as session:
|
||||
config = {}
|
||||
multisite = []
|
||||
for setting in (
|
||||
multisite = set()
|
||||
|
||||
query = (
|
||||
session.query(Settings)
|
||||
.with_entities(
|
||||
Settings.id,
|
||||
|
|
@ -1522,81 +1656,25 @@ class Database:
|
|||
Settings.multiple,
|
||||
)
|
||||
.order_by(Settings.order)
|
||||
):
|
||||
)
|
||||
|
||||
if filtered_settings:
|
||||
query = query.filter(Settings.id.in_(filtered_settings))
|
||||
|
||||
for setting in query:
|
||||
default = setting.default or ""
|
||||
config[setting.id] = default if not methods else {"value": default, "global": True, "method": "default"}
|
||||
|
||||
for global_value in (
|
||||
session.query(Global_values).with_entities(Global_values.value, Global_values.suffix, Global_values.method).filter_by(setting_id=setting.id)
|
||||
):
|
||||
config[setting.id + (f"_{global_value.suffix}" if setting.multiple and global_value.suffix > 0 else "")] = (
|
||||
global_value.value
|
||||
if not methods
|
||||
else {
|
||||
"value": global_value.value,
|
||||
"global": True,
|
||||
"method": global_value.method,
|
||||
}
|
||||
)
|
||||
|
||||
if setting.context == "multisite":
|
||||
multisite.append(setting.id)
|
||||
multisite.add(setting.id)
|
||||
|
||||
is_multisite = config.get("MULTISITE", {"value": "no"})["value"] == "yes" if methods else config.get("MULTISITE", "no") == "yes"
|
||||
|
||||
services = session.query(Services).with_entities(Services.id, Services.is_draft)
|
||||
if not with_drafts:
|
||||
services = services.filter_by(is_draft=False)
|
||||
|
||||
if not global_only and is_multisite:
|
||||
for service in services:
|
||||
config[f"{service.id}_IS_DRAFT"] = "yes" if service.is_draft else "no"
|
||||
if methods:
|
||||
config[f"{service.id}_IS_DRAFT"] = {"value": config[f"{service.id}_IS_DRAFT"], "global": False, "method": "default"}
|
||||
|
||||
checked_settings = []
|
||||
for key, value in config.copy().items():
|
||||
original_key = key
|
||||
if self.suffix_rx.search(key):
|
||||
key = key[: -len(str(key.split("_")[-1])) - 1]
|
||||
|
||||
if key not in multisite:
|
||||
continue
|
||||
elif f"{service.id}_{original_key}" not in config:
|
||||
config[f"{service.id}_{original_key}"] = value
|
||||
|
||||
if original_key not in checked_settings:
|
||||
checked_settings.append(original_key)
|
||||
else:
|
||||
continue
|
||||
|
||||
for service_setting in (
|
||||
session.query(Services_settings)
|
||||
.with_entities(
|
||||
Services_settings.value,
|
||||
Services_settings.suffix,
|
||||
Services_settings.method,
|
||||
)
|
||||
.filter_by(service_id=service.id, setting_id=key)
|
||||
):
|
||||
value = service_setting.value
|
||||
if key == "SERVER_NAME" and service.id not in value.split(" "):
|
||||
value = f"{service.id} {value}".strip()
|
||||
|
||||
config[f"{service.id}_{key}" + (f"_{service_setting.suffix}" if service_setting.suffix > 0 else "")] = (
|
||||
value
|
||||
if not methods
|
||||
else {
|
||||
"value": value,
|
||||
"global": False,
|
||||
"method": service_setting.method,
|
||||
}
|
||||
)
|
||||
|
||||
servers = " ".join(service.id for service in services)
|
||||
config["SERVER_NAME"] = servers if not methods else {"value": servers, "global": True, "method": "default"}
|
||||
|
||||
return config
|
||||
return self.get_non_default_settings(
|
||||
global_only=global_only,
|
||||
methods=methods,
|
||||
with_drafts=with_drafts,
|
||||
filtered_settings=filtered_settings,
|
||||
original_config=config,
|
||||
original_multisite=multisite,
|
||||
)
|
||||
|
||||
def get_custom_configs(self) -> List[Dict[str, Any]]:
|
||||
"""Get the custom configs from the database"""
|
||||
|
|
|
|||
|
|
@ -234,6 +234,7 @@ class Metadata(Base):
|
|||
id = Column(Integer, primary_key=True, default=1)
|
||||
is_initialized = Column(Boolean, nullable=False)
|
||||
is_pro = Column(Boolean, default=False, nullable=False)
|
||||
pro_license = Column(String(128), default="", nullable=True)
|
||||
pro_expire = Column(DateTime, nullable=True)
|
||||
pro_status = Column(PRO_STATUS_ENUM, default="invalid", nullable=False)
|
||||
pro_services = Column(Integer, default=0, nullable=False)
|
||||
|
|
@ -250,5 +251,6 @@ class Metadata(Base):
|
|||
last_pro_plugins_change = Column(DateTime, nullable=True)
|
||||
instances_changed = Column(Boolean, default=False, nullable=True)
|
||||
last_instances_change = Column(DateTime, nullable=True)
|
||||
failover = Column(Boolean, default=None, nullable=True)
|
||||
integration = Column(INTEGRATIONS_ENUM, default="Unknown", nullable=False)
|
||||
version = Column(String(32), default="1.5.8", nullable=False)
|
||||
|
|
|
|||
|
|
@ -222,9 +222,9 @@ sqlalchemy==2.0.30 \
|
|||
--hash=sha256:f7703c2010355dd28f53deb644a05fc30f796bd8598b43f0ba678878780b6e4c \
|
||||
--hash=sha256:fa561138a64f949f3e889eb9ab8c58e1504ab351d6cf55259dc4c248eaa19da6
|
||||
# via -r requirements.armv7.in
|
||||
typing-extensions==4.12.1 \
|
||||
--hash=sha256:6024b58b69089e5a89c347397254e35f1bf02a907728ec7fee9bf0fe837d203a \
|
||||
--hash=sha256:915f5e35ff76f56588223f15fdd5938f9a1cf9195c0de25130c627e4d597f6d1
|
||||
typing-extensions==4.12.2 \
|
||||
--hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \
|
||||
--hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8
|
||||
# via
|
||||
# psycopg
|
||||
# psycopg-pool
|
||||
|
|
|
|||
|
|
@ -284,9 +284,9 @@ sqlalchemy==2.0.30 \
|
|||
--hash=sha256:f7703c2010355dd28f53deb644a05fc30f796bd8598b43f0ba678878780b6e4c \
|
||||
--hash=sha256:fa561138a64f949f3e889eb9ab8c58e1504ab351d6cf55259dc4c248eaa19da6
|
||||
# via -r requirements.in
|
||||
typing-extensions==4.12.1 \
|
||||
--hash=sha256:6024b58b69089e5a89c347397254e35f1bf02a907728ec7fee9bf0fe837d203a \
|
||||
--hash=sha256:915f5e35ff76f56588223f15fdd5938f9a1cf9195c0de25130c627e4d597f6d1
|
||||
typing-extensions==4.12.2 \
|
||||
--hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \
|
||||
--hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8
|
||||
# via
|
||||
# psycopg
|
||||
# psycopg-pool
|
||||
|
|
|
|||
|
|
@ -2,4 +2,4 @@ docker==7.1.0
|
|||
jinja2==3.1.4
|
||||
kubernetes==30.1.0
|
||||
python-dotenv==1.0.1
|
||||
redis==5.0.5
|
||||
redis==5.0.6
|
||||
|
|
|
|||
|
|
@ -269,9 +269,9 @@ pyyaml==6.0.1 \
|
|||
--hash=sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d \
|
||||
--hash=sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f
|
||||
# via kubernetes
|
||||
redis==5.0.5 \
|
||||
--hash=sha256:30b47d4ebb6b7a0b9b40c1275a19b87bb6f46b3bed82a89012cf56dea4024ada \
|
||||
--hash=sha256:3417688621acf6ee368dec4a04dd95881be24efd34c79f00d31f62bb528800ae
|
||||
redis==5.0.6 \
|
||||
--hash=sha256:38473cd7c6389ad3e44a91f4c3eaf6bcb8a9f746007f29bf4fb20824ff0b2197 \
|
||||
--hash=sha256:c0d6d990850c627bbf7be01c5c4cbaadf67b48593e913bb71c9819c30df37eee
|
||||
# via -r requirements.in
|
||||
requests==2.32.3 \
|
||||
--hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 \
|
||||
|
|
|
|||
|
|
@ -71,15 +71,15 @@
|
|||
},
|
||||
{
|
||||
"id": "libmaxminddb",
|
||||
"name": "libmaxminddb v1.9.1",
|
||||
"name": "libmaxminddb v1.10.0",
|
||||
"url": "https://github.com/maxmind/libmaxminddb.git",
|
||||
"commit": "e26013e1d2b57eff0ed22b7364270358adb72205"
|
||||
"commit": "7acfe43a72a5043d01cc3dd6429005acdf812cb3"
|
||||
},
|
||||
{
|
||||
"id": "lua-cjson",
|
||||
"name": "lua-cjson v2.1.0.12",
|
||||
"name": "lua-cjson v2.1.0.14",
|
||||
"url": "https://github.com/openresty/lua-cjson.git",
|
||||
"commit": "881accc8fadca5ec02aa34d364df2a1aa25cd2f9"
|
||||
"commit": "f95cd9ea1e39221a36818772eb85f05b4164bbb1"
|
||||
},
|
||||
{
|
||||
"id": "lua-ffi-zlib",
|
||||
|
|
|
|||
|
|
@ -125,9 +125,9 @@ importlib-metadata==7.1.0 \
|
|||
--hash=sha256:30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570 \
|
||||
--hash=sha256:b78938b926ee8d5f020fc4772d487045805a55ddbad2ecf21c6d60938dc7fcd2
|
||||
# via build
|
||||
packaging==24.0 \
|
||||
--hash=sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5 \
|
||||
--hash=sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9
|
||||
packaging==24.1 \
|
||||
--hash=sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002 \
|
||||
--hash=sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124
|
||||
# via importlib-metadata
|
||||
|
||||
# The following packages are considered to be unsafe in a requirements file:
|
||||
|
|
|
|||
|
|
@ -16,9 +16,9 @@ importlib-metadata==7.1.0 \
|
|||
--hash=sha256:30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570 \
|
||||
--hash=sha256:b78938b926ee8d5f020fc4772d487045805a55ddbad2ecf21c6d60938dc7fcd2
|
||||
# via build
|
||||
packaging==24.0 \
|
||||
--hash=sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5 \
|
||||
--hash=sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9
|
||||
packaging==24.1 \
|
||||
--hash=sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002 \
|
||||
--hash=sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124
|
||||
# via importlib-metadata
|
||||
|
||||
# The following packages are considered to be unsafe in a requirements file:
|
||||
|
|
|
|||
43
src/deps/src/libmaxminddb/CMakeLists.txt
vendored
43
src/deps/src/libmaxminddb/CMakeLists.txt
vendored
|
|
@ -2,7 +2,7 @@ cmake_minimum_required (VERSION 3.9)
|
|||
|
||||
project(maxminddb
|
||||
LANGUAGES C
|
||||
VERSION 1.9.1
|
||||
VERSION 1.10.0
|
||||
)
|
||||
set(MAXMINDDB_SOVERSION 0.0.7)
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
|
|
@ -13,6 +13,8 @@ if (WIN32)
|
|||
endif()
|
||||
option(BUILD_SHARED_LIBS "Build shared libraries (.dll/.so) instead of static ones (.lib/.a)" OFF)
|
||||
option(BUILD_TESTING "Build test programs" ON)
|
||||
option(MAXMINDDB_BUILD_BINARIES "Build binaries" ON)
|
||||
option(MAXMINDDB_INSTALL "Generate the install target" ON)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
|
|
@ -90,17 +92,20 @@ set(MAXMINDB_HEADERS
|
|||
)
|
||||
set_target_properties(maxminddb PROPERTIES PUBLIC_HEADER "${MAXMINDB_HEADERS}")
|
||||
|
||||
install(TARGETS maxminddb
|
||||
EXPORT maxminddb)
|
||||
if (MAXMINDDB_INSTALL)
|
||||
install(TARGETS maxminddb
|
||||
EXPORT maxminddb)
|
||||
|
||||
# This is required to work with FetchContent
|
||||
install(EXPORT maxminddb
|
||||
FILE maxminddb-config.cmake
|
||||
NAMESPACE maxminddb::
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/maxminddb)
|
||||
# This is required to work with FetchContent
|
||||
install(EXPORT maxminddb
|
||||
FILE maxminddb-config.cmake
|
||||
NAMESPACE maxminddb::
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/maxminddb)
|
||||
endif()
|
||||
|
||||
# We always want to build mmdblookup
|
||||
add_subdirectory(bin)
|
||||
if (MAXMINDDB_BUILD_BINARIES)
|
||||
add_subdirectory(bin)
|
||||
endif()
|
||||
|
||||
if (BUILD_TESTING)
|
||||
enable_testing()
|
||||
|
|
@ -110,14 +115,16 @@ endif()
|
|||
# Generate libmaxminddb.pc file for pkg-config
|
||||
# Set the required variables as same with autotools
|
||||
set(prefix ${CMAKE_INSTALL_PREFIX})
|
||||
set(exec_prefix \${prefix})
|
||||
set(libdir \${exec_prefix}/lib)
|
||||
set(includedir \${prefix}/include)
|
||||
set(exec_prefix ${CMAKE_INSTALL_PREFIX})
|
||||
set(libdir ${CMAKE_INSTALL_LIBDIR})
|
||||
set(includedir ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
set(PACKAGE_VERSION ${maxminddb_VERSION})
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/libmaxminddb.pc.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/src/libmaxminddb.pc
|
||||
@ONLY)
|
||||
if (MAXMINDDB_INSTALL)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/libmaxminddb.pc.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/src/libmaxminddb.pc
|
||||
@ONLY)
|
||||
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/src/libmaxminddb.pc
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/src/libmaxminddb.pc
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||
endif()
|
||||
|
|
|
|||
14
src/deps/src/libmaxminddb/Changes.md
vendored
14
src/deps/src/libmaxminddb/Changes.md
vendored
|
|
@ -1,3 +1,15 @@
|
|||
## 1.10.0 - 2024-06-10
|
||||
|
||||
* When building with CMake, it is now possible to disable the building
|
||||
of binaries (e.g., `mmdblookup`) with the `MAXMINDDB_BUILD_BINARIES`
|
||||
option and the install target generation with the `MAXMINDDB_INSTALL`
|
||||
option. Pull request by Seena Fallah. GitHub #342.
|
||||
* CMake now makes greater use of GNUInstallDirs. Pull request by Maximilian
|
||||
Downey Twiss. GitHub #346.
|
||||
* The reader can now lookup records on a database with a search tree
|
||||
that is greater than 4 gigabytes without sometimes returning erroneous
|
||||
results due to an integer overflow.
|
||||
|
||||
## 1.9.1 - 2024-01-09
|
||||
|
||||
* `SSIZE_MAX` is now defined conditionally on Windows. The 1.9.0
|
||||
|
|
@ -230,7 +242,7 @@
|
|||
code to think it had found valid metadata when none existed. In addition,
|
||||
this could lead to an attempt to read past the end of the database
|
||||
entirely. Finally, if there are multiple metadata markers in the database,
|
||||
we treat the final one as the start of the metdata, instead of the first.
|
||||
we treat the final one as the start of the metadata, instead of the first.
|
||||
Implemented by Tobias Stoeckmann. GitHub #102.
|
||||
* Don't attempt to mmap a file that is too large to be mmapped on the
|
||||
system. Implemented by Tobias Stoeckmann. GitHub #101.
|
||||
|
|
|
|||
10
src/deps/src/libmaxminddb/bin/CMakeLists.txt
vendored
10
src/deps/src/libmaxminddb/bin/CMakeLists.txt
vendored
|
|
@ -15,8 +15,10 @@ if(NOT MSVC)
|
|||
|
||||
target_link_libraries(mmdblookup maxminddb pthread)
|
||||
|
||||
install(
|
||||
TARGETS mmdblookup
|
||||
DESTINATION bin
|
||||
)
|
||||
if (MAXMINDDB_INSTALL)
|
||||
install(
|
||||
TARGETS mmdblookup
|
||||
DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
|
|
|||
2
src/deps/src/libmaxminddb/configure.ac
vendored
2
src/deps/src/libmaxminddb/configure.ac
vendored
|
|
@ -2,7 +2,7 @@
|
|||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ([2.63])
|
||||
AC_INIT([libmaxminddb], [1.9.1], [support@maxmind.com])
|
||||
AC_INIT([libmaxminddb], [1.10.0], [support@maxmind.com])
|
||||
AC_CONFIG_SRCDIR([include/maxminddb.h])
|
||||
AC_CONFIG_HEADERS([config.h include/maxminddb_config.h])
|
||||
|
||||
|
|
|
|||
6
src/deps/src/libmaxminddb/doc/mmdblookup.md
vendored
6
src/deps/src/libmaxminddb/doc/mmdblookup.md
vendored
|
|
@ -9,8 +9,10 @@ mmdblookup --file [FILE PATH] --ip [IP ADDRESS] [DATA PATH]
|
|||
# DESCRIPTION
|
||||
|
||||
`mmdblookup` looks up an IP address in the specified MaxMind DB file. The
|
||||
record for the IP address is displayed in a JSON-like structure with type
|
||||
annotations.
|
||||
record for the IP address is displayed with `{}` to denote maps and `[]` to
|
||||
denote arrays. The values are followed by type annotations. This output is
|
||||
_not_ JSON and is not intended to be used as such. If you need JSON, please
|
||||
see [`mmdbinspect`](https://github.com/maxmind/mmdbinspect).
|
||||
|
||||
If an IP's data entry resolves to a map or array, you can provide a lookup
|
||||
path to only show part of that data.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#define MAXMINDDB_CONFIG_H
|
||||
|
||||
#ifndef MMDB_UINT128_USING_MODE
|
||||
/* Define as 1 if we use unsigned int __atribute__ ((__mode__(TI))) for uint128 values */
|
||||
/* Define as 1 if we use unsigned int __attribute__ ((__mode__(TI))) for uint128 values */
|
||||
#cmakedefine MMDB_UINT128_USING_MODE @MMDB_UINT128_USING_MODE@
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#define MAXMINDDB_CONFIG_H
|
||||
|
||||
#ifndef MMDB_UINT128_USING_MODE
|
||||
/* Define as 1 if we use unsigned int __atribute__ ((__mode__(TI))) for uint128 values */
|
||||
/* Define as 1 if we use unsigned int __attribute__ ((__mode__(TI))) for uint128 values */
|
||||
#define MMDB_UINT128_USING_MODE 0
|
||||
#endif
|
||||
|
||||
|
|
|
|||
3
src/deps/src/libmaxminddb/src/maxminddb.c
vendored
3
src/deps/src/libmaxminddb/src/maxminddb.c
vendored
|
|
@ -947,7 +947,7 @@ static int find_address_in_search_tree(const MMDB_s *const mmdb,
|
|||
return MMDB_UNKNOWN_DATABASE_FORMAT_ERROR;
|
||||
}
|
||||
|
||||
uint32_t value = 0;
|
||||
uint64_t value = 0;
|
||||
uint16_t current_bit = 0;
|
||||
if (mmdb->metadata.ip_version == 6 && address_family == AF_INET) {
|
||||
value = mmdb->ipv4_start_node.node_value;
|
||||
|
|
@ -961,6 +961,7 @@ static int find_address_in_search_tree(const MMDB_s *const mmdb,
|
|||
uint8_t bit =
|
||||
1U & (address[current_bit >> 3] >> (7 - (current_bit % 8)));
|
||||
|
||||
// Note that value*record_info.record_length can be larger than 2**32
|
||||
record_pointer = &search_tree[value * record_info.record_length];
|
||||
if (record_pointer + record_info.record_length > mmdb->data_section) {
|
||||
return MMDB_CORRUPT_SEARCH_TREE_ERROR;
|
||||
|
|
|
|||
2
src/deps/src/libmaxminddb/t/maxmind-db
vendored
2
src/deps/src/libmaxminddb/t/maxmind-db
vendored
|
|
@ -1 +1 @@
|
|||
Subproject commit 31a33b3c09ac53028216e82f3d8a6d33749a8df5
|
||||
Subproject commit 880f6b4b5eb6c12ea9d5c70dd201dec2cb5639a2
|
||||
6
src/deps/src/libmaxminddb/t/metadata_t.c
vendored
6
src/deps/src/libmaxminddb/t/metadata_t.c
vendored
|
|
@ -3,8 +3,8 @@
|
|||
void test_metadata(MMDB_s *mmdb, const char *mode_desc) {
|
||||
cmp_ok(mmdb->metadata.node_count,
|
||||
"==",
|
||||
37,
|
||||
"node_count is 37 - %s",
|
||||
163,
|
||||
"node_count is 163 - %s",
|
||||
mode_desc);
|
||||
cmp_ok(mmdb->metadata.record_size,
|
||||
"==",
|
||||
|
|
@ -197,7 +197,7 @@ void test_metadata_as_data_entry_list(MMDB_s *mmdb, const char *mode_desc) {
|
|||
if (strcmp(key_name, "node_count") == 0) {
|
||||
MMDB_entry_data_list_s *value = entry_data_list =
|
||||
entry_data_list->next;
|
||||
cmp_ok(value->entry_data.uint32, "==", 37, "node_count == 37");
|
||||
cmp_ok(value->entry_data.uint32, "==", 163, "node_count == 163");
|
||||
} else if (strcmp(key_name, "record_size") == 0) {
|
||||
MMDB_entry_data_list_s *value = entry_data_list =
|
||||
entry_data_list->next;
|
||||
|
|
|
|||
279
src/deps/src/libmaxminddb/t/read_node_t.c
vendored
279
src/deps/src/libmaxminddb/t/read_node_t.c
vendored
|
|
@ -74,50 +74,55 @@ void run_24_bit_record_tests(int mode, const char *mode_desc) {
|
|||
MMDB_s *mmdb = open_ok(path, mode, mode_desc);
|
||||
free(path);
|
||||
|
||||
const uint32_t tests[7][5] = {
|
||||
{0, 1, MMDB_RECORD_TYPE_SEARCH_NODE, 242, MMDB_RECORD_TYPE_EMPTY},
|
||||
{
|
||||
80,
|
||||
81,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
197,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
},
|
||||
{
|
||||
96,
|
||||
97,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
242,
|
||||
MMDB_RECORD_TYPE_EMPTY,
|
||||
},
|
||||
{
|
||||
103,
|
||||
242,
|
||||
MMDB_RECORD_TYPE_EMPTY,
|
||||
104,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
},
|
||||
{
|
||||
127,
|
||||
242,
|
||||
MMDB_RECORD_TYPE_EMPTY,
|
||||
315,
|
||||
MMDB_RECORD_TYPE_DATA,
|
||||
},
|
||||
{
|
||||
132,
|
||||
329,
|
||||
MMDB_RECORD_TYPE_DATA,
|
||||
242,
|
||||
MMDB_RECORD_TYPE_EMPTY,
|
||||
},
|
||||
{
|
||||
241,
|
||||
96,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
242,
|
||||
MMDB_RECORD_TYPE_EMPTY,
|
||||
}};
|
||||
const uint32_t tests[7][5] = {{
|
||||
0,
|
||||
1,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
435,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
},
|
||||
{
|
||||
80,
|
||||
81,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
323,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
},
|
||||
{
|
||||
96,
|
||||
97,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
148,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
},
|
||||
{
|
||||
103,
|
||||
444,
|
||||
MMDB_RECORD_TYPE_EMPTY,
|
||||
104,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
},
|
||||
{
|
||||
127,
|
||||
444,
|
||||
MMDB_RECORD_TYPE_EMPTY,
|
||||
514,
|
||||
MMDB_RECORD_TYPE_DATA,
|
||||
},
|
||||
{
|
||||
132,
|
||||
527,
|
||||
MMDB_RECORD_TYPE_DATA,
|
||||
444,
|
||||
MMDB_RECORD_TYPE_EMPTY,
|
||||
},
|
||||
{
|
||||
241,
|
||||
444,
|
||||
MMDB_RECORD_TYPE_EMPTY,
|
||||
242,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
}};
|
||||
run_read_node_tests(mmdb, tests, 7, 24);
|
||||
|
||||
MMDB_close(mmdb);
|
||||
|
|
@ -130,50 +135,55 @@ void run_28_bit_record_tests(int mode, const char *mode_desc) {
|
|||
MMDB_s *mmdb = open_ok(path, mode, mode_desc);
|
||||
free(path);
|
||||
|
||||
const uint32_t tests[7][5] = {
|
||||
{0, 1, MMDB_RECORD_TYPE_SEARCH_NODE, 242, MMDB_RECORD_TYPE_EMPTY},
|
||||
{
|
||||
80,
|
||||
81,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
197,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
},
|
||||
{
|
||||
96,
|
||||
97,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
242,
|
||||
MMDB_RECORD_TYPE_EMPTY,
|
||||
},
|
||||
{
|
||||
103,
|
||||
242,
|
||||
MMDB_RECORD_TYPE_EMPTY,
|
||||
104,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
},
|
||||
{
|
||||
127,
|
||||
242,
|
||||
MMDB_RECORD_TYPE_EMPTY,
|
||||
315,
|
||||
MMDB_RECORD_TYPE_DATA,
|
||||
},
|
||||
{
|
||||
132,
|
||||
329,
|
||||
MMDB_RECORD_TYPE_DATA,
|
||||
242,
|
||||
MMDB_RECORD_TYPE_EMPTY,
|
||||
},
|
||||
{
|
||||
241,
|
||||
96,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
242,
|
||||
MMDB_RECORD_TYPE_EMPTY,
|
||||
}};
|
||||
const uint32_t tests[7][5] = {{
|
||||
0,
|
||||
1,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
435,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
},
|
||||
{
|
||||
80,
|
||||
81,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
323,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
},
|
||||
{
|
||||
96,
|
||||
97,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
148,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
},
|
||||
{
|
||||
103,
|
||||
444,
|
||||
MMDB_RECORD_TYPE_EMPTY,
|
||||
104,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
},
|
||||
{
|
||||
127,
|
||||
444,
|
||||
MMDB_RECORD_TYPE_EMPTY,
|
||||
514,
|
||||
MMDB_RECORD_TYPE_DATA,
|
||||
},
|
||||
{
|
||||
132,
|
||||
527,
|
||||
MMDB_RECORD_TYPE_DATA,
|
||||
444,
|
||||
MMDB_RECORD_TYPE_EMPTY,
|
||||
},
|
||||
{
|
||||
241,
|
||||
444,
|
||||
MMDB_RECORD_TYPE_EMPTY,
|
||||
242,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
}};
|
||||
run_read_node_tests(mmdb, tests, 7, 28);
|
||||
|
||||
MMDB_close(mmdb);
|
||||
|
|
@ -186,50 +196,55 @@ void run_32_bit_record_tests(int mode, const char *mode_desc) {
|
|||
MMDB_s *mmdb = open_ok(path, mode, mode_desc);
|
||||
free(path);
|
||||
|
||||
const uint32_t tests[7][5] = {
|
||||
{0, 1, MMDB_RECORD_TYPE_SEARCH_NODE, 242, MMDB_RECORD_TYPE_EMPTY},
|
||||
{
|
||||
80,
|
||||
81,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
197,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
},
|
||||
{
|
||||
96,
|
||||
97,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
242,
|
||||
MMDB_RECORD_TYPE_EMPTY,
|
||||
},
|
||||
{
|
||||
103,
|
||||
242,
|
||||
MMDB_RECORD_TYPE_EMPTY,
|
||||
104,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
},
|
||||
{
|
||||
127,
|
||||
242,
|
||||
MMDB_RECORD_TYPE_EMPTY,
|
||||
315,
|
||||
MMDB_RECORD_TYPE_DATA,
|
||||
},
|
||||
{
|
||||
132,
|
||||
329,
|
||||
MMDB_RECORD_TYPE_DATA,
|
||||
242,
|
||||
MMDB_RECORD_TYPE_EMPTY,
|
||||
},
|
||||
{
|
||||
241,
|
||||
96,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
242,
|
||||
MMDB_RECORD_TYPE_EMPTY,
|
||||
}};
|
||||
const uint32_t tests[7][5] = {{
|
||||
0,
|
||||
1,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
435,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
},
|
||||
{
|
||||
80,
|
||||
81,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
323,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
},
|
||||
{
|
||||
96,
|
||||
97,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
148,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
},
|
||||
{
|
||||
103,
|
||||
444,
|
||||
MMDB_RECORD_TYPE_EMPTY,
|
||||
104,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
},
|
||||
{
|
||||
127,
|
||||
444,
|
||||
MMDB_RECORD_TYPE_EMPTY,
|
||||
514,
|
||||
MMDB_RECORD_TYPE_DATA,
|
||||
},
|
||||
{
|
||||
132,
|
||||
527,
|
||||
MMDB_RECORD_TYPE_DATA,
|
||||
444,
|
||||
MMDB_RECORD_TYPE_EMPTY,
|
||||
},
|
||||
{
|
||||
241,
|
||||
444,
|
||||
MMDB_RECORD_TYPE_EMPTY,
|
||||
242,
|
||||
MMDB_RECORD_TYPE_SEARCH_NODE,
|
||||
}};
|
||||
|
||||
run_read_node_tests(mmdb, tests, 7, 32);
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ jobs:
|
|||
runtestArgs: "LUA_INCLUDE_DIR=.lua/include/luajit-2.1"
|
||||
runtestEnv: "SKIP_CMAKE=1"
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
|
|
@ -47,7 +47,7 @@ jobs:
|
|||
sudo cpanm --notest Test::Base Test::LongString
|
||||
|
||||
- name: cppcheck
|
||||
run: cppcheck -i .lua/ -i .install/ -i dtoa.c --force --error-exitcode=1 --enable=warning .
|
||||
run: cppcheck -i .lua/ -i .install/ -i dtoa.c --force --error-exitcode=1 --enable=warning --inline-suppr .
|
||||
|
||||
- name: prove
|
||||
run: LUA_BIN=lua prove -Itests tests
|
||||
|
|
|
|||
1
src/deps/src/lua-cjson/.gitignore
vendored
1
src/deps/src/lua-cjson/.gitignore
vendored
|
|
@ -1,6 +1,7 @@
|
|||
*.html
|
||||
*.o
|
||||
*.so
|
||||
*.a
|
||||
notes
|
||||
packages
|
||||
tags
|
||||
|
|
|
|||
2
src/deps/src/lua-cjson/.travis.yml
vendored
2
src/deps/src/lua-cjson/.travis.yml
vendored
|
|
@ -27,7 +27,7 @@ env:
|
|||
- JOBS=3
|
||||
- LUAROCKS_VER=2.4.2
|
||||
matrix:
|
||||
#- LUA=1 LUA_DIR=/usr LUA_INCLUDE_DIR=$LUA_DIR/include/lua5.1
|
||||
#- LUA=1 LUA_DIR=/usr LUA_INCLUDE_DIR=$LUA_DIR/include/lua5.1
|
||||
- LUAJIT=1 LUA_DIR=/usr/local LUA_INCLUDE_DIR=$LUA_DIR/include/luajit-2.1 LUA_SUFFIX=--lua-suffix=jit
|
||||
|
||||
install:
|
||||
|
|
|
|||
7
src/deps/src/lua-cjson/CMakeLists.txt
vendored
7
src/deps/src/lua-cjson/CMakeLists.txt
vendored
|
|
@ -68,6 +68,13 @@ else()
|
|||
set(_lua_module_dir "${_lua_lib_dir}/lua/5.1")
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
add_definitions(-Dinline=__inline)
|
||||
add_definitions(-Dsnprintf=_snprintf)
|
||||
add_definitions(-Dstrncasecmp=_strnicmp)
|
||||
endif()
|
||||
|
||||
add_library(cjson MODULE lua_cjson.c strbuf.c ${FPCONV_SOURCES})
|
||||
set_target_properties(cjson PROPERTIES PREFIX "")
|
||||
target_link_libraries(cjson ${_MODULE_LINK})
|
||||
|
|
|
|||
8
src/deps/src/lua-cjson/Makefile
vendored
8
src/deps/src/lua-cjson/Makefile
vendored
|
|
@ -23,6 +23,8 @@ LUA_CMODULE_DIR ?= $(PREFIX)/lib/lua/$(LUA_VERSION)
|
|||
LUA_MODULE_DIR ?= $(PREFIX)/share/lua/$(LUA_VERSION)
|
||||
LUA_BIN_DIR ?= $(PREFIX)/bin
|
||||
|
||||
AR= $(CC) -o
|
||||
|
||||
##### Platform overrides #####
|
||||
##
|
||||
## Tweak one of the platform sections below to suit your situation.
|
||||
|
|
@ -84,12 +86,12 @@ OBJS = lua_cjson.o strbuf.o $(FPCONV_OBJS)
|
|||
|
||||
.PHONY: all clean install install-extra doc
|
||||
|
||||
.SUFFIXES: .html .txt
|
||||
.SUFFIXES: .html .adoc
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $(CPPFLAGS) $(BUILD_CFLAGS) -o $@ $<
|
||||
|
||||
.txt.html:
|
||||
.adoc.html:
|
||||
$(ASCIIDOC) -n -a toc $<
|
||||
|
||||
all: $(TARGET)
|
||||
|
|
@ -97,7 +99,7 @@ all: $(TARGET)
|
|||
doc: manual.html performance.html
|
||||
|
||||
$(TARGET): $(OBJS)
|
||||
$(CC) $(LDFLAGS) $(CJSON_LDFLAGS) -o $@ $(OBJS)
|
||||
$(AR) $@ $(LDFLAGS) $(CJSON_LDFLAGS) $(OBJS)
|
||||
|
||||
install: $(TARGET)
|
||||
mkdir -p $(DESTDIR)$(LUA_CMODULE_DIR)
|
||||
|
|
|
|||
2
src/deps/src/lua-cjson/build-packages.sh
vendored
2
src/deps/src/lua-cjson/build-packages.sh
vendored
|
|
@ -5,7 +5,7 @@
|
|||
# Build packages. Use current checked out version, or a specific tag/commit.
|
||||
|
||||
# Files requiring a version bump
|
||||
VERSION_FILES="lua-cjson-2.1devel-1.rockspec lua-cjson.spec lua_cjson.c manual.txt runtests.sh tests/test.lua"
|
||||
VERSION_FILES="lua-cjson-2.1devel-1.rockspec lua-cjson.spec lua_cjson.c manual.adoc runtests.sh tests/test.lua"
|
||||
|
||||
[ "$1" ] && BRANCH="$1" || BRANCH="`git describe --match '[1-3].[0-9]*'`"
|
||||
VERSION="`git describe --match '[1-3].[0-9]*' $BRANCH`"
|
||||
|
|
|
|||
115
src/deps/src/lua-cjson/dtoa.c
vendored
115
src/deps/src/lua-cjson/dtoa.c
vendored
|
|
@ -1,3 +1,7 @@
|
|||
/* The code comes from https://portal.ampl.com/~dmg/netlib/fp/dtoa.c
|
||||
* Go to https://portal.ampl.com/~dmg/netlib/fp/changes for the detailed changes.
|
||||
*/
|
||||
|
||||
/****************************************************************
|
||||
*
|
||||
* The author of this software is David M. Gay.
|
||||
|
|
@ -1533,12 +1537,18 @@ ThInfo {
|
|||
set_max_dtoa_threads(unsigned int n)
|
||||
{
|
||||
size_t L;
|
||||
ThInfo *newTI1;
|
||||
|
||||
if (n > maxthreads) {
|
||||
L = n*sizeof(ThInfo);
|
||||
if (TI1) {
|
||||
TI1 = (ThInfo*)REALLOC(TI1, L);
|
||||
memset(TI1 + maxthreads, 0, (n-maxthreads)*sizeof(ThInfo));
|
||||
newTI1 = (ThInfo*)REALLOC(TI1, L);
|
||||
if (newTI1) {
|
||||
TI1 = newTI1;
|
||||
memset(TI1 + maxthreads, 0, (n-maxthreads)*sizeof(ThInfo));
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
else {
|
||||
TI1 = (ThInfo*)MALLOC(L);
|
||||
|
|
@ -1871,7 +1881,7 @@ mult(Bigint *a, Bigint *b MTd)
|
|||
#else
|
||||
#ifdef Pack_32
|
||||
for(; xb < xbe; xb++, xc0++) {
|
||||
if (y = *xb & 0xffff) {
|
||||
if ((y = *xb & 0xffff)) {
|
||||
x = xa;
|
||||
xc = xc0;
|
||||
carry = 0;
|
||||
|
|
@ -1885,7 +1895,7 @@ mult(Bigint *a, Bigint *b MTd)
|
|||
while(x < xae);
|
||||
*xc = carry;
|
||||
}
|
||||
if (y = *xb >> 16) {
|
||||
if ((y = *xb >> 16)) {
|
||||
x = xa;
|
||||
xc = xc0;
|
||||
carry = 0;
|
||||
|
|
@ -2718,13 +2728,14 @@ enum { /* rounding values: same as FLT_ROUNDS */
|
|||
};
|
||||
|
||||
void
|
||||
gethex( const char **sp, U *rvp, int rounding, int sign MTd)
|
||||
gethex(const char **sp, U *rvp, int rounding, int sign MTd)
|
||||
{
|
||||
Bigint *b;
|
||||
char d;
|
||||
const unsigned char *decpt, *s0, *s, *s1;
|
||||
Long e, e1;
|
||||
ULong L, lostbits, *x;
|
||||
int big, denorm, esign, havedig, k, n, nbits, up, zret;
|
||||
int big, denorm, esign, havedig, k, n, nb, nbits, nz, up, zret;
|
||||
#ifdef IBM
|
||||
int j;
|
||||
#endif
|
||||
|
|
@ -2742,6 +2753,9 @@ gethex( const char **sp, U *rvp, int rounding, int sign MTd)
|
|||
#endif
|
||||
#endif /*}}*/
|
||||
};
|
||||
#ifdef IEEE_Arith
|
||||
int check_denorm = 0;
|
||||
#endif
|
||||
#ifdef USE_LOCALE
|
||||
int i;
|
||||
#ifdef NO_LOCALE_CACHE
|
||||
|
|
@ -2893,7 +2907,7 @@ gethex( const char **sp, U *rvp, int rounding, int sign MTd)
|
|||
k++;
|
||||
b = Balloc(k MTa);
|
||||
x = b->x;
|
||||
n = 0;
|
||||
havedig = n = nz = 0;
|
||||
L = 0;
|
||||
#ifdef USE_LOCALE
|
||||
for(i = 0; decimalpoint[i+1]; ++i);
|
||||
|
|
@ -2908,22 +2922,28 @@ gethex( const char **sp, U *rvp, int rounding, int sign MTd)
|
|||
if (*--s1 == '.')
|
||||
continue;
|
||||
#endif
|
||||
if ((d = hexdig[*s1]))
|
||||
havedig = 1;
|
||||
else if (!havedig) {
|
||||
e += 4;
|
||||
continue;
|
||||
}
|
||||
if (n == ULbits) {
|
||||
*x++ = L;
|
||||
L = 0;
|
||||
n = 0;
|
||||
}
|
||||
L |= (hexdig[*s1] & 0x0f) << n;
|
||||
L |= (d & 0x0f) << n;
|
||||
n += 4;
|
||||
}
|
||||
*x++ = L;
|
||||
b->wds = n = x - b->x;
|
||||
n = ULbits*n - hi0bits(L);
|
||||
nb = ULbits*n - hi0bits(L);
|
||||
nbits = Nbits;
|
||||
lostbits = 0;
|
||||
x = b->x;
|
||||
if (n > nbits) {
|
||||
n -= nbits;
|
||||
if (nb > nbits) {
|
||||
n = nb - nbits;
|
||||
if (any_on(b,n)) {
|
||||
lostbits = 1;
|
||||
k = n - 1;
|
||||
|
|
@ -2936,8 +2956,8 @@ gethex( const char **sp, U *rvp, int rounding, int sign MTd)
|
|||
rshift(b, n);
|
||||
e += n;
|
||||
}
|
||||
else if (n < nbits) {
|
||||
n = nbits - n;
|
||||
else if (nb < nbits) {
|
||||
n = nbits - nb;
|
||||
b = lshift(b, n MTa);
|
||||
e -= n;
|
||||
x = b->x;
|
||||
|
|
@ -2992,12 +3012,49 @@ gethex( const char **sp, U *rvp, int rounding, int sign MTd)
|
|||
return;
|
||||
}
|
||||
k = n - 1;
|
||||
#ifdef IEEE_Arith
|
||||
if (!k) {
|
||||
switch(rounding) {
|
||||
case Round_near:
|
||||
if (((b->x[0] & 3) == 3) || (lostbits && (b->x[0] & 1))) {
|
||||
multadd(b, 1, 1 MTa);
|
||||
emin_check:
|
||||
if (b->x[1] == (1 << (Exp_shift + 1))) {
|
||||
rshift(b,1);
|
||||
e = emin;
|
||||
goto normal;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Round_up:
|
||||
if (!sign && (lostbits || (b->x[0] & 1))) {
|
||||
incr_denorm:
|
||||
multadd(b, 1, 2 MTa);
|
||||
check_denorm = 1;
|
||||
lostbits = 0;
|
||||
goto emin_check;
|
||||
}
|
||||
break;
|
||||
case Round_down:
|
||||
if (sign && (lostbits || (b->x[0] & 1)))
|
||||
goto incr_denorm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (lostbits)
|
||||
lostbits = 1;
|
||||
else if (k > 0)
|
||||
lostbits = any_on(b,k);
|
||||
#ifdef IEEE_Arith
|
||||
else if (check_denorm)
|
||||
goto no_lostbits;
|
||||
#endif
|
||||
if (x[k>>kshift] & 1 << (k & kmask))
|
||||
lostbits |= 2;
|
||||
#ifdef IEEE_Arith
|
||||
no_lostbits:
|
||||
#endif
|
||||
nbits -= n;
|
||||
rshift(b,n);
|
||||
e = emin;
|
||||
|
|
@ -3022,16 +3079,9 @@ gethex( const char **sp, U *rvp, int rounding, int sign MTd)
|
|||
k = b->wds;
|
||||
b = increment(b MTa);
|
||||
x = b->x;
|
||||
if (denorm) {
|
||||
#if 0
|
||||
if (nbits == Nbits - 1
|
||||
&& x[nbits >> kshift] & 1 << (nbits & kmask))
|
||||
denorm = 0; /* not currently used */
|
||||
#endif
|
||||
}
|
||||
else if (b->wds > k
|
||||
if (!denorm && (b->wds > k
|
||||
|| ((n = nbits & kmask) !=0
|
||||
&& hi0bits(x[k-1]) < 32-n)) {
|
||||
&& hi0bits(x[k-1]) < 32-n))) {
|
||||
rshift(b,1);
|
||||
if (++e > Emax)
|
||||
goto ovfl;
|
||||
|
|
@ -3041,8 +3091,10 @@ gethex( const char **sp, U *rvp, int rounding, int sign MTd)
|
|||
#ifdef IEEE_Arith
|
||||
if (denorm)
|
||||
word0(rvp) = b->wds > 1 ? b->x[1] & ~0x100000 : 0;
|
||||
else
|
||||
else {
|
||||
normal:
|
||||
word0(rvp) = (b->x[1] & ~0x100000) | ((e + 0x3ff + 52) << 20);
|
||||
}
|
||||
word1(rvp) = b->x[0];
|
||||
#endif
|
||||
#ifdef IBM
|
||||
|
|
@ -3409,6 +3461,7 @@ retlow1:
|
|||
if ((j = ((word0(rv) & Exp_mask) >> Exp_shift) - bc->scale) <= 0) {
|
||||
i = 1 - j;
|
||||
if (i <= 31) {
|
||||
/* cppcheck-suppress integerOverflowCond */
|
||||
if (word1(rv) & (0x1 << i))
|
||||
goto odd;
|
||||
}
|
||||
|
|
@ -3619,10 +3672,11 @@ fpconv_strtod(const char *s00, char **se)
|
|||
c = *++s;
|
||||
if (c > '0' && c <= '9') {
|
||||
L = c - '0';
|
||||
s1 = s;
|
||||
while((c = *++s) >= '0' && c <= '9')
|
||||
L = 10*L + c - '0';
|
||||
if (s - s1 > 8 || L > 19999)
|
||||
while((c = *++s) >= '0' && c <= '9') {
|
||||
if (L <= 19999)
|
||||
L = 10*L + c - '0';
|
||||
}
|
||||
if (L > 19999)
|
||||
/* Avoid confusion from exponents
|
||||
* so large that e might overflow.
|
||||
*/
|
||||
|
|
@ -4884,6 +4938,7 @@ nrv_alloc(const char *s, char *s0, size_t s0len, char **rve, int n MTd)
|
|||
s0 = rv_alloc(n MTa);
|
||||
else if (s0len <= n) {
|
||||
rv = 0;
|
||||
/* cppcheck-suppress nullPointerArithmetic */
|
||||
t = rv + n;
|
||||
goto rve_chk;
|
||||
}
|
||||
|
|
@ -5237,9 +5292,11 @@ dtoa_r(double dd, int mode, int ndigits, int *decpt, int *sign, char **rve, char
|
|||
#ifndef SET_INEXACT
|
||||
#ifdef Check_FLT_ROUNDS
|
||||
try_quick = Rounding == 1;
|
||||
#else
|
||||
try_quick = 1;
|
||||
#endif
|
||||
#endif /*SET_INEXACT*/
|
||||
#endif
|
||||
#endif /*USE_BF96*/
|
||||
|
||||
if (mode > 5) {
|
||||
mode -= 4;
|
||||
|
|
@ -5281,6 +5338,7 @@ dtoa_r(double dd, int mode, int ndigits, int *decpt, int *sign, char **rve, char
|
|||
else if (blen <= i) {
|
||||
buf = 0;
|
||||
if (rve)
|
||||
/* cppcheck-suppress nullPointerArithmetic */
|
||||
*rve = buf + i;
|
||||
return buf;
|
||||
}
|
||||
|
|
@ -5469,6 +5527,7 @@ dtoa_r(double dd, int mode, int ndigits, int *decpt, int *sign, char **rve, char
|
|||
res3 = p10->b1 * dbhi + (tv3 & 0xffffffffull);
|
||||
res = p10->b0 * dbhi + (tv3>>32) + (res3>>32);
|
||||
be += p10->e - 0x3fe;
|
||||
/* cppcheck-suppress integerOverflowCond */
|
||||
eulp = j1 = be - 54 + ulpadj;
|
||||
if (!(res & 0x8000000000000000ull)) {
|
||||
--be;
|
||||
|
|
|
|||
2
src/deps/src/lua-cjson/fpconv.c
vendored
2
src/deps/src/lua-cjson/fpconv.c
vendored
|
|
@ -130,7 +130,7 @@ double fpconv_strtod(const char *nptr, char **endptr)
|
|||
/* Duplicate number into buffer */
|
||||
if (buflen >= FPCONV_G_FMT_BUFSIZE) {
|
||||
/* Handle unusually large numbers */
|
||||
buf = malloc(buflen + 1);
|
||||
buf = (char *)malloc(buflen + 1);
|
||||
if (!buf) {
|
||||
fprintf(stderr, "Out of memory");
|
||||
abort();
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
package = "lua-cjson"
|
||||
version = "2.1.0.11-1"
|
||||
version = "2.1.0.14-1"
|
||||
|
||||
source = {
|
||||
url = "git+https://github.com/openresty/lua-cjson",
|
||||
tag = "2.1.0.11",
|
||||
tag = "2.1.0.14",
|
||||
}
|
||||
|
||||
description = {
|
||||
2
src/deps/src/lua-cjson/lua-cjson.spec
vendored
2
src/deps/src/lua-cjson/lua-cjson.spec
vendored
|
|
@ -50,7 +50,7 @@ rm -rf "$RPM_BUILD_ROOT"
|
|||
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%doc LICENSE NEWS performance.html performance.txt manual.html manual.txt rfc4627.txt THANKS
|
||||
%doc LICENSE NEWS performance.html performance.adoc manual.html manual.adoc rfc4627.txt THANKS
|
||||
%{lualibdir}/*
|
||||
%{luadatadir}/*
|
||||
%{_bindir}/*
|
||||
|
|
|
|||
117
src/deps/src/lua-cjson/lua_cjson.c
vendored
117
src/deps/src/lua-cjson/lua_cjson.c
vendored
|
|
@ -40,6 +40,7 @@
|
|||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
|
|
@ -65,6 +66,13 @@
|
|||
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define CJSON_EXPORT __declspec(dllexport)
|
||||
#define strncasecmp(x,y,z) _strnicmp(x,y,z)
|
||||
#else
|
||||
#define CJSON_EXPORT extern
|
||||
#endif
|
||||
|
||||
/* Workaround for Solaris platforms missing isinf() */
|
||||
#if !defined(isinf) && (defined(USE_INTERNAL_ISINF) || defined(MISSING_ISINF))
|
||||
#define isinf(x) (!isnan(x) && isnan((x) - (x)))
|
||||
|
|
@ -103,8 +111,8 @@
|
|||
#define json_lightudata_mask(ludata) (ludata)
|
||||
#endif
|
||||
|
||||
#if LUA_VERSION_NUM > 501
|
||||
#define lua_objlen(L,i) lua_rawlen(L, (i))
|
||||
#if LUA_VERSION_NUM >= 502
|
||||
#define lua_objlen(L,i) luaL_len(L, (i))
|
||||
#endif
|
||||
|
||||
static const char * const *json_empty_array;
|
||||
|
|
@ -117,6 +125,7 @@ typedef enum {
|
|||
T_ARR_END,
|
||||
T_STRING,
|
||||
T_NUMBER,
|
||||
T_INTEGER,
|
||||
T_BOOLEAN,
|
||||
T_NULL,
|
||||
T_COLON,
|
||||
|
|
@ -134,6 +143,7 @@ static const char *json_token_type_name[] = {
|
|||
"T_ARR_END",
|
||||
"T_STRING",
|
||||
"T_NUMBER",
|
||||
"T_INTEGER",
|
||||
"T_BOOLEAN",
|
||||
"T_NULL",
|
||||
"T_COLON",
|
||||
|
|
@ -179,13 +189,14 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
json_token_type_t type;
|
||||
int index;
|
||||
size_t index;
|
||||
union {
|
||||
const char *string;
|
||||
double number;
|
||||
lua_Integer integer;
|
||||
int boolean;
|
||||
} value;
|
||||
int string_len;
|
||||
size_t string_len;
|
||||
} json_token_t;
|
||||
|
||||
static const char *char2escape[256] = {
|
||||
|
|
@ -233,7 +244,7 @@ static json_config_t *json_fetch_config(lua_State *l)
|
|||
{
|
||||
json_config_t *cfg;
|
||||
|
||||
cfg = lua_touserdata(l, lua_upvalueindex(1));
|
||||
cfg = (json_config_t *)lua_touserdata(l, lua_upvalueindex(1));
|
||||
if (!cfg)
|
||||
luaL_error(l, "BUG: Unable to fetch CJSON configuration");
|
||||
|
||||
|
|
@ -442,7 +453,7 @@ static int json_destroy_config(lua_State *l)
|
|||
{
|
||||
json_config_t *cfg;
|
||||
|
||||
cfg = lua_touserdata(l, 1);
|
||||
cfg = (json_config_t *)lua_touserdata(l, 1);
|
||||
if (cfg)
|
||||
strbuf_free(&cfg->encode_buf);
|
||||
cfg = NULL;
|
||||
|
|
@ -455,7 +466,11 @@ static void json_create_config(lua_State *l)
|
|||
json_config_t *cfg;
|
||||
int i;
|
||||
|
||||
cfg = lua_newuserdata(l, sizeof(*cfg));
|
||||
cfg = (json_config_t *)lua_newuserdata(l, sizeof(*cfg));
|
||||
if (!cfg)
|
||||
abort();
|
||||
|
||||
memset(cfg, 0, sizeof(*cfg));
|
||||
|
||||
/* Create GC method to clean up strbuf */
|
||||
lua_newtable(l);
|
||||
|
|
@ -547,9 +562,9 @@ static void json_encode_exception(lua_State *l, json_config_t *cfg, strbuf_t *js
|
|||
static void json_append_string(lua_State *l, strbuf_t *json, int lindex)
|
||||
{
|
||||
const char *escstr;
|
||||
unsigned i;
|
||||
const char *str;
|
||||
size_t len;
|
||||
size_t i;
|
||||
|
||||
str = lua_tolstring(l, lindex, &len);
|
||||
|
||||
|
|
@ -557,6 +572,8 @@ static void json_append_string(lua_State *l, strbuf_t *json, int lindex)
|
|||
* This buffer is reused constantly for small strings
|
||||
* If there are any excess pages, they won't be hit anyway.
|
||||
* This gains ~5% speedup. */
|
||||
if (len > SIZE_MAX / 6 - 3)
|
||||
abort(); /* Overflow check */
|
||||
strbuf_ensure_empty_length(json, len * 6 + 2);
|
||||
|
||||
strbuf_append_char_unsafe(json, '\"');
|
||||
|
|
@ -646,9 +663,9 @@ static int json_append_data(lua_State *l, json_config_t *cfg,
|
|||
/* json_append_array args:
|
||||
* - lua_State
|
||||
* - JSON strbuf
|
||||
* - Size of passwd Lua array (top of stack) */
|
||||
* - Size of passed Lua array (top of stack) */
|
||||
static void json_append_array(lua_State *l, json_config_t *cfg, int current_depth,
|
||||
strbuf_t *json, int array_length)
|
||||
strbuf_t *json, int array_length, int raw)
|
||||
{
|
||||
int comma, i, json_pos, err;
|
||||
|
||||
|
|
@ -660,7 +677,17 @@ static void json_append_array(lua_State *l, json_config_t *cfg, int current_dept
|
|||
if (comma++ > 0)
|
||||
strbuf_append_char(json, ',');
|
||||
|
||||
lua_rawgeti(l, -1, i);
|
||||
if (raw) {
|
||||
lua_rawgeti(l, -1, i);
|
||||
} else {
|
||||
#if LUA_VERSION_NUM >= 503
|
||||
lua_geti(l, -1, i);
|
||||
#else
|
||||
lua_pushinteger(l, i);
|
||||
lua_gettable(l, -2);
|
||||
#endif
|
||||
}
|
||||
|
||||
err = json_append_data(l, cfg, current_depth, json);
|
||||
if (err) {
|
||||
strbuf_set_length(json, json_pos);
|
||||
|
|
@ -677,8 +704,17 @@ static void json_append_array(lua_State *l, json_config_t *cfg, int current_dept
|
|||
static void json_append_number(lua_State *l, json_config_t *cfg,
|
||||
strbuf_t *json, int lindex)
|
||||
{
|
||||
double num = lua_tonumber(l, lindex);
|
||||
int len;
|
||||
#if LUA_VERSION_NUM >= 503
|
||||
if (lua_isinteger(l, lindex)) {
|
||||
lua_Integer num = lua_tointeger(l, lindex);
|
||||
strbuf_ensure_empty_length(json, FPCONV_G_FMT_BUFSIZE); /* max length of int64 is 19 */
|
||||
len = sprintf(strbuf_empty_ptr(json), LUA_INTEGER_FMT, num);
|
||||
strbuf_extend_length(json, len);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
double num = lua_tonumber(l, lindex);
|
||||
|
||||
if (cfg->encode_invalid_numbers == 0) {
|
||||
/* Prevent encoding invalid numbers */
|
||||
|
|
@ -766,6 +802,7 @@ static int json_append_data(lua_State *l, json_config_t *cfg,
|
|||
int len;
|
||||
int as_array = 0;
|
||||
int has_metatable;
|
||||
int raw = 1;
|
||||
|
||||
switch (lua_type(l, -1)) {
|
||||
case LUA_TSTRING:
|
||||
|
|
@ -790,17 +827,30 @@ static int json_append_data(lua_State *l, json_config_t *cfg,
|
|||
lua_pushlightuserdata(l, json_lightudata_mask(&json_array));
|
||||
lua_rawget(l, LUA_REGISTRYINDEX);
|
||||
as_array = lua_rawequal(l, -1, -2);
|
||||
lua_pop(l, 2);
|
||||
if (as_array) {
|
||||
raw = 1;
|
||||
lua_pop(l, 2);
|
||||
len = lua_objlen(l, -1);
|
||||
} else {
|
||||
raw = 0;
|
||||
lua_pop(l, 2);
|
||||
if (luaL_getmetafield(l, -1, "__len")) {
|
||||
lua_pushvalue(l, -2);
|
||||
lua_call(l, 1, 1);
|
||||
len = lua_tonumber(l, -1);
|
||||
lua_pop(l, 1);
|
||||
as_array = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (as_array) {
|
||||
len = lua_objlen(l, -1);
|
||||
json_append_array(l, cfg, current_depth, json, len);
|
||||
json_append_array(l, cfg, current_depth, json, len, raw);
|
||||
} else {
|
||||
len = lua_array_length(l, cfg, json);
|
||||
|
||||
if (len > 0 || (len == 0 && !cfg->encode_empty_table_as_object)) {
|
||||
json_append_array(l, cfg, current_depth, json, len);
|
||||
json_append_array(l, cfg, current_depth, json, len, raw);
|
||||
} else {
|
||||
if (has_metatable) {
|
||||
lua_getmetatable(l, -1);
|
||||
|
|
@ -810,7 +860,9 @@ static int json_append_data(lua_State *l, json_config_t *cfg,
|
|||
as_array = lua_rawequal(l, -1, -2);
|
||||
lua_pop(l, 2); /* pop pointer + metatable */
|
||||
if (as_array) {
|
||||
json_append_array(l, cfg, current_depth, json, 0);
|
||||
len = lua_objlen(l, -1);
|
||||
raw = 1;
|
||||
json_append_array(l, cfg, current_depth, json, len, raw);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -825,7 +877,7 @@ static int json_append_data(lua_State *l, json_config_t *cfg,
|
|||
if (lua_touserdata(l, -1) == NULL) {
|
||||
strbuf_append_mem(json, "null", 4);
|
||||
} else if (lua_touserdata(l, -1) == json_lightudata_mask(&json_array)) {
|
||||
json_append_array(l, cfg, current_depth, json, 0);
|
||||
json_append_array(l, cfg, current_depth, json, 0, 1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
@ -848,7 +900,7 @@ static int json_encode(lua_State *l)
|
|||
strbuf_t local_encode_buf;
|
||||
strbuf_t *encode_buf;
|
||||
char *json;
|
||||
int len;
|
||||
size_t len;
|
||||
|
||||
luaL_argcheck(l, lua_gettop(l) == 1, 1, "expected 1 argument");
|
||||
|
||||
|
|
@ -1138,13 +1190,19 @@ static int json_is_invalid_number(json_parse_t *json)
|
|||
static void json_next_number_token(json_parse_t *json, json_token_t *token)
|
||||
{
|
||||
char *endptr;
|
||||
|
||||
token->type = T_NUMBER;
|
||||
token->value.number = fpconv_strtod(json->ptr, &endptr);
|
||||
if (json->ptr == endptr)
|
||||
json_set_token_error(token, json, "invalid number");
|
||||
else
|
||||
json->ptr = endptr; /* Skip the processed number */
|
||||
token->value.integer = strtoll(json->ptr, &endptr, 10);
|
||||
if (json->ptr == endptr || *endptr == '.' || *endptr == 'e' ||
|
||||
*endptr == 'E' || *endptr == 'x') {
|
||||
token->type = T_NUMBER;
|
||||
token->value.number = fpconv_strtod(json->ptr, &endptr);
|
||||
if (json->ptr == endptr) {
|
||||
json_set_token_error(token, json, "invalid number");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
token->type = T_INTEGER;
|
||||
}
|
||||
json->ptr = endptr; /* Skip the processed number */
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -1380,6 +1438,9 @@ static void json_process_value(lua_State *l, json_parse_t *json,
|
|||
case T_NUMBER:
|
||||
lua_pushnumber(l, token->value.number);
|
||||
break;;
|
||||
case T_INTEGER:
|
||||
lua_pushinteger(l, token->value.integer);
|
||||
break;;
|
||||
case T_BOOLEAN:
|
||||
lua_pushboolean(l, token->value.boolean);
|
||||
break;;
|
||||
|
|
@ -1595,7 +1656,7 @@ static int lua_cjson_safe_new(lua_State *l)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int luaopen_cjson(lua_State *l)
|
||||
CJSON_EXPORT int luaopen_cjson(lua_State *l)
|
||||
{
|
||||
lua_cjson_new(l);
|
||||
|
||||
|
|
@ -1609,7 +1670,7 @@ int luaopen_cjson(lua_State *l)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int luaopen_cjson_safe(lua_State *l)
|
||||
CJSON_EXPORT int luaopen_cjson_safe(lua_State *l)
|
||||
{
|
||||
lua_cjson_safe_new(l);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
= Lua CJSON 2.1devel Manual =
|
||||
Mark Pulford <mark@kyne.com.au>
|
||||
:revdate: 1st March 2012
|
||||
:revdate: August 2016
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
|
@ -20,7 +20,7 @@ The Lua CJSON module provides JSON support for Lua.
|
|||
Lua CJSON is covered by the MIT license. Review the file +LICENSE+ for
|
||||
details.
|
||||
|
||||
The latest version of this software is available from the
|
||||
The current stable version of this software is available from the
|
||||
http://www.kyne.com.au/%7Emark/software/lua-cjson.php[Lua CJSON website].
|
||||
|
||||
Feel free to email me if you have any patches, suggestions, or comments.
|
||||
|
|
@ -29,8 +29,8 @@ Feel free to email me if you have any patches, suggestions, or comments.
|
|||
Installation
|
||||
------------
|
||||
|
||||
Lua CJSON requires either http://www.lua.org[Lua] 5.1, Lua 5.2, or
|
||||
http://www.luajit.org[LuaJIT] to build.
|
||||
Lua CJSON requires either http://www.lua.org[Lua] 5.1, Lua 5.2, Lua 5.3,
|
||||
or http://www.luajit.org[LuaJIT] to build.
|
||||
|
||||
The build method can be selected from 4 options:
|
||||
|
||||
|
|
@ -203,8 +203,8 @@ Import Lua CJSON via the Lua +require+ function. Lua CJSON does not
|
|||
register a global module table.
|
||||
|
||||
The +cjson+ module will throw an error during JSON conversion if any
|
||||
invalid data is encountered. Refer to <<cjson_encode,+cjson.encode+>>
|
||||
and <<cjson_decode,+cjson.decode+>> for details.
|
||||
invalid data is encountered. Refer to <<encode,+cjson.encode+>> and
|
||||
<<decode,+cjson.decode+>> for details.
|
||||
|
||||
The +cjson.safe+ module behaves identically to the +cjson+ module,
|
||||
except when errors are encountered during JSON conversion. On error, the
|
||||
|
|
@ -238,6 +238,7 @@ workaround if required. Lua CJSON should be reinitialised via
|
|||
different locale per thread is not supported.
|
||||
|
||||
|
||||
[[decode]]
|
||||
decode
|
||||
~~~~~~
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ http://chiselapp.com/user/dhkolf/repository/dkjson/[DKJSON 2.1]::
|
|||
https://github.com/brimworks/lua-yajl[Lua YAJL 2.0]::
|
||||
- C wrapper for the YAJL library
|
||||
|
||||
http://www.kyne.com.au/%7Emark/software/lua-cjson.php[Lua CSJON 2.0.0]::
|
||||
http://www.kyne.com.au/%7Emark/software/lua-cjson.php[Lua CJSON 2.0.0]::
|
||||
- C implementation with no dependencies on other libraries
|
||||
|
||||
|
||||
116
src/deps/src/lua-cjson/strbuf.c
vendored
116
src/deps/src/lua-cjson/strbuf.c
vendored
|
|
@ -26,6 +26,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "strbuf.h"
|
||||
|
||||
|
|
@ -38,38 +39,38 @@ static void die(const char *fmt, ...)
|
|||
va_end(arg);
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
exit(-1);
|
||||
abort();
|
||||
}
|
||||
|
||||
void strbuf_init(strbuf_t *s, int len)
|
||||
void strbuf_init(strbuf_t *s, size_t len)
|
||||
{
|
||||
int size;
|
||||
size_t size;
|
||||
|
||||
if (len <= 0)
|
||||
if (!len)
|
||||
size = STRBUF_DEFAULT_SIZE;
|
||||
else
|
||||
size = len + 1; /* \0 terminator */
|
||||
|
||||
size = len + 1;
|
||||
if (size < len)
|
||||
die("Overflow, len: %zu", len);
|
||||
s->buf = NULL;
|
||||
s->size = size;
|
||||
s->length = 0;
|
||||
s->increment = STRBUF_DEFAULT_INCREMENT;
|
||||
s->dynamic = 0;
|
||||
s->reallocs = 0;
|
||||
s->debug = 0;
|
||||
|
||||
s->buf = malloc(size);
|
||||
s->buf = (char *)malloc(size);
|
||||
if (!s->buf)
|
||||
die("Out of memory");
|
||||
|
||||
strbuf_ensure_null(s);
|
||||
}
|
||||
|
||||
strbuf_t *strbuf_new(int len)
|
||||
strbuf_t *strbuf_new(size_t len)
|
||||
{
|
||||
strbuf_t *s;
|
||||
|
||||
s = malloc(sizeof(strbuf_t));
|
||||
s = (strbuf_t*)malloc(sizeof(strbuf_t));
|
||||
if (!s)
|
||||
die("Out of memory");
|
||||
|
||||
|
|
@ -81,20 +82,10 @@ strbuf_t *strbuf_new(int len)
|
|||
return s;
|
||||
}
|
||||
|
||||
void strbuf_set_increment(strbuf_t *s, int increment)
|
||||
{
|
||||
/* Increment > 0: Linear buffer growth rate
|
||||
* Increment < -1: Exponential buffer growth rate */
|
||||
if (increment == 0 || increment == -1)
|
||||
die("BUG: Invalid string increment");
|
||||
|
||||
s->increment = increment;
|
||||
}
|
||||
|
||||
static inline void debug_stats(strbuf_t *s)
|
||||
{
|
||||
if (s->debug) {
|
||||
fprintf(stderr, "strbuf(%lx) reallocs: %d, length: %d, size: %d\n",
|
||||
fprintf(stderr, "strbuf(%lx) reallocs: %d, length: %zd, size: %zd\n",
|
||||
(long)s, s->reallocs, s->length, s->size);
|
||||
}
|
||||
}
|
||||
|
|
@ -113,7 +104,7 @@ void strbuf_free(strbuf_t *s)
|
|||
free(s);
|
||||
}
|
||||
|
||||
char *strbuf_free_to_string(strbuf_t *s, int *len)
|
||||
char *strbuf_free_to_string(strbuf_t *s, size_t *len)
|
||||
{
|
||||
char *buf;
|
||||
|
||||
|
|
@ -131,57 +122,63 @@ char *strbuf_free_to_string(strbuf_t *s, int *len)
|
|||
return buf;
|
||||
}
|
||||
|
||||
static int calculate_new_size(strbuf_t *s, int len)
|
||||
static size_t calculate_new_size(strbuf_t *s, size_t len)
|
||||
{
|
||||
int reqsize, newsize;
|
||||
size_t reqsize, newsize;
|
||||
|
||||
if (len <= 0)
|
||||
die("BUG: Invalid strbuf length requested");
|
||||
|
||||
/* Ensure there is room for optional NULL termination */
|
||||
reqsize = len + 1;
|
||||
if (reqsize < len)
|
||||
die("Overflow, len: %zu", len);
|
||||
|
||||
/* If the user has requested to shrink the buffer, do it exactly */
|
||||
if (s->size > reqsize)
|
||||
return reqsize;
|
||||
|
||||
newsize = s->size;
|
||||
if (s->increment < 0) {
|
||||
if (reqsize >= SIZE_MAX / 2) {
|
||||
newsize = reqsize;
|
||||
} else {
|
||||
/* Exponential sizing */
|
||||
while (newsize < reqsize)
|
||||
newsize *= -s->increment;
|
||||
} else if (s->increment != 0) {
|
||||
/* Linear sizing */
|
||||
newsize = ((newsize + s->increment - 1) / s->increment) * s->increment;
|
||||
newsize *= 2;
|
||||
}
|
||||
|
||||
if (newsize < reqsize)
|
||||
die("BUG: strbuf length would overflow, len: %zu", len);
|
||||
|
||||
|
||||
return newsize;
|
||||
}
|
||||
|
||||
|
||||
/* Ensure strbuf can handle a string length bytes long (ignoring NULL
|
||||
* optional termination). */
|
||||
void strbuf_resize(strbuf_t *s, int len)
|
||||
void strbuf_resize(strbuf_t *s, size_t len)
|
||||
{
|
||||
int newsize;
|
||||
size_t newsize;
|
||||
|
||||
newsize = calculate_new_size(s, len);
|
||||
|
||||
if (s->debug > 1) {
|
||||
fprintf(stderr, "strbuf(%lx) resize: %d => %d\n",
|
||||
fprintf(stderr, "strbuf(%lx) resize: %zd => %zd\n",
|
||||
(long)s, s->size, newsize);
|
||||
}
|
||||
|
||||
s->size = newsize;
|
||||
s->buf = realloc(s->buf, s->size);
|
||||
s->buf = (char *)realloc(s->buf, s->size);
|
||||
if (!s->buf)
|
||||
die("Out of memory");
|
||||
die("Out of memory, len: %zu", len);
|
||||
s->reallocs++;
|
||||
}
|
||||
|
||||
void strbuf_append_string(strbuf_t *s, const char *str)
|
||||
{
|
||||
int space, i;
|
||||
int i;
|
||||
size_t space;
|
||||
|
||||
space = strbuf_empty_length(s);
|
||||
|
||||
|
|
@ -197,55 +194,6 @@ void strbuf_append_string(strbuf_t *s, const char *str)
|
|||
}
|
||||
}
|
||||
|
||||
/* strbuf_append_fmt() should only be used when an upper bound
|
||||
* is known for the output string. */
|
||||
void strbuf_append_fmt(strbuf_t *s, int len, const char *fmt, ...)
|
||||
{
|
||||
va_list arg;
|
||||
int fmt_len;
|
||||
|
||||
strbuf_ensure_empty_length(s, len);
|
||||
|
||||
va_start(arg, fmt);
|
||||
fmt_len = vsnprintf(s->buf + s->length, len, fmt, arg);
|
||||
va_end(arg);
|
||||
|
||||
if (fmt_len < 0)
|
||||
die("BUG: Unable to convert number"); /* This should never happen.. */
|
||||
|
||||
s->length += fmt_len;
|
||||
}
|
||||
|
||||
/* strbuf_append_fmt_retry() can be used when the there is no known
|
||||
* upper bound for the output string. */
|
||||
void strbuf_append_fmt_retry(strbuf_t *s, const char *fmt, ...)
|
||||
{
|
||||
va_list arg;
|
||||
int fmt_len, try;
|
||||
int empty_len;
|
||||
|
||||
/* If the first attempt to append fails, resize the buffer appropriately
|
||||
* and try again */
|
||||
for (try = 0; ; try++) {
|
||||
va_start(arg, fmt);
|
||||
/* Append the new formatted string */
|
||||
/* fmt_len is the length of the string required, excluding the
|
||||
* trailing NULL */
|
||||
empty_len = strbuf_empty_length(s);
|
||||
/* Add 1 since there is also space to store the terminating NULL. */
|
||||
fmt_len = vsnprintf(s->buf + s->length, empty_len + 1, fmt, arg);
|
||||
va_end(arg);
|
||||
|
||||
if (fmt_len <= empty_len)
|
||||
break; /* SUCCESS */
|
||||
if (try > 0)
|
||||
die("BUG: length of formatted string changed");
|
||||
|
||||
strbuf_resize(s, s->length + fmt_len);
|
||||
}
|
||||
|
||||
s->length += fmt_len;
|
||||
}
|
||||
|
||||
/* vi:ai et sw=4 ts=4:
|
||||
*/
|
||||
|
|
|
|||
46
src/deps/src/lua-cjson/strbuf.h
vendored
46
src/deps/src/lua-cjson/strbuf.h
vendored
|
|
@ -32,15 +32,13 @@
|
|||
|
||||
/* Size: Total bytes allocated to *buf
|
||||
* Length: String length, excluding optional NULL terminator.
|
||||
* Increment: Allocation increments when resizing the string buffer.
|
||||
* Dynamic: True if created via strbuf_new()
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
char *buf;
|
||||
int size;
|
||||
int length;
|
||||
int increment;
|
||||
size_t size;
|
||||
size_t length;
|
||||
int dynamic;
|
||||
int reallocs;
|
||||
int debug;
|
||||
|
|
@ -49,33 +47,27 @@ typedef struct {
|
|||
#ifndef STRBUF_DEFAULT_SIZE
|
||||
#define STRBUF_DEFAULT_SIZE 1023
|
||||
#endif
|
||||
#ifndef STRBUF_DEFAULT_INCREMENT
|
||||
#define STRBUF_DEFAULT_INCREMENT -2
|
||||
#endif
|
||||
|
||||
/* Initialise */
|
||||
extern strbuf_t *strbuf_new(int len);
|
||||
extern void strbuf_init(strbuf_t *s, int len);
|
||||
extern void strbuf_set_increment(strbuf_t *s, int increment);
|
||||
extern strbuf_t *strbuf_new(size_t len);
|
||||
extern void strbuf_init(strbuf_t *s, size_t len);
|
||||
|
||||
/* Release */
|
||||
extern void strbuf_free(strbuf_t *s);
|
||||
extern char *strbuf_free_to_string(strbuf_t *s, int *len);
|
||||
extern char *strbuf_free_to_string(strbuf_t *s, size_t *len);
|
||||
|
||||
/* Management */
|
||||
extern void strbuf_resize(strbuf_t *s, int len);
|
||||
static int strbuf_empty_length(strbuf_t *s);
|
||||
static int strbuf_length(strbuf_t *s);
|
||||
static char *strbuf_string(strbuf_t *s, int *len);
|
||||
static void strbuf_ensure_empty_length(strbuf_t *s, int len);
|
||||
extern void strbuf_resize(strbuf_t *s, size_t len);
|
||||
static size_t strbuf_empty_length(strbuf_t *s);
|
||||
static size_t strbuf_length(strbuf_t *s);
|
||||
static char *strbuf_string(strbuf_t *s, size_t *len);
|
||||
static void strbuf_ensure_empty_length(strbuf_t *s, size_t len);
|
||||
static char *strbuf_empty_ptr(strbuf_t *s);
|
||||
static void strbuf_extend_length(strbuf_t *s, int len);
|
||||
static void strbuf_extend_length(strbuf_t *s, size_t len);
|
||||
static void strbuf_set_length(strbuf_t *s, int len);
|
||||
|
||||
/* Update */
|
||||
extern void strbuf_append_fmt(strbuf_t *s, int len, const char *fmt, ...);
|
||||
extern void strbuf_append_fmt_retry(strbuf_t *s, const char *format, ...);
|
||||
static void strbuf_append_mem(strbuf_t *s, const char *c, int len);
|
||||
static void strbuf_append_mem(strbuf_t *s, const char *c, size_t len);
|
||||
extern void strbuf_append_string(strbuf_t *s, const char *str);
|
||||
static void strbuf_append_char(strbuf_t *s, const char c);
|
||||
static void strbuf_ensure_null(strbuf_t *s);
|
||||
|
|
@ -93,12 +85,12 @@ static inline int strbuf_allocated(strbuf_t *s)
|
|||
|
||||
/* Return bytes remaining in the string buffer
|
||||
* Ensure there is space for a NULL terminator. */
|
||||
static inline int strbuf_empty_length(strbuf_t *s)
|
||||
static inline size_t strbuf_empty_length(strbuf_t *s)
|
||||
{
|
||||
return s->size - s->length - 1;
|
||||
}
|
||||
|
||||
static inline void strbuf_ensure_empty_length(strbuf_t *s, int len)
|
||||
static inline void strbuf_ensure_empty_length(strbuf_t *s, size_t len)
|
||||
{
|
||||
if (len > strbuf_empty_length(s))
|
||||
strbuf_resize(s, s->length + len);
|
||||
|
|
@ -114,12 +106,12 @@ static inline void strbuf_set_length(strbuf_t *s, int len)
|
|||
s->length = len;
|
||||
}
|
||||
|
||||
static inline void strbuf_extend_length(strbuf_t *s, int len)
|
||||
static inline void strbuf_extend_length(strbuf_t *s, size_t len)
|
||||
{
|
||||
s->length += len;
|
||||
}
|
||||
|
||||
static inline int strbuf_length(strbuf_t *s)
|
||||
static inline size_t strbuf_length(strbuf_t *s)
|
||||
{
|
||||
return s->length;
|
||||
}
|
||||
|
|
@ -135,14 +127,14 @@ static inline void strbuf_append_char_unsafe(strbuf_t *s, const char c)
|
|||
s->buf[s->length++] = c;
|
||||
}
|
||||
|
||||
static inline void strbuf_append_mem(strbuf_t *s, const char *c, int len)
|
||||
static inline void strbuf_append_mem(strbuf_t *s, const char *c, size_t len)
|
||||
{
|
||||
strbuf_ensure_empty_length(s, len);
|
||||
memcpy(s->buf + s->length, c, len);
|
||||
s->length += len;
|
||||
}
|
||||
|
||||
static inline void strbuf_append_mem_unsafe(strbuf_t *s, const char *c, int len)
|
||||
static inline void strbuf_append_mem_unsafe(strbuf_t *s, const char *c, size_t len)
|
||||
{
|
||||
memcpy(s->buf + s->length, c, len);
|
||||
s->length += len;
|
||||
|
|
@ -153,7 +145,7 @@ static inline void strbuf_ensure_null(strbuf_t *s)
|
|||
s->buf[s->length] = 0;
|
||||
}
|
||||
|
||||
static inline char *strbuf_string(strbuf_t *s, int *len)
|
||||
static inline char *strbuf_string(strbuf_t *s, size_t *len)
|
||||
{
|
||||
if (len)
|
||||
*len = s->length;
|
||||
|
|
|
|||
42
src/deps/src/lua-cjson/tests/agentzh.t
vendored
42
src/deps/src/lua-cjson/tests/agentzh.t
vendored
|
|
@ -332,3 +332,45 @@ Cannot serialise function: type not supported
|
|||
|
||||
{"valid":"valid"}
|
||||
["one","two","three"]
|
||||
|
||||
|
||||
|
||||
=== TEST 23: array-like proxy object with __len and __index
|
||||
--- lua
|
||||
local cjson = require "cjson"
|
||||
local real_array = {"foo", "bar", "baz"}
|
||||
local proxy_array = {}
|
||||
setmetatable(proxy_array, {
|
||||
__len = function() return 3 end,
|
||||
__index = function(t, k)
|
||||
return real_array[k]
|
||||
end,
|
||||
})
|
||||
|
||||
print(cjson.encode(proxy_array))
|
||||
--- out
|
||||
["foo","bar","baz"]
|
||||
|
||||
|
||||
|
||||
=== TEST 24: check that integers are handled correctly on Lua 5.3+
|
||||
--- lua
|
||||
local lv = tonumber((_VERSION):match("Lua 5%.([0-9]+)"))
|
||||
|
||||
if lv >= 3 then
|
||||
local cjson = require "cjson"
|
||||
local array = cjson.decode [[ [10, 10.0, 3.5] ]]
|
||||
for i = 1, 4 do
|
||||
print(tostring(i) .. ": " .. tostring(math.type(array[i])))
|
||||
end
|
||||
else
|
||||
print("1: integer")
|
||||
print("2: float")
|
||||
print("3: float")
|
||||
print("4: nil")
|
||||
end
|
||||
--- out
|
||||
1: integer
|
||||
2: float
|
||||
3: float
|
||||
4: nil
|
||||
|
|
|
|||
1
src/deps/src/lua-cjson/tests/genutf8.pl
vendored
1
src/deps/src/lua-cjson/tests/genutf8.pl
vendored
|
|
@ -6,6 +6,7 @@
|
|||
# cff03b039d850f370a7362f3313e5268
|
||||
|
||||
use strict;
|
||||
no warnings 'nonchar';
|
||||
|
||||
# 0xD800 - 0xDFFF are used to encode supplementary codepoints
|
||||
# 0x10000 - 0x10FFFF are supplementary codepoints
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM redhat/ubi9:9.4@sha256:d31d3e5e92c0c47277c5011c0326b285ab7ae627eff036133be1dccc4208004d as builder
|
||||
FROM redhat/ubi9:9.4@sha256:d98fdae16212df566150ac975cab860cd8d2cb1b322ed9966d09a13e219112e9 as builder
|
||||
|
||||
ENV OS=rhel
|
||||
ENV NGINX_VERSION 1.26.1
|
||||
|
|
@ -68,7 +68,7 @@ COPY src/scheduler scheduler
|
|||
COPY src/ui ui
|
||||
COPY src/VERSION VERSION
|
||||
|
||||
FROM redhat/ubi9:9.4@sha256:d31d3e5e92c0c47277c5011c0326b285ab7ae627eff036133be1dccc4208004d
|
||||
FROM redhat/ubi9:9.4@sha256:d98fdae16212df566150ac975cab860cd8d2cb1b322ed9966d09a13e219112e9
|
||||
|
||||
# Set default umask to prevent huge recursive chmod increasing the final image size
|
||||
RUN umask 027
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.3-alpine3.19@sha256:ef097620baf1272e38264207003b0982285da3236a20ed829bf6bbf1e85fe3cb as builder
|
||||
FROM python:3.12.4-alpine3.19@sha256:ef3397d09070efd36583e83d2619cf8006158641e5b6b629d4d92a9778f5aa1c as builder
|
||||
|
||||
# Export var for specific actions on linux/arm/v7
|
||||
ARG TARGETPLATFORM
|
||||
|
|
@ -35,7 +35,7 @@ COPY src/common/utils utils
|
|||
COPY src/scheduler scheduler
|
||||
COPY src/VERSION VERSION
|
||||
|
||||
FROM python:3.12.3-alpine3.19@sha256:ef097620baf1272e38264207003b0982285da3236a20ed829bf6bbf1e85fe3cb
|
||||
FROM python:3.12.4-alpine3.19@sha256:ef3397d09070efd36583e83d2619cf8006158641e5b6b629d4d92a9778f5aa1c
|
||||
|
||||
# Set default umask to prevent huge recursive chmod increasing the final image size
|
||||
RUN umask 027
|
||||
|
|
|
|||
|
|
@ -9,13 +9,13 @@ from json import load as json_load
|
|||
from os import _exit, environ, getenv, getpid, sep
|
||||
from os.path import join
|
||||
from pathlib import Path
|
||||
from shutil import copy, rmtree
|
||||
from shutil import copy, rmtree, copytree
|
||||
from signal import SIGINT, SIGTERM, signal, SIGHUP
|
||||
from stat import S_IEXEC
|
||||
from subprocess import run as subprocess_run, DEVNULL, STDOUT, PIPE
|
||||
from sys import path as sys_path
|
||||
from tarfile import TarFile, open as tar_open
|
||||
from threading import Thread
|
||||
from threading import Event, Thread
|
||||
from time import sleep
|
||||
from traceback import format_exc
|
||||
from typing import Any, Dict, List, Literal, Optional, Union
|
||||
|
|
@ -30,13 +30,15 @@ from common_utils import bytes_hash, dict_to_frozenset, get_integration # type:
|
|||
from logger import setup_logger # type: ignore
|
||||
from Database import Database # type: ignore
|
||||
from JobScheduler import JobScheduler
|
||||
from API import API
|
||||
from jobs import Job # type: ignore
|
||||
from API import API # type: ignore
|
||||
|
||||
APPLYING_CHANGES = Event()
|
||||
RUN = True
|
||||
SCHEDULER: Optional[JobScheduler] = None
|
||||
|
||||
CACHE_PATH = join(sep, "var", "cache", "bunkerweb")
|
||||
Path(CACHE_PATH).mkdir(parents=True, exist_ok=True)
|
||||
CACHE_PATH = Path(sep, "var", "cache", "bunkerweb")
|
||||
CACHE_PATH.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
CUSTOM_CONFIGS_PATH = Path(sep, "etc", "bunkerweb", "configs")
|
||||
CUSTOM_CONFIGS_PATH.mkdir(parents=True, exist_ok=True)
|
||||
|
|
@ -54,6 +56,8 @@ CUSTOM_CONFIGS_DIRS = (
|
|||
for custom_config_dir in CUSTOM_CONFIGS_DIRS:
|
||||
CUSTOM_CONFIGS_PATH.joinpath(custom_config_dir).mkdir(parents=True, exist_ok=True)
|
||||
|
||||
CONFIG_PATH = Path(sep, "etc", "nginx")
|
||||
|
||||
EXTERNAL_PLUGINS_PATH = Path(sep, "etc", "bunkerweb", "plugins")
|
||||
EXTERNAL_PLUGINS_PATH.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
|
@ -63,6 +67,9 @@ PRO_PLUGINS_PATH.mkdir(parents=True, exist_ok=True)
|
|||
TMP_PATH = Path(sep, "var", "tmp", "bunkerweb")
|
||||
TMP_PATH.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
FAILOVER_PATH = TMP_PATH.joinpath("failover")
|
||||
FAILOVER_PATH.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
HEALTHY_PATH = TMP_PATH.joinpath("scheduler.healthy")
|
||||
|
||||
SCHEDULER_TMP_ENV_PATH = TMP_PATH.joinpath("scheduler.env")
|
||||
|
|
@ -76,6 +83,14 @@ MASTER_MODE = environ.get("MASTER_MODE", "no") == "yes"
|
|||
|
||||
|
||||
def handle_stop(signum, frame):
|
||||
current_time = datetime.now()
|
||||
while APPLYING_CHANGES.is_set() and (datetime.now() - current_time).seconds < 30:
|
||||
logger.warning("Waiting for the changes to be applied before stopping ...")
|
||||
sleep(1)
|
||||
|
||||
if APPLYING_CHANGES.is_set():
|
||||
logger.warning("Timeout reached, stopping without waiting for the changes to be applied ...")
|
||||
|
||||
if SCHEDULER is not None:
|
||||
SCHEDULER.clear()
|
||||
stop(0)
|
||||
|
|
@ -124,6 +139,56 @@ def stop(status):
|
|||
_exit(status)
|
||||
|
||||
|
||||
def send_nginx_configs(sent_path: Path = CONFIG_PATH):
|
||||
assert SCHEDULER is not None, "SCHEDULER is not defined"
|
||||
logger.info(f"Sending {sent_path} folder ...")
|
||||
ret = SCHEDULER.send_files(sent_path.as_posix(), "/confs")
|
||||
if not ret:
|
||||
logger.error("Sending nginx configs failed, configuration will not work as expected...")
|
||||
|
||||
|
||||
def send_nginx_cache(sent_path: Path = CACHE_PATH):
|
||||
assert SCHEDULER is not None, "SCHEDULER is not defined"
|
||||
logger.info(f"Sending {sent_path} folder ...")
|
||||
if not SCHEDULER.send_files(sent_path.as_posix(), "/cache"):
|
||||
logger.error(f"Error while sending {sent_path} folder")
|
||||
else:
|
||||
logger.info(f"Successfully sent {sent_path} folder")
|
||||
|
||||
|
||||
def send_nginx_custom_configs(sent_path: Path = CUSTOM_CONFIGS_PATH):
|
||||
assert SCHEDULER is not None, "SCHEDULER is not defined"
|
||||
logger.info(f"Sending {sent_path} folder ...")
|
||||
if not SCHEDULER.send_files(sent_path.as_posix(), "/custom_configs"):
|
||||
logger.error(f"Error while sending {sent_path} folder")
|
||||
else:
|
||||
logger.info(f"Successfully sent {sent_path} folder")
|
||||
|
||||
|
||||
def listen_for_instances_reload():
|
||||
from docker import DockerClient
|
||||
|
||||
global SCHEDULER
|
||||
assert SCHEDULER is not None, "SCHEDULER is not defined"
|
||||
|
||||
docker_client = DockerClient(base_url=getenv("DOCKER_HOST", "unix:///var/run/docker.sock"))
|
||||
for event in docker_client.events(decode=True, filters={"type": "container", "label": "bunkerweb.INSTANCE"}):
|
||||
if event["Action"] in ("start", "die"):
|
||||
logger.info(f"🐋 Detected {event['Action']} event on container {event['Actor']['Attributes']['name']}")
|
||||
SCHEDULER.auto_setup()
|
||||
try:
|
||||
ret = SCHEDULER.db.update_instances([api_to_instance(api) for api in SCHEDULER.apis], changed=event["Action"] == "die")
|
||||
if ret:
|
||||
logger.error(f"Error while updating instances after {event['Action']} event: {ret}")
|
||||
continue
|
||||
if event["Action"] == "start":
|
||||
ret = SCHEDULER.db.checked_changes(value=True)
|
||||
if ret:
|
||||
logger.error(f"Error while setting changes to checked in the database after {event['Action']} event: {ret}")
|
||||
except BaseException as e:
|
||||
logger.error(f"Error while updating instances after {event['Action']} event: {e}")
|
||||
|
||||
|
||||
def generate_custom_configs(configs: Optional[List[Dict[str, Any]]] = None, *, original_path: Union[Path, str] = CUSTOM_CONFIGS_PATH):
|
||||
if not isinstance(original_path, Path):
|
||||
original_path = Path(original_path)
|
||||
|
|
@ -168,11 +233,7 @@ def generate_custom_configs(configs: Optional[List[Dict[str, Any]]] = None, *, o
|
|||
)
|
||||
|
||||
if SCHEDULER and SCHEDULER.apis:
|
||||
logger.info("Sending custom configs to BunkerWeb")
|
||||
ret = SCHEDULER.send_files(original_path, "/custom_configs")
|
||||
|
||||
if not ret:
|
||||
logger.error("Sending custom configs failed, configuration will not work as expected...")
|
||||
send_nginx_custom_configs(original_path)
|
||||
|
||||
|
||||
def generate_external_plugins(plugins: Optional[List[Dict[str, Any]]] = None, *, original_path: Union[Path, str] = EXTERNAL_PLUGINS_PATH):
|
||||
|
|
@ -351,7 +412,7 @@ def run_in_slave_mode():
|
|||
"--templates",
|
||||
join(sep, "usr", "share", "bunkerweb", "confs"),
|
||||
"--output",
|
||||
join(sep, "etc", "nginx"),
|
||||
CONFIG_PATH.as_posix(),
|
||||
"--variables",
|
||||
str(SCHEDULER_TMP_ENV_PATH),
|
||||
],
|
||||
|
|
@ -387,15 +448,19 @@ if __name__ == "__main__":
|
|||
|
||||
INTEGRATION = get_integration()
|
||||
tmp_variables_path = Path(args.variables or join(sep, "var", "tmp", "bunkerweb", "variables.env"))
|
||||
nginx_variables_path = Path(sep, "etc", "nginx", "variables.env")
|
||||
nginx_variables_path = CONFIG_PATH.joinpath("variables.env")
|
||||
dotenv_env = dotenv_values(str(tmp_variables_path))
|
||||
|
||||
SCHEDULER = JobScheduler(environ, logger, INTEGRATION, db=Database(logger, sqlalchemy_string=dotenv_env.get("DATABASE_URI", getenv("DATABASE_URI", None)))) # type: ignore
|
||||
|
||||
JOB = Job(logger, SCHEDULER.db)
|
||||
|
||||
if SLAVE_MODE:
|
||||
run_in_slave_mode()
|
||||
stop(1)
|
||||
|
||||
APPLYING_CHANGES.set()
|
||||
|
||||
if (
|
||||
INTEGRATION in ("Swarm", "Kubernetes", "Autoconf")
|
||||
or not tmp_variables_path.exists()
|
||||
|
|
@ -466,6 +531,7 @@ if __name__ == "__main__":
|
|||
|
||||
def check_configs_changes():
|
||||
# Checking if any custom config has been created by the user
|
||||
assert SCHEDULER is not None, "SCHEDULER is not defined"
|
||||
logger.info("Checking if there are any changes in custom configs ...")
|
||||
custom_configs = []
|
||||
db_configs = SCHEDULER.db.get_custom_configs()
|
||||
|
|
@ -507,6 +573,7 @@ if __name__ == "__main__":
|
|||
|
||||
def check_plugin_changes(_type: Literal["external", "pro"] = "external"):
|
||||
# Check if any external or pro plugin has been added by the user
|
||||
assert SCHEDULER is not None, "SCHEDULER is not defined"
|
||||
logger.info(f"Checking if there are any changes in {_type} plugins ...")
|
||||
plugin_path = EXTERNAL_PLUGINS_PATH if _type == "external" else PRO_PLUGINS_PATH
|
||||
db_plugins = SCHEDULER.db.get_plugins(_type=_type)
|
||||
|
|
@ -624,41 +691,6 @@ if __name__ == "__main__":
|
|||
RUN_JOBS_ONCE = True
|
||||
CHANGES = []
|
||||
|
||||
def send_nginx_configs():
|
||||
logger.info(f"Sending {join(sep, 'etc', 'nginx')} folder ...")
|
||||
ret = SCHEDULER.send_files(join(sep, "etc", "nginx"), "/confs")
|
||||
if not ret:
|
||||
logger.error("Sending nginx configs failed, configuration will not work as expected...")
|
||||
|
||||
def send_nginx_cache():
|
||||
logger.info(f"Sending {CACHE_PATH} folder ...")
|
||||
if not SCHEDULER.send_files(CACHE_PATH, "/cache"):
|
||||
logger.error(f"Error while sending {CACHE_PATH} folder")
|
||||
else:
|
||||
logger.info(f"Successfully sent {CACHE_PATH} folder")
|
||||
|
||||
def listen_for_instances_reload():
|
||||
from docker import DockerClient
|
||||
|
||||
global SCHEDULER
|
||||
|
||||
docker_client = DockerClient(base_url=getenv("DOCKER_HOST", "unix:///var/run/docker.sock"))
|
||||
for event in docker_client.events(decode=True, filters={"type": "container", "label": "bunkerweb.INSTANCE"}):
|
||||
if event["Action"] in ("start", "die"):
|
||||
logger.info(f"🐋 Detected {event['Action']} event on container {event['Actor']['Attributes']['name']}")
|
||||
SCHEDULER.auto_setup()
|
||||
try:
|
||||
ret = SCHEDULER.db.update_instances([api_to_instance(api) for api in SCHEDULER.apis], changed=event["Action"] == "die")
|
||||
if ret:
|
||||
logger.error(f"Error while updating instances after {event['Action']} event: {ret}")
|
||||
continue
|
||||
if event["Action"] == "start":
|
||||
ret = SCHEDULER.db.checked_changes(value=True)
|
||||
if ret:
|
||||
logger.error(f"Error while setting changes to checked in the database after {event['Action']} event: {ret}")
|
||||
except BaseException as e:
|
||||
logger.error(f"Error while updating instances after {event['Action']} event: {e}")
|
||||
|
||||
if INTEGRATION == "Docker" and not override_instances:
|
||||
Thread(target=listen_for_instances_reload, name="listen_for_instances_reload").start()
|
||||
|
||||
|
|
@ -692,7 +724,7 @@ if __name__ == "__main__":
|
|||
"--templates",
|
||||
join(sep, "usr", "share", "bunkerweb", "confs"),
|
||||
"--output",
|
||||
join(sep, "etc", "nginx"),
|
||||
CONFIG_PATH.as_posix(),
|
||||
"--variables",
|
||||
str(SCHEDULER_TMP_ENV_PATH),
|
||||
]
|
||||
|
|
@ -716,6 +748,7 @@ if __name__ == "__main__":
|
|||
logger.warning("No BunkerWeb instance found, skipping nginx configs sending ...")
|
||||
|
||||
try:
|
||||
failed = False
|
||||
if SCHEDULER.apis:
|
||||
# send cache
|
||||
thread = Thread(target=send_nginx_cache)
|
||||
|
|
@ -725,10 +758,7 @@ if __name__ == "__main__":
|
|||
for thread in threads:
|
||||
thread.join()
|
||||
|
||||
if SCHEDULER.send_to_apis("POST", "/reload"):
|
||||
logger.info("Successfully reloaded nginx")
|
||||
else:
|
||||
logger.error("Error while reloading nginx")
|
||||
failed = not SCHEDULER.send_to_apis("POST", "/reload")
|
||||
elif INTEGRATION == "Linux":
|
||||
# Reload nginx
|
||||
logger.info("Reloading nginx ...")
|
||||
|
|
@ -740,14 +770,47 @@ if __name__ == "__main__":
|
|||
check=False,
|
||||
stdout=PIPE,
|
||||
)
|
||||
if proc.returncode == 0:
|
||||
logger.info("Successfully sent reload signal to nginx")
|
||||
else:
|
||||
logger.error(
|
||||
f"Error while reloading nginx - returncode: {proc.returncode} - error: {proc.stdout.decode('utf-8') if proc.stdout else 'no output'}"
|
||||
)
|
||||
failed = proc.returncode != 0
|
||||
else:
|
||||
logger.warning("No BunkerWeb instance found, skipping nginx reload ...")
|
||||
logger.warning("No BunkerWeb instance found, skipping bunkerweb reload ...")
|
||||
|
||||
try:
|
||||
SCHEDULER.db.set_failover(failed)
|
||||
except BaseException as e:
|
||||
logger.error(f"Error while setting failover to true in the database: {e}")
|
||||
|
||||
if failed:
|
||||
logger.error("Error while reloading bunkerweb, failing over to last working configuration ...")
|
||||
if (
|
||||
not FAILOVER_PATH.joinpath("config").is_dir()
|
||||
or not FAILOVER_PATH.joinpath("custom_configs").is_dir()
|
||||
or not FAILOVER_PATH.joinpath("cache").is_dir()
|
||||
):
|
||||
logger.error("No failover configuration found, ignoring failover ...")
|
||||
else:
|
||||
# Failover to last working configuration
|
||||
if SCHEDULER.apis:
|
||||
tmp_threads = [
|
||||
Thread(target=send_nginx_configs, args=(FAILOVER_PATH.joinpath("config"),)),
|
||||
Thread(target=send_nginx_cache, args=(FAILOVER_PATH.joinpath("cache"),)),
|
||||
Thread(target=send_nginx_custom_configs, args=(FAILOVER_PATH.joinpath("custom_configs"),)),
|
||||
]
|
||||
for thread in tmp_threads:
|
||||
thread.start()
|
||||
|
||||
for thread in tmp_threads:
|
||||
thread.join()
|
||||
|
||||
SCHEDULER.send_to_apis("POST", "/reload")
|
||||
else:
|
||||
logger.info("Successfully reloaded bunkerweb")
|
||||
# Update the failover path with the working configuration
|
||||
rmtree(FAILOVER_PATH, ignore_errors=True)
|
||||
FAILOVER_PATH.mkdir(parents=True, exist_ok=True)
|
||||
copytree(CONFIG_PATH, FAILOVER_PATH.joinpath("config"))
|
||||
copytree(CUSTOM_CONFIGS_PATH, FAILOVER_PATH.joinpath("custom_configs"))
|
||||
copytree(CACHE_PATH, FAILOVER_PATH.joinpath("cache"))
|
||||
Thread(target=JOB.cache_dir, args=(FAILOVER_PATH,), kwargs={"job_name": "failover-backup"}).start()
|
||||
except:
|
||||
logger.error(f"Exception while reloading after running jobs once scheduling : {format_exc()}")
|
||||
|
||||
|
|
@ -783,6 +846,8 @@ if __name__ == "__main__":
|
|||
if not HEALTHY_PATH.is_file():
|
||||
HEALTHY_PATH.write_text(datetime.now().isoformat(), encoding="utf-8")
|
||||
|
||||
APPLYING_CHANGES.clear()
|
||||
|
||||
# infinite schedule for the jobs
|
||||
logger.info("Executing job scheduler ...")
|
||||
errors = 0
|
||||
|
|
@ -879,6 +944,7 @@ if __name__ == "__main__":
|
|||
sleep(5)
|
||||
|
||||
if NEED_RELOAD:
|
||||
APPLYING_CHANGES.set()
|
||||
logger.debug(f"Changes: {changes}")
|
||||
SCHEDULER.try_database_readonly(force=True)
|
||||
CHANGES.clear()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
certbot==2.11.0
|
||||
configobj==5.0.8
|
||||
cryptography==42.0.8
|
||||
maxminddb==2.6.1
|
||||
maxminddb==2.6.2
|
||||
python-magic==0.4.27
|
||||
requests==2.32.3
|
||||
schedule==1.2.2
|
||||
|
|
|
|||
|
|
@ -229,76 +229,76 @@ josepy==1.14.0 \
|
|||
# via
|
||||
# acme
|
||||
# certbot
|
||||
maxminddb==2.6.1 \
|
||||
--hash=sha256:03f59f5c06bb54907e74f8a5d5149032a6e14cb2d990e17e4b0446d18195ede6 \
|
||||
--hash=sha256:0855c3532063e16c71b9ca7f624d3061f0e6da03a1e4ff7fabf9253a278b3016 \
|
||||
--hash=sha256:0f5286b5db8065a59cf9e005281c9d74d3839a8cda8e8ee04305d42d5afcc523 \
|
||||
--hash=sha256:103c7c5740a63d42f1062a99c79712d73106b3b0663c4e6c559f502b673c50c8 \
|
||||
--hash=sha256:153ca60a282d5ba1db86eedd27b6bb0e158d0f94682598f9900f20690e01395f \
|
||||
--hash=sha256:16dc122ebaae59922c007bcb9cf2a0621f550392b54f7f5e0171baa111be5a55 \
|
||||
--hash=sha256:17272badaa3e0293858ea9a48fe3e9fe8d6b20cc465a54cd4766d05aeff6ca59 \
|
||||
--hash=sha256:21e93c0d094d167bb96ab49c89df2746d78c99228c5273bd7dc6d11385dd63b3 \
|
||||
--hash=sha256:2319e73cad84bb3897a0cfbe8473a87b0e83b7a69b84118be829cc761a4388ac \
|
||||
--hash=sha256:2396eb49868c2f078ba566359b66249643409dfca1372b5497cef06bf7965c4a \
|
||||
--hash=sha256:242e572b3e132146acd0e2633c00564a8e33cf6de54c060778c618070d109054 \
|
||||
--hash=sha256:24f362eb049109f01dda5adba03d703d1a83e73fa95569ea2bc723a7ecbbea2b \
|
||||
--hash=sha256:2a943e4a0dd59bd6b98ee131f40bdf4efbab8db7667c3dfa9165b1e06ed3b46d \
|
||||
--hash=sha256:2ad27b9a06da43f0192e19e772b3fc01b72a6d231d55e665ec675a235533b0c5 \
|
||||
--hash=sha256:30d66df204847ab114b84b04adf60e91a1dc1a30ab42a3e41337ed10efb4f2ab \
|
||||
--hash=sha256:32571299316c01eecfc364cd5b94cfa2a484ee45b1cb2cd80464d7f666c4be11 \
|
||||
--hash=sha256:33859797f89c2949f86a98a0b89dc577a40561643e78084ad44307bbdc40dd76 \
|
||||
--hash=sha256:39be382e82ecf231869e4c3f628f18b21f032b7bc42f980b75f042c16818b991 \
|
||||
--hash=sha256:3c8db454446d83b65bd605f6093400897a8698de82ca1c20f37494361ee5b6a7 \
|
||||
--hash=sha256:3ce8cdf86cbfb569fe7f33dbef283476d7693e002a4b73195996655067f770bd \
|
||||
--hash=sha256:3eb4711af74a6d8e10e28095c2a18a7ab010826d68665757383c140989f7e075 \
|
||||
--hash=sha256:3f04a217240323caea98adb0eaf0342466656486fc27b18ff53f74414dbaecce \
|
||||
--hash=sha256:416f3fddd1add9a421483b26d24abaf2dd355f3a5afd72923681698d345d99d6 \
|
||||
--hash=sha256:41af38a328cfa94041135753b7ab2dc08863b22535a4295f6e65f72de0a862b9 \
|
||||
--hash=sha256:44d546d6f8ac103c13daf965ac1970a6a32a8b2f33bdbc8a280f87383ce7c5cd \
|
||||
--hash=sha256:45d78c8e527ea90947d04450709032459221011a2d14cf5ac645ca1f76e8e7f2 \
|
||||
--hash=sha256:4774750c744c378653536ad6d5f8e28bcb2566e7e24081e881b00c95b51cad09 \
|
||||
--hash=sha256:4a2a1b713ceea188d066ca676c033f334baad4f41bc1d89640c9795d514b6617 \
|
||||
--hash=sha256:4a75d73d8aaa82718d3553880951d1b7fe8c1cd309a84b992ca7789b832b1de7 \
|
||||
--hash=sha256:4d718bb2379d06e8ca3c4aa09f22634e84fe76db44f66845d7c18c1f0e414fd6 \
|
||||
--hash=sha256:4e21d5ccf34eb1eee14d95c616b7628035953ed4d79ff560188014ae7f1aaaf7 \
|
||||
--hash=sha256:5555698be89fa568b787570911a2aa5c666c335c12dcc5cd8166f96e3155e210 \
|
||||
--hash=sha256:5719b58cfbed4464f89afcbdbaf1eb84f9de805f1716f27c671bf11635ce5458 \
|
||||
--hash=sha256:58a070a18ca6d17d79002b35351fa9373012a98ad5680c0c49d0794c1286d9d9 \
|
||||
--hash=sha256:6acc873145aade367d39f5c2c013eeba1fc7709c1cca8aa9a46dd25db12958ef \
|
||||
--hash=sha256:6c5d591f625e03b0a34df0c7ff81580676397b8335e13ece130c6e39e4a3afb9 \
|
||||
--hash=sha256:6d3790e9ee0157a320b0aa7ddf9f33290f33797608beae604b202a24aaf9db17 \
|
||||
--hash=sha256:81a1070b61e2fabff936d256490924e49c8b54d3f9fa61f32c0c91b83dc11259 \
|
||||
--hash=sha256:86457125adccf5c248d481fc1cd80e77674afeaf45995aed480a3c7e0e118ddc \
|
||||
--hash=sha256:87989f153ce9a0974c69bb0bf26a3cb339c7dfbbfe3330883075543d8ef70fc5 \
|
||||
--hash=sha256:8eb72818e43d2e52e896e72622f41219afe98913eda456ef626fb10a636acca3 \
|
||||
--hash=sha256:940c349e0937e1123f1ae7f213e4a7e90e972cd4501c5898ec70814e4c472747 \
|
||||
--hash=sha256:9ac567627ac141d3e1a797b5696b4e652b1660ddfa6c861f202eed1eb34143ab \
|
||||
--hash=sha256:9b8ef7ed2bbbd8216a0560dd06caafe2fc1d6f9fa18cf46282c6f4a9a3d91b9c \
|
||||
--hash=sha256:9c5aa6d50a30cc733b57afa80cbb51c004a7beac23a6c6a56e3550992faaeac1 \
|
||||
--hash=sha256:9eb6a13e781e2e7a02e88734e29139fb0e5e4024020b146da56202893e425595 \
|
||||
--hash=sha256:a029d2c23b8ad9f4e8316319d79f0d55899aa8e6d69a2bee77d998991256dee0 \
|
||||
--hash=sha256:a467ebf7cec651001a318aab5c9582f6774886e8d2d86aac77db33e5006ea118 \
|
||||
--hash=sha256:ae3c76fbc989eca9b31512ae899528a9dae9092f4c9b7e807ed55b9ff4254ed0 \
|
||||
--hash=sha256:b1090088504c4b45cf1f3ffc32eabd6d5065e56883d910658e5d5f31e80e4be4 \
|
||||
--hash=sha256:b3863e6017b96ee3ae1a6bb7ef0c25cd9013b04cccc1fd27880ab6371cdd1d84 \
|
||||
--hash=sha256:b8e0fa2ec7f58411262ab3edd837d3a1844e6068e128eca222867ad465b97e9d \
|
||||
--hash=sha256:bcc9ac85007ab222838974b084f49bb62531669e793a7730260dec2cf6e34bfd \
|
||||
--hash=sha256:c8f9fcd1bb0e016e7a2ff2341920f99932cd0f573e18bc89e9ad168c9cb93392 \
|
||||
--hash=sha256:c9dd4275749d1d3fb3700df373cd593235ee307f17a3180bad151562e8294a61 \
|
||||
--hash=sha256:cd4afedf6fab1678e5fac0f0cdeb9be2f77fcc07ae1ebc5abe788aec32dd3de8 \
|
||||
--hash=sha256:d0a8b70fcfa0980c0e8501e1506115dbd6f2410436f54161647627430d7cbb66 \
|
||||
--hash=sha256:d44081ec6633a225e051eaf851aa5986aae5f5c8c1f33cf78b3a825c5d0df642 \
|
||||
--hash=sha256:d45a6a5d964182ff083f2ee545d049517e88f0898ab4df3e119582518cd97b64 \
|
||||
--hash=sha256:db8e0a5c1262d43ba5d0f6efb357ba9e5b65b7f3fc982b77a9f543f222a7fca3 \
|
||||
--hash=sha256:e973d98f3bf828a94016d3875cb44e17739ad3957282505c16c68d20cf3a70a1 \
|
||||
--hash=sha256:f117fe0b5bafee78dbd97606dc60bba2160cfe1968484925174d7aadb7a38f37 \
|
||||
--hash=sha256:f11a0899eb671c77dc131c8dd5d6702eb2d7c19952790c87b36ef72d73696bc2 \
|
||||
--hash=sha256:f1481c05b2a7fa909bb48ada037d2c920d7845ea737d9a1e6513ab1c85a64a32 \
|
||||
--hash=sha256:f40c1a145550a297b8c8743d62b8b1bf9fa572b36fa1df9157ea45fed0da9abc \
|
||||
--hash=sha256:f6edc11c4fb4c1ecbfb28cc5da167f7db415c4fabc1aeff0171b06473057e5fb \
|
||||
--hash=sha256:fa43c3783da55ca2a2ed68b97048b63c86ee1462caf32e5f9bfe038db9dac31f \
|
||||
--hash=sha256:fb56115caee4f3beafd2907845dc8f80c633424cbe270a3738f6ba609ff7248e \
|
||||
--hash=sha256:fc3526c587f53dd32a5191e81f4239bb3ead70f56a97936b3427b72e3a5cc55f
|
||||
maxminddb==2.6.2 \
|
||||
--hash=sha256:058ca89789bc1770fe58d02a88272ca91dabeef9f3fe0011fe506484355f1804 \
|
||||
--hash=sha256:05e873eb82281cef6e787bd40bd1d58b2e496a21b3689346f0d0420988b3cbb1 \
|
||||
--hash=sha256:0b281c0eec3601dde1f169a1c04e2615751c66368141aded9f03131fe635450b \
|
||||
--hash=sha256:0b480a31589750da4e36d1ba04b77ee3ac3853ac7b94d63f337b9d4d0403043f \
|
||||
--hash=sha256:12207f0becf3f2bf14e7a4bf86efcaa6e90d665a918915ae228c4e77792d7151 \
|
||||
--hash=sha256:1c096dfd20926c4de7d7fd5b5e75c756eddd4bdac5ab7aafd4bb67d000b13743 \
|
||||
--hash=sha256:1dc2b511c7255f7cbbb01e8ba01ba82e62e9c1213e382d36f9d9b0ee45c2f6b2 \
|
||||
--hash=sha256:20662878bc9514e90b0b4c4eb1a76622ecc7504d012e76bad9cdb7372fc0ef96 \
|
||||
--hash=sha256:28a2eaf9769262c05c486e777016771f3367c843b053c43cd5fde1108755753d \
|
||||
--hash=sha256:28af9470f28fce2ccb945478235f53fb52d98a505653b1bf4028e34df6149a06 \
|
||||
--hash=sha256:2aaefb62f881151960bb67e5aeb302c159a32bd2d623cf72dad688bda1020869 \
|
||||
--hash=sha256:34b6e8d667d724f60d52635f3d959f793ab4e5d57d78b27fe66f02752d8c6b08 \
|
||||
--hash=sha256:38941a38278491bf95e5ca544969782c7ab33326802f6a93816867289c3f6401 \
|
||||
--hash=sha256:3987e103396e925edebbef4877e94515822f63b3b436027a0b164b500622fccd \
|
||||
--hash=sha256:39eab93ddd75fd02f8d5ad6b1bd3f8d894828d91d6f6c1a96bb9e87c34e94aaa \
|
||||
--hash=sha256:47170ec0e1e76787cc5882301c487f495d67f3146318f2f4e2adc281951a96ef \
|
||||
--hash=sha256:485c0778f6801e1437c2efd6e3b964a7ae71c8819f063e0b5460c3267d977040 \
|
||||
--hash=sha256:5662386db91872d5505fde9e7bb0b9530b6aab7a6f3ece7df59a2b43a7b45d17 \
|
||||
--hash=sha256:58bfd2c55c96aaaa7c4996c704edabfb1bd369dfc1592cedf8957a24062178b1 \
|
||||
--hash=sha256:5c7c520d06d335b288d06a00b786cea9b7e023bd588efb1a6ef485e94ccc7244 \
|
||||
--hash=sha256:6a50bc348c699d8f6a5f0aa35e5096515d642ca2f38b944bd71c3dedda3d3588 \
|
||||
--hash=sha256:6fd1a612110ff182a559d8010e7615e5d05ef9d2c234b5f7de124ee8fdf1ecb9 \
|
||||
--hash=sha256:7607e45f7eca991fa34d57c03a791a1dfbe774ddd9250d0f35cdcc6f17142a15 \
|
||||
--hash=sha256:78c3aa70c62be68ace23f819e7f23258545f2bfbd92cd6c33ee398cd261f6b84 \
|
||||
--hash=sha256:7c1220838ba9b0bcdaa0c5846f9da70a2304df2ac255fe518370f8faf8c18316 \
|
||||
--hash=sha256:7cd7f525eb2331cf05181c5ba562cc3edec3de4b41dbb18a5fee9ad24884b499 \
|
||||
--hash=sha256:7cfdf5c29a2739610700b9fea7f8d68ce81dcf30bb8016f1a1853ef889a2624b \
|
||||
--hash=sha256:7d842d32e2620abc894b7d79a5a1007a69df2c6cf279a06b94c9c3913f66f264 \
|
||||
--hash=sha256:7e5a90a1cb0c7fd6226aa44e18a87b26fa85b6eebae36d529d7582f93e8dfbd1 \
|
||||
--hash=sha256:80d20683afe01b4d41bad1c1829f87ab12f3d19c68ec230f83318a2fd13871a7 \
|
||||
--hash=sha256:80d7495565d30260c630afbe74d61522b13dd31ed05b8916003ec5b127109a12 \
|
||||
--hash=sha256:80d7f943f6b8bc437eaae5da778a83d8f38e4b7463756fdee04833e1be0bdea2 \
|
||||
--hash=sha256:8101291e5b92bd272a050c25822a5e30860d453dde16b4fffed9d751f0483a82 \
|
||||
--hash=sha256:826a1858b93b193df7fa71e3caca65c3051db20545df0020444f55c02e8ed2c3 \
|
||||
--hash=sha256:85fc9406f42c1311ce8ea9f2c820db5d7ac687a39ab5d932708dc783607378ef \
|
||||
--hash=sha256:86048ff328793599e584bcc2fc8278c2b7c5d3a4005c70403613449ec93817ef \
|
||||
--hash=sha256:886af3ba4aa26214ff39214565f53152b62a5abdb6ef9e00c76c194dbfd79231 \
|
||||
--hash=sha256:8cb992da535264177b380e7b81943c884d57dcbfad6b3335d7f633967144746e \
|
||||
--hash=sha256:93691c8b4b4c448babb37bedc6f3d51523a3f06ab11bdd171da7ffc4005a7897 \
|
||||
--hash=sha256:96a1fa38322bce1d587bb6ce39a0e6ca4c1b824f48fbc5739a5ec507f63aa889 \
|
||||
--hash=sha256:9a2671e8f4161130803cf226cd9cb8b93ec5c4b2493f83a902986177052d95d3 \
|
||||
--hash=sha256:9dccd7a438f81e3df84dfc31a75af4c8d29adefb6082329385bfde604c9ea01b \
|
||||
--hash=sha256:a74b60cdc61a69b967ec44201c6259fbc48ef2eab2e885fbdc50ec1accaad545 \
|
||||
--hash=sha256:a771df92e599ad867c16ae4acb08cc3763c9d1028f4ca772c0571da97f7f86d2 \
|
||||
--hash=sha256:aa8cb54b01a29a23a0ea6659fbb38deec6f35453588c5decdbf8669feb53b624 \
|
||||
--hash=sha256:add1e55620033516c5f0734b1d9d03848859192d9f3825aabe720dfa8a783958 \
|
||||
--hash=sha256:b0a3b9cab1a94cc633df3da85c6567f0188f10165e3338ec9a6c421de9fe53b9 \
|
||||
--hash=sha256:b31ecf3083b78c77624783bfdf6177e6ac73ae14684ef182855eb5569bc78e7c \
|
||||
--hash=sha256:b4d9cd7ddd02ee123a44d0d7821166d31540ea85352deb06b29d55e802f32781 \
|
||||
--hash=sha256:c9e9e893f7c0fa44cfdd5ab819a07d93f63ee398c28b792cedd50b94dcfea7c0 \
|
||||
--hash=sha256:cd4530b9604d66cfa5e37eb94c671e54feff87769f8ba7fa997cce959e0cb241 \
|
||||
--hash=sha256:d0970b661c4fac6624b9128057ed5fe35a2d95aa60359272289cd4c7207c9a6d \
|
||||
--hash=sha256:d15414d251513748cb646d284a2829a5f4c69d8c90963a6e6da53a1a6d0accf7 \
|
||||
--hash=sha256:d32266792b349f5507b0369d3277d45318fcd346a16dcc98b484aadc208e4d74 \
|
||||
--hash=sha256:d8ccca5327cb4e706f669456ec6d556badfa92c0fdacd57a15076f3cdc061560 \
|
||||
--hash=sha256:dc9f1203eb2b139252aa08965960fe13c36cc8b80b536490b94b05c31aa1fca9 \
|
||||
--hash=sha256:dd90c3798e6c347d48d5d9a9c95dc678b52a5a965f1fb72152067fdf52b994da \
|
||||
--hash=sha256:e1e40449bd278fdca1f351df442f391e72fd3d98b054ccac1672f27d70210642 \
|
||||
--hash=sha256:e2b85ffc9fb2e192321c2f0b34d0b291b8e82de6e51a6ec7534645663678e835 \
|
||||
--hash=sha256:e63649a82926f1d93acdd3df5f7be66dc9473653350afe73f365bb25e5b34368 \
|
||||
--hash=sha256:e9013076deca5d136c260510cd05e82ec2b4ddb9476d63e2180a13ddfd305c3e \
|
||||
--hash=sha256:eacd65e38bdf4efdf42bbc15cfa734b09eb818ecfef76b7b36e64be382be4c83 \
|
||||
--hash=sha256:eb534333f5fd7180e35c0207b3d95d621e4b9be3b8c1709995d0feb6c752b6f4 \
|
||||
--hash=sha256:ebf9fdf8a8e55862aabb8b2c34a4af31a8a5b686007288eeb561fa20ef348378 \
|
||||
--hash=sha256:ecce0b2d125691e2311f94dbd564c2d61c36c5033d082919431a21e6c694fa3f \
|
||||
--hash=sha256:eef1c26210155c7b94c4ca28fef65eb44a5ca1584427b1fbdeec1cd3c81e25c5 \
|
||||
--hash=sha256:f2e326a99eaa924ff2fb09d6e44127983a43016228e7780888f15e9ba171d7b3 \
|
||||
--hash=sha256:f412a54f87ef9083911c334267188d3d1b14f2591eac94b94ca32528f21d5f25 \
|
||||
--hash=sha256:fb38aa94e76a87785b654c035f9f3ee39b74a98e9beea9a10b1aa62abdcc4cbd
|
||||
# via -r requirements.in
|
||||
parsedatetime==2.6 \
|
||||
--hash=sha256:4cb368fbb18a0b7231f4d76119165451c8d2e35951455dfee97c62a87b04d455 \
|
||||
|
|
@ -334,7 +334,9 @@ pytz==2024.1 \
|
|||
requests==2.32.3 \
|
||||
--hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 \
|
||||
--hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6
|
||||
# via acme
|
||||
# via
|
||||
# -r requirements.in
|
||||
# acme
|
||||
schedule==1.2.2 \
|
||||
--hash=sha256:5bef4a2a0183abf44046ae0d164cadcac21b1db011bdd8102e4a0c1e91e06a7d
|
||||
# via importlib-metadata
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.3-alpine3.19@sha256:ef097620baf1272e38264207003b0982285da3236a20ed829bf6bbf1e85fe3cb as builder
|
||||
FROM python:3.12.4-alpine3.19@sha256:ef3397d09070efd36583e83d2619cf8006158641e5b6b629d4d92a9778f5aa1c as builder
|
||||
|
||||
# Export var for specific actions on linux/arm/v7
|
||||
ARG TARGETPLATFORM
|
||||
|
|
@ -34,7 +34,7 @@ COPY src/common/templates templates
|
|||
COPY src/ui ui
|
||||
COPY src/VERSION VERSION
|
||||
|
||||
FROM python:3.12.3-alpine3.19@sha256:ef097620baf1272e38264207003b0982285da3236a20ed829bf6bbf1e85fe3cb
|
||||
FROM python:3.12.4-alpine3.19@sha256:ef3397d09070efd36583e83d2619cf8006158641e5b6b629d4d92a9778f5aa1c
|
||||
|
||||
# Set default umask to prevent huge recursive chmod increasing the final image size
|
||||
RUN umask 027
|
||||
|
|
|
|||
270
src/ui/main.py
270
src/ui/main.py
|
|
@ -94,72 +94,80 @@ sbin_nginx_path = Path(sep, "usr", "sbin", "nginx")
|
|||
# Flask app
|
||||
app = Flask(__name__, static_url_path="/", static_folder="static", template_folder="templates")
|
||||
|
||||
PROXY_NUMBERS = int(getenv("PROXY_NUMBERS", "1"))
|
||||
app.wsgi_app = ReverseProxied(app.wsgi_app, x_for=PROXY_NUMBERS, x_proto=PROXY_NUMBERS, x_host=PROXY_NUMBERS, x_prefix=PROXY_NUMBERS)
|
||||
app.logger = setup_logger("UI")
|
||||
with app.app_context():
|
||||
PROXY_NUMBERS = int(getenv("PROXY_NUMBERS", "1"))
|
||||
app.wsgi_app = ReverseProxied(app.wsgi_app, x_for=PROXY_NUMBERS, x_proto=PROXY_NUMBERS, x_host=PROXY_NUMBERS, x_prefix=PROXY_NUMBERS)
|
||||
app.logger = setup_logger("UI")
|
||||
|
||||
FLASK_SECRET = getenv("FLASK_SECRET")
|
||||
FLASK_SECRET = getenv("FLASK_SECRET")
|
||||
|
||||
if not FLASK_SECRET:
|
||||
if not TMP_DIR.joinpath(".flask_secret").is_file():
|
||||
app.logger.error("The .flask_secret file is missing")
|
||||
stop(1)
|
||||
FLASK_SECRET = TMP_DIR.joinpath(".flask_secret").read_text(encoding="utf-8").strip()
|
||||
if not FLASK_SECRET:
|
||||
if not TMP_DIR.joinpath(".flask_secret").is_file():
|
||||
app.logger.error("The .flask_secret file is missing")
|
||||
stop(1)
|
||||
FLASK_SECRET = TMP_DIR.joinpath(".flask_secret").read_text(encoding="utf-8").strip()
|
||||
|
||||
app.config["SECRET_KEY"] = FLASK_SECRET
|
||||
app.config["SECRET_KEY"] = FLASK_SECRET
|
||||
app.config["SESSION_COOKIE_NAME"] = "__Host-bw_ui_session"
|
||||
app.config["SESSION_COOKIE_PATH"] = "/"
|
||||
app.config["SESSION_COOKIE_SECURE"] = True # Required for __Host- prefix
|
||||
app.config["SESSION_COOKIE_HTTPONLY"] = True # Recommended for security
|
||||
app.config["SESSION_COOKIE_SAMESITE"] = "Lax" # Or 'Strict' for stricter settings
|
||||
app.config["PERMANENT_SESSION_LIFETIME"] = timedelta(minutes=30)
|
||||
app.config["PREFERRED_URL_SCHEME"] = "https"
|
||||
|
||||
login_manager = LoginManager()
|
||||
login_manager.session_protection = "strong"
|
||||
login_manager.init_app(app)
|
||||
login_manager.login_view = "login"
|
||||
login_manager.anonymous_user = AnonymousUser
|
||||
PLUGIN_KEYS = ["id", "name", "description", "version", "stream", "settings"]
|
||||
login_manager = LoginManager()
|
||||
login_manager.session_protection = "strong"
|
||||
login_manager.init_app(app)
|
||||
login_manager.login_view = "login"
|
||||
login_manager.anonymous_user = AnonymousUser
|
||||
PLUGIN_KEYS = ["id", "name", "description", "version", "stream", "settings"]
|
||||
|
||||
INTEGRATION = get_integration()
|
||||
INTEGRATION = get_integration()
|
||||
|
||||
docker_client = None
|
||||
kubernetes_client = None
|
||||
if INTEGRATION in ("Docker", "Swarm", "Autoconf"):
|
||||
try:
|
||||
docker_client: DockerClient = DockerClient(base_url=getenv("DOCKER_HOST", "unix:///var/run/docker.sock"))
|
||||
except (docker_APIError, DockerException):
|
||||
app.logger.warning("No docker host found")
|
||||
elif INTEGRATION == "Kubernetes":
|
||||
kube_config.load_incluster_config()
|
||||
kubernetes_client = kube_client.CoreV1Api()
|
||||
|
||||
db = Database(app.logger, ui=True, log=False)
|
||||
|
||||
USER_PASSWORD_RX = re_compile(r"^(?=.*?\p{Lowercase_Letter})(?=.*?\p{Uppercase_Letter})(?=.*?\d)(?=.*?[ !\"#$%&'()*+,./:;<=>?@[\\\]^_`{|}~-]).{8,}$")
|
||||
|
||||
bw_version = get_version()
|
||||
|
||||
if not TMP_DIR.joinpath(".ui.json").is_file():
|
||||
TMP_DIR.joinpath(".ui.json").write_text("{}", encoding="utf-8")
|
||||
|
||||
docker_client = None
|
||||
kubernetes_client = None
|
||||
if INTEGRATION in ("Docker", "Swarm", "Autoconf"):
|
||||
try:
|
||||
docker_client: DockerClient = DockerClient(base_url=getenv("DOCKER_HOST", "unix:///var/run/docker.sock"))
|
||||
except (docker_APIError, DockerException):
|
||||
app.logger.warning("No docker host found")
|
||||
elif INTEGRATION == "Kubernetes":
|
||||
kube_config.load_incluster_config()
|
||||
kubernetes_client = kube_client.CoreV1Api()
|
||||
app.config.update(
|
||||
INSTANCES=Instances(docker_client, kubernetes_client, INTEGRATION, db),
|
||||
CONFIG=Config(db),
|
||||
CONFIGFILES=ConfigFiles(),
|
||||
WTF_CSRF_SSL_STRICT=False,
|
||||
SEND_FILE_MAX_AGE_DEFAULT=86400,
|
||||
SCRIPT_NONCE=sha256(urandom(32)).hexdigest(),
|
||||
DB=db,
|
||||
UI_TEMPLATES=get_ui_templates(),
|
||||
)
|
||||
except FileNotFoundError as e:
|
||||
app.logger.error(repr(e), e.filename)
|
||||
stop(1)
|
||||
|
||||
db = Database(app.logger, ui=True, log=False)
|
||||
plugin_id_rx = re_compile(r"^[\w_-]{1,64}$")
|
||||
|
||||
USER_PASSWORD_RX = re_compile(r"^(?=.*?\p{Lowercase_Letter})(?=.*?\p{Uppercase_Letter})(?=.*?\d)(?=.*?[ !\"#$%&'()*+,./:;<=>?@[\\\]^_`{|}~-]).{8,}$")
|
||||
# Declare functions for jinja2
|
||||
app.jinja_env.globals.update(check_settings=check_settings)
|
||||
|
||||
bw_version = get_version()
|
||||
|
||||
if not TMP_DIR.joinpath(".ui.json").is_file():
|
||||
TMP_DIR.joinpath(".ui.json").write_text("{}", encoding="utf-8")
|
||||
|
||||
try:
|
||||
app.config.update(
|
||||
INSTANCES=Instances(docker_client, kubernetes_client, INTEGRATION, db),
|
||||
CONFIG=Config(db),
|
||||
CONFIGFILES=ConfigFiles(),
|
||||
WTF_CSRF_SSL_STRICT=False,
|
||||
SEND_FILE_MAX_AGE_DEFAULT=86400,
|
||||
SCRIPT_NONCE=sha256(urandom(32)).hexdigest(),
|
||||
DB=db,
|
||||
UI_TEMPLATES=get_ui_templates(),
|
||||
)
|
||||
except FileNotFoundError as e:
|
||||
app.logger.error(repr(e), e.filename)
|
||||
stop(1)
|
||||
|
||||
plugin_id_rx = re_compile(r"^[\w_-]{1,64}$")
|
||||
|
||||
# Declare functions for jinja2
|
||||
app.jinja_env.globals.update(check_settings=check_settings)
|
||||
|
||||
# CSRF protection
|
||||
csrf = CSRFProtect()
|
||||
csrf.init_app(app)
|
||||
# CSRF protection
|
||||
csrf = CSRFProtect()
|
||||
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})))?)$")
|
||||
|
|
@ -224,7 +232,7 @@ def manage_bunkerweb(method: str, *args, operation: str = "reloads", is_draft: b
|
|||
elif operation == "restart":
|
||||
operation = app.config["INSTANCES"].restart_instance(args[0])
|
||||
elif not error:
|
||||
operation = "The scheduler will be in charge of reloading the instances."
|
||||
operation = "The scheduler will be in charge of applying the changes."
|
||||
|
||||
if operation:
|
||||
if isinstance(operation, list):
|
||||
|
|
@ -372,13 +380,24 @@ def inject_variables():
|
|||
ui_data = get_ui_data()
|
||||
metadata = app.config["DB"].get_metadata()
|
||||
|
||||
curr_changes = app.config["DB"].check_changes()
|
||||
changes_ongoing = any(app.config["DB"].check_changes().values())
|
||||
|
||||
if ui_data.get("PRO_LOADING") and not any(curr_changes.values()):
|
||||
if ui_data.get("PRO_LOADING") and not changes_ongoing:
|
||||
ui_data["PRO_LOADING"] = False
|
||||
with LOCK:
|
||||
TMP_DATA_FILE.write_text(dumps(ui_data), encoding="utf-8")
|
||||
|
||||
if not changes_ongoing and metadata["failover"]:
|
||||
flash(
|
||||
"The last changes could not be applied because it creates a configuration error on NGINX, please check the logs for more information. The configured fell back to the last working one.",
|
||||
"error",
|
||||
)
|
||||
elif not changes_ongoing and not metadata["failover"] and ui_data.get("CONFIG_CHANGED", False):
|
||||
flash("The last changes have been applied successfully.", "success")
|
||||
ui_data["CONFIG_CHANGED"] = False
|
||||
with LOCK:
|
||||
TMP_DATA_FILE.write_text(dumps(ui_data), encoding="utf-8")
|
||||
|
||||
# check that is value is in tuple
|
||||
return dict(
|
||||
script_nonce=app.config["SCRIPT_NONCE"],
|
||||
|
|
@ -430,8 +449,7 @@ def handle_csrf_error(_):
|
|||
:param e: The exception object
|
||||
:return: A template with the error message and a 401 status code.
|
||||
"""
|
||||
session.clear()
|
||||
logout_user()
|
||||
logout()
|
||||
flash("Wrong CSRF token !", "error")
|
||||
if not current_user:
|
||||
return render_template("setup.html"), 403
|
||||
|
|
@ -529,7 +547,7 @@ def check():
|
|||
|
||||
@app.route("/setup", methods=["GET", "POST"])
|
||||
def setup():
|
||||
db_config = app.config["CONFIG"].get_config(methods=False)
|
||||
db_config = app.config["CONFIG"].get_config(methods=False, filtered_settings=("SERVER_NAME", "USE_UI", "UI_HOST"))
|
||||
|
||||
for server_name in db_config["SERVER_NAME"].split(" "):
|
||||
if db_config.get(f"{server_name}_USE_UI", "no") == "yes":
|
||||
|
|
@ -671,8 +689,8 @@ def home():
|
|||
if r and r.status_code == 200:
|
||||
remote_version = basename(r.url).strip().replace("v", "")
|
||||
|
||||
config = app.config["CONFIG"].get_config(with_drafts=True)
|
||||
override_instances = config["OVERRIDE_INSTANCES"]["value"] != ""
|
||||
config = app.config["CONFIG"].get_config(with_drafts=True, filtered_settings=("SERVER_NAME", "OVERRIDE_INSTANCES"))
|
||||
override_instances = config.get("OVERRIDE_INSTANCES", {"value": ""})["value"] != ""
|
||||
instances = app.config["INSTANCES"].get_instances(override_instances=override_instances)
|
||||
|
||||
instance_health_count = 0
|
||||
|
|
@ -735,9 +753,9 @@ def account():
|
|||
variable = {}
|
||||
variable["PRO_LICENSE_KEY"] = request.form["license"]
|
||||
|
||||
error = app.config["CONFIG"].check_variables(variable)
|
||||
variable = app.config["CONFIG"].check_variables(variable, {"PRO_LICENSE_KEY": request.form["license"]})
|
||||
|
||||
if error:
|
||||
if not variable:
|
||||
return redirect_flash_error("The license key variable checks returned error", "account", True)
|
||||
|
||||
# Force job to contact PRO API
|
||||
|
|
@ -761,6 +779,7 @@ def account():
|
|||
|
||||
ui_data = get_ui_data()
|
||||
ui_data["PRO_LOADING"] = True
|
||||
ui_data["CONFIG_CHANGED"] = True
|
||||
|
||||
if any(curr_changes.values()):
|
||||
ui_data["RELOADING"] = True
|
||||
|
|
@ -792,8 +811,7 @@ def account():
|
|||
|
||||
username = request.form["admin_username"]
|
||||
|
||||
session.clear()
|
||||
logout_user()
|
||||
logout()
|
||||
|
||||
if request.form["operation"] == "password":
|
||||
|
||||
|
|
@ -810,8 +828,7 @@ def account():
|
|||
|
||||
password = request.form["admin_password"]
|
||||
|
||||
session.clear()
|
||||
logout_user()
|
||||
logout()
|
||||
|
||||
if request.form["operation"] == "totp":
|
||||
|
||||
|
|
@ -908,8 +925,8 @@ def instances():
|
|||
)
|
||||
|
||||
# Display instances
|
||||
config = app.config["CONFIG"].get_config(global_only=True)
|
||||
override_instances = config["OVERRIDE_INSTANCES"]["value"] != ""
|
||||
config = app.config["CONFIG"].get_config(global_only=True, methods=False, filtered_settings=("OVERRIDE_INSTANCES",))
|
||||
override_instances = config.get("OVERRIDE_INSTANCES", "") != ""
|
||||
instances = app.config["INSTANCES"].get_instances(override_instances=override_instances)
|
||||
return render_template("instances.html", title="Instances", instances=instances, username=current_user.get_id())
|
||||
|
||||
|
|
@ -946,7 +963,7 @@ def services():
|
|||
if "SERVER_NAME" not in variables:
|
||||
variables["SERVER_NAME"] = variables["OLD_SERVER_NAME"]
|
||||
|
||||
config = app.config["CONFIG"].get_config(methods=True, with_drafts=True)
|
||||
config = app.config["DB"].get_config(methods=True, with_drafts=True)
|
||||
server_name = variables["SERVER_NAME"].split(" ")[0]
|
||||
was_draft = config.get(f"{server_name}_IS_DRAFT", {"value": "no"})["value"] == "yes"
|
||||
operation = request.form["operation"]
|
||||
|
|
@ -980,16 +997,7 @@ def services():
|
|||
del variables["OLD_SERVER_NAME"]
|
||||
|
||||
# Edit check fields and remove already existing ones
|
||||
for variable, value in deepcopy(variables).items():
|
||||
if variable == "IS_DRAFT" or variable.endswith("SCHEMA"):
|
||||
del variables[variable]
|
||||
continue
|
||||
|
||||
if value == "on":
|
||||
value = "yes"
|
||||
elif value == "off":
|
||||
value = "no"
|
||||
|
||||
for variable, value in variables.copy().items():
|
||||
if (
|
||||
variable in variables
|
||||
and variable != "SERVER_NAME"
|
||||
|
|
@ -997,6 +1005,8 @@ def services():
|
|||
):
|
||||
del variables[variable]
|
||||
|
||||
variables = app.config["CONFIG"].check_variables(variables, config)
|
||||
|
||||
if (
|
||||
was_draft == is_draft
|
||||
and request.form["operation"] == "edit"
|
||||
|
|
@ -1009,26 +1019,19 @@ def services():
|
|||
elif request.form["operation"] == "new" and not variables:
|
||||
return redirect_flash_error("The service was not created because all values had the default value.", "services", True)
|
||||
|
||||
error = app.config["CONFIG"].check_variables(variables)
|
||||
|
||||
if error:
|
||||
error_message("The config variable checks returned error")
|
||||
|
||||
# Delete
|
||||
if request.form["operation"] == "delete":
|
||||
|
||||
is_request_params(["SERVER_NAME"], "services", True)
|
||||
|
||||
error = app.config["CONFIG"].check_variables({"SERVER_NAME": request.form["SERVER_NAME"]})
|
||||
variables = app.config["CONFIG"].check_variables({"SERVER_NAME": request.form["SERVER_NAME"]}, config)
|
||||
|
||||
if error:
|
||||
if not variables:
|
||||
error_message(f"Error while deleting the service {request.form['SERVER_NAME']}")
|
||||
|
||||
if config.get(f"{request.form['SERVER_NAME'].split(' ')[0]}_SERVER_NAME", {"method": "scheduler"})["method"] != "ui":
|
||||
return redirect_flash_error("The service cannot be deleted because it has not been created with the UI.", "services", True)
|
||||
|
||||
error = 0
|
||||
|
||||
curr_changes = app.config["DB"].check_changes()
|
||||
|
||||
old_server_name = request.form.get("OLD_SERVER_NAME", "")
|
||||
|
|
@ -1048,17 +1051,20 @@ def services():
|
|||
threaded=threaded,
|
||||
)
|
||||
|
||||
ui_data = get_ui_data()
|
||||
|
||||
if any(curr_changes.values()):
|
||||
ui_data = get_ui_data()
|
||||
ui_data["RELOADING"] = True
|
||||
ui_data["LAST_RELOAD"] = time()
|
||||
Thread(target=update_services, args=(True,)).start()
|
||||
|
||||
with LOCK:
|
||||
TMP_DATA_FILE.write_text(dumps(ui_data), encoding="utf-8")
|
||||
else:
|
||||
update_services()
|
||||
|
||||
ui_data["CONFIG_CHANGED"] = True
|
||||
|
||||
with LOCK:
|
||||
TMP_DATA_FILE.write_text(dumps(ui_data), encoding="utf-8")
|
||||
|
||||
message = ""
|
||||
|
||||
if request.form["operation"] == "new":
|
||||
|
|
@ -1072,7 +1078,7 @@ def services():
|
|||
|
||||
# Display services
|
||||
services = []
|
||||
global_config = app.config["CONFIG"].get_config(with_drafts=True)
|
||||
global_config = app.config["DB"].get_config(methods=True, with_drafts=True)
|
||||
service_names = global_config["SERVER_NAME"]["value"].split(" ")
|
||||
for service in service_names:
|
||||
service_settings = []
|
||||
|
|
@ -1132,30 +1138,19 @@ def global_config():
|
|||
del variables["csrf_token"]
|
||||
|
||||
# Edit check fields and remove already existing ones
|
||||
config = app.config["CONFIG"].get_config(methods=True, with_drafts=True)
|
||||
config = app.config["DB"].get_config(methods=True, with_drafts=True)
|
||||
services = config["SERVER_NAME"]["value"].split(" ")
|
||||
for variable, value in variables.copy().items():
|
||||
if variable in ("AUTOCONF_MODE", "SWARM_MODE", "KUBERNETES_MODE", "SERVER_NAME", "IS_LOADING", "IS_DRAFT") or variable.endswith("SCHEMA"):
|
||||
del variables[variable]
|
||||
continue
|
||||
|
||||
if value == "on":
|
||||
value = "yes"
|
||||
elif value == "off":
|
||||
value = "no"
|
||||
|
||||
setting = config.get(variable, {"value": None, "global": True})
|
||||
if setting["global"] and value == setting["value"]:
|
||||
del variables[variable]
|
||||
continue
|
||||
|
||||
variables = app.config["CONFIG"].check_variables(variables, config)
|
||||
|
||||
if not variables:
|
||||
return redirect_flash_error("The global configuration was not edited because no values were changed.", "global_config", True)
|
||||
|
||||
error = app.config["CONFIG"].check_variables(variables)
|
||||
|
||||
if error:
|
||||
return redirect_flash_error("The global configuration variable checks returned error", "global_config", True)
|
||||
|
||||
for variable, value in variables.copy().items():
|
||||
for service in services:
|
||||
setting = config.get(f"{service}_{variable}", None)
|
||||
|
|
@ -1181,6 +1176,8 @@ def global_config():
|
|||
else:
|
||||
update_global_config()
|
||||
|
||||
ui_data["CONFIG_CHANGED"] = True
|
||||
|
||||
with LOCK:
|
||||
TMP_DATA_FILE.write_text(dumps(ui_data), encoding="utf-8")
|
||||
|
||||
|
|
@ -1197,7 +1194,7 @@ def global_config():
|
|||
)
|
||||
|
||||
# Display global config
|
||||
global_config = app.config["CONFIG"].get_config(global_only=True)
|
||||
global_config = app.config["DB"].get_config(global_only=True, methods=True)
|
||||
return render_template("global_config.html", username=current_user.get_id(), global_config=global_config, dumped_global_config=dumps(global_config))
|
||||
|
||||
|
||||
|
|
@ -1304,6 +1301,11 @@ def configs():
|
|||
app.logger.error(f"Could not save custom configs: {error}")
|
||||
return redirect_flash_error("Couldn't save custom configs", "configs", True)
|
||||
|
||||
ui_data = get_ui_data()
|
||||
ui_data["CONFIG_CHANGED"] = True
|
||||
with LOCK:
|
||||
TMP_DATA_FILE.write_text(dumps(ui_data), encoding="utf-8")
|
||||
|
||||
flash(operation)
|
||||
|
||||
return redirect(url_for("loading", next=url_for("configs")))
|
||||
|
|
@ -1314,7 +1316,7 @@ def configs():
|
|||
path_to_dict(
|
||||
join(sep, "etc", "bunkerweb", "configs"),
|
||||
db_data=db_configs,
|
||||
services=app.config["CONFIG"].get_config(methods=False).get("SERVER_NAME", "").split(" "),
|
||||
services=app.config["CONFIG"].get_config(global_only=True, methods=False, filtered_settings=("SERVER_NAME",)).get("SERVER_NAME", "").split(" "),
|
||||
)
|
||||
],
|
||||
username=current_user.get_id(),
|
||||
|
|
@ -1729,7 +1731,7 @@ def custom_plugin(plugin: str):
|
|||
if plugin_id is None:
|
||||
return error_message("Plugin not found"), 404
|
||||
|
||||
config = app.config["CONFIG"].get_config(methods=False)
|
||||
config = app.config["DB"].get_config()
|
||||
|
||||
# Check if we are using metrics
|
||||
for service in config.get("SERVER_NAME", "").split(" "):
|
||||
|
|
@ -1839,7 +1841,7 @@ def cache():
|
|||
join(sep, "var", "cache", "bunkerweb"),
|
||||
is_cache=True,
|
||||
db_data=app.config["DB"].get_jobs_cache_files(),
|
||||
services=app.config["CONFIG"].get_config(methods=False).get("SERVER_NAME", "").split(" "),
|
||||
services=app.config["CONFIG"].get_config(global_only=True, methods=False, filtered_settings=("SERVER_NAME",)).get("SERVER_NAME", "").split(" "),
|
||||
)
|
||||
],
|
||||
username=current_user.get_id(),
|
||||
|
|
@ -1849,8 +1851,8 @@ def cache():
|
|||
@app.route("/logs", methods=["GET"])
|
||||
@login_required
|
||||
def logs():
|
||||
config = app.config["CONFIG"].get_config(with_drafts=True)
|
||||
override_instances = config["OVERRIDE_INSTANCES"]["value"] != ""
|
||||
config = app.config["CONFIG"].get_config(global_only=True, methods=False, filtered_settings=("OVERRIDE_INSTANCES",))
|
||||
override_instances = config.get("OVERRIDE_INSTANCES", "") != ""
|
||||
instances = app.config["INSTANCES"].get_instances(override_instances=override_instances)
|
||||
return render_template("logs.html", instances=instances, username=current_user.get_id())
|
||||
|
||||
|
|
@ -1945,7 +1947,11 @@ def logs_linux():
|
|||
error_type = (
|
||||
"error"
|
||||
if "[error]" in log_lower or "[crit]" in log_lower or "[alert]" in log_lower or "❌" in log_lower
|
||||
else (("warn" if "[warn]" in log_lower or "⚠️" in log_lower else ("info" if "[info]" in log_lower or "ℹ️" in log_lower else "message")))
|
||||
else (
|
||||
"emerg"
|
||||
if "[emerg]" in log_lower
|
||||
else ("warn" if "[warn]" in log_lower or "⚠️" in log_lower else ("info" if "[info]" in log_lower or "ℹ️" in log_lower else "message"))
|
||||
)
|
||||
)
|
||||
|
||||
logs.append(
|
||||
|
|
@ -2071,7 +2077,11 @@ def logs_container(container_id):
|
|||
"type": (
|
||||
"error"
|
||||
if "[error]" in log_lower or "[crit]" in log_lower or "[alert]" in log_lower or "❌" in log_lower
|
||||
else ("warn" if "[warn]" in log_lower or "⚠️" in log_lower else ("info" if "[info]" in log_lower or "ℹ️" in log_lower else "message"))
|
||||
else (
|
||||
"emerg"
|
||||
if "[emerg]" in log_lower
|
||||
else ("warn" if "[warn]" in log_lower or "⚠️" in log_lower else ("info" if "[info]" in log_lower or "ℹ️" in log_lower else "message"))
|
||||
)
|
||||
),
|
||||
}
|
||||
)
|
||||
|
|
@ -2120,7 +2130,25 @@ def bans():
|
|||
return redirect_flash_error("Database is in read-only mode", "bans")
|
||||
|
||||
redis_client = None
|
||||
db_config = app.config["CONFIG"].get_config(methods=False)
|
||||
db_config = app.config["CONFIG"].get_config(
|
||||
global_only=True,
|
||||
methods=False,
|
||||
filtered_settings=(
|
||||
"USE_REDIS",
|
||||
"REDIS_HOST",
|
||||
"REDIS_PORT",
|
||||
"REDIS_DB",
|
||||
"REDIS_TIMEOUT",
|
||||
"REDIS_KEEPALIVE_POOL",
|
||||
"REDIS_SSL",
|
||||
"REDIS_USERNAME",
|
||||
"REDIS_PASSWORD",
|
||||
"REDIS_SENTINEL_HOSTS",
|
||||
"REDIS_SENTINEL_USERNAME",
|
||||
"REDIS_SENTINEL_PASSWORD",
|
||||
"REDIS_SENTINEL_MASTER",
|
||||
),
|
||||
)
|
||||
use_redis = db_config.get("USE_REDIS", "no") == "yes"
|
||||
redis_host = db_config.get("REDIS_HOST")
|
||||
if use_redis and redis_host:
|
||||
|
|
|
|||
|
|
@ -145,9 +145,9 @@ markupsafe==2.1.5 \
|
|||
# jinja2
|
||||
# werkzeug
|
||||
# wtforms
|
||||
packaging==24.0 \
|
||||
--hash=sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5 \
|
||||
--hash=sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9
|
||||
packaging==24.1 \
|
||||
--hash=sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002 \
|
||||
--hash=sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124
|
||||
# via gunicorn
|
||||
pyotp==2.9.0 \
|
||||
--hash=sha256:346b6642e0dbdde3b4ff5a930b664ca82abfa116356ed48cc42c7d6590d36f63 \
|
||||
|
|
@ -258,9 +258,9 @@ soupsieve==2.5 \
|
|||
--hash=sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690 \
|
||||
--hash=sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7
|
||||
# via beautifulsoup4
|
||||
typing-extensions==4.12.1 \
|
||||
--hash=sha256:6024b58b69089e5a89c347397254e35f1bf02a907728ec7fee9bf0fe837d203a \
|
||||
--hash=sha256:915f5e35ff76f56588223f15fdd5938f9a1cf9195c0de25130c627e4d597f6d1
|
||||
typing-extensions==4.12.2 \
|
||||
--hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \
|
||||
--hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8
|
||||
# via qrcode
|
||||
werkzeug==3.0.3 \
|
||||
--hash=sha256:097e5bfda9f0aba8da6b8545146def481d06aa7d3266e7448e2cccf67dd8bd18 \
|
||||
|
|
|
|||
|
|
@ -78,7 +78,13 @@ class Config:
|
|||
def get_settings(self) -> dict:
|
||||
return self.__settings
|
||||
|
||||
def get_config(self, global_only: bool = False, methods: bool = True, with_drafts: bool = False) -> dict:
|
||||
def get_config(
|
||||
self,
|
||||
global_only: bool = False,
|
||||
methods: bool = True,
|
||||
with_drafts: bool = False,
|
||||
filtered_settings: Optional[Union[List[str], Set[str], Tuple[str]]] = None,
|
||||
) -> dict:
|
||||
"""Get the nginx variables env file and returns it as a dict
|
||||
|
||||
Returns
|
||||
|
|
@ -86,7 +92,7 @@ class Config:
|
|||
dict
|
||||
The nginx variables env file as a dict
|
||||
"""
|
||||
return self.__db.get_config(global_only=global_only, methods=methods, with_drafts=with_drafts)
|
||||
return self.__db.get_non_default_settings(global_only=global_only, methods=methods, with_drafts=with_drafts, filtered_settings=filtered_settings)
|
||||
|
||||
def get_services(self, methods: bool = True, with_drafts: bool = False) -> list[dict]:
|
||||
"""Get nginx's services
|
||||
|
|
@ -98,7 +104,7 @@ class Config:
|
|||
"""
|
||||
return self.__db.get_services_settings(methods=methods, with_drafts=with_drafts)
|
||||
|
||||
def check_variables(self, variables: dict) -> int:
|
||||
def check_variables(self, variables: dict, config: dict) -> dict:
|
||||
"""Testify that the variables passed are valid
|
||||
|
||||
Parameters
|
||||
|
|
@ -111,32 +117,44 @@ class Config:
|
|||
int
|
||||
Return the error code
|
||||
"""
|
||||
error = 0
|
||||
plugins_settings = self.get_plugins_settings()
|
||||
for k, v in variables.items():
|
||||
for k, v in variables.copy().items():
|
||||
check = False
|
||||
|
||||
if k.endswith("SCHEMA"):
|
||||
variables.pop(k)
|
||||
continue
|
||||
|
||||
if k in plugins_settings:
|
||||
setting = k
|
||||
else:
|
||||
setting = k[0 : k.rfind("_")] # noqa: E203
|
||||
if setting not in plugins_settings or "multiple" not in plugins_settings[setting]:
|
||||
error = 1
|
||||
flash(f"Variable {k} is not valid.", "error")
|
||||
variables.pop(k)
|
||||
continue
|
||||
|
||||
if setting in ("AUTOCONF_MODE", "SWARM_MODE", "KUBERNETES_MODE", "IS_LOADING", "IS_DRAFT"):
|
||||
flash(f"Variable {k} is not editable, ignoring it", "error")
|
||||
variables.pop(k)
|
||||
continue
|
||||
elif setting not in config and plugins_settings[setting]["default"] == v:
|
||||
variables.pop(k)
|
||||
continue
|
||||
|
||||
try:
|
||||
if re_search(plugins_settings[setting]["regex"], v):
|
||||
check = True
|
||||
except RegexError:
|
||||
self.__db.logger.warning(f"Invalid regex for setting {setting} : {plugins_settings[setting]['regex']}, ignoring regex check")
|
||||
|
||||
if not check:
|
||||
error = 1
|
||||
flash(f"Variable {k} is not valid.", "error")
|
||||
except RegexError as e:
|
||||
flash(f"Invalid regex for setting {setting} : {plugins_settings[setting]['regex']}, ignoring regex check:{e}", "error")
|
||||
variables.pop(k)
|
||||
continue
|
||||
|
||||
return error
|
||||
if not check:
|
||||
flash(f"Variable {k} is not valid.", "error")
|
||||
variables.pop(k)
|
||||
|
||||
return variables
|
||||
|
||||
def new_service(self, variables: dict, is_draft: bool = False) -> Tuple[str, int]:
|
||||
"""Creates a new service from the given variables
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue