-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathintegration_test.go
More file actions
154 lines (132 loc) · 4.06 KB
/
integration_test.go
File metadata and controls
154 lines (132 loc) · 4.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
//go:build integration
// +build integration
package e5s_test
import (
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"testing"
"time"
"github.com/sufield/e5s"
"github.com/sufield/e5s/internal/testhelpers"
"github.com/sufield/e5s/spiffehttp"
)
// getOrSetupSPIRE returns a socket path to use for testing.
// If SPIFFE_ENDPOINT_SOCKET is set, it uses the existing SPIRE agent.
// Otherwise, it starts a new SPIRE server and agent for the test.
func getOrSetupSPIRE(t *testing.T) string {
socketPath := os.Getenv("SPIFFE_ENDPOINT_SOCKET")
if socketPath != "" {
t.Logf("Using existing SPIRE agent from environment: %s", socketPath)
return socketPath
}
// No existing SPIRE, start our own
st := testhelpers.SetupSPIRE(t)
return "unix://" + st.SocketPath
}
// TestE2E_Start_Client_PeerID tests the high-level e5s API end-to-end.
//
// This test verifies:
// - Starting an mTLS server with Start()
// - Creating an mTLS client with Client()
// - Successful TLS handshake using real SPIRE SVIDs
// - Extracting peer SPIFFE ID with PeerID()
//
// Requires: SPIRE server and agent running with workload registration
func TestE2E_Start_Client_PeerID(t *testing.T) {
// Get or setup SPIRE infrastructure
socketPath := getOrSetupSPIRE(t)
// Create temporary config file with dynamic socket path
tempDir := t.TempDir()
cfgPath := filepath.Join(tempDir, "e5s-test.yaml")
configContent := fmt.Sprintf(`spire:
workload_socket: "%s"
initial_fetch_timeout: "30s"
server:
listen_addr: ":18443"
allowed_client_trust_domain: "example.org"
client:
server_url: "https://localhost:18443/api"
expected_server_trust_domain: "example.org"
`, socketPath)
if err := os.WriteFile(cfgPath, []byte(configContent), 0600); err != nil {
t.Fatalf("failed to create test config: %v", err)
}
// Handler inspects the authenticated SPIFFE ID
var seenID string
var seenPeerInfo spiffehttp.Peer
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Test PeerID extraction
id, ok := e5s.PeerID(r)
if !ok {
http.Error(w, "unauthorized: no SPIFFE ID", http.StatusUnauthorized)
return
}
seenID = id
// Test PeerInfo extraction
peer, ok := e5s.PeerInfo(r)
if !ok {
http.Error(w, "unauthorized: no peer info", http.StatusUnauthorized)
return
}
seenPeerInfo = peer
fmt.Fprintf(w, "hello %s", id)
})
// Start server with integration config
t.Logf("Starting server with config: %s", cfgPath)
shutdown, err := e5s.Start(cfgPath, handler)
if err != nil {
t.Fatalf("failed to start e5s server: %v", err)
}
defer func() {
if err := shutdown(); err != nil {
t.Errorf("shutdown failed: %v", err)
}
}()
// Give the server time to bind to port
time.Sleep(500 * time.Millisecond)
// Create client with same config
t.Logf("Creating client with config: %s", cfgPath)
client, cleanup, err := e5s.Client(cfgPath)
if err != nil {
t.Fatalf("failed to create e5s client: %v", err)
}
defer func() {
if err := cleanup(); err != nil {
t.Errorf("client cleanup failed: %v", err)
}
}()
// Make request to server
resp, err := client.Get("https://localhost:18443/api")
if err != nil {
t.Fatalf("client request failed: %v", err)
}
defer resp.Body.Close()
// Verify response
if resp.StatusCode != http.StatusOK {
body, _ := io.ReadAll(resp.Body)
t.Fatalf("unexpected status %d body=%q", resp.StatusCode, string(body))
}
// Verify handler saw authenticated peer
if seenID == "" {
t.Fatal("expected handler to see authenticated SPIFFE ID")
}
t.Logf("✓ Verified peer SPIFFE ID: %s", seenID)
// Verify PeerInfo fields
if seenPeerInfo.ID.String() == "" {
t.Fatal("expected peer info to contain SPIFFE ID")
}
if seenPeerInfo.ID.String() != seenID {
t.Errorf("PeerInfo.ID = %s, want %s", seenPeerInfo.ID, seenID)
}
if seenPeerInfo.ExpiresAt.IsZero() {
t.Error("expected peer info to contain certificate expiration time")
}
if seenPeerInfo.ExpiresAt.Before(time.Now()) {
t.Error("peer certificate already expired")
}
t.Logf("✓ Verified peer info: trust domain=%s, expires=%s",
seenPeerInfo.ID.TrustDomain().Name(), seenPeerInfo.ExpiresAt)
}