UNPKG

polyv-live-cli

Version:

CLI tool for managing PolyV live streaming services.

290 lines 12.2 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.defaultFilePermissionManager = exports.FilePermissionManager = void 0; const fs = __importStar(require("fs")); const path = __importStar(require("path")); const os = __importStar(require("os")); const SECURE_PERMISSIONS = { OWNER_RW: 0o600, OWNER_RWX: 0o700 }; class FilePermissionManager { constructor() { this.platform = os.platform(); } supportsUnixPermissions() { return this.platform !== 'win32'; } getPermissionInfo(filePath) { try { const stats = fs.statSync(filePath); const mode = stats.mode & parseInt('777', 8); const isSecure = this.isPermissionSecure(mode, stats.isDirectory()); return { path: filePath, mode, isSecure, description: this.describePermissions(mode), warnings: this.generatePermissionWarnings(mode, stats.isDirectory()) }; } catch (error) { throw new Error(`Failed to get permission info for ${filePath}: ${error instanceof Error ? error.message : 'Unknown error'}`); } } isPermissionSecure(mode, isDirectory) { if (!this.supportsUnixPermissions()) { return true; } const expectedMode = isDirectory ? SECURE_PERMISSIONS.OWNER_RWX : SECURE_PERMISSIONS.OWNER_RW; return mode === expectedMode; } describePermissions(mode) { if (!this.supportsUnixPermissions()) { return 'Windows NTFS permissions (managed by system)'; } const owner = this.formatPermissionGroup((mode >> 6) & 7); const group = this.formatPermissionGroup((mode >> 3) & 7); const others = this.formatPermissionGroup(mode & 7); return `Owner: ${owner}, Group: ${group}, Others: ${others} (${mode.toString(8)})`; } formatPermissionGroup(perms) { const read = (perms & 4) ? 'r' : '-'; const write = (perms & 2) ? 'w' : '-'; const execute = (perms & 1) ? 'x' : '-'; return `${read}${write}${execute}`; } generatePermissionWarnings(mode, _isDirectory) { const warnings = []; if (!this.supportsUnixPermissions()) { return warnings; } const groupPerms = (mode >> 3) & 7; if (groupPerms > 0) { warnings.push('Group has access permissions - configuration file should be accessible only by owner'); } const otherPerms = mode & 7; if (otherPerms > 0) { warnings.push('Others have access permissions - configuration file should be accessible only by owner'); } if (otherPerms & 4) { warnings.push('SECURITY RISK: Configuration file is world-readable'); } if (otherPerms & 2) { warnings.push('CRITICAL SECURITY RISK: Configuration file is world-writable'); } return warnings; } validatePermissions(filePath) { try { if (!fs.existsSync(filePath)) { return { isValid: false, message: `File does not exist: ${filePath}`, recommendations: ['Create the configuration file first'] }; } const permissionInfo = this.getPermissionInfo(filePath); const recommendations = []; if (!permissionInfo.isSecure) { if (this.supportsUnixPermissions()) { recommendations.push(`Run: chmod 600 ${filePath}`); recommendations.push('Or use: polyv-live-cli config fix-permissions'); } else { recommendations.push('Ensure only your user account has access to the configuration file'); recommendations.push('Check Windows file properties and remove other users\' access'); } } if (permissionInfo.warnings.length > 0) { recommendations.push('Review and fix permission warnings above'); } return { isValid: permissionInfo.isSecure && permissionInfo.warnings.length === 0, message: permissionInfo.isSecure ? 'File permissions are secure' : 'File permissions are not secure - configuration file should only be accessible by owner', recommendations, permissionInfo }; } catch (error) { return { isValid: false, message: `Failed to validate permissions: ${error instanceof Error ? error.message : 'Unknown error'}`, recommendations: ['Check if file exists and is accessible'] }; } } setSecurePermissions(filePath, isDirectory = false) { try { if (!fs.existsSync(filePath)) { return { success: false, message: `Cannot set permissions: File does not exist: ${filePath}` }; } const before = this.getPermissionInfo(filePath); if (!this.supportsUnixPermissions()) { return { success: true, message: 'Windows NTFS permissions are managed by the system. Ensure only your user account has access.', before, after: before }; } const targetMode = isDirectory ? SECURE_PERMISSIONS.OWNER_RWX : SECURE_PERMISSIONS.OWNER_RW; fs.chmodSync(filePath, targetMode); const after = this.getPermissionInfo(filePath); return { success: true, message: `Successfully set secure permissions (${targetMode.toString(8)}) on ${filePath}`, before, after }; } catch (error) { return { success: false, message: `Failed to set secure permissions: ${error instanceof Error ? error.message : 'Unknown error'}` }; } } ensureSecureDirectory(dirPath) { try { if (!fs.existsSync(dirPath)) { const parentDir = path.dirname(dirPath); if (!fs.existsSync(parentDir)) { fs.mkdirSync(parentDir, { recursive: true, mode: SECURE_PERMISSIONS.OWNER_RWX }); } fs.mkdirSync(dirPath, { mode: SECURE_PERMISSIONS.OWNER_RWX }); } return this.setSecurePermissions(dirPath, true); } catch (error) { return { success: false, message: `Failed to ensure secure directory: ${error instanceof Error ? error.message : 'Unknown error'}` }; } } repairConfigurationFile(filePath) { try { const dirPath = path.dirname(filePath); const dirResult = this.ensureSecureDirectory(dirPath); if (!dirResult.success) { return { success: false, message: `Failed to secure parent directory: ${dirResult.message}` }; } if (fs.existsSync(filePath)) { return this.setSecurePermissions(filePath, false); } else { return { success: true, message: `Parent directory secured. Configuration file ${filePath} will be created with secure permissions.` }; } } catch (error) { return { success: false, message: `Failed to repair configuration file permissions: ${error instanceof Error ? error.message : 'Unknown error'}` }; } } detectPotentialTampering(filePath) { const reasons = []; const recommendations = []; try { if (!fs.existsSync(filePath)) { return { isTampered: false, reasons: ['File does not exist'], recommendations: ['Create configuration file if needed'] }; } const permissionInfo = this.getPermissionInfo(filePath); if (permissionInfo.warnings.length > 0) { reasons.push('Insecure file permissions detected'); reasons.push(...permissionInfo.warnings); recommendations.push('Run permission repair: polyv-live-cli config fix-permissions'); } if (this.supportsUnixPermissions()) { const mode = permissionInfo.mode; if (mode & 2) { reasons.push('File is world-writable - possible tampering risk'); recommendations.push('Immediately secure the file with: chmod 600 ' + filePath); } if (mode & 0o020) { reasons.push('File is group-writable - possible unauthorized access'); recommendations.push('Remove group write access'); } } return { isTampered: reasons.length > 0, reasons, recommendations }; } catch (error) { return { isTampered: true, reasons: [`Error checking file permissions: ${error instanceof Error ? error.message : 'Unknown error'}`], recommendations: ['Verify file exists and is accessible'] }; } } getSecurityRecommendations() { const recommendations = [ 'Keep your configuration file in a secure location', 'Regularly backup your configuration file', 'Use the POLYV_MASTER_KEY environment variable for additional security' ]; if (this.supportsUnixPermissions()) { recommendations.push('Ensure configuration file permissions are set to 600 (owner read/write only)', 'Configuration directory permissions should be 700 (owner access only)', 'Use "ls -la" to check file permissions'); } else { recommendations.push('On Windows, ensure only your user account has access to the configuration file', 'Use Windows file properties to review and manage access permissions', 'Consider using Windows folder encryption for additional security'); } return recommendations; } } exports.FilePermissionManager = FilePermissionManager; exports.defaultFilePermissionManager = new FilePermissionManager(); //# sourceMappingURL=file-permission-manager.js.map