aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXe Iaso <me@xeiaso.net>2025-03-27 08:41:17 -0400
committerXe Iaso <me@xeiaso.net>2025-03-27 08:41:17 -0400
commitee1ccfe109e47ec6ec4fb20a12e0e5b93e24c846 (patch)
treeec87f6ad4d3aaabe1636203d0937c0dc05f6deaf
parent43c442bc1f75a030f57c8887dee18d94fd6e2509 (diff)
downloadanubis-ee1ccfe109e47ec6ec4fb20a12e0e5b93e24c846.tar.xz
anubis-ee1ccfe109e47ec6ec4fb20a12e0e5b93e24c846.zip
add COOKIE_PARTITIONED flag
Signed-off-by: Xe Iaso <me@xeiaso.net>
-rw-r--r--cmd/anubis/main.go12
-rw-r--r--docs/docs/CHANGELOG.md3
-rw-r--r--docs/docs/admin/installation.mdx1
-rw-r--r--lib/anubis.go13
-rw-r--r--lib/anubis_test.go19
5 files changed, 29 insertions, 19 deletions
diff --git a/cmd/anubis/main.go b/cmd/anubis/main.go
index c380ae0..7f98e7b 100644
--- a/cmd/anubis/main.go
+++ b/cmd/anubis/main.go
@@ -35,6 +35,7 @@ var (
bindNetwork = flag.String("bind-network", "tcp", "network family to bind HTTP to, e.g. unix, tcp")
challengeDifficulty = flag.Int("difficulty", anubis.DefaultDifficulty, "difficulty of the challenge")
cookieDomain = flag.String("cookie-domain", "", "if set, the top-level domain that the Anubis cookie will be valid for")
+ cookiePartitioned = flag.Bool("cookie-partitioned", false, "if true, sets the partitioned flag on Anubis cookies, enabling CHIPS support")
ed25519PrivateKeyHex = flag.String("ed25519-private-key-hex", "", "private key used to sign JWTs, if not set a random one will be assigned")
metricsBind = flag.String("metrics-bind", ":9090", "network address to bind metrics to")
metricsBindNetwork = flag.String("metrics-bind-network", "tcp", "network family for the metrics server to bind to")
@@ -190,11 +191,12 @@ func main() {
}
s, err := libanubis.New(libanubis.Options{
- Next: rp,
- Policy: policy,
- ServeRobotsTXT: *robotsTxt,
- PrivateKey: priv,
- CookieDomain: *cookieDomain,
+ Next: rp,
+ Policy: policy,
+ ServeRobotsTXT: *robotsTxt,
+ PrivateKey: priv,
+ CookieDomain: *cookieDomain,
+ CookiePartitioned: *cookiePartitioned,
})
if err != nil {
log.Fatalf("can't construct libanubis.Server: %v", err)
diff --git a/docs/docs/CHANGELOG.md b/docs/docs/CHANGELOG.md
index 8bab92a..b690b6a 100644
--- a/docs/docs/CHANGELOG.md
+++ b/docs/docs/CHANGELOG.md
@@ -19,7 +19,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fix default difficulty setting that was broken in a refactor
- Linting fixes
- Make dark mode diff lines readable in the documentation
-- Add the ability to set the cookie domain with the envvar `COOKIE_DOMAIN`
+- Add the ability to set the cookie domain with the envvar `COOKIE_DOMAIN=techaro.lol` for all domains under `techaro.lol`
+- Add the ability to set the cookie partitioned flag with the envvar `COOKIE_PARTITIONED=true`
## v1.14.2
diff --git a/docs/docs/admin/installation.mdx b/docs/docs/admin/installation.mdx
index 4338851..5352683 100644
--- a/docs/docs/admin/installation.mdx
+++ b/docs/docs/admin/installation.mdx
@@ -46,6 +46,7 @@ Anubis uses these environment variables for configuration:
| `BIND` | `:8923` | The network address that Anubis listens on. For `unix`, set this to a path: `/run/anubis/instance.sock` |
| `BIND_NETWORK` | `tcp` | The address family that Anubis listens on. Accepts `tcp`, `unix` and anything Go's [`net.Listen`](https://pkg.go.dev/net#Listen) supports. |
| `COOKIE_DOMAIN` | unset | The domain the Anubis challenge pass cookie should be set to. This should be set to the domain you bought from your registrar (EG: `techaro.lol` if your webapp is running on `anubis.techaro.lol`). See [here](https://stackoverflow.com/a/1063760) for more information. |
+| `COOKIE_PARTITIONED` | `false` | If set to `true`, enables the [partitioned (CHIPS) flag](https://developers.google.com/privacy-sandbox/cookies/chips), meaning that Anubis inside an iframe has a different set of cookies than the domain hosting the iframe. |
| `DIFFICULTY` | `5` | The difficulty of the challenge, or the number of leading zeroes that must be in successful responses. |
| `ED25519_PRIVATE_KEY_HEX` | | The hex-encoded ed25519 private key used to sign Anubis responses. If this is not set, Anubis will generate one for you. This should be exactly 64 characters long. See below for details. |
| `METRICS_BIND` | `:9090` | The network address that Anubis serves Prometheus metrics on. See `BIND` for more information. |
diff --git a/lib/anubis.go b/lib/anubis.go
index 5e8ae2c..83e04dd 100644
--- a/lib/anubis.go
+++ b/lib/anubis.go
@@ -454,12 +454,13 @@ func (s *Server) PassChallenge(w http.ResponseWriter, r *http.Request) {
}
http.SetCookie(w, &http.Cookie{
- Name: anubis.CookieName,
- Value: tokenString,
- Expires: time.Now().Add(24 * 7 * time.Hour),
- SameSite: http.SameSiteLaxMode,
- Domain: s.opts.CookieDomain,
- Path: "/",
+ Name: anubis.CookieName,
+ Value: tokenString,
+ Expires: time.Now().Add(24 * 7 * time.Hour),
+ SameSite: http.SameSiteLaxMode,
+ Domain: s.opts.CookieDomain,
+ Partitioned: s.opts.CookiePartitioned,
+ Path: "/",
})
challengesValidated.Inc()
diff --git a/lib/anubis_test.go b/lib/anubis_test.go
index 088e17e..90d2cdf 100644
--- a/lib/anubis_test.go
+++ b/lib/anubis_test.go
@@ -96,20 +96,25 @@ func TestCookieSettings(t *testing.T) {
t.Errorf("wanted %d, got: %d", http.StatusFound, resp.StatusCode)
}
- found := false
+ var ckie *http.Cookie
for _, cookie := range resp.Cookies() {
t.Logf("%#v", cookie)
if cookie.Name == anubis.CookieName {
- found = true
+ ckie = cookie
+ break
}
+ }
- if found && cookie.Domain != "local.cetacean.club" {
- t.Errorf("cookie domain is wrong, wanted local.cetacean.club, got: %s", cookie.Domain)
- }
+ if ckie.Domain != "local.cetacean.club" {
+ t.Errorf("cookie domain is wrong, wanted local.cetacean.club, got: %s", ckie.Domain)
+ }
+
+ if ckie.Partitioned != srv.opts.CookiePartitioned {
+ t.Errorf("wanted partitioned flag %v, got: %v", srv.opts.CookiePartitioned, ckie.Partitioned)
}
- if !found {
- t.Errorf("Cookie %q not found", t.Name())
+ if ckie == nil {
+ t.Errorf("Cookie %q not found", anubis.CookieName)
}
}