160 lines
5.2 KiB
Go
160 lines
5.2 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 TestCookiePrefixesRule_NoHTTPS(t *testing.T) {
|
|
data := &HTTPData{Probes: []HTTPProbe{httpProbe("a:80")}}
|
|
states := runRule(t, &cookiePrefixesRule{}, data, nil)
|
|
mustStatus(t, states, sdk.StatusUnknown)
|
|
if !hasCode(states, "http.cookie_prefixes.no_https") {
|
|
t.Errorf("missing no_https code: %+v", states)
|
|
}
|
|
}
|
|
|
|
func TestCookiePrefixesRule_NoPrefixed(t *testing.T) {
|
|
p := httpsProbe("a:443")
|
|
p.Cookies = []CookieInfo{{Name: "sid", Secure: true, HttpOnly: true, SameSite: "Lax"}}
|
|
states := runRule(t, &cookiePrefixesRule{}, &HTTPData{Probes: []HTTPProbe{p}}, nil)
|
|
mustStatus(t, states, sdk.StatusInfo)
|
|
if !hasCode(states, "http.cookie_prefixes.none") {
|
|
t.Errorf("missing 'none' code: %+v", states)
|
|
}
|
|
}
|
|
|
|
func TestCookiePrefixesRule_HostOK(t *testing.T) {
|
|
p := httpsProbe("a:443")
|
|
p.Cookies = []CookieInfo{
|
|
{Name: "__Host-sid", Secure: true, HttpOnly: true, SameSite: "Strict", Path: "/"},
|
|
{Name: "__Secure-tok", Secure: true, HttpOnly: true, SameSite: "Lax", Path: "/app"},
|
|
}
|
|
states := runRule(t, &cookiePrefixesRule{}, &HTTPData{Probes: []HTTPProbe{p}}, nil)
|
|
mustStatus(t, states, sdk.StatusOK)
|
|
if !hasCode(states, "http.cookie_prefixes.ok") {
|
|
t.Errorf("missing ok code: %+v", states)
|
|
}
|
|
}
|
|
|
|
func TestCookiePrefixesRule_SecureMissingSecure(t *testing.T) {
|
|
p := httpsProbe("a:443")
|
|
p.Cookies = []CookieInfo{{Name: "__Secure-x", Secure: false, HttpOnly: true, SameSite: "Lax"}}
|
|
states := runRule(t, &cookiePrefixesRule{}, &HTTPData{Probes: []HTTPProbe{p}}, nil)
|
|
mustStatus(t, states, sdk.StatusWarn)
|
|
if !hasCode(states, "http.cookie_prefixes.invalid_secure") {
|
|
t.Errorf("missing invalid_secure code: %+v", states)
|
|
}
|
|
}
|
|
|
|
func TestCookiePrefixesRule_HostViolations(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
cookie CookieInfo
|
|
want []string
|
|
}{
|
|
{
|
|
name: "no Secure",
|
|
cookie: CookieInfo{Name: "__Host-a", Secure: false, Path: "/"},
|
|
want: []string{"missing Secure"},
|
|
},
|
|
{
|
|
name: "Domain set",
|
|
cookie: CookieInfo{Name: "__Host-a", Secure: true, Domain: "example.test", Path: "/"},
|
|
want: []string{"Domain attribute is forbidden"},
|
|
},
|
|
{
|
|
name: "wrong Path",
|
|
cookie: CookieInfo{Name: "__Host-a", Secure: true, Path: "/app"},
|
|
want: []string{`Path must be "/"`},
|
|
},
|
|
{
|
|
name: "all three",
|
|
cookie: CookieInfo{Name: "__Host-a", Secure: false, Domain: "x", Path: "/x"},
|
|
want: []string{"missing Secure", "Domain attribute is forbidden", `Path must be "/"`},
|
|
},
|
|
}
|
|
for _, c := range cases {
|
|
t.Run(c.name, func(t *testing.T) {
|
|
p := httpsProbe("a:443")
|
|
p.Cookies = []CookieInfo{c.cookie}
|
|
states := runRule(t, &cookiePrefixesRule{}, &HTTPData{Probes: []HTTPProbe{p}}, nil)
|
|
mustStatus(t, states, sdk.StatusWarn)
|
|
if !hasCode(states, "http.cookie_prefixes.invalid_host") {
|
|
t.Fatalf("missing invalid_host code: %+v", states)
|
|
}
|
|
for _, w := range c.want {
|
|
if !strings.Contains(states[0].Message, w) {
|
|
t.Errorf("message missing %q: %s", w, states[0].Message)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCookiePrefixesRule_LoadFailure(t *testing.T) {
|
|
states := (&cookiePrefixesRule{}).Evaluate(t.Context(), &fakeObs{failGet: true}, nil)
|
|
if len(states) != 1 || states[0].Status != sdk.StatusError {
|
|
t.Fatalf("expected single error state, got %+v", states)
|
|
}
|
|
}
|
|
|
|
func TestCookieSizeRule_NoHTTPS(t *testing.T) {
|
|
data := &HTTPData{Probes: []HTTPProbe{httpProbe("a:80")}}
|
|
states := runRule(t, &cookieSizeRule{}, data, nil)
|
|
mustStatus(t, states, sdk.StatusUnknown)
|
|
}
|
|
|
|
func TestCookieSizeRule_None(t *testing.T) {
|
|
data := &HTTPData{Probes: []HTTPProbe{httpsProbe("a:443")}}
|
|
states := runRule(t, &cookieSizeRule{}, data, nil)
|
|
mustStatus(t, states, sdk.StatusOK)
|
|
if !hasCode(states, "http.cookie_size.none") {
|
|
t.Errorf("missing 'none' code: %+v", states)
|
|
}
|
|
}
|
|
|
|
func TestCookieSizeRule_OK(t *testing.T) {
|
|
p := httpsProbe("a:443")
|
|
p.Cookies = []CookieInfo{
|
|
{Name: "small", Size: 200},
|
|
{Name: "borderline", Size: MaxCookieSize}, // exactly the limit is acceptable
|
|
}
|
|
states := runRule(t, &cookieSizeRule{}, &HTTPData{Probes: []HTTPProbe{p}}, nil)
|
|
mustStatus(t, states, sdk.StatusOK)
|
|
if !hasCode(states, "http.cookie_size.ok") {
|
|
t.Errorf("missing ok code: %+v", states)
|
|
}
|
|
}
|
|
|
|
func TestCookieSizeRule_TooLarge(t *testing.T) {
|
|
p := httpsProbe("a:443")
|
|
p.Cookies = []CookieInfo{
|
|
{Name: "small", Size: 100},
|
|
{Name: "huge", Size: MaxCookieSize + 1},
|
|
}
|
|
states := runRule(t, &cookieSizeRule{}, &HTTPData{Probes: []HTTPProbe{p}}, nil)
|
|
if len(states) != 1 {
|
|
t.Fatalf("got %d states, want 1 (only the oversized cookie)", len(states))
|
|
}
|
|
mustStatus(t, states, sdk.StatusWarn)
|
|
if !hasCode(states, "http.cookie_size.too_large") {
|
|
t.Errorf("missing too_large code: %+v", states)
|
|
}
|
|
if !strings.Contains(states[0].Message, "huge") {
|
|
t.Errorf("message should mention cookie name: %q", states[0].Message)
|
|
}
|
|
}
|
|
|
|
func TestCookieSizeRule_LoadFailure(t *testing.T) {
|
|
states := (&cookieSizeRule{}).Evaluate(t.Context(), &fakeObs{failGet: true}, nil)
|
|
if len(states) != 1 || states[0].Status != sdk.StatusError {
|
|
t.Fatalf("expected single error state, got %+v", states)
|
|
}
|
|
}
|