Files
nezha_domains/cmd/dashboard/rpc/nat_capability_agentcompat_test.go
2026-07-20 04:30:50 +00:00

83 lines
2.7 KiB
Go

//go:build agentcompat
package rpc
import (
"bytes"
"log"
"net/http"
"strings"
"testing"
"github.com/nezhahq/nezha/model"
"github.com/nezhahq/nezha/pkg/agentcompatcontract"
serviceRPC "github.com/nezhahq/nezha/service/rpc"
)
func TestPrepareNATCapabilityConsumesAndRemovesHeaderBeforeNATWork(t *testing.T) {
// Given
handler := serviceRPC.NewNezhaHandler()
original := serviceRPC.NezhaHandlerSingleton
serviceRPC.NezhaHandlerSingleton = handler
t.Cleanup(func() { serviceRPC.NezhaHandlerSingleton = original })
request := &http.Request{Header: make(http.Header)}
request.Header.Set(agentcompatcontract.IOStreamCapabilityHeader, "malformed")
// When
lease, err := prepareNATCapability(request, &model.NAT{Common: model.Common{ID: 91}, ServerID: 81})
// Then
if err == nil {
t.Fatal("malformed capability unexpectedly accepted")
}
if lease.active {
t.Fatal("malformed capability unexpectedly activated")
}
if _, present := request.Header[agentcompatcontract.IOStreamCapabilityHeader]; present {
t.Fatal("capability header remained after hook")
}
}
func TestPrepareNATCapabilityRejectsDuplicateHeaderAfterRemovingAllValues(t *testing.T) {
// Given
request := &http.Request{Header: make(http.Header)}
request.Header.Add(agentcompatcontract.IOStreamCapabilityHeader, "one")
request.Header.Add(agentcompatcontract.IOStreamCapabilityHeader, "two")
// When
lease, err := prepareNATCapability(request, &model.NAT{Common: model.Common{ID: 92}, ServerID: 82})
// Then
if err == nil {
t.Fatal("duplicate capability header unexpectedly accepted")
}
if lease.active {
t.Fatal("duplicate capability header unexpectedly activated")
}
if _, present := request.Header[agentcompatcontract.IOStreamCapabilityHeader]; present {
t.Fatal("duplicate capability header remained after hook")
}
}
func TestServeNATAgentCompatSensitiveHeadersStayOutOfErrorsAndLogs(t *testing.T) {
request := &http.Request{Header: make(http.Header)}
request.Header.Set(agentcompatcontract.IOStreamCapabilityHeader, "capability-secret")
request.Header.Set("Authorization", "Bearer deterministic-secret")
writer := &serveNATResponseWriter{}
var logs bytes.Buffer
originalOutput := log.Writer()
log.SetOutput(&logs)
t.Cleanup(func() { log.SetOutput(originalOutput) })
ServeNAT(writer, request, &model.NAT{Common: model.Common{ID: 91}, ServerID: 81})
if writer.status != http.StatusServiceUnavailable {
t.Fatalf("status = %d, want %d", writer.status, http.StatusServiceUnavailable)
}
for _, output := range []string{writer.body, logs.String()} {
if strings.Contains(output, "capability-secret") || strings.Contains(output, "deterministic-secret") {
t.Fatalf("sensitive value leaked in %q", output)
}
}
}