mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Refactoring ssh-keygen function (#1533)
This commit is contained in:
parent
9c350311e8
commit
5a6cde1446
@ -59,7 +59,6 @@
|
||||
"raw-body":"2.2.0",
|
||||
"semver": "5.3.0",
|
||||
"sentiment":"2.1.0",
|
||||
"ssh-keygen":"0.4.1",
|
||||
"uglify-js":"3.0.20",
|
||||
"when": "3.7.8",
|
||||
"ws": "1.1.1",
|
||||
|
@ -23,6 +23,7 @@ var crypto = require('crypto');
|
||||
var storageSettings = require("../settings");
|
||||
var util = require("../util");
|
||||
var gitTools = require("./git");
|
||||
var sshTools = require("./ssh");
|
||||
|
||||
var Projects = require("./Project");
|
||||
|
||||
@ -89,6 +90,7 @@ function init(_settings, _runtime) {
|
||||
projectsEnabled = false;
|
||||
} else {
|
||||
Projects.init(settings,runtime);
|
||||
sshTools.init(settings,runtime);
|
||||
projectsDir = fspath.join(settings.userDir,"projects");
|
||||
if (!settings.readOnly) {
|
||||
return fs.ensureDir(projectsDir)
|
||||
|
80
red/runtime/storage/localfilesystem/projects/ssh.js
Normal file
80
red/runtime/storage/localfilesystem/projects/ssh.js
Normal file
@ -0,0 +1,80 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var exec = require('child_process').exec;
|
||||
var spawn = require('child_process').spawn;
|
||||
|
||||
var sshkeygenCommand = "ssh-keygen";
|
||||
|
||||
var log;
|
||||
|
||||
function runSshKeygenCommand(args,cwd,env) {
|
||||
// console.log("[run ssh-keygen] args:", args);
|
||||
return new Promise(function(resolve, reject) {
|
||||
var child = spawn(sshkeygenCommand, args, {cwd: cwd, detached: true, env: env});
|
||||
var stdout = "";
|
||||
var stderr = "";
|
||||
|
||||
child.stdout.on('data', function(data) {
|
||||
stdout += data;
|
||||
});
|
||||
child.stderr.on('data', function(data) {
|
||||
stderr += data;
|
||||
});
|
||||
child.on('close', function(code, signal) {
|
||||
if (code !== 0) {
|
||||
var err = new Error(stderr);
|
||||
err.stdout = stdout;
|
||||
err.stderr = stderr;
|
||||
if (/passphrase is too short/.test(stderr)) {
|
||||
err.code = "key_passphrase_too_short";
|
||||
} else if(/Key must at least be 1024 bits/.test(stderr)) {
|
||||
err.code = "key_length_too_short";
|
||||
}
|
||||
reject(err);
|
||||
}
|
||||
else {
|
||||
resolve(stdout);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function init(_settings, _runtime) {
|
||||
log = _runtime.log;
|
||||
}
|
||||
|
||||
function generateKey(options) {
|
||||
var args = ['-q', '-t', 'rsa'];
|
||||
if (options.size) {
|
||||
args.push('-b', options.size);
|
||||
}
|
||||
if (options.location) {
|
||||
args.push('-f', options.location);
|
||||
}
|
||||
if (options.comment) {
|
||||
args.push('-C', options.comment);
|
||||
}
|
||||
if (options.password) {
|
||||
args.push('-N', options.password);
|
||||
}
|
||||
return runSshKeygenCommand(args,__dirname);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
init: init,
|
||||
generateKey: generateKey,
|
||||
};
|
@ -17,7 +17,7 @@
|
||||
var fs = require('fs-extra');
|
||||
var when = require('when');
|
||||
var fspath = require("path");
|
||||
var keygen = require('ssh-keygen');
|
||||
var sshTools = require("./projects/ssh");
|
||||
|
||||
var settings;
|
||||
var runtime;
|
||||
@ -97,26 +97,12 @@ function generateSSHKey(username, options) {
|
||||
} else {
|
||||
var comment = options.comment || "";
|
||||
var password = options.password || "";
|
||||
if (password.length > 0 && password.length < 5) {
|
||||
var e2 = new Error("SSH Key passphrase too short");
|
||||
e2.code = "key_passphrase_too_short";
|
||||
throw e2;
|
||||
}
|
||||
var size = options.size || 2048;
|
||||
var sshKeyFileBasename = username + '_' + name;
|
||||
var privateKeyFilePath = fspath.join(sshkeyDir, sshKeyFileBasename);
|
||||
return generateSSHKeyPair(name, privateKeyFilePath, comment, password, size)
|
||||
}
|
||||
})
|
||||
// .then(function(keyfile_name) {
|
||||
// return checkSSHKeyFileAndGetPublicKeyFileName(username, name)
|
||||
// .then(function() {
|
||||
// return keyfile_name;
|
||||
// })
|
||||
// .catch(function(err) {
|
||||
// throw new Error('Failed to generate ssh key files');
|
||||
// });
|
||||
// });
|
||||
}
|
||||
|
||||
function deleteSSHKey(username, name) {
|
||||
@ -162,27 +148,22 @@ function deleteSSHKeyFiles(username, name) {
|
||||
return Promise.all([
|
||||
fs.remove(privateKeyFilePath),
|
||||
fs.remove(publicKeyFilePath)
|
||||
]);
|
||||
])
|
||||
.then(function() {
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
function generateSSHKeyPair(name, privateKeyPath, comment, password, size) {
|
||||
log.trace("ssh-keygen["+[name,privateKeyPath,comment,size,"hasPassword?"+!!password].join(",")+"]");
|
||||
return new Promise(function(resolve, reject) {
|
||||
keygen({
|
||||
location: privateKeyPath,
|
||||
comment: comment,
|
||||
password: password,
|
||||
size: size
|
||||
}, function(err, out) {
|
||||
if ( err ) {
|
||||
err.code = "key_generation_failed";
|
||||
reject(err);
|
||||
}
|
||||
else {
|
||||
resolve(name);
|
||||
}
|
||||
});
|
||||
});
|
||||
return sshTools.generateKey({location: privateKeyPath, comment: comment, password: password, size: size})
|
||||
.then(function(stdout) {
|
||||
return name;
|
||||
})
|
||||
.catch(function(err) {
|
||||
log.log('[SSHKey generation] error:', err);
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
@ -29,6 +29,7 @@ describe("storage/localfilesystem/sshkeys", function() {
|
||||
log:{
|
||||
_:function() { return "placeholder message"},
|
||||
info: function() { },
|
||||
log: function() { },
|
||||
trace: function() { }
|
||||
}
|
||||
};
|
||||
@ -61,7 +62,6 @@ describe("storage/localfilesystem/sshkeys", function() {
|
||||
localfilesystem.init(mockSettings, mockRuntime).then(function() {
|
||||
sshkeys.init(mockSettings, mockRuntime).then(function() {
|
||||
sshkeys.listSSHKeys(username).then(function(retObj) {
|
||||
console.log('retObj:', retObj);
|
||||
retObj.should.be.instanceOf(Array).and.have.lengthOf(0);
|
||||
done();
|
||||
}).catch(function(err) {
|
||||
@ -246,7 +246,31 @@ describe("storage/localfilesystem/sshkeys", function() {
|
||||
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
||||
var username = 'test';
|
||||
var options = {
|
||||
email: 'test@test.com',
|
||||
name: 'test-key01'
|
||||
};
|
||||
localfilesystem.init(mockSettings, mockRuntime).then(function() {
|
||||
sshkeys.init(mockSettings, mockRuntime).then(function() {
|
||||
sshkeys.generateSSHKey(username, options).then(function(retObj) {
|
||||
retObj.should.be.equal(options.name);
|
||||
fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name)).should.be.true();
|
||||
fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name+'.pub')).should.be.true();
|
||||
done();
|
||||
}).catch(function(err) {
|
||||
done(err);
|
||||
});
|
||||
}).catch(function(err) {
|
||||
done(err);
|
||||
});
|
||||
}).catch(function(err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
it('should generate sshkey file with only comment data', function(done) {
|
||||
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
||||
var username = 'test';
|
||||
var options = {
|
||||
comment: 'test@test.com',
|
||||
name: 'test-key01'
|
||||
};
|
||||
localfilesystem.init(mockSettings, mockRuntime).then(function() {
|
||||
@ -271,7 +295,7 @@ describe("storage/localfilesystem/sshkeys", function() {
|
||||
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
||||
var username = 'test';
|
||||
var options = {
|
||||
email: 'test@test.com',
|
||||
comment: 'test@test.com',
|
||||
name: 'test-key01',
|
||||
password: 'testtest'
|
||||
};
|
||||
@ -297,7 +321,7 @@ describe("storage/localfilesystem/sshkeys", function() {
|
||||
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
||||
var username = 'test';
|
||||
var options = {
|
||||
email: 'test@test.com',
|
||||
comment: 'test@test.com',
|
||||
name: 'test-key01',
|
||||
size: 4096
|
||||
};
|
||||
@ -324,7 +348,7 @@ describe("storage/localfilesystem/sshkeys", function() {
|
||||
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
||||
var username = 'test';
|
||||
var options = {
|
||||
email: 'test@test.com',
|
||||
comment: 'test@test.com',
|
||||
name: 'test-key01',
|
||||
password: 'testtest',
|
||||
size: 4096
|
||||
@ -352,19 +376,52 @@ describe("storage/localfilesystem/sshkeys", function() {
|
||||
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
||||
var username = 'test';
|
||||
var options = {
|
||||
email: 'test@test.com',
|
||||
comment: 'test@test.com',
|
||||
name: 'test-key01',
|
||||
size: 3333
|
||||
size: 1023
|
||||
};
|
||||
localfilesystem.init(mockSettings, mockRuntime).then(function() {
|
||||
sshkeys.init(mockSettings, mockRuntime).then(function() {
|
||||
sshkeys.generateSSHKey(username, options).then(function(retObj) {
|
||||
retObj.should.be.equal(options.name);
|
||||
fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name)).should.be.true();
|
||||
fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name+'.pub')).should.be.true();
|
||||
done();
|
||||
done(new Error('Does NOT throw error!'));
|
||||
}).catch(function(err) {
|
||||
done(err);
|
||||
try {
|
||||
err.should.have.have.property('code', 'key_length_too_short');
|
||||
done();
|
||||
}
|
||||
catch (error) {
|
||||
done(error);
|
||||
}
|
||||
});
|
||||
}).catch(function(err) {
|
||||
done(err);
|
||||
});
|
||||
}).catch(function(err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
it('should not generate sshkey file with illegal password', function(done) {
|
||||
this.timeout(5000);
|
||||
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
||||
var username = 'test';
|
||||
var options = {
|
||||
comment: 'test@test.com',
|
||||
name: 'test-key01',
|
||||
password: 'aa'
|
||||
};
|
||||
localfilesystem.init(mockSettings, mockRuntime).then(function() {
|
||||
sshkeys.init(mockSettings, mockRuntime).then(function() {
|
||||
sshkeys.generateSSHKey(username, options).then(function(retObj) {
|
||||
done(new Error('Does NOT throw error!'));
|
||||
}).catch(function(err) {
|
||||
try {
|
||||
err.should.have.have.property('code', 'key_passphrase_too_short');
|
||||
done();
|
||||
}
|
||||
catch (error) {
|
||||
done(error);
|
||||
}
|
||||
});
|
||||
}).catch(function(err) {
|
||||
done(err);
|
||||
|
Loading…
Reference in New Issue
Block a user