Files
llmgw/internal/pgha/rest_test.go
T
Ilker ManapandClaude Opus 5.5 191c65e3db Put etcd and Patroni's API on TLS, and move a running cluster there in maintenance mode
Members' etcd speaks TLS to peers and clients with a certificate from the
cluster's authority and asks clients for one; Patroni reaches it with the
member's certificate and serves its API over TLS. A running plain-HTTP
cluster is moved with Patroni paused, so PostgreSQL serves throughout:
Patroni's lease-free keys are carried over to the new etcd.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-04 12:07:17 +02:00

66 lines
1.9 KiB
Go

package pgha
import (
"crypto/tls"
"encoding/pem"
"net"
"net/http"
"net/http/httptest"
"strconv"
"testing"
"time"
"gitea.mynodes.xyz/ilker/llmgw/internal/tlsconf"
)
func TestTheAPIIsAskedOverTLSAndOverHTTPOnlyWhenItSpeaksHTTP(t *testing.T) {
answer := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte(`{"scheme":"` + map[bool]string{true: "https", false: "http"}[r.TLS != nil] + `"}`))
})
secure := httptest.NewTLSServer(answer)
defer secure.Close()
plain := httptest.NewServer(answer)
defer plain.Close()
t.Cleanup(func() { restMu.Lock(); restCA = nil; restMu.Unlock(); restPort = PatroniPort })
if err := setRESTCAPEM(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: secure.Certificate().Raw})); err != nil {
t.Fatal(err)
}
ask := func(url string) (string, error) {
_, port, _ := net.SplitHostPort(url[len("https://"):])
if url[:5] == "http:" {
_, port, _ = net.SplitHostPort(url[len("http://"):])
}
restPort, _ = strconv.Atoi(port)
b, err := restJSON(t.Context(), "127.0.0.1", http.MethodGet, "/x", nil, "", 3*time.Second)
return string(b), err
}
if got, err := ask(secure.URL); err != nil || got != `{"scheme":"https"}` {
t.Errorf("a member on TLS: %s, %v", got, err)
}
if got, err := ask(plain.URL); err != nil || got != `{"scheme":"http"}` {
t.Errorf("a member not yet on TLS: %s, %v", got, err)
}
// A certificate from elsewhere is refused, not fallen back from.
ca, err := tlsconf.NewCA("elsewhere")
if err != nil {
t.Fatal(err)
}
leaf, err := ca.IssueServer("other", []string{"127.0.0.1"})
if err != nil {
t.Fatal(err)
}
cert, err := tls.X509KeyPair(leaf.CertPEM, leaf.KeyPEM)
if err != nil {
t.Fatal(err)
}
other := httptest.NewUnstartedServer(answer)
other.TLS = &tls.Config{Certificates: []tls.Certificate{cert}}
other.StartTLS()
defer other.Close()
if _, err := ask(other.URL); err == nil {
t.Error("a certificate the authority did not sign was accepted")
}
}