@@ -38,6 +38,8 @@ import { GitpodPublicApi } from './publicApi';
38
38
import { SSHKey } from '@gitpod/public-api/lib/gitpod/experimental/v1/user_pb' ;
39
39
import { getAgentSock , SSHError , testSSHConnection } from './sshTestConnection' ;
40
40
import { gatherIdentityFiles } from './ssh/identityFiles' ;
41
+ import { isWindows } from './common/platform' ;
42
+ import SSHDestination from './ssh/sshDestination' ;
41
43
42
44
interface SSHConnectionParams {
43
45
workspaceId : string ;
@@ -443,7 +445,7 @@ export default class RemoteConnector extends Disposable {
443
445
}
444
446
}
445
447
446
- private async getWorkspaceSSHDestination ( session : vscode . AuthenticationSession , { workspaceId, gitpodHost, debugWorkspace } : SSHConnectionParams ) : Promise < { destination : string ; password ?: string } > {
448
+ private async getWorkspaceSSHDestination ( session : vscode . AuthenticationSession , { workspaceId, gitpodHost, debugWorkspace } : SSHConnectionParams ) : Promise < { destination : SSHDestination ; password ?: string } > {
447
449
const serviceUrl = new URL ( gitpodHost ) ;
448
450
const sshKeysSupported = session . scopes . includes ( ScopeFeature . SSHPublicKeys ) ;
449
451
@@ -471,21 +473,20 @@ export default class RemoteConnector extends Disposable {
471
473
throw new NoSSHGatewayError ( gitpodHost ) ;
472
474
}
473
475
474
- const sshHostKeys = ( await sshHostKeyResponse . json ( ) ) as { type : string ; host_key : string } [ ] ;
476
+ const sshHostKeys = ( await sshHostKeyResponse . json ( ) ) as { type : string ; host_key : string } [ ] ;
475
477
let user = workspaceId ;
476
478
// See https://github.com/gitpod-io/gitpod/pull/9786 for reasoning about `.ssh` suffix
477
- let hostName = workspaceUrl . host . replace ( workspaceId , `${ workspaceId } .ssh` )
479
+ let hostname = workspaceUrl . host . replace ( workspaceId , `${ workspaceId } .ssh` ) ;
478
480
if ( debugWorkspace ) {
479
481
user = 'debug-' + workspaceId ;
480
- hostName = hostName . replace ( workspaceId , user ) ;
482
+ hostname = hostname . replace ( workspaceId , user ) ;
481
483
}
482
- const sshDestInfo = { user, hostName } ;
483
484
484
485
const sshConfiguration = await SSHConfiguration . loadFromFS ( ) ;
485
486
486
487
const verifiedHostKey = await testSSHConnection ( {
487
- host : sshDestInfo . hostName ,
488
- username : sshDestInfo . user ,
488
+ host : hostname ,
489
+ username : user ,
489
490
readyTimeout : 40000 ,
490
491
password : ownerToken
491
492
} , sshHostKeys , sshConfiguration , this . logger ) ;
@@ -497,15 +498,15 @@ const sshHostKeys = (await sshHostKeyResponse.json()) as { type: string; host_ke
497
498
throw result ;
498
499
}
499
500
const parseKey = Array . isArray ( result ) ? result [ 0 ] : result ;
500
- if ( parseKey && await checkNewHostInHostkeys ( sshDestInfo . hostName ) ) {
501
- await addHostToHostFile ( sshDestInfo . hostName , verifiedHostKey ! , parseKey . type ) ;
502
- this . logger . info ( `'${ sshDestInfo . hostName } ' host added to known_hosts file` ) ;
501
+ if ( parseKey && await checkNewHostInHostkeys ( hostname ) ) {
502
+ await addHostToHostFile ( hostname , verifiedHostKey ! , parseKey . type ) ;
503
+ this . logger . info ( `'${ hostname } ' host added to known_hosts file` ) ;
503
504
}
504
505
} catch ( e ) {
505
- this . logger . error ( `Couldn't write '${ sshDestInfo . hostName } ' host to known_hosts file:` , e ) ;
506
+ this . logger . error ( `Couldn't write '${ hostname } ' host to known_hosts file:` , e ) ;
506
507
}
507
508
508
- const hostConfiguration = sshConfiguration . getHostConfiguration ( sshDestInfo . hostName ) ;
509
+ const hostConfiguration = sshConfiguration . getHostConfiguration ( hostname ) ;
509
510
let identityKeys = await gatherIdentityFiles ( [ ] , getAgentSock ( hostConfiguration ) , false , this . logger ) ;
510
511
511
512
if ( registeredSSHKeys ) {
@@ -526,19 +527,19 @@ const sshHostKeys = (await sshHostKeyResponse.json()) as { type: string; host_ke
526
527
identityKeys = identityKeys . filter ( k => ! ! registeredKeys . find ( regKey => regKey . fingerprint === k . fingerprint ) ) ;
527
528
} else {
528
529
if ( identityKeys . length ) {
529
- sshDestInfo . user = `${ user } #${ ownerToken } ` ;
530
+ user = `${ user } #${ ownerToken } ` ;
530
531
}
531
532
const gitpodVersion = await getGitpodVersion ( gitpodHost , this . logger ) ;
532
533
this . logger . warn ( `Registered SSH public keys not supported in ${ gitpodHost } , using version ${ gitpodVersion . raw } ` ) ;
533
534
}
534
535
535
536
return {
536
- destination : Buffer . from ( JSON . stringify ( sshDestInfo ) , 'utf8' ) . toString ( 'hex' ) ,
537
+ destination : new SSHDestination ( hostname , user ) ,
537
538
password : identityKeys . length === 0 ? ownerToken : undefined
538
539
} ;
539
540
}
540
541
541
- private async getWorkspaceLocalAppSSHDestination ( params : SSHConnectionParams ) : Promise < { localAppSSHDest : string ; localAppSSHConfigPath : string } > {
542
+ private async getWorkspaceLocalAppSSHDestination ( params : SSHConnectionParams ) : Promise < { destination : SSHDestination ; localAppSSHConfigPath : string } > {
542
543
return vscode . window . withProgress ( {
543
544
location : vscode . ProgressLocation . Notification ,
544
545
cancellable : true ,
@@ -558,7 +559,7 @@ const sshHostKeys = (await sshHostKeyResponse.json()) as { type: string; host_ke
558
559
} , token ) ;
559
560
560
561
return {
561
- localAppSSHDest : connection . getHost ( ) ,
562
+ destination : new SSHDestination ( connection . getHost ( ) ) ,
562
563
localAppSSHConfigPath : connection . getConfigFile ( )
563
564
} ;
564
565
} catch ( e ) {
@@ -721,7 +722,7 @@ const sshHostKeys = (await sshHostKeyResponse.json()) as { type: string; host_ke
721
722
? ( await this . experiments . get < boolean > ( 'gitpod.remote.useLocalApp' , session . account . id , { gitpodHost : params . gitpodHost } ) ) !
722
723
: ( await this . experiments . get < boolean > ( 'gitpod.remote.useLocalApp' , session . account . id , { gitpodHost : params . gitpodHost } , 'gitpod_remote_useLocalApp_sh' ) ) ! ;
723
724
const userOverride = String ( isUserOverrideSetting ( 'gitpod.remote.useLocalApp' ) ) ;
724
- let sshDestination : string | undefined ;
725
+ let sshDestination : SSHDestination | undefined ;
725
726
if ( ! forceUseLocalApp ) {
726
727
const openSSHVersion = await getOpenSSHVersion ( ) ;
727
728
const gatewayFlow = { kind : 'gateway' , openSSHVersion, userOverride, ...sshFlow } ;
@@ -782,7 +783,7 @@ const sshHostKeys = (await sshHostKeyResponse.json()) as { type: string; host_ke
782
783
this . telemetry . sendUserFlowStatus ( 'connecting' , localAppFlow ) ;
783
784
784
785
const localAppDestData = await this . getWorkspaceLocalAppSSHDestination ( params ) ;
785
- sshDestination = localAppDestData . localAppSSHDest ;
786
+ sshDestination = localAppDestData . destination ;
786
787
localAppSSHConfigPath = localAppDestData . localAppSSHConfigPath ;
787
788
788
789
this . telemetry . sendUserFlowStatus ( 'connected' , localAppFlow ) ;
@@ -811,12 +812,21 @@ const sshHostKeys = (await sshHostKeyResponse.json()) as { type: string; host_ke
811
812
812
813
await this . updateRemoteSSHConfig ( usingSSHGateway , localAppSSHConfigPath ) ;
813
814
814
- await this . context . globalState . update ( `${ RemoteConnector . SSH_DEST_KEY } ${ sshDestination ! } ` , { ...params , isFirstConnection : true } ) ;
815
+ await this . context . globalState . update ( `${ RemoteConnector . SSH_DEST_KEY } ${ sshDestination ! . toRemoteSSHString ( ) } ` , { ...params , isFirstConnection : true } ) ;
815
816
816
817
const forceNewWindow = this . context . extensionMode === vscode . ExtensionMode . Production ;
818
+
819
+ // Force Linux as host platform (https://github.com/gitpod-io/gitpod/issues/16058)
820
+ if ( isWindows ) {
821
+ const existingSSHHostPlatforms = vscode . workspace . getConfiguration ( 'remote.SSH' ) . get < { [ host : string ] : string } > ( 'remotePlatform' , { } ) ;
822
+ if ( ! existingSSHHostPlatforms [ sshDestination ! . hostname ] ) {
823
+ await vscode . workspace . getConfiguration ( 'remote.SSH' ) . update ( 'remotePlatform' , { ...existingSSHHostPlatforms , [ sshDestination ! . hostname ] : 'linux' } , vscode . ConfigurationTarget . Global ) ;
824
+ }
825
+ }
826
+
817
827
vscode . commands . executeCommand (
818
828
'vscode.openFolder' ,
819
- vscode . Uri . parse ( `vscode-remote://ssh-remote+${ sshDestination } ${ uri . path || '/' } ` ) ,
829
+ vscode . Uri . parse ( `vscode-remote://ssh-remote+${ sshDestination ! . toRemoteSSHString ( ) } ${ uri . path || '/' } ` ) ,
820
830
{ forceNewWindow }
821
831
) ;
822
832
}
0 commit comments