diff --git a/packages/core/src/awsService/ec2/sshKeyPair.ts b/packages/core/src/awsService/ec2/sshKeyPair.ts index 1b7a461655d..0bc01b12367 100644 --- a/packages/core/src/awsService/ec2/sshKeyPair.ts +++ b/packages/core/src/awsService/ec2/sshKeyPair.ts @@ -8,6 +8,7 @@ import { ToolkitError } from '../../shared/errors' import { tryRun } from '../../shared/utilities/pathFind' import { Timeout } from '../../shared/utilities/timeoutUtils' import { findAsync } from '../../shared/utilities/collectionUtils' +import { RunParameterContext } from '../../shared/utilities/processUtils' type sshKeyType = 'rsa' | 'ed25519' @@ -17,7 +18,7 @@ export class SshKeyPair { private deleted: boolean = false private constructor( - private keyPath: string, + private readonly keyPath: string, lifetime: number ) { this.publicKeyPath = `${keyPath}.pub` @@ -29,10 +30,6 @@ export class SshKeyPair { } public static async getSshKeyPair(keyPath: string, lifetime: number) { - // Overwrite key if already exists - if (await fs.existsFile(keyPath)) { - await fs.delete(keyPath) - } await SshKeyPair.generateSshKeyPair(keyPath) return new SshKeyPair(keyPath, lifetime) } @@ -50,7 +47,12 @@ export class SshKeyPair { * @param keyType type of key to generate. */ public static async tryKeyGen(keyPath: string, keyType: sshKeyType): Promise { - return !(await tryRun('ssh-keygen', ['-t', keyType, '-N', '', '-q', '-f', keyPath], 'yes', 'unknown key type')) + const overrideKeys = async (_t: string, proc: RunParameterContext) => { + await proc.send('yes') + } + return !(await tryRun('ssh-keygen', ['-t', keyType, '-N', '', '-q', '-f', keyPath], 'yes', 'unknown key type', { + onStdout: overrideKeys, + })) } public static async tryKeyTypes(keyPath: string, keyTypes: sshKeyType[]): Promise { diff --git a/packages/core/src/shared/utilities/pathFind.ts b/packages/core/src/shared/utilities/pathFind.ts index a61d081c0c4..585dd2cde93 100644 --- a/packages/core/src/shared/utilities/pathFind.ts +++ b/packages/core/src/shared/utilities/pathFind.ts @@ -6,7 +6,7 @@ import * as vscode from 'vscode' import * as path from 'path' import fs from '../../shared/fs/fs' -import { ChildProcess } from './processUtils' +import { ChildProcess, ChildProcessOptions } from './processUtils' import { GitExtension } from '../extensions/git' import { Settings } from '../settings' import { getLogger } from '../logger/logger' @@ -30,10 +30,11 @@ export async function tryRun( p: string, args: string[], logging: 'yes' | 'no' | 'noresult' = 'yes', - expected?: string + expected?: string, + opt?: ChildProcessOptions ): Promise { const proc = new ChildProcess(p, args, { logging: 'no' }) - const r = await proc.run() + const r = await proc.run(opt) const ok = r.exitCode === 0 && (expected === undefined || r.stdout.includes(expected)) if (logging === 'noresult') { getLogger().info('tryRun: %s: %s', ok ? 'ok' : 'failed', proc) diff --git a/packages/core/src/shared/utilities/processUtils.ts b/packages/core/src/shared/utilities/processUtils.ts index 7003cc230a7..3e78aa0525c 100644 --- a/packages/core/src/shared/utilities/processUtils.ts +++ b/packages/core/src/shared/utilities/processUtils.ts @@ -9,11 +9,13 @@ import * as logger from '../logger' import { Timeout, CancellationError, waitUntil } from './timeoutUtils' import { isWeb } from '../extensionGlobals' -interface RunParameterContext { +export interface RunParameterContext { /** Reports an error parsed from the stdin/stdout streams. */ reportError(err: string | Error): void /** Attempts to stop the running process. See {@link ChildProcess.stop}. */ stop(force?: boolean, signal?: string): void + /** Send string to stdin */ + send(text: string): Promise /** The active `Timeout` object (if applicable). */ readonly timeout?: Timeout /** The logger being used by the process. */ @@ -161,6 +163,7 @@ export class ChildProcess { timeout, logger: this.#log, stop: this.stop.bind(this), + send: this.send.bind(this), reportError: (err) => errorHandler(err instanceof Error ? err : new Error(err)), } diff --git a/packages/core/src/test/awsService/ec2/model.test.ts b/packages/core/src/test/awsService/ec2/model.test.ts index 98c0103c06e..36a7895a35f 100644 --- a/packages/core/src/test/awsService/ec2/model.test.ts +++ b/packages/core/src/test/awsService/ec2/model.test.ts @@ -139,8 +139,8 @@ describe('Ec2ConnectClient', function () { instanceId: 'test-id', region: 'test-region', } - const mockKeys = await SshKeyPair.getSshKeyPair('', 30000) - await client.sendSshKeyToInstance(testSelection, mockKeys, '') + const mockKeys = await SshKeyPair.getSshKeyPair('fakeDir', 30000) + await client.sendSshKeyToInstance(testSelection, mockKeys, 'test-user') sinon.assert.calledWith(sendCommandStub, testSelection.instanceId, 'AWS-RunShellScript') sinon.restore() }) diff --git a/packages/core/src/test/awsService/ec2/sshKeyPair.test.ts b/packages/core/src/test/awsService/ec2/sshKeyPair.test.ts index d0069cdc5a6..3051aea534e 100644 --- a/packages/core/src/test/awsService/ec2/sshKeyPair.test.ts +++ b/packages/core/src/test/awsService/ec2/sshKeyPair.test.ts @@ -33,7 +33,7 @@ describe('SshKeyUtility', async function () { }) after(async function () { - await keyPair.delete() + await fs.delete(temporaryDirectory, { recursive: true, force: true }) clock.uninstall() sinon.restore() }) diff --git a/packages/core/src/test/techdebt.test.ts b/packages/core/src/test/techdebt.test.ts index 4818da88070..d83a8d68c85 100644 --- a/packages/core/src/test/techdebt.test.ts +++ b/packages/core/src/test/techdebt.test.ts @@ -53,6 +53,6 @@ describe('tech debt', function () { // Monitor telemtry to determine removal or snooze // toolkit_showNotification.id = sessionSeparation // auth_modifyConnection.action = deleteProfile OR auth_modifyConnection.source contains CodeCatalyst - fixByDate('2024-9-30', 'Remove the edge case code from the commit that this test is a part of.') + fixByDate('2024-10-30', 'Remove the edge case code from the commit that this test is a part of.') }) })