E2E Testing Framework
Relevant source files
The following files were used as context for generating this wiki page:
The E2E (End-to-End) Testing Framework in sshpiper is designed to validate the full lifecycle of an SSH connection as it passes through the sshpiperd daemon and its various plugins. It ensures that downstream clients can successfully authenticate and be routed to upstream servers based on complex logic defined in YAML, Lua, or Kubernetes configurations.
The framework utilizes Docker Compose to orchestrate a controlled environment containing multiple SSH servers (sshd), a test runner, and specialized proxies. This setup allows for automated verification of authentication methods (password, public key, keyboard-interactive, and certificates), terminal recording, and plugin-specific features.
Sources: CONTRIBUTING.md:27-46, e2e/main_test.go:193-210
Architecture and Components
The framework consists of a containerized environment where a testrunner container executes Go tests against a live instance of sshpiperd.
Core Components
| Component | Description |
|---|---|
| Test Runner | A container that runs go test and manages the lifecycle of the sshpiperd process under test. |
| host-password | An OpenSSH server configured for password-only authentication (user: user, password: pass). |
| host-publickey | An OpenSSH server configured for public key authentication. |
| host-k8s-proxy | A specialized service for testing the Kubernetes plugin via a Kind cluster. |
| Shared Volume | A tmpfs volume mounted across containers to verify file creation and content after successful SSH commands. |
Sources: e2e/docker-compose.yml:2-100, CONTRIBUTING.md:32-37
Test Environment Flow
The following diagram illustrates how the testrunner initiates a test, spawns sshpiperd, and validates the connection through a real SSH client.
The framework uses a shared volume to verify that commands executed via the piped SSH session actually reached the intended upstream and performed the expected action.
Sources: e2e/main_test.go:104-122, e2e/docker-compose.yml:126-130
Test Execution Logic
Tests are written in Go and leverage the os/exec package to manage the sshpiperd daemon and the ssh client.
Command Management
The framework provides several helper functions in e2e/main_test.go to handle command execution:
runCmd: Starts a process within a PTY (Pseudo-Terminal) usingpty.Startand captures output via anio.TeeReader.waitForEndpointReady: A polling mechanism that attempts to connect via TCP until a service (likesshpiperd) is ready.enterPassword: Scans the captured stdout for a password prompt and writes the password to the PTY's stdin.
Sources: e2e/main_test.go:50-86, e2e/main_test.go:94-102
Verification via Shared Files
A common pattern in the test suite involves generating a unique string (UUID) and instructing the SSH client to echo that string into a file on the shared volume.
randtext := uuid.New().String()
targetfie := uuid.New().String()
// ... execution of ssh command: echo -n [randtext] > /shared/[targetfie]
checkSharedFileContent(t, targetfie, randtext)
Sources: e2e/main_test.go:104-122, e2e/yaml_test.go:185-200
Plugin-Specific Testing
The E2E framework includes dedicated test files for each major plugin, ensuring their unique routing and authentication logic works as expected.
YAML Plugin Testing
Tests for the YAML plugin verify regex-based username matching, upstream private key mapping, and CA-based routing. The TestYaml function dynamically generates a config.yaml using Go templates to inject temporary file paths and base64 encoded keys.
Sources: e2e/yaml_test.go:17-170
Lua Plugin Testing
The Lua test suite (TestLua) validates scriptable callbacks including:
sshpiper_on_passwordsshpiper_on_publickeysshpiper_on_keyboard_interactivesshpiper_on_bannersshpiper_on_verify_hostkey
It specifically tests "Auth Method Switching," where the script can dynamically change allowed authentication methods based on failure counts.
Sources: e2e/lua_test.go:12-92, e2e/lua_test.go:343-400
Kubernetes Plugin Testing
Testing the Kubernetes plugin involves a complex setup using a Kind (Kubernetes in Docker) cluster. The host-k8s-proxy container builds a local cluster, applies CRDs, and forwards ports to simulate a production Kubernetes environment.
Sources: e2e/docker-compose.yml:68-100, e2e/kubernetes_test.go:15-30
Configuration and Environment Variables
The framework behavior is controlled via several environment variables passed to the testrunner.
| Variable | Purpose |
|---|---|
SSHPIPERD_E2E_TEST | Must be set to 1 to enable E2E tests; otherwise, they are skipped. |
SSHPIPERD_SERVER_KEY_GENERATE_MODE | Set to notexist to ensure sshpiperd generates host keys if they are missing. |
SSHPIPERD_LOG_LEVEL | Typically set to trace to capture detailed proxy logs during failures. |
SSHPIPERD_DEBUG | Enables additional debugging output in the containers. |
Sources: e2e/main_test.go:193-200, e2e/docker-compose.yml:102-113
Summary
The E2E Testing Framework provides a robust, isolated environment for verifying the core functionality of sshpiper. By orchestrating real SSH servers and using PTY-based interaction, it ensures that sshpiperd correctly handles complex authentication and routing scenarios across its plugin ecosystem. The use of a shared volume for side-effect verification provides a reliable "black-box" testing method for end-to-end connectivity.