Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/platform/agentHost/common/sshRemoteAgentHost.ts
13394 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { Event } from '../../../base/common/event.js';
7
import { IDisposable } from '../../../base/common/lifecycle.js';
8
import { URI } from '../../../base/common/uri.js';
9
import { createDecorator } from '../../instantiation/common/instantiation.js';
10
11
export const ISSHRemoteAgentHostService = createDecorator<ISSHRemoteAgentHostService>('sshRemoteAgentHostService');
12
13
/**
14
* IPC channel name for the main-process SSH service.
15
*/
16
export const SSH_REMOTE_AGENT_HOST_CHANNEL = 'sshRemoteAgentHost';
17
18
export const enum SSHAuthMethod {
19
/** Use the local SSH agent for key-based auth. */
20
Agent = 'agent',
21
/** Authenticate with an explicit private key file. */
22
KeyFile = 'keyFile',
23
/** Authenticate with a password. */
24
Password = 'password',
25
}
26
27
export interface ISSHAgentHostConfig {
28
/** Remote hostname or IP. */
29
readonly host: string;
30
/** SSH port (default 22). */
31
readonly port?: number;
32
/** Username on the remote machine. */
33
readonly username: string;
34
/** Authentication method. */
35
readonly authMethod: SSHAuthMethod;
36
/** Path to the private key file (when {@link authMethod} is KeyFile). */
37
readonly privateKeyPath?: string;
38
/** Password string (when {@link authMethod} is Password). */
39
readonly password?: string;
40
/** Display name for this connection. */
41
readonly name: string;
42
/** SSH config host alias (e.g. "robfast2") for reconnection on restart. */
43
readonly sshConfigHost?: string;
44
/** Dev override: custom command to start the remote agent host instead of the default CLI. */
45
readonly remoteAgentHostCommand?: string;
46
/** When true, enables OpenSSH agent forwarding ([email protected]) for this connection. Requires {@link authMethod} to be Agent. */
47
readonly agentForward?: boolean;
48
}
49
50
/**
51
* A sanitized view of the SSH config that omits secret material
52
* (password, private key path). Exposed on active connections so
53
* consumers can inspect connection metadata without accessing credentials.
54
*/
55
export type ISSHAgentHostConfigSanitized = Omit<ISSHAgentHostConfig, 'password' | 'privateKeyPath'>;
56
57
export interface ISSHAgentHostConnection extends IDisposable {
58
/** The SSH config used to establish this connection (secrets stripped). */
59
readonly config: ISSHAgentHostConfigSanitized;
60
/** The connection address (e.g. `ssh:myhost` or `user@host:22`) registered with IRemoteAgentHostService. */
61
readonly localAddress: string;
62
/** The display name. */
63
readonly name: string;
64
/** Fires when this SSH connection is closed or lost. */
65
readonly onDidClose: Event<void>;
66
}
67
68
/**
69
* Manages SSH connections that bootstrap a remote agent host process.
70
*
71
* Each connection SSHs into a remote machine, ensures the VS Code CLI
72
* is installed, starts `code agent-host`, and creates a WebSocket relay
73
* over the SSH channel. Messages are forwarded between the renderer and
74
* the remote agent host via IPC through the shared process.
75
*/
76
export interface ISSHRemoteAgentHostService {
77
readonly _serviceBrand: undefined;
78
79
/** Fires when the set of active SSH connections changes. */
80
readonly onDidChangeConnections: Event<void>;
81
82
/** Progress messages during connect. */
83
readonly onDidReportConnectProgress: Event<ISSHConnectProgress>;
84
85
/** Currently active SSH-bootstrapped connections. */
86
readonly connections: readonly ISSHAgentHostConnection[];
87
88
/**
89
* Bootstrap a remote agent host over SSH.
90
*
91
* 1. Opens an SSH connection to the remote host
92
* 2. Downloads and installs the VS Code CLI if needed
93
* 3. Starts `code agent-host`
94
* 4. Creates a WebSocket relay over the SSH channel
95
* 5. Registers the connection with {@link IRemoteAgentHostService}
96
*
97
* Resolves with the connection handle once the agent host is reachable.
98
*/
99
connect(config: ISSHAgentHostConfig): Promise<ISSHAgentHostConnection>;
100
101
/**
102
* Disconnect an SSH-bootstrapped connection by host address.
103
* Tears down the SSH tunnel, stops the remote agent host, and
104
* removes the entry from {@link IRemoteAgentHostService}.
105
*/
106
disconnect(host: string): Promise<void>;
107
108
/** List SSH config host aliases (excluding wildcards). */
109
listSSHConfigHosts(): Promise<string[]>;
110
111
/**
112
* Ensure `~/.ssh/config` exists (creating it with the right permissions if
113
* missing) and return its URI. The parent `~/.ssh` directory is created
114
* with mode 0700 and the config file with mode 0600 on POSIX systems.
115
*/
116
ensureUserSSHConfig(): Promise<URI>;
117
118
/**
119
* List the known SSH configuration file URIs in priority order — typically the
120
* per-user `~/.ssh/config` (always returned, even if it does not yet exist) and
121
* the system-wide `/etc/ssh/ssh_config` (only when present on disk).
122
*/
123
listSSHConfigFiles(): Promise<URI[]>;
124
125
/** Resolve full SSH config for a host via `ssh -G`. */
126
resolveSSHConfig(host: string): Promise<ISSHResolvedConfig>;
127
128
/**
129
* Re-establish an SSH tunnel on startup for a previously connected host.
130
* Returns the new local forwarded address and registers it.
131
*/
132
reconnect(sshConfigHost: string, name: string): Promise<ISSHAgentHostConnection>;
133
}
134
/**
135
* Serializable result from a successful SSH connect operation.
136
* Returned over IPC from the main process.
137
*/
138
export interface ISSHConnectResult {
139
/** Unique identifier for this connection's relay channel. */
140
readonly connectionId: string;
141
/** Display-friendly address (e.g. "ssh:robfast2"). */
142
readonly address: string;
143
readonly name: string;
144
readonly connectionToken: string | undefined;
145
readonly config: ISSHAgentHostConfigSanitized;
146
/** SSH config host alias for reconnection on restart. */
147
readonly sshConfigHost?: string;
148
}
149
150
/**
151
* Resolved SSH configuration for a host, obtained from `ssh -G`.
152
*/
153
export interface ISSHResolvedConfig {
154
readonly hostname: string;
155
readonly user: string | undefined;
156
readonly port: number;
157
readonly identityFile: string[];
158
readonly forwardAgent: boolean;
159
}
160
161
export interface ISSHConnectProgress {
162
readonly connectionKey: string;
163
readonly message: string;
164
}
165
166
/**
167
* A message relayed from a remote agent host through the SSH tunnel.
168
* The shared process acts as a WebSocket proxy, forwarding JSON messages
169
* bidirectionally between the SSH channel and the renderer via IPC.
170
*/
171
export interface ISSHRelayMessage {
172
readonly connectionId: string;
173
readonly data: string;
174
}
175
176
/**
177
* Main-process service that performs the actual SSH work.
178
* The renderer calls this over IPC and handles registration
179
* with {@link IRemoteAgentHostService} locally.
180
*/
181
export const ISSHRemoteAgentHostMainService = createDecorator<ISSHRemoteAgentHostMainService>('sshRemoteAgentHostMainService');
182
183
export interface ISSHRemoteAgentHostMainService {
184
readonly _serviceBrand: undefined;
185
186
/** Fires when the set of active SSH connections changes. */
187
readonly onDidChangeConnections: Event<void>;
188
189
/** Fires when a connection is closed from the shared process side. */
190
readonly onDidCloseConnection: Event<string /* connectionId */>;
191
192
/** Progress messages during connect (e.g. "Installing CLI..."). */
193
readonly onDidReportConnectProgress: Event<ISSHConnectProgress>;
194
195
/** Fires when a message is received from a remote agent host via the SSH relay. */
196
readonly onDidRelayMessage: Event<ISSHRelayMessage>;
197
198
/** Fires when a relay connection to a remote agent host closes. */
199
readonly onDidRelayClose: Event<string /* connectionId */>;
200
201
/**
202
* Bootstrap a remote agent host over SSH. Returns serializable
203
* connection info for the renderer to register.
204
*/
205
connect(config: ISSHAgentHostConfig): Promise<ISSHConnectResult>;
206
207
/**
208
* Send a message to a remote agent host through the SSH relay.
209
*/
210
relaySend(connectionId: string, message: string): Promise<void>;
211
212
/**
213
* Disconnect an SSH-bootstrapped connection by host address.
214
*/
215
disconnect(host: string): Promise<void>;
216
217
/** List SSH config host aliases (excluding wildcards). */
218
listSSHConfigHosts(): Promise<string[]>;
219
220
/**
221
* Ensure `~/.ssh/config` exists (creating it with the right permissions if
222
* missing) and return its URI.
223
*/
224
ensureUserSSHConfig(): Promise<URI>;
225
226
/** List the known SSH configuration file URIs (user config always included). */
227
listSSHConfigFiles(): Promise<URI[]>;
228
229
/** Resolve full SSH config for a host via `ssh -G`. */
230
resolveSSHConfig(host: string): Promise<ISSHResolvedConfig>;
231
232
/**
233
* Re-establish an SSH tunnel for a previously connected host.
234
* Resolves the SSH config alias, connects, and returns fresh
235
* connection info with a new local forwarded port.
236
*/
237
reconnect(sshConfigHost: string, name: string, remoteAgentHostCommand?: string, agentForward?: boolean): Promise<ISSHConnectResult>;
238
}
239
240