Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita53b8db

Browse files
authored
feat: add handling for insecure requests (#106)
1 parent9b936cd commita53b8db

File tree

7 files changed

+148
-23
lines changed

7 files changed

+148
-23
lines changed

‎package.json‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@
4242
},
4343
"scope":"machine",
4444
"default": []
45+
},
46+
"coder.insecure": {
47+
"markdownDescription":"If true, the extension will not verify the authenticity of the remote host. This is useful for self-signed certificates.",
48+
"type":"boolean",
49+
"default":false
4550
}
4651
}
4752
},
@@ -241,4 +246,4 @@
241246
"yaml":"^1.10.0",
242247
"zod":"^3.21.4"
243248
}
244-
}
249+
}

‎src/commands.ts‎

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { getAuthenticatedUser, getWorkspaces, updateWorkspaceVersion } from "cod
33
import{Workspace,WorkspaceAgent}from"coder/site/src/api/typesGenerated"
44
import*asvscodefrom"vscode"
55
import{extractAgents}from"./api-helper"
6+
import{SelfSignedCertificateError}from"./error"
67
import{Remote}from"./remote"
78
import{Storage}from"./storage"
89
import{OpenableTreeItem}from"./workspacesProvider"
@@ -61,6 +62,14 @@ export class Commands {
6162
if(axios.isAxiosError(err)&&err.response?.data){
6263
message=err.response.data.detail
6364
}
65+
if(errinstanceofSelfSignedCertificateError){
66+
err.showInsecureNotification(this.storage)
67+
68+
return{
69+
message:err.message,
70+
severity:vscode.InputBoxValidationSeverity.Error,
71+
}
72+
}
6473
return{
6574
message:"Invalid session token! ("+message+")",
6675
severity:vscode.InputBoxValidationSeverity.Error,
@@ -189,7 +198,10 @@ export class Commands {
189198
quickPick.items=items
190199
quickPick.busy=false
191200
})
192-
.catch(()=>{
201+
.catch((ex)=>{
202+
if(exinstanceofSelfSignedCertificateError){
203+
ex.showInsecureNotification(this.storage)
204+
}
193205
return
194206
})
195207
})

‎src/error.ts‎

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import*asfsfrom"fs/promises"
2+
import*asjsoncfrom"jsonc-parser"
3+
import*asvscodefrom"vscode"
4+
import{Storage}from"./storage"
5+
6+
exportclassSelfSignedCertificateErrorextendsError{
7+
publicstaticNotification=
8+
"Your Coder deployment is using a self-signed certificate. VS Code uses a version of Electron that does not support registering self-signed intermediate certificates with extensions."
9+
publicstaticActionAllowInsecure="Allow Insecure"
10+
publicstaticActionViewMoreDetails="View More Details"
11+
12+
constructor(message:string){
13+
super(`Your Coder deployment is using a self-signed certificate:${message}`)
14+
}
15+
16+
publicviewMoreDetails():Thenable<boolean>{
17+
returnvscode.env.openExternal(vscode.Uri.parse("https://github.com/coder/vscode-coder/issues/105"))
18+
}
19+
20+
// allowInsecure manually reads the settings file and updates the value of the
21+
// "coder.insecure" property.
22+
publicasyncallowInsecure(storage:Storage):Promise<void>{
23+
letsettingsContent="{}"
24+
try{
25+
settingsContent=awaitfs.readFile(storage.getUserSettingsPath(),"utf8")
26+
}catch(ex){
27+
// Ignore! It's probably because the file doesn't exist.
28+
}
29+
constedits=jsonc.modify(settingsContent,["coder.insecure"],true,{})
30+
awaitfs.writeFile(storage.getUserSettingsPath(),jsonc.applyEdits(settingsContent,edits))
31+
32+
vscode.window.showInformationMessage(
33+
'The Coder extension will no longer verify TLS on HTTPS requests. You can change this at any time with the "coder.insecure" property in your VS Code settings.',
34+
)
35+
}
36+
37+
publicasyncshowInsecureNotification(storage:Storage):Promise<void>{
38+
constvalue=awaitvscode.window.showErrorMessage(
39+
SelfSignedCertificateError.Notification,
40+
SelfSignedCertificateError.ActionAllowInsecure,
41+
SelfSignedCertificateError.ActionViewMoreDetails,
42+
)
43+
if(value===SelfSignedCertificateError.ActionViewMoreDetails){
44+
awaitthis.viewMoreDetails()
45+
return
46+
}
47+
if(value===SelfSignedCertificateError.ActionAllowInsecure){
48+
returnthis.allowInsecure(storage)
49+
}
50+
}
51+
}

‎src/extension.ts‎

Lines changed: 75 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,67 @@
11
"use strict"
2+
importaxiosfrom"axios"
23
import{getAuthenticatedUser}from"coder/site/src/api/api"
4+
import*ashttpsfrom"https"
35
import*asmodulefrom"module"
46
import*asvscodefrom"vscode"
57
import{Commands}from"./commands"
8+
import{SelfSignedCertificateError}from"./error"
69
import{Remote}from"./remote"
710
import{Storage}from"./storage"
811
import{WorkspaceQuery,WorkspaceProvider}from"./workspacesProvider"
912

1013
exportasyncfunctionactivate(ctx:vscode.ExtensionContext):Promise<void>{
14+
// The Remote SSH extension's proposed APIs are used to override
15+
// the SSH host name in VS Code itself. It's visually unappealing
16+
// having a lengthy name!
17+
//
18+
// This is janky, but that's alright since it provides such minimal
19+
// functionality to the extension.
20+
constremoteSSHExtension=vscode.extensions.getExtension("ms-vscode-remote.remote-ssh")
21+
if(!remoteSSHExtension){
22+
thrownewError("Remote SSH extension not found")
23+
}
24+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
25+
constvscodeProposed:typeofvscode=(moduleasany)._load(
26+
"vscode",
27+
{
28+
filename:remoteSSHExtension?.extensionPath,
29+
},
30+
false,
31+
)
32+
33+
// updateInsecure is called on extension activation and when the insecure
34+
// setting is changed. It updates the https agent to allow self-signed
35+
// certificates if the insecure setting is true.
36+
constapplyInsecure=()=>{
37+
constinsecure=Boolean(vscode.workspace.getConfiguration().get("coder.insecure"))
38+
39+
axios.defaults.httpsAgent=newhttps.Agent({
40+
// rejectUnauthorized defaults to true, so we need to explicitly set it to false
41+
// if we want to allow self-signed certificates.
42+
rejectUnauthorized:!insecure,
43+
})
44+
}
45+
46+
axios.interceptors.response.use(
47+
(r)=>r,
48+
(err)=>{
49+
if(err){
50+
constmsg=err.toString()asstring
51+
if(msg.indexOf("unable to verify the first certificate")!==-1){
52+
thrownewSelfSignedCertificateError(msg)
53+
}
54+
}
55+
56+
throwerr
57+
},
58+
)
59+
60+
vscode.workspace.onDidChangeConfiguration((e)=>{
61+
e.affectsConfiguration("coder.insecure")&&applyInsecure()
62+
})
63+
applyInsecure()
64+
1165
constoutput=vscode.window.createOutputChannel("Coder")
1266
conststorage=newStorage(output,ctx.globalState,ctx.secrets,ctx.globalStorageUri,ctx.logUri)
1367
awaitstorage.init()
@@ -62,25 +116,6 @@ export async function activate(ctx: vscode.ExtensionContext): Promise<void> {
62116
},
63117
})
64118

65-
// The Remote SSH extension's proposed APIs are used to override
66-
// the SSH host name in VS Code itself. It's visually unappealing
67-
// having a lengthy name!
68-
//
69-
// This is janky, but that's alright since it provides such minimal
70-
// functionality to the extension.
71-
constremoteSSHExtension=vscode.extensions.getExtension("ms-vscode-remote.remote-ssh")
72-
if(!remoteSSHExtension){
73-
thrownewError("Remote SSH extension not found")
74-
}
75-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
76-
constvscodeProposed:typeofvscode=(moduleasany)._load(
77-
"vscode",
78-
{
79-
filename:remoteSSHExtension?.extensionPath,
80-
},
81-
false,
82-
)
83-
84119
constcommands=newCommands(vscodeProposed,storage)
85120

86121
vscode.commands.registerCommand("coder.login",commands.login.bind(commands))
@@ -109,6 +144,27 @@ export async function activate(ctx: vscode.ExtensionContext): Promise<void> {
109144
try{
110145
awaitremote.setup(vscodeProposed.env.remoteAuthority)
111146
}catch(ex){
147+
if(exinstanceofSelfSignedCertificateError){
148+
constprompt=awaitvscodeProposed.window.showErrorMessage(
149+
"Failed to open workspace",
150+
{
151+
detail:SelfSignedCertificateError.Notification,
152+
modal:true,
153+
useCustom:true,
154+
},
155+
SelfSignedCertificateError.ActionAllowInsecure,
156+
SelfSignedCertificateError.ActionViewMoreDetails,
157+
)
158+
if(prompt===SelfSignedCertificateError.ActionAllowInsecure){
159+
awaitex.allowInsecure(storage)
160+
awaitremote.reloadWindow()
161+
return
162+
}
163+
if(prompt===SelfSignedCertificateError.ActionViewMoreDetails){
164+
awaitex.viewMoreDetails()
165+
return
166+
}
167+
}
112168
awaitvscodeProposed.window.showErrorMessage("Failed to open workspace",{
113169
detail:(exasstring).toString(),
114170
modal:true,

‎src/remote.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -696,7 +696,7 @@ export class Remote {
696696
}
697697

698698
// reloadWindow reloads the current window.
699-
privateasyncreloadWindow(){
699+
publicasyncreloadWindow(){
700700
awaitvscode.commands.executeCommand("workbench.action.reloadWindow")
701701
}
702702

‎src/sshSupport.test.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { computeSSHProperties, sshSupportsSetEnv, sshVersionSupportsSetEnv } fro
33

44
constsupports={
55
"OpenSSH_8.9p1 Ubuntu-3ubuntu0.1, OpenSSL 3.0.2 15 Mar 2022":true,
6+
"OpenSSH_for_Windows_8.1p1, LibreSSL 3.0.2":true,
67
"OpenSSH_9.0p1, LibreSSL 3.3.6":true,
78
"OpenSSH_7.6p1 Ubuntu-4ubuntu0.7, OpenSSL 1.0.2n 7 Dec 2017":false,
89
"OpenSSH_7.4p1, OpenSSL 1.0.2k-fips 26 Jan 2017":false,

‎src/sshSupport.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export function sshSupportsSetEnv(): boolean {
1616
//
1717
// It was introduced in SSH 7.8 and not all versions support it.
1818
exportfunctionsshVersionSupportsSetEnv(sshVersionString:string):boolean{
19-
constmatch=sshVersionString.match(/OpenSSH_([\d.]+)[^,]*/)
19+
constmatch=sshVersionString.match(/OpenSSH.*_([\d.]+)[^,]*/)
2020
if(match&&match[1]){
2121
constinstalledVersion=match[1]
2222
constparts=installedVersion.split(".")

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp