import type { CloudCredentials, CloudProvider } from '../types/index.js';
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
import { join } from 'path';
import { homedir } from 'os';
export class CredentialManager {
private credentialsPath: string;
constructor() {
const configDir = join(homedir(), '.cloud-services-mcp');
if (!existsSync(configDir)) {
mkdirSync(configDir, { recursive: true });
}
this.credentialsPath = join(configDir, 'credentials.json');
}
/**
* Get credentials for a provider
*/
async getCredentials(provider: CloudProvider): Promise<CloudCredentials | null> {
try {
if (!existsSync(this.credentialsPath)) {
return null;
}
const data = readFileSync(this.credentialsPath, 'utf-8');
const credentials = JSON.parse(data);
return credentials[provider] || null;
} catch {
return null;
}
}
/**
* Set credentials for a provider
*/
async setCredentials(provider: CloudProvider, credentials: CloudCredentials): Promise<void> {
try {
let allCredentials: Record<string, CloudCredentials> = {};
if (existsSync(this.credentialsPath)) {
const data = readFileSync(this.credentialsPath, 'utf-8');
allCredentials = JSON.parse(data);
}
allCredentials[provider] = credentials;
writeFileSync(this.credentialsPath, JSON.stringify(allCredentials, null, 2));
} catch (error) {
throw new Error(`Failed to save credentials: ${error instanceof Error ? error.message : String(error)}`);
}
}
/**
* Validate credentials for a provider
*/
async validateCredentials(provider: CloudProvider): Promise<boolean> {
const credentials = await this.getCredentials(provider);
if (!credentials) {
return false;
}
// Basic validation
switch (provider) {
case 'aws':
return !!(credentials.accessKeyId && credentials.secretAccessKey);
case 'azure':
return !!(credentials.clientId && credentials.clientSecret && credentials.tenantId);
case 'gcp':
return !!(credentials.projectId);
default:
return false;
}
}
/**
* Load credentials from environment variables
*/
loadFromEnvironment(provider: CloudProvider): CloudCredentials | null {
switch (provider) {
case 'aws': {
const accessKeyId = process.env.AWS_ACCESS_KEY_ID;
const secretAccessKey = process.env.AWS_SECRET_ACCESS_KEY;
const region = process.env.AWS_REGION || 'us-east-1';
if (accessKeyId && secretAccessKey) {
return {
provider: 'aws',
type: 'access-key',
accessKeyId,
secretAccessKey,
region,
};
}
return null;
}
case 'azure': {
const clientId = process.env.AZURE_CLIENT_ID;
const clientSecret = process.env.AZURE_CLIENT_SECRET;
const tenantId = process.env.AZURE_TENANT_ID;
const subscriptionId = process.env.AZURE_SUBSCRIPTION_ID;
if (clientId && clientSecret && tenantId) {
return {
provider: 'azure',
type: 'service-account',
clientId,
clientSecret,
tenantId,
subscriptionId,
};
}
return null;
}
case 'gcp': {
const projectId = process.env.GCP_PROJECT_ID;
if (projectId) {
return {
provider: 'gcp',
type: 'service-account',
projectId,
};
}
return null;
}
default:
return null;
}
}
/**
* Clear credentials for a provider
*/
async clearCredentials(provider: CloudProvider): Promise<void> {
try {
if (!existsSync(this.credentialsPath)) {
return;
}
const data = readFileSync(this.credentialsPath, 'utf-8');
const allCredentials = JSON.parse(data);
delete allCredentials[provider];
writeFileSync(this.credentialsPath, JSON.stringify(allCredentials, null, 2));
} catch (error) {
throw new Error(`Failed to clear credentials: ${error instanceof Error ? error.message : String(error)}`);
}
}
}
export const credentialManager = new CredentialManager();