fix: Resolve temp directory permission issues for policy creation

- Changed default temp directory to local backend/temp instead of system temp
- Added write permission test during temp directory initialization
- Implemented fallback to OS temp directory if local temp fails
- Added unique random suffix to policy filenames to avoid conflicts
- Set proper file permissions (0o644) when writing policy files
- Improved error handling for temp directory creation failures
- Fixed fs.constants reference for file access checks

This resolves the EACCES permission denied error when creating policies
in Docker/production environments.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-08-19 21:49:19 +02:00
parent df78c57c48
commit 26a86e0746
5 changed files with 1016 additions and 13 deletions
+34 -13
View File
@@ -1,8 +1,10 @@
const { exec, spawn } = require('child_process');
const util = require('util');
const fs = require('fs').promises;
const fsConstants = require('fs').constants;
const path = require('path');
const crypto = require('crypto');
const os = require('os');
const config = require('../config');
const { logger } = require('../utils/logger');
const { AppError } = require('../middleware/errorHandler.middleware');
@@ -12,17 +14,30 @@ const execAsync = util.promisify(exec);
class MinIOService {
constructor(alias = config.minio.defaultAlias) {
this.alias = alias;
this.tempDir = process.env.TEMP_DIR || path.join(__dirname, '../../temp');
// Use local temp directory by default, fallback to system temp if needed
this.tempDir = path.join(__dirname, '../../temp');
this.ensureTempDir();
}
async ensureTempDir() {
try {
await fs.mkdir(this.tempDir, { recursive: true });
await fs.mkdir(this.tempDir, { recursive: true, mode: 0o755 });
// Test write permissions
const testFile = path.join(this.tempDir, '.write-test');
await fs.writeFile(testFile, 'test');
await fs.unlink(testFile);
// Clean up old temp files (older than 1 hour)
this.cleanupTempFiles();
} catch (error) {
logger.error('Failed to create temp directory:', error);
logger.error('Failed to create or write to temp directory:', error);
// Fallback to node's temp directory
this.tempDir = path.join(os.tmpdir(), 'minio-webui-temp');
try {
await fs.mkdir(this.tempDir, { recursive: true, mode: 0o755 });
logger.info(`Using fallback temp directory: ${this.tempDir}`);
} catch (fallbackError) {
logger.error('Failed to create fallback temp directory:', fallbackError);
}
}
}
@@ -236,12 +251,14 @@ class MinIOService {
}]
};
// Write policy to temp file
const policyFile = path.join(this.tempDir, `${policyName}-${Date.now()}.json`);
// Write policy to temp file with unique name
const timestamp = Date.now();
const randomStr = Math.random().toString(36).substring(7);
const policyFile = path.join(this.tempDir, `${policyName}-${timestamp}-${randomStr}.json`);
// Ensure temp directory exists before writing
await fs.mkdir(this.tempDir, { recursive: true });
await fs.writeFile(policyFile, JSON.stringify(policy, null, 2));
// Ensure temp directory exists and is writable
await this.ensureTempDir();
await fs.writeFile(policyFile, JSON.stringify(policy, null, 2), { mode: 0o644 });
try {
// Verify the file was written
@@ -337,18 +354,22 @@ class MinIOService {
throw new AppError('Invalid policy document', 400);
}
const policyFile = path.join(this.tempDir, `${policyName}-${Date.now()}.json`);
// Generate unique filename
const timestamp = Date.now();
const randomStr = Math.random().toString(36).substring(7);
const policyFile = path.join(this.tempDir, `${policyName}-${timestamp}-${randomStr}.json`);
try {
// Ensure temp directory exists before writing
await fs.mkdir(this.tempDir, { recursive: true });
// Ensure temp directory exists and is writable
await this.ensureTempDir();
await fs.writeFile(policyFile,
typeof policyDocument === 'string' ? policyDocument : JSON.stringify(policyDocument, null, 2)
typeof policyDocument === 'string' ? policyDocument : JSON.stringify(policyDocument, null, 2),
{ mode: 0o644 }
);
// Verify the file was written
await fs.access(policyFile);
await fs.access(policyFile, fsConstants.R_OK);
await this.executeCommand(
`mc admin policy create ${this.alias} ${policyName} ${policyFile}`