ProofedMesh/services/admin-api/internal/tlog/interop_test.go

98 lines
3.2 KiB
Go
Raw Permalink Normal View History

package tlog
// Interop test: the real admin-api HTTPSubmitter talks to the real
// transparency-log HTTP handler + in-memory backend from the sibling
// services/transparency-log module. This proves end-to-end that the
// ADR-0005 wire shape agreed on both sides (field names, status codes,
// idempotency semantics, content_hash algorithm) is actually compatible.
//
// The transparency-log module is pulled in via a replace directive in the
// top-level go.mod.
import (
"context"
"net/http/httptest"
"testing"
"basicstack.de/proofedmesh/services/admin-api/internal/attest"
tlbackend "basicstack.de/proofedmesh/services/transparency-log/pkg/backend"
tlhttp "basicstack.de/proofedmesh/services/transparency-log/pkg/httpapi"
)
func TestInterop_HTTPSubmitter_HappyPathAndIdempotency(t *testing.T) {
backendMem := tlbackend.NewMemory()
server := httptest.NewServer((&tlhttp.Server{Backend: backendMem}).Handler())
defer server.Close()
sub := HTTPSubmitter{BaseURL: server.URL, TokenSource: attest.StaticToken("dev")}
env := attest.Envelope{
PayloadType: "application/vnd.in-toto+json",
Payload: "aGVsbG8",
Signatures: []attest.EnvelopeSignature{{KeyID: "k", Sig: "c2ln"}},
}
ch, err := attest.EnvelopeContentHash(env)
if err != nil {
t.Fatalf("hash: %v", err)
}
r1, err := sub.Submit(context.Background(), env, ch)
if err != nil {
t.Fatalf("first submit: %v", err)
}
if r1.LogIndex != 0 {
t.Errorf("first log_index: want 0, got %d", r1.LogIndex)
}
if r1.ContentHash != ch {
t.Errorf("content_hash echoed wrong: %q vs %q", r1.ContentHash, ch)
}
if r1.InclusionProof.TreeSize != 1 {
t.Errorf("tree_size: %d", r1.InclusionProof.TreeSize)
}
// Idempotent repeat.
r2, err := sub.Submit(context.Background(), env, ch)
if err != nil {
t.Fatalf("second submit: %v", err)
}
if r2.LogIndex != r1.LogIndex {
t.Errorf("idempotent log_index drifted: %d -> %d", r1.LogIndex, r2.LogIndex)
}
if r2.InclusionProof.TreeRootHash != r1.InclusionProof.TreeRootHash {
t.Errorf("tree_root drifted without new entries")
}
// Second distinct envelope — tree grows.
envB := env
envB.Payload = "d29ybGQ"
chB, _ := attest.EnvelopeContentHash(envB)
rB, err := sub.Submit(context.Background(), envB, chB)
if err != nil {
t.Fatalf("submit B: %v", err)
}
if rB.LogIndex != 1 {
t.Errorf("second entry log_index: want 1, got %d", rB.LogIndex)
}
if rB.InclusionProof.TreeSize != 2 {
t.Errorf("tree_size after B: %d", rB.InclusionProof.TreeSize)
}
}
func TestInterop_HTTPSubmitter_ContentHashMismatchFails(t *testing.T) {
server := httptest.NewServer((&tlhttp.Server{Backend: tlbackend.NewMemory()}).Handler())
defer server.Close()
sub := HTTPSubmitter{BaseURL: server.URL, TokenSource: attest.StaticToken("dev")}
env := attest.Envelope{
PayloadType: "application/vnd.in-toto+json",
Payload: "aGVsbG8",
Signatures: []attest.EnvelopeSignature{{KeyID: "k", Sig: "c2ln"}},
}
// Wrong hash on purpose. Server must respond 409; the client surfaces
// that as an error.
_, err := sub.Submit(context.Background(), env, "sha256:00000000000000000000000000000000000000000000000000000000deadbeef")
if err == nil {
t.Fatalf("expected error on content_hash mismatch, got nil")
}
}