checker-http/checker/types.go

136 lines
5 KiB
Go

// This file is part of the happyDomain (R) project.
// Copyright (c) 2020-2026 happyDomain
// Authors: Pierre-Olivier Mercier, et al.
//
// This program is offered under a commercial and under the AGPL license.
// For commercial licensing, contact us at <contact@happydomain.org>.
// Package checker implements an HTTP/HTTPS server checker for happyDomain.
// It probes the abstract.Server it is attached to over HTTP (80) and HTTPS
// (443), captures response headers, cookies and the (parsed) HTML body, then
// evaluates a set of independent rules covering reachability, the HTTP→HTTPS
// upgrade path, modern transport-security headers (HSTS, CSP), application
// security headers (X-Frame-Options, X-Content-Type-Options, X-XSS-Protection)
// and Subresource Integrity. Deep TLS / certificate analysis is intentionally
// delegated to checker-tls.
package checker
import (
"encoding/json"
"time"
)
const ObservationKeyHTTP = "http"
const (
OptionService = "service"
OptionDomainName = "domain_name"
OptionProbeTimeoutMs = "probeTimeoutMs"
OptionMaxRedirects = "maxRedirects"
OptionUserAgent = "userAgent"
OptionRequireHTTPS = "requireHTTPS"
OptionRequireHSTS = "requireHSTS"
OptionMinHSTSMaxAgeDays = "minHSTSMaxAgeDays"
OptionRequireCSP = "requireCSP"
)
const (
DefaultHTTPPort uint16 = 80
DefaultHTTPSPort uint16 = 443
DefaultProbeTimeoutMs = 10000
DefaultMaxRedirects = 5
DefaultUserAgent = "happyDomain-checker-http/1.0"
DefaultMinHSTSMaxAge = 180 // days; 180d ≈ 15552000s, the commonly recommended minimum
MaxConcurrentProbes = 8
MaxBodyBytes = 1 << 20 // 1 MiB cap on HTML body to keep memory bounded
)
// HTTPData is the full collected payload written under ObservationKeyHTTP.
//
// Probes/Domain/CollectedAt come from the root collector and are kept at
// the top level for backward compatibility with the rules that have
// always read them directly.
//
// Extensions holds the JSON-encoded outputs of every additional Collector
// registered via RegisterCollector, keyed by Collector.Key(). Rules
// access them via LoadExtension[T] to get a typed view.
type HTTPData struct {
Domain string `json:"domain,omitempty"`
Probes []HTTPProbe `json:"probes"`
CollectedAt time.Time `json:"collected_at"`
Extensions map[string]json.RawMessage `json:"extensions,omitempty"`
}
// HTTPProbe is the outcome of a single (scheme, ip, port) probe.
type HTTPProbe struct {
Scheme string `json:"scheme"` // "http" or "https"
Host string `json:"host"`
IP string `json:"ip,omitempty"`
Port uint16 `json:"port"`
Address string `json:"address"`
IsIPv6 bool `json:"ipv6,omitempty"`
TCPConnected bool `json:"tcp_connected"`
ElapsedMS int64 `json:"elapsed_ms,omitempty"`
Error string `json:"error,omitempty"`
// Final response after following redirects (if any).
StatusCode int `json:"status_code,omitempty"`
FinalURL string `json:"final_url,omitempty"`
Headers map[string]string `json:"headers,omitempty"`
Cookies []CookieInfo `json:"cookies,omitempty"`
RedirectChain []RedirectStep `json:"redirect_chain,omitempty"`
// Parsed HTML resource references (only populated for the primary
// HTTPS probe, to keep payloads small).
Resources []HTMLResource `json:"resources,omitempty"`
HTMLBytes int `json:"html_bytes,omitempty"`
BodyTruncated bool `json:"body_truncated,omitempty"`
}
// RedirectStep records one hop of a redirect chain.
type RedirectStep struct {
From string `json:"from"`
To string `json:"to"`
Status int `json:"status"`
}
// CookieInfo summarises one Set-Cookie header.
type CookieInfo struct {
Name string `json:"name"`
Domain string `json:"domain,omitempty"`
Path string `json:"path,omitempty"`
Secure bool `json:"secure"`
HttpOnly bool `json:"http_only"`
SameSite string `json:"same_site,omitempty"` // "Strict", "Lax", "None", or ""
HasExpiry bool `json:"has_expiry,omitempty"`
// Size is the byte length of the raw Set-Cookie header value
// (everything after "Set-Cookie: "), used to evaluate the
// per-cookie 4096-byte budget RFC 6265 §6.1 says browsers SHOULD
// support.
Size int `json:"size,omitempty"`
}
// MaxCookieSize is the per-cookie size browsers are required to
// support per RFC 6265 §6.1. Cookies above this are likely to be
// silently dropped by some user agents.
const MaxCookieSize = 4096
// HTMLResource is a <script src=...> or <link href=...> reference extracted
// from the HTML body, used to evaluate Subresource Integrity coverage.
type HTMLResource struct {
Tag string `json:"tag"` // "script" or "link"
URL string `json:"url"`
CrossOrigin bool `json:"cross_origin"`
Integrity string `json:"integrity,omitempty"`
Rel string `json:"rel,omitempty"`
}
// Severity levels used internally by rules.
const (
SeverityCrit = "crit"
SeverityWarn = "warn"
SeverityInfo = "info"
SeverityOK = "ok"
)