luci-app-sshtunnel: ssh_keys: list keys without a corresponding .pub

The private keys doesn't have any extension so the only way to clearly say that this file is a key is a presence of the corresponding .pub file.
Most of time key files have a prefix id_ e.g. id_rsa etc.

The dropbearkey generates a key without a corresponding .pub file e.g. id_dropbearkey.

So we need to detect a key files by both .pub file or id_ prefix.
Key files without the id_ prefix won't be listed, sorry.

Signed-off-by: Sergey Ponomarev <stokito@gmail.com>
This commit is contained in:
Sergey Ponomarev 2023-12-17 14:34:32 +02:00 committed by Paul Donald
parent 3933633dd0
commit 949e7cbcb3
2 changed files with 65 additions and 30 deletions

View file

@ -11,14 +11,16 @@ return view.extend({
load: function () {
return L.resolveDefault(fs.list('/root/.ssh/'), []).then(function (entries) {
var tasks = [
// detect if OpenSSH ssh-keygen is installed
L.resolveDefault(fs.stat('/usr/bin/ssh-keygen'), {}),
];
var sshKeyNames = _findAllPossibleIdKeys(entries);
// read pub keys
for (var i = 0; i < entries.length; i++) {
if (entries[i].type === 'file' && entries[i].name.match(/\.pub$/)) {
tasks.push(Promise.resolve(entries[i].name));
tasks.push(fs.lines('/root/.ssh/' + entries[i].name));
}
for (var sshKeyName of sshKeyNames) {
var sshPubKeyName = sshKeyName + '.pub';
tasks.push(Promise.resolve(sshKeyName));
tasks.push(fs.lines('/root/.ssh/' + sshPubKeyName));
}
return Promise.all(tasks);
});
@ -42,12 +44,37 @@ return view.extend({
},
});
function _findAllPossibleIdKeys(entries) {
var sshKeyNames = [];
for (var item of entries) {
if (item.type !== 'file') {
continue
}
// a key file should have a corresponding .pub file
if (item.name.endsWith('.pub')) {
var sshPubKeyName = item.name;
var sshKeyName = sshPubKeyName.substring(0, sshPubKeyName.length - 4);
if (!sshKeyNames.includes(sshKeyName)) {
sshKeyNames.push(sshKeyName)
}
} else {
// or at least it should start with id_ e.g. id_dropbear
if (item.name.startsWith('id_')) {
var sshKeyName = item.name;
if (!sshKeyNames.includes(sshKeyName)) {
sshKeyNames.push(sshKeyName)
}
}
}
}
return sshKeyNames;
}
function _splitSshKeys(sshFiles) {
var sshKeys = {};
for (var i = 0; i < sshFiles.length; i++) {
var sshPubKeyName = sshFiles[i];
var sshKeyName = sshPubKeyName.substring(0, sshPubKeyName.length - 4);
i++;
var sshKeyName = sshFiles[i];
i++; // next is a .pub content
var sshPub = sshFiles[i];
sshKeys[sshKeyName] = '<small><code>' + sshPub + '</code></small>';
}

View file

@ -5,24 +5,17 @@
'require ui';
'require view';
var allSshKeys = {};
return view.extend({
load: function () {
return L.resolveDefault(fs.list('/root/.ssh/'), []).then(function (entries) {
var tasks = [];
for (var i = 0; i < entries.length; i++) {
if (entries[i].type === 'file' && entries[i].name.match(/\.pub$/)) {
tasks.push(Promise.resolve(entries[i].name));
}
}
return Promise.all(tasks);
var sshKeyNames = _findAllPossibleIdKeys(entries);
return Promise.resolve(sshKeyNames);
});
},
render: function (data) {
var sshKeys = _splitSshKeys(data);
if (sshKeys.length === 0) {
var sshKeyNames = data;
if (sshKeyNames.length === 0) {
ui.addNotification(null, E('p', _('No SSH keys found, <a %s>generate a new one</a>').format('href="./ssh_keys"')), 'warning');
}
@ -58,9 +51,9 @@ return view.extend({
'See <em>ssh_config IdentityFile</em>')
);
o.value('');
Object.keys(sshKeys).forEach(function (keyName) {
o.value('/root/.ssh/' + keyName, keyName);
});
for (var sshKeyName of sshKeyNames) {
o.value('/root/.ssh/' + sshKeyName, sshKeyName);
}
o.optional = true;
@ -135,13 +128,28 @@ return view.extend({
},
});
function _splitSshKeys(sshFiles) {
var sshKeys = {};
for (var i = 0; i < sshFiles.length; i++) {
var sshPubKeyName = sshFiles[i];
function _findAllPossibleIdKeys(entries) {
var sshKeyNames = [];
for (var item of entries) {
if (item.type !== 'file') {
continue
}
// a key file should have a corresponding .pub file
if (item.name.endsWith('.pub')) {
var sshPubKeyName = item.name;
var sshKeyName = sshPubKeyName.substring(0, sshPubKeyName.length - 4);
sshKeys[sshKeyName] = '';
if (!sshKeyNames.includes(sshKeyName)) {
sshKeyNames.push(sshKeyName)
}
allSshKeys = sshKeys;
return sshKeys;
} else {
// or at least it should start with id_ e.g. id_dropbear
if (item.name.startsWith('id_')) {
var sshKeyName = item.name;
if (!sshKeyNames.includes(sshKeyName)) {
sshKeyNames.push(sshKeyName)
}
}
}
}
return sshKeyNames;
}