backend redesign
This commit is contained in:
192
doc/auth.md
192
doc/auth.md
@@ -1,192 +0,0 @@
|
||||
# Authentication & Secrets Management Guide
|
||||
|
||||
## Overview
|
||||
|
||||
Your system now has a complete encrypted secrets management solution with WebSocket authentication. All secrets (like API keys) are stored in an encrypted file, protected by a master password that users enter when connecting.
|
||||
|
||||
## Architecture
|
||||
|
||||
### Backend Components
|
||||
|
||||
1. **Secrets Store** (`backend/src/secrets_manager/`)
|
||||
- `crypto.py` - Argon2id password hashing + Fernet (AES-256) encryption
|
||||
- `store.py` - SecretsStore class for managing encrypted secrets
|
||||
- `cli.py` - Command-line interface for secrets management
|
||||
|
||||
2. **Encrypted Storage**
|
||||
- `backend/data/secrets.enc` - Encrypted secrets file
|
||||
- `backend/data/.master.key` - Salt + verification hash (never stores actual password)
|
||||
- Both files are created with 0600 permissions (owner-only access)
|
||||
|
||||
3. **WebSocket Authentication** (`backend/src/main.py`)
|
||||
- First message must be `auth` message
|
||||
- On first use: requires password + confirmation → initializes secrets store
|
||||
- Subsequent uses: requires password → unlocks secrets store
|
||||
- Failed auth closes connection immediately
|
||||
|
||||
### Frontend Components
|
||||
|
||||
1. **Login Screen** (`web/src/components/LoginScreen.vue`)
|
||||
- Shows before WebSocket connection
|
||||
- Detects first-time setup and shows confirmation field
|
||||
- Displays error messages for failed authentication
|
||||
|
||||
2. **WebSocket Manager** (`web/src/composables/useWebSocket.ts`)
|
||||
- Updated to send auth message on connect
|
||||
- Returns auth result (success/failure)
|
||||
- Prevents reconnection on auth failure
|
||||
|
||||
3. **App Integration** (`web/src/App.vue`)
|
||||
- Shows login screen until authenticated
|
||||
- Initializes state sync only after successful auth
|
||||
|
||||
## Security Features
|
||||
|
||||
✓ **Password-based encryption** - Argon2id (OWASP recommended)
|
||||
✓ **AES-256 encryption** - Industry-standard Fernet cipher
|
||||
✓ **Salted passwords** - Unique salt per installation
|
||||
✓ **No plaintext storage** - Master password never stored
|
||||
✓ **Restricted permissions** - Secrets files are 0600 (owner-only)
|
||||
✓ **Constant-time verification** - Prevents timing attacks
|
||||
✓ **Auto-lock on disconnect** - Secrets cleared from memory
|
||||
|
||||
## Usage
|
||||
|
||||
### First Time Setup
|
||||
|
||||
1. Start backend: `cd backend && python -m uvicorn src.main:app --reload --port 8080`
|
||||
2. Start frontend: `cd web && npm run dev`
|
||||
3. Open browser - you'll see "Welcome" screen
|
||||
4. Create a master password (with confirmation)
|
||||
5. System automatically migrates `ANTHROPIC_API_KEY` from `.env` to encrypted store
|
||||
|
||||
### Subsequent Logins
|
||||
|
||||
1. Start backend and frontend
|
||||
2. Enter your master password
|
||||
3. System unlocks and connects
|
||||
|
||||
### Managing Secrets (CLI)
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
|
||||
# List all secrets
|
||||
python -m secrets_manager.cli list
|
||||
|
||||
# Add a new secret
|
||||
python -m secrets_manager.cli set MY_SECRET "secret-value"
|
||||
|
||||
# Get a secret
|
||||
python -m secrets_manager.cli get ANTHROPIC_API_KEY
|
||||
|
||||
# Change master password
|
||||
python -m secrets_manager.cli change-password
|
||||
|
||||
# Backup secrets (encrypted)
|
||||
python -m secrets_manager.cli export backup.enc
|
||||
|
||||
# Migrate from .env file
|
||||
python -m secrets_manager.cli migrate-from-env
|
||||
```
|
||||
|
||||
### Managing Secrets (Python)
|
||||
|
||||
```python
|
||||
from secrets_manager import SecretsStore
|
||||
|
||||
# Initialize (first time)
|
||||
store = SecretsStore()
|
||||
store.initialize("my-password")
|
||||
|
||||
# Unlock (subsequent times)
|
||||
store = SecretsStore()
|
||||
store.unlock("my-password")
|
||||
|
||||
# Use secrets
|
||||
api_key = store.get("ANTHROPIC_API_KEY")
|
||||
store.set("NEW_SECRET", "value")
|
||||
store.delete("OLD_SECRET")
|
||||
|
||||
# Change password
|
||||
store.change_master_password("old-password", "new-password")
|
||||
```
|
||||
|
||||
## Protocol
|
||||
|
||||
### Authentication Flow
|
||||
|
||||
```
|
||||
Client → Server: { type: "auth", password: "...", confirm_password: "..." }
|
||||
Server → Client: { type: "auth_response", success: true, message: "..." }
|
||||
|
||||
# If initialization needed:
|
||||
Client → Server: { type: "auth", password: "...", confirm_password: "..." }
|
||||
Server → Client: { type: "auth_response", success: false, needs_confirmation: true, ... }
|
||||
Client → Server: { type: "auth", password: "same", confirm_password: "same" }
|
||||
Server → Client: { type: "auth_response", success: true, message: "Initialized" }
|
||||
|
||||
# After successful auth, normal protocol continues:
|
||||
Client → Server: { type: "hello", seqs: {...} }
|
||||
Server → Client: { type: "snapshot", ... }
|
||||
```
|
||||
|
||||
### Error Codes
|
||||
|
||||
- `1008` - Authentication failed (invalid password)
|
||||
- `1011` - Internal error during authentication
|
||||
|
||||
## Migration from .env
|
||||
|
||||
The system automatically migrates `ANTHROPIC_API_KEY` from `.env` when you first initialize the secrets store through the web interface. You can also use the CLI:
|
||||
|
||||
```bash
|
||||
python -m secrets_manager.cli migrate-from-env
|
||||
# This will ask if you want to delete .env after migration
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
1. **Master Password Strength** - Use a strong password (8+ characters recommended)
|
||||
2. **Backup** - Export encrypted backups regularly: `python -m secrets_manager.cli export backup.enc`
|
||||
3. **Environment** - Can still fall back to `.env` if secrets store not unlocked (for development)
|
||||
4. **Transport** - Use HTTPS/WSS in production (currently using HTTP/WS for development)
|
||||
|
||||
## File Locations
|
||||
|
||||
```
|
||||
backend/
|
||||
├── data/
|
||||
│ ├── secrets.enc # Encrypted secrets (created on first auth)
|
||||
│ ├── .master.key # Salt + verification (created on first auth)
|
||||
│ └── checkpoints.db # Agent state (existing)
|
||||
└── src/
|
||||
└── secrets/ # Secrets management module
|
||||
├── __init__.py
|
||||
├── crypto.py # Cryptographic primitives
|
||||
├── store.py # SecretsStore class
|
||||
└── cli.py # Command-line interface
|
||||
|
||||
web/
|
||||
└── src/
|
||||
├── components/
|
||||
│ └── LoginScreen.vue # Authentication UI
|
||||
└── composables/
|
||||
└── useWebSocket.ts # Updated with auth support
|
||||
```
|
||||
|
||||
## Development Tips
|
||||
|
||||
1. **Testing First-Time Setup**: Delete `backend/data/.master.key` to simulate first-time setup
|
||||
2. **Reset Password**: Delete both `.master.key` and `secrets.enc`, then reconnect
|
||||
3. **Debug Auth**: Check backend logs for authentication attempts
|
||||
4. **Bypass Auth (Dev)**: Set `ANTHROPIC_API_KEY` in `.env` and don't initialize secrets store
|
||||
|
||||
## Next Steps
|
||||
|
||||
Consider adding:
|
||||
- [ ] Password reset mechanism (security questions or backup codes)
|
||||
- [ ] Session timeout / auto-lock
|
||||
- [ ] Multi-user support with different passwords
|
||||
- [ ] Secret versioning / audit log
|
||||
- [ ] Integration with external secret managers (Vault, AWS Secrets Manager)
|
||||
Reference in New Issue
Block a user