diff --git a/.vscode/launch.json b/.vscode/launch.json index 196840c108c..b8293df3b70 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -85,6 +85,19 @@ "${workspaceFolder}/vscode-extensions/rush-vscode-extension/dist/**/*.js" ] // "preLaunchTask": "npm: build:watch - vscode-extensions/rush-vscode-extension" + }, + { + "name": "Launch Debug Certificate Manager VS Code Extension", + "type": "extensionHost", + "request": "launch", + "cwd": "${workspaceFolder}/vscode-extensions/debug-certificate-manager-vscode-extension/dist/vsix/unpacked", + "args": [ + "--extensionDevelopmentPath=${workspaceFolder}/vscode-extensions/debug-certificate-manager-vscode-extension/dist/vsix/unpacked" + ], + "sourceMaps": true, + "outFiles": [ + "${workspaceFolder}/vscode-extensions/debug-certificate-manager-vscode-extension/**" + ] } ] } diff --git a/README.md b/README.md index 2eb877f8fc5..009488b2501 100644 --- a/README.md +++ b/README.md @@ -218,12 +218,9 @@ These GitHub repositories provide supplementary resources for Rush Stack: | [/rigs/local-node-rig](./rigs/local-node-rig/) | A rig package for Node.js projects that build using Heft inside the RushStack repository. | | [/rigs/local-web-rig](./rigs/local-web-rig/) | A rig package for Web projects that build using Heft inside the RushStack repository. | | [/rush-plugins/rush-litewatch-plugin](./rush-plugins/rush-litewatch-plugin/) | An experimental alternative approach for multi-project watch mode | +| [/vscode-extensions/debug-certificate-manager-vscode-extension](./vscode-extensions/debug-certificate-manager-vscode-extension/) | VS Code extension to manage debug TLS certificates and sync them to the VS Code workspace. Works with VS Code remote development (Codespaces, SSH, Dev Containers, WSL, VS Code Tunnels). | | [/vscode-extensions/rush-vscode-command-webview](./vscode-extensions/rush-vscode-command-webview/) | Part of the Rush Stack VSCode extension, provides a UI for invoking Rush commands | | [/vscode-extensions/rush-vscode-extension](./vscode-extensions/rush-vscode-extension/) | Enhanced experience for monorepos that use the Rush Stack toolchain | -| [/vscode-extensions/tls-sync-vscode-extension-pack](./vscode-extensions/tls-sync-vscode-extension-pack/) | | -| [/vscode-extensions/tls-sync-vscode-shared](./vscode-extensions/tls-sync-vscode-shared/) | | -| [/vscode-extensions/tls-sync-vscode-ui-extension](./vscode-extensions/tls-sync-vscode-ui-extension/) | | -| [/vscode-extensions/tls-sync-vscode-workspace-extension](./vscode-extensions/tls-sync-vscode-workspace-extension/) | | | [/vscode-extensions/vscode-shared](./vscode-extensions/vscode-shared/) | | | [/webpack/webpack-deep-imports-plugin](./webpack/webpack-deep-imports-plugin/) | This plugin creates a bundle and commonJS files in a 'lib' folder mirroring modules in another 'lib' folder. | diff --git a/common/changes/@rushstack/debug-certificate-manager/bmiddha-tls-sync-v2_2025-07-24-22-08.json b/common/changes/@rushstack/debug-certificate-manager/bmiddha-tls-sync-v2_2025-07-24-22-08.json new file mode 100644 index 00000000000..b6da4f16a64 --- /dev/null +++ b/common/changes/@rushstack/debug-certificate-manager/bmiddha-tls-sync-v2_2025-07-24-22-08.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@rushstack/debug-certificate-manager", + "comment": "Read CertificateStore configuration from .vscode/debug-certificate-manager.json", + "type": "patch" + } + ], + "packageName": "@rushstack/debug-certificate-manager" +} \ No newline at end of file diff --git a/common/changes/@rushstack/heft-vscode-extension-plugin/bmiddha-tls-sync-v2_2025-07-24-22-08.json b/common/changes/@rushstack/heft-vscode-extension-plugin/bmiddha-tls-sync-v2_2025-07-24-22-08.json new file mode 100644 index 00000000000..a1f9f43b0ee --- /dev/null +++ b/common/changes/@rushstack/heft-vscode-extension-plugin/bmiddha-tls-sync-v2_2025-07-24-22-08.json @@ -0,0 +1,15 @@ +{ + "changes": [ + { + "packageName": "@rushstack/heft-vscode-extension-plugin", + "comment": "Add support for generating extension manifest.", + "type": "minor" + }, + { + "packageName": "@rushstack/heft-vscode-extension-plugin", + "comment": "Add VSIX publish plugin.", + "type": "minor" + } + ], + "packageName": "@rushstack/heft-vscode-extension-plugin" +} \ No newline at end of file diff --git a/common/changes/@rushstack/heft-vscode-extension-rig/bmiddha-tls-sync-v2_2025-07-25-06-09.json b/common/changes/@rushstack/heft-vscode-extension-rig/bmiddha-tls-sync-v2_2025-07-25-06-09.json new file mode 100644 index 00000000000..f6bd7e992ce --- /dev/null +++ b/common/changes/@rushstack/heft-vscode-extension-rig/bmiddha-tls-sync-v2_2025-07-25-06-09.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@rushstack/heft-vscode-extension-rig", + "comment": "Add publish vsix plugin configuration.", + "type": "patch" + } + ], + "packageName": "@rushstack/heft-vscode-extension-rig" +} \ No newline at end of file diff --git a/common/config/azure-pipelines/vscode-extension-publish.yaml b/common/config/azure-pipelines/vscode-extension-publish.yaml index 172133d03b5..b73321d7aca 100644 --- a/common/config/azure-pipelines/vscode-extension-publish.yaml +++ b/common/config/azure-pipelines/vscode-extension-publish.yaml @@ -9,17 +9,13 @@ parameters: - name: ExtensionPublishConfig type: object default: - - key: 'tls-sync-vscode-ui-extension' + - key: 'debug-certificate-manager-vscode-extension' vsixPath: 'dist/vsix/packaged.vsix' - projectPath: '$(Build.SourcesDirectory)/vscode-extensions/tls-sync-vscode-ui-extension' - - key: 'tls-sync-vscode-workspace-extension' - vsixPath: 'dist/vsix/packaged.vsix' - projectPath: '$(Build.SourcesDirectory)/vscode-extensions/tls-sync-vscode-workspace-extension' - - key: 'tls-sync-vscode-extension-pack' - vsixPath: 'dist/vsix/packaged.vsix' - projectPath: '$(Build.SourcesDirectory)/vscode-extensions/tls-sync-vscode-extension-pack' + manifestPath: 'dist/vsix/extension-manifest.json' + projectPath: '$(Build.SourcesDirectory)/vscode-extensions/debug-certificate-manager-vscode-extension' - key: 'rush-vscode-extension' vsixPath: 'dist/vsix/packaged.vsix' + manifestPath: 'dist/vsix/extension-manifest.json' projectPath: '$(Build.SourcesDirectory)/vscode-extensions/rush-vscode-extension' resources: @@ -62,7 +58,43 @@ extends: --to tag:vsix - ${{ if parameters.shouldPublish }}: + - task: AzureCLI@2 + displayName: 'Get managed identity user info' + inputs: + azureSubscription: 'rushstack-vscode-publish' + scriptType: bash + scriptLocation: inlineScript + inlineScript: | + az rest -u https://app.vssps.visualstudio.com/_apis/profile/profiles/me --resource 499b84ac-1321-427f-aa17-267ca6975798 + - ${{ each extension in parameters.ExtensionPublishConfig }}: + - bash: cp ${{ extension.manifestPath }} ${{ extension.projectPath }}/extension.signature.p7s + workingDirectory: ${{ extension.projectPath }} + displayName: 'Prepare manifest for signing: ${{ extension.key }}' + + - task: EsrpCodeSigning@5 + displayName: 'ESRP CodeSigning' + inputs: + connectedservicename: '' # TODO + AppRegistrationClientId: '' # TODO + AppRegistrationTenantId: '' # TODO + AuthAKVName: '' # TODO + AuthCertName: '' # TODO + AuthSignCertName: '' # TODO + FolderPath: '${{ extension.projectPath }}' + Pattern: 'extension.signature.p7s' + signConfigType: inlineSignParams + inlineOperation: | + [ + { + "keyCode": "CP-401405", + "operationSetCode": "VSCodePublisherSign", + "parameters": [], + "toolName": "sign", + "toolVersion": "1.0" + } + ] + - task: AzureCLI@2 displayName: 'Publish VSIX: ${{ extension.key }}' inputs: @@ -70,5 +102,5 @@ extends: scriptType: 'bash' scriptLocation: 'inlineScript' inlineScript: | - node node_modules/@rushstack/heft-vscode-extension-rig/node_modules/@rushstack/heft-vscode-extension-plugin/node_modules/@vscode/vsce/vsce publish --no-dependencies --azure-credential --packagePath ${{ extension.vsixPath }} + node node_modules/@rushstack/heft/lib/start.js publish-vsix --vsix-path ${{ extension.vsixPath }} --manifest-path ${{ extension.projectPath }}/extension.manifest --signature-path ${{ extension.projectPath }}/extension.signature.p7s workingDirectory: ${{ extension.projectPath }} diff --git a/common/config/rush/version-policies.json b/common/config/rush/version-policies.json index c4eee5f5abb..bdbeeb351d2 100644 --- a/common/config/rush/version-policies.json +++ b/common/config/rush/version-policies.json @@ -105,15 +105,5 @@ "version": "5.156.0", "nextBump": "minor", "mainProject": "@microsoft/rush" - }, - { - // This policy is used for the TLS Sync VS Code extensions. - // Updating them in lockstep is necessary for the UI and Workspace extensions to work together. - // The Workspace and UI extensions perform a ping-pong version check to ensure they are compatible. - "policyName": "tls-sync-vscode-extensions", - "definitionName": "lockStepVersion", - "version": "0.0.1", - "nextBump": "minor", - "mainProject": "tls-sync-vscode-extension-pack" } ] diff --git a/common/config/subspaces/default/pnpm-lock.yaml b/common/config/subspaces/default/pnpm-lock.yaml index 1c5bc38a084..44e89ad3432 100644 --- a/common/config/subspaces/default/pnpm-lock.yaml +++ b/common/config/subspaces/default/pnpm-lock.yaml @@ -4744,22 +4744,7 @@ importers: specifier: ^10.1.0 version: 10.4.0 - ../../../vscode-extensions/tls-sync-vscode-extension-pack: - devDependencies: - '@rushstack/heft': - specifier: workspace:* - version: link:../../apps/heft - '@rushstack/heft-vscode-extension-rig': - specifier: workspace:* - version: link:../../rigs/heft-vscode-extension-rig - tls-sync-vscode-ui-extension: - specifier: workspace:* - version: link:../tls-sync-vscode-ui-extension - tls-sync-vscode-workspace-extension: - specifier: workspace:* - version: link:../tls-sync-vscode-workspace-extension - - ../../../vscode-extensions/tls-sync-vscode-shared: + ../../../vscode-extensions/debug-certificate-manager-vscode-extension: dependencies: '@rushstack/debug-certificate-manager': specifier: workspace:* @@ -4770,71 +4755,6 @@ importers: '@rushstack/terminal': specifier: workspace:* version: link:../../libraries/terminal - devDependencies: - '@rushstack/heft': - specifier: workspace:* - version: link:../../apps/heft - '@rushstack/heft-node-rig': - specifier: workspace:* - version: link:../../rigs/heft-node-rig - '@types/node': - specifier: 20.17.19 - version: 20.17.19 - '@types/vscode': - specifier: ^1.63.0 - version: 1.87.0 - - ../../../vscode-extensions/tls-sync-vscode-ui-extension: - dependencies: - '@rushstack/debug-certificate-manager': - specifier: workspace:* - version: link:../../libraries/debug-certificate-manager - '@rushstack/node-core-library': - specifier: workspace:* - version: link:../../libraries/node-core-library - '@rushstack/terminal': - specifier: workspace:* - version: link:../../libraries/terminal - '@rushstack/tls-sync-vscode-shared': - specifier: workspace:* - version: link:../tls-sync-vscode-shared - '@rushstack/vscode-shared': - specifier: workspace:* - version: link:../vscode-shared - tslib: - specifier: ~2.3.1 - version: 2.3.1 - devDependencies: - '@rushstack/heft': - specifier: workspace:* - version: link:../../apps/heft - '@rushstack/heft-vscode-extension-rig': - specifier: workspace:* - version: link:../../rigs/heft-vscode-extension-rig - '@types/node': - specifier: 20.17.19 - version: 20.17.19 - '@types/vscode': - specifier: ^1.63.0 - version: 1.87.0 - '@types/webpack-env': - specifier: 1.18.8 - version: 1.18.8 - - ../../../vscode-extensions/tls-sync-vscode-workspace-extension: - dependencies: - '@rushstack/debug-certificate-manager': - specifier: workspace:* - version: link:../../libraries/debug-certificate-manager - '@rushstack/node-core-library': - specifier: workspace:* - version: link:../../libraries/node-core-library - '@rushstack/terminal': - specifier: workspace:* - version: link:../../libraries/terminal - '@rushstack/tls-sync-vscode-shared': - specifier: workspace:* - version: link:../tls-sync-vscode-shared '@rushstack/vscode-shared': specifier: workspace:* version: link:../vscode-shared diff --git a/heft-plugins/heft-vscode-extension-plugin/heft-plugin.json b/heft-plugins/heft-vscode-extension-plugin/heft-plugin.json index 98845cc6151..ca301083ed4 100644 --- a/heft-plugins/heft-vscode-extension-plugin/heft-plugin.json +++ b/heft-plugins/heft-vscode-extension-plugin/heft-plugin.json @@ -1,10 +1,38 @@ { "$schema": "https://developer.microsoft.com/json-schemas/heft/v0/heft-plugin.schema.json", - "taskPlugins": [ { "pluginName": "vscode-extension-package-plugin", - "entryPoint": "./lib/VSCodeExtensionPackagePlugin.js" + "entryPoint": "./lib/VSCodeExtensionPackagePlugin.js", + "parameterScope": "package" + }, + { + "pluginName": "vscode-extension-publish-plugin", + "entryPoint": "./lib/VSCodeExtensionPublishPlugin.js", + "parameterScope": "publish-vsix", + "parameters": [ + { + "longName": "--vsix-path", + "parameterKind": "string", + "argumentName": "RELATIVE_PATH", + "description": "Use this parameter to control which VSIX file will be used for publishing.", + "required": true + }, + { + "longName": "--manifest-path", + "parameterKind": "string", + "argumentName": "RELATIVE_PATH", + "description": "Use this parameter to control which manifest file will be used for publishing.", + "required": true + }, + { + "longName": "--signature-path", + "parameterKind": "string", + "argumentName": "RELATIVE_PATH", + "description": "Use this parameter to control which signature file will be used for publishing.", + "required": true + } + ] } ] } diff --git a/heft-plugins/heft-vscode-extension-plugin/src/VSCodeExtensionPackagePlugin.ts b/heft-plugins/heft-vscode-extension-plugin/src/VSCodeExtensionPackagePlugin.ts index e5b4cc694ba..5bb8e63c061 100644 --- a/heft-plugins/heft-vscode-extension-plugin/src/VSCodeExtensionPackagePlugin.ts +++ b/heft-plugins/heft-vscode-extension-plugin/src/VSCodeExtensionPackagePlugin.ts @@ -7,10 +7,9 @@ import type { IHeftTaskSession, IHeftTaskRunHookOptions } from '@rushstack/heft'; -import { Executable, IWaitForExitResult } from '@rushstack/node-core-library'; -import type { ChildProcess } from 'node:child_process'; +import type { IWaitForExitResult } from '@rushstack/node-core-library'; import * as path from 'node:path'; -import { TerminalStreamWritable, TerminalProviderSeverity } from '@rushstack/terminal'; +import { executeAndWaitAsync, vsceScriptPath } from './util'; interface IVSCodeExtensionPackagePluginOptions { /** @@ -24,13 +23,15 @@ interface IVSCodeExtensionPackagePluginOptions { * If a directory is provided, the VSIX file will be named based on the extension's `package.json` name and version. */ vsixPath: string; + /** + * The path where the generated manifest file will be saved. + * This manifest is used for signing the VS Code extension. + */ + manifestPath: string; } const PLUGIN_NAME: 'vscode-extension-package-plugin' = 'vscode-extension-package-plugin'; -const vsceBasePackagePath: string = require.resolve('@vscode/vsce/package.json'); -const vsceScript: string = path.resolve(vsceBasePackagePath, '../vsce'); - export default class VSCodeExtensionPackagePlugin implements IHeftTaskPlugin { @@ -40,46 +41,50 @@ export default class VSCodeExtensionPackagePlugin pluginOptions: IVSCodeExtensionPackagePluginOptions ): void { heftTaskSession.hooks.run.tapPromise(PLUGIN_NAME, async (runOptions: IHeftTaskRunHookOptions) => { - const { unpackedFolderPath, vsixPath } = pluginOptions; + const { unpackedFolderPath, vsixPath, manifestPath } = pluginOptions; + const { buildFolderPath } = heftConfiguration; const { logger: { terminal } } = heftTaskSession; - terminal.writeLine(`Using VSCE script: ${vsceScript}`); + terminal.writeLine(`Using VSCE script: ${vsceScriptPath}`); + terminal.writeLine(`Packaging VSIX from ${unpackedFolderPath} to ${vsixPath}`); - const terminalOutStream: TerminalStreamWritable = new TerminalStreamWritable({ - terminal, - severity: TerminalProviderSeverity.log - }); - const terminalErrorStream: TerminalStreamWritable = new TerminalStreamWritable({ + const packageResult: IWaitForExitResult = await executeAndWaitAsync( terminal, - severity: TerminalProviderSeverity.error - }); - - const childProcess: ChildProcess = Executable.spawn( 'node', - [vsceScript, 'package', '--no-dependencies', '--out', `${path.resolve(vsixPath)}`], + [vsceScriptPath, 'package', '--no-dependencies', '--out', path.resolve(vsixPath)], { - currentWorkingDirectory: path.resolve(unpackedFolderPath), - stdio: [ - 'ignore', // stdin - 'pipe', // stdout - 'pipe' // stderr - ] + currentWorkingDirectory: path.resolve(buildFolderPath, unpackedFolderPath) } ); - - childProcess.stdout?.pipe(terminalOutStream); - childProcess.stderr?.pipe(terminalErrorStream); - - const result: IWaitForExitResult = await Executable.waitForExitAsync(childProcess, { - encoding: 'utf8' - }); - - if (result.exitCode !== 0) { - throw new Error(`VSIX packaging failed with exit code ${result.exitCode}`); + if (packageResult.exitCode !== 0) { + throw new Error(`VSIX packaging failed with exit code ${packageResult.exitCode}`); } terminal.writeLine('VSIX successfully packaged.'); + + terminal.writeLine(`Generating manifest at ${manifestPath}`); + const manifestResult: IWaitForExitResult = await executeAndWaitAsync( + terminal, + 'node', + [ + vsceScriptPath, + 'generate-manifest', + '--packagePath', + path.resolve(vsixPath), + '--out', + path.resolve(manifestPath) + ], + { + currentWorkingDirectory: buildFolderPath + } + ); + if (manifestResult.exitCode !== 0) { + throw new Error(`Manifest generation failed with exit code ${manifestResult.exitCode}`); + } + terminal.writeLine('Manifest successfully generated.'); + + terminal.writeLine(`VSIX package and manifest generation completed successfully.`); }); } } diff --git a/heft-plugins/heft-vscode-extension-plugin/src/VSCodeExtensionPublishPlugin.ts b/heft-plugins/heft-vscode-extension-plugin/src/VSCodeExtensionPublishPlugin.ts new file mode 100644 index 00000000000..f2393e58745 --- /dev/null +++ b/heft-plugins/heft-vscode-extension-plugin/src/VSCodeExtensionPublishPlugin.ts @@ -0,0 +1,94 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See LICENSE in the project root for license information. + +import type { + HeftConfiguration, + IHeftTaskPlugin, + IHeftTaskSession, + IHeftTaskRunHookOptions, + CommandLineStringParameter +} from '@rushstack/heft'; +import type { IWaitForExitResult } from '@rushstack/node-core-library'; +import * as path from 'node:path'; +import { executeAndWaitAsync, vsceScriptPath } from './util'; + +interface IVSCodeExtensionPublishPluginOptions {} + +const PLUGIN_NAME: 'vscode-extension-publish-plugin' = 'vscode-extension-publish-plugin'; + +const VSIX_PATH_PARAMETER_NAME: string = '--vsix-path'; +const MANIFEST_PATH_PARAMETER_NAME: string = '--manifest-path'; +const SIGNATURE_PATH_PARAMETER_NAME: string = '--signature-path'; + +export default class VSCodeExtensionPublishPlugin + implements IHeftTaskPlugin +{ + public apply( + heftTaskSession: IHeftTaskSession, + heftConfiguration: HeftConfiguration, + pluginOptions: IVSCodeExtensionPublishPluginOptions + ): void { + const vsixPathParameter: CommandLineStringParameter = + heftTaskSession.parameters.getStringParameter(VSIX_PATH_PARAMETER_NAME); + const manifestPathParameter: CommandLineStringParameter = heftTaskSession.parameters.getStringParameter( + MANIFEST_PATH_PARAMETER_NAME + ); + const signaturePathParameter: CommandLineStringParameter = heftTaskSession.parameters.getStringParameter( + SIGNATURE_PATH_PARAMETER_NAME + ); + + if (!vsixPathParameter.value) { + throw new Error( + `The parameter "${VSIX_PATH_PARAMETER_NAME}" is required for the VSCodeExtensionPublishPlugin.` + ); + } + if (!manifestPathParameter.value) { + throw new Error( + `The parameter "${MANIFEST_PATH_PARAMETER_NAME}" is required for the VSCodeExtensionPublishPlugin.` + ); + } + if (!signaturePathParameter.value) { + throw new Error( + `The parameter "${SIGNATURE_PATH_PARAMETER_NAME}" is required for the VSCodeExtensionPublishPlugin.` + ); + } + + const vsixPath: string = vsixPathParameter.value; + const manifestPath: string = manifestPathParameter.value; + const signaturePath: string = signaturePathParameter.value; + + heftTaskSession.hooks.run.tapPromise(PLUGIN_NAME, async (runOptions: IHeftTaskRunHookOptions) => { + const { buildFolderPath } = heftConfiguration; + const { + logger: { terminal } + } = heftTaskSession; + + terminal.writeLine(`Using VSCE script: ${vsceScriptPath}`); + terminal.writeLine(`Publishing VSIX ${vsixPath}`); + + const publishResult: IWaitForExitResult = await executeAndWaitAsync( + terminal, + 'node', + [ + vsceScriptPath, + 'publish', + '--no-dependencies', + '--azure-credential', + '--packagePath', + path.resolve(vsixPath), + '--manifestPath', + path.resolve(manifestPath), + '--signaturePath', + path.resolve(signaturePath) + ], + { + currentWorkingDirectory: path.resolve(buildFolderPath) + } + ); + if (publishResult.exitCode !== 0) { + throw new Error(`VSIX publishing failed with exit code ${publishResult.exitCode}`); + } + terminal.writeLine('VSIX successfully published.'); + }); + } +} diff --git a/heft-plugins/heft-vscode-extension-plugin/src/util.ts b/heft-plugins/heft-vscode-extension-plugin/src/util.ts new file mode 100644 index 00000000000..0772a2698a0 --- /dev/null +++ b/heft-plugins/heft-vscode-extension-plugin/src/util.ts @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See LICENSE in the project root for license information. + +import { Executable, IExecutableSpawnOptions, IWaitForExitResult } from '@rushstack/node-core-library'; +import type { ChildProcess } from 'node:child_process'; +import * as path from 'node:path'; +import { TerminalStreamWritable, TerminalProviderSeverity, ITerminal } from '@rushstack/terminal'; + +export async function executeAndWaitAsync( + terminal: ITerminal, + command: string, + args: string[], + options: Omit = {} +): Promise> { + const childProcess: ChildProcess = Executable.spawn(command, args, { + ...options, + stdio: [ + 'ignore', // stdin + 'pipe', // stdout + 'pipe' // stderr + ] + }); + childProcess.stdout?.pipe( + new TerminalStreamWritable({ + terminal, + severity: TerminalProviderSeverity.log + }) + ); + childProcess.stderr?.pipe( + new TerminalStreamWritable({ + terminal, + severity: TerminalProviderSeverity.error + }) + ); + const result: IWaitForExitResult = await Executable.waitForExitAsync(childProcess, { + encoding: 'utf8' + }); + return result; +} + +const vsceBasePackagePath: string = require.resolve('@vscode/vsce/package.json'); +export const vsceScriptPath: string = path.resolve(vsceBasePackagePath, '../vsce'); diff --git a/libraries/debug-certificate-manager/src/CertificateStore.ts b/libraries/debug-certificate-manager/src/CertificateStore.ts index 7acfbfd1ca1..246b2793705 100644 --- a/libraries/debug-certificate-manager/src/CertificateStore.ts +++ b/libraries/debug-certificate-manager/src/CertificateStore.ts @@ -49,24 +49,68 @@ export class CertificateStore { public constructor(options: ICertificateStoreOptions = {}) { const requestedStorePath: string | undefined = options.storePath; + let storePath: string | undefined; + let debugCertificateManagerConfig: ICertificateStoreOptions | undefined = undefined; + if (requestedStorePath) { storePath = path.resolve(requestedStorePath); } else { - // Default to the user's home directory under `.rushstack` - const unresolvedUserFolder: string = homedir(); - const userProfilePath: string = path.resolve(unresolvedUserFolder); - if (!FileSystem.exists(userProfilePath)) { - throw new Error("Unable to determine the current user's home directory"); + // TLS Sync extension configuration lives in `.vscode/debug-certificate-manager.json` + let currentDir: string | undefined = process.cwd(); + while (currentDir) { + const debugCertificateManagerConfigFile: string = path.join( + currentDir, + '.vscode', + 'debug-certificate-manager.json' + ); + if (FileSystem.exists(debugCertificateManagerConfigFile)) { + const configContent: string = FileSystem.readFile(debugCertificateManagerConfigFile); + debugCertificateManagerConfig = JSON.parse(configContent) as ICertificateStoreOptions; + if (debugCertificateManagerConfig.storePath) { + storePath = path.resolve(currentDir, debugCertificateManagerConfig.storePath); + } + } + const parentDir: string | undefined = path.dirname(currentDir); + if (parentDir === currentDir) { + break; // reached the root directory + } + currentDir = parentDir; + } + + if (!storePath) { + // Fallback to the user's home directory under `.rushstack` + const unresolvedUserFolder: string = homedir(); + const userProfilePath: string = path.resolve(unresolvedUserFolder); + if (!FileSystem.exists(userProfilePath)) { + throw new Error("Unable to determine the current user's home directory"); + } + storePath = path.join(userProfilePath, '.rushstack'); } - storePath = path.join(userProfilePath, '.rushstack'); } - this._storePath = storePath; FileSystem.ensureFolder(storePath); - this._caCertificatePath = path.join(storePath, options.caCertificateFilename ?? 'rushstack-ca.pem'); - this._certificatePath = path.join(storePath, options.certificateFilename ?? 'rushstack-serve.pem'); - this._keyPath = path.join(storePath, options.keyFilename ?? 'rushstack-serve.key'); + const caCertificatePath: string = path.join( + storePath, + options.caCertificateFilename ?? + debugCertificateManagerConfig?.caCertificateFilename ?? + 'rushstack-ca.pem' + ); + const certificatePath: string = path.join( + storePath, + options.certificateFilename ?? + debugCertificateManagerConfig?.certificateFilename ?? + 'rushstack-serve.pem' + ); + const keyPath: string = path.join( + storePath, + options.keyFilename ?? debugCertificateManagerConfig?.keyFilename ?? 'rushstack-serve.key' + ); + + this._storePath = storePath; + this._caCertificatePath = caCertificatePath; + this._certificatePath = certificatePath; + this._keyPath = keyPath; } /** diff --git a/rigs/heft-vscode-extension-rig/profiles/default/config/heft.json b/rigs/heft-vscode-extension-rig/profiles/default/config/heft.json index 29002b40b08..23c63c45c5c 100644 --- a/rigs/heft-vscode-extension-rig/profiles/default/config/heft.json +++ b/rigs/heft-vscode-extension-rig/profiles/default/config/heft.json @@ -1,8 +1,6 @@ { "$schema": "https://developer.microsoft.com/json-schemas/heft/v0/heft.schema.json", - "extends": "@rushstack/heft-node-rig/profiles/default/config/heft.json", - /** * The list of Heft phases that can be run by Heft. */ @@ -33,7 +31,6 @@ } } }, - "package-vsix": { "taskDependencies": ["typescript", "webpack", "copy-assets"], "taskPlugin": { @@ -41,7 +38,23 @@ "pluginName": "vscode-extension-package-plugin", "options": { "unpackedFolderPath": "dist/vsix/unpacked", - "vsixPath": "dist/vsix/packaged.vsix" + "vsixPath": "dist/vsix/packaged.vsix", + "manifestPath": "dist/vsix/extension-manifest.json" + } + } + } + } + }, + "publish-vsix": { + "phaseDescription": "Publish the VSIX package.", + "tasksByName": { + "publish-vsix": { + "taskPlugin": { + "pluginPackage": "@rushstack/heft-vscode-extension-plugin", + "pluginName": "vscode-extension-publish-plugin", + "options": { + "vsixPath": "dist/vsix/packaged.vsix", + "manifestPath": "dist/vsix/extension-manifest.json" } } } diff --git a/rush.json b/rush.json index 23a51a475ba..e50b04f65d1 100644 --- a/rush.json +++ b/rush.json @@ -1235,12 +1235,6 @@ "shouldPublish": true, "decoupledLocalDependencies": ["@rushstack/heft"] }, - { - "packageName": "@rushstack/tls-sync-vscode-shared", - "projectFolder": "vscode-extensions/tls-sync-vscode-shared", - "reviewCategory": "libraries", - "shouldPublish": false - }, { "packageName": "@rushstack/tree-pattern", "projectFolder": "libraries/tree-pattern", @@ -1404,28 +1398,10 @@ "tags": ["vsix"] }, { - "packageName": "tls-sync-vscode-workspace-extension", - "projectFolder": "vscode-extensions/tls-sync-vscode-workspace-extension", - "reviewCategory": "vscode-extensions", - "tags": ["vsix"] - // For now, to keep this from being published to the npm package feed - // "versionPolicyName": "tls-sync-vscode-extensions" - }, - { - "packageName": "tls-sync-vscode-ui-extension", - "projectFolder": "vscode-extensions/tls-sync-vscode-ui-extension", - "reviewCategory": "vscode-extensions", - "tags": ["vsix"] - // For now, to keep this from being published to the npm package feed - // "versionPolicyName": "tls-sync-vscode-extensions" - }, - { - "packageName": "tls-sync-vscode-extension-pack", - "projectFolder": "vscode-extensions/tls-sync-vscode-extension-pack", + "packageName": "debug-certificate-manager", + "projectFolder": "vscode-extensions/debug-certificate-manager-vscode-extension", "reviewCategory": "vscode-extensions", "tags": ["vsix"] - // For now, to keep this from being published to the npm package feed - // "versionPolicyName": "tls-sync-vscode-extensions" }, // "webpack" folder (alphabetical order) diff --git a/vscode-extensions/tls-sync-vscode-extension-pack/.npmignore b/vscode-extensions/debug-certificate-manager-vscode-extension/.npmignore similarity index 100% rename from vscode-extensions/tls-sync-vscode-extension-pack/.npmignore rename to vscode-extensions/debug-certificate-manager-vscode-extension/.npmignore diff --git a/vscode-extensions/tls-sync-vscode-workspace-extension/.vscodeignore b/vscode-extensions/debug-certificate-manager-vscode-extension/.vscodeignore similarity index 100% rename from vscode-extensions/tls-sync-vscode-workspace-extension/.vscodeignore rename to vscode-extensions/debug-certificate-manager-vscode-extension/.vscodeignore diff --git a/vscode-extensions/tls-sync-vscode-ui-extension/LICENSE b/vscode-extensions/debug-certificate-manager-vscode-extension/LICENSE similarity index 97% rename from vscode-extensions/tls-sync-vscode-ui-extension/LICENSE rename to vscode-extensions/debug-certificate-manager-vscode-extension/LICENSE index 4575ab4ab2c..fd71bda5f04 100644 --- a/vscode-extensions/tls-sync-vscode-ui-extension/LICENSE +++ b/vscode-extensions/debug-certificate-manager-vscode-extension/LICENSE @@ -1,4 +1,4 @@ -tls-sync-vscode-ui-extension +debug-certificate-manager Copyright (c) Microsoft Corporation. All rights reserved. diff --git a/vscode-extensions/debug-certificate-manager-vscode-extension/README.md b/vscode-extensions/debug-certificate-manager-vscode-extension/README.md new file mode 100644 index 00000000000..d1006981386 --- /dev/null +++ b/vscode-extensions/debug-certificate-manager-vscode-extension/README.md @@ -0,0 +1,9 @@ +# Debug Certificate Manager VS Code Extension + +VS Code extension to manage debug TLS certificates and sync them to the VS Code workspace. Works with VS Code remote development (Codespaces, SSH, Dev Containers, WSL, VS Code Tunnels). + +## Sync Process + +The Debug Certificate Manager extension uses `@rushstack/debug-certificate-manager` to manage TLS certificates. It can also be used to sync certificates when connected to a VS Code remote workspace (WSL, Codespaces, Devcontainers, VS Code Tunnels). + +The extension reads `.vscode/debug-certificate-manager.json` for the certificate store path. When present, the extension will auto-activate and attempt to sync the certificates to the remote workspace. diff --git a/vscode-extensions/tls-sync-vscode-extension-pack/assets/extension-icon.png b/vscode-extensions/debug-certificate-manager-vscode-extension/assets/extension-icon.png similarity index 100% rename from vscode-extensions/tls-sync-vscode-extension-pack/assets/extension-icon.png rename to vscode-extensions/debug-certificate-manager-vscode-extension/assets/extension-icon.png diff --git a/vscode-extensions/tls-sync-vscode-extension-pack/config/heft.json b/vscode-extensions/debug-certificate-manager-vscode-extension/config/heft.json similarity index 100% rename from vscode-extensions/tls-sync-vscode-extension-pack/config/heft.json rename to vscode-extensions/debug-certificate-manager-vscode-extension/config/heft.json diff --git a/vscode-extensions/tls-sync-vscode-extension-pack/config/rig.json b/vscode-extensions/debug-certificate-manager-vscode-extension/config/rig.json similarity index 100% rename from vscode-extensions/tls-sync-vscode-extension-pack/config/rig.json rename to vscode-extensions/debug-certificate-manager-vscode-extension/config/rig.json diff --git a/vscode-extensions/tls-sync-vscode-extension-pack/config/rush-project.json b/vscode-extensions/debug-certificate-manager-vscode-extension/config/rush-project.json similarity index 100% rename from vscode-extensions/tls-sync-vscode-extension-pack/config/rush-project.json rename to vscode-extensions/debug-certificate-manager-vscode-extension/config/rush-project.json diff --git a/vscode-extensions/tls-sync-vscode-ui-extension/eslint.config.js b/vscode-extensions/debug-certificate-manager-vscode-extension/eslint.config.js similarity index 100% rename from vscode-extensions/tls-sync-vscode-ui-extension/eslint.config.js rename to vscode-extensions/debug-certificate-manager-vscode-extension/eslint.config.js diff --git a/vscode-extensions/debug-certificate-manager-vscode-extension/package.json b/vscode-extensions/debug-certificate-manager-vscode-extension/package.json new file mode 100644 index 00000000000..47f89a08701 --- /dev/null +++ b/vscode-extensions/debug-certificate-manager-vscode-extension/package.json @@ -0,0 +1,126 @@ +{ + "name": "debug-certificate-manager", + "version": "0.0.0", + "repository": { + "type": "git", + "url": "https://github.com/microsoft/rushstack.git", + "directory": "vscode-extensions/debug-certificate-manager-vscode-extension" + }, + "license": "MIT", + "publisher": "RushStack", + "preview": true, + "displayName": "Debug Certificate Manager", + "description": "VS Code extension to manage debug TLS certificates and sync them to the VS Code workspace. Works with VS Code remote development (Codespaces, SSH, Dev Containers, WSL, VS Code Tunnels).", + "homepage": "https://github.com/microsoft/rushstack/tree/main/vscode-extensions/debug-certificate-manager-vscode-extension", + "icon": "assets/extension-icon.png", + "extensionKind": [ + "ui" + ], + "categories": [ + "Other" + ], + "keywords": [], + "galleryBanner": { + "color": "#f0f0f0", + "theme": "light" + }, + "engines": { + "vscode": "^1.98.0" + }, + "main": "./extension.js", + "scripts": { + "build": "heft build --clean", + "build:watch": "heft build-watch", + "start": "heft start", + "_phase:build": "heft run --only build -- --clean", + "_phase:test": "" + }, + "contributes": { + "commands": [ + { + "command": "debugCertificateManager.showLog", + "title": "Show Log", + "category": "Debug Certificate Manager" + }, + { + "command": "debugCertificateManager.untrustCertificate", + "title": "Untrust Certificate", + "category": "Debug Certificate Manager" + }, + { + "command": "debugCertificateManager.ensureCertificate", + "title": "Ensure Certificate", + "category": "Debug Certificate Manager" + }, + { + "command": "debugCertificateManager.sync", + "title": "Sync TLS Certificates", + "category": "Debug Certificate Manager" + }, + { + "command": "debugCertificateManager.showSettings", + "title": "Show Settings", + "category": "Debug Certificate Manager" + } + ], + "configuration": { + "title": "Debug Certificate Manager", + "properties": { + "debugCertificateManager.storePath.osx": { + "type": "string", + "title": "Local Machine - Debug Certificate Manager Store Path (macOS)", + "description": "[Local machine] [macOS] Directory where TLS certificates are read and written." + }, + "debugCertificateManager.storePath.windows": { + "type": "string", + "title": "Local Machine - Debug Certificate Manager Store Path (Windows)", + "description": "[Local machine] [Windows] Directory where TLS certificates are read and written." + }, + "debugCertificateManager.storePath.linux": { + "type": "string", + "title": "Local Machine - Debug Certificate Manager Store Path (Linux)", + "description": "[Local machine] [Linux] Directory where TLS certificates are read and written." + }, + "debugCertificateManager.caCertificateFilename": { + "type": "string", + "title": "CA Certificate Filename", + "description": "Filename for the CA certificate." + }, + "debugCertificateManager.certificateFilename": { + "type": "string", + "title": "Server Certificate Filename", + "description": "Filename for the server certificate." + }, + "debugCertificateManager.keyFilename": { + "type": "string", + "title": "Server Key Filename", + "description": "Filename for the server key." + }, + "debugCertificateManager.autoSync": { + "type": "boolean", + "title": "Automatically Sync Certificates", + "default": true, + "description": "Check certificates when extension is activated. Extension is automatically activated when a `.vscode/debug-certificate-manager.json` file is present in the workspace." + } + } + } + }, + "enabledApiProposals": [], + "activationEvents": [ + "workspaceContains:.vscode/debug-certificate-manager.json" + ], + "dependencies": { + "@rushstack/debug-certificate-manager": "workspace:*", + "@rushstack/node-core-library": "workspace:*", + "@rushstack/terminal": "workspace:*", + "@rushstack/vscode-shared": "workspace:*", + "tslib": "~2.3.1" + }, + "devDependencies": { + "@rushstack/heft-vscode-extension-rig": "workspace:*", + "@rushstack/heft": "workspace:*", + "@types/node": "20.17.19", + "@types/vscode": "^1.63.0", + "@types/webpack-env": "1.18.8" + } +} diff --git a/vscode-extensions/tls-sync-vscode-shared/src/certificates.ts b/vscode-extensions/debug-certificate-manager-vscode-extension/src/certificates.ts similarity index 70% rename from vscode-extensions/tls-sync-vscode-shared/src/certificates.ts rename to vscode-extensions/debug-certificate-manager-vscode-extension/src/certificates.ts index 16537281730..b918be65368 100644 --- a/vscode-extensions/tls-sync-vscode-shared/src/certificates.ts +++ b/vscode-extensions/debug-certificate-manager-vscode-extension/src/certificates.ts @@ -5,14 +5,8 @@ import { getConfig } from './config'; import { CertificateManager, CertificateStore } from '@rushstack/debug-certificate-manager'; import type { ITerminal } from '@rushstack/terminal'; -export function getCertificateManager( - terminal: ITerminal, - configType: 'ui' | 'workspace' -): CertificateManager { - const { caCertificateFilename, keyFilename, certificateFilename, storePath } = getConfig( - terminal, - configType - ); +export function getCertificateManager(terminal: ITerminal): CertificateManager { + const { caCertificateFilename, keyFilename, certificateFilename, storePath } = getConfig(terminal); const certificateManager: CertificateManager = new CertificateManager({ caCertificateFilename, keyFilename, @@ -23,11 +17,8 @@ export function getCertificateManager( return certificateManager; } -export function getCertificateStore(terminal: ITerminal, configType: 'ui' | 'workspace'): CertificateStore { - const { caCertificateFilename, keyFilename, certificateFilename, storePath } = getConfig( - terminal, - configType - ); +export function getCertificateStore(terminal: ITerminal): CertificateStore { + const { caCertificateFilename, keyFilename, certificateFilename, storePath } = getConfig(terminal); const certificateStore: CertificateStore = new CertificateStore({ caCertificateFilename, keyFilename, diff --git a/vscode-extensions/tls-sync-vscode-shared/src/config.ts b/vscode-extensions/debug-certificate-manager-vscode-extension/src/config.ts similarity index 66% rename from vscode-extensions/tls-sync-vscode-shared/src/config.ts rename to vscode-extensions/debug-certificate-manager-vscode-extension/src/config.ts index e444008c052..1a6371b81b8 100644 --- a/vscode-extensions/tls-sync-vscode-shared/src/config.ts +++ b/vscode-extensions/debug-certificate-manager-vscode-extension/src/config.ts @@ -4,7 +4,7 @@ import * as vscode from 'vscode'; import * as path from 'node:path'; import type { ITerminal } from '@rushstack/terminal'; -import type { ICertificateManagerOptions } from '@rushstack/debug-certificate-manager'; +import type { ICertificateStoreOptions } from '@rushstack/debug-certificate-manager'; import { CONFIG_AUTOSYNC, CONFIG_SECTION, @@ -15,22 +15,20 @@ import { } from './constants'; type StorePaths = Record<'windows' | 'linux' | 'osx', string>; -export interface IExtensionConfig extends ICertificateManagerOptions { +export interface IExtensionConfig extends ICertificateStoreOptions { autoSync: boolean; } -export function getConfig(terminal: ITerminal, configType: 'ui' | 'workspace'): IExtensionConfig { +export function getConfig(terminal: ITerminal): IExtensionConfig { const config: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration(CONFIG_SECTION); - const caCertificateFilename: string | undefined = config.get(CONFIG_CA_CERTIFICATE_FILENAME) || undefined; - const certificateFilename: string | undefined = config.get(CONFIG_CERTIFICATE_FILENAME) || undefined; - const keyFilename: string | undefined = config.get(CONFIG_KEY_FILENAME) || undefined; + const caCertificateFilename: string | undefined = + config.get(CONFIG_CA_CERTIFICATE_FILENAME) || 'rushstack-ca.pem'; + const certificateFilename: string | undefined = + config.get(CONFIG_CERTIFICATE_FILENAME) || 'rushstack-serve.pem'; + const keyFilename: string | undefined = config.get(CONFIG_KEY_FILENAME) || 'rushstack-serve.key'; const autoSync: boolean = config.get(CONFIG_AUTOSYNC) ?? false; let storePath: string | undefined = undefined; - const storePaths: StorePaths = { - windows: config.get(`${configType}.${CONFIG_STORE_PATH}.windows`) || '', - linux: config.get(`${configType}.${CONFIG_STORE_PATH}.linux`) || '', - osx: config.get(`${configType}.${CONFIG_STORE_PATH}.osx`) || '' - }; + const platformMap: Record = { win32: 'windows', linux: 'linux', @@ -38,8 +36,9 @@ export function getConfig(terminal: ITerminal, configType: 'ui' | 'workspace'): }; const platformKey: keyof StorePaths = platformMap[process.platform]; + if (platformKey) { - storePath = storePaths[platformKey]; + storePath = config.get(`${CONFIG_STORE_PATH}.${platformKey}`) || '~/.rushstack'; if (storePath) { const homeDir: string | undefined = process.env.HOME || process.env.USERPROFILE; if (storePath[0] === '~' && homeDir) { diff --git a/vscode-extensions/debug-certificate-manager-vscode-extension/src/constants.ts b/vscode-extensions/debug-certificate-manager-vscode-extension/src/constants.ts new file mode 100644 index 00000000000..088cd173204 --- /dev/null +++ b/vscode-extensions/debug-certificate-manager-vscode-extension/src/constants.ts @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See LICENSE in the project root for license information. + +export const EXTENSION_DISPLAY_NAME: string = 'Debug Certificate Manager'; + +export const EXTENSION_ID: string = 'RushStack.debug-certificate-manager'; + +export const COMMAND_PREFIX: string = 'debugCertificateManager'; +export const COMMAND_SYNC: string = `${COMMAND_PREFIX}.sync`; +export const COMMAND_ENSURE_CERTIFICATE: string = `${COMMAND_PREFIX}.ensureCertificate`; +export const COMMAND_UNTRUST_CERTIFICATE: string = `${COMMAND_PREFIX}.untrustCertificate`; +export const COMMAND_SHOW_LOG: string = `${COMMAND_PREFIX}.showLog`; +export const COMMAND_SHOW_SETTINGS: string = `${COMMAND_PREFIX}.showSettings`; + +export const CONFIG_SECTION: string = 'debugCertificateManager'; +export const CONFIG_AUTOSYNC: string = 'autoSync'; +export const CONFIG_CA_CERTIFICATE_FILENAME: string = 'caCertificateFilename'; +export const CONFIG_CERTIFICATE_FILENAME: string = 'certificateFilename'; +export const CONFIG_KEY_FILENAME: string = 'keyFilename'; +export const CONFIG_STORE_PATH: string = 'storePath'; + +export const VSCODE_COMMAND_WORKSPACE_OPEN_SETTINGS: string = 'workbench.action.openSettings'; diff --git a/vscode-extensions/tls-sync-vscode-ui-extension/src/extension.ts b/vscode-extensions/debug-certificate-manager-vscode-extension/src/extension.ts similarity index 56% rename from vscode-extensions/tls-sync-vscode-ui-extension/src/extension.ts rename to vscode-extensions/debug-certificate-manager-vscode-extension/src/extension.ts index 974034d6fbf..87f293854a4 100644 --- a/vscode-extensions/tls-sync-vscode-ui-extension/src/extension.ts +++ b/vscode-extensions/debug-certificate-manager-vscode-extension/src/extension.ts @@ -7,39 +7,27 @@ import { Async } from '@rushstack/node-core-library/lib/Async'; import { Terminal } from '@rushstack/terminal'; import { CertificateManager, + ICertificateStoreOptions, ICertificateValidationResult, type ICertificate } from '@rushstack/debug-certificate-manager'; import { VScodeOutputChannelTerminalProvider } from '@rushstack/vscode-shared/lib/VScodeOutputChannelTerminalProvider'; -import { getCertificateManager } from '@rushstack/tls-sync-vscode-shared/lib/certificates'; -import { getConfig } from '@rushstack/tls-sync-vscode-shared/lib/config'; +import { getCertificateManager } from './certificates'; +import { getConfig } from './config'; import { - UI_COMMAND_ENSURE_CERTIFICATE, - UI_COMMAND_SHOW_LOG, - UI_COMMAND_SHOW_SETTINGS, - UI_COMMAND_SHOW_WALKTHROUGH, - UI_COMMAND_SYNC, - UI_COMMAND_UNTRUST_CERTIFICATE, - UI_EXTENSION_DISPLAY_NAME, - UI_EXTENSION_ID, - UI_WALKTHROUGH_ID, - VSCODE_COMMAND_WORKSPACE_OPEN_SETTINGS, - VSCODE_COMMAND_WORKSPACE_OPEN_WALKTHROUGH, - WORKSPACE_COMMAND_PING, - WORKSPACE_COMMAND_SYNC, - WORKSPACE_EXTENSION_DISPLAY_NAME -} from '@rushstack/tls-sync-vscode-shared/lib/constants'; - -import { version } from '../package.json'; - -/* - * This extension provides commands to manage debug TLS certificates on the local machine. This capability is - * primarily intended to be called by the workspace extension counterpart. - */ + COMMAND_ENSURE_CERTIFICATE, + COMMAND_SHOW_LOG, + COMMAND_SHOW_SETTINGS, + COMMAND_SYNC, + COMMAND_UNTRUST_CERTIFICATE, + EXTENSION_DISPLAY_NAME, + EXTENSION_ID, + VSCODE_COMMAND_WORKSPACE_OPEN_SETTINGS +} from './constants'; export function activate(context: vscode.ExtensionContext): void { - const outputChannel: vscode.OutputChannel = vscode.window.createOutputChannel(UI_EXTENSION_DISPLAY_NAME); + const outputChannel: vscode.OutputChannel = vscode.window.createOutputChannel(EXTENSION_DISPLAY_NAME); const terminalProvider: VScodeOutputChannelTerminalProvider = new VScodeOutputChannelTerminalProvider( outputChannel, { @@ -48,7 +36,7 @@ export function activate(context: vscode.ExtensionContext): void { } ); const terminal: Terminal = new Terminal(terminalProvider); - terminal.writeLine(`${UI_EXTENSION_DISPLAY_NAME} Extension output channel initialized.`); + terminal.writeLine(`${EXTENSION_DISPLAY_NAME} Extension output channel initialized.`); function handleShowLog(): void { outputChannel.show(); @@ -57,7 +45,7 @@ export function activate(context: vscode.ExtensionContext): void { async function handleUntrustCertificate(): Promise { try { terminal.writeLine('Attempting to clean up certificates...'); - const certificateManager: CertificateManager = getCertificateManager(terminal, 'ui'); + const certificateManager: CertificateManager = getCertificateManager(terminal); await certificateManager.untrustCertificateAsync(terminal); const message: string = 'Certificates untrusted successfully.'; @@ -79,7 +67,7 @@ export function activate(context: vscode.ExtensionContext): void { async function _handleEnsureCertificateInternal(): Promise { try { terminal.writeLine('Attempting to retrieve certificates...'); - const certificateManager: CertificateManager = getCertificateManager(terminal, 'ui'); + const certificateManager: CertificateManager = getCertificateManager(terminal); let skipCertificateTrust: boolean = true; let canGenerateNewCertificate: boolean = false; @@ -149,53 +137,8 @@ export function activate(context: vscode.ExtensionContext): void { } } - async function handleShowWalkthrough(): Promise { - await vscode.commands.executeCommand( - VSCODE_COMMAND_WORKSPACE_OPEN_WALKTHROUGH, - `${UI_EXTENSION_ID}#${UI_WALKTHROUGH_ID}`, - false - ); - } - async function handleShowSettings(): Promise { - await vscode.commands.executeCommand(VSCODE_COMMAND_WORKSPACE_OPEN_SETTINGS, `@ext:${UI_EXTENSION_ID}`); - } - - async function waitForWorkspaceExtension(): Promise { - terminal.writeLine( - `Waiting for Workspace extension (${WORKSPACE_EXTENSION_DISPLAY_NAME}) to become active...` - ); - - const maxRetries: number = 30; - try { - await Async.runWithRetriesAsync({ - action: async (attempt: number) => { - terminal.writeLine(`Pinging Workspace extension... Attempt ${attempt + 1}/${maxRetries}`); - const { version: workspaceVersion } = await vscode.commands.executeCommand<{ version: string }>( - WORKSPACE_COMMAND_PING - ); - if (!workspaceVersion) { - terminal.writeLine('Workspace extension is not yet active. Retrying...'); - return; - } - terminal.writeLine(`Workspace extension is active. Version: ${workspaceVersion}`); - if (version !== workspaceVersion) { - terminal.writeLine( - `Warning: Workspace extension version mismatch. Expected ${version}, got ${workspaceVersion}.` - ); - void vscode.window.showWarningMessage( - `Workspace extension version mismatch. Expected ${version}, got ${workspaceVersion}. Please check that both ${WORKSPACE_EXTENSION_DISPLAY_NAME} and ${UI_EXTENSION_DISPLAY_NAME} are up to date.` - ); - throw new Error('Version mismatch'); - } - }, - maxRetries, - retryDelayMs: 1000 - }); - } catch (error) { - terminal.writeLine('UI extension did not respond within the expected time frame.'); - throw new Error('UI extension did not respond within the expected time frame.'); - } + await vscode.commands.executeCommand(VSCODE_COMMAND_WORKSPACE_OPEN_SETTINGS, `@ext:${EXTENSION_ID}`); } async function handleSync(): Promise { @@ -204,11 +147,11 @@ export function activate(context: vscode.ExtensionContext): void { 'This command is only available in remote workspaces. Please open this workspace in a remote environment.'; terminal.writeLine(message); void vscode.window.showErrorMessage(message); + return; } try { - await waitForWorkspaceExtension(); - terminal.writeLine('Workspace extension is active. Proceeding with certificate synchronization...'); + terminal.writeLine('Starting certificate synchronization...'); const certificate: ICertificate | undefined = await _handleEnsureCertificateInternal(); if (!certificate) { @@ -216,20 +159,84 @@ export function activate(context: vscode.ExtensionContext): void { return; } - terminal.writeLine('Sending certificates to workspace extension for synchronization...'); - const isSynchronized: boolean = await vscode.commands.executeCommand( - WORKSPACE_COMMAND_SYNC, - certificate - ); + const { pemCaCertificate, pemCertificate, pemKey } = certificate; + if (!pemCaCertificate || !pemCertificate || !pemKey) { + terminal.writeLine('Invalid certificate data. Synchronization aborted.'); + void vscode.window.showErrorMessage('Invalid certificate data. Synchronization aborted.'); + return; + } + + terminal.writeLine('Writing certificates to the workspace...'); - if (isSynchronized) { - await vscode.commands.executeCommand('setContext', 'tlssync.ui.sync.complete', true); - terminal.writeLine('Certificates synchronized successfully.'); - void vscode.window.showInformationMessage('Certificates synchronized successfully.'); + const workspaceUri: vscode.Uri | undefined = vscode.workspace.workspaceFolders?.[0].uri; + if (!workspaceUri) { + terminal.writeLine('No workspace folder found. Synchronization aborted.'); + void vscode.window.showErrorMessage( + 'No workspace folder found. Please open a folder in the remote workspace.' + ); + return; + } + + let remoteCertificateStoreOptions: Required | undefined = undefined; + + try { + const configFileUri: vscode.Uri = vscode.Uri.joinPath( + workspaceUri, + '.vscode', + 'debug-certificate-manager.json' + ); + const configFile: Uint8Array = await vscode.workspace.fs.readFile(configFileUri); + const parsedConfig: ICertificateStoreOptions & Required> = + JSON.parse(configFile.toString()); + + remoteCertificateStoreOptions = { + storePath: parsedConfig.storePath, + caCertificateFilename: parsedConfig.caCertificateFilename || 'rushstack-ca.pem', + certificateFilename: parsedConfig.certificateFilename || 'rushstack-serve.pem', + keyFilename: parsedConfig.keyFilename || 'rushstack-serve.key' + }; + } catch (error) { + void vscode.window.showErrorMessage( + 'Failed to read or parse the configuration file. Ensure that .vscode/debug-certificate-manager.json exists and is valid.' + ); + terminal.writeLine( + `Error reading or parsing configuration file: ${ + error instanceof Error ? error.message : 'Unknown error' + }` + ); + return; + } + + const { storePath, caCertificateFilename, certificateFilename, keyFilename } = + remoteCertificateStoreOptions; + + let resolvedRemoteStorePath: string; + if (storePath.startsWith('/')) { + resolvedRemoteStorePath = storePath; } else { - terminal.writeLine('Failed to synchronize certificates.'); - void vscode.window.showErrorMessage('Failed to synchronize certificates.'); + resolvedRemoteStorePath = vscode.Uri.joinPath(workspaceUri, storePath).fsPath; } + + const storePathUri: vscode.Uri = vscode.Uri.from({ + scheme: 'vscode-remote', + authority: workspaceUri.authority, + path: resolvedRemoteStorePath + }); + const caCertificateUri: vscode.Uri = vscode.Uri.joinPath(storePathUri, caCertificateFilename); + const certificateUri: vscode.Uri = vscode.Uri.joinPath(storePathUri, certificateFilename); + const keyUri: vscode.Uri = vscode.Uri.joinPath(storePathUri, keyFilename); + + terminal.writeLine(`Writing CA certificate to: ${caCertificateUri.toString()}`); + terminal.writeLine(`Writing certificate to: ${certificateUri.toString()}`); + terminal.writeLine(`Writing key to: ${keyUri.toString()}`); + + await Promise.all([ + vscode.workspace.fs.writeFile(caCertificateUri, Buffer.from(pemCaCertificate, 'utf8')), + vscode.workspace.fs.writeFile(certificateUri, Buffer.from(pemCertificate, 'utf8')), + vscode.workspace.fs.writeFile(keyUri, Buffer.from(pemKey, 'utf8')) + ]); + + terminal.writeLine('Certificates written to the workspace successfully.'); } catch (err) { const message: string = `Error synchronizing certificates: ${ err instanceof Error ? err.message : 'Unknown error' @@ -239,20 +246,18 @@ export function activate(context: vscode.ExtensionContext): void { } } - const { autoSync } = getConfig(terminal, 'ui'); + const { autoSync } = getConfig(terminal); if (autoSync && !vscode.env.remoteName) { terminal.writeLine(`Auto-sync is enabled. Synchronizing certificates on activation...`); - void vscode.commands.executeCommand(UI_COMMAND_SYNC); } context.subscriptions.push( outputChannel, - vscode.commands.registerCommand(UI_COMMAND_SHOW_LOG, handleShowLog), - vscode.commands.registerCommand(UI_COMMAND_SHOW_SETTINGS, handleShowSettings), - vscode.commands.registerCommand(UI_COMMAND_SHOW_WALKTHROUGH, handleShowWalkthrough), - vscode.commands.registerCommand(UI_COMMAND_UNTRUST_CERTIFICATE, handleUntrustCertificate), - vscode.commands.registerCommand(UI_COMMAND_ENSURE_CERTIFICATE, handleEnsureCertificate), - vscode.commands.registerCommand(UI_COMMAND_SYNC, handleSync) + vscode.commands.registerCommand(COMMAND_SHOW_LOG, handleShowLog), + vscode.commands.registerCommand(COMMAND_SHOW_SETTINGS, handleShowSettings), + vscode.commands.registerCommand(COMMAND_UNTRUST_CERTIFICATE, handleUntrustCertificate), + vscode.commands.registerCommand(COMMAND_ENSURE_CERTIFICATE, handleEnsureCertificate), + vscode.commands.registerCommand(COMMAND_SYNC, handleSync) ); } diff --git a/vscode-extensions/tls-sync-vscode-ui-extension/tsconfig.json b/vscode-extensions/debug-certificate-manager-vscode-extension/tsconfig.json similarity index 100% rename from vscode-extensions/tls-sync-vscode-ui-extension/tsconfig.json rename to vscode-extensions/debug-certificate-manager-vscode-extension/tsconfig.json diff --git a/vscode-extensions/tls-sync-vscode-workspace-extension/webpack.config.js b/vscode-extensions/debug-certificate-manager-vscode-extension/webpack.config.js similarity index 95% rename from vscode-extensions/tls-sync-vscode-workspace-extension/webpack.config.js rename to vscode-extensions/debug-certificate-manager-vscode-extension/webpack.config.js index bc6dfe67040..c12db6ac9df 100644 --- a/vscode-extensions/tls-sync-vscode-workspace-extension/webpack.config.js +++ b/vscode-extensions/debug-certificate-manager-vscode-extension/webpack.config.js @@ -10,7 +10,7 @@ const path = require('node:path'); function createConfig({ production, webpack }) { const config = createExtensionConfig({ - production, + production: false, webpack, entry: { extension: './lib/extension.js' diff --git a/vscode-extensions/tls-sync-vscode-extension-pack/.vscodeignore b/vscode-extensions/tls-sync-vscode-extension-pack/.vscodeignore deleted file mode 100644 index 9a22e7e9769..00000000000 --- a/vscode-extensions/tls-sync-vscode-extension-pack/.vscodeignore +++ /dev/null @@ -1,5 +0,0 @@ -** -!LICENSE -!README.md -!package.json -!assets/extension-icon.png diff --git a/vscode-extensions/tls-sync-vscode-extension-pack/LICENSE b/vscode-extensions/tls-sync-vscode-extension-pack/LICENSE deleted file mode 100644 index a79de558c93..00000000000 --- a/vscode-extensions/tls-sync-vscode-extension-pack/LICENSE +++ /dev/null @@ -1,24 +0,0 @@ -tls-sync-vscode-extension-pack - -Copyright (c) Microsoft Corporation. All rights reserved. - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vscode-extensions/tls-sync-vscode-extension-pack/README.md b/vscode-extensions/tls-sync-vscode-extension-pack/README.md deleted file mode 100644 index fc4ddd50127..00000000000 --- a/vscode-extensions/tls-sync-vscode-extension-pack/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# TLS Sync VS Code Extension Pack - -## Sync Process - -The workspace and UI extensions work together to use `@rushstack/debug-certificate-manager` to manage TLS certificates. The UI extension manages the machine where the VS Code client is running, while the Workspace extension manages the remote workspace (WSL, Codespaces, Devcontainers, VS Code Tunnels). - -Both the UI and Workspace extensions must be installed for the sync process to work. - -1. VS Code activates the UI extension if `.tlssync` file is present in the workspace or if the user runs the Sync command. -2. The UI extension checks if the Workspace extension is available. -3. If the Workspace extension is available, it ensures that valid certificates are present in the local certificate store. If not, it generates a new certificate and stores it in the local certificate store. -4. The UI extension then sends the certificate to the Workspace extension. - -The certificate store paths and the file names can be configured in the VS Code settings. Run the `TLS Sync: Show Settings` command to view and modify the configuration. - -## Extensions - -- [TLS Sync VS Code (UI Extension)](../tls-sync-vscode-ui-extension) -- [TLS Sync VS Code (Workspace Extension)](../tls-sync-vscode-extension-pack) diff --git a/vscode-extensions/tls-sync-vscode-extension-pack/package.json b/vscode-extensions/tls-sync-vscode-extension-pack/package.json deleted file mode 100644 index 3b9db955878..00000000000 --- a/vscode-extensions/tls-sync-vscode-extension-pack/package.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "name": "tls-sync-vscode-extension-pack", - "version": "0.0.0", - "repository": { - "type": "git", - "url": "https://github.com/microsoft/rushstack.git", - "directory": "vscode-extensions/tls-sync-vscode-extension-pack" - }, - "license": "MIT", - "publisher": "RushStack", - "preview": true, - "displayName": "TLS Sync", - "description": "", - "homepage": "https://github.com/microsoft/rushstack/tree/main/vscode-extensions/tls-sync-vscode-extension-pack", - "icon": "assets/extension-icon.png", - "categories": [ - "Other" - ], - "extensionPack": [ - "Rushstack.tls-sync-vscode-ui-extension", - "Rushstack.tls-sync-vscode-workspace-extension" - ], - "keywords": [], - "galleryBanner": { - "color": "#f0f0f0", - "theme": "light" - }, - "engines": { - "vscode": "^1.98.0" - }, - "scripts": { - "build": "heft build --clean", - "build:watch": "heft build-watch", - "start": "heft start", - "_phase:build": "heft run --only build -- --clean", - "_phase:test": "" - }, - "dependencies": {}, - "devDependencies": { - "@rushstack/heft-vscode-extension-rig": "workspace:*", - "@rushstack/heft": "workspace:*", - "tls-sync-vscode-ui-extension": "workspace:*", - "tls-sync-vscode-workspace-extension": "workspace:*" - } -} diff --git a/vscode-extensions/tls-sync-vscode-shared/.npmignore b/vscode-extensions/tls-sync-vscode-shared/.npmignore deleted file mode 100644 index dcf329e5ffa..00000000000 --- a/vscode-extensions/tls-sync-vscode-shared/.npmignore +++ /dev/null @@ -1,2 +0,0 @@ -# Ignore all files by default, to avoid accidentally publishing unintended files. -** diff --git a/vscode-extensions/tls-sync-vscode-shared/LICENSE b/vscode-extensions/tls-sync-vscode-shared/LICENSE deleted file mode 100644 index 1fefe388f93..00000000000 --- a/vscode-extensions/tls-sync-vscode-shared/LICENSE +++ /dev/null @@ -1,24 +0,0 @@ -@rushstack/tls-sync-vscode-shared - -Copyright (c) Microsoft Corporation. All rights reserved. - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vscode-extensions/tls-sync-vscode-shared/README.md b/vscode-extensions/tls-sync-vscode-shared/README.md deleted file mode 100644 index 7cbcf0522b6..00000000000 --- a/vscode-extensions/tls-sync-vscode-shared/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# @rushstack/tls-sync-vscode-shared - -This library provides a set of utilities for TLS Sync VS Code extensions. diff --git a/vscode-extensions/tls-sync-vscode-shared/config/rig.json b/vscode-extensions/tls-sync-vscode-shared/config/rig.json deleted file mode 100644 index 58032e098f0..00000000000 --- a/vscode-extensions/tls-sync-vscode-shared/config/rig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json", - - "rigPackageName": "@rushstack/heft-node-rig" -} diff --git a/vscode-extensions/tls-sync-vscode-shared/eslint.config.js b/vscode-extensions/tls-sync-vscode-shared/eslint.config.js deleted file mode 100644 index 006cb82d1c0..00000000000 --- a/vscode-extensions/tls-sync-vscode-shared/eslint.config.js +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. -// See LICENSE in the project root for license information. - -const nodeTrustedToolProfile = require('@rushstack/heft-node-rig/profiles/default/includes/eslint/flat/profile/node-trusted-tool'); -const friendlyLocalsMixin = require('@rushstack/heft-node-rig/profiles/default/includes/eslint/flat/mixins/friendly-locals'); - -module.exports = [...nodeTrustedToolProfile, ...friendlyLocalsMixin]; diff --git a/vscode-extensions/tls-sync-vscode-shared/package.json b/vscode-extensions/tls-sync-vscode-shared/package.json deleted file mode 100644 index b09528d52ac..00000000000 --- a/vscode-extensions/tls-sync-vscode-shared/package.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "@rushstack/tls-sync-vscode-shared", - "version": "0.0.0", - "description": "", - "main": "lib/index.js", - "typings": "dist/index.d.ts", - "license": "MIT", - "repository": { - "type": "git", - "url": "https://github.com/microsoft/rushstack.git", - "directory": "vscode-extensions/tls-sync-vscode-shared" - }, - "scripts": { - "build": "heft build --clean", - "_phase:build": "heft run --only build -- --clean", - "_phase:test": "heft run --only test -- --clean" - }, - "dependencies": { - "@rushstack/debug-certificate-manager": "workspace:*", - "@rushstack/node-core-library": "workspace:*", - "@rushstack/terminal": "workspace:*" - }, - "devDependencies": { - "@rushstack/heft-node-rig": "workspace:*", - "@rushstack/heft": "workspace:*", - "@types/node": "20.17.19", - "@types/vscode": "^1.63.0" - } -} diff --git a/vscode-extensions/tls-sync-vscode-shared/src/constants.ts b/vscode-extensions/tls-sync-vscode-shared/src/constants.ts deleted file mode 100644 index 55b961db633..00000000000 --- a/vscode-extensions/tls-sync-vscode-shared/src/constants.ts +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. -// See LICENSE in the project root for license information. - -export const WORKSPACE_EXTENSION_DISPLAY_NAME: string = 'TLS Sync (Workspace Extension)'; -export const UI_EXTENSION_DISPLAY_NAME: string = 'TLS Sync (UI Extension)'; - -export const WORKSPACE_EXTENSION_ID: string = 'RushStack.tls-sync-vscode-workspace-extension'; -export const UI_EXTENSION_ID: string = 'RushStack.tls-sync-vscode-ui-extension'; - -export const WORKSPACE_COMMAND_PREFIX: string = 'tlssync.workspace'; -export const UI_COMMAND_PREFIX: string = 'tlssync.ui'; - -export const WORKSPACE_COMMAND_SYNC: string = `${WORKSPACE_COMMAND_PREFIX}.sync`; -export const WORKSPACE_COMMAND_SHOW_LOG: string = `${WORKSPACE_COMMAND_PREFIX}.showLog`; -export const WORKSPACE_COMMAND_PING: string = `${WORKSPACE_COMMAND_PREFIX}.ping`; - -export const UI_COMMAND_SYNC: string = `${UI_COMMAND_PREFIX}.sync`; -export const UI_COMMAND_ENSURE_CERTIFICATE: string = `${UI_COMMAND_PREFIX}.ensureCertificate`; -export const UI_COMMAND_UNTRUST_CERTIFICATE: string = `${UI_COMMAND_PREFIX}.untrustCertificate`; -export const UI_COMMAND_SHOW_LOG: string = `${UI_COMMAND_PREFIX}.showLog`; -export const UI_COMMAND_SHOW_WALKTHROUGH: string = `${UI_COMMAND_PREFIX}.showWalkthrough`; -export const UI_COMMAND_SHOW_SETTINGS: string = `${UI_COMMAND_PREFIX}.showSettings`; - -export const CONFIG_SECTION: string = 'tlssync'; -export const CONFIG_AUTOSYNC: string = 'autoSync'; -export const CONFIG_CA_CERTIFICATE_FILENAME: string = 'caCertificateFilename'; -export const CONFIG_CERTIFICATE_FILENAME: string = 'certificateFilename'; -export const CONFIG_KEY_FILENAME: string = 'keyFilename'; -export const CONFIG_STORE_PATH: string = 'storePath'; - -export const VSCODE_COMMAND_WORKSPACE_OPEN_SETTINGS: string = 'workbench.action.openSettings'; -export const VSCODE_COMMAND_WORKSPACE_OPEN_WALKTHROUGH: string = 'workbench.action.openWalkthrough'; - -export const UI_WALKTHROUGH_ID: string = 'sync-certificates'; diff --git a/vscode-extensions/tls-sync-vscode-shared/tsconfig.json b/vscode-extensions/tls-sync-vscode-shared/tsconfig.json deleted file mode 100644 index a114c3448ed..00000000000 --- a/vscode-extensions/tls-sync-vscode-shared/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "./node_modules/@rushstack/heft-node-rig/profiles/default/tsconfig-base.json" -} diff --git a/vscode-extensions/tls-sync-vscode-ui-extension/.npmignore b/vscode-extensions/tls-sync-vscode-ui-extension/.npmignore deleted file mode 100644 index dcf329e5ffa..00000000000 --- a/vscode-extensions/tls-sync-vscode-ui-extension/.npmignore +++ /dev/null @@ -1,2 +0,0 @@ -# Ignore all files by default, to avoid accidentally publishing unintended files. -** diff --git a/vscode-extensions/tls-sync-vscode-ui-extension/.vscodeignore b/vscode-extensions/tls-sync-vscode-ui-extension/.vscodeignore deleted file mode 100644 index 57c6857fd22..00000000000 --- a/vscode-extensions/tls-sync-vscode-ui-extension/.vscodeignore +++ /dev/null @@ -1,8 +0,0 @@ -** -!LICENSE -!README.md -!extension.js -!package.json -!assets/extension-icon.png -!assets/walkthrough-sync.md -!assets/walkthrough-settings.md diff --git a/vscode-extensions/tls-sync-vscode-ui-extension/README.md b/vscode-extensions/tls-sync-vscode-ui-extension/README.md deleted file mode 100644 index 7fcea8962e3..00000000000 --- a/vscode-extensions/tls-sync-vscode-ui-extension/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# TLS Sync VS Code Extension (Local / UI Extension) - -This extension is designed to work with the [TLS Sync VS Code Workspace extension](../tls-sync-vscode-workspace-extension), providing a seamless experience for managing TLS certificates in a remote development environment. - -The UI extension manages the certificates on the local machine and provides an API for the Workspace extension to synchronize certificates with the remote workspace. - -See [TLS Sync VS Code Workspace extension](../tls-sync-vscode-workspace-extension) for more details on the TLS Sync extensions. diff --git a/vscode-extensions/tls-sync-vscode-ui-extension/assets/extension-icon.png b/vscode-extensions/tls-sync-vscode-ui-extension/assets/extension-icon.png deleted file mode 100644 index ee2bd331df9..00000000000 Binary files a/vscode-extensions/tls-sync-vscode-ui-extension/assets/extension-icon.png and /dev/null differ diff --git a/vscode-extensions/tls-sync-vscode-ui-extension/assets/walkthrough-settings.md b/vscode-extensions/tls-sync-vscode-ui-extension/assets/walkthrough-settings.md deleted file mode 100644 index ebb255bcac5..00000000000 --- a/vscode-extensions/tls-sync-vscode-ui-extension/assets/walkthrough-settings.md +++ /dev/null @@ -1 +0,0 @@ -Change where TLS Sync stores and sync certificates. diff --git a/vscode-extensions/tls-sync-vscode-ui-extension/assets/walkthrough-sync.md b/vscode-extensions/tls-sync-vscode-ui-extension/assets/walkthrough-sync.md deleted file mode 100644 index 01bd1268880..00000000000 --- a/vscode-extensions/tls-sync-vscode-ui-extension/assets/walkthrough-sync.md +++ /dev/null @@ -1 +0,0 @@ -Sync TLS certificates from your local machine to the VSCode remote workspace. diff --git a/vscode-extensions/tls-sync-vscode-ui-extension/config/heft.json b/vscode-extensions/tls-sync-vscode-ui-extension/config/heft.json deleted file mode 100644 index e1dd458ed26..00000000000 --- a/vscode-extensions/tls-sync-vscode-ui-extension/config/heft.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/heft/v0/heft.schema.json", - - "extends": "@rushstack/heft-vscode-extension-rig/profiles/default/config/heft.json" -} diff --git a/vscode-extensions/tls-sync-vscode-ui-extension/config/rig.json b/vscode-extensions/tls-sync-vscode-ui-extension/config/rig.json deleted file mode 100644 index ec33a848348..00000000000 --- a/vscode-extensions/tls-sync-vscode-ui-extension/config/rig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json", - - "rigPackageName": "@rushstack/heft-vscode-extension-rig" -} diff --git a/vscode-extensions/tls-sync-vscode-ui-extension/config/rush-project.json b/vscode-extensions/tls-sync-vscode-ui-extension/config/rush-project.json deleted file mode 100644 index b2453d544bc..00000000000 --- a/vscode-extensions/tls-sync-vscode-ui-extension/config/rush-project.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush-project.schema.json", - "extends": "@rushstack/heft-vscode-extension-rig/profiles/default/config/rush-project.json" -} diff --git a/vscode-extensions/tls-sync-vscode-ui-extension/package.json b/vscode-extensions/tls-sync-vscode-ui-extension/package.json deleted file mode 100644 index d9fabbb2fab..00000000000 --- a/vscode-extensions/tls-sync-vscode-ui-extension/package.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "name": "tls-sync-vscode-ui-extension", - "version": "0.0.0", - "repository": { - "type": "git", - "url": "https://github.com/microsoft/rushstack.git", - "directory": "vscode-extensions/tls-sync-vscode-ui-extension" - }, - "license": "MIT", - "publisher": "RushStack", - "preview": true, - "displayName": "TLS Sync (UI Extension)", - "description": "", - "homepage": "https://github.com/microsoft/rushstack/tree/main/vscode-extensions/tls-sync-vscode-ui-extension", - "icon": "assets/extension-icon.png", - "extensionKind": [ - "ui" - ], - "categories": [ - "Other" - ], - "keywords": [], - "galleryBanner": { - "color": "#f0f0f0", - "theme": "light" - }, - "engines": { - "vscode": "^1.98.0" - }, - "main": "./extension.js", - "scripts": { - "build": "heft build --clean", - "build:watch": "heft build-watch", - "start": "heft start", - "_phase:build": "heft run --only build -- --clean", - "_phase:test": "" - }, - "contributes": { - "commands": [ - { - "command": "tlssync.ui.showLog", - "title": "Show Log", - "category": "TLS Sync" - }, - { - "command": "tlssync.ui.untrustCertificate", - "title": "Untrust Certificate", - "category": "TLS Sync" - }, - { - "command": "tlssync.ui.ensureCertificate", - "title": "Ensure Certificate", - "category": "TLS Sync" - }, - { - "command": "tlssync.ui.sync", - "title": "Sync TLS Certificates", - "category": "TLS Sync" - }, - { - "command": "tlssync.ui.showWalkthrough", - "title": "Show Walkthrough", - "category": "TLS Sync" - }, - { - "command": "tlssync.ui.showSettings", - "title": "Show Settings", - "category": "TLS Sync" - } - ], - "walkthroughs": [ - { - "id": "sync-certificates", - "title": "TLS Sync", - "description": "Sync your debug TLS certificates with the remote machine.", - "featuredFor": [ - ".tlssync" - ], - "steps": [ - { - "id": "runsynccommand", - "title": "Sync Certificates", - "description": "[Sync](command:tlssync.ui.sync)", - "completionEvents": [ - "onContext:tlssync.ui.sync.complete" - ], - "media": { - "markdown": "./media/walkthrough-sync.md" - } - }, - { - "id": "changetlssyncsettings", - "title": "Change Sync Settings", - "description": "[Open Settings](command:tlssync.ui.showSettings)", - "completionEvents": [], - "media": { - "markdown": "./media/walkthrough-settings.md" - } - } - ] - } - ], - "configuration": { - "title": "TLS Sync", - "properties": { - "tlssync.ui.storePath.osx": { - "type": "string", - "title": "UI Extension - TLS Sync Store Path (macOS)", - "description": "[UI Extension] Directory where TLS certificates are read and written." - }, - "tlssync.ui.storePath.windows": { - "type": "string", - "title": "UI Extension - TLS Sync Store Path (Windows)", - "description": "[UI Extension] Directory where TLS certificates are read and written." - }, - "tlssync.ui.storePath.linux": { - "type": "string", - "title": "UI Extension - TLS Sync Store Path (Linux)", - "description": "[UI Extension] Directory where TLS certificates are read and written." - }, - "tlssync.workspace.storePath.osx": { - "type": "string", - "title": "Workspace Extension - TLS Sync Store Path (macOS)", - "description": "[Workspace Extension] Directory where TLS certificates are read and written." - }, - "tlssync.workspace.storePath.windows": { - "type": "string", - "title": "Workspace Extension - TLS Sync Store Path (Windows)", - "description": "[Workspace Extension] Directory where TLS certificates are read and written." - }, - "tlssync.workspace.storePath.linux": { - "type": "string", - "title": "Workspace Extension - TLS Sync Store Path (Linux)", - "description": "[Workspace Extension] Directory where TLS certificates are read and written." - }, - "tlssync.caCertificateFilename": { - "type": "string", - "title": "CA Certificate Filename", - "description": "Filename for the CA certificate." - }, - "tlssync.certificateFilename": { - "type": "string", - "title": "Server Certificate Filename", - "description": "Filename for the server certificate." - }, - "tlssync.keyFilename": { - "type": "string", - "title": "Server Key Filename", - "description": "Filename for the server key." - }, - "tlssync.autoSync": { - "type": "boolean", - "title": "Automatically Sync Certificates", - "default": true, - "description": "Check certificates when extension is activated. Extension is automatically activated when a `.tlssync` file is present in the workspace." - } - } - } - }, - "activationEvents": [ - "workspaceContains:**/.tlssync" - ], - "dependencies": { - "@rushstack/debug-certificate-manager": "workspace:*", - "@rushstack/node-core-library": "workspace:*", - "@rushstack/terminal": "workspace:*", - "@rushstack/tls-sync-vscode-shared": "workspace:*", - "@rushstack/vscode-shared": "workspace:*", - "tslib": "~2.3.1" - }, - "devDependencies": { - "@rushstack/heft-vscode-extension-rig": "workspace:*", - "@rushstack/heft": "workspace:*", - "@types/node": "20.17.19", - "@types/vscode": "^1.63.0", - "@types/webpack-env": "1.18.8" - } -} diff --git a/vscode-extensions/tls-sync-vscode-ui-extension/webpack.config.js b/vscode-extensions/tls-sync-vscode-ui-extension/webpack.config.js deleted file mode 100644 index bc6dfe67040..00000000000 --- a/vscode-extensions/tls-sync-vscode-ui-extension/webpack.config.js +++ /dev/null @@ -1,23 +0,0 @@ -// @ts-check -/* eslint-env es6 */ - -'use strict'; - -const { - createExtensionConfig -} = require('@rushstack/heft-vscode-extension-rig/profiles/default/webpack.config.base'); -const path = require('node:path'); - -function createConfig({ production, webpack }) { - const config = createExtensionConfig({ - production, - webpack, - entry: { - extension: './lib/extension.js' - }, - outputPath: path.resolve(__dirname, 'dist', 'vsix', 'unpacked') - }); - return config; -} - -module.exports = createConfig; diff --git a/vscode-extensions/tls-sync-vscode-workspace-extension/.npmignore b/vscode-extensions/tls-sync-vscode-workspace-extension/.npmignore deleted file mode 100644 index dcf329e5ffa..00000000000 --- a/vscode-extensions/tls-sync-vscode-workspace-extension/.npmignore +++ /dev/null @@ -1,2 +0,0 @@ -# Ignore all files by default, to avoid accidentally publishing unintended files. -** diff --git a/vscode-extensions/tls-sync-vscode-workspace-extension/LICENSE b/vscode-extensions/tls-sync-vscode-workspace-extension/LICENSE deleted file mode 100644 index cee4fe2d135..00000000000 --- a/vscode-extensions/tls-sync-vscode-workspace-extension/LICENSE +++ /dev/null @@ -1,24 +0,0 @@ -tls-sync-vscode-workspace-extension - -Copyright (c) Microsoft Corporation. All rights reserved. - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vscode-extensions/tls-sync-vscode-workspace-extension/README.md b/vscode-extensions/tls-sync-vscode-workspace-extension/README.md deleted file mode 100644 index eb99cbde6e9..00000000000 --- a/vscode-extensions/tls-sync-vscode-workspace-extension/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# TLS Sync VS Code Extension (Remote / Workspace Extension) - -This extension is designed to work with the [TLS Sync VS Code UI extension](../tls-sync-vscode-ui-extension), providing a seamless experience for managing TLS certificates in a remote workspace environment. - -The Workspace extension gets the client's debug certificate from the UI extension and writes it to the remote workspace. diff --git a/vscode-extensions/tls-sync-vscode-workspace-extension/assets/extension-icon.png b/vscode-extensions/tls-sync-vscode-workspace-extension/assets/extension-icon.png deleted file mode 100644 index ee2bd331df9..00000000000 Binary files a/vscode-extensions/tls-sync-vscode-workspace-extension/assets/extension-icon.png and /dev/null differ diff --git a/vscode-extensions/tls-sync-vscode-workspace-extension/config/heft.json b/vscode-extensions/tls-sync-vscode-workspace-extension/config/heft.json deleted file mode 100644 index e1dd458ed26..00000000000 --- a/vscode-extensions/tls-sync-vscode-workspace-extension/config/heft.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/heft/v0/heft.schema.json", - - "extends": "@rushstack/heft-vscode-extension-rig/profiles/default/config/heft.json" -} diff --git a/vscode-extensions/tls-sync-vscode-workspace-extension/config/rig.json b/vscode-extensions/tls-sync-vscode-workspace-extension/config/rig.json deleted file mode 100644 index ec33a848348..00000000000 --- a/vscode-extensions/tls-sync-vscode-workspace-extension/config/rig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json", - - "rigPackageName": "@rushstack/heft-vscode-extension-rig" -} diff --git a/vscode-extensions/tls-sync-vscode-workspace-extension/config/rush-project.json b/vscode-extensions/tls-sync-vscode-workspace-extension/config/rush-project.json deleted file mode 100644 index b2453d544bc..00000000000 --- a/vscode-extensions/tls-sync-vscode-workspace-extension/config/rush-project.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush-project.schema.json", - "extends": "@rushstack/heft-vscode-extension-rig/profiles/default/config/rush-project.json" -} diff --git a/vscode-extensions/tls-sync-vscode-workspace-extension/eslint.config.js b/vscode-extensions/tls-sync-vscode-workspace-extension/eslint.config.js deleted file mode 100644 index eac79367926..00000000000 --- a/vscode-extensions/tls-sync-vscode-workspace-extension/eslint.config.js +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. -// See LICENSE in the project root for license information. - -const nodeTrustedToolProfile = require('@rushstack/heft-vscode-extension-rig/profiles/default/includes/eslint/flat/profile/node-trusted-tool'); -const friendlyLocalsMixin = require('@rushstack/heft-vscode-extension-rig/profiles/default/includes/eslint/flat/mixins/friendly-locals'); - -module.exports = [...nodeTrustedToolProfile, ...friendlyLocalsMixin]; diff --git a/vscode-extensions/tls-sync-vscode-workspace-extension/package.json b/vscode-extensions/tls-sync-vscode-workspace-extension/package.json deleted file mode 100644 index 5abb8235b56..00000000000 --- a/vscode-extensions/tls-sync-vscode-workspace-extension/package.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "name": "tls-sync-vscode-workspace-extension", - "version": "0.0.0", - "repository": { - "type": "git", - "url": "https://github.com/microsoft/rushstack.git", - "directory": "vscode-extensions/tls-sync-vscode-workspace-extension" - }, - "license": "MIT", - "publisher": "RushStack", - "preview": true, - "displayName": "TLS Sync (Workspace Extension)", - "description": "", - "homepage": "https://github.com/microsoft/rushstack/tree/main/vscode-extensions/tls-sync-vscode-workspace-extension", - "icon": "assets/extension-icon.png", - "extensionKind": [ - "workspace" - ], - "categories": [ - "Other" - ], - "keywords": [], - "galleryBanner": { - "color": "#f0f0f0", - "theme": "light" - }, - "engines": { - "vscode": "^1.98.0" - }, - "main": "./extension.js", - "scripts": { - "build": "heft build --clean", - "build:watch": "heft build-watch", - "start": "heft start", - "_phase:build": "heft run --only build -- --clean", - "_phase:test": "" - }, - "contributes": { - "commands": [ - { - "command": "tlssync.workspace.showLog", - "title": "Show Log (Workspace)", - "category": "TLS Sync" - } - ] - }, - "activationEvents": [ - "onCommand:tlssync.workspace.ping", - "onCommand:tlssync.workspace.sync", - "workspaceContains:**/.tlssync" - ], - "dependencies": { - "@rushstack/debug-certificate-manager": "workspace:*", - "@rushstack/node-core-library": "workspace:*", - "@rushstack/terminal": "workspace:*", - "@rushstack/tls-sync-vscode-shared": "workspace:*", - "@rushstack/vscode-shared": "workspace:*", - "tslib": "~2.3.1" - }, - "devDependencies": { - "@rushstack/heft-vscode-extension-rig": "workspace:*", - "@rushstack/heft": "workspace:*", - "@types/node": "20.17.19", - "@types/vscode": "^1.63.0", - "@types/webpack-env": "1.18.8" - } -} diff --git a/vscode-extensions/tls-sync-vscode-workspace-extension/src/extension.ts b/vscode-extensions/tls-sync-vscode-workspace-extension/src/extension.ts deleted file mode 100644 index 30e18838981..00000000000 --- a/vscode-extensions/tls-sync-vscode-workspace-extension/src/extension.ts +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. -// See LICENSE in the project root for license information. - -import * as vscode from 'vscode'; - -import { CertificateStore, type ICertificate } from '@rushstack/debug-certificate-manager'; -import { Terminal } from '@rushstack/terminal'; - -import { VScodeOutputChannelTerminalProvider } from '@rushstack/vscode-shared/lib/VScodeOutputChannelTerminalProvider'; -import { getCertificateStore } from '@rushstack/tls-sync-vscode-shared/lib/certificates'; -import { - WORKSPACE_COMMAND_PING, - WORKSPACE_COMMAND_SHOW_LOG, - WORKSPACE_COMMAND_SYNC, - WORKSPACE_EXTENSION_DISPLAY_NAME -} from '@rushstack/tls-sync-vscode-shared/lib/constants'; - -import { version } from '../package.json'; - -/* - * This extension provides commands to sync debug TLS certificates with the UI extension. This allows for VS Code - * remotes to use the same certificates as the local machine. - */ - -export function activate(context: vscode.ExtensionContext): void { - const outputChannel: vscode.OutputChannel = vscode.window.createOutputChannel( - WORKSPACE_EXTENSION_DISPLAY_NAME - ); - const terminalProvider: VScodeOutputChannelTerminalProvider = new VScodeOutputChannelTerminalProvider( - outputChannel, - { - verboseEnabled: true, - debugEnabled: true - } - ); - const terminal: Terminal = new Terminal(terminalProvider); - terminal.writeLine(`${WORKSPACE_EXTENSION_DISPLAY_NAME} output channel initialized.`); - - async function handleShowLog(): Promise { - outputChannel.show(); - } - - async function handleSyncCertificates(certificatesFromUI: ICertificate): Promise { - const certificateStore: CertificateStore = getCertificateStore(terminal, 'workspace'); - - void vscode.window.showInformationMessage(`Synchronizing TLS certificates.`); - terminal.writeLine('Starting certificate synchronization...'); - try { - if (!certificatesFromUI) { - void vscode.window.showErrorMessage( - 'No certificates found in the UI extension. Please ensure the UI extension is installed and configured.' - ); - terminal.writeLine('No certificates found in the UI extension. Synchronization aborted.'); - return false; - } - - let isSynchronized: boolean = false; - isSynchronized = - certificateStore.caCertificateData === certificatesFromUI.pemCaCertificate && - certificateStore.certificateData === certificatesFromUI.pemCertificate && - certificateStore.keyData === certificatesFromUI.pemKey; - if (isSynchronized) { - void vscode.window.showInformationMessage( - 'Local certificates are already synchronized with UI certificates.' - ); - return true; - } - - certificateStore.caCertificateData = certificatesFromUI.pemCaCertificate; - terminal.writeLine(`Writing CA certificate to ${certificateStore.caCertificatePath}...`); - - certificateStore.certificateData = certificatesFromUI.pemCertificate; - terminal.writeLine(`Writing TLS server certificates to ${certificateStore.certificateData}...`); - - certificateStore.keyData = certificatesFromUI.pemKey; - terminal.writeLine(`Writing TLS private key to ${certificateStore.keyPath}...`); - - terminal.writeLine(`Certificates synchronized successfully.`); - return true; - } catch (err) { - const message: string = `Error synchronizing certificates: ${ - err instanceof Error ? err.message : 'Unknown error' - }`; - terminal.writeLine(message); - void vscode.window.showErrorMessage(message); - return false; - } - } - - function handlePing(): { version: string } { - return { - version - }; - } - - context.subscriptions.push( - outputChannel, - vscode.commands.registerCommand(WORKSPACE_COMMAND_PING, handlePing), - vscode.commands.registerCommand(WORKSPACE_COMMAND_SHOW_LOG, handleShowLog), - vscode.commands.registerCommand(WORKSPACE_COMMAND_SYNC, handleSyncCertificates) - ); -} - -export function deactivate(): void {} diff --git a/vscode-extensions/tls-sync-vscode-workspace-extension/tsconfig.json b/vscode-extensions/tls-sync-vscode-workspace-extension/tsconfig.json deleted file mode 100644 index 1226387ecf8..00000000000 --- a/vscode-extensions/tls-sync-vscode-workspace-extension/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "./node_modules/@rushstack/heft-vscode-extension-rig/profiles/default/tsconfig-base.json" -}