alwaysai
Version:
The alwaysAI command-line interface (CLI)
104 lines (98 loc) • 3.22 kB
text/typescript
import { existsSync, writeFileSync } from 'fs';
import { execFile } from 'child_process';
import { promisify } from 'util';
import { CliTerseError } from '@alwaysai/alwayscli';
import mkdirp = require('mkdirp');
import { dirname } from 'path';
import {
PRIVATE_KEY_FILE_PRETTY_PATH,
PRIVATE_KEY_FILE_PATH,
PUBLIC_KEY_FILE_PATH,
PUBLIC_KEY_FILE_PRETTY_PATH
} from '../../paths';
import { ALWAYSAI_OS_PLATFORM } from '../../environment';
import { UnableToProceedWithoutMessage, Spinner } from '../../util';
import { confirmWriteFilePromptComponent } from './confirm-write-file-prompt-component';
const WRITE_MESSAGE = `Write ${PRIVATE_KEY_FILE_PRETTY_PATH}`;
export const PUBLIC_KEY_FILE_COMMENT = 'Generated by the alwaysAI CLI';
export async function findOrWritePrivateKeyFileComponent(props: {
yes: boolean;
}) {
const { yes } = props;
if (existsSync(PRIVATE_KEY_FILE_PATH)) {
// Make sure that the public part of the key is in place. It should be if it
// was created with ssh-keygen. It might not be if the private key was
// copied to this host from elsewhere.
if (!existsSync(PUBLIC_KEY_FILE_PATH)) {
const confirmed =
yes ||
(await confirmWriteFilePromptComponent({
fileName: PUBLIC_KEY_FILE_PRETTY_PATH,
description: 'Public key file'
}));
if (!confirmed) {
throw new CliTerseError(
UnableToProceedWithoutMessage(PUBLIC_KEY_FILE_PATH)
);
}
const spinner = Spinner(`Write ${PUBLIC_KEY_FILE_PRETTY_PATH}`);
try {
const { stdout } = await promisify(execFile)('ssh-keygen', [
'-y',
'-f',
PRIVATE_KEY_FILE_PATH
]);
await writeFileSync(PUBLIC_KEY_FILE_PATH, stdout, { flag: 'wx' });
spinner.succeed();
} catch (exception) {
if (exception.code === 'EEXIST') {
spinner.succeed();
// Unlikely scenario that the file did not exist but now does
} else {
spinner.fail();
throw exception;
}
}
}
} else {
// !exists
const confirmed =
yes ||
(await confirmWriteFilePromptComponent({
fileName: PRIVATE_KEY_FILE_PRETTY_PATH,
description: 'Private key file'
}));
if (!confirmed) {
throw new CliTerseError(
UnableToProceedWithoutMessage(PRIVATE_KEY_FILE_PRETTY_PATH)
);
}
// ssh-keygen does not automatically create the .ssh directory on Windows if
// it does not already exist. On non-Windows let's just let ssh-keygen
// create the directory so that it has proper permissions.
if (ALWAYSAI_OS_PLATFORM === 'win32') {
mkdirp.sync(dirname(PRIVATE_KEY_FILE_PATH));
}
// ssh-keygen creates the private key file and the corresponding .pub file
const spinner = Spinner(WRITE_MESSAGE);
try {
await promisify(execFile)('ssh-keygen', [
'-q',
'-b',
'2048',
'-t',
'rsa',
'-N',
'',
'-C',
PUBLIC_KEY_FILE_COMMENT,
'-f',
PRIVATE_KEY_FILE_PATH
]);
spinner.succeed();
} catch (exception) {
spinner.fail();
throw exception;
}
}
}