ssh-over-sse 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. ssh_over_sse-0.1.0/.gitignore +10 -0
  2. ssh_over_sse-0.1.0/CHANGELOG.md +18 -0
  3. ssh_over_sse-0.1.0/PKG-INFO +137 -0
  4. ssh_over_sse-0.1.0/README.md +123 -0
  5. ssh_over_sse-0.1.0/pyproject.toml +30 -0
  6. ssh_over_sse-0.1.0/src/ssh_over_sse/__init__.py +3 -0
  7. ssh_over_sse-0.1.0/ssh-sse-gateway/README.md +109 -0
  8. ssh_over_sse-0.1.0/ssh-sse-gateway/pyproject.toml +29 -0
  9. ssh_over_sse-0.1.0/ssh-sse-gateway/src/ssh_sse_gateway/__init__.py +1 -0
  10. ssh_over_sse-0.1.0/ssh-sse-gateway/src/ssh_sse_gateway/app.py +368 -0
  11. ssh_over_sse-0.1.0/ssh-sse-gateway/src/ssh_sse_gateway/audit.py +31 -0
  12. ssh_over_sse-0.1.0/ssh-sse-gateway/src/ssh_sse_gateway/auth.py +142 -0
  13. ssh_over_sse-0.1.0/ssh-sse-gateway/src/ssh_sse_gateway/bridge.py +75 -0
  14. ssh_over_sse-0.1.0/ssh-sse-gateway/src/ssh_sse_gateway/cli.py +62 -0
  15. ssh_over_sse-0.1.0/ssh-sse-gateway/src/ssh_sse_gateway/config.py +251 -0
  16. ssh_over_sse-0.1.0/ssh-sse-gateway/src/ssh_sse_gateway/metrics.py +38 -0
  17. ssh_over_sse-0.1.0/ssh-sse-gateway/src/ssh_sse_gateway/policy.py +109 -0
  18. ssh_over_sse-0.1.0/ssh-sse-gateway/src/ssh_sse_gateway/protocol.py +33 -0
  19. ssh_over_sse-0.1.0/ssh-sse-gateway/src/ssh_sse_gateway/sessions.py +156 -0
  20. ssh_over_sse-0.1.0/ssh-sse-tool/README.md +121 -0
  21. ssh_over_sse-0.1.0/ssh-sse-tool/pyproject.toml +29 -0
  22. ssh_over_sse-0.1.0/ssh-sse-tool/src/ssh_sse_tool/__init__.py +1 -0
  23. ssh_over_sse-0.1.0/ssh-sse-tool/src/ssh_sse_tool/auth.py +65 -0
  24. ssh_over_sse-0.1.0/ssh-sse-tool/src/ssh_sse_tool/cli.py +86 -0
  25. ssh_over_sse-0.1.0/ssh-sse-tool/src/ssh_sse_tool/config.py +242 -0
  26. ssh_over_sse-0.1.0/ssh-sse-tool/src/ssh_sse_tool/protocol.py +48 -0
  27. ssh_over_sse-0.1.0/ssh-sse-tool/src/ssh_sse_tool/sse.py +87 -0
  28. ssh_over_sse-0.1.0/ssh-sse-tool/src/ssh_sse_tool/stdio.py +54 -0
  29. ssh_over_sse-0.1.0/ssh-sse-tool/src/ssh_sse_tool/transport.py +274 -0
@@ -0,0 +1,10 @@
1
+ .venv/
2
+ __pycache__/
3
+ *.py[cod]
4
+ .pytest_cache/
5
+ .ruff_cache/
6
+ .mypy_cache/
7
+ dist/
8
+ *.egg-info/
9
+ .runtime/
10
+ .coverage
@@ -0,0 +1,18 @@
1
+ # Changelog
2
+
3
+ Release notes for ssh-over-sse.
4
+
5
+ ## 0.1.0 — 2026-11-11
6
+
7
+ ### Features
8
+
9
+ - Use SSH, SCP, SFTP, and rsync through an HTTPS gateway.
10
+ - Install the client, gateway, or both with pip, or install either command with uv.
11
+ - Use Ed25519, RSA, and ECDSA keys with existing SSH host settings.
12
+ - Check gateway key access with `ssh-sse-cli --url URL check`; select a key with `-i`.
13
+ - Manage gateway access with `authorized_keys` and allowed SSH destinations.
14
+
15
+ ### Fixes
16
+
17
+ - Keep idle SSH connections alive through OCI gateways.
18
+ - Improve cleanup after interrupted connections and authentication error reporting.
@@ -0,0 +1,137 @@
1
+ Metadata-Version: 2.5
2
+ Name: ssh-over-sse
3
+ Version: 0.1.0
4
+ Summary: Use SSH through an HTTPS gateway with a local CLI, a gateway, or both
5
+ Requires-Python: >=3.12
6
+ Provides-Extra: all
7
+ Requires-Dist: ssh-over-sse-cli==0.1.0; extra == 'all'
8
+ Requires-Dist: ssh-over-sse-gateway==0.1.0; extra == 'all'
9
+ Provides-Extra: cli
10
+ Requires-Dist: ssh-over-sse-cli==0.1.0; extra == 'cli'
11
+ Provides-Extra: gateway
12
+ Requires-Dist: ssh-over-sse-gateway==0.1.0; extra == 'gateway'
13
+ Description-Content-Type: text/markdown
14
+
15
+ # ssh-over-sse
16
+
17
+ Use your usual SSH commands through an HTTPS gateway. Install **ssh-sse-cli** on
18
+ your computer and **ssh-sse-gateway** on a host that can reach your SSH servers.
19
+
20
+ ## Install
21
+
22
+ Requires Python 3.12 or newer and OpenSSH. The client supports Linux and macOS.
23
+ The gateway needs `ssh-keygen` available.
24
+
25
+ Choose the commands you need with pip:
26
+
27
+ | Install | Commands |
28
+ | --- | --- |
29
+ | `pip install 'ssh-over-sse[cli]'` | `ssh-sse-cli` |
30
+ | `pip install 'ssh-over-sse[gateway]'` | `ssh-sse-gateway` |
31
+ | `pip install 'ssh-over-sse[all]'` | Both |
32
+
33
+ `ssh-over-sse[cli,gateway]` also installs both. Select an option when installing;
34
+ the base package alone does not install commands.
35
+
36
+ Or use uv to install either command as a tool:
37
+
38
+ ```sh
39
+ uv tool install --python 3.12 ssh-over-sse-cli
40
+ uv tool install --python 3.12 ssh-over-sse-gateway
41
+ ```
42
+
43
+ Supported keys are Ed25519, RSA (2048–8192 bits), and ECDSA (P-256, P-384, P-521).
44
+ Your private key stays on your computer. Load encrypted keys into `ssh-agent`
45
+ before connecting.
46
+
47
+ ## Connect
48
+
49
+ Ask your administrator for the gateway URL and an allowed SSH destination.
50
+ Add an entry to your SSH configuration using your own values:
51
+
52
+ ```sshconfig
53
+ Host my-server
54
+ HostName 192.0.2.20
55
+ Port 22
56
+ User alice
57
+ IdentityFile ~/.ssh/id_ed25519
58
+ IdentitiesOnly yes
59
+ StrictHostKeyChecking yes
60
+ ProxyCommand ssh-sse-cli --url https://gateway.example.com --ssh-host %n
61
+ ```
62
+
63
+ The client reads the destination, port, user, and identity from that host entry.
64
+ Use the gateway's root URL; no additional path is needed.
65
+
66
+ Connect and transfer files normally:
67
+
68
+ ```sh
69
+ ssh my-server
70
+ scp report.txt my-server:report.txt
71
+ sftp my-server
72
+ rsync -e ssh report.txt my-server:report.txt
73
+ ```
74
+
75
+ Your public key must be authorized by both the gateway and destination server.
76
+ Verify the destination's host key before your first connection.
77
+
78
+ ## Check gateway access
79
+
80
+ Open the gateway URL in a browser to see its landing page, then check your key:
81
+
82
+ ```sh
83
+ ssh-sse-cli --url https://gateway.example.com check
84
+ ```
85
+
86
+ The default identity is `~/.ssh/id_ed25519`. Select another key with `-i`, or use
87
+ `--ssh-host my-server` to read its identity from your SSH configuration:
88
+
89
+ ```sh
90
+ ssh-sse-cli --url https://gateway.example.com -i ~/.ssh/id_ecdsa check
91
+ ssh-sse-cli --url https://gateway.example.com --ssh-host my-server check
92
+ ```
93
+
94
+ Success prints `Gateway SSH key authentication succeeded.` and exits with status
95
+ 0. Failure exits with status 1. This checks gateway access; destination access is
96
+ verified when you connect. Direct backend key checks also accept an HTTP URL.
97
+ SSH connections use HTTPS.
98
+
99
+ ## Run a gateway
100
+
101
+ Save your public HTTPS URL and allowed destinations in
102
+ `~/.config/ssh-over-sse/gateway.yaml`:
103
+
104
+ ```yaml
105
+ server:
106
+ audience: https://gateway.example.com
107
+ listen: 0.0.0.0:7010
108
+ ingress_network_restricted: true
109
+ targets:
110
+ - host: 192.0.2.20
111
+ ports: [22]
112
+ ssh_users: [alice]
113
+ ```
114
+
115
+ Authorize users' public keys in the gateway account's `~/.ssh/authorized_keys`.
116
+ Restrict the configuration file to its owner. Limit backend access to your trusted
117
+ network before setting `ingress_network_restricted: true`.
118
+
119
+ Validate the configuration, then start:
120
+
121
+ ```sh
122
+ ssh-sse-gateway --check-config
123
+ ssh-sse-gateway
124
+ ```
125
+
126
+ With OCI providing HTTPS, the gateway uses plain HTTP on port **7010** and needs
127
+ no TLS certificate. The default listener is `127.0.0.1:7010`; the example above
128
+ accepts ingress on all interfaces.
129
+
130
+ ## Help
131
+
132
+ ```sh
133
+ ssh-sse-cli --help
134
+ ssh-sse-gateway --help
135
+ ```
136
+
137
+ Release notes are in `CHANGELOG.md`.
@@ -0,0 +1,123 @@
1
+ # ssh-over-sse
2
+
3
+ Use your usual SSH commands through an HTTPS gateway. Install **ssh-sse-cli** on
4
+ your computer and **ssh-sse-gateway** on a host that can reach your SSH servers.
5
+
6
+ ## Install
7
+
8
+ Requires Python 3.12 or newer and OpenSSH. The client supports Linux and macOS.
9
+ The gateway needs `ssh-keygen` available.
10
+
11
+ Choose the commands you need with pip:
12
+
13
+ | Install | Commands |
14
+ | --- | --- |
15
+ | `pip install 'ssh-over-sse[cli]'` | `ssh-sse-cli` |
16
+ | `pip install 'ssh-over-sse[gateway]'` | `ssh-sse-gateway` |
17
+ | `pip install 'ssh-over-sse[all]'` | Both |
18
+
19
+ `ssh-over-sse[cli,gateway]` also installs both. Select an option when installing;
20
+ the base package alone does not install commands.
21
+
22
+ Or use uv to install either command as a tool:
23
+
24
+ ```sh
25
+ uv tool install --python 3.12 ssh-over-sse-cli
26
+ uv tool install --python 3.12 ssh-over-sse-gateway
27
+ ```
28
+
29
+ Supported keys are Ed25519, RSA (2048–8192 bits), and ECDSA (P-256, P-384, P-521).
30
+ Your private key stays on your computer. Load encrypted keys into `ssh-agent`
31
+ before connecting.
32
+
33
+ ## Connect
34
+
35
+ Ask your administrator for the gateway URL and an allowed SSH destination.
36
+ Add an entry to your SSH configuration using your own values:
37
+
38
+ ```sshconfig
39
+ Host my-server
40
+ HostName 192.0.2.20
41
+ Port 22
42
+ User alice
43
+ IdentityFile ~/.ssh/id_ed25519
44
+ IdentitiesOnly yes
45
+ StrictHostKeyChecking yes
46
+ ProxyCommand ssh-sse-cli --url https://gateway.example.com --ssh-host %n
47
+ ```
48
+
49
+ The client reads the destination, port, user, and identity from that host entry.
50
+ Use the gateway's root URL; no additional path is needed.
51
+
52
+ Connect and transfer files normally:
53
+
54
+ ```sh
55
+ ssh my-server
56
+ scp report.txt my-server:report.txt
57
+ sftp my-server
58
+ rsync -e ssh report.txt my-server:report.txt
59
+ ```
60
+
61
+ Your public key must be authorized by both the gateway and destination server.
62
+ Verify the destination's host key before your first connection.
63
+
64
+ ## Check gateway access
65
+
66
+ Open the gateway URL in a browser to see its landing page, then check your key:
67
+
68
+ ```sh
69
+ ssh-sse-cli --url https://gateway.example.com check
70
+ ```
71
+
72
+ The default identity is `~/.ssh/id_ed25519`. Select another key with `-i`, or use
73
+ `--ssh-host my-server` to read its identity from your SSH configuration:
74
+
75
+ ```sh
76
+ ssh-sse-cli --url https://gateway.example.com -i ~/.ssh/id_ecdsa check
77
+ ssh-sse-cli --url https://gateway.example.com --ssh-host my-server check
78
+ ```
79
+
80
+ Success prints `Gateway SSH key authentication succeeded.` and exits with status
81
+ 0. Failure exits with status 1. This checks gateway access; destination access is
82
+ verified when you connect. Direct backend key checks also accept an HTTP URL.
83
+ SSH connections use HTTPS.
84
+
85
+ ## Run a gateway
86
+
87
+ Save your public HTTPS URL and allowed destinations in
88
+ `~/.config/ssh-over-sse/gateway.yaml`:
89
+
90
+ ```yaml
91
+ server:
92
+ audience: https://gateway.example.com
93
+ listen: 0.0.0.0:7010
94
+ ingress_network_restricted: true
95
+ targets:
96
+ - host: 192.0.2.20
97
+ ports: [22]
98
+ ssh_users: [alice]
99
+ ```
100
+
101
+ Authorize users' public keys in the gateway account's `~/.ssh/authorized_keys`.
102
+ Restrict the configuration file to its owner. Limit backend access to your trusted
103
+ network before setting `ingress_network_restricted: true`.
104
+
105
+ Validate the configuration, then start:
106
+
107
+ ```sh
108
+ ssh-sse-gateway --check-config
109
+ ssh-sse-gateway
110
+ ```
111
+
112
+ With OCI providing HTTPS, the gateway uses plain HTTP on port **7010** and needs
113
+ no TLS certificate. The default listener is `127.0.0.1:7010`; the example above
114
+ accepts ingress on all interfaces.
115
+
116
+ ## Help
117
+
118
+ ```sh
119
+ ssh-sse-cli --help
120
+ ssh-sse-gateway --help
121
+ ```
122
+
123
+ Release notes are in `CHANGELOG.md`.
@@ -0,0 +1,30 @@
1
+ [project]
2
+ name = "ssh-over-sse"
3
+ version = "0.1.0"
4
+ description = "Use SSH through an HTTPS gateway with a local CLI, a gateway, or both"
5
+ readme = "README.md"
6
+ requires-python = ">=3.12"
7
+ dependencies = []
8
+
9
+ [project.optional-dependencies]
10
+ cli = ["ssh-over-sse-cli==0.1.0"]
11
+ gateway = ["ssh-over-sse-gateway==0.1.0"]
12
+ all = ["ssh-over-sse-cli==0.1.0", "ssh-over-sse-gateway==0.1.0"]
13
+
14
+ [build-system]
15
+ requires = ["hatchling"]
16
+ build-backend = "hatchling.build"
17
+
18
+ [tool.uv.sources]
19
+ ssh-over-sse-cli = { path = "ssh-sse-tool" }
20
+ ssh-over-sse-gateway = { path = "ssh-sse-gateway" }
21
+
22
+ [tool.hatch.build.targets.wheel]
23
+ packages = ["src/ssh_over_sse"]
24
+
25
+ [tool.hatch.build.targets.sdist]
26
+ include = [
27
+ "/pyproject.toml", "/README.md", "/CHANGELOG.md", "/src/ssh_over_sse",
28
+ "/ssh-sse-tool/pyproject.toml", "/ssh-sse-tool/README.md", "/ssh-sse-tool/src",
29
+ "/ssh-sse-gateway/pyproject.toml", "/ssh-sse-gateway/README.md", "/ssh-sse-gateway/src",
30
+ ]
@@ -0,0 +1,3 @@
1
+ """SSH over HTTPS/SSE. Install the cli, gateway, or all extra to select commands."""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,109 @@
1
+ # ssh-sse-gateway
2
+
3
+ Provide authorized SSH access through an HTTPS endpoint. Run the gateway on a
4
+ host that can reach your approved SSH destinations.
5
+
6
+ ## Install
7
+
8
+ Requires Python 3.12 or newer and OpenSSH's `ssh-keygen`.
9
+
10
+ With uv:
11
+
12
+ ```sh
13
+ uv tool install --python 3.12 ssh-over-sse-gateway
14
+ ```
15
+
16
+ Or with pip:
17
+
18
+ ```sh
19
+ pip install 'ssh-over-sse[gateway]'
20
+ ```
21
+
22
+ Use `ssh-over-sse[all]` with pip to install the client command too.
23
+
24
+ ## Configure
25
+
26
+ Save your configuration as `~/.config/ssh-over-sse/gateway.yaml`. Use your public
27
+ HTTPS root URL and allow each SSH destination and login username:
28
+
29
+ ```yaml
30
+ server:
31
+ audience: https://gateway.example.com
32
+ listen: 0.0.0.0:7010
33
+ ingress_network_restricted: true
34
+ targets:
35
+ - host: 192.0.2.20
36
+ ports: [22]
37
+ ssh_users: [alice]
38
+ ```
39
+
40
+ Replace the example values and restrict the file to its owner. Limit backend
41
+ access to your trusted network before setting `ingress_network_restricted: true`;
42
+ this setting acknowledges your network restrictions and does not create them.
43
+
44
+ The default listener is `127.0.0.1:7010`. With OCI providing HTTPS, the gateway
45
+ runs plain HTTP on port **7010** and needs no backend certificate. The example
46
+ above accepts ingress on all interfaces.
47
+
48
+ ## Authorize users
49
+
50
+ The gateway reads public keys from its account's `~/.ssh/authorized_keys` by
51
+ default. Set `server.authorized_keys_file` if the file is elsewhere.
52
+
53
+ Supported entries are unrestricted Ed25519, RSA (2048–8192 bits), and ECDSA
54
+ (P-256, P-384, P-521) public keys. Entries with SSH restrictions such as `from=` or
55
+ `command=` are skipped. Use only keys intended to have gateway access.
56
+
57
+ All eligible keys authenticate to the gateway account. The requested destination
58
+ and SSH username must also be allowed in your configuration. The destination
59
+ server separately authorizes the user's SSH login. Private user keys stay on
60
+ users' computers.
61
+
62
+ Removing a key denies new access and ends its active connections. Restart the
63
+ gateway after changing destination permissions; restarting ends active sessions.
64
+
65
+ ## Start
66
+
67
+ Validate the configuration, then start:
68
+
69
+ ```sh
70
+ ssh-sse-gateway --check-config
71
+ ssh-sse-gateway
72
+ ```
73
+
74
+ To use another configuration file:
75
+
76
+ ```sh
77
+ ssh-sse-gateway --config /path/to/gateway.yaml --check-config
78
+ ssh-sse-gateway --config /path/to/gateway.yaml
79
+ ```
80
+
81
+ Configure HTTPS ingress to forward requests to the gateway. It must pass
82
+ authorization headers and support streaming without buffering or compression.
83
+ The root URL shows a landing page in a browser. Users pass that same root URL to
84
+ `ssh-sse-cli`.
85
+
86
+ For direct HTTPS without an ingress, set `server.tls_mode: direct` and provide
87
+ `--tls-cert /path/to/cert.pem` and `--tls-key /path/to/key.pem` when starting.
88
+ Restrict the server's private certificate key to its owner.
89
+
90
+ ## Check access
91
+
92
+ From a user's computer:
93
+
94
+ ```sh
95
+ ssh-sse-cli --url https://gateway.example.com -i ~/.ssh/id_ecdsa check
96
+ ```
97
+
98
+ Success confirms gateway key access. Users still need destination permission and
99
+ an authorized SSH login. A landing page alone does not confirm SSH access.
100
+
101
+ ## Troubleshooting
102
+
103
+ If startup fails, run `--check-config` and check required values, file ownership,
104
+ and permissions. If users cannot connect, check the HTTPS route, public-key
105
+ access, destination permissions, and network reachability.
106
+
107
+ ```sh
108
+ ssh-sse-gateway --help
109
+ ```
@@ -0,0 +1,29 @@
1
+ [project]
2
+ name = "ssh-over-sse-gateway"
3
+ version = "0.1.0"
4
+ readme = "README.md"
5
+ description = "Policy-restricted SSH TCP relay over HTTPS POST and SSE"
6
+ requires-python = ">=3.12"
7
+ dependencies = ["starlette>=1.3.1,<2", "uvicorn>=0.35,<1", "pyyaml>=6,<7", "cryptography>=45"]
8
+ [project.scripts]
9
+ ssh-sse-gateway = "ssh_sse_gateway.cli:main"
10
+ [build-system]
11
+ requires = ["hatchling"]
12
+ build-backend = "hatchling.build"
13
+ [dependency-groups]
14
+ dev = ["pytest>=8", "pytest-asyncio>=1", "httpx>=0.28", "ruff>=0.12", "mypy>=1.16", "types-PyYAML"]
15
+ [tool.pytest.ini_options]
16
+ asyncio_mode = "auto"
17
+ asyncio_default_fixture_loop_scope = "function"
18
+ [tool.ruff]
19
+ line-length = 100
20
+ [tool.ruff.lint]
21
+ select = ["E4", "E7", "E9", "F", "I"]
22
+ [tool.mypy]
23
+ check_untyped_defs = true
24
+
25
+ [tool.hatch.build.targets.wheel]
26
+ packages = ["src/ssh_sse_gateway"]
27
+
28
+ [tool.hatch.build.targets.sdist]
29
+ include = ["/pyproject.toml", "/README.md", "/uv.lock", "/src"]
@@ -0,0 +1 @@
1
+ """SSH-over-SSE gateway."""