first commit
This commit is contained in:
277
SECURITY.md
Normal file
277
SECURITY.md
Normal file
@@ -0,0 +1,277 @@
|
||||
# MinIO Security Guide
|
||||
|
||||
## Console Access Security
|
||||
|
||||
### Production Console Access Options
|
||||
|
||||
#### ✅ Option 1: SSH Tunnel (Most Secure - RECOMMENDED)
|
||||
|
||||
**Don't expose console to internet at all.** Access via SSH tunnel:
|
||||
|
||||
```bash
|
||||
# From your local machine
|
||||
ssh -L 9001:localhost:9001 user@your-server
|
||||
|
||||
# Then access: http://localhost:9001
|
||||
```
|
||||
|
||||
**Pros:**
|
||||
- No public exposure
|
||||
- No additional authentication needed
|
||||
- Protected by SSH security
|
||||
|
||||
**Cons:**
|
||||
- Requires SSH access
|
||||
- Not convenient for multiple team members
|
||||
|
||||
---
|
||||
|
||||
#### ✅ Option 2: Domain with Traefik BasicAuth (Recommended for Teams)
|
||||
|
||||
Expose console via HTTPS with double authentication:
|
||||
|
||||
**Setup Steps:**
|
||||
|
||||
1. **Generate BasicAuth credentials:**
|
||||
```bash
|
||||
# Install htpasswd (if not installed)
|
||||
sudo apt-get install apache2-utils # Ubuntu/Debian
|
||||
# OR
|
||||
brew install httpd # macOS
|
||||
|
||||
# Generate password hash
|
||||
htpasswd -nb admin YourStrongPassword123
|
||||
|
||||
# Output example:
|
||||
# admin:$apr1$xyz123$abc...def
|
||||
```
|
||||
|
||||
2. **Add to production `.env`:**
|
||||
```bash
|
||||
# Double authentication: BasicAuth + MinIO login
|
||||
TRAEFIK_CONSOLE_AUTH='admin:$$apr1$$xyz123$$abc...def' # Note: $$ for docker-compose
|
||||
```
|
||||
|
||||
3. **Update docker-compose.prod.yml** (already done):
|
||||
```yaml
|
||||
- "traefik.http.routers.minio-console.middlewares=minio-auth"
|
||||
- "traefik.http.middlewares.minio-auth.basicauth.users=${TRAEFIK_CONSOLE_AUTH}"
|
||||
```
|
||||
|
||||
4. **Access:** https://console.crewsportswear.com
|
||||
- First: Browser BasicAuth prompt (admin/YourStrongPassword123)
|
||||
- Second: MinIO login (your MINIO_ROOT_USER/PASSWORD)
|
||||
|
||||
**Pros:**
|
||||
- Double authentication layer
|
||||
- Works from anywhere
|
||||
- Can share with team
|
||||
|
||||
**Cons:**
|
||||
- Console still publicly accessible (but protected)
|
||||
- Need to manage two sets of credentials
|
||||
|
||||
---
|
||||
|
||||
#### ⚠️ Option 3: IP Whitelist (For Fixed IPs)
|
||||
|
||||
Add IP restriction to BasicAuth:
|
||||
|
||||
```yaml
|
||||
# In docker-compose.prod.yml labels
|
||||
- "traefik.http.middlewares.minio-ipwhitelist.ipwhitelist.sourcerange=YOUR_IP/32,OFFICE_IP/32"
|
||||
- "traefik.http.routers.minio-console.middlewares=minio-auth,minio-ipwhitelist"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### ❌ Option 4: Public Console (NOT RECOMMENDED)
|
||||
|
||||
**Never do this in production:**
|
||||
- Exposed to brute force attacks
|
||||
- Admin panel publicly accessible
|
||||
- Single point of failure if credentials leaked
|
||||
|
||||
---
|
||||
|
||||
## S3 API Endpoint Security
|
||||
|
||||
The S3 API endpoint (`minio.crewsportswear.com`) **should remain public** for:
|
||||
- Application file uploads/downloads
|
||||
- Direct image access
|
||||
- S3 API operations
|
||||
|
||||
**Why it's safe:**
|
||||
- Requires valid access keys
|
||||
- Bucket policies control access
|
||||
- Can't browse/delete without credentials
|
||||
|
||||
**Example public URL:**
|
||||
```
|
||||
https://minio.crewsportswear.com/crewsportswear/images/product.jpg
|
||||
```
|
||||
|
||||
Only publicly readable paths (like `/images/`) are accessible. Private uploads require auth.
|
||||
|
||||
---
|
||||
|
||||
## Production Security Checklist
|
||||
|
||||
### 1. Strong Credentials
|
||||
```bash
|
||||
# Generate strong password
|
||||
openssl rand -base64 32
|
||||
|
||||
# Update .env
|
||||
MINIO_ROOT_USER=admin_$(date +%s) # Unique username
|
||||
MINIO_ROOT_PASSWORD=<generated_password>
|
||||
```
|
||||
|
||||
### 2. Console Access
|
||||
- [ ] Use SSH tunnel OR
|
||||
- [ ] Enable Traefik BasicAuth
|
||||
- [ ] Consider IP whitelist
|
||||
- [ ] Never expose without protection
|
||||
|
||||
### 3. Bucket Policies
|
||||
```bash
|
||||
# Only make necessary paths public
|
||||
mc anonymous set download crewminio/crewsportswear/images/
|
||||
|
||||
# Keep uploads private
|
||||
mc anonymous set none crewminio/crewsportswear/uploads/
|
||||
```
|
||||
|
||||
### 4. Application Access Keys
|
||||
|
||||
Create separate access keys per app (don't use root credentials):
|
||||
|
||||
```bash
|
||||
# Access MinIO console → Administrator → Users → Create User
|
||||
# Or via mc:
|
||||
mc admin user add crewminio crewsportswear-app <password>
|
||||
mc admin policy attach crewminio readwrite --user crewsportswear-app
|
||||
```
|
||||
|
||||
Then use in app:
|
||||
```bash
|
||||
MINIO_KEY=crewsportswear-app
|
||||
MINIO_SECRET=<password>
|
||||
```
|
||||
|
||||
### 5. Network Segmentation
|
||||
```yaml
|
||||
# Apps should access MinIO via internal network
|
||||
MINIO_ENDPOINT=http://crew-minio:9000 # Internal
|
||||
# Not: https://minio.crewsportswear.com (external)
|
||||
```
|
||||
|
||||
### 6. HTTPS Only
|
||||
```yaml
|
||||
environment:
|
||||
- MINIO_SERVER_URL=https://minio.crewsportswear.com # Force HTTPS
|
||||
```
|
||||
|
||||
### 7. Regular Backups
|
||||
```bash
|
||||
# Automated daily backup
|
||||
mc mirror crewminio/ /var/backups/minio/$(date +%Y%m%d)/
|
||||
```
|
||||
|
||||
### 8. Monitor Access Logs
|
||||
```bash
|
||||
# Enable audit logging
|
||||
docker exec crew-minio-prod mc admin trace crewminio
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Recommended Production Setup
|
||||
|
||||
### For Solo Developer:
|
||||
```yaml
|
||||
# Don't expose console publicly
|
||||
# Remove console Traefik labels
|
||||
# Access via SSH tunnel only
|
||||
```
|
||||
|
||||
### For Small Team (2-5 people):
|
||||
```yaml
|
||||
# Use BasicAuth + MinIO login (double auth)
|
||||
# IP whitelist to office/VPN
|
||||
# Strong passwords (32+ chars)
|
||||
```
|
||||
|
||||
### For Larger Team:
|
||||
```yaml
|
||||
# Use VPN (Tailscale/WireGuard) + internal console
|
||||
# Separate access keys per app/user
|
||||
# Audit logging enabled
|
||||
# Regular security reviews
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Quick Setup Commands
|
||||
|
||||
### Secure Console (BasicAuth)
|
||||
|
||||
```bash
|
||||
# 1. Generate password
|
||||
htpasswd -nb admin $(openssl rand -base64 16)
|
||||
|
||||
# Output: admin:$apr1$xyz...
|
||||
# Copy this to .env
|
||||
|
||||
# 2. Update .env
|
||||
cat >> .env << EOF
|
||||
TRAEFIK_CONSOLE_AUTH='admin:\$\$apr1\$\$xyz...' # Escape $ with $$
|
||||
EOF
|
||||
|
||||
# 3. Restart
|
||||
docker-compose -f docker-compose.prod.yml up -d
|
||||
```
|
||||
|
||||
### SSH Tunnel (No Public Console)
|
||||
|
||||
```bash
|
||||
# 1. Remove console Traefik labels from docker-compose.prod.yml
|
||||
# 2. Don't expose port 9001
|
||||
# 3. Access via SSH:
|
||||
ssh -L 9001:localhost:9001 user@server
|
||||
# Then: http://localhost:9001
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Emergency: Credentials Compromised
|
||||
|
||||
```bash
|
||||
# 1. Immediately change root password
|
||||
docker exec crew-minio-prod mc admin user update crewminio minioadmin --password NewPassword123
|
||||
|
||||
# 2. Revoke leaked access keys
|
||||
docker exec crew-minio-prod mc admin user disable crewminio leaked-user
|
||||
|
||||
# 3. Review access logs
|
||||
docker exec crew-minio-prod mc admin trace crewminio
|
||||
|
||||
# 4. Rotate application keys
|
||||
# Update all apps with new credentials
|
||||
|
||||
# 5. Check for unauthorized files
|
||||
docker exec crew-minio-prod mc ls --recursive crewminio/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
| Access Method | Security Level | Use Case |
|
||||
|--------------|----------------|----------|
|
||||
| SSH Tunnel | ⭐⭐⭐⭐⭐ | Solo dev, maximum security |
|
||||
| BasicAuth + IP | ⭐⭐⭐⭐ | Small team, fixed IPs |
|
||||
| BasicAuth Only | ⭐⭐⭐ | Remote team, can't use VPN |
|
||||
| Public Console | ⭐ | **NEVER USE** |
|
||||
|
||||
**Recommendation:** Start with SSH tunnel. Add BasicAuth only if multiple people need access.
|
||||
Reference in New Issue
Block a user