tasq/node_modules/agentic-flow/dist/federation/SecurityManager.js

192 lines
6.3 KiB
JavaScript

/**
* Security Manager - Authentication, encryption, and access control
*
* Features:
* - JWT token generation and validation
* - AES-256 encryption for data at rest
* - Tenant isolation
* - mTLS certificate management
*/
import crypto from 'crypto';
import { logger } from '../utils/logger.js';
export class SecurityManager {
algorithm = 'aes-256-gcm';
jwtSecret;
encryptionCache = new Map();
constructor() {
// In production, load from secure vault (AWS Secrets Manager, HashiCorp Vault, etc.)
this.jwtSecret = process.env.JWT_SECRET || crypto.randomBytes(32).toString('hex');
}
/**
* Create JWT token for agent authentication
*/
async createAgentToken(payload) {
const header = {
alg: 'HS256',
typ: 'JWT'
};
const now = Date.now();
const tokenPayload = {
...payload,
iat: now,
exp: payload.expiresAt,
iss: 'agentic-flow-federation'
};
// Encode header and payload
const encodedHeader = this.base64UrlEncode(JSON.stringify(header));
const encodedPayload = this.base64UrlEncode(JSON.stringify(tokenPayload));
// Create signature
const signature = crypto
.createHmac('sha256', this.jwtSecret)
.update(`${encodedHeader}.${encodedPayload}`)
.digest('base64url');
const token = `${encodedHeader}.${encodedPayload}.${signature}`;
logger.info('Created agent token', {
agentId: payload.agentId,
tenantId: payload.tenantId,
expiresAt: new Date(payload.expiresAt).toISOString()
});
return token;
}
/**
* Verify JWT token
*/
async verifyAgentToken(token) {
const parts = token.split('.');
if (parts.length !== 3) {
throw new Error('Invalid token format');
}
const [encodedHeader, encodedPayload, signature] = parts;
// Verify signature
const expectedSignature = crypto
.createHmac('sha256', this.jwtSecret)
.update(`${encodedHeader}.${encodedPayload}`)
.digest('base64url');
if (signature !== expectedSignature) {
throw new Error('Invalid token signature');
}
// Decode payload
const payload = JSON.parse(this.base64UrlDecode(encodedPayload));
// Check expiration
if (Date.now() >= payload.exp) {
throw new Error('Token expired');
}
logger.debug('Token verified', {
agentId: payload.agentId,
tenantId: payload.tenantId
});
return payload;
}
/**
* Get or create encryption keys for a tenant
*/
async getEncryptionKeys(tenantId) {
// Check cache
if (this.encryptionCache.has(tenantId)) {
return this.encryptionCache.get(tenantId);
}
// Generate new keys for tenant
// In production, these would be stored in a secure key management service
const encryptionKey = crypto.randomBytes(32); // 256-bit key
const iv = crypto.randomBytes(16); // 128-bit IV
const keys = { encryptionKey, iv };
// Cache keys
this.encryptionCache.set(tenantId, keys);
logger.info('Generated encryption keys for tenant', { tenantId });
return keys;
}
/**
* Encrypt data with AES-256-GCM
*/
async encrypt(data, tenantId) {
const keys = await this.getEncryptionKeys(tenantId);
const cipher = crypto.createCipheriv(this.algorithm, keys.encryptionKey, keys.iv);
let encrypted = cipher.update(data, 'utf8', 'base64');
encrypted += cipher.final('base64');
const authTag = cipher.getAuthTag().toString('base64');
logger.debug('Data encrypted', {
tenantId,
originalLength: data.length,
encryptedLength: encrypted.length
});
return { encrypted, authTag };
}
/**
* Decrypt data with AES-256-GCM
*/
async decrypt(encrypted, authTag, tenantId) {
const keys = await this.getEncryptionKeys(tenantId);
const decipher = crypto.createDecipheriv(this.algorithm, keys.encryptionKey, keys.iv);
decipher.setAuthTag(Buffer.from(authTag, 'base64'));
let decrypted = decipher.update(encrypted, 'base64', 'utf8');
decrypted += decipher.final('utf8');
logger.debug('Data decrypted', {
tenantId,
decryptedLength: decrypted.length
});
return decrypted;
}
/**
* Generate mTLS certificates for agent-to-hub communication
*/
async generateMTLSCertificates(agentId) {
// Placeholder: Actual implementation would use OpenSSL or similar
// to generate X.509 certificates with proper CA chain
logger.info('Generating mTLS certificates', { agentId });
return {
cert: 'PLACEHOLDER_CERT',
key: 'PLACEHOLDER_KEY',
ca: 'PLACEHOLDER_CA'
};
}
/**
* Validate tenant access to data
*/
validateTenantAccess(requestTenantId, dataTenantId) {
if (requestTenantId !== dataTenantId) {
logger.warn('Tenant access violation detected', {
requestTenantId,
dataTenantId
});
return false;
}
return true;
}
/**
* Hash sensitive data for storage (one-way)
*/
hashData(data) {
return crypto.createHash('sha256').update(data).digest('hex');
}
/**
* Generate secure random ID
*/
generateSecureId() {
return crypto.randomBytes(16).toString('hex');
}
/**
* Base64 URL-safe encoding
*/
base64UrlEncode(str) {
return Buffer.from(str)
.toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
}
/**
* Base64 URL-safe decoding
*/
base64UrlDecode(str) {
const base64 = str.replace(/-/g, '+').replace(/_/g, '/');
return Buffer.from(base64, 'base64').toString('utf8');
}
/**
* Clear cached keys (for testing or security refresh)
*/
clearCache() {
this.encryptionCache.clear();
logger.info('Encryption cache cleared');
}
}
//# sourceMappingURL=SecurityManager.js.map