Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #519 - Implement SSH Key Generation via oputil #578

Merged
merged 5 commits into from
Nov 25, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions core/oputil/oputil_help.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Commands:
config Configuration management
fb File base management
mb Message base management
ssh SSH key management
`,
User: `usage: oputil.js user <action> [<arguments>]

Expand Down Expand Up @@ -219,6 +220,11 @@ qwk-export arguments:
TIMESTAMP.
--no-qwke Disable QWKE extensions.
--no-synchronet Disable Synchronet style extensions.
`,
SSH: `usage: oputil.js ssh <action>

Actions:
create Create new SSH Keys
`,
});

Expand Down
3 changes: 3 additions & 0 deletions core/oputil/oputil_main.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const handleFileBaseCommand = require('./oputil_file_base.js').handleFileBaseCom
const handleMessageBaseCommand =
require('./oputil_message_base.js').handleMessageBaseCommand;
const handleConfigCommand = require('./oputil_config.js').handleConfigCommand;
const handleSSHKeyCommand = require('./oputil_ssh_key.js').handleSSHKeyCommand;
const getHelpFor = require('./oputil_help.js').getHelpFor;

module.exports = function () {
Expand All @@ -32,6 +33,8 @@ module.exports = function () {
return handleFileBaseCommand();
case 'mb':
return handleMessageBaseCommand();
case 'ssh':
return handleSSHKeyCommand();
default:
return printUsageAndSetExitCode(getHelpFor('General'), ExitCodes.BAD_COMMAND);
}
Expand Down
158 changes: 158 additions & 0 deletions core/oputil/oputil_ssh_key.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
/* jslint node: true */
/* eslint-disable no-console */
'use strict';

// ENiGMA½
const initConfigAndDatabases = require('./oputil_common.js').initConfigAndDatabases;

const {
printUsageAndSetExitCode,
argv,
ExitCodes,
getAnswers,
} = require('./oputil_common.js');
const getHelpFor = require('./oputil_help.js').getHelpFor;

// deps
const async = require('async');
const fs = require('graceful-fs');
const exec = require('child_process').exec;
const inq = require('inquirer');
const _ = require('lodash');


exports.handleSSHKeyCommand = handleSSHKeyCommand;

const ConfigIncludeKeys = [
'loginServers.ssh',
'loginServers.ssh.privateKeyPem',
];

const MINIMUM_PASSWORD_LENGTH = 8;
const QUESTIONS = {
Create: [
{
name: 'createNew',
message: 'Generate New SSH Keys?',
type: 'confirm',
default: false,
},
{
name: 'password',
message: 'SSL Password:',
default: "",
when: answers => answers.createNew,
},
],
};

function execute(ui, command) {
ui.log.write("Ping!");
ui.log.write(command);
exec(
command,
function (error, stdout, stderr) {
ui.log.write(error);

if (error) {
const reason = error ? error.message : 'OpenSSL Error';
logDebug(
{
reason: reason,
cmd: util.cmd,
args: args
},
`openssl command failed`
);
}
else {
ui.log.write("SSH Keys Generated")
}
}
);
}

function createNew(cb) {
const ui = new inq.ui.BottomBar();

let sslPassword;
crhultay marked this conversation as resolved.
Show resolved Hide resolved

async.waterfall(
[
function init(callback) {
return initConfigAndDatabases(callback);
},
function create(configuration, callback) {
getAnswers(QUESTIONS.Create, answers => {
if (!answers.createNew) {
return callback('exit');
}

// Get Answer Value
sslPassword = answers.password;
if (!sslPassword || sslPassword.replaceAll(" ", "") == "") {
crhultay marked this conversation as resolved.
Show resolved Hide resolved
ui.log.write('Password must be set.');

return callback('exit');
}
if (sslPassword.length < MINIMUM_PASSWORD_LENGTH) {
ui.log.write(`Password must be at least ${MINIMUM_PASSWORD_LENGTH} characters.`);

return callback('exit');
}

// Check if Keyfiles Exist
const sshKeyPath = "config/security/";
const sshKeyFilename = "ssh_private_key.pem";
const targetKeyFile = sshKeyPath + sshKeyFilename;

// Check if Keyfile Exists
if (fs.existsSync(targetKeyFile)) {
ui.log.write(`${targetKeyFile} already exists.`)

return callback('exit');
}

ui.log.write(`Creating SSH Key: ${targetKeyFile}`);

// Create Dir
if (!fs.existsSync(sshKeyPath)) {
crhultay marked this conversation as resolved.
Show resolved Hide resolved
ui.log.write(`Creating Directory: ${sshKeyPath}`);
exec(`mkdir -p ${sshKeyPath}`);
crhultay marked this conversation as resolved.
Show resolved Hide resolved
}

// Check if OpenSSL binary is installed
const binaryPath = "/usr/bin/openssl";
crhultay marked this conversation as resolved.
Show resolved Hide resolved
if (!fs.existsSync(binaryPath)) {
ui.log.write(`${binaryPath} was not found in your path`);

return callback('exit');
}

// Create SSH Keys
const command = `${binaryPath} genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537 | openssl rsa -out ./${targetKeyFile} -aes128 -traditional -passout pass:`;
execute(ui, `${command}${sslPassword}`);
});
},
],
err => {
return cb(err, configPath, config);
}
);
}

function handleSSHKeyCommand() {
if (true === argv.help) {
return printUsageAndSetExitCode(getHelpFor('SSH'), ExitCodes.ERROR);
}

const action = argv._[1];

switch (action) {
case 'create':
return createNew();

default:
return printUsageAndSetExitCode(getHelpFor('SSH'), ExitCodes.ERROR);
}
}
Loading