From f0f00b0987838ff0f1a47ee71184a99e39a4c259 Mon Sep 17 00:00:00 2001 From: yini-chen Date: Mon, 2 Sep 2024 15:10:36 +0800 Subject: [PATCH 1/6] =?UTF-8?q?feat:=20=E6=95=8F=E6=84=9F=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E5=91=8A=E8=AD=A6Linter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 12 +++++- src/commands.ts | 63 ++++++------------------------- src/extension.ts | 27 +++++++++++--- src/provider/autofix.ts | 33 ++++++++++++----- src/provider/linter.ts | 82 +++++++++++++++++++++++++++++++++++++++++ src/utils.ts | 19 ++++++++++ 6 files changed, 169 insertions(+), 67 deletions(-) create mode 100644 src/provider/linter.ts diff --git a/package.json b/package.json index 17d9abb..e52d6f7 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,13 @@ ], "activationEvents": [ "onStartFinished", - "onWebviewPanel:alicloud-api-webview" + "onWebviewPanel:alicloud-api-webview", + "onLanguage:javascript", + "onLanguage:typescript", + "onLanguage:go", + "onLanguage:php", + "onLanguage:python", + "onLanguage:java" ], "main": "./dist/extension", "contributes": { @@ -24,6 +30,10 @@ "command": "alicloud.api.autoImport", "title": "导入依赖" }, + { + "command": "alicloud.api.akSecurityHelper", + "title": "凭据的安全使用方案" + }, { "command": "alicloud.api.feedback", "title": "反馈", diff --git a/src/commands.ts b/src/commands.ts index b9bc2c3..5894b5e 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -2,6 +2,7 @@ import { PontManager } from "pontx-manager"; import * as _ from "lodash"; import * as vscode from "vscode"; import { + AKHelperWithLanguage, findAlicloudAPIConfig, findInterface, getSpecInfoFromName, @@ -200,39 +201,6 @@ export class AlicloudApiCommands { }); }); - // vscode.commands.registerCommand("alicloud.api.regenerateAPIMocks", async (event) => { - // const filePaths: string[] = (event.path || "")?.split("/"); - // const lastMocksIndex = filePaths.lastIndexOf("mocks"); - // const names = filePaths.slice(lastMocksIndex + 1); - // names.push(names.pop().replace(".ts", "")); - - // if (service.pontManager.localPontSpecs?.[0]?.name) { - // showProgress("重新生成 API Mocks", service.pontManager, async (log) => { - // log("代码生成中..."); - // await wait(100); - - // let specName, modName, apiName; - // if (names.length === 3) { - // [specName, modName, apiName] = names; - // } else { - // [specName, apiName] = names; - // } - // const mocksPlugin = await service.pontManager.innerManagerConfig.plugins.mocks?.instance; - // const mocksOptions = await service.pontManager.innerManagerConfig.plugins.mocks?.options; - // const mocksCode = await mocksPlugin.getAPIMockCode( - // service.pontManager, - // mocksOptions, - // apiName, - // modName, - // specName, - // ); - // fs.writeFileSync(event.path, mocksCode, "utf-8"); - - // log("API Mocks 生成成功!"); - // vscode.window.showInformationMessage("API Mocks生成成功!"); - // }); - // } - // }); vscode.commands.registerCommand("alicloud.api.autoImport", (...argus) => { const diagnostic = argus[0]; const missingDep = argus[1]; @@ -243,6 +211,17 @@ export class AlicloudApiCommands { } }); + vscode.commands.registerCommand("alicloud.api.akSecurityHelper", (...argus) => { + const document = argus[0]; + if (AKHelperWithLanguage[document.languageId]) { + vscode.env.openExternal(vscode.Uri.parse(AKHelperWithLanguage[document.languageId])); + } else { + vscode.env.openExternal( + vscode.Uri.parse("https://help.aliyun.com/zh/sdk/developer-reference/ak-security-scheme"), + ); + } + }); + vscode.commands.registerCommand("alicloud.api.fetchRemote", (config) => { const pontManager = service.pontManager; @@ -329,23 +308,5 @@ export class AlicloudApiCommands { spec: spec?.apis?.[`${result.apiKey}`], }); }); - // vscode.commands.registerTextEditorCommand("alicloud.api.viewMocks", async (editor, edit) => { - // const isSingleSpec = PontManager.checkIsSingleSpec(service.pontManager); - // const result = (await findInterface(editor, !isSingleSpec, service.pontManager)) || ({} as any); - // const spec = PontManager.getSpec(service.pontManager, result.specName); - - // if (!result.apiName) { - // vscode.window.showErrorMessage("未找到该 OpenAPI"); - // return; - // } - - // const namespace = [result.specName, result.modName, result.apiName].filter((id) => id).join("/"); - // const mocksFilePath = path.join(service.pontManager.innerManagerConfig.outDir, "mocks", namespace + ".ts"); - // vscode.commands.executeCommand("vscode.open", vscode.Uri.file(mocksFilePath)); - // }); - - // vscode.commands.registerCommand('alicloud.api.refreshPontExplorer', () => { - // service.treeDataProvider.refresh(); - // }); } } diff --git a/src/extension.ts b/src/extension.ts index d995aea..701b6ca 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,6 +1,4 @@ "use strict"; -// The module 'vscode' contains the VS Code extensibility API -// Import the module and reference it with the alias vscode in your code below import { PontManager } from "pontx-manager"; import PontMetaFetchPlugin from "pontx-meta-fetch-plugin"; import * as vscode from "vscode"; @@ -16,12 +14,29 @@ import autoCompletion from "./provider/autoCompletion"; import autofix from "./provider/autofix"; import hoverInfo from "./provider/hoverProvider"; import { getProfileInfoInstance } from "./profileManager"; +import { updateDiagnostics } from "./provider/linter"; export async function activate(context: vscode.ExtensionContext) { - // if (!vscode.workspace.rootPath) { - // return; - // } - // registerConfigSchema(context); + // 插件诊断器 + const collection = vscode.languages.createDiagnosticCollection("test"); + if (vscode.window.activeTextEditor) { + updateDiagnostics(vscode.window.activeTextEditor.document, collection); + } + context.subscriptions.push( + vscode.window.onDidChangeActiveTextEditor((editor) => { + if (editor) { + updateDiagnostics(editor.document, collection); + } + }), + ); + context.subscriptions.push( + vscode.workspace.onDidChangeTextDocument((editor) => { + if (editor) { + updateDiagnostics(editor.document, collection); + } + }), + ); + const pontxConfig = await findAlicloudAPIConfig(context); if (!pontxConfig) { diff --git a/src/provider/autofix.ts b/src/provider/autofix.ts index 0030ab0..b283902 100644 --- a/src/provider/autofix.ts +++ b/src/provider/autofix.ts @@ -2,9 +2,10 @@ * @description: Quick fix need to be used with a Linter */ import * as vscode from "vscode"; -import { containsAnySubstring, fileSel, getSpecInfoFromName } from "../utils"; +import { containsAnySubstring, fileSel, getSpecInfoFromName, SDKLanguageLabel } from "../utils"; import { getDepsByLanguage } from "../common/generateImport"; import { alicloudAPIMessageService } from "../Service"; +import { LintRules } from "./linter"; class CodeActionProvider { provideCodeActions( @@ -21,16 +22,13 @@ class CodeActionProvider { const document = editor.document; const errorText = document.getText(item?.range); const service = alicloudAPIMessageService; - const products = service.pontManager.localPontSpecs - .map((pontSpec) => { - return getSpecInfoFromName(pontSpec?.name)[0]; - }) + const products = service.pontManager.localPontSpecs.map((pontSpec) => { + return getSpecInfoFromName(pontSpec?.name)[0]; + }); + // 未导入依赖的诊断建议 if (getDepsByLanguage(errorText, item.range)?.includes(errorText) || containsAnySubstring(errorText, products)) { - const autoImportAction = new vscode.CodeAction( - item.message + "导入依赖", - vscode.CodeActionKind.QuickFix, - ); + const autoImportAction = new vscode.CodeAction(item.message + "导入依赖", vscode.CodeActionKind.QuickFix); const newDiagnostic = new vscode.Diagnostic(item.range, "importLists", vscode.DiagnosticSeverity.Error); // 自动修复命令注册 autoImportAction.command = { @@ -40,6 +38,23 @@ class CodeActionProvider { }; return autoImportAction; } + + // AccessKey 可能泄露的诊断建议 + const lintResult = LintRules?.find((rule) => rule.source === item.source); + if (lintResult) { + // 自动修复命令注册 + const codeAction = new vscode.CodeAction( + `${lintResult.methods[0]?.title}(${SDKLanguageLabel[document.languageId] || "阿里云 SDK"})`, + vscode.CodeActionKind.QuickFix, + ); + codeAction.command = { + title: `${lintResult.methods[0]?.title}(${SDKLanguageLabel[document.languageId] || "阿里云 SDK"})`, + command: lintResult.methods[0]?.command, + arguments: [document], + }; + + return codeAction; + } }); return result; diff --git a/src/provider/linter.ts b/src/provider/linter.ts new file mode 100644 index 0000000..ac2f532 --- /dev/null +++ b/src/provider/linter.ts @@ -0,0 +1,82 @@ +/** + * @description: Linter of the Code + */ +import * as vscode from "vscode"; +import { fileSel } from "../utils"; + +class Rule { + LintName: string; + pattern: string; + message: string; + source: string; + information: string; + methods: Array<{ + title: string; + command: string; + }>; +} +export const LintRules: Array = [ + { + LintName: "AccessKey-KeyValue", + source: "Alicloud AccessKey Lint", + pattern: + '(?access|key|secret|scret|ak|sk)[^\\w\\n]*(?:\\n)?(?["\'\\s]*[:=@,]\\s*(?:"|\')?|\\w*"\\s*?,\\s*?")[\\s"\']*(?[0-9A-Za-z]{14,40})(?["\'\\s]*)', + message: "工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。", + information: "在此处透露了 AccessKey。", + methods: [{ title: "凭据的安全使用方案", command: "alicloud.api.akSecurityHelper" }], + }, + { + LintName: "AccessKey-NewAK", + source: "Alicloud AccessKey Lint", + information: "在此处透露了 AccessKey。", + pattern: + "^LTAI(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)[A-Za-z\\d]{12}$|^LTAI(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)[A-Za-z\\d]{16}$|^LTAI(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)[A-Za-z\\d]{18}$|^LTAI(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)[A-Za-z\\d]{20}$|^LTAI(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)[A-Za-z\\d]{22}$", + message: "工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。", + methods: [{ title: "凭据的安全使用方案", command: "alicloud.api.akSecurityHelper" }], + }, +]; + +function searchCode( + diagnosticCollection: vscode.Diagnostic[], + rule: Rule, + text: string, + document: vscode.TextDocument, +) { + const regex = new RegExp(rule.pattern, "gi"); + let match; + while ((match = regex.exec(text)) !== null) { + const range = new vscode.Range(document.positionAt(match.index), document.positionAt(regex.lastIndex)); + const matchText = document.getText(range); + if (!diagnosticCollection?.find((item) => item.code === matchText)) { + diagnosticCollection.push({ + code: "", + message: rule.message, + range: range, + severity: vscode.DiagnosticSeverity.Error, + source: rule.source, + relatedInformation: [ + new vscode.DiagnosticRelatedInformation(new vscode.Location(document.uri, range), rule.information), + ], + }); + } + } +} + +export async function updateDiagnostics( + document: vscode.TextDocument, + collection: vscode.DiagnosticCollection, +): Promise { + if ((fileSel as any)?.find((sel) => sel.language === document.languageId)) { + const text = document.getText(); + + let diagnosticCollection: vscode.Diagnostic[] = []; + + LintRules.forEach((rule) => { + searchCode(diagnosticCollection, rule, text, document); + }); + + collection.set(document.uri, diagnosticCollection); + } else { + collection.clear(); + } +} diff --git a/src/utils.ts b/src/utils.ts index faae7c1..a9b0b59 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -487,6 +487,7 @@ export const getRequiredParamsValue = (product: string, version: string, api: st export const fileSel: vscode.DocumentSelector = [ { scheme: "file", language: "typescript" }, + { scheme: "file", language: "javascript" }, { scheme: "file", language: "go" }, { scheme: "file", language: "java" }, { scheme: "file", language: "csharp" }, @@ -494,6 +495,24 @@ export const fileSel: vscode.DocumentSelector = [ { scheme: "file", language: "php" }, ]; +export const SDKLanguageLabel = { + typescript: "V2.0 Node.js SDK", + javascript: "V2.0 Node.js SDK", + go: "V2.0 Go SDK", + java: "V2.0 Java SDK", + python: "V2.0 Python SDK", + php: "V2.0 PHP SDK", +}; + +export const AKHelperWithLanguage = { + typescript: "https://help.aliyun.com/zh/sdk/developer-reference/v2-manage-node-js-access-credentials", + javascript: "https://help.aliyun.com/zh/sdk/developer-reference/v2-manage-node-js-access-credentials", + java: "https://help.aliyun.com/zh/sdk/developer-reference/v2-manage-access-credentials", + go: "https://help.aliyun.com/zh/sdk/developer-reference/v2-manage-go-access-credentials", + python: "https://help.aliyun.com/zh/sdk/developer-reference/v2-manage-python-access-credentials", + php: "https://help.aliyun.com/zh/sdk/developer-reference/v2-manage-php-access-credentials", +}; + export const containsAnySubstring = (targetStr, substrings) => { const language = vscode.window.activeTextEditor?.document.languageId; if (language !== "typescript") { From 939b8daa985b745aa3addf9be4ff50d60b55f2e3 Mon Sep 17 00:00:00 2001 From: yini-chen Date: Mon, 2 Sep 2024 19:52:10 +0800 Subject: [PATCH 2/6] =?UTF-8?q?test:=20=E6=95=8F=E6=84=9F=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E5=91=8A=E8=AD=A6Linter=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/extension.ts | 2 +- src/provider/linter.ts | 28 ++++++------- src/test/suite/extension.test.ts | 5 --- src/test/suite/linter.test.ts | 70 ++++++++++++++++++++++++++++++++ 4 files changed, 83 insertions(+), 22 deletions(-) create mode 100644 src/test/suite/linter.test.ts diff --git a/src/extension.ts b/src/extension.ts index 701b6ca..883846a 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -18,7 +18,7 @@ import { updateDiagnostics } from "./provider/linter"; export async function activate(context: vscode.ExtensionContext) { // 插件诊断器 - const collection = vscode.languages.createDiagnosticCollection("test"); + const collection = vscode.languages.createDiagnosticCollection("alicloud-linter"); if (vscode.window.activeTextEditor) { updateDiagnostics(vscode.window.activeTextEditor.document, collection); } diff --git a/src/provider/linter.ts b/src/provider/linter.ts index ac2f532..32e6d67 100644 --- a/src/provider/linter.ts +++ b/src/provider/linter.ts @@ -16,38 +16,33 @@ class Rule { }>; } export const LintRules: Array = [ - { - LintName: "AccessKey-KeyValue", - source: "Alicloud AccessKey Lint", - pattern: - '(?access|key|secret|scret|ak|sk)[^\\w\\n]*(?:\\n)?(?["\'\\s]*[:=@,]\\s*(?:"|\')?|\\w*"\\s*?,\\s*?")[\\s"\']*(?[0-9A-Za-z]{14,40})(?["\'\\s]*)', - message: "工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。", - information: "在此处透露了 AccessKey。", - methods: [{ title: "凭据的安全使用方案", command: "alicloud.api.akSecurityHelper" }], - }, { LintName: "AccessKey-NewAK", source: "Alicloud AccessKey Lint", information: "在此处透露了 AccessKey。", - pattern: - "^LTAI(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)[A-Za-z\\d]{12}$|^LTAI(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)[A-Za-z\\d]{16}$|^LTAI(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)[A-Za-z\\d]{18}$|^LTAI(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)[A-Za-z\\d]{20}$|^LTAI(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)[A-Za-z\\d]{22}$", + pattern: `^LTAI(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)[A-Za-z\\d]{12}$|^LTAI(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)[A-Za-z\\d]{16}$|^LTAI(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)[A-Za-z\\d]{18}$|^LTAI(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)[A-Za-z\\d]{20}$|^LTAI(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)[A-Za-z\\d]{22}$`, message: "工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。", methods: [{ title: "凭据的安全使用方案", command: "alicloud.api.akSecurityHelper" }], }, ]; -function searchCode( +export function searchCode( diagnosticCollection: vscode.Diagnostic[], rule: Rule, text: string, document: vscode.TextDocument, ) { const regex = new RegExp(rule.pattern, "gi"); - let match; - while ((match = regex.exec(text)) !== null) { - const range = new vscode.Range(document.positionAt(match.index), document.positionAt(regex.lastIndex)); + const strRegex = new RegExp(`[\'\"\`](.*?)[\'\"\`]`, "gi"); + let strMatch; + let matchTexts = []; + while ((strMatch = strRegex.exec(text)) !== null) { + const range = new vscode.Range(document.positionAt(strMatch.index), document.positionAt(strRegex.lastIndex)); const matchText = document.getText(range); - if (!diagnosticCollection?.find((item) => item.code === matchText)) { + const pureString = matchText.substring(1, matchText.length - 1); + const isMatch = regex.test(pureString); + if (isMatch) { + matchTexts.push(pureString); diagnosticCollection.push({ code: "", message: rule.message, @@ -60,6 +55,7 @@ function searchCode( }); } } + return matchTexts; } export async function updateDiagnostics( diff --git a/src/test/suite/extension.test.ts b/src/test/suite/extension.test.ts index fe844ca..f368f9b 100644 --- a/src/test/suite/extension.test.ts +++ b/src/test/suite/extension.test.ts @@ -25,9 +25,4 @@ suite("Extension Test Suite", () => { console.log("alicloud.api.restart successfully executed"); assert.strictEqual("ok", result); }); - - test("Sample test", () => { - assert.strictEqual(-1, [1, 2, 3].indexOf(5)); - assert.strictEqual(-1, [1, 2, 3].indexOf(0)); - }); }); diff --git a/src/test/suite/linter.test.ts b/src/test/suite/linter.test.ts new file mode 100644 index 0000000..a8dcbcc --- /dev/null +++ b/src/test/suite/linter.test.ts @@ -0,0 +1,70 @@ +import * as assert from "assert"; +import { after, before } from "mocha"; +import path from "path"; +import * as vscode from "vscode"; +import { LintRules, searchCode } from "../../provider/linter"; + +suite("Alicloud linter Test Suite", function () { + let document; + + // 运行前的初始化 + setup(async function () { + const text = `String[] tests = { + "LTAIAbcd1234abcd", // Length 16, should match + "LTAIAbcd1234abcdefgh", // Length 20, should match + "LTAIAbcd1234abcdefghij", // Length 22, should match + "LTAIAbcd1234abcdefghijkl", // Length 24, should match + "LTAIAbcd1234abcdefghijklmn", // Length 26, should match + "LTAIabc", // Too short, should not match + "LTAIabcdefghijklm", // Too short, should not match + "LTAIAbcd1234abcdefghijklmnop", // Too long, should not match + "LTAIabcd1234abcdefghij", // Length 22, missing uppercase letter, should not match + "LTAIABCD1234ABCDEFGHIJ", // Length 22, missing lowercase letter, should not match + "LTAIAbcdabcdabcdefghij", // Length 22, missing digit, should not match + "LTAIAbcd1234abcdefghiJ", // Length 22, should match + "ltaiAbcd1234abcdefghij", // Length 22, does not start with "LTAI", should not match + "LTAIAbcd1234abcdefghi", // Length 21, should not match + };`; + + const uri = vscode.Uri.file(path.join(__dirname, "testDocument.txt")); + + // 写入自定义文本到文件 + await vscode.workspace.fs.writeFile(uri, Buffer.from(text, "utf8")); + + // 打开文件作为 TextDocument + document = await vscode.workspace.openTextDocument(uri); + }); + + // 测试指定单词是否存在于文档中 + test("Check if document contains the AK", async function () { + // 指定要查找的单词 + const wordToFind = "sample"; + const text = document.getText(); + + let diagnosticCollection: vscode.Diagnostic[] = []; + + let matches = []; + + LintRules.forEach((rule) => { + matches = matches.concat(matches, searchCode(diagnosticCollection, rule, text, document)); + }); + + console.log(diagnosticCollection); + + const mock = [ + "LTAIAbcd1234abcd", + "LTAIAbcd1234abcdefghij", + "LTAIAbcd1234abcdefghijklmn", + "LTAIabcd1234abcdefghij", + "LTAIAbcd1234abcdefghiJ", + ]; + assert.equal(matches.toString(), mock.toString()); + // assert.ok(matches, `test failed`); + }); + + // 清理工作 + teardown(async function () { + const uri = vscode.Uri.file(path.join(__dirname, "testDocument.txt")); + await vscode.workspace.fs.delete(uri, { useTrash: true }); + }); +}); From 1b3ff1e4bf8bca88bc834cbd824feafbaf8ee2aa Mon Sep 17 00:00:00 2001 From: yini-chen Date: Tue, 3 Sep 2024 10:56:20 +0800 Subject: [PATCH 3/6] fix: linter message --- media/yarn.lock | 67 ++++++++++++++++++++++++++++++------------ src/provider/linter.ts | 14 +++++++-- 2 files changed, 59 insertions(+), 22 deletions(-) diff --git a/media/yarn.lock b/media/yarn.lock index 3c86ed4..537d841 100644 --- a/media/yarn.lock +++ b/media/yarn.lock @@ -1061,6 +1061,21 @@ acorn@^8.9.0: resolved "https://registry.npmmirror.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== +ahooks@^3.8.1: + version "3.8.1" + resolved "https://registry.npmmirror.com/ahooks/-/ahooks-3.8.1.tgz#3a19d0e4085618a7a38a22a34b568c8d3fd974c0" + integrity sha512-JoP9+/RWO7MnI/uSKdvQ8WB10Y3oo1PjLv+4Sv4Vpm19Z86VUMdXh+RhWvMGxZZs06sq2p0xVtFk8Oh5ZObsoA== + dependencies: + "@babel/runtime" "^7.21.0" + dayjs "^1.9.1" + intersection-observer "^0.12.0" + js-cookie "^3.0.5" + lodash "^4.17.21" + react-fast-compare "^3.2.2" + resize-observer-polyfill "^1.5.1" + screenfull "^5.0.0" + tslib "^2.4.1" + ajv@^6.12.4: version "6.12.6" resolved "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -1828,6 +1843,11 @@ dayjs@^1.11.1, dayjs@^1.9.6: resolved "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.10.tgz#68acea85317a6e164457d6d6947564029a6a16a0" integrity sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ== +dayjs@^1.9.1: + version "1.11.13" + resolved "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c" + integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== + debug@^3.2.7: version "3.2.7" resolved "https://registry.npmmirror.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -3107,6 +3127,11 @@ internal-slot@^1.0.7: hasown "^2.0.0" side-channel "^1.0.4" +intersection-observer@^0.12.0: + version "0.12.2" + resolved "https://registry.npmmirror.com/intersection-observer/-/intersection-observer-0.12.2.tgz#4a45349cc0cd91916682b1f44c28d7ec737dc375" + integrity sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg== + intl-format@^1.2.0: version "1.2.0" resolved "https://registry.npmmirror.com/intl-format/-/intl-format-1.2.0.tgz#3d4a3e9b9517d1fbf0cc914e90cad81b0bf820dc" @@ -3387,6 +3412,11 @@ jiti@^1.21.0: resolved "https://registry.npmmirror.com/jiti/-/jiti-1.21.0.tgz#7c97f8fe045724e136a397f7340475244156105d" integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q== +js-cookie@^3.0.5: + version "3.0.5" + resolved "https://registry.npmmirror.com/js-cookie/-/js-cookie-3.0.5.tgz#0b7e2fd0c01552c58ba86e0841f94dc2557dcdbc" + integrity sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw== + "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -3589,7 +3619,7 @@ lodash.merge@^4.6.2: resolved "https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash@^4.17.20: +lodash@^4.17.20, lodash@^4.17.21: version "4.17.21" resolved "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -5069,6 +5099,11 @@ react-dom@^18.3.1: loose-envify "^1.1.0" scheduler "^0.23.2" +react-fast-compare@^3.2.2: + version "3.2.2" + resolved "https://registry.npmmirror.com/react-fast-compare/-/react-fast-compare-3.2.2.tgz#929a97a532304ce9fee4bcae44234f1ce2c21d49" + integrity sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ== + react-is@^16.13.1, react-is@^16.7.0: version "16.13.1" resolved "https://registry.npmmirror.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" @@ -5451,6 +5486,11 @@ scheduler@^0.23.2: dependencies: loose-envify "^1.1.0" +screenfull@^5.0.0: + version "5.2.0" + resolved "https://registry.npmmirror.com/screenfull/-/screenfull-5.2.0.tgz#6533d524d30621fc1283b9692146f3f13a93d1ba" + integrity sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA== + scroll-into-view-if-needed@^3.1.0: version "3.1.0" resolved "https://registry.npmmirror.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz#fa9524518c799b45a2ef6bbffb92bcad0296d01f" @@ -5639,16 +5679,7 @@ string-convert@^0.2.0: resolved "https://registry.npmmirror.com/string-convert/-/string-convert-0.2.1.tgz#6982cc3049fbb4cd85f8b24568b9d9bf39eeff97" integrity sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A== -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^4.1.0: +"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0: version "4.2.3" resolved "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -5719,14 +5750,7 @@ string_decoder@^1.1.1: dependencies: safe-buffer "~5.2.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": - version "6.0.1" - resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -5968,6 +5992,11 @@ tslib@^2.3.0, tslib@^2.4.0, tslib@^2.5.0: resolved "https://registry.npmmirror.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== +tslib@^2.4.1: + version "2.7.0" + resolved "https://registry.npmmirror.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" + integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== + tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.npmmirror.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" diff --git a/src/provider/linter.ts b/src/provider/linter.ts index 32e6d67..4e8aba2 100644 --- a/src/provider/linter.ts +++ b/src/provider/linter.ts @@ -18,10 +18,18 @@ class Rule { export const LintRules: Array = [ { LintName: "AccessKey-NewAK", - source: "Alicloud AccessKey Lint", - information: "在此处透露了 AccessKey。", + source: "Alicloud Access Key Lint", + information: "在此处透露了 Access Key。", pattern: `^LTAI(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)[A-Za-z\\d]{12}$|^LTAI(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)[A-Za-z\\d]{16}$|^LTAI(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)[A-Za-z\\d]{18}$|^LTAI(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)[A-Za-z\\d]{20}$|^LTAI(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)[A-Za-z\\d]{22}$`, - message: "工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。", + message: "在工程中硬编码 Access Key ID/Secret 容易发生凭证数据泄漏,并进而威胁到您账号下所有资源的安全性。", + methods: [{ title: "凭据的安全使用方案", command: "alicloud.api.akSecurityHelper" }], + }, + { + LintName: "AccessSecret", + source: "Alicloud AccessKey Lint", + information: "在此处透露了 Access Secret。", + pattern: `[a-zA-Z0-9]{30}`, + message: "在工程中硬编码 Access Key ID/Secret 容易发生凭证数据泄漏,并进而威胁到您账号下所有资源的安全性。", methods: [{ title: "凭据的安全使用方案", command: "alicloud.api.akSecurityHelper" }], }, ]; From 6d662692ba411704af70c89c56cac93366e6a2ed Mon Sep 17 00:00:00 2001 From: yini-chen Date: Tue, 3 Sep 2024 11:16:12 +0800 Subject: [PATCH 4/6] fix: linter code --- src/extension.ts | 24 +++--------------------- src/provider/linter.ts | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index 883846a..c235ce1 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -14,29 +14,9 @@ import autoCompletion from "./provider/autoCompletion"; import autofix from "./provider/autofix"; import hoverInfo from "./provider/hoverProvider"; import { getProfileInfoInstance } from "./profileManager"; -import { updateDiagnostics } from "./provider/linter"; +import { registerLinter, updateDiagnostics } from "./provider/linter"; export async function activate(context: vscode.ExtensionContext) { - // 插件诊断器 - const collection = vscode.languages.createDiagnosticCollection("alicloud-linter"); - if (vscode.window.activeTextEditor) { - updateDiagnostics(vscode.window.activeTextEditor.document, collection); - } - context.subscriptions.push( - vscode.window.onDidChangeActiveTextEditor((editor) => { - if (editor) { - updateDiagnostics(editor.document, collection); - } - }), - ); - context.subscriptions.push( - vscode.workspace.onDidChangeTextDocument((editor) => { - if (editor) { - updateDiagnostics(editor.document, collection); - } - }), - ); - const pontxConfig = await findAlicloudAPIConfig(context); if (!pontxConfig) { @@ -102,6 +82,8 @@ export async function activate(context: vscode.ExtensionContext) { autofix(context); // hover提示 hoverInfo(context); + // 代码诊断 + registerLinter(context); } } catch (e) { vscode.window.showErrorMessage(e.message); diff --git a/src/provider/linter.ts b/src/provider/linter.ts index 4e8aba2..9efdaba 100644 --- a/src/provider/linter.ts +++ b/src/provider/linter.ts @@ -84,3 +84,25 @@ export async function updateDiagnostics( collection.clear(); } } + +export async function registerLinter(context: vscode.ExtensionContext) { + // 插件诊断器 + const collection = vscode.languages.createDiagnosticCollection("alicloud-linter"); + if (vscode.window.activeTextEditor) { + updateDiagnostics(vscode.window.activeTextEditor.document, collection); + } + context.subscriptions.push( + vscode.window.onDidChangeActiveTextEditor((editor) => { + if (editor) { + updateDiagnostics(editor.document, collection); + } + }), + ); + context.subscriptions.push( + vscode.workspace.onDidChangeTextDocument((editor) => { + if (editor) { + updateDiagnostics(editor.document, collection); + } + }), + ); +} From 3de801a06b1db9d79aeef5bed899c2e2bf95d720 Mon Sep 17 00:00:00 2001 From: yini-chen Date: Tue, 3 Sep 2024 11:22:17 +0800 Subject: [PATCH 5/6] fix: linter test code --- src/extension.ts | 2 +- src/test/suite/linter.test.ts | 10 +++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index c235ce1..e4b2282 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -14,7 +14,7 @@ import autoCompletion from "./provider/autoCompletion"; import autofix from "./provider/autofix"; import hoverInfo from "./provider/hoverProvider"; import { getProfileInfoInstance } from "./profileManager"; -import { registerLinter, updateDiagnostics } from "./provider/linter"; +import { registerLinter } from "./provider/linter"; export async function activate(context: vscode.ExtensionContext) { const pontxConfig = await findAlicloudAPIConfig(context); diff --git a/src/test/suite/linter.test.ts b/src/test/suite/linter.test.ts index a8dcbcc..418774d 100644 --- a/src/test/suite/linter.test.ts +++ b/src/test/suite/linter.test.ts @@ -1,5 +1,4 @@ import * as assert from "assert"; -import { after, before } from "mocha"; import path from "path"; import * as vscode from "vscode"; import { LintRules, searchCode } from "../../provider/linter"; @@ -37,8 +36,6 @@ suite("Alicloud linter Test Suite", function () { // 测试指定单词是否存在于文档中 test("Check if document contains the AK", async function () { - // 指定要查找的单词 - const wordToFind = "sample"; const text = document.getText(); let diagnosticCollection: vscode.Diagnostic[] = []; @@ -49,16 +46,15 @@ suite("Alicloud linter Test Suite", function () { matches = matches.concat(matches, searchCode(diagnosticCollection, rule, text, document)); }); - console.log(diagnosticCollection); - - const mock = [ + const result = [ "LTAIAbcd1234abcd", "LTAIAbcd1234abcdefghij", "LTAIAbcd1234abcdefghijklmn", "LTAIabcd1234abcdefghij", "LTAIAbcd1234abcdefghiJ", ]; - assert.equal(matches.toString(), mock.toString()); + + assert.equal(matches.toString(), result.toString()); // assert.ok(matches, `test failed`); }); From 89d406464664c48fef8d29453a039f3dff44c633 Mon Sep 17 00:00:00 2001 From: yini-chen Date: Tue, 3 Sep 2024 11:46:30 +0800 Subject: [PATCH 6/6] fix: linter test code --- src/extension.ts | 2 +- src/test/suite/linter.test.ts | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index c235ce1..e4b2282 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -14,7 +14,7 @@ import autoCompletion from "./provider/autoCompletion"; import autofix from "./provider/autofix"; import hoverInfo from "./provider/hoverProvider"; import { getProfileInfoInstance } from "./profileManager"; -import { registerLinter, updateDiagnostics } from "./provider/linter"; +import { registerLinter } from "./provider/linter"; export async function activate(context: vscode.ExtensionContext) { const pontxConfig = await findAlicloudAPIConfig(context); diff --git a/src/test/suite/linter.test.ts b/src/test/suite/linter.test.ts index a8dcbcc..e74ce34 100644 --- a/src/test/suite/linter.test.ts +++ b/src/test/suite/linter.test.ts @@ -1,5 +1,4 @@ import * as assert from "assert"; -import { after, before } from "mocha"; import path from "path"; import * as vscode from "vscode"; import { LintRules, searchCode } from "../../provider/linter"; @@ -37,8 +36,6 @@ suite("Alicloud linter Test Suite", function () { // 测试指定单词是否存在于文档中 test("Check if document contains the AK", async function () { - // 指定要查找的单词 - const wordToFind = "sample"; const text = document.getText(); let diagnosticCollection: vscode.Diagnostic[] = []; @@ -49,16 +46,17 @@ suite("Alicloud linter Test Suite", function () { matches = matches.concat(matches, searchCode(diagnosticCollection, rule, text, document)); }); - console.log(diagnosticCollection); + const result = Array.from(new Set(matches)); - const mock = [ + const expected = [ "LTAIAbcd1234abcd", "LTAIAbcd1234abcdefghij", "LTAIAbcd1234abcdefghijklmn", "LTAIabcd1234abcdefghij", "LTAIAbcd1234abcdefghiJ", ]; - assert.equal(matches.toString(), mock.toString()); + + assert.equal(result.toString(), expected.toString()); // assert.ok(matches, `test failed`); });