checker-http/checker/rules_cookies_test.go

85 lines
2.8 KiB
Go

// This file is part of the happyDomain (R) project.
// Copyright (c) 2020-2026 happyDomain
// Authors: Pierre-Olivier Mercier, et al.
package checker
import (
"strings"
"testing"
sdk "git.happydns.org/checker-sdk-go/checker"
)
func TestCookieFlagsRule_NoHTTPS(t *testing.T) {
data := &HTTPData{Probes: []HTTPProbe{httpProbe("a:80")}}
states := runRule(t, &cookieFlagsRule{}, data, nil)
mustStatus(t, states, sdk.StatusUnknown)
}
func TestCookieFlagsRule_NoCookies(t *testing.T) {
data := &HTTPData{Probes: []HTTPProbe{httpsProbe("a:443")}}
states := runRule(t, &cookieFlagsRule{}, data, nil)
mustStatus(t, states, sdk.StatusOK)
if !hasCode(states, "http.cookie_flags.none") {
t.Errorf("missing 'none' code: %+v", states)
}
}
func TestCookieFlagsRule_AllOK(t *testing.T) {
p := httpsProbe("a:443")
p.Cookies = []CookieInfo{
{Name: "sid", Secure: true, HttpOnly: true, SameSite: "Strict"},
{Name: "tok", Secure: true, HttpOnly: true, SameSite: "Lax"},
}
states := runRule(t, &cookieFlagsRule{}, &HTTPData{Probes: []HTTPProbe{p}}, nil)
mustStatus(t, states, sdk.StatusOK)
if !hasCode(states, "http.cookie_flags.ok") {
t.Errorf("missing ok code: %+v", states)
}
}
func TestCookieFlagsRule_Issues(t *testing.T) {
p := httpsProbe("a:443")
p.Cookies = []CookieInfo{
{Name: "no-secure", Secure: false, HttpOnly: true, SameSite: "Lax"},
{Name: "no-httponly", Secure: true, HttpOnly: false, SameSite: "Lax"},
{Name: "no-samesite", Secure: true, HttpOnly: true, SameSite: ""},
{Name: "none-without-secure", Secure: false, HttpOnly: true, SameSite: "None"},
}
states := runRule(t, &cookieFlagsRule{}, &HTTPData{Probes: []HTTPProbe{p}}, nil)
if len(states) != len(p.Cookies) {
t.Fatalf("got %d states, want %d", len(states), len(p.Cookies))
}
mustStatus(t, states, sdk.StatusWarn)
// Check each diagnostic mentions the cookie name and a relevant phrase.
wantSubstr := map[string]string{
"no-secure": "missing Secure",
"no-httponly": "missing HttpOnly",
"no-samesite": "missing SameSite",
"none-without-secure": "SameSite=None requires Secure",
}
for _, st := range states {
matched := false
for name, phrase := range wantSubstr {
if strings.Contains(st.Message, name) && strings.Contains(st.Message, phrase) {
matched = true
break
}
}
if !matched {
t.Errorf("unexpected state message: %q", st.Message)
}
}
}
func TestCookieFlagsRule_SameSiteNoneCaseInsensitive(t *testing.T) {
p := httpsProbe("a:443")
p.Cookies = []CookieInfo{{Name: "x", Secure: false, HttpOnly: true, SameSite: "none"}}
states := runRule(t, &cookieFlagsRule{}, &HTTPData{Probes: []HTTPProbe{p}}, nil)
mustStatus(t, states, sdk.StatusWarn)
if !strings.Contains(states[0].Message, "SameSite=None requires Secure") {
t.Errorf("expected SameSite=None warning regardless of casing, got %q", states[0].Message)
}
}