Compare commits

..

6 Commits

Author SHA1 Message Date
Xe Iaso c8bff8f137 docs(admin/policies): give people a python command
Signed-off-by: Xe Iaso <me@xeiaso.net>
2026-04-22 23:52:09 -04:00
Xe Iaso cca88fa520 chore: spelling
Signed-off-by: Xe Iaso <me@xeiaso.net>
2026-04-22 23:27:05 -04:00
Xe Iaso 6ecb909bfd doc: document HTTP basic auth for metrics server
Signed-off-by: Xe Iaso <me@xeiaso.net>
2026-04-22 23:24:23 -04:00
Xe Iaso 1a7b7601f9 feat(metrics): wire up basic auth
Signed-off-by: Xe Iaso <me@xeiaso.net>
2026-04-22 23:16:31 -04:00
Xe Iaso 2cbc1b0917 feat(config): add HTTP basic auth for metrics
Signed-off-by: Xe Iaso <me@xeiaso.net>
2026-04-22 23:16:20 -04:00
Xe Iaso 40de0bf9f4 feat(internal): add basic auth HTTP middleware
Signed-off-by: Xe Iaso <me@xeiaso.net>
2026-04-22 23:04:24 -04:00
14 changed files with 47 additions and 32 deletions
+1 -1
View File
@@ -22,7 +22,7 @@ jobs:
sudo apt-get update sudo apt-get update
sudo apt-get install -y build-essential sudo apt-get install -y build-essential
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.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@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
+1 -1
View File
@@ -26,7 +26,7 @@ jobs:
sudo apt-get update sudo apt-get update
sudo apt-get install -y build-essential sudo apt-get install -y build-essential
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.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@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
+1 -1
View File
@@ -36,7 +36,7 @@ jobs:
run: | run: |
echo "IMAGE=ghcr.io/${GITHUB_REPOSITORY,,}" >> $GITHUB_ENV echo "IMAGE=ghcr.io/${GITHUB_REPOSITORY,,}" >> $GITHUB_ENV
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.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@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
+3 -3
View File
@@ -42,7 +42,7 @@ jobs:
- name: Build and push - name: Build and push
id: build id: build
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0 uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
with: with:
context: ./docs context: ./docs
cache-to: type=gha cache-to: type=gha
@@ -53,14 +53,14 @@ jobs:
push: true push: true
- name: Apply k8s manifests to limsa lominsa - name: Apply k8s manifests to limsa lominsa
uses: actions-hub/kubectl@f8645c756533365a9fc1ae9aad8980b2a892d2c2 # v1.36.0 uses: actions-hub/kubectl@934aaa4354bbbc3d2176ae8d7cae92d515032dff # v1.35.3
env: env:
KUBE_CONFIG: ${{ secrets.LIMSA_LOMINSA_KUBECONFIG }} KUBE_CONFIG: ${{ secrets.LIMSA_LOMINSA_KUBECONFIG }}
with: with:
args: apply -k docs/manifest args: apply -k docs/manifest
- name: Apply k8s manifests to limsa lominsa - name: Apply k8s manifests to limsa lominsa
uses: actions-hub/kubectl@f8645c756533365a9fc1ae9aad8980b2a892d2c2 # v1.36.0 uses: actions-hub/kubectl@934aaa4354bbbc3d2176ae8d7cae92d515032dff # v1.35.3
env: env:
KUBE_CONFIG: ${{ secrets.LIMSA_LOMINSA_KUBECONFIG }} KUBE_CONFIG: ${{ secrets.LIMSA_LOMINSA_KUBECONFIG }}
with: with:
+1 -1
View File
@@ -31,7 +31,7 @@ jobs:
- name: Build and push - name: Build and push
id: build id: build
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0 uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
with: with:
context: ./docs context: ./docs
cache-to: type=gha cache-to: type=gha
+2 -2
View File
@@ -24,7 +24,7 @@ jobs:
sudo apt-get update sudo apt-get update
sudo apt-get install -y build-essential sudo apt-get install -y build-essential
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.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@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
@@ -32,7 +32,7 @@ jobs:
go-version: "stable" go-version: "stable"
- name: Cache playwright binaries - name: Cache playwright binaries
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
id: playwright-cache id: playwright-cache
with: with:
path: | path: |
+1 -1
View File
@@ -25,7 +25,7 @@ jobs:
sudo apt-get update sudo apt-get update
sudo apt-get install -y build-essential sudo apt-get install -y build-essential
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.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@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
@@ -26,7 +26,7 @@ jobs:
sudo apt-get update sudo apt-get update
sudo apt-get install -y build-essential sudo apt-get install -y build-essential
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.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@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
@@ -41,7 +41,7 @@ jobs:
run: | run: |
go tool yeet go tool yeet
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with: with:
name: packages name: packages
path: var/* path: var/*
+2 -2
View File
@@ -34,7 +34,7 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.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@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
@@ -57,7 +57,7 @@ jobs:
run: echo "ARTIFACT_NAME=${{ matrix.test }}" | sed 's|/|-|g' >> $GITHUB_ENV run: echo "ARTIFACT_NAME=${{ matrix.test }}" | sed 's|/|-|g' >> $GITHUB_ENV
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f
if: always() if: always()
with: with:
name: ${{ env.ARTIFACT_NAME }} name: ${{ env.ARTIFACT_NAME }}
+2 -2
View File
@@ -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@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.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@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 uses: github/codeql-action/upload-sarif@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1
with: with:
sarif_file: results.sarif sarif_file: results.sarif
category: zizmor category: zizmor
-2
View File
@@ -20,11 +20,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- 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))
- Fixed case-sensitivity mismatch in geoipchecker.go
- 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)).
- Enable [metrics serving via TLS](./admin/policies.mdx#tls), including [mutual TLS (mTLS)](./admin/policies.mdx#mtls). - Enable [metrics serving via TLS](./admin/policies.mdx#tls), including [mutual TLS (mTLS)](./admin/policies.mdx#mtls).
- Enable [HTTP basic auth](./admin/policies.mdx#http-basic-authentication) for the metrics server. - Enable [HTTP basic auth](./admin/policies.mdx#http-basic-authentication) for the metrics server.
- Fix a bug in the dataset poisoning maze that could allow denial of service [#1580](https://github.com/TecharoHQ/anubis/issues/1580).
## v1.25.0: Necron ## v1.25.0: Necron
+22 -13
View File
@@ -76,6 +76,13 @@ type Impl struct {
affirmation, body, title spintax.Spintax affirmation, body, title spintax.Spintax
} }
func (i *Impl) incrementUA(ctx context.Context, userAgent string) int {
result, _ := i.uaWeight.Get(ctx, internal.SHA256sum(userAgent))
result++
i.uaWeight.Set(ctx, internal.SHA256sum(userAgent), result, time.Hour)
return result
}
func (i *Impl) incrementNetwork(ctx context.Context, network string) int { func (i *Impl) incrementNetwork(ctx context.Context, network string) int {
result, _ := i.networkWeight.Get(ctx, internal.SHA256sum(network)) result, _ := i.networkWeight.Get(ctx, internal.SHA256sum(network))
result++ result++
@@ -83,19 +90,20 @@ func (i *Impl) incrementNetwork(ctx context.Context, network string) int {
return result return result
} }
func (i *Impl) CheckUA() checker.Impl {
return checker.Func(func(r *http.Request) (bool, error) {
result, _ := i.uaWeight.Get(r.Context(), internal.SHA256sum(r.UserAgent()))
if result >= 25 {
return true, nil
}
return false, nil
})
}
func (i *Impl) CheckNetwork() checker.Impl { func (i *Impl) CheckNetwork() checker.Impl {
return checker.Func(func(r *http.Request) (bool, error) { return checker.Func(func(r *http.Request) (bool, error) {
realIP, _ := internal.RealIP(r) result, _ := i.uaWeight.Get(r.Context(), internal.SHA256sum(r.UserAgent()))
if !realIP.IsValid() {
realIP = netip.MustParseAddr(r.Header.Get("X-Real-Ip"))
}
network, ok := internal.ClampIP(realIP)
if !ok {
return false, nil
}
result, _ := i.networkWeight.Get(r.Context(), internal.SHA256sum(network.String()))
if result >= 25 { if result >= 25 {
return true, nil return true, nil
} }
@@ -156,6 +164,7 @@ func (i *Impl) ServeHTTP(w http.ResponseWriter, r *http.Request) {
} }
networkCount := i.incrementNetwork(r.Context(), network.String()) networkCount := i.incrementNetwork(r.Context(), network.String())
uaCount := i.incrementUA(r.Context(), r.UserAgent())
stage := r.PathValue("stage") stage := r.PathValue("stage")
@@ -163,8 +172,8 @@ func (i *Impl) ServeHTTP(w http.ResponseWriter, r *http.Request) {
lg.Debug("found new entrance point", "id", id, "stage", stage, "userAgent", r.UserAgent(), "clampedIP", network) lg.Debug("found new entrance point", "id", id, "stage", stage, "userAgent", r.UserAgent(), "clampedIP", network)
} else { } else {
switch { switch {
case networkCount%256 == 0: case networkCount%256 == 0, uaCount%256 == 0:
lg.Warn("found possible crawler", "id", id, "network", network, "userAgent", r.UserAgent()) lg.Warn("found possible crawler", "id", id, "network", network)
} }
} }
+8
View File
@@ -190,6 +190,14 @@ func New(opts Options) (*Server, error) {
}, },
Name: "honeypot/network", Name: "honeypot/network",
}, },
policy.Bot{
Rules: mazeGen.CheckUA(),
Action: config.RuleWeigh,
Weight: &config.Weight{
Adjust: 30,
},
Name: "honeypot/user-agent",
},
) )
} else { } else {
result.logger.Error("can't init honeypot subsystem", "err", err) result.logger.Error("can't init honeypot subsystem", "err", err)
+1 -1
View File
@@ -18,7 +18,7 @@ func (c *Client) GeoIPCheckerFor(countries []string) checker.Impl {
var sb strings.Builder var sb strings.Builder
fmt.Fprintln(&sb, "GeoIPChecker") fmt.Fprintln(&sb, "GeoIPChecker")
for _, cc := range countries { for _, cc := range countries {
countryMap[strings.ToLower(cc)] = struct{}{} countryMap[cc] = struct{}{}
fmt.Fprintln(&sb, cc) fmt.Fprintln(&sb, cc)
} }