ludus-mcp
Version:
MCP server for managing Ludus cybersecurity training environments through natural language commands
124 lines • 3.72 kB
JavaScript
/**
* Keyring utility for secure credential storage
* Uses OS-level keyring services for maximum security
*/
import keytar from 'keytar';
const SERVICE_NAME = 'ludus-mcp';
/**
* Credential keys used by the MCP server
*/
export const CREDENTIAL_KEYS = {
ADMIN_USER: 'admin-user',
CONNECTION_METHOD: 'connection-method',
WIREGUARD_CONFIG_PATH: 'wireguard-config-path',
API_KEY: 'api-key',
SSH_HOST: 'ssh-host',
SSH_USER: 'ssh-user',
SSH_AUTH_METHOD: 'ssh-auth-method',
SSH_PASSWORD: 'ssh-password',
SSH_KEY_PATH: 'ssh-key-path',
SSH_KEY_PASSPHRASE: 'ssh-key-passphrase',
};
/**
* Store a credential in the OS keyring
*/
export async function storeCredential(key, value) {
try {
await keytar.setPassword(SERVICE_NAME, key, value);
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
throw new Error(`Failed to store credential '${key}': ${errorMessage}`);
}
}
/**
* Retrieve a credential from the OS keyring
*/
export async function getCredential(key) {
try {
return await keytar.getPassword(SERVICE_NAME, key);
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
throw new Error(`Failed to retrieve credential '${key}': ${errorMessage}`);
}
}
/**
* Delete a credential from the OS keyring
*/
export async function deleteCredential(key) {
try {
return await keytar.deletePassword(SERVICE_NAME, key);
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
throw new Error(`Failed to delete credential '${key}': ${errorMessage}`);
}
}
/**
* Check if a credential exists in the keyring
*/
export async function hasCredential(key) {
const value = await getCredential(key);
return value !== null;
}
/**
* Store multiple credentials at once
*/
export async function storeCredentials(credentials) {
const promises = Object.entries(credentials).map(([key, value]) => storeCredential(key, value));
await Promise.all(promises);
}
/**
* Retrieve multiple credentials at once
*/
export async function getCredentials(keys) {
const promises = keys.map(async (key) => ({
key,
value: await getCredential(key)
}));
const results = await Promise.all(promises);
return results.reduce((acc, { key, value }) => {
acc[key] = value;
return acc;
}, {});
}
/**
* Clear all MCP server credentials from the keyring
*/
export async function clearAllCredentials() {
const keys = Object.values(CREDENTIAL_KEYS);
const promises = keys.map(key => deleteCredential(key));
await Promise.all(promises);
}
/**
* Check if keyring is available on this system
*/
export function isKeyringSupportAvailable() {
try {
// Since keytar is already imported at the top of the file, just check if it works
const platform = process.platform;
const display = process.env.DISPLAY;
const waylandDisplay = process.env.WAYLAND_DISPLAY;
return platform !== 'linux' || display !== undefined || waylandDisplay !== undefined;
}
catch (error) {
return false;
}
}
/**
* Get a summary of stored credentials (for debugging)
*/
export async function getCredentialSummary() {
const keys = Object.values(CREDENTIAL_KEYS);
const promises = keys.map(async (key) => ({
key,
exists: await hasCredential(key)
}));
const results = await Promise.all(promises);
return results.reduce((acc, { key, exists }) => {
acc[key] = exists;
return acc;
}, {});
}
//# sourceMappingURL=keyring.js.map