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",
|
"raw-body":"2.2.0",
|
||||||
"semver": "5.3.0",
|
"semver": "5.3.0",
|
||||||
"sentiment":"2.1.0",
|
"sentiment":"2.1.0",
|
||||||
"ssh-keygen":"0.4.1",
|
|
||||||
"uglify-js":"3.0.20",
|
"uglify-js":"3.0.20",
|
||||||
"when": "3.7.8",
|
"when": "3.7.8",
|
||||||
"ws": "1.1.1",
|
"ws": "1.1.1",
|
||||||
|
@ -23,6 +23,7 @@ var crypto = require('crypto');
|
|||||||
var storageSettings = require("../settings");
|
var storageSettings = require("../settings");
|
||||||
var util = require("../util");
|
var util = require("../util");
|
||||||
var gitTools = require("./git");
|
var gitTools = require("./git");
|
||||||
|
var sshTools = require("./ssh");
|
||||||
|
|
||||||
var Projects = require("./Project");
|
var Projects = require("./Project");
|
||||||
|
|
||||||
@ -89,6 +90,7 @@ function init(_settings, _runtime) {
|
|||||||
projectsEnabled = false;
|
projectsEnabled = false;
|
||||||
} else {
|
} else {
|
||||||
Projects.init(settings,runtime);
|
Projects.init(settings,runtime);
|
||||||
|
sshTools.init(settings,runtime);
|
||||||
projectsDir = fspath.join(settings.userDir,"projects");
|
projectsDir = fspath.join(settings.userDir,"projects");
|
||||||
if (!settings.readOnly) {
|
if (!settings.readOnly) {
|
||||||
return fs.ensureDir(projectsDir)
|
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 fs = require('fs-extra');
|
||||||
var when = require('when');
|
var when = require('when');
|
||||||
var fspath = require("path");
|
var fspath = require("path");
|
||||||
var keygen = require('ssh-keygen');
|
var sshTools = require("./projects/ssh");
|
||||||
|
|
||||||
var settings;
|
var settings;
|
||||||
var runtime;
|
var runtime;
|
||||||
@ -97,26 +97,12 @@ function generateSSHKey(username, options) {
|
|||||||
} else {
|
} else {
|
||||||
var comment = options.comment || "";
|
var comment = options.comment || "";
|
||||||
var password = options.password || "";
|
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 size = options.size || 2048;
|
||||||
var sshKeyFileBasename = username + '_' + name;
|
var sshKeyFileBasename = username + '_' + name;
|
||||||
var privateKeyFilePath = fspath.join(sshkeyDir, sshKeyFileBasename);
|
var privateKeyFilePath = fspath.join(sshkeyDir, sshKeyFileBasename);
|
||||||
return generateSSHKeyPair(name, privateKeyFilePath, comment, password, size)
|
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) {
|
function deleteSSHKey(username, name) {
|
||||||
@ -162,26 +148,21 @@ function deleteSSHKeyFiles(username, name) {
|
|||||||
return Promise.all([
|
return Promise.all([
|
||||||
fs.remove(privateKeyFilePath),
|
fs.remove(privateKeyFilePath),
|
||||||
fs.remove(publicKeyFilePath)
|
fs.remove(publicKeyFilePath)
|
||||||
]);
|
])
|
||||||
|
.then(function() {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateSSHKeyPair(name, privateKeyPath, comment, password, size) {
|
function generateSSHKeyPair(name, privateKeyPath, comment, password, size) {
|
||||||
log.trace("ssh-keygen["+[name,privateKeyPath,comment,size,"hasPassword?"+!!password].join(",")+"]");
|
log.trace("ssh-keygen["+[name,privateKeyPath,comment,size,"hasPassword?"+!!password].join(",")+"]");
|
||||||
return new Promise(function(resolve, reject) {
|
return sshTools.generateKey({location: privateKeyPath, comment: comment, password: password, size: size})
|
||||||
keygen({
|
.then(function(stdout) {
|
||||||
location: privateKeyPath,
|
return name;
|
||||||
comment: comment,
|
})
|
||||||
password: password,
|
.catch(function(err) {
|
||||||
size: size
|
log.log('[SSHKey generation] error:', err);
|
||||||
}, function(err, out) {
|
throw err;
|
||||||
if ( err ) {
|
|
||||||
err.code = "key_generation_failed";
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
resolve(name);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ describe("storage/localfilesystem/sshkeys", function() {
|
|||||||
log:{
|
log:{
|
||||||
_:function() { return "placeholder message"},
|
_:function() { return "placeholder message"},
|
||||||
info: function() { },
|
info: function() { },
|
||||||
|
log: function() { },
|
||||||
trace: function() { }
|
trace: function() { }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -61,7 +62,6 @@ describe("storage/localfilesystem/sshkeys", function() {
|
|||||||
localfilesystem.init(mockSettings, mockRuntime).then(function() {
|
localfilesystem.init(mockSettings, mockRuntime).then(function() {
|
||||||
sshkeys.init(mockSettings, mockRuntime).then(function() {
|
sshkeys.init(mockSettings, mockRuntime).then(function() {
|
||||||
sshkeys.listSSHKeys(username).then(function(retObj) {
|
sshkeys.listSSHKeys(username).then(function(retObj) {
|
||||||
console.log('retObj:', retObj);
|
|
||||||
retObj.should.be.instanceOf(Array).and.have.lengthOf(0);
|
retObj.should.be.instanceOf(Array).and.have.lengthOf(0);
|
||||||
done();
|
done();
|
||||||
}).catch(function(err) {
|
}).catch(function(err) {
|
||||||
@ -246,7 +246,31 @@ describe("storage/localfilesystem/sshkeys", function() {
|
|||||||
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
||||||
var username = 'test';
|
var username = 'test';
|
||||||
var options = {
|
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'
|
name: 'test-key01'
|
||||||
};
|
};
|
||||||
localfilesystem.init(mockSettings, mockRuntime).then(function() {
|
localfilesystem.init(mockSettings, mockRuntime).then(function() {
|
||||||
@ -271,7 +295,7 @@ describe("storage/localfilesystem/sshkeys", function() {
|
|||||||
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
||||||
var username = 'test';
|
var username = 'test';
|
||||||
var options = {
|
var options = {
|
||||||
email: 'test@test.com',
|
comment: 'test@test.com',
|
||||||
name: 'test-key01',
|
name: 'test-key01',
|
||||||
password: 'testtest'
|
password: 'testtest'
|
||||||
};
|
};
|
||||||
@ -297,7 +321,7 @@ describe("storage/localfilesystem/sshkeys", function() {
|
|||||||
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
||||||
var username = 'test';
|
var username = 'test';
|
||||||
var options = {
|
var options = {
|
||||||
email: 'test@test.com',
|
comment: 'test@test.com',
|
||||||
name: 'test-key01',
|
name: 'test-key01',
|
||||||
size: 4096
|
size: 4096
|
||||||
};
|
};
|
||||||
@ -324,7 +348,7 @@ describe("storage/localfilesystem/sshkeys", function() {
|
|||||||
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
||||||
var username = 'test';
|
var username = 'test';
|
||||||
var options = {
|
var options = {
|
||||||
email: 'test@test.com',
|
comment: 'test@test.com',
|
||||||
name: 'test-key01',
|
name: 'test-key01',
|
||||||
password: 'testtest',
|
password: 'testtest',
|
||||||
size: 4096
|
size: 4096
|
||||||
@ -352,23 +376,56 @@ describe("storage/localfilesystem/sshkeys", function() {
|
|||||||
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
||||||
var username = 'test';
|
var username = 'test';
|
||||||
var options = {
|
var options = {
|
||||||
email: 'test@test.com',
|
comment: 'test@test.com',
|
||||||
name: 'test-key01',
|
name: 'test-key01',
|
||||||
size: 3333
|
size: 1023
|
||||||
};
|
};
|
||||||
localfilesystem.init(mockSettings, mockRuntime).then(function() {
|
localfilesystem.init(mockSettings, mockRuntime).then(function() {
|
||||||
sshkeys.init(mockSettings, mockRuntime).then(function() {
|
sshkeys.init(mockSettings, mockRuntime).then(function() {
|
||||||
sshkeys.generateSSHKey(username, options).then(function(retObj) {
|
sshkeys.generateSSHKey(username, options).then(function(retObj) {
|
||||||
retObj.should.be.equal(options.name);
|
done(new Error('Does NOT throw error!'));
|
||||||
fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name)).should.be.true();
|
}).catch(function(err) {
|
||||||
fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name+'.pub')).should.be.true();
|
try {
|
||||||
|
err.should.have.have.property('code', 'key_length_too_short');
|
||||||
done();
|
done();
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
done(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
}).catch(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
}).catch(function(err) {
|
}).catch(function(err) {
|
||||||
done(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);
|
||||||
|
});
|
||||||
}).catch(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user