mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Rearrange ssh logic to bring it together
This commit is contained in:
@@ -23,7 +23,7 @@ var os = require('os');
|
||||
var gitTools = require("./git");
|
||||
var util = require("../util");
|
||||
var defaultFileSet = require("./defaultFileSet");
|
||||
var sshKeys = require("../sshkeys");
|
||||
var sshKeys = require("./ssh");
|
||||
var settings;
|
||||
var runtime;
|
||||
var log;
|
||||
|
@@ -23,7 +23,7 @@ var crypto = require('crypto');
|
||||
var storageSettings = require("../settings");
|
||||
var util = require("../util");
|
||||
var gitTools = require("./git");
|
||||
var sshTools = require("./sshKeygen");
|
||||
var sshTools = require("./ssh");
|
||||
|
||||
var Projects = require("./Project");
|
||||
|
||||
@@ -85,45 +85,47 @@ function init(_settings, _runtime) {
|
||||
var setupProjectsPromise;
|
||||
|
||||
if (projectsEnabled) {
|
||||
return gitTools.init(_settings, _runtime).then(function(gitVersion) {
|
||||
if (!gitVersion) {
|
||||
projectLogMessages.push(log._("storage.localfilesystem.projects.git-not-found"))
|
||||
projectsEnabled = false;
|
||||
} else {
|
||||
Projects.init(settings,runtime);
|
||||
sshTools.init(settings,runtime);
|
||||
projectsDir = fspath.join(settings.userDir,"projects");
|
||||
if (!settings.readOnly) {
|
||||
return fs.ensureDir(projectsDir)
|
||||
//TODO: this is accessing settings from storage directly as settings
|
||||
// has not yet been initialised. That isn't ideal - can this be deferred?
|
||||
.then(storageSettings.getSettings)
|
||||
.then(function(globalSettings) {
|
||||
var saveSettings = false;
|
||||
if (!globalSettings.projects) {
|
||||
globalSettings.projects = {
|
||||
projects: {}
|
||||
}
|
||||
saveSettings = true;
|
||||
} else {
|
||||
activeProject = globalSettings.projects.activeProject;
|
||||
}
|
||||
if (settings.flowFile) {
|
||||
if (globalSettings.projects.projects.hasOwnProperty(settings.flowFile)) {
|
||||
activeProject = settings.flowFile;
|
||||
globalSettings.projects.activeProject = settings.flowFile;
|
||||
return sshTools.init(settings,runtime).then(function() {
|
||||
gitTools.init(_settings, _runtime).then(function(gitVersion) {
|
||||
if (!gitVersion) {
|
||||
projectLogMessages.push(log._("storage.localfilesystem.projects.git-not-found"))
|
||||
projectsEnabled = false;
|
||||
} else {
|
||||
Projects.init(settings,runtime);
|
||||
sshTools.init(settings,runtime);
|
||||
projectsDir = fspath.join(settings.userDir,"projects");
|
||||
if (!settings.readOnly) {
|
||||
return fs.ensureDir(projectsDir)
|
||||
//TODO: this is accessing settings from storage directly as settings
|
||||
// has not yet been initialised. That isn't ideal - can this be deferred?
|
||||
.then(storageSettings.getSettings)
|
||||
.then(function(globalSettings) {
|
||||
var saveSettings = false;
|
||||
if (!globalSettings.projects) {
|
||||
globalSettings.projects = {
|
||||
projects: {}
|
||||
}
|
||||
saveSettings = true;
|
||||
} else {
|
||||
activeProject = globalSettings.projects.activeProject;
|
||||
}
|
||||
}
|
||||
if (!activeProject) {
|
||||
projectLogMessages.push(log._("storage.localfilesystem.no-active-project"))
|
||||
}
|
||||
if (saveSettings) {
|
||||
return storageSettings.saveSettings(globalSettings);
|
||||
}
|
||||
});
|
||||
if (settings.flowFile) {
|
||||
if (globalSettings.projects.projects.hasOwnProperty(settings.flowFile)) {
|
||||
activeProject = settings.flowFile;
|
||||
globalSettings.projects.activeProject = settings.flowFile;
|
||||
saveSettings = true;
|
||||
}
|
||||
}
|
||||
if (!activeProject) {
|
||||
projectLogMessages.push(log._("storage.localfilesystem.no-active-project"))
|
||||
}
|
||||
if (saveSettings) {
|
||||
return storageSettings.saveSettings(globalSettings);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
return Promise.resolve();
|
||||
@@ -552,6 +554,8 @@ module.exports = {
|
||||
getFlows: getFlows,
|
||||
saveFlows: saveFlows,
|
||||
getCredentials: getCredentials,
|
||||
saveCredentials: saveCredentials
|
||||
saveCredentials: saveCredentials,
|
||||
|
||||
ssh: sshTools
|
||||
|
||||
};
|
||||
|
209
red/runtime/storage/localfilesystem/projects/ssh/index.js
Normal file
209
red/runtime/storage/localfilesystem/projects/ssh/index.js
Normal file
@@ -0,0 +1,209 @@
|
||||
/**
|
||||
* 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 fs = require('fs-extra');
|
||||
var when = require('when');
|
||||
var fspath = require("path");
|
||||
var keygen = require("./keygen");
|
||||
|
||||
var settings;
|
||||
var runtime;
|
||||
var log;
|
||||
var sshkeyDir;
|
||||
var userSSHKeyDir;
|
||||
|
||||
function init(_settings, _runtime) {
|
||||
settings = _settings;
|
||||
runtime = _runtime;
|
||||
log = runtime.log;
|
||||
sshkeyDir = fspath.join(settings.userDir, "projects", ".sshkeys");
|
||||
userSSHKeyDir = fspath.join(process.env.HOME || process.env.USERPROFILE || process.env.HOMEPATH, ".ssh");
|
||||
// console.log('sshkeys.init()');
|
||||
return fs.ensureDir(sshkeyDir);
|
||||
}
|
||||
|
||||
function listSSHKeys(username) {
|
||||
return listSSHKeysInDir(sshkeyDir,username + '_').then(function(customKeys) {
|
||||
return listSSHKeysInDir(userSSHKeyDir).then(function(existingKeys) {
|
||||
existingKeys.forEach(function(k){
|
||||
k.system = true;
|
||||
customKeys.push(k);
|
||||
})
|
||||
return customKeys;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function listSSHKeysInDir(dir,startStr) {
|
||||
startStr = startStr || "";
|
||||
return fs.readdir(dir).then(function(fns) {
|
||||
var ret = fns.sort()
|
||||
.filter(function(fn) {
|
||||
var fullPath = fspath.join(dir,fn);
|
||||
if (fn.length > 2 || fn[0] != ".") {
|
||||
var stats = fs.lstatSync(fullPath);
|
||||
if (stats.isFile()) {
|
||||
return fn.startsWith(startStr);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
})
|
||||
.map(function(filename) {
|
||||
return filename.substr(startStr.length);
|
||||
})
|
||||
.reduce(function(prev, current) {
|
||||
var parsePath = fspath.parse(current);
|
||||
if ( parsePath ) {
|
||||
if ( parsePath.ext !== '.pub' ) {
|
||||
// Private Keys
|
||||
prev.keyFiles.push(parsePath.base);
|
||||
}
|
||||
else if ( parsePath.ext === '.pub' && (prev.keyFiles.some(function(elem){ return elem === parsePath.name; }))) {
|
||||
prev.privateKeyFiles.push(parsePath.name);
|
||||
}
|
||||
}
|
||||
return prev;
|
||||
}, { keyFiles: [], privateKeyFiles: [] });
|
||||
return ret.privateKeyFiles.map(function(filename) {
|
||||
return {
|
||||
name: filename
|
||||
};
|
||||
});
|
||||
}).then(function(result) {
|
||||
return result;
|
||||
}).catch(function() {
|
||||
return []
|
||||
});
|
||||
}
|
||||
|
||||
function getSSHKey(username, name) {
|
||||
return checkSSHKeyFileAndGetPublicKeyFileName(username, name)
|
||||
.then(function(publicSSHKeyPath) {
|
||||
return fs.readFile(publicSSHKeyPath, 'utf-8');
|
||||
}).catch(function() {
|
||||
var privateKeyPath = fspath.join(userSSHKeyDir,name);
|
||||
var publicKeyPath = privateKeyPath+".pub";
|
||||
return checkFilePairExist(privateKeyPath,publicKeyPath).then(function() {
|
||||
return fs.readFile(publicKeyPath, 'utf-8');
|
||||
}).catch(function() {
|
||||
return null
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function generateSSHKey(username, options) {
|
||||
options = options || {};
|
||||
var name = options.name || "";
|
||||
return checkExistSSHKeyFiles(username, name)
|
||||
.then(function(result) {
|
||||
if ( result ) {
|
||||
var e = new Error("SSH Key name exists");
|
||||
e.code = "key_exists";
|
||||
throw e;
|
||||
} else {
|
||||
var comment = options.comment || "";
|
||||
var password = options.password || "";
|
||||
var size = options.size || 2048;
|
||||
var sshKeyFileBasename = username + '_' + name;
|
||||
var privateKeyFilePath = fspath.join(sshkeyDir, sshKeyFileBasename);
|
||||
return generateSSHKeyPair(name, privateKeyFilePath, comment, password, size)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function deleteSSHKey(username, name) {
|
||||
return checkSSHKeyFileAndGetPublicKeyFileName(username, name)
|
||||
.then(function() {
|
||||
return deleteSSHKeyFiles(username, name);
|
||||
});
|
||||
}
|
||||
|
||||
function checkExistSSHKeyFiles(username, name) {
|
||||
var sshKeyFileBasename = username + '_' + name;
|
||||
var privateKeyFilePath = fspath.join(sshkeyDir, sshKeyFileBasename);
|
||||
var publicKeyFilePath = fspath.join(sshkeyDir, sshKeyFileBasename + '.pub');
|
||||
return checkFilePairExist(privateKeyFilePath,publicKeyFilePath)
|
||||
.then(function() {
|
||||
return true;
|
||||
})
|
||||
.catch(function() {
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
function checkSSHKeyFileAndGetPublicKeyFileName(username, name) {
|
||||
var sshKeyFileBasename = username + '_' + name;
|
||||
var privateKeyFilePath = fspath.join(sshkeyDir, sshKeyFileBasename);
|
||||
var publicKeyFilePath = fspath.join(sshkeyDir, sshKeyFileBasename + '.pub');
|
||||
return checkFilePairExist(privateKeyFilePath,publicKeyFilePath).then(function() {
|
||||
return publicKeyFilePath;
|
||||
});
|
||||
}
|
||||
|
||||
function checkFilePairExist(privateKeyFilePath,publicKeyFilePath) {
|
||||
return Promise.all([
|
||||
fs.access(privateKeyFilePath, (fs.constants || fs).R_OK),
|
||||
fs.access(publicKeyFilePath , (fs.constants || fs).R_OK)
|
||||
])
|
||||
}
|
||||
|
||||
function deleteSSHKeyFiles(username, name) {
|
||||
var sshKeyFileBasename = username + '_' + name;
|
||||
var privateKeyFilePath = fspath.join(sshkeyDir, sshKeyFileBasename);
|
||||
var publicKeyFilePath = fspath.join(sshkeyDir, sshKeyFileBasename + '.pub');
|
||||
return Promise.all([
|
||||
fs.remove(privateKeyFilePath),
|
||||
fs.remove(publicKeyFilePath)
|
||||
])
|
||||
}
|
||||
|
||||
function generateSSHKeyPair(name, privateKeyPath, comment, password, size) {
|
||||
log.trace("ssh-keygen["+[name,privateKeyPath,comment,size,"hasPassword?"+!!password].join(",")+"]");
|
||||
return keygen.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;
|
||||
});
|
||||
}
|
||||
|
||||
function getPrivateKeyPath(username, name) {
|
||||
var sshKeyFileBasename = username + '_' + name;
|
||||
var privateKeyFilePath = fspath.join(sshkeyDir, sshKeyFileBasename);
|
||||
try {
|
||||
fs.accessSync(privateKeyFilePath, (fs.constants || fs).R_OK);
|
||||
return privateKeyFilePath;
|
||||
} catch(err) {
|
||||
privateKeyFilePath = fspath.join(userSSHKeyDir,name);
|
||||
try {
|
||||
fs.accessSync(privateKeyFilePath, (fs.constants || fs).R_OK);
|
||||
return privateKeyFilePath;
|
||||
} catch(err2) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
init: init,
|
||||
listSSHKeys: listSSHKeys,
|
||||
getSSHKey: getSSHKey,
|
||||
getPrivateKeyPath: getPrivateKeyPath,
|
||||
generateSSHKey: generateSSHKey,
|
||||
deleteSSHKey: deleteSSHKey
|
||||
};
|
Reference in New Issue
Block a user