Skip to content
This repository was archived by the owner on Jan 23, 2026. It is now read-only.

Commit 3b97a14

Browse files
authored
Merge branch 'main' into custom-lease-name
2 parents 6d6c9fc + 9214623 commit 3b97a14

30 files changed

Lines changed: 1649 additions & 29 deletions

File tree

.devcontainer/Dockerfile

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,5 @@ COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv
99
COPY --from=ghcr.io/astral-sh/uv:latest /uvx /bin/uvx
1010
COPY ./.python-version ./
1111

12-
RUN uv python pin "$(cat .python-version)"
13-
1412
# Install required tools for development
1513
RUN apt-get update && apt-get install -y iperf3 libusb-dev

.devcontainer/devcontainer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"dockerfile": "Dockerfile"
66
},
77
"postCreateCommand": "make sync",
8-
"postStartCommand": "uv run pre-commit install",
8+
"postStartCommand": "uv python pin 3.12 && uv run pre-commit install",
99
"remoteUser": "vscode",
1010
// Mount USB devices to devcontainer for tests
1111
"mounts": [

.github/workflows/documentation.yaml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ jobs:
4242
version: "latest"
4343

4444
- name: Install Python
45-
run: uv python install
45+
run: |
46+
uv python pin 3.12
47+
uv python install
4648
4749
- name: Setup Pages
4850
id: pages
@@ -80,7 +82,9 @@ jobs:
8082
version: "latest"
8183

8284
- name: Install Python
83-
run: uv python install
85+
run: |
86+
uv python pin 3.12
87+
uv python install
8488
8589
- name: Build the documentation for the current version (no warnings allowed)
8690
run: make sync && make docs

.python-version

Lines changed: 0 additions & 1 deletion
This file was deleted.

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,17 @@
33
[![Matrix](https://img.shields.io/matrix/jumpstarter%3Amatrix.org?color=blue)](https://matrix.to/#/#jumpstarter:matrix.org)
44
[![Etherpad](https://img.shields.io/badge/Etherpad-Notes-blue?logo=etherpad)](https://etherpad.jumpstarter.dev/pad-lister)
55
[![Community Meeting](https://img.shields.io/badge/Weekly%20Meeting-Google%20Meet-blue?logo=google-meet)](https://meet.google.com/gzd-hhbd-hpu)
6+
![GitHub Release](https://img.shields.io/github/v/release/jumpstarter-dev/jumpstarter)
7+
![PyPI - Version](https://img.shields.io/pypi/v/jumpstarter)
8+
![GitHub Downloads (all assets, all releases)](https://img.shields.io/github/downloads/jumpstarter-dev/jumpstarter/total)
9+
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/jumpstarter-dev/jumpstarter)
10+
11+
[![E2E Tests](https://github.com/jumpstarter-dev/jumpstarter/actions/workflows/e2e.yaml/badge.svg)](https://github.com/jumpstarter-dev/jumpstarter/actions/workflows/e2e.yaml)
12+
[![Tests](https://github.com/jumpstarter-dev/jumpstarter/actions/workflows/pytest.yaml/badge.svg)](https://github.com/jumpstarter-dev/jumpstarter/actions/workflows/pytest.yaml)
13+
[![documentation](https://github.com/jumpstarter-dev/jumpstarter/actions/workflows/documentation.yaml/badge.svg)](https://github.com/jumpstarter-dev/jumpstarter/actions/workflows/documentation.yaml)<br>
14+
[![Wheels](https://github.com/jumpstarter-dev/jumpstarter/actions/workflows/publish.yaml/badge.svg)](https://github.com/jumpstarter-dev/jumpstarter/actions/workflows/publish.yaml)
15+
[![Flashing bundles](https://github.com/jumpstarter-dev/jumpstarter/actions/workflows/build_oci_bundle.yaml/badge.svg)](https://github.com/jumpstarter-dev/jumpstarter/actions/workflows/build_oci_bundle.yaml)
16+
[![Containers](https://github.com/jumpstarter-dev/jumpstarter/actions/workflows/build.yaml/badge.svg)](https://github.com/jumpstarter-dev/jumpstarter/actions/workflows/build.yaml)
617

718
A free, open source tool for automated testing on real and virtual hardware with
819
CI/CD integration. Simplify device automation with consistent rules across local

docs/source/reference/package-apis/drivers/index.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ Drivers that provide various communication interfaces:
4242
Protocol
4343
* **[TFTP](tftp.md)** (`jumpstarter-driver-tftp`) - Trivial File Transfer
4444
Protocol
45+
* **[VNC](vnc.md)** (`jumpstarter-driver-vnc`) - VNC (Virtual Network Computing) remote desktop protocol
4546

4647
### Storage and Data Drivers
4748

@@ -111,5 +112,6 @@ tmt.md
111112
tftp.md
112113
uboot.md
113114
ustreamer.md
115+
vnc.md
114116
yepkit.md
115117
```
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../../../packages/jumpstarter-driver-vnc/README.md

packages/jumpstarter-cli/jumpstarter_cli/shell.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def _run_shell_with_lease(lease, exporter_logs, config, command):
2020
def launch_remote_shell(path: str) -> int:
2121
return launch_shell(
2222
path, lease.exporter_name, config.drivers.allow, config.drivers.unsafe,
23-
config.shell.use_profiles, command=command
23+
config.shell.use_profiles, command=command, lease=lease
2424
)
2525

2626
with lease.serve_unix() as path:

packages/jumpstarter-driver-network/jumpstarter_driver_network/adapters/novnc.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,22 @@
1010

1111
@blocking
1212
@asynccontextmanager
13-
async def NovncAdapter(*, client: DriverClient, method: str = "connect"):
13+
async def NovncAdapter(*, client: DriverClient, method: str = "connect", encrypt: bool = True):
14+
"""
15+
Provide a noVNC URL that proxies a temporary local TCP listener to a remote
16+
driver stream via a WebSocket bridge.
17+
18+
Parameters:
19+
client (DriverClient): Client used to open the remote stream that will be
20+
bridged to the local listener.
21+
method (str): Name of the async stream method to call on the client (default "connect").
22+
encrypt (bool): If True request an encrypted (TLS) vnc connection;
23+
if False request an unencrypted vnc connection.
24+
25+
Returns:
26+
str: The URL to connect to the VNC session.
27+
"""
28+
1429
async def handler(conn):
1530
async with conn:
1631
async with client.stream_async(method) as stream:
@@ -19,13 +34,21 @@ async def handler(conn):
1934
pass
2035

2136
async with TemporaryTcpListener(handler) as addr:
37+
params = {
38+
"encrypt": 1 if encrypt else 0,
39+
"autoconnect": 1,
40+
"reconnect": 1,
41+
"host": addr[0],
42+
"port": addr[1],
43+
}
44+
2245
yield urlunparse(
2346
(
2447
"https",
2548
"novnc.com",
2649
"/noVNC/vnc.html",
2750
"",
28-
urlencode({"autoconnect": 1, "reconnect": 1, "host": addr[0], "port": addr[1]}),
51+
urlencode(params),
2952
"",
3053
)
3154
)
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# SSH MITM Driver
2+
3+
`jumpstarter-driver-ssh-mitm` provides a secure SSH proxy layer where private keys
4+
are stored on the exporter and never transmitted to clients. It is designed to be
5+
used as a child of `SSHWrapper`.
6+
7+
## Installation
8+
9+
```{code-block} console
10+
:substitutions:
11+
$ pip3 install --extra-index-url {{index_url}} jumpstarter-driver-ssh-mitm
12+
```
13+
14+
## Architecture
15+
16+
```
17+
SSHWrapper --> SSHMITM --> TcpNetwork --> DUT
18+
```
19+
20+
- **SSHWrapper**: Handles SSH CLI and command execution
21+
- **SSHMITM**: Provides authenticated proxy connection (stores the SSH key)
22+
- **TcpNetwork**: Raw TCP connection to the DUT
23+
24+
## Configuration
25+
26+
The command name is determined by the key in the `export` section. Use `ssh_mitm` to get the `j ssh_mitm` command:
27+
28+
```yaml
29+
export:
30+
ssh_mitm: # ← This gives you "j ssh_mitm" command
31+
type: jumpstarter_driver_ssh.driver.SSHWrapper
32+
config:
33+
default_username: root
34+
children:
35+
tcp:
36+
type: jumpstarter_driver_ssh_mitm.driver.SSHMITM
37+
config:
38+
ssh_identity_file: /path/to/private/key
39+
default_username: root
40+
children:
41+
tcp:
42+
type: jumpstarter_driver_network.driver.TcpNetwork
43+
config:
44+
host: 192.168.1.100
45+
port: 22
46+
```
47+
48+
Or with inline key:
49+
50+
```yaml
51+
export:
52+
ssh_mitm: # ← This gives you "j ssh_mitm" command
53+
type: jumpstarter_driver_ssh.driver.SSHWrapper
54+
config:
55+
default_username: root
56+
children:
57+
tcp:
58+
type: jumpstarter_driver_ssh_mitm.driver.SSHMITM
59+
config:
60+
default_username: root
61+
ssh_identity: |
62+
-----BEGIN OPENSSH PRIVATE KEY-----
63+
...
64+
-----END OPENSSH PRIVATE KEY-----
65+
children:
66+
tcp:
67+
type: jumpstarter_driver_network.driver.TcpNetwork
68+
config:
69+
host: 192.168.1.100
70+
port: 22
71+
```
72+
73+
### SSHMITM Config parameters
74+
75+
| Parameter | Description | Type | Required | Default |
76+
| ----------------- | ---------------------------------------- | ----- | -------- | ------- |
77+
| default_username | SSH username for DUT connection | str | no | "" |
78+
| ssh_identity | SSH private key content (inline) | str | no* | None |
79+
| ssh_identity_file | Path to SSH private key file | str | no* | None |
80+
81+
\* Either `ssh_identity` or `ssh_identity_file` must be provided.
82+
83+
### Required children
84+
85+
- `tcp`: A `TcpNetwork` driver providing target host and port
86+
87+
## Usage
88+
89+
Since SSHMITM is used as a child of SSHWrapper, you use the configured command name (e.g., `ssh_mitm`):
90+
91+
```bash
92+
# Execute a command
93+
j ssh_mitm whoami
94+
95+
# Interactive shell
96+
j ssh_mitm
97+
98+
# With arguments
99+
j ssh_mitm ls -la /tmp
100+
101+
# With SSH flags
102+
j ssh_mitm -v hostname
103+
```
104+
105+
**Note**: The command name (`ssh_mitm`) is determined by the key in your exporter config's `export` section. You can use any name you prefer.
106+
107+
## API Reference
108+
109+
```{eval-rst}
110+
.. autoclass:: jumpstarter_driver_ssh_mitm.driver.SSHMITM()
111+
```

0 commit comments

Comments
 (0)