Skip to content

Commit 6777104

Browse files
authored
Merge pull request #80 from GitGuardian/severine/fix-ggshield-retrieval-with-proxy
(Attempt) Fix ggshield retrieval with proxy
2 parents 456226a + 613ea33 commit 6777104

9 files changed

+169
-311
lines changed

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ repos:
1818
stages: [commit-msg]
1919
additional_dependencies: [ggcommitizen]
2020

21-
- repo: https://github.com/pre-commit/mirrors-prettier # to format JSON, YAML and markdown files among others
22-
rev: v2.6.2 # Keep synchronize with .gitlab-ci.yml
21+
- repo: https://github.com/pre-commit/mirrors-prettier
22+
rev: v3.1.0
2323
hooks:
2424
- id: prettier
2525

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,6 @@
156156
"@types/node": "20.2.5",
157157
"@types/simple-mock": "^0.8.6",
158158
"@types/tar": "^6.1.13",
159-
"@types/unzipper": "^0.10.10",
160159
"@types/vscode": "^1.81.0",
161160
"@typescript-eslint/eslint-plugin": "^5.59.8",
162161
"@typescript-eslint/parser": "^5.59.8",
@@ -169,7 +168,7 @@
169168
},
170169
"dependencies": {
171170
"adm-zip": "^0.5.16",
172-
"sync-request": "^6.1.0",
171+
"axios": "^1.9.0",
173172
"tar": "^7.4.3"
174173
}
175174
}

src/extension.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,9 @@ function registerOpenViewsCommands(
6969
);
7070
}
7171

72-
export function activate(context: ExtensionContext) {
72+
export async function activate(context: ExtensionContext) {
7373
const outputChannel = window.createOutputChannel("GitGuardian");
74-
let configuration = getConfiguration(context, outputChannel);
74+
let configuration = await getConfiguration(context, outputChannel);
7575

7676
const ggshieldResolver = new GGShieldResolver(
7777
outputChannel,

src/lib/ggshield-configuration-utils.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,27 @@ import { getGGShield } from "./ggshield-resolver-utils";
77
* Retrieve configuration from settings
88
* @returns {GGShieldConfiguration} from the extension settings
99
*/
10-
export function getConfiguration(
10+
export async function getConfiguration(
1111
context: ExtensionContext,
12-
outputChannel: OutputChannel
13-
): GGShieldConfiguration {
12+
outputChannel: OutputChannel,
13+
): Promise<GGShieldConfiguration> {
1414
const config = workspace.getConfiguration("gitguardian");
1515

1616
const ggshieldPath: string | undefined = config.get("GGShieldPath");
1717
const apiUrl: string | undefined = config.get("apiUrl");
1818
const allowSelfSigned: boolean = config.get("allowSelfSigned", false);
1919

20-
const pathToGGShield: string = getGGShield(
20+
const pathToGGShield: string = await getGGShield(
2121
os.platform(),
2222
os.arch(),
2323
context,
24-
outputChannel
24+
outputChannel,
25+
allowSelfSigned,
2526
);
2627

2728
return new GGShieldConfiguration(
2829
pathToGGShield,
2930
apiUrl,
30-
allowSelfSigned || false
31+
allowSelfSigned || false,
3132
);
3233
}

src/lib/ggshield-resolver-utils.ts

Lines changed: 68 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,28 @@
11
import * as path from "path";
22
import * as fs from "fs";
33
import * as tar from "tar";
4+
import axios, { AxiosRequestConfig } from "axios";
5+
import { Agent } from "https";
6+
47
const AdmZip = require("adm-zip");
58
import { ExtensionContext, OutputChannel } from "vscode";
69

10+
const defaultRequestConfig = {
11+
headers: { "User-Agent": "GitGuardian-VSCode-Extension" },
12+
timeout: 30_000,
13+
} satisfies AxiosRequestConfig;
14+
15+
/**
16+
* Get the version of GGShield
17+
* @param context The extension context
18+
* @returns The version of GGShield
19+
*/
20+
export function getGGShieldVersion(context: ExtensionContext): string {
21+
return fs
22+
.readFileSync(path.join(context.extensionPath, "ggshield_version"), "utf8")
23+
.trim();
24+
}
25+
726
/**
827
* Get the absolute path to GGShield binary. If it doesn't exist, it will be installed.
928
* @param platform The platform of the user
@@ -12,31 +31,30 @@ import { ExtensionContext, OutputChannel } from "vscode";
1231
* @param outputChannel The output channel to use
1332
* @returns The absolute path to the GGShield binary
1433
*/
15-
export function getGGShield(
34+
export async function getGGShield(
1635
platform: NodeJS.Platform,
1736
arch: string,
1837
context: ExtensionContext,
19-
outputChannel: OutputChannel
20-
): string {
21-
const version = fs
22-
.readFileSync(path.join(context.extensionPath, "ggshield_version"), "utf8")
23-
.trim();
38+
outputChannel: OutputChannel,
39+
allowSelfSigned: boolean,
40+
): Promise<string> {
41+
const version = getGGShieldVersion(context);
2442
console.log(`Latest GGShield version: ${version}`);
2543
const ggshieldFolder: string = path.join(
2644
context.extensionPath,
27-
"ggshield-internal"
45+
"ggshield-internal",
2846
);
2947
const ggshieldBinaryPath: string = computeGGShieldPath(
3048
platform,
3149
arch,
3250
ggshieldFolder,
33-
version
51+
version,
3452
);
3553

3654
// if exists, return the path
3755
if (fs.existsSync(ggshieldBinaryPath)) {
3856
outputChannel.appendLine(
39-
`Using GGShield v${version}. Checkout https://github.com/GitGuardian/ggshield for more info.`
57+
`Using GGShield v${version}. Checkout https://github.com/GitGuardian/ggshield for more info.`,
4058
);
4159
console.log(`GGShield already exists at ${ggshieldBinaryPath}`);
4260
return ggshieldBinaryPath;
@@ -47,28 +65,20 @@ export function getGGShield(
4765
}
4866
fs.mkdirSync(ggshieldFolder);
4967
// install GGShield
50-
installGGShield(platform, arch, ggshieldFolder, version);
68+
await installGGShield(
69+
platform,
70+
arch,
71+
ggshieldFolder,
72+
version,
73+
allowSelfSigned,
74+
);
5175
outputChannel.appendLine(
52-
`Updated to GGShield v${version}. Checkout https://github.com/GitGuardian/ggshield for more info.`
76+
`Updated to GGShield v${version}. Checkout https://github.com/GitGuardian/ggshield for more info.`,
5377
);
5478
console.log(`GGShield binary installed at ${ggshieldBinaryPath}`);
5579
return ggshieldBinaryPath;
5680
}
5781

58-
/**
59-
* Get the latest version of GGShield
60-
* @returns The latest version of GGShield
61-
*/
62-
export function getGGShieldLatestVersion(): string {
63-
const response = require("sync-request")(
64-
"GET",
65-
"https://api.github.com/repos/GitGuardian/ggshield/releases/latest",
66-
{ headers: { "User-Agent": "GitGuardian-VSCode-Extension" } }
67-
);
68-
const data = JSON.parse(response.getBody("utf8"));
69-
return data.tag_name?.replace(/^v/, "");
70-
}
71-
7282
/**
7383
* Compute the folder name of the GGShield binary
7484
* @param platform The platform of the user
@@ -79,7 +89,7 @@ export function getGGShieldLatestVersion(): string {
7989
export function computeGGShieldFolderName(
8090
platform: NodeJS.Platform,
8191
arch: string,
82-
version: string
92+
version: string,
8393
): string {
8494
let archString: string = "";
8595
let platformString: string = "";
@@ -119,12 +129,13 @@ export function computeGGShieldFolderName(
119129
* @param ggshieldFolder The folder of the GGShield binary
120130
* @param version The version of GGShield
121131
*/
122-
export function installGGShield(
132+
export async function installGGShield(
123133
platform: NodeJS.Platform,
124134
arch: string,
125135
ggshieldFolder: string,
126-
version: string
127-
): void {
136+
version: string,
137+
allowSelfSigned: boolean,
138+
): Promise<void> {
128139
let extension: string = "";
129140
switch (platform) {
130141
case "win32":
@@ -141,10 +152,15 @@ export function installGGShield(
141152
const fileName: string = `${computeGGShieldFolderName(
142153
platform,
143154
arch,
144-
version
155+
version,
145156
)}.${extension}`;
146157
const downloadUrl: string = `https://github.com/GitGuardian/ggshield/releases/download/v${version}/${fileName}`;
147-
downloadGGShieldFromGitHub(fileName, downloadUrl, ggshieldFolder);
158+
await downloadGGShieldFromGitHub(
159+
fileName,
160+
downloadUrl,
161+
ggshieldFolder,
162+
allowSelfSigned,
163+
);
148164
extractGGShieldBinary(path.join(ggshieldFolder, fileName), ggshieldFolder);
149165
}
150166

@@ -155,7 +171,7 @@ export function installGGShield(
155171
*/
156172
export function extractGGShieldBinary(
157173
filePath: string,
158-
ggshieldFolder: string
174+
ggshieldFolder: string,
159175
): void {
160176
if (filePath.endsWith(".tar.gz")) {
161177
tar.x({
@@ -177,18 +193,29 @@ export function extractGGShieldBinary(
177193
* @param downloadUrl The URL of the GGShield binary
178194
* @param ggshieldFolder The folder of the GGShield binary
179195
*/
180-
function downloadGGShieldFromGitHub(
196+
async function downloadGGShieldFromGitHub(
181197
fileName: string,
182198
downloadUrl: string,
183-
ggshieldFolder: string
184-
): void {
199+
ggshieldFolder: string,
200+
allowSelfSigned: boolean,
201+
): Promise<void> {
185202
console.log(`Downloading GGShield from ${downloadUrl}`);
186-
const response = require("sync-request")("GET", downloadUrl, {
187-
headers: { "User-Agent": "GitGuardian-VSCode-Extension" },
203+
204+
const instance = allowSelfSigned
205+
? new Agent({
206+
rejectUnauthorized: false,
207+
})
208+
: undefined;
209+
210+
const { data } = await axios.get(downloadUrl, {
211+
...defaultRequestConfig,
212+
responseType: "arraybuffer",
213+
httpsAgent: instance,
188214
});
189-
fs.writeFileSync(path.join(ggshieldFolder, fileName), response.getBody());
215+
216+
fs.writeFileSync(path.join(ggshieldFolder, fileName), data);
190217
console.log(
191-
`GGShield archive downloaded to ${path.join(ggshieldFolder, fileName)}`
218+
`GGShield archive downloaded to ${path.join(ggshieldFolder, fileName)}`,
192219
);
193220
}
194221

@@ -203,7 +230,7 @@ export function computeGGShieldPath(
203230
platform: NodeJS.Platform,
204231
arch: string,
205232
ggshieldFolder: string,
206-
version: string
233+
version: string,
207234
): string {
208235
console.log(`Platform: ${platform}; Arch: ${arch}`);
209236
let executable: string = "";
@@ -222,6 +249,6 @@ export function computeGGShieldPath(
222249
return path.join(
223250
ggshieldFolder,
224251
computeGGShieldFolderName(platform, arch, version),
225-
executable
252+
executable,
226253
);
227254
}

src/test/suite/extension.test.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ import * as assert from "assert";
22
import { extensions, commands } from "vscode";
33

44
suite("activate", () => {
5-
test("Should activate extension successfully", async () => {
5+
test("Should activate extension successfully", async function () {
6+
this.timeout(10000);
7+
68
const ext = extensions.getExtension(
7-
"gitguardian-secret-security.gitguardian"
9+
"gitguardian-secret-security.gitguardian",
810
);
911
await ext?.activate();
1012
assert.ok(ext?.isActive, "Extension should be active");
@@ -25,13 +27,13 @@ suite("activate", () => {
2527

2628
const registered = await commands.getCommands(true);
2729
const gitguardianCommands = registered.filter((command) =>
28-
command.startsWith("gitguardian")
30+
command.startsWith("gitguardian"),
2931
);
3032

3133
for (const command of commandIds) {
3234
assert.ok(
3335
gitguardianCommands.includes(command),
34-
`Command ${command} should be registered`
36+
`Command ${command} should be registered`,
3537
);
3638
}
3739
});

src/test/suite/lib/ggshield-configuration-utils.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ suite("getConfiguration", () => {
2727
simple.restore();
2828
});
2929

30-
test("Vscode settings are correctly read", () => {
30+
test("Vscode settings are correctly read", async () => {
3131
const context = {} as ExtensionContext;
3232
const outputChannel = window.createOutputChannel("GitGuardian");
3333
simple.mock(context, "asAbsolutePath").returnWith("");
@@ -42,7 +42,7 @@ suite("getConfiguration", () => {
4242
}
4343
},
4444
});
45-
const configuration = getConfiguration(context, outputChannel);
45+
const configuration = await getConfiguration(context, outputChannel);
4646

4747
// Assert both workspace.getConfiguration and GGShieldConfiguration constructor were called
4848
assert(

0 commit comments

Comments
 (0)