Initial commit - Project start (July 17, 2025)
Mirror to GitHub / mirror (push) Successful in 26s
Test and Lint / backend-test (push) Successful in 1m11s
continuous-integration/drone/push Build is passing
Test and Lint / frontend-test (push) Successful in 2m28s
Version and Release / version-bump (push) Successful in 32s
Version and Release / trigger-drone (push) Has been skipped
Mirror to GitHub / mirror (push) Successful in 26s
Test and Lint / backend-test (push) Successful in 1m11s
continuous-integration/drone/push Build is passing
Test and Lint / frontend-test (push) Successful in 2m28s
Version and Release / version-bump (push) Successful in 32s
Version and Release / trigger-drone (push) Has been skipped
Original: feat: enhance security logging and ensure rate limit blocks are properly tracked - Add comprehensive logging for rate limit blocks with full request details - IP address (with proper proxy detection), user agent, headers, timestamps - Rate limit info (current count, limit, remaining, reset time) - Separate tracking for auth vs general endpoints - Enhance authentication failure logging - JWT validation failures with detailed error info - Admin auth attempts without token - Failed token validation with user context - All events include IP, path, method, user agent - Improve Winston logger configuration for production - Add automatic log rotation (10MB errors, 50MB combined) - Create separate security.log for auth/rate limit events - Ensure logs directory exists automatically - Add structured JSON format for log aggregation - Support container logging with LOG_TO_CONSOLE env var - Create comprehensive documentation - Security logging guide with examples - Monitoring recommendations - Configuration reference - Add test script to verify logging functionality All rate limit settings remain configurable via admin panel: - Window duration, max requests, auth limits - Skip authenticated requests option - Public endpoints only option 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,164 @@
|
||||
# Admin Setup Guide - Secure Password System
|
||||
|
||||
## Overview
|
||||
|
||||
PicPeak now uses a secure admin setup process that eliminates the default password vulnerability. When you first set up the application, a secure password is automatically generated for the admin account.
|
||||
|
||||
## Initial Setup Process
|
||||
|
||||
### 1. First Installation
|
||||
|
||||
When you run the database migrations for the first time:
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
npm run migrate
|
||||
```
|
||||
|
||||
The system will:
|
||||
- Create an admin user with username `admin`
|
||||
- Generate a secure, random password (e.g., `SwiftEagle3847!`)
|
||||
- Display the credentials in the console
|
||||
- Save the credentials to `ADMIN_CREDENTIALS.txt`
|
||||
|
||||
### 2. Retrieving Your Credentials
|
||||
|
||||
After setup, you can find your admin credentials in:
|
||||
- **Console output** - Displayed immediately after setup
|
||||
- **ADMIN_CREDENTIALS.txt** - File in the project root
|
||||
|
||||
**Example output:**
|
||||
```
|
||||
========================================
|
||||
✅ Admin user created successfully!
|
||||
========================================
|
||||
Username: admin
|
||||
Password: SwiftEagle3847!
|
||||
|
||||
⚠️ IMPORTANT:
|
||||
1. Save these credentials securely
|
||||
2. You will be required to change the password on first login
|
||||
3. Credentials are also saved in: ADMIN_CREDENTIALS.txt
|
||||
========================================
|
||||
```
|
||||
|
||||
### 3. First Login
|
||||
|
||||
1. Navigate to the admin panel: `http://localhost:3001/admin`
|
||||
2. Login with:
|
||||
- Username: `admin`
|
||||
- Password: (from ADMIN_CREDENTIALS.txt)
|
||||
3. You will be prompted to change your password immediately
|
||||
|
||||
### 4. Password Requirements
|
||||
|
||||
When changing your password, it must meet these requirements:
|
||||
- Minimum 12 characters long
|
||||
- Contains uppercase letters (A-Z)
|
||||
- Contains lowercase letters (a-z)
|
||||
- Contains numbers (0-9)
|
||||
- Contains special characters (!@#$%^&*()_+-=[]{}|;:,.<>?)
|
||||
- Not a common password
|
||||
|
||||
## Security Features
|
||||
|
||||
### Generated Passwords
|
||||
- Uses cryptographically secure random generation
|
||||
- Human-readable format: `AdjectiveNoun####!`
|
||||
- Example: `BrightMountain7823$`
|
||||
|
||||
### Password Storage
|
||||
- Passwords are hashed using bcrypt with 12 rounds
|
||||
- Original password is never stored in the database
|
||||
- Credentials file should be deleted after noting the password
|
||||
|
||||
### Forced Password Change
|
||||
- Admin must change password on first login
|
||||
- System tracks `must_change_password` flag
|
||||
- Cannot access admin features until password is changed
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Lost Admin Password
|
||||
|
||||
If you lose the admin password before first login:
|
||||
|
||||
1. Delete the admin user from the database:
|
||||
```sql
|
||||
DELETE FROM admin_users WHERE username = 'admin';
|
||||
```
|
||||
|
||||
2. Run migrations again:
|
||||
```bash
|
||||
npm run migrate
|
||||
```
|
||||
|
||||
3. New credentials will be generated
|
||||
|
||||
### Password Change Issues
|
||||
|
||||
If you can't change your password:
|
||||
- Ensure new password meets all requirements
|
||||
- Check for detailed error messages
|
||||
- Password strength validator provides specific feedback
|
||||
|
||||
### Can't Find Credentials File
|
||||
|
||||
If ADMIN_CREDENTIALS.txt is missing:
|
||||
- Check the console output from when you ran migrations
|
||||
- File is created in the backend directory root
|
||||
- File might have been deleted for security (as recommended)
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Immediate Action**
|
||||
- Change the generated password on first login
|
||||
- Use a password manager to store credentials
|
||||
- Delete ADMIN_CREDENTIALS.txt after noting the password
|
||||
|
||||
2. **Password Security**
|
||||
- Use unique passwords for each environment
|
||||
- Rotate passwords regularly (every 90 days)
|
||||
- Never share admin credentials
|
||||
|
||||
3. **Multiple Admins**
|
||||
- Create separate admin accounts for each person
|
||||
- Avoid sharing the main admin account
|
||||
- Use role-based access control when available
|
||||
|
||||
## Migration from Old System
|
||||
|
||||
If upgrading from the old system with hardcoded `admin123`:
|
||||
|
||||
1. The system will detect existing admin user
|
||||
2. You must manually reset the password:
|
||||
```bash
|
||||
# Run the password reset script
|
||||
node scripts/reset-admin-password.js
|
||||
```
|
||||
|
||||
3. Follow the new secure password process
|
||||
|
||||
## Environment-Specific Setup
|
||||
|
||||
### Development
|
||||
- Generated passwords are suitable for development
|
||||
- Consider using simpler passwords for convenience
|
||||
- Always use strong passwords in staging/production
|
||||
|
||||
### Production
|
||||
- Generate new admin account for production
|
||||
- Use extremely strong passwords (20+ characters)
|
||||
- Enable two-factor authentication when available
|
||||
- Regularly audit admin access logs
|
||||
|
||||
## Security Checklist
|
||||
|
||||
- [ ] Retrieved generated password from ADMIN_CREDENTIALS.txt
|
||||
- [ ] Logged in successfully with generated password
|
||||
- [ ] Changed password to a strong, unique password
|
||||
- [ ] Deleted ADMIN_CREDENTIALS.txt file
|
||||
- [ ] Stored new password in password manager
|
||||
- [ ] Tested login with new password
|
||||
- [ ] Set up additional admin accounts if needed
|
||||
- [ ] Configured password policies for organization
|
||||
@@ -0,0 +1,109 @@
|
||||
# JWT_SECRET Security Fix - Migration Guide
|
||||
|
||||
## Overview
|
||||
|
||||
A critical security vulnerability has been fixed where the application would fall back to a hardcoded JWT secret (`'your-secret-key'`) if the `JWT_SECRET` environment variable was not set. This has been addressed by:
|
||||
|
||||
1. Adding startup validation that requires `JWT_SECRET` to be set
|
||||
2. Removing all hardcoded fallback values
|
||||
3. Ensuring the secret meets minimum security requirements
|
||||
|
||||
## Changes Made
|
||||
|
||||
### 1. Added Environment Validation (`backend/src/config/validateEnv.js`)
|
||||
- The server now validates critical environment variables at startup
|
||||
- If `JWT_SECRET` is missing or set to the insecure default, the server will refuse to start
|
||||
- Warns if `JWT_SECRET` is less than 32 characters (recommended minimum)
|
||||
|
||||
### 2. Updated Server Startup (`backend/server.js`)
|
||||
- Added validation call immediately after loading environment variables
|
||||
- Ensures all routes and middleware have access to validated configuration
|
||||
|
||||
### 3. Removed Hardcoded Fallbacks (`backend/src/routes/protectedImages.js`)
|
||||
- Removed `|| 'your-secret-key'` fallback from lines 15 and 27
|
||||
- Functions now rely on the validated `JWT_SECRET` from environment
|
||||
|
||||
## Migration Steps for Production
|
||||
|
||||
### Before Deployment
|
||||
|
||||
1. **Verify JWT_SECRET is set in production**:
|
||||
```bash
|
||||
# Check if JWT_SECRET is set
|
||||
echo $JWT_SECRET
|
||||
```
|
||||
|
||||
2. **Ensure JWT_SECRET is secure**:
|
||||
- Must NOT be `'your-secret-key'`
|
||||
- Should be at least 32 characters long
|
||||
- Should be randomly generated
|
||||
|
||||
3. **Generate a secure JWT_SECRET if needed**:
|
||||
```bash
|
||||
# Generate a secure 64-character secret
|
||||
openssl rand -hex 32
|
||||
```
|
||||
|
||||
### Deployment Process
|
||||
|
||||
1. **Update environment variables** (if needed):
|
||||
```bash
|
||||
# Example for .env file
|
||||
JWT_SECRET=your-secure-64-character-random-string-here
|
||||
```
|
||||
|
||||
2. **Deploy the updated code**
|
||||
|
||||
3. **Monitor startup logs** to ensure no validation errors:
|
||||
```
|
||||
✓ Environment validation passed
|
||||
✓ Server running on port 3000
|
||||
```
|
||||
|
||||
### Rollback Plan
|
||||
|
||||
If the deployment fails due to missing `JWT_SECRET`:
|
||||
|
||||
1. **Quick Fix** (temporary):
|
||||
- Set `JWT_SECRET` environment variable to a secure value
|
||||
- Restart the application
|
||||
|
||||
2. **Full Rollback** (if needed):
|
||||
- Revert to previous version
|
||||
- Set `JWT_SECRET` properly before attempting deployment again
|
||||
|
||||
## Verification
|
||||
|
||||
After deployment, verify the fix is working:
|
||||
|
||||
1. **Check server logs** for successful startup
|
||||
2. **Test authentication** to ensure JWT tokens are working
|
||||
3. **Verify image protection** routes are functioning
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- **Never** commit JWT_SECRET to version control
|
||||
- **Rotate** JWT_SECRET periodically
|
||||
- **Use different** secrets for different environments (dev, staging, production)
|
||||
- **Monitor** for authentication failures that might indicate token issues
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Server won't start
|
||||
- **Error**: "Missing required environment variable: JWT_SECRET"
|
||||
- **Solution**: Set the JWT_SECRET environment variable
|
||||
|
||||
### JWT_SECRET rejection
|
||||
- **Error**: "JWT_SECRET is set to the insecure default value"
|
||||
- **Solution**: Change JWT_SECRET from 'your-secret-key' to a secure value
|
||||
|
||||
### Authentication failures after deployment
|
||||
- **Cause**: Existing tokens were signed with old secret
|
||||
- **Solution**: Users will need to re-authenticate to get new tokens
|
||||
|
||||
## Support
|
||||
|
||||
If you encounter issues during migration:
|
||||
1. Check the server logs for specific error messages
|
||||
2. Verify environment variables are properly set
|
||||
3. Ensure the JWT_SECRET value doesn't contain special characters that might need escaping
|
||||
@@ -0,0 +1,179 @@
|
||||
# Security Best Practices for PicPeak
|
||||
|
||||
## JWT Secret Management
|
||||
|
||||
### Generating Secure Secrets
|
||||
|
||||
Always generate cryptographically secure random secrets for JWT signing:
|
||||
|
||||
```bash
|
||||
# Generate a 64-character hex string (256 bits)
|
||||
openssl rand -hex 32
|
||||
|
||||
# Alternative: Generate a base64 string
|
||||
openssl rand -base64 32
|
||||
|
||||
# Alternative: Using Node.js
|
||||
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
|
||||
```
|
||||
|
||||
### Environment-Specific Secrets
|
||||
|
||||
**NEVER use the same JWT secret across different environments!**
|
||||
|
||||
- **Development**: Use the secure secret in `docker-compose.yml`
|
||||
- **Staging**: Generate a unique secret for staging
|
||||
- **Production**: Generate a unique secret for production
|
||||
|
||||
### Secret Requirements
|
||||
|
||||
1. **Minimum Length**: 32 characters (enforced by application)
|
||||
2. **Recommended Length**: 64 characters (256 bits)
|
||||
3. **Character Set**: Use hex or base64 encoding
|
||||
4. **Uniqueness**: Each environment must have a unique secret
|
||||
|
||||
### What NOT to Do
|
||||
|
||||
❌ **Never commit real secrets to version control**
|
||||
```bash
|
||||
# Bad - real secret in code
|
||||
JWT_SECRET=my-actual-production-secret
|
||||
```
|
||||
|
||||
❌ **Never use predictable or weak secrets**
|
||||
```bash
|
||||
# Bad examples
|
||||
JWT_SECRET=secret123
|
||||
JWT_SECRET=mycompanyname
|
||||
JWT_SECRET=password
|
||||
JWT_SECRET=your-secret-key
|
||||
```
|
||||
|
||||
❌ **Never share secrets between environments**
|
||||
```bash
|
||||
# Bad - same secret everywhere
|
||||
DEV_JWT_SECRET=same-secret
|
||||
PROD_JWT_SECRET=same-secret
|
||||
```
|
||||
|
||||
### Secure Secret Storage
|
||||
|
||||
#### For Local Development
|
||||
- Docker Compose files can contain development secrets
|
||||
- These should still be secure random values
|
||||
|
||||
#### For Production
|
||||
1. **Environment Variables**
|
||||
```bash
|
||||
# Set via secure environment
|
||||
export JWT_SECRET=$(openssl rand -hex 32)
|
||||
```
|
||||
|
||||
2. **Secret Management Services**
|
||||
- AWS Secrets Manager
|
||||
- HashiCorp Vault
|
||||
- Azure Key Vault
|
||||
- Kubernetes Secrets
|
||||
|
||||
3. **CI/CD Integration**
|
||||
- Store secrets in CI/CD platform's secret storage
|
||||
- Never log or echo secrets in build scripts
|
||||
|
||||
### Secret Rotation
|
||||
|
||||
Implement a secret rotation strategy:
|
||||
|
||||
1. **Regular Rotation**: Rotate secrets every 90 days
|
||||
2. **Incident Response**: Rotate immediately if compromised
|
||||
3. **Graceful Rotation**: Support multiple valid secrets during transition
|
||||
|
||||
### Monitoring and Alerts
|
||||
|
||||
1. **Startup Validation**: Application refuses to start without proper JWT_SECRET
|
||||
2. **Length Warnings**: Warnings for secrets shorter than 32 characters
|
||||
3. **Default Detection**: Critical error if default secret is detected
|
||||
|
||||
## Additional Security Measures
|
||||
|
||||
### Password Requirements
|
||||
- Minimum 12 characters
|
||||
- Mix of uppercase, lowercase, numbers, and special characters
|
||||
- Check against common password lists
|
||||
- Implement password strength meter
|
||||
|
||||
### Session Security
|
||||
- Implement token expiration (24 hours for admin, configurable for galleries)
|
||||
- Add refresh token mechanism
|
||||
- Implement token revocation
|
||||
- Use secure session storage (Redis in production)
|
||||
|
||||
### API Security
|
||||
- Rate limiting on all endpoints
|
||||
- Extra strict limits on authentication endpoints
|
||||
- CSRF protection for state-changing operations
|
||||
- Input validation on all user inputs
|
||||
|
||||
### File Upload Security
|
||||
- Validate file types by content, not just extension
|
||||
- Implement virus scanning
|
||||
- Limit file sizes
|
||||
- Sanitize filenames
|
||||
- Store files outside web root
|
||||
|
||||
### Database Security
|
||||
- Use parameterized queries (Knex.js handles this)
|
||||
- Validate and sanitize all inputs
|
||||
- Implement query timeouts
|
||||
- Use least-privilege database users
|
||||
|
||||
### HTTPS and Headers
|
||||
- Always use HTTPS in production
|
||||
- Implement security headers:
|
||||
- Strict-Transport-Security
|
||||
- X-Frame-Options
|
||||
- X-Content-Type-Options
|
||||
- Content-Security-Policy
|
||||
- X-XSS-Protection
|
||||
|
||||
### Logging and Monitoring
|
||||
- Log authentication attempts
|
||||
- Monitor for suspicious patterns
|
||||
- Never log sensitive data (passwords, tokens)
|
||||
- Implement audit trails for admin actions
|
||||
|
||||
## Security Checklist for Deployment
|
||||
|
||||
- [ ] Generate unique JWT_SECRET for environment
|
||||
- [ ] Verify JWT_SECRET meets minimum requirements
|
||||
- [ ] Store secrets securely (not in code)
|
||||
- [ ] Enable HTTPS
|
||||
- [ ] Configure security headers
|
||||
- [ ] Set up rate limiting
|
||||
- [ ] Enable audit logging
|
||||
- [ ] Test authentication flows
|
||||
- [ ] Verify file upload restrictions
|
||||
- [ ] Check database query security
|
||||
|
||||
## Incident Response
|
||||
|
||||
If a security incident occurs:
|
||||
|
||||
1. **Immediate Actions**
|
||||
- Rotate all secrets
|
||||
- Review access logs
|
||||
- Disable compromised accounts
|
||||
|
||||
2. **Investigation**
|
||||
- Analyze logs for unauthorized access
|
||||
- Check for data exfiltration
|
||||
- Review code changes
|
||||
|
||||
3. **Recovery**
|
||||
- Deploy security patches
|
||||
- Force password resets if needed
|
||||
- Notify affected users
|
||||
|
||||
4. **Prevention**
|
||||
- Update security practices
|
||||
- Implement additional monitoring
|
||||
- Conduct security audit
|
||||
@@ -0,0 +1,59 @@
|
||||
# Nginx Configuration Fix for Photo Authentication
|
||||
|
||||
If photos and thumbnails are not loading in gallery view but work in admin, it's likely that the Authorization header is being stripped by nginx or another reverse proxy.
|
||||
|
||||
## Common Issue
|
||||
|
||||
The `Authorization` header is often not passed through by default in nginx proxy configurations.
|
||||
|
||||
## Fix
|
||||
|
||||
Add these lines to your nginx configuration for the PicPeak location block:
|
||||
|
||||
```nginx
|
||||
location / {
|
||||
proxy_pass http://localhost:3001;
|
||||
|
||||
# Important: Pass the Authorization header
|
||||
proxy_pass_header Authorization;
|
||||
proxy_set_header Authorization $http_authorization;
|
||||
|
||||
# Other standard proxy headers
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
```
|
||||
|
||||
## Alternative Fix Using Traefik
|
||||
|
||||
If using Traefik, ensure headers are passed:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
picpeak:
|
||||
labels:
|
||||
- "traefik.http.middlewares.picpeak-headers.headers.customrequestheaders.Authorization="
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
1. Check if Authorization header is reaching the backend:
|
||||
```bash
|
||||
curl -H "Authorization: Bearer YOUR_TOKEN" https://picpeak.yourdomain.com/thumbnails/test.jpg -v
|
||||
```
|
||||
|
||||
2. Check nginx logs to see if the header is present:
|
||||
```bash
|
||||
tail -f /var/log/nginx/access.log
|
||||
```
|
||||
|
||||
## Docker Compose Fix
|
||||
|
||||
If using docker-compose with nginx proxy, add:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
- NGINX_PROXY_PASS_HEADER=Authorization
|
||||
```
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.4 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 450 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 390 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.4 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 412 KiB |
Reference in New Issue
Block a user