mirror of
https://github.com/TecharoHQ/anubis.git
synced 2026-04-22 16:16:41 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 082a57a1a0 |
@@ -34,7 +34,3 @@ de
|
|||||||
resourced
|
resourced
|
||||||
envoyproxy
|
envoyproxy
|
||||||
unipromos
|
unipromos
|
||||||
Samsung
|
|
||||||
wenet
|
|
||||||
qwertiko
|
|
||||||
setuplistener
|
|
||||||
|
|||||||
@@ -80,7 +80,6 @@ databento
|
|||||||
dayjob
|
dayjob
|
||||||
dco
|
dco
|
||||||
DDOS
|
DDOS
|
||||||
ddwrt
|
|
||||||
Debian
|
Debian
|
||||||
debrpm
|
debrpm
|
||||||
decaymap
|
decaymap
|
||||||
@@ -103,7 +102,6 @@ duckduckbot
|
|||||||
eerror
|
eerror
|
||||||
ellenjoe
|
ellenjoe
|
||||||
emacs
|
emacs
|
||||||
embe
|
|
||||||
enbyware
|
enbyware
|
||||||
etld
|
etld
|
||||||
everyones
|
everyones
|
||||||
@@ -121,6 +119,7 @@ FCr
|
|||||||
fcrdns
|
fcrdns
|
||||||
fediverse
|
fediverse
|
||||||
ffprobe
|
ffprobe
|
||||||
|
FFXIV
|
||||||
fhdr
|
fhdr
|
||||||
financials
|
financials
|
||||||
finfos
|
finfos
|
||||||
@@ -222,6 +221,7 @@ LLU
|
|||||||
loadbalancer
|
loadbalancer
|
||||||
lol
|
lol
|
||||||
lominsa
|
lominsa
|
||||||
|
maintainership
|
||||||
malware
|
malware
|
||||||
mcr
|
mcr
|
||||||
memes
|
memes
|
||||||
@@ -239,6 +239,7 @@ mymaster
|
|||||||
mypass
|
mypass
|
||||||
myuser
|
myuser
|
||||||
nbf
|
nbf
|
||||||
|
Necron
|
||||||
nepeat
|
nepeat
|
||||||
netsurf
|
netsurf
|
||||||
nginx
|
nginx
|
||||||
@@ -333,6 +334,7 @@ spyderbot
|
|||||||
srcip
|
srcip
|
||||||
srv
|
srv
|
||||||
stackoverflow
|
stackoverflow
|
||||||
|
Stargate
|
||||||
startprecmd
|
startprecmd
|
||||||
stoppostcmd
|
stoppostcmd
|
||||||
storetest
|
storetest
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ jobs:
|
|||||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
||||||
with:
|
with:
|
||||||
node-version: "24.11.0"
|
node-version: "24.11.0"
|
||||||
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
|
- uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
|
||||||
with:
|
with:
|
||||||
go-version: "1.25.7"
|
go-version: "1.25.7"
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ jobs:
|
|||||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
||||||
with:
|
with:
|
||||||
node-version: "24.11.0"
|
node-version: "24.11.0"
|
||||||
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
|
- uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
|
||||||
with:
|
with:
|
||||||
go-version: "stable"
|
go-version: "stable"
|
||||||
|
|
||||||
|
|||||||
@@ -39,14 +39,14 @@ jobs:
|
|||||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
||||||
with:
|
with:
|
||||||
node-version: "24.11.0"
|
node-version: "24.11.0"
|
||||||
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
|
- uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
|
||||||
with:
|
with:
|
||||||
go-version: "stable"
|
go-version: "stable"
|
||||||
|
|
||||||
- uses: ko-build/setup-ko@d006021bd0c28d1ce33a07e7943d48b079944c8d # v0.9
|
- uses: ko-build/setup-ko@d006021bd0c28d1ce33a07e7943d48b079944c8d # v0.9
|
||||||
|
|
||||||
- name: Log into registry
|
- name: Log into registry
|
||||||
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
|
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ jobs:
|
|||||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||||
|
|
||||||
- name: Log into registry
|
- name: Log into registry
|
||||||
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
|
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: techarohq
|
username: techarohq
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
|
- uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
|
||||||
with:
|
with:
|
||||||
go-version: "stable"
|
go-version: "stable"
|
||||||
|
|
||||||
|
|||||||
@@ -27,12 +27,12 @@ jobs:
|
|||||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
||||||
with:
|
with:
|
||||||
node-version: "24.11.0"
|
node-version: "24.11.0"
|
||||||
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
|
- uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
|
||||||
with:
|
with:
|
||||||
go-version: "stable"
|
go-version: "stable"
|
||||||
|
|
||||||
- name: Cache playwright binaries
|
- name: Cache playwright binaries
|
||||||
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
|
||||||
id: playwright-cache
|
id: playwright-cache
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ jobs:
|
|||||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
||||||
with:
|
with:
|
||||||
node-version: "24.11.0"
|
node-version: "24.11.0"
|
||||||
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
|
- uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
|
||||||
with:
|
with:
|
||||||
go-version: "stable"
|
go-version: "stable"
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ jobs:
|
|||||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
||||||
with:
|
with:
|
||||||
node-version: "24.11.0"
|
node-version: "24.11.0"
|
||||||
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
|
- uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
|
||||||
with:
|
with:
|
||||||
go-version: "stable"
|
go-version: "stable"
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ jobs:
|
|||||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
||||||
with:
|
with:
|
||||||
node-version: "24.11.0"
|
node-version: "24.11.0"
|
||||||
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
|
- uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
|
||||||
with:
|
with:
|
||||||
go-version: "stable"
|
go-version: "stable"
|
||||||
|
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: check-spelling
|
- name: check-spelling
|
||||||
id: spelling
|
id: spelling
|
||||||
uses: check-spelling/check-spelling@cfb6f7e75bbfc89c71eaa30366d0c166f1bd9c8c # v0.0.26
|
uses: check-spelling/check-spelling@c635c2f3f714eec2fcf27b643a1919b9a811ef2e # v0.0.25
|
||||||
with:
|
with:
|
||||||
suppress_push_for_open_pull_request: ${{ github.actor != 'dependabot[bot]' && 1 }}
|
suppress_push_for_open_pull_request: ${{ github.actor != 'dependabot[bot]' && 1 }}
|
||||||
checkout: true
|
checkout: true
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ jobs:
|
|||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- name: Log into registry
|
- name: Log into registry
|
||||||
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
|
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
|
|||||||
@@ -30,13 +30,13 @@ jobs:
|
|||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Install CI target SSH key
|
- name: Install CI target SSH key
|
||||||
uses: shimataro/ssh-key-action@87a8f067114a8ce263df83e9ed5c849953548bc3 # v2.8.1
|
uses: shimataro/ssh-key-action@6b84f2e793b32fa0b03a379cadadec75cc539391 # v2.8.0
|
||||||
with:
|
with:
|
||||||
key: ${{ secrets.CI_SSH_KEY }}
|
key: ${{ secrets.CI_SSH_KEY }}
|
||||||
name: id_rsa
|
name: id_rsa
|
||||||
known_hosts: ${{ secrets.CI_SSH_KNOWN_HOSTS }}
|
known_hosts: ${{ secrets.CI_SSH_KNOWN_HOSTS }}
|
||||||
|
|
||||||
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
|
- uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
|
||||||
with:
|
with:
|
||||||
go-version: "stable"
|
go-version: "stable"
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ jobs:
|
|||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Install the latest version of uv
|
- name: Install the latest version of uv
|
||||||
uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0
|
uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
|
||||||
|
|
||||||
- name: Run zizmor 🌈
|
- name: Run zizmor 🌈
|
||||||
run: uvx zizmor --format sarif . > results.sarif
|
run: uvx zizmor --format sarif . > results.sarif
|
||||||
@@ -29,7 +29,7 @@ jobs:
|
|||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Upload SARIF file
|
- name: Upload SARIF file
|
||||||
uses: github/codeql-action/upload-sarif@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1
|
uses: github/codeql-action/upload-sarif@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9
|
||||||
with:
|
with:
|
||||||
sarif_file: results.sarif
|
sarif_file: results.sarif
|
||||||
category: zizmor
|
category: zizmor
|
||||||
|
|||||||
@@ -73,15 +73,6 @@ Anubis is brought to you by sponsors and donors like:
|
|||||||
<a href="https://www.anexia.com/">
|
<a href="https://www.anexia.com/">
|
||||||
<img src="./docs/static/img/sponsors/anexia-cloudsolutions-logo.webp" alt="ANEXIA Cloud Solutions" height="64">
|
<img src="./docs/static/img/sponsors/anexia-cloudsolutions-logo.webp" alt="ANEXIA Cloud Solutions" height="64">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://dd-wrt.com/">
|
|
||||||
<img src="./docs/static/img/sponsors/ddwrt-logo.webp" alt="embeDD GmbH" height="64">
|
|
||||||
</a>
|
|
||||||
<a href="https://www.qwertiko.de?utm_campaign=github&utm_medium=referral&utm_content=anubis">
|
|
||||||
<img src="./docs/static/img/sponsors/qwertiko-logo.webp" alt="Qwertiko" height="64">
|
|
||||||
</a>
|
|
||||||
<a href="https://wenet.pl/?utm_campaign=github&utm_medium=referral&utm_content=anubis">
|
|
||||||
<img src="./docs/static/img/sponsors/wenet-logo.webp" alt="Wenet" height="64">
|
|
||||||
</a>
|
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
|
|||||||
+131
-27
@@ -17,10 +17,12 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httputil"
|
"net/http/httputil"
|
||||||
|
"net/http/pprof"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
@@ -31,12 +33,12 @@ import (
|
|||||||
"github.com/TecharoHQ/anubis/internal"
|
"github.com/TecharoHQ/anubis/internal"
|
||||||
libanubis "github.com/TecharoHQ/anubis/lib"
|
libanubis "github.com/TecharoHQ/anubis/lib"
|
||||||
"github.com/TecharoHQ/anubis/lib/config"
|
"github.com/TecharoHQ/anubis/lib/config"
|
||||||
"github.com/TecharoHQ/anubis/lib/metrics"
|
|
||||||
botPolicy "github.com/TecharoHQ/anubis/lib/policy"
|
botPolicy "github.com/TecharoHQ/anubis/lib/policy"
|
||||||
"github.com/TecharoHQ/anubis/lib/thoth"
|
"github.com/TecharoHQ/anubis/lib/thoth"
|
||||||
"github.com/TecharoHQ/anubis/web"
|
"github.com/TecharoHQ/anubis/web"
|
||||||
"github.com/facebookgo/flagenv"
|
"github.com/facebookgo/flagenv"
|
||||||
_ "github.com/joho/godotenv/autoload"
|
_ "github.com/joho/godotenv/autoload"
|
||||||
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
healthv1 "google.golang.org/grpc/health/grpc_health_v1"
|
healthv1 "google.golang.org/grpc/health/grpc_health_v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -117,6 +119,33 @@ func doHealthCheck() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parseBindNetFromAddr determine bind network and address based on the given network and address.
|
||||||
|
func parseBindNetFromAddr(address string) (string, string) {
|
||||||
|
defaultScheme := "http://"
|
||||||
|
if !strings.Contains(address, "://") {
|
||||||
|
if strings.HasPrefix(address, ":") {
|
||||||
|
address = defaultScheme + "localhost" + address
|
||||||
|
} else {
|
||||||
|
address = defaultScheme + address
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bindUri, err := url.Parse(address)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(fmt.Errorf("failed to parse bind URL: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
switch bindUri.Scheme {
|
||||||
|
case "unix":
|
||||||
|
return "unix", bindUri.Path
|
||||||
|
case "tcp", "http", "https":
|
||||||
|
return "tcp", bindUri.Host
|
||||||
|
default:
|
||||||
|
log.Fatal(fmt.Errorf("unsupported network scheme %s in address %s", bindUri.Scheme, address))
|
||||||
|
}
|
||||||
|
return "", address
|
||||||
|
}
|
||||||
|
|
||||||
func parseSameSite(s string) http.SameSite {
|
func parseSameSite(s string) http.SameSite {
|
||||||
switch strings.ToLower(s) {
|
switch strings.ToLower(s) {
|
||||||
case "none":
|
case "none":
|
||||||
@@ -133,6 +162,53 @@ func parseSameSite(s string) http.SameSite {
|
|||||||
return http.SameSiteDefaultMode
|
return http.SameSiteDefaultMode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setupListener(network string, address string) (net.Listener, string) {
|
||||||
|
formattedAddress := ""
|
||||||
|
|
||||||
|
if network == "" {
|
||||||
|
// keep compatibility
|
||||||
|
network, address = parseBindNetFromAddr(address)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch network {
|
||||||
|
case "unix":
|
||||||
|
formattedAddress = "unix:" + address
|
||||||
|
case "tcp":
|
||||||
|
if strings.HasPrefix(address, ":") { // assume it's just a port e.g. :4259
|
||||||
|
formattedAddress = "http://localhost" + address
|
||||||
|
} else {
|
||||||
|
formattedAddress = "http://" + address
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
formattedAddress = fmt.Sprintf(`(%s) %s`, network, address)
|
||||||
|
}
|
||||||
|
|
||||||
|
listener, err := net.Listen(network, address)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(fmt.Errorf("failed to bind to %s: %w", formattedAddress, err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// additional permission handling for unix sockets
|
||||||
|
if network == "unix" {
|
||||||
|
mode, err := strconv.ParseUint(*socketMode, 8, 0)
|
||||||
|
if err != nil {
|
||||||
|
listener.Close()
|
||||||
|
log.Fatal(fmt.Errorf("could not parse socket mode %s: %w", *socketMode, err))
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.Chmod(address, os.FileMode(mode))
|
||||||
|
if err != nil {
|
||||||
|
err := listener.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("failed to close listener: %v", err)
|
||||||
|
}
|
||||||
|
log.Fatal(fmt.Errorf("could not change socket mode: %w", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return listener, formattedAddress
|
||||||
|
}
|
||||||
|
|
||||||
func makeReverseProxy(target string, targetSNI string, targetHost string, insecureSkipVerify bool, targetDisableKeepAlive bool) (http.Handler, error) {
|
func makeReverseProxy(target string, targetSNI string, targetHost string, insecureSkipVerify bool, targetDisableKeepAlive bool) (http.Handler, error) {
|
||||||
targetUri, err := url.Parse(target)
|
targetUri, err := url.Parse(target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -200,7 +276,7 @@ func main() {
|
|||||||
|
|
||||||
internal.SetHealth("anubis", healthv1.HealthCheckResponse_NOT_SERVING)
|
internal.SetHealth("anubis", healthv1.HealthCheckResponse_NOT_SERVING)
|
||||||
|
|
||||||
lg := internal.InitSlog(*slogLevel, os.Stderr)
|
lg := internal.InitSlog(*slogLevel, os.Stderr, false)
|
||||||
lg.Info("starting up Anubis")
|
lg.Info("starting up Anubis")
|
||||||
|
|
||||||
if *healthcheck {
|
if *healthcheck {
|
||||||
@@ -228,6 +304,11 @@ func main() {
|
|||||||
|
|
||||||
wg := new(sync.WaitGroup)
|
wg := new(sync.WaitGroup)
|
||||||
|
|
||||||
|
if *metricsBind != "" {
|
||||||
|
wg.Add(1)
|
||||||
|
go metricsServer(ctx, *lg.With("subsystem", "metrics"), wg.Done)
|
||||||
|
}
|
||||||
|
|
||||||
var rp http.Handler
|
var rp http.Handler
|
||||||
// when using anubis via Systemd and environment variables, then it is not possible to set targe to an empty string but only to space
|
// when using anubis via Systemd and environment variables, then it is not possible to set targe to an empty string but only to space
|
||||||
if strings.TrimSpace(*target) != "" {
|
if strings.TrimSpace(*target) != "" {
|
||||||
@@ -267,26 +348,6 @@ func main() {
|
|||||||
lg.Debug("swapped to new logger")
|
lg.Debug("swapped to new logger")
|
||||||
slog.SetDefault(lg)
|
slog.SetDefault(lg)
|
||||||
|
|
||||||
if *metricsBind != "" || policy.Metrics != nil {
|
|
||||||
wg.Add(1)
|
|
||||||
|
|
||||||
ms := &metrics.Server{
|
|
||||||
Config: policy.Metrics,
|
|
||||||
Log: lg,
|
|
||||||
}
|
|
||||||
|
|
||||||
if policy.Metrics == nil {
|
|
||||||
lg.Debug("migrating flags to metrics config", "bind", *metricsBind, "network", *metricsBindNetwork, "socket-mode", *socketMode)
|
|
||||||
ms.Config = &config.Metrics{
|
|
||||||
Bind: *metricsBind,
|
|
||||||
Network: *metricsBindNetwork,
|
|
||||||
SocketMode: *socketMode,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
go ms.Run(ctx, wg.Done)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Warn if persistent storage is used without a configured signing key
|
// Warn if persistent storage is used without a configured signing key
|
||||||
if policy.Store.IsPersistent() {
|
if policy.Store.IsPersistent() {
|
||||||
if *hs512Secret == "" && *ed25519PrivateKeyHex == "" && *ed25519PrivateKeyHexFile == "" {
|
if *hs512Secret == "" && *ed25519PrivateKeyHex == "" && *ed25519PrivateKeyHexFile == "" {
|
||||||
@@ -423,11 +484,7 @@ func main() {
|
|||||||
h = internal.JA4H(h)
|
h = internal.JA4H(h)
|
||||||
|
|
||||||
srv := http.Server{Handler: h, ErrorLog: internal.GetFilteredHTTPLogger()}
|
srv := http.Server{Handler: h, ErrorLog: internal.GetFilteredHTTPLogger()}
|
||||||
listener, listenerUrl, err := internal.SetupListener(*bindNetwork, *bind, *socketMode)
|
listener, listenerUrl := setupListener(*bindNetwork, *bind)
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("SetupListener(%q, %q, %q): %v", *bindNetwork, *bind, *socketMode, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
lg.Info(
|
lg.Info(
|
||||||
"listening",
|
"listening",
|
||||||
"url", listenerUrl,
|
"url", listenerUrl,
|
||||||
@@ -462,6 +519,53 @@ func main() {
|
|||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func metricsServer(ctx context.Context, lg slog.Logger, done func()) {
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("GET /debug/pprof/", pprof.Index)
|
||||||
|
mux.HandleFunc("GET /debug/pprof/cmdline", pprof.Cmdline)
|
||||||
|
mux.HandleFunc("GET /debug/pprof/profile", pprof.Profile)
|
||||||
|
mux.HandleFunc("GET /debug/pprof/symbol", pprof.Symbol)
|
||||||
|
mux.HandleFunc("GET /debug/pprof/trace", pprof.Trace)
|
||||||
|
mux.Handle("/metrics", promhttp.Handler())
|
||||||
|
mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
st, ok := internal.GetHealth("anubis")
|
||||||
|
if !ok {
|
||||||
|
slog.Error("health service anubis does not exist, file a bug")
|
||||||
|
}
|
||||||
|
|
||||||
|
switch st {
|
||||||
|
case healthv1.HealthCheckResponse_NOT_SERVING:
|
||||||
|
http.Error(w, "NOT OK", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
case healthv1.HealthCheckResponse_SERVING:
|
||||||
|
fmt.Fprintln(w, "OK")
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
http.Error(w, "UNKNOWN", http.StatusFailedDependency)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
srv := http.Server{Handler: mux, ErrorLog: internal.GetFilteredHTTPLogger()}
|
||||||
|
listener, metricsUrl := setupListener(*metricsBindNetwork, *metricsBind)
|
||||||
|
lg.Debug("listening for metrics", "url", metricsUrl)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
<-ctx.Done()
|
||||||
|
c, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
if err := srv.Shutdown(c); err != nil {
|
||||||
|
log.Printf("cannot shut down: %v", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err := srv.Serve(listener); !errors.Is(err, http.ErrServerClosed) {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func extractEmbedFS(fsys embed.FS, root string, destDir string) error {
|
func extractEmbedFS(fsys embed.FS, root string, destDir string) error {
|
||||||
return fs.WalkDir(fsys, root, func(path string, d fs.DirEntry, err error) error {
|
return fs.WalkDir(fsys, root, func(path string, d fs.DirEntry, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ func main() {
|
|||||||
flagenv.Parse()
|
flagenv.Parse()
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
slog.SetDefault(internal.InitSlog(*slogLevel, os.Stderr))
|
slog.SetDefault(internal.InitSlog(*slogLevel, os.Stderr, false))
|
||||||
|
|
||||||
koDockerRepo := strings.TrimSuffix(*dockerRepo, "/"+filepath.Base(*dockerRepo))
|
koDockerRepo := strings.TrimSuffix(*dockerRepo, "/"+filepath.Base(*dockerRepo))
|
||||||
|
|
||||||
@@ -159,8 +159,8 @@ func run(command string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setOutput(key, val string) {
|
func setOutput(key, val string) {
|
||||||
github_output := os.Getenv("GITHUB_OUTPUT")
|
github_output := os.Getenv("GITHUB_OUTPUT")
|
||||||
f, _ := os.OpenFile(github_output, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
|
f, _ := os.OpenFile(github_output, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
|
||||||
fmt.Fprintf(f, "%s=%s\n", key, val)
|
fmt.Fprintf(f, "%s=%s\n", key, val)
|
||||||
f.Close()
|
f.Close()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -166,15 +166,6 @@ status_codes:
|
|||||||
CHALLENGE: 200
|
CHALLENGE: 200
|
||||||
DENY: 200
|
DENY: 200
|
||||||
|
|
||||||
# # Configuration for the metrics server. See the docs for more information:
|
|
||||||
# #
|
|
||||||
# # https://anubis.techaro.lol/docs/admin/policies#metrics-server
|
|
||||||
# #
|
|
||||||
# # This is commented out by default so that command line flags take precedence.
|
|
||||||
# metrics:
|
|
||||||
# bind: ":9090"
|
|
||||||
# network: "tcp"
|
|
||||||
|
|
||||||
# Anubis can store temporary data in one of a few backends. See the storage
|
# Anubis can store temporary data in one of a few backends. See the storage
|
||||||
# backends section of the docs for more information:
|
# backends section of the docs for more information:
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -11,15 +11,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
<!-- This changes the project to: -->
|
|
||||||
|
|
||||||
- Move metrics server configuration to [the policy file](./admin/policies.mdx#metrics-server).
|
|
||||||
- Expose [pprof endpoints](https://pkg.go.dev/net/http/pprof) on the metrics listener to enable profiling Anubis in production.
|
- Expose [pprof endpoints](https://pkg.go.dev/net/http/pprof) on the metrics listener to enable profiling Anubis in production.
|
||||||
- fix: prevent nil pointer panic in challenge validation when threshold rules match during PassChallenge (#1463)
|
- fix: prevent nil pointer panic in challenge validation when threshold rules match during PassChallenge (#1463)
|
||||||
- Instruct reverse proxies to not cache error pages.
|
- Instruct reverse proxies to not cache error pages.
|
||||||
- Fixed mixed tab/space indentation in Caddy documentation code block
|
- Fixed mixed tab/space indentation in Caddy documentation code block
|
||||||
- Improve error messages and fix broken REDIRECT_DOMAINS link in docs ([#1193](https://github.com/TecharoHQ/anubis/issues/1193))
|
- Improve error messages and fix broken REDIRECT_DOMAINS link in docs ([#1193](https://github.com/TecharoHQ/anubis/issues/1193))
|
||||||
- Add Bulgarian locale ([#1394](https://github.com/TecharoHQ/anubis/pull/1394))
|
- Add Bulgarian locale ([#1394](https://github.com/TecharoHQ/anubis/pull/1394))
|
||||||
|
- Add option to hide source code origin of log lines in [logging configuration](./admin/policies.mdx#logging-management)
|
||||||
|
|
||||||
|
<!-- This changes the project to: -->
|
||||||
|
|
||||||
- Fix CEL internal errors when iterating `headers`/`query` map wrappers by implementing map iterators for `HTTPHeaders` and `URLValues` ([#1465](https://github.com/TecharoHQ/anubis/pull/1465)).
|
- Fix CEL internal errors when iterating `headers`/`query` map wrappers by implementing map iterators for `HTTPHeaders` and `URLValues` ([#1465](https://github.com/TecharoHQ/anubis/pull/1465)).
|
||||||
|
|
||||||
## v1.25.0: Necron
|
## v1.25.0: Necron
|
||||||
|
|||||||
@@ -87,15 +87,15 @@ Anubis uses these environment variables for configuration:
|
|||||||
| `ED25519_PRIVATE_KEY_HEX_FILE` | unset | Path to a file containing the hex-encoded ed25519 private key. Only one of this or its sister option may be set. **Required when using persistent storage backends** (like bbolt) to ensure challenges survive service restarts. When running multiple instances on the same base domain, the key must be the same across all instances. |
|
| `ED25519_PRIVATE_KEY_HEX_FILE` | unset | Path to a file containing the hex-encoded ed25519 private key. Only one of this or its sister option may be set. **Required when using persistent storage backends** (like bbolt) to ensure challenges survive service restarts. When running multiple instances on the same base domain, the key must be the same across all instances. |
|
||||||
| `ERROR_TITLE` | unset | <EO /> If set, override the translation stack to show a custom title for error pages such as "Something went wrong!". See [Customizing messages](./botstopper.mdx#customizing-messages) for more details. |
|
| `ERROR_TITLE` | unset | <EO /> If set, override the translation stack to show a custom title for error pages such as "Something went wrong!". See [Customizing messages](./botstopper.mdx#customizing-messages) for more details. |
|
||||||
| `JWT_RESTRICTION_HEADER` | `X-Real-IP` | If set, the JWT is only valid if the current value of this header matches the value when the JWT was created. You can use it e.g. to restrict a JWT to the source IP of the user using `X-Real-IP`. |
|
| `JWT_RESTRICTION_HEADER` | `X-Real-IP` | If set, the JWT is only valid if the current value of this header matches the value when the JWT was created. You can use it e.g. to restrict a JWT to the source IP of the user using `X-Real-IP`. |
|
||||||
| `METRICS_BIND` | `:9090` | The legacy configuration value for the network address that Anubis serves Prometheus metrics on. Please migrate this to [the policy file](./policies.mdx#metrics-server) as soon as possible. |
|
| `METRICS_BIND` | `:9090` | The network address that Anubis serves Prometheus metrics on. See `BIND` for more information. |
|
||||||
| `METRICS_BIND_NETWORK` | `tcp` | The legacy configuration value for the address family that Anubis serves Prometheus metrics on. Please migrate this to [the policy file](./policies.mdx#metrics-server) as soon as possible. |
|
| `METRICS_BIND_NETWORK` | `tcp` | The address family that the Anubis metrics server listens on. See `BIND_NETWORK` for more information. |
|
||||||
| `OG_EXPIRY_TIME` | `24h` | The expiration time for the Open Graph tag cache. Prefer using [the policy file](./configuration/open-graph.mdx) to configure the Open Graph subsystem. |
|
| `OG_EXPIRY_TIME` | `24h` | The expiration time for the Open Graph tag cache. Prefer using [the policy file](./configuration/open-graph.mdx) to configure the Open Graph subsystem. |
|
||||||
| `OG_PASSTHROUGH` | `false` | If set to `true`, Anubis will enable Open Graph tag passthrough. Prefer using [the policy file](./configuration/open-graph.mdx) to configure the Open Graph subsystem. |
|
| `OG_PASSTHROUGH` | `false` | If set to `true`, Anubis will enable Open Graph tag passthrough. Prefer using [the policy file](./configuration/open-graph.mdx) to configure the Open Graph subsystem. |
|
||||||
| `OG_CACHE_CONSIDER_HOST` | `false` | If set to `true`, Anubis will consider the host in the Open Graph tag cache key. Prefer using [the policy file](./configuration/open-graph.mdx) to configure the Open Graph subsystem. |
|
| `OG_CACHE_CONSIDER_HOST` | `false` | If set to `true`, Anubis will consider the host in the Open Graph tag cache key. Prefer using [the policy file](./configuration/open-graph.mdx) to configure the Open Graph subsystem. |
|
||||||
| `OVERLAY_FOLDER` | unset | <EO /> If set, treat the given path as an [overlay folder](./botstopper.mdx#custom-images-and-css), allowing you to customize CSS, fonts, images, and add other assets to BotStopper deployments. |
|
| `OVERLAY_FOLDER` | unset | <EO /> If set, treat the given path as an [overlay folder](./botstopper.mdx#custom-images-and-css), allowing you to customize CSS, fonts, images, and add other assets to BotStopper deployments. |
|
||||||
| `POLICY_FNAME` | unset | The file containing [bot policy configuration](./policies.mdx). See the bot policy documentation for more details. If unset, the default bot policy configuration is used. |
|
| `POLICY_FNAME` | unset | The file containing [bot policy configuration](./policies.mdx). See the bot policy documentation for more details. If unset, the default bot policy configuration is used. |
|
||||||
| `PUBLIC_URL` | unset | The externally accessible URL for this Anubis instance, used for constructing redirect URLs (e.g., for Traefik forwardAuth). Leave it unset when Anubis terminates traffic directly (sidecar/standalone deployments) or redirect building will fail with `redir=null`. |
|
| `PUBLIC_URL` | unset | The externally accessible URL for this Anubis instance, used for constructing redirect URLs (e.g., for Traefik forwardAuth). Leave it unset when Anubis terminates traffic directly (sidecar/standalone deployments) or redirect building will fail with `redir=null`. |
|
||||||
| `REDIRECT_DOMAINS` | unset | Comma-separated list of domain names that Anubis should allow redirects to when passing a challenge. See [Redirect Domain Configuration](./configuration/redirect-domains.mdx) for more details. |
|
| `REDIRECT_DOMAINS` | unset | Comma-separated list of domain names that Anubis should allow redirects to when passing a challenge. See [Redirect Domain Configuration](./configuration/redirect-domains.mdx) for more details. |
|
||||||
| `SERVE_ROBOTS_TXT` | `false` | If set `true`, Anubis will serve a default `robots.txt` file that disallows all known AI scrapers by name and then additionally disallows every scraper. This is useful if facts and circumstances make it difficult to change the underlying service to serve such a `robots.txt` file. |
|
| `SERVE_ROBOTS_TXT` | `false` | If set `true`, Anubis will serve a default `robots.txt` file that disallows all known AI scrapers by name and then additionally disallows every scraper. This is useful if facts and circumstances make it difficult to change the underlying service to serve such a `robots.txt` file. |
|
||||||
| `SLOG_LEVEL` | `INFO` | The log level for structured logging. Valid values are `DEBUG`, `INFO`, `WARN`, and `ERROR`. Set to `DEBUG` to see all requests, evaluations, and detailed diagnostic information. |
|
| `SLOG_LEVEL` | `INFO` | The log level for structured logging. Valid values are `DEBUG`, `INFO`, `WARN`, and `ERROR`. Set to `DEBUG` to see all requests, evaluations, and detailed diagnostic information. |
|
||||||
| `SOCKET_MODE` | `0770` | _Only used when at least one of the `*_BIND_NETWORK` variables are set to `unix`._ The socket mode (permissions) for Unix domain sockets. |
|
| `SOCKET_MODE` | `0770` | _Only used when at least one of the `*_BIND_NETWORK` variables are set to `unix`._ The socket mode (permissions) for Unix domain sockets. |
|
||||||
|
|||||||
@@ -117,27 +117,6 @@ remote_addresses:
|
|||||||
- 100.64.0.0/10
|
- 100.64.0.0/10
|
||||||
```
|
```
|
||||||
|
|
||||||
## Metrics server
|
|
||||||
|
|
||||||
Anubis includes support for [Prometheus-style metrics](https://prometheus.io/docs/introduction/overview/), allowing systems administrators to monitor Anubis' performance and effectiveness. This is a separate HTTP server with metrics, health checking, and debug routes.
|
|
||||||
|
|
||||||
Anubis' metrics server is configured with the `metrics` block in the configuration file:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
metrics:
|
|
||||||
bind: ":9090"
|
|
||||||
network: "tcp"
|
|
||||||
```
|
|
||||||
|
|
||||||
If you want to bind metrics to a Unix socket, make sure to set the network to `unix` and add a socket mode:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
metrics:
|
|
||||||
bind: "/tmp/anubis_metrics.sock"
|
|
||||||
network: unix
|
|
||||||
socketMode: "0700" # must be a string
|
|
||||||
```
|
|
||||||
|
|
||||||
## Imprint / Impressum support
|
## Imprint / Impressum support
|
||||||
|
|
||||||
Anubis has support for showing imprint / impressum information. This is defined in the `impressum` block of your configuration. See [Imprint / Impressum configuration](./configuration/impressum.mdx) for more information.
|
Anubis has support for showing imprint / impressum information. This is defined in the `impressum` block of your configuration. See [Imprint / Impressum configuration](./configuration/impressum.mdx) for more information.
|
||||||
@@ -360,6 +339,7 @@ Anubis exposes the following logging settings in the policy file:
|
|||||||
| `level` | [log level](#log-levels) | `info` | The logging level threshold. Any logs that are at or above this threshold will be drained to the sink. Any other logs will be discarded. |
|
| `level` | [log level](#log-levels) | `info` | The logging level threshold. Any logs that are at or above this threshold will be drained to the sink. Any other logs will be discarded. |
|
||||||
| `sink` | string | `stdio`, `file` | The sink where the logs drain to as they are being recorded in Anubis. |
|
| `sink` | string | `stdio`, `file` | The sink where the logs drain to as they are being recorded in Anubis. |
|
||||||
| `parameters` | object | | Parameters for the given logging sink. This will vary based on the logging sink of choice. See below for more information. |
|
| `parameters` | object | | Parameters for the given logging sink. This will vary based on the logging sink of choice. See below for more information. |
|
||||||
|
| `hideSource` | boolean | `false` | If set, hide the details of which line of code triggered a log line. Setting this to `true` may make getting support more difficult. |
|
||||||
|
|
||||||
Anubis supports the following logging sinks:
|
Anubis supports the following logging sinks:
|
||||||
|
|
||||||
|
|||||||
@@ -87,15 +87,6 @@ Anubis is brought to you by sponsors and donors like:
|
|||||||
height="64"
|
height="64"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
<a href="https://dd-wrt.com/">
|
|
||||||
<img src="/img/sponsors/ddwrt-logo.webp" alt="embeDD GmbH" height="64" />
|
|
||||||
</a>
|
|
||||||
<a href="https://www.qwertiko.de?utm_campaign=github&utm_medium=referral&utm_content=anubis">
|
|
||||||
<img src="/img/sponsors/qwertiko-logo.webp" alt="Qwertiko" height="64" />
|
|
||||||
</a>
|
|
||||||
<a href="https://wenet.pl/?utm_campaign=github&utm_medium=referral&utm_content=anubis">
|
|
||||||
<img src="/img/sponsors/wenet-logo.webp" alt="Wenet" height="64" />
|
|
||||||
</a>
|
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
|
|||||||
@@ -32,14 +32,3 @@ This interpreter is much slower than native code because it has to translate eac
|
|||||||
Some users choose to disable JIT as a hardening measure against theoretical browser exploits. This is a reasonable choice if you face targeted attacks from well-resourced adversaries (such as nation-state actors), but it comes with real performance costs.
|
Some users choose to disable JIT as a hardening measure against theoretical browser exploits. This is a reasonable choice if you face targeted attacks from well-resourced adversaries (such as nation-state actors), but it comes with real performance costs.
|
||||||
|
|
||||||
If you've disabled JIT and find Anubis checks slow, re-enabling JIT is the fix. There is no way for Anubis to work around this on our end.
|
If you've disabled JIT and find Anubis checks slow, re-enabling JIT is the fix. There is no way for Anubis to work around this on our end.
|
||||||
|
|
||||||
## What versions of browsers does Anubis support?
|
|
||||||
|
|
||||||
Anubis is written mainly by a single person in a basement in Canada. As such it is impossible for Anubis to support every version of every browser on the planet. As such, here's a few rules of thumb for the browsers that Anubis focuses on supporting:
|
|
||||||
|
|
||||||
- At least the two (2) most recent LTS releases of Firefox and Chrome.
|
|
||||||
- At least the version of Chromium as used by the Samsung Browser on Android.
|
|
||||||
- At least the last version of Chromium and Firefox that are known to run on Windows 7.
|
|
||||||
- At least the version of Safari that runs on the second-to-oldest iPhone model currently on the market.
|
|
||||||
|
|
||||||
We cannot give more cohesive version bounds than this. If you run into problems, please file an issue. Sometimes you may just need to upgrade hardware though.
|
|
||||||
|
|||||||
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 4.9 KiB |
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 31 KiB |
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 5.7 KiB |
+9
-3
@@ -10,7 +10,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func InitSlog(level string, sink io.Writer) *slog.Logger {
|
func InitSlog(level string, sink io.Writer, hideSource bool) *slog.Logger {
|
||||||
var programLevel slog.Level
|
var programLevel slog.Level
|
||||||
if err := (&programLevel).UnmarshalText([]byte(level)); err != nil {
|
if err := (&programLevel).UnmarshalText([]byte(level)); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "invalid log level %s: %v, using info\n", level, err)
|
fmt.Fprintf(os.Stderr, "invalid log level %s: %v, using info\n", level, err)
|
||||||
@@ -20,10 +20,16 @@ func InitSlog(level string, sink io.Writer) *slog.Logger {
|
|||||||
leveler := &slog.LevelVar{}
|
leveler := &slog.LevelVar{}
|
||||||
leveler.Set(programLevel)
|
leveler.Set(programLevel)
|
||||||
|
|
||||||
h := slog.NewJSONHandler(sink, &slog.HandlerOptions{
|
opts := &slog.HandlerOptions{
|
||||||
AddSource: true,
|
AddSource: true,
|
||||||
Level: leveler,
|
Level: leveler,
|
||||||
})
|
}
|
||||||
|
|
||||||
|
if hideSource {
|
||||||
|
opts.AddSource = false
|
||||||
|
}
|
||||||
|
|
||||||
|
h := slog.NewJSONHandler(sink, opts)
|
||||||
result := slog.New(h)
|
result := slog.New(h)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,92 +0,0 @@
|
|||||||
package internal
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"net/url"
|
|
||||||
"os"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// parseBindNetFromAddr determine bind network and address based on the given network and address.
|
|
||||||
func parseBindNetFromAddr(address string) (string, string, error) {
|
|
||||||
defaultScheme := "http://"
|
|
||||||
if !strings.Contains(address, "://") {
|
|
||||||
if strings.HasPrefix(address, ":") {
|
|
||||||
address = defaultScheme + "localhost" + address
|
|
||||||
} else {
|
|
||||||
address = defaultScheme + address
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bindUri, err := url.Parse(address)
|
|
||||||
if err != nil {
|
|
||||||
return "", "", fmt.Errorf("failed to parse bind URL: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch bindUri.Scheme {
|
|
||||||
case "unix":
|
|
||||||
return "unix", bindUri.Path, nil
|
|
||||||
case "tcp", "http", "https":
|
|
||||||
return "tcp", bindUri.Host, nil
|
|
||||||
default:
|
|
||||||
return "", "", fmt.Errorf("unsupported network scheme %s in address %s", bindUri.Scheme, address)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetupListener sets up a network listener based on the input from configuration
|
|
||||||
// envvars. It returns a network listener and the URL to that listener or an error.
|
|
||||||
func SetupListener(network, address, socketMode string) (net.Listener, string, error) {
|
|
||||||
formattedAddress := ""
|
|
||||||
var err error
|
|
||||||
|
|
||||||
if network == "" {
|
|
||||||
// keep compatibility
|
|
||||||
network, address, err = parseBindNetFromAddr(address)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, "", fmt.Errorf("can't parse bind and network: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch network {
|
|
||||||
case "unix":
|
|
||||||
formattedAddress = "unix:" + address
|
|
||||||
case "tcp":
|
|
||||||
if strings.HasPrefix(address, ":") { // assume it's just a port e.g. :4259
|
|
||||||
formattedAddress = "http://localhost" + address
|
|
||||||
} else {
|
|
||||||
formattedAddress = "http://" + address
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
formattedAddress = fmt.Sprintf(`(%s) %s`, network, address)
|
|
||||||
}
|
|
||||||
|
|
||||||
ln, err := net.Listen(network, address)
|
|
||||||
if err != nil {
|
|
||||||
return nil, "", fmt.Errorf("failed to bind to %s: %w", formattedAddress, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// additional permission handling for unix sockets
|
|
||||||
if network == "unix" {
|
|
||||||
mode, err := strconv.ParseUint(socketMode, 8, 0)
|
|
||||||
if err != nil {
|
|
||||||
ln.Close()
|
|
||||||
return nil, "", fmt.Errorf("could not parse socket mode %s: %w", socketMode, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = os.Chmod(address, os.FileMode(mode))
|
|
||||||
if err != nil {
|
|
||||||
err := fmt.Errorf("could not change socket mode: %w", err)
|
|
||||||
clErr := ln.Close()
|
|
||||||
if clErr != nil {
|
|
||||||
return nil, "", errors.Join(err, clErr)
|
|
||||||
}
|
|
||||||
return nil, "", err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ln, formattedAddress, nil
|
|
||||||
}
|
|
||||||
@@ -1,180 +0,0 @@
|
|||||||
package internal
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/fs"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestParseBindNetFromAddr(t *testing.T) {
|
|
||||||
for _, tt := range []struct {
|
|
||||||
name string
|
|
||||||
address string
|
|
||||||
wantErr bool
|
|
||||||
network string
|
|
||||||
bind string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "simple tcp",
|
|
||||||
address: "localhost:9090",
|
|
||||||
wantErr: false,
|
|
||||||
network: "tcp",
|
|
||||||
bind: "localhost:9090",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "simple unix",
|
|
||||||
address: "unix:///tmp/foo.sock",
|
|
||||||
wantErr: false,
|
|
||||||
network: "unix",
|
|
||||||
bind: "/tmp/foo.sock",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "invalid network",
|
|
||||||
address: "foo:///tmp/bar.sock",
|
|
||||||
wantErr: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "tcp uri",
|
|
||||||
address: "tcp://[::]:9090",
|
|
||||||
wantErr: false,
|
|
||||||
network: "tcp",
|
|
||||||
bind: "[::]:9090",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "http uri",
|
|
||||||
address: "http://[::]:9090",
|
|
||||||
wantErr: false,
|
|
||||||
network: "tcp",
|
|
||||||
bind: "[::]:9090",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "https uri",
|
|
||||||
address: "https://[::]:9090",
|
|
||||||
wantErr: false,
|
|
||||||
network: "tcp",
|
|
||||||
bind: "[::]:9090",
|
|
||||||
},
|
|
||||||
} {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
network, bind, err := parseBindNetFromAddr(tt.address)
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case tt.wantErr && err == nil:
|
|
||||||
t.Errorf("parseBindNetFromAddr(%q) should have errored but did not", tt.address)
|
|
||||||
case !tt.wantErr && err != nil:
|
|
||||||
t.Errorf("parseBindNetFromAddr(%q) threw an error: %v", tt.address, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if network != tt.network {
|
|
||||||
t.Errorf("parseBindNetFromAddr(%q) wanted network: %q, got: %q", tt.address, tt.network, network)
|
|
||||||
}
|
|
||||||
|
|
||||||
if bind != tt.bind {
|
|
||||||
t.Errorf("parseBindNetFromAddr(%q) wanted bind: %q, got: %q", tt.address, tt.bind, bind)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSetupListener(t *testing.T) {
|
|
||||||
td := t.TempDir()
|
|
||||||
|
|
||||||
for _, tt := range []struct {
|
|
||||||
name string
|
|
||||||
network, address, socketMode string
|
|
||||||
wantErr bool
|
|
||||||
socketURLPrefix string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "simple tcp",
|
|
||||||
network: "",
|
|
||||||
address: ":0",
|
|
||||||
wantErr: false,
|
|
||||||
socketURLPrefix: "http://localhost:",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "simple unix",
|
|
||||||
network: "",
|
|
||||||
address: "unix://" + filepath.Join(td, "a"),
|
|
||||||
socketMode: "0770",
|
|
||||||
wantErr: false,
|
|
||||||
socketURLPrefix: "unix:" + filepath.Join(td, "a"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "tcp",
|
|
||||||
network: "tcp",
|
|
||||||
address: ":0",
|
|
||||||
wantErr: false,
|
|
||||||
socketURLPrefix: "http://localhost:",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "udp",
|
|
||||||
network: "udp",
|
|
||||||
address: ":0",
|
|
||||||
wantErr: true,
|
|
||||||
socketURLPrefix: "http://localhost:",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "unix socket",
|
|
||||||
network: "unix",
|
|
||||||
socketMode: "0770",
|
|
||||||
address: filepath.Join(td, "a"),
|
|
||||||
wantErr: false,
|
|
||||||
socketURLPrefix: "unix:" + filepath.Join(td, "a"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "invalid socket mode",
|
|
||||||
network: "unix",
|
|
||||||
socketMode: "taco bell",
|
|
||||||
address: filepath.Join(td, "a"),
|
|
||||||
wantErr: true,
|
|
||||||
socketURLPrefix: "unix:" + filepath.Join(td, "a"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "empty socket mode",
|
|
||||||
network: "unix",
|
|
||||||
socketMode: "",
|
|
||||||
address: filepath.Join(td, "a"),
|
|
||||||
wantErr: true,
|
|
||||||
socketURLPrefix: "unix:" + filepath.Join(td, "a"),
|
|
||||||
},
|
|
||||||
} {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
ln, socketURL, err := SetupListener(tt.network, tt.address, tt.socketMode)
|
|
||||||
switch {
|
|
||||||
case tt.wantErr && err == nil:
|
|
||||||
t.Errorf("SetupListener(%q, %q, %q) should have errored but did not", tt.network, tt.address, tt.socketMode)
|
|
||||||
case !tt.wantErr && err != nil:
|
|
||||||
t.Fatalf("SetupListener(%q, %q, %q) threw an error: %v", tt.network, tt.address, tt.socketMode, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ln != nil {
|
|
||||||
defer ln.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
if !tt.wantErr && !strings.HasPrefix(socketURL, tt.socketURLPrefix) {
|
|
||||||
t.Errorf("SetupListener(%q, %q, %q) should have returned a URL with prefix %q but got: %q", tt.network, tt.address, tt.socketMode, tt.socketURLPrefix, socketURL)
|
|
||||||
}
|
|
||||||
|
|
||||||
if tt.socketMode != "" {
|
|
||||||
mode, err := strconv.ParseUint(tt.socketMode, 8, 0)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
sockPath := strings.TrimPrefix(socketURL, "unix:")
|
|
||||||
st, err := os.Stat(sockPath)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("can't os.Stat(%q): %v", sockPath, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if st.Mode().Perm() != fs.FileMode(mode) {
|
|
||||||
t.Errorf("file mode of %q should be %s but is actually %s", sockPath, strconv.FormatUint(mode, 8), strconv.FormatUint(uint64(st.Mode()), 8))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -334,7 +334,6 @@ type fileConfig struct {
|
|||||||
DNSBL bool `json:"dnsbl"`
|
DNSBL bool `json:"dnsbl"`
|
||||||
DNSTTL DnsTTL `json:"dns_ttl"`
|
DNSTTL DnsTTL `json:"dns_ttl"`
|
||||||
Logging *Logging `json:"logging"`
|
Logging *Logging `json:"logging"`
|
||||||
Metrics *Metrics `json:"metrics,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *fileConfig) Valid() error {
|
func (c *fileConfig) Valid() error {
|
||||||
@@ -376,12 +375,6 @@ func (c *fileConfig) Valid() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Metrics != nil {
|
|
||||||
if err := c.Metrics.Valid(); err != nil {
|
|
||||||
errs = append(errs, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(errs) != 0 {
|
if len(errs) != 0 {
|
||||||
return fmt.Errorf("config is not valid:\n%w", errors.Join(errs...))
|
return fmt.Errorf("config is not valid:\n%w", errors.Join(errs...))
|
||||||
}
|
}
|
||||||
@@ -424,7 +417,6 @@ func Load(fin io.Reader, fname string) (*Config, error) {
|
|||||||
StatusCodes: c.StatusCodes,
|
StatusCodes: c.StatusCodes,
|
||||||
Store: c.Store,
|
Store: c.Store,
|
||||||
Logging: c.Logging,
|
Logging: c.Logging,
|
||||||
Metrics: c.Metrics,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.OpenGraph.TimeToLive != "" {
|
if c.OpenGraph.TimeToLive != "" {
|
||||||
@@ -516,7 +508,6 @@ type Config struct {
|
|||||||
Logging *Logging
|
Logging *Logging
|
||||||
DNSBL bool
|
DNSBL bool
|
||||||
DNSTTL DnsTTL
|
DNSTTL DnsTTL
|
||||||
Metrics *Metrics
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Config) Valid() error {
|
func (c Config) Valid() error {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ type Logging struct {
|
|||||||
Sink string `json:"sink"` // Logging sink, either "stdio" or "file"
|
Sink string `json:"sink"` // Logging sink, either "stdio" or "file"
|
||||||
Level *slog.Level `json:"level"` // Log level, if set supersedes the level in flags
|
Level *slog.Level `json:"level"` // Log level, if set supersedes the level in flags
|
||||||
Parameters *LoggingFileConfig `json:"parameters"` // Logging parameters, to be dynamic in the future
|
Parameters *LoggingFileConfig `json:"parameters"` // Logging parameters, to be dynamic in the future
|
||||||
|
HideSource bool `json:"hideSource"` // If true, hide the `source` field in log lines
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
package config
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrInvalidMetricsConfig = errors.New("config: invalid metrics configuration")
|
|
||||||
ErrNoMetricsBind = errors.New("config.Metrics: must define bind")
|
|
||||||
ErrNoMetricsNetwork = errors.New("config.Metrics: must define network")
|
|
||||||
ErrNoMetricsSocketMode = errors.New("config.Metrics: must define socket mode when using unix sockets")
|
|
||||||
ErrInvalidMetricsSocketMode = errors.New("config.Metrics: invalid unix socket mode")
|
|
||||||
ErrInvalidMetricsNetwork = errors.New("config.Metrics: invalid metrics network")
|
|
||||||
)
|
|
||||||
|
|
||||||
type Metrics struct {
|
|
||||||
Bind string `json:"bind" yaml:"bind"`
|
|
||||||
Network string `json:"network" yaml:"network"`
|
|
||||||
SocketMode string `json:"socketMode" yaml:"socketMode"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Metrics) Valid() error {
|
|
||||||
var errs []error
|
|
||||||
|
|
||||||
if m.Bind == "" {
|
|
||||||
errs = append(errs, ErrNoMetricsBind)
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.Network == "" {
|
|
||||||
errs = append(errs, ErrNoMetricsNetwork)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch m.Network {
|
|
||||||
case "tcp", "tcp4", "tcp6": // https://pkg.go.dev/net#Listen
|
|
||||||
case "unix":
|
|
||||||
if m.SocketMode == "" {
|
|
||||||
errs = append(errs, ErrNoMetricsSocketMode)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := strconv.ParseUint(m.SocketMode, 8, 0); err != nil {
|
|
||||||
errs = append(errs, fmt.Errorf("%w: %w", ErrInvalidMetricsSocketMode, err))
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
errs = append(errs, ErrInvalidMetricsNetwork)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(errs) != 0 {
|
|
||||||
return errors.Join(ErrInvalidMetricsConfig, errors.Join(errs...))
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
package config
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestMetricsValid(t *testing.T) {
|
|
||||||
for _, tt := range []struct {
|
|
||||||
name string
|
|
||||||
input *Metrics
|
|
||||||
err error
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "basic TCP",
|
|
||||||
input: &Metrics{
|
|
||||||
Bind: ":9090",
|
|
||||||
Network: "tcp",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "basic TCP4",
|
|
||||||
input: &Metrics{
|
|
||||||
Bind: ":9090",
|
|
||||||
Network: "tcp4",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "basic TCP6",
|
|
||||||
input: &Metrics{
|
|
||||||
Bind: ":9090",
|
|
||||||
Network: "tcp6",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "basic unix",
|
|
||||||
input: &Metrics{
|
|
||||||
Bind: "/tmp/anubis-metrics.sock",
|
|
||||||
Network: "unix",
|
|
||||||
SocketMode: "0770",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "no bind",
|
|
||||||
input: &Metrics{},
|
|
||||||
err: ErrNoMetricsBind,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "no network",
|
|
||||||
input: &Metrics{},
|
|
||||||
err: ErrNoMetricsNetwork,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "no unix socket mode",
|
|
||||||
input: &Metrics{
|
|
||||||
Bind: "/tmp/anubis-metrics.sock",
|
|
||||||
Network: "unix",
|
|
||||||
},
|
|
||||||
err: ErrNoMetricsSocketMode,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "invalid unix socket mode",
|
|
||||||
input: &Metrics{
|
|
||||||
Bind: "/tmp/anubis-metrics.sock",
|
|
||||||
Network: "unix",
|
|
||||||
SocketMode: "taco bell",
|
|
||||||
},
|
|
||||||
err: ErrInvalidMetricsSocketMode,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "invalid network",
|
|
||||||
input: &Metrics{
|
|
||||||
Bind: ":9090",
|
|
||||||
Network: "taco",
|
|
||||||
},
|
|
||||||
err: ErrInvalidMetricsNetwork,
|
|
||||||
},
|
|
||||||
} {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
if err := tt.input.Valid(); !errors.Is(err, tt.err) {
|
|
||||||
t.Logf("wanted error: %v", tt.err)
|
|
||||||
t.Logf("got error: %v", err)
|
|
||||||
t.Error("validation failed")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
metrics:
|
|
||||||
bind: ":9090"
|
|
||||||
network: taco
|
|
||||||
+1
-5
@@ -5,9 +5,5 @@
|
|||||||
"remote_addresses": ["0.0.0.0/0", "::/0"],
|
"remote_addresses": ["0.0.0.0/0", "::/0"],
|
||||||
"action": "ALLOW"
|
"action": "ALLOW"
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"metrics": {
|
|
||||||
"bind": ":9090",
|
|
||||||
"network": "tcp"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,3 @@ bots:
|
|||||||
- "0.0.0.0/0"
|
- "0.0.0.0/0"
|
||||||
- "::/0"
|
- "::/0"
|
||||||
action: ALLOW
|
action: ALLOW
|
||||||
|
|
||||||
metrics:
|
|
||||||
bind: ":9090"
|
|
||||||
network: "tcp"
|
|
||||||
|
|||||||
+1
-5
@@ -8,9 +8,5 @@
|
|||||||
"action": "DENY"
|
"action": "DENY"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dnsbl": false,
|
"dnsbl": false
|
||||||
"metrics": {
|
|
||||||
"bind": ":9090",
|
|
||||||
"network": "tcp"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,3 @@ bots:
|
|||||||
headers_regex:
|
headers_regex:
|
||||||
CF-Worker: .*
|
CF-Worker: .*
|
||||||
action: DENY
|
action: DENY
|
||||||
|
|
||||||
metrics:
|
|
||||||
bind: ":9090"
|
|
||||||
network: "tcp"
|
|
||||||
|
|||||||
@@ -4,7 +4,3 @@ bots:
|
|||||||
asns:
|
asns:
|
||||||
match:
|
match:
|
||||||
- 13335 # Cloudflare
|
- 13335 # Cloudflare
|
||||||
|
|
||||||
metrics:
|
|
||||||
bind: ":9090"
|
|
||||||
network: "tcp"
|
|
||||||
|
|||||||
+1
-5
@@ -5,9 +5,5 @@
|
|||||||
"user_agent_regex": "Mozilla",
|
"user_agent_regex": "Mozilla",
|
||||||
"action": "CHALLENGE"
|
"action": "CHALLENGE"
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"metrics": {
|
|
||||||
"bind": ":9090",
|
|
||||||
"network": "tcp"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,3 @@ bots:
|
|||||||
- name: generic-browser
|
- name: generic-browser
|
||||||
user_agent_regex: Mozilla
|
user_agent_regex: Mozilla
|
||||||
action: CHALLENGE
|
action: CHALLENGE
|
||||||
|
|
||||||
metrics:
|
|
||||||
bind: ":9090"
|
|
||||||
network: "tcp"
|
|
||||||
|
|||||||
@@ -6,7 +6,3 @@ bots:
|
|||||||
- name: "test"
|
- name: "test"
|
||||||
user_agent_regex: ".*"
|
user_agent_regex: ".*"
|
||||||
action: "DENY"
|
action: "DENY"
|
||||||
|
|
||||||
metrics:
|
|
||||||
bind: ":9090"
|
|
||||||
network: "tcp"
|
|
||||||
|
|||||||
-4
@@ -6,7 +6,3 @@ bots:
|
|||||||
- '"Accept" in headers'
|
- '"Accept" in headers'
|
||||||
- headers["Accept"].contains("text/html")
|
- headers["Accept"].contains("text/html")
|
||||||
- randInt(1) == 0
|
- randInt(1) == 0
|
||||||
|
|
||||||
metrics:
|
|
||||||
bind: ":9090"
|
|
||||||
network: "tcp"
|
|
||||||
|
|||||||
+1
-5
@@ -6,9 +6,5 @@
|
|||||||
"action": "DENY"
|
"action": "DENY"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dnsbl": false,
|
"dnsbl": false
|
||||||
"metrics": {
|
|
||||||
"bind": ":9090",
|
|
||||||
"network": "tcp"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,3 @@ bots:
|
|||||||
- name: everything
|
- name: everything
|
||||||
user_agent_regex: .*
|
user_agent_regex: .*
|
||||||
action: DENY
|
action: DENY
|
||||||
|
|
||||||
metrics:
|
|
||||||
bind: ":9090"
|
|
||||||
network: "tcp"
|
|
||||||
|
|||||||
-4
@@ -4,7 +4,3 @@ bots:
|
|||||||
geoip:
|
geoip:
|
||||||
countries:
|
countries:
|
||||||
- US
|
- US
|
||||||
|
|
||||||
metrics:
|
|
||||||
bind: ":9090"
|
|
||||||
network: "tcp"
|
|
||||||
|
|||||||
+1
-5
@@ -10,9 +10,5 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"metrics": {
|
|
||||||
"bind": ":9090",
|
|
||||||
"network": "tcp"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
-4
@@ -6,7 +6,3 @@ bots:
|
|||||||
- userAgent.startsWith("git/") || userAgent.contains("libgit")
|
- userAgent.startsWith("git/") || userAgent.contains("libgit")
|
||||||
- >
|
- >
|
||||||
"Git-Protocol" in headers && headers["Git-Protocol"] == "version=2"
|
"Git-Protocol" in headers && headers["Git-Protocol"] == "version=2"
|
||||||
|
|
||||||
metrics:
|
|
||||||
bind: ":9090"
|
|
||||||
network: "tcp"
|
|
||||||
|
|||||||
+1
-5
@@ -3,9 +3,5 @@
|
|||||||
{
|
{
|
||||||
"import": "./testdata/hack-test.json"
|
"import": "./testdata/hack-test.json"
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"metrics": {
|
|
||||||
"bind": ":9090",
|
|
||||||
"network": "tcp"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,2 @@
|
|||||||
bots:
|
bots:
|
||||||
- import: ./testdata/hack-test.yaml
|
- import: ./testdata/hack-test.yaml
|
||||||
|
|
||||||
metrics:
|
|
||||||
bind: ":9090"
|
|
||||||
network: "tcp"
|
|
||||||
|
|||||||
@@ -3,9 +3,5 @@
|
|||||||
{
|
{
|
||||||
"import": "(data)/common/keep-internet-working.yaml"
|
"import": "(data)/common/keep-internet-working.yaml"
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"metrics": {
|
|
||||||
"bind": ":9090",
|
|
||||||
"network": "tcp"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,2 @@
|
|||||||
bots:
|
bots:
|
||||||
- import: (data)/common/keep-internet-working.yaml
|
- import: (data)/common/keep-internet-working.yaml
|
||||||
|
|
||||||
metrics:
|
|
||||||
bind: ":9090"
|
|
||||||
network: "tcp"
|
|
||||||
|
|||||||
-4
@@ -8,7 +8,3 @@ impressum:
|
|||||||
page:
|
page:
|
||||||
title: Test
|
title: Test
|
||||||
body: <p>This is a test</p>
|
body: <p>This is a test</p>
|
||||||
|
|
||||||
metrics:
|
|
||||||
bind: ":9090"
|
|
||||||
network: "tcp"
|
|
||||||
|
|||||||
-4
@@ -13,7 +13,3 @@ logs:
|
|||||||
oldFileTimeFormat: 2006-01-02T15-04-05 # RFC 3339-ish
|
oldFileTimeFormat: 2006-01-02T15-04-05 # RFC 3339-ish
|
||||||
compress: true
|
compress: true
|
||||||
useLocalTime: false # timezone for rotated files is UTC
|
useLocalTime: false # timezone for rotated files is UTC
|
||||||
|
|
||||||
metrics:
|
|
||||||
bind: ":9090"
|
|
||||||
network: "tcp"
|
|
||||||
|
|||||||
-4
@@ -5,7 +5,3 @@ bots:
|
|||||||
|
|
||||||
logging:
|
logging:
|
||||||
sink: "stdio"
|
sink: "stdio"
|
||||||
|
|
||||||
metrics:
|
|
||||||
bind: ":9090"
|
|
||||||
network: "tcp"
|
|
||||||
|
|||||||
-4
@@ -6,7 +6,3 @@ bots:
|
|||||||
adjust: 5
|
adjust: 5
|
||||||
|
|
||||||
thresholds: []
|
thresholds: []
|
||||||
|
|
||||||
metrics:
|
|
||||||
bind: ":9090"
|
|
||||||
network: "tcp"
|
|
||||||
|
|||||||
+1
-5
@@ -75,9 +75,5 @@
|
|||||||
"user_agent_regex": "Mozilla",
|
"user_agent_regex": "Mozilla",
|
||||||
"action": "CHALLENGE"
|
"action": "CHALLENGE"
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"metrics": {
|
|
||||||
"bind": ":9090",
|
|
||||||
"network": "tcp"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,3 @@ openGraph:
|
|||||||
default:
|
default:
|
||||||
"og:title": "Xe's magic land of fun"
|
"og:title": "Xe's magic land of fun"
|
||||||
"og:description": "We're no strangers to love, you know the rules and so do I"
|
"og:description": "We're no strangers to love, you know the rules and so do I"
|
||||||
|
|
||||||
metrics:
|
|
||||||
bind: ":9090"
|
|
||||||
network: "tcp"
|
|
||||||
|
|||||||
-4
@@ -4,7 +4,3 @@ bots:
|
|||||||
user_agent_regex: Mozilla
|
user_agent_regex: Mozilla
|
||||||
weight:
|
weight:
|
||||||
adjust: 5
|
adjust: 5
|
||||||
|
|
||||||
metrics:
|
|
||||||
bind: ":9090"
|
|
||||||
network: "tcp"
|
|
||||||
|
|||||||
@@ -9,9 +9,5 @@
|
|||||||
"status_codes": {
|
"status_codes": {
|
||||||
"CHALLENGE": 200,
|
"CHALLENGE": 200,
|
||||||
"DENY": 200
|
"DENY": 200
|
||||||
},
|
|
||||||
"metrics": {
|
|
||||||
"bind": ":9090",
|
|
||||||
"network": "tcp"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,3 @@ bots:
|
|||||||
status_codes:
|
status_codes:
|
||||||
CHALLENGE: 200
|
CHALLENGE: 200
|
||||||
DENY: 200
|
DENY: 200
|
||||||
|
|
||||||
metrics:
|
|
||||||
bind: ":9090"
|
|
||||||
network: "tcp"
|
|
||||||
|
|||||||
@@ -9,9 +9,5 @@
|
|||||||
"status_codes": {
|
"status_codes": {
|
||||||
"CHALLENGE": 403,
|
"CHALLENGE": 403,
|
||||||
"DENY": 403
|
"DENY": 403
|
||||||
},
|
|
||||||
"metrics": {
|
|
||||||
"bind": ":9090",
|
|
||||||
"network": "tcp"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,3 @@ bots:
|
|||||||
status_codes:
|
status_codes:
|
||||||
CHALLENGE: 403
|
CHALLENGE: 403
|
||||||
DENY: 403
|
DENY: 403
|
||||||
|
|
||||||
metrics:
|
|
||||||
bind: ":9090"
|
|
||||||
network: "tcp"
|
|
||||||
|
|||||||
-4
@@ -33,7 +33,3 @@ thresholds:
|
|||||||
challenge:
|
challenge:
|
||||||
algorithm: fast
|
algorithm: fast
|
||||||
difficulty: 4
|
difficulty: 4
|
||||||
|
|
||||||
metrics:
|
|
||||||
bind: ":9090"
|
|
||||||
network: "tcp"
|
|
||||||
|
|||||||
@@ -2,7 +2,3 @@ bots:
|
|||||||
- name: weight
|
- name: weight
|
||||||
action: WEIGH
|
action: WEIGH
|
||||||
user_agent_regex: Mozilla
|
user_agent_regex: Mozilla
|
||||||
|
|
||||||
metrics:
|
|
||||||
bind: ":9090"
|
|
||||||
network: "tcp"
|
|
||||||
|
|||||||
@@ -1,81 +0,0 @@
|
|||||||
package metrics
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
"net/http"
|
|
||||||
"net/http/pprof"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/TecharoHQ/anubis/internal"
|
|
||||||
"github.com/TecharoHQ/anubis/lib/config"
|
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
|
||||||
healthv1 "google.golang.org/grpc/health/grpc_health_v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Server struct {
|
|
||||||
Config *config.Metrics
|
|
||||||
Log *slog.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Server) Run(ctx context.Context, done func()) error {
|
|
||||||
defer done()
|
|
||||||
lg := s.Log.With("subsystem", "metrics")
|
|
||||||
|
|
||||||
mux := http.NewServeMux()
|
|
||||||
mux.HandleFunc("GET /debug/pprof/", pprof.Index)
|
|
||||||
mux.HandleFunc("GET /debug/pprof/cmdline", pprof.Cmdline)
|
|
||||||
mux.HandleFunc("GET /debug/pprof/profile", pprof.Profile)
|
|
||||||
mux.HandleFunc("GET /debug/pprof/symbol", pprof.Symbol)
|
|
||||||
mux.HandleFunc("GET /debug/pprof/trace", pprof.Trace)
|
|
||||||
mux.Handle("/metrics", promhttp.Handler())
|
|
||||||
mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
st, ok := internal.GetHealth("anubis")
|
|
||||||
if !ok {
|
|
||||||
slog.Error("health service anubis does not exist, file a bug")
|
|
||||||
}
|
|
||||||
|
|
||||||
switch st {
|
|
||||||
case healthv1.HealthCheckResponse_NOT_SERVING:
|
|
||||||
http.Error(w, "NOT OK", http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
case healthv1.HealthCheckResponse_SERVING:
|
|
||||||
fmt.Fprintln(w, "OK")
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
http.Error(w, "UNKNOWN", http.StatusFailedDependency)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
srv := http.Server{
|
|
||||||
Handler: mux,
|
|
||||||
ErrorLog: internal.GetFilteredHTTPLogger(),
|
|
||||||
}
|
|
||||||
|
|
||||||
ln, metricsURL, err := internal.SetupListener(s.Config.Bind, s.Config.Network, s.Config.SocketMode)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("can't setup listener: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
defer ln.Close()
|
|
||||||
|
|
||||||
lg.Debug("listening for metrics", "url", metricsURL)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
<-ctx.Done()
|
|
||||||
c, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
||||||
defer cancel()
|
|
||||||
if err := srv.Shutdown(c); err != nil {
|
|
||||||
lg.Error("can't shut down metrics server", "err", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
if err := srv.Serve(ln); !errors.Is(err, http.ErrServerClosed) {
|
|
||||||
return fmt.Errorf("can't serve metrics server: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -46,7 +46,6 @@ type ParsedConfig struct {
|
|||||||
DnsCache *dns.DnsCache
|
DnsCache *dns.DnsCache
|
||||||
Dns *dns.Dns
|
Dns *dns.Dns
|
||||||
Logger *slog.Logger
|
Logger *slog.Logger
|
||||||
Metrics *config.Metrics
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newParsedConfig(orig *config.Config) *ParsedConfig {
|
func newParsedConfig(orig *config.Config) *ParsedConfig {
|
||||||
@@ -54,7 +53,6 @@ func newParsedConfig(orig *config.Config) *ParsedConfig {
|
|||||||
orig: orig,
|
orig: orig,
|
||||||
OpenGraph: orig.OpenGraph,
|
OpenGraph: orig.OpenGraph,
|
||||||
StatusCodes: orig.StatusCodes,
|
StatusCodes: orig.StatusCodes,
|
||||||
Metrics: orig.Metrics,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,7 +75,7 @@ func ParseConfig(ctx context.Context, fin io.Reader, fname string, defaultDiffic
|
|||||||
|
|
||||||
switch c.Logging.Sink {
|
switch c.Logging.Sink {
|
||||||
case config.LogSinkStdio:
|
case config.LogSinkStdio:
|
||||||
result.Logger = internal.InitSlog(logLevel, os.Stderr)
|
result.Logger = internal.InitSlog(logLevel, os.Stderr, c.Logging.HideSource)
|
||||||
case config.LogSinkFile:
|
case config.LogSinkFile:
|
||||||
out := &logrotate.Logger{
|
out := &logrotate.Logger{
|
||||||
Filename: c.Logging.Parameters.Filename,
|
Filename: c.Logging.Parameters.Filename,
|
||||||
@@ -89,7 +87,7 @@ func ParseConfig(ctx context.Context, fin io.Reader, fname string, defaultDiffic
|
|||||||
Compress: c.Logging.Parameters.Compress,
|
Compress: c.Logging.Parameters.Compress,
|
||||||
}
|
}
|
||||||
|
|
||||||
result.Logger = internal.InitSlog(logLevel, out)
|
result.Logger = internal.InitSlog(logLevel, out, c.Logging.HideSource)
|
||||||
}
|
}
|
||||||
|
|
||||||
lg := result.Logger.With("at", "config-validate")
|
lg := result.Logger.With("at", "config-validate")
|
||||||
|
|||||||
Generated
+160
-160
@@ -10,15 +10,15 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-crypto/sha256-js": "^5.2.0",
|
"@aws-crypto/sha256-js": "^5.2.0",
|
||||||
"preact": "^10.29.1"
|
"preact": "^10.28.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "^20.5.0",
|
"@commitlint/cli": "^20.4.3",
|
||||||
"@commitlint/config-conventional": "^20.5.0",
|
"@commitlint/config-conventional": "^20.4.3",
|
||||||
"baseline-browser-mapping": "^2.10.15",
|
"baseline-browser-mapping": "^2.10.0",
|
||||||
"cssnano": "^7.1.4",
|
"cssnano": "^7.1.3",
|
||||||
"cssnano-preset-advanced": "^7.0.12",
|
"cssnano-preset-advanced": "^7.0.11",
|
||||||
"esbuild": "^0.28.0",
|
"esbuild": "^0.27.3",
|
||||||
"husky": "^9.1.7",
|
"husky": "^9.1.7",
|
||||||
"playwright": "^1.52.0",
|
"playwright": "^1.52.0",
|
||||||
"postcss-cli": "^11.0.1",
|
"postcss-cli": "^11.0.1",
|
||||||
@@ -91,25 +91,18 @@
|
|||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@colordx/core": {
|
|
||||||
"version": "5.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@colordx/core/-/core-5.0.3.tgz",
|
|
||||||
"integrity": "sha512-xBQ0MYRTNNxW3mS2sJtlQTT7C3Sasqgh1/PsHva7fyDb5uqYY+gv9V0utDdX8X80mqzbGz3u/IDJdn2d/uW09g==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/@commitlint/cli": {
|
"node_modules/@commitlint/cli": {
|
||||||
"version": "20.5.0",
|
"version": "20.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-20.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-20.4.3.tgz",
|
||||||
"integrity": "sha512-yNkyN/tuKTJS3wdVfsZ2tXDM4G4Gi7z+jW54Cki8N8tZqwKBltbIvUUrSbT4hz1bhW/h0CdR+5sCSpXD+wMKaQ==",
|
"integrity": "sha512-Z37EMoDT7+Upg500vlr/vZrgRsb6Xc5JAA3Tv7BYbobnN/ZpqUeZnSLggBg2+1O+NptRDtyujr2DD1CPV2qwhA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@commitlint/format": "^20.5.0",
|
"@commitlint/format": "^20.4.3",
|
||||||
"@commitlint/lint": "^20.5.0",
|
"@commitlint/lint": "^20.4.3",
|
||||||
"@commitlint/load": "^20.5.0",
|
"@commitlint/load": "^20.4.3",
|
||||||
"@commitlint/read": "^20.5.0",
|
"@commitlint/read": "^20.4.3",
|
||||||
"@commitlint/types": "^20.5.0",
|
"@commitlint/types": "^20.4.3",
|
||||||
"tinyexec": "^1.0.0",
|
"tinyexec": "^1.0.0",
|
||||||
"yargs": "^17.0.0"
|
"yargs": "^17.0.0"
|
||||||
},
|
},
|
||||||
@@ -121,13 +114,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@commitlint/config-conventional": {
|
"node_modules/@commitlint/config-conventional": {
|
||||||
"version": "20.5.0",
|
"version": "20.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-20.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-20.4.3.tgz",
|
||||||
"integrity": "sha512-t3Ni88rFw1XMa4nZHgOKJ8fIAT9M2j5TnKyTqJzsxea7FUetlNdYFus9dz+MhIRZmc16P0PPyEfh6X2d/qw8SA==",
|
"integrity": "sha512-9RtLySbYQAs8yEqWEqhSZo9nYhbm57jx7qHXtgRmv/nmeQIjjMcwf6Dl+y5UZcGWgWx435TAYBURONaJIuCjWg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@commitlint/types": "^20.5.0",
|
"@commitlint/types": "^20.4.3",
|
||||||
"conventional-changelog-conventionalcommits": "^9.2.0"
|
"conventional-changelog-conventionalcommits": "^9.2.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -408,9 +401,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/aix-ppc64": {
|
"node_modules/@esbuild/aix-ppc64": {
|
||||||
"version": "0.28.0",
|
"version": "0.27.3",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz",
|
||||||
"integrity": "sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==",
|
"integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
@@ -425,9 +418,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/android-arm": {
|
"node_modules/@esbuild/android-arm": {
|
||||||
"version": "0.28.0",
|
"version": "0.27.3",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz",
|
||||||
"integrity": "sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==",
|
"integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@@ -442,9 +435,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/android-arm64": {
|
"node_modules/@esbuild/android-arm64": {
|
||||||
"version": "0.28.0",
|
"version": "0.27.3",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz",
|
||||||
"integrity": "sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==",
|
"integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -459,9 +452,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/android-x64": {
|
"node_modules/@esbuild/android-x64": {
|
||||||
"version": "0.28.0",
|
"version": "0.27.3",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz",
|
||||||
"integrity": "sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==",
|
"integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -476,9 +469,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/darwin-arm64": {
|
"node_modules/@esbuild/darwin-arm64": {
|
||||||
"version": "0.28.0",
|
"version": "0.27.3",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz",
|
||||||
"integrity": "sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==",
|
"integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -493,9 +486,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/darwin-x64": {
|
"node_modules/@esbuild/darwin-x64": {
|
||||||
"version": "0.28.0",
|
"version": "0.27.3",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz",
|
||||||
"integrity": "sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==",
|
"integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -510,9 +503,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/freebsd-arm64": {
|
"node_modules/@esbuild/freebsd-arm64": {
|
||||||
"version": "0.28.0",
|
"version": "0.27.3",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz",
|
||||||
"integrity": "sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==",
|
"integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -527,9 +520,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/freebsd-x64": {
|
"node_modules/@esbuild/freebsd-x64": {
|
||||||
"version": "0.28.0",
|
"version": "0.27.3",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz",
|
||||||
"integrity": "sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==",
|
"integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -544,9 +537,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-arm": {
|
"node_modules/@esbuild/linux-arm": {
|
||||||
"version": "0.28.0",
|
"version": "0.27.3",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz",
|
||||||
"integrity": "sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==",
|
"integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@@ -561,9 +554,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-arm64": {
|
"node_modules/@esbuild/linux-arm64": {
|
||||||
"version": "0.28.0",
|
"version": "0.27.3",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz",
|
||||||
"integrity": "sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==",
|
"integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -578,9 +571,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-ia32": {
|
"node_modules/@esbuild/linux-ia32": {
|
||||||
"version": "0.28.0",
|
"version": "0.27.3",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz",
|
||||||
"integrity": "sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==",
|
"integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
@@ -595,9 +588,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-loong64": {
|
"node_modules/@esbuild/linux-loong64": {
|
||||||
"version": "0.28.0",
|
"version": "0.27.3",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz",
|
||||||
"integrity": "sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==",
|
"integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"loong64"
|
"loong64"
|
||||||
],
|
],
|
||||||
@@ -612,9 +605,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-mips64el": {
|
"node_modules/@esbuild/linux-mips64el": {
|
||||||
"version": "0.28.0",
|
"version": "0.27.3",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz",
|
||||||
"integrity": "sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==",
|
"integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"mips64el"
|
"mips64el"
|
||||||
],
|
],
|
||||||
@@ -629,9 +622,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-ppc64": {
|
"node_modules/@esbuild/linux-ppc64": {
|
||||||
"version": "0.28.0",
|
"version": "0.27.3",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz",
|
||||||
"integrity": "sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==",
|
"integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
@@ -646,9 +639,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-riscv64": {
|
"node_modules/@esbuild/linux-riscv64": {
|
||||||
"version": "0.28.0",
|
"version": "0.27.3",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz",
|
||||||
"integrity": "sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==",
|
"integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"riscv64"
|
"riscv64"
|
||||||
],
|
],
|
||||||
@@ -663,9 +656,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-s390x": {
|
"node_modules/@esbuild/linux-s390x": {
|
||||||
"version": "0.28.0",
|
"version": "0.27.3",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz",
|
||||||
"integrity": "sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==",
|
"integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"s390x"
|
"s390x"
|
||||||
],
|
],
|
||||||
@@ -680,9 +673,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-x64": {
|
"node_modules/@esbuild/linux-x64": {
|
||||||
"version": "0.28.0",
|
"version": "0.27.3",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz",
|
||||||
"integrity": "sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==",
|
"integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -697,9 +690,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/netbsd-arm64": {
|
"node_modules/@esbuild/netbsd-arm64": {
|
||||||
"version": "0.28.0",
|
"version": "0.27.3",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz",
|
||||||
"integrity": "sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==",
|
"integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -714,9 +707,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/netbsd-x64": {
|
"node_modules/@esbuild/netbsd-x64": {
|
||||||
"version": "0.28.0",
|
"version": "0.27.3",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz",
|
||||||
"integrity": "sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==",
|
"integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -731,9 +724,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/openbsd-arm64": {
|
"node_modules/@esbuild/openbsd-arm64": {
|
||||||
"version": "0.28.0",
|
"version": "0.27.3",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz",
|
||||||
"integrity": "sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==",
|
"integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -748,9 +741,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/openbsd-x64": {
|
"node_modules/@esbuild/openbsd-x64": {
|
||||||
"version": "0.28.0",
|
"version": "0.27.3",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz",
|
||||||
"integrity": "sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==",
|
"integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -765,9 +758,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/openharmony-arm64": {
|
"node_modules/@esbuild/openharmony-arm64": {
|
||||||
"version": "0.28.0",
|
"version": "0.27.3",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz",
|
||||||
"integrity": "sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==",
|
"integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -782,9 +775,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/sunos-x64": {
|
"node_modules/@esbuild/sunos-x64": {
|
||||||
"version": "0.28.0",
|
"version": "0.27.3",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz",
|
||||||
"integrity": "sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==",
|
"integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -799,9 +792,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/win32-arm64": {
|
"node_modules/@esbuild/win32-arm64": {
|
||||||
"version": "0.28.0",
|
"version": "0.27.3",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz",
|
||||||
"integrity": "sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==",
|
"integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -816,9 +809,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/win32-ia32": {
|
"node_modules/@esbuild/win32-ia32": {
|
||||||
"version": "0.28.0",
|
"version": "0.27.3",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz",
|
||||||
"integrity": "sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==",
|
"integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
@@ -833,9 +826,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/win32-x64": {
|
"node_modules/@esbuild/win32-x64": {
|
||||||
"version": "0.28.0",
|
"version": "0.27.3",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz",
|
||||||
"integrity": "sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==",
|
"integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -1055,9 +1048,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/baseline-browser-mapping": {
|
"node_modules/baseline-browser-mapping": {
|
||||||
"version": "2.10.15",
|
"version": "2.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.15.tgz",
|
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz",
|
||||||
"integrity": "sha512-1nfKCq9wuAZFTkA2ey/3OXXx7GzFjLdkTiFVNwlJ9WqdI706CZRIhEqjuwanjMIja+84jDLa9rcyZDPDiVkASQ==",
|
"integrity": "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"bin": {
|
"bin": {
|
||||||
@@ -1249,6 +1242,13 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/colord": {
|
||||||
|
"version": "2.9.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz",
|
||||||
|
"integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/commander": {
|
"node_modules/commander": {
|
||||||
"version": "11.1.0",
|
"version": "11.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
|
||||||
@@ -1436,13 +1436,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/cssnano": {
|
"node_modules/cssnano": {
|
||||||
"version": "7.1.4",
|
"version": "7.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/cssnano/-/cssnano-7.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/cssnano/-/cssnano-7.1.3.tgz",
|
||||||
"integrity": "sha512-T9PNS7y+5Nc9Qmu9mRONqfxG1RVY7Vuvky0XN6MZ+9hqplesTEwnj9r0ROtVuSwUVfaDhVlavuzWIVLUgm4hkQ==",
|
"integrity": "sha512-mLFHQAzyapMVFLiJIn7Ef4C2UCEvtlTlbyILR6B5ZsUAV3D/Pa761R5uC1YPhyBkRd3eqaDm2ncaNrD7R4mTRg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cssnano-preset-default": "^7.0.12",
|
"cssnano-preset-default": "^7.0.11",
|
||||||
"lilconfig": "^3.1.3"
|
"lilconfig": "^3.1.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -1457,15 +1457,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/cssnano-preset-advanced": {
|
"node_modules/cssnano-preset-advanced": {
|
||||||
"version": "7.0.12",
|
"version": "7.0.11",
|
||||||
"resolved": "https://registry.npmjs.org/cssnano-preset-advanced/-/cssnano-preset-advanced-7.0.12.tgz",
|
"resolved": "https://registry.npmjs.org/cssnano-preset-advanced/-/cssnano-preset-advanced-7.0.11.tgz",
|
||||||
"integrity": "sha512-S+UCfEMBCaYqNmjY+yCTNh4ur+B83z5qpwkzUMER6kVpdQ5CBUxIkALZGhp2KPP3M4VefRCIBMqJ6Z0PFMwvEA==",
|
"integrity": "sha512-k9Dz/8TBOmLojoMZ+2xwrGjscU1XwYVDVB9T1AmvZcwiWz4ibWm8/y+/SN5jhYcpMPTeDe7FhI2uEYlNq1iDGg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"autoprefixer": "^10.4.27",
|
"autoprefixer": "^10.4.27",
|
||||||
"browserslist": "^4.28.1",
|
"browserslist": "^4.28.1",
|
||||||
"cssnano-preset-default": "^7.0.12",
|
"cssnano-preset-default": "^7.0.11",
|
||||||
"postcss-discard-unused": "^7.0.5",
|
"postcss-discard-unused": "^7.0.5",
|
||||||
"postcss-merge-idents": "^7.0.1",
|
"postcss-merge-idents": "^7.0.1",
|
||||||
"postcss-reduce-idents": "^7.0.1",
|
"postcss-reduce-idents": "^7.0.1",
|
||||||
@@ -1479,9 +1479,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/cssnano-preset-default": {
|
"node_modules/cssnano-preset-default": {
|
||||||
"version": "7.0.12",
|
"version": "7.0.11",
|
||||||
"resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-7.0.12.tgz",
|
"resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-7.0.11.tgz",
|
||||||
"integrity": "sha512-B3Eoouzw/sl2zANI0AL9KbacummJTCww+fkHaDBMZad/xuVx8bUduPLly6hKVQAlrmvYkS1jB1CVQEKm3gn0AA==",
|
"integrity": "sha512-waWlAMuCakP7//UCY+JPrQS1z0OSLeOXk2sKWJximKWGupVxre50bzPlvpbUwZIDylhf/ptf0Pk+Yf7C+hoa3g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -1489,7 +1489,7 @@
|
|||||||
"css-declaration-sorter": "^7.2.0",
|
"css-declaration-sorter": "^7.2.0",
|
||||||
"cssnano-utils": "^5.0.1",
|
"cssnano-utils": "^5.0.1",
|
||||||
"postcss-calc": "^10.1.1",
|
"postcss-calc": "^10.1.1",
|
||||||
"postcss-colormin": "^7.0.7",
|
"postcss-colormin": "^7.0.6",
|
||||||
"postcss-convert-values": "^7.0.9",
|
"postcss-convert-values": "^7.0.9",
|
||||||
"postcss-discard-comments": "^7.0.6",
|
"postcss-discard-comments": "^7.0.6",
|
||||||
"postcss-discard-duplicates": "^7.0.2",
|
"postcss-discard-duplicates": "^7.0.2",
|
||||||
@@ -1498,7 +1498,7 @@
|
|||||||
"postcss-merge-longhand": "^7.0.5",
|
"postcss-merge-longhand": "^7.0.5",
|
||||||
"postcss-merge-rules": "^7.0.8",
|
"postcss-merge-rules": "^7.0.8",
|
||||||
"postcss-minify-font-values": "^7.0.1",
|
"postcss-minify-font-values": "^7.0.1",
|
||||||
"postcss-minify-gradients": "^7.0.2",
|
"postcss-minify-gradients": "^7.0.1",
|
||||||
"postcss-minify-params": "^7.0.6",
|
"postcss-minify-params": "^7.0.6",
|
||||||
"postcss-minify-selectors": "^7.0.6",
|
"postcss-minify-selectors": "^7.0.6",
|
||||||
"postcss-normalize-charset": "^7.0.1",
|
"postcss-normalize-charset": "^7.0.1",
|
||||||
@@ -1709,9 +1709,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/esbuild": {
|
"node_modules/esbuild": {
|
||||||
"version": "0.28.0",
|
"version": "0.27.3",
|
||||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz",
|
||||||
"integrity": "sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==",
|
"integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -1722,32 +1722,32 @@
|
|||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@esbuild/aix-ppc64": "0.28.0",
|
"@esbuild/aix-ppc64": "0.27.3",
|
||||||
"@esbuild/android-arm": "0.28.0",
|
"@esbuild/android-arm": "0.27.3",
|
||||||
"@esbuild/android-arm64": "0.28.0",
|
"@esbuild/android-arm64": "0.27.3",
|
||||||
"@esbuild/android-x64": "0.28.0",
|
"@esbuild/android-x64": "0.27.3",
|
||||||
"@esbuild/darwin-arm64": "0.28.0",
|
"@esbuild/darwin-arm64": "0.27.3",
|
||||||
"@esbuild/darwin-x64": "0.28.0",
|
"@esbuild/darwin-x64": "0.27.3",
|
||||||
"@esbuild/freebsd-arm64": "0.28.0",
|
"@esbuild/freebsd-arm64": "0.27.3",
|
||||||
"@esbuild/freebsd-x64": "0.28.0",
|
"@esbuild/freebsd-x64": "0.27.3",
|
||||||
"@esbuild/linux-arm": "0.28.0",
|
"@esbuild/linux-arm": "0.27.3",
|
||||||
"@esbuild/linux-arm64": "0.28.0",
|
"@esbuild/linux-arm64": "0.27.3",
|
||||||
"@esbuild/linux-ia32": "0.28.0",
|
"@esbuild/linux-ia32": "0.27.3",
|
||||||
"@esbuild/linux-loong64": "0.28.0",
|
"@esbuild/linux-loong64": "0.27.3",
|
||||||
"@esbuild/linux-mips64el": "0.28.0",
|
"@esbuild/linux-mips64el": "0.27.3",
|
||||||
"@esbuild/linux-ppc64": "0.28.0",
|
"@esbuild/linux-ppc64": "0.27.3",
|
||||||
"@esbuild/linux-riscv64": "0.28.0",
|
"@esbuild/linux-riscv64": "0.27.3",
|
||||||
"@esbuild/linux-s390x": "0.28.0",
|
"@esbuild/linux-s390x": "0.27.3",
|
||||||
"@esbuild/linux-x64": "0.28.0",
|
"@esbuild/linux-x64": "0.27.3",
|
||||||
"@esbuild/netbsd-arm64": "0.28.0",
|
"@esbuild/netbsd-arm64": "0.27.3",
|
||||||
"@esbuild/netbsd-x64": "0.28.0",
|
"@esbuild/netbsd-x64": "0.27.3",
|
||||||
"@esbuild/openbsd-arm64": "0.28.0",
|
"@esbuild/openbsd-arm64": "0.27.3",
|
||||||
"@esbuild/openbsd-x64": "0.28.0",
|
"@esbuild/openbsd-x64": "0.27.3",
|
||||||
"@esbuild/openharmony-arm64": "0.28.0",
|
"@esbuild/openharmony-arm64": "0.27.3",
|
||||||
"@esbuild/sunos-x64": "0.28.0",
|
"@esbuild/sunos-x64": "0.27.3",
|
||||||
"@esbuild/win32-arm64": "0.28.0",
|
"@esbuild/win32-arm64": "0.27.3",
|
||||||
"@esbuild/win32-ia32": "0.28.0",
|
"@esbuild/win32-ia32": "0.27.3",
|
||||||
"@esbuild/win32-x64": "0.28.0"
|
"@esbuild/win32-x64": "0.27.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/escalade": {
|
"node_modules/escalade": {
|
||||||
@@ -2554,15 +2554,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/postcss-colormin": {
|
"node_modules/postcss-colormin": {
|
||||||
"version": "7.0.7",
|
"version": "7.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-7.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-7.0.6.tgz",
|
||||||
"integrity": "sha512-sBQ628lSj3VQpDquQel8Pen5mmjFPsO4pH9lDLaHB1AVkMRHtkl0pRB5DCWznc9upWsxint/kV+AveSj7W1tew==",
|
"integrity": "sha512-oXM2mdx6IBTRm39797QguYzVEWzbdlFiMNfq88fCCN1Wepw3CYmJ/1/Ifa/KjWo+j5ZURDl2NTldLJIw51IeNQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@colordx/core": "^5.0.0",
|
|
||||||
"browserslist": "^4.28.1",
|
"browserslist": "^4.28.1",
|
||||||
"caniuse-api": "^3.0.0",
|
"caniuse-api": "^3.0.0",
|
||||||
|
"colord": "^2.9.3",
|
||||||
"postcss-value-parser": "^4.2.0"
|
"postcss-value-parser": "^4.2.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -2808,13 +2808,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/postcss-minify-gradients": {
|
"node_modules/postcss-minify-gradients": {
|
||||||
"version": "7.0.2",
|
"version": "7.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-7.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-7.0.1.tgz",
|
||||||
"integrity": "sha512-fVY3AB8Um7SJR5usHqTY2Ngf9qh8IRN+FFzrBP0ONJy6yYXsP7xyjK2BvSAIrpgs1cST+H91V0TXi3diHLYJtw==",
|
"integrity": "sha512-X9JjaysZJwlqNkJbUDgOclyG3jZEpAMOfof6PUZjPnPrePnPG62pS17CjdM32uT1Uq1jFvNSff9l7kNbmMSL2A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@colordx/core": "^5.0.0",
|
"colord": "^2.9.3",
|
||||||
"cssnano-utils": "^5.0.1",
|
"cssnano-utils": "^5.0.1",
|
||||||
"postcss-value-parser": "^4.2.0"
|
"postcss-value-parser": "^4.2.0"
|
||||||
},
|
},
|
||||||
@@ -3182,9 +3182,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/preact": {
|
"node_modules/preact": {
|
||||||
"version": "10.29.1",
|
"version": "10.28.4",
|
||||||
"resolved": "https://registry.npmjs.org/preact/-/preact-10.29.1.tgz",
|
"resolved": "https://registry.npmjs.org/preact/-/preact-10.28.4.tgz",
|
||||||
"integrity": "sha512-gQCLc/vWroE8lIpleXtdJhTFDogTdZG9AjMUpVkDf2iTCNwYNWA+u16dL41TqUDJO4gm2IgrcMv3uTpjd4Pwmg==",
|
"integrity": "sha512-uKFfOHWuSNpRFVTnljsCluEFq57OKT+0QdOiQo8XWnQ/pSvg7OpX5eNOejELXJMWy+BwM2nobz0FkvzmnpCNsQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
|
|||||||
+7
-7
@@ -20,12 +20,12 @@
|
|||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "^20.5.0",
|
"@commitlint/cli": "^20.4.3",
|
||||||
"@commitlint/config-conventional": "^20.5.0",
|
"@commitlint/config-conventional": "^20.4.3",
|
||||||
"baseline-browser-mapping": "^2.10.15",
|
"baseline-browser-mapping": "^2.10.0",
|
||||||
"cssnano": "^7.1.4",
|
"cssnano": "^7.1.3",
|
||||||
"cssnano-preset-advanced": "^7.0.12",
|
"cssnano-preset-advanced": "^7.0.11",
|
||||||
"esbuild": "^0.28.0",
|
"esbuild": "^0.27.3",
|
||||||
"husky": "^9.1.7",
|
"husky": "^9.1.7",
|
||||||
"playwright": "^1.52.0",
|
"playwright": "^1.52.0",
|
||||||
"postcss-cli": "^11.0.1",
|
"postcss-cli": "^11.0.1",
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-crypto/sha256-js": "^5.2.0",
|
"@aws-crypto/sha256-js": "^5.2.0",
|
||||||
"preact": "^10.29.1"
|
"preact": "^10.28.4"
|
||||||
},
|
},
|
||||||
"commitlint": {
|
"commitlint": {
|
||||||
"extends": [
|
"extends": [
|
||||||
|
|||||||
Reference in New Issue
Block a user