Skip to content

Commit 46d9bc3

Browse files
test: add e2e-tests for boundary CLI
1 parent d628bfc commit 46d9bc3

File tree

2 files changed

+131
-2
lines changed

2 files changed

+131
-2
lines changed
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
package e2e_tests
2+
3+
import (
4+
"context"
5+
"os"
6+
"os/exec"
7+
"strings"
8+
"testing"
9+
"time"
10+
11+
"github.com/stretchr/testify/require"
12+
)
13+
14+
// getNamespaceName gets the single network namespace name
15+
// Fails if there are 0 or multiple namespaces
16+
func getNamespaceName(t *testing.T) string {
17+
cmd := exec.Command("ip", "netns", "list")
18+
output, err := cmd.Output()
19+
require.NoError(t, err, "Failed to list network namespaces")
20+
21+
lines := strings.Split(string(output), "\n")
22+
var namespaces []string
23+
24+
for _, line := range lines {
25+
line = strings.TrimSpace(line)
26+
if line != "" {
27+
// Extract namespace name (first field)
28+
parts := strings.Fields(line)
29+
if len(parts) > 0 {
30+
namespaces = append(namespaces, parts[0])
31+
}
32+
}
33+
}
34+
35+
require.Len(t, namespaces, 1, "Expected exactly one network namespace, found %d: %v", len(namespaces), namespaces)
36+
return namespaces[0]
37+
}
38+
39+
func TestBoundaryIntegration(t *testing.T) {
40+
// Build the boundary binary
41+
buildCmd := exec.Command("go", "build", "-o", "/tmp/boundary-test", "./cmd/...")
42+
buildCmd.Dir = "/home/coder/boundary"
43+
err := buildCmd.Run()
44+
require.NoError(t, err, "Failed to build boundary binary")
45+
46+
// Create context for boundary process
47+
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
48+
defer cancel()
49+
50+
// Start boundary process with sudo
51+
boundaryCmd := exec.CommandContext(ctx, "/tmp/boundary-test",
52+
"--allow", "dev.coder.com",
53+
"--allow", "jsonplaceholder.typicode.com",
54+
"--log-level", "debug",
55+
"--", "bash", "-c", "sleep 10 && echo 'Test completed'")
56+
57+
// Suppress output to prevent terminal corruption
58+
boundaryCmd.Stdout = os.Stdout // Let it go to /dev/null
59+
boundaryCmd.Stderr = os.Stderr
60+
61+
// Start the process
62+
err = boundaryCmd.Start()
63+
require.NoError(t, err, "Failed to start boundary process")
64+
65+
// Give boundary time to start
66+
time.Sleep(2 * time.Second)
67+
68+
// Get the namespace name that boundary created
69+
namespaceName := getNamespaceName(t)
70+
71+
// Test HTTP request through boundary (from inside the jail)
72+
t.Run("HTTPRequestThroughBoundary", func(t *testing.T) {
73+
// Run curl directly in the namespace using ip netns exec
74+
curlCmd := exec.Command("sudo", "ip", "netns", "exec", namespaceName,
75+
"curl", "-s", "http://jsonplaceholder.typicode.com/todos/1")
76+
77+
// Capture output
78+
output, err := curlCmd.Output()
79+
require.NoError(t, err, "curl command failed")
80+
81+
// Verify response contains expected content
82+
expectedResponse := `{
83+
"userId": 1,
84+
"id": 1,
85+
"title": "delectus aut autem",
86+
"completed": false
87+
}`
88+
require.Equal(t, expectedResponse, string(output))
89+
})
90+
91+
// Test HTTPS request through boundary (from inside the jail)
92+
t.Run("HTTPSRequestThroughBoundary", func(t *testing.T) {
93+
// Run curl directly in the namespace using ip netns exec
94+
// TODO(yevhenii): remove env
95+
curlCmd := exec.Command("sudo", "ip", "netns", "exec", namespaceName,
96+
"env", "SSL_CERT_FILE=/home/coder/.config/coder_boundary/ca-cert.pem", "curl", "-s", "https://dev.coder.com/api/v2")
97+
98+
// Capture output
99+
output, err := curlCmd.Output()
100+
require.NoError(t, err, "curl command failed")
101+
102+
// Verify response contains expected content
103+
expectedResponse := `{"message":"👋"}
104+
`
105+
require.Equal(t, expectedResponse, string(output))
106+
})
107+
108+
// Test blocked domain (from inside the jail)
109+
t.Run("BlockedDomainTest", func(t *testing.T) {
110+
// Run curl directly in the namespace using ip netns exec
111+
curlCmd := exec.Command("sudo", "ip", "netns", "exec", namespaceName,
112+
"curl", "-s", "http://example.com")
113+
114+
// This should fail
115+
output, err := curlCmd.Output()
116+
require.NoError(t, err, "curl command failed")
117+
require.Contains(t, string(output), "Request Blocked by Boundary")
118+
})
119+
120+
// Clean up
121+
cancel() // This will terminate the boundary process
122+
err = boundaryCmd.Wait() // Wait for process to finish
123+
if err != nil {
124+
t.Logf("Boundary process finished with error: %v", err)
125+
}
126+
127+
// Clean up binary
128+
os.Remove("/tmp/boundary-test")
129+
}

jail/linux.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,10 @@ func (l *LinuxJail) Start() error {
7575
func (l *LinuxJail) Command(command []string) *exec.Cmd {
7676
l.logger.Debug("Creating command with namespace", "namespace", l.namespace)
7777

78-
cmdArgs := []string{"ip", "netns", "exec", l.namespace}
78+
cmdArgs := []string{"netns", "exec", l.namespace}
7979
cmdArgs = append(cmdArgs, command...)
8080

81-
cmd := exec.Command("sudo", cmdArgs...)
81+
cmd := exec.Command("ip", cmdArgs...)
8282
cmd.Env = l.commandEnv
8383

8484
return cmd

0 commit comments

Comments
 (0)