diff --git a/PASSWORD_GENERATION.md b/PASSWORD_GENERATION.md new file mode 100644 index 0000000..0478ab7 --- /dev/null +++ b/PASSWORD_GENERATION.md @@ -0,0 +1,166 @@ +# Password Generation Guide for MinIO WebUI + +## Quick Start + +### Method 1: Simple Command (Recommended) + +```bash +cd backend +npm run hash-password YourSecurePassword123! +``` + +This will output: +``` +=== Generated Password Hash === +ADMIN_PASSWORD_HASH=$2b$12$...your.hash.here... + +Copy the above line to your .env file +``` + +### Method 2: Interactive Mode + +```bash +cd backend +npm run generate-password +``` + +This will: +- Prompt you for a password (hidden input) +- Generate the bcrypt hash +- Show you the hash to copy to your .env file +- Verify the hash works correctly + +## Docker Usage + +If you're using Docker, you can run the password generator inside the container: + +```bash +# Method 1: Quick hash +docker exec -it minio-webui-backend npm run hash-password YourPassword123! + +# Method 2: Interactive +docker exec -it minio-webui-backend npm run generate-password +``` + +## Password Requirements + +Your password should meet these criteria: +- Minimum 8 characters +- At least one uppercase letter (A-Z) +- At least one lowercase letter (a-z) +- At least one number (0-9) +- At least one special character (!@#$%^&* etc.) + +## Example Passwords + +Good passwords: +- `MySecure@Pass123` +- `Admin#2024!Strong` +- `MinIO$WebUI&Safe99` + +## Step-by-Step Instructions + +1. **Navigate to backend directory:** + ```bash + cd backend + ``` + +2. **Generate your password hash:** + ```bash + npm run hash-password MyChosenPassword123! + ``` + +3. **Copy the output** (it will look like this): + ``` + ADMIN_PASSWORD_HASH=$2b$12$abcdefghijklmnopqrstuvwxyz... + ``` + +4. **Add to your .env file:** + ```bash + # Edit your .env file + nano ../.env + + # Or append directly + echo "ADMIN_PASSWORD_HASH=\$2b\$12\$your_hash_here" >> ../.env + ``` + +5. **Restart the backend:** + ```bash + # If using Docker + docker-compose restart backend + + # If running locally + npm start + ``` + +## Troubleshooting + +### "bcrypt: command not found" + +The script uses the Node.js bcrypt library, not the system bcrypt. Make sure you're in the backend directory and have run `npm install`. + +### "Cannot find module 'bcrypt'" + +Install dependencies first: +```bash +cd backend +npm install +``` + +### Hash not working + +1. Make sure you copied the entire hash including the `$2b$12$` prefix +2. Check for any extra spaces or line breaks +3. Ensure the .env file is in the project root directory +4. Try generating a new hash + +### Special characters in password + +If your password contains special shell characters, wrap it in single quotes: +```bash +npm run hash-password 'My$uper!Pass@123' +``` + +## Security Notes + +1. **Never commit your .env file** to version control +2. **Use strong passwords** - the hash is only as secure as your password +3. **Change default passwords** immediately in production +4. **Store .env securely** with appropriate file permissions: + ```bash + chmod 600 .env + ``` + +## Advanced Usage + +### Custom Salt Rounds + +The scripts use 12 salt rounds by default (recommended). If you need to change this, edit the script: + +```javascript +const saltRounds = 12; // Change this value if needed +``` + +Higher numbers are more secure but slower to compute. + +### Verify a Hash + +To verify if a password matches a hash: + +```javascript +// In Node.js +const bcrypt = require('bcrypt'); +const isValid = await bcrypt.compare('YourPassword', '$2b$12$...'); +console.log(isValid); // true or false +``` + +## Integration with MinIO WebUI + +Once you've set the `ADMIN_PASSWORD_HASH` in your .env file: + +1. Start/restart the application +2. Navigate to the login page +3. Username: `admin` (fixed) +4. Password: The password you used to generate the hash + +The application will compare your entered password with the stored hash for authentication. \ No newline at end of file diff --git a/backend/generate-password.js b/backend/generate-password.js new file mode 100755 index 0000000..aae6631 --- /dev/null +++ b/backend/generate-password.js @@ -0,0 +1,76 @@ +#!/usr/bin/env node + +const bcrypt = require('bcrypt'); +const readline = require('readline'); + +// Colors for console output +const colors = { + reset: '\x1b[0m', + green: '\x1b[32m', + yellow: '\x1b[33m', + blue: '\x1b[36m', + red: '\x1b[31m' +}; + +const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout +}); + +// Hide password input +rl._writeToOutput = function _writeToOutput(stringToWrite) { + if (rl.stdoutMuted) + rl.output.write("*"); + else + rl.output.write(stringToWrite); +}; + +console.log(`${colors.blue}=== MinIO WebUI Password Hash Generator ===${colors.reset}\n`); + +rl.question('Enter the password you want to hash: ', async (password) => { + rl.stdoutMuted = true; + + if (!password || password.length === 0) { + console.log(`\n${colors.red}Error: Password cannot be empty${colors.reset}`); + rl.close(); + process.exit(1); + } + + try { + console.log(`\n${colors.yellow}Generating hash...${colors.reset}`); + + // Use the same salt rounds as in the application (default is 10) + const saltRounds = 12; + const hash = await bcrypt.hash(password, saltRounds); + + console.log(`\n${colors.green}✓ Password hash generated successfully!${colors.reset}\n`); + console.log('Add this to your .env file:'); + console.log(`${colors.yellow}ADMIN_PASSWORD_HASH=${hash}${colors.reset}`); + + // Verify the hash works + const verifyResult = await bcrypt.compare(password, hash); + if (verifyResult) { + console.log(`\n${colors.green}✓ Hash verification successful${colors.reset}`); + } else { + console.log(`\n${colors.red}✗ Hash verification failed${colors.reset}`); + } + + console.log('\nPassword requirements:'); + console.log('- Minimum 8 characters'); + console.log('- At least one uppercase letter'); + console.log('- At least one lowercase letter'); + console.log('- At least one number'); + console.log('- At least one special character'); + + } catch (error) { + console.error(`\n${colors.red}Error generating hash:${colors.reset}`, error.message); + process.exit(1); + } + + rl.close(); +}); + +rl.on('close', () => { + console.log(`\n${colors.blue}Done!${colors.reset}`); + process.exit(0); +}); \ No newline at end of file diff --git a/backend/package.json b/backend/package.json index 7f5c7fc..a919406 100644 --- a/backend/package.json +++ b/backend/package.json @@ -9,7 +9,9 @@ "dev:node": "node --watch src/app.js", "test": "jest --coverage", "lint": "eslint src/", - "lint:fix": "eslint src/ --fix" + "lint:fix": "eslint src/ --fix", + "hash-password": "node scripts/hash-password.js", + "generate-password": "node generate-password.js" }, "keywords": ["minio", "api", "backend"], "author": "", diff --git a/backend/scripts/hash-password.js b/backend/scripts/hash-password.js new file mode 100644 index 0000000..038f83a --- /dev/null +++ b/backend/scripts/hash-password.js @@ -0,0 +1,23 @@ +const bcrypt = require('bcrypt'); + +const password = process.argv[2]; + +if (!password) { + console.error('Usage: npm run hash-password '); + console.error('Example: npm run hash-password MySecurePass123!'); + process.exit(1); +} + +async function hashPassword() { + try { + const hash = await bcrypt.hash(password, 12); + console.log('\n=== Generated Password Hash ==='); + console.log(`ADMIN_PASSWORD_HASH=${hash}`); + console.log('\nCopy the above line to your .env file'); + } catch (error) { + console.error('Error:', error.message); + process.exit(1); + } +} + +hashPassword(); \ No newline at end of file