- Add Pydantic settings with trading mode validation (paper/testnet/live) - Implement Binance USDⓈ-M Futures adapter with hedge mode, isolated margin - Add type definitions for orders, positions, and market data - Create documentation (PLAN.md, ARCHITECTURE.md, SECURITY.md) - Add setup.sh with uv/pip auto-detection for consistent dev environments - Configure Docker multi-stage build and docker-compose services - Add pyproject.toml with all dependencies and tool configs
271 lines
5.8 KiB
Markdown
271 lines
5.8 KiB
Markdown
# TradeFinder Security Guidelines
|
|
|
|
## API Key Management
|
|
|
|
### Key Permissions
|
|
|
|
**Binance Futures API Keys**:
|
|
| Permission | Required | Notes |
|
|
|------------|----------|-------|
|
|
| Enable Futures | Yes | Required for USDⓈ-M trading |
|
|
| Enable Reading | Yes | Account info, positions, orders |
|
|
| Enable Spot & Margin Trading | No | Not needed for futures |
|
|
| Enable Withdrawals | **NEVER** | Do not enable under any circumstances |
|
|
| Enable Internal Transfer | No | Not needed |
|
|
|
|
### Key Separation
|
|
|
|
Maintain separate API keys for:
|
|
1. **Testnet** (paper trading): Lower security concern, can be more permissive
|
|
2. **Production** (live trading): Maximum security, IP whitelist required
|
|
|
|
```bash
|
|
# .env structure
|
|
BINANCE_TESTNET_API_KEY=xxx # Testnet keys
|
|
BINANCE_TESTNET_SECRET=xxx
|
|
|
|
BINANCE_API_KEY=xxx # Production keys (empty until ready)
|
|
BINANCE_SECRET=xxx
|
|
```
|
|
|
|
### IP Whitelisting
|
|
|
|
For production keys:
|
|
1. Enable IP restriction in Binance API settings
|
|
2. Whitelist only the server IP running the bot
|
|
3. If using Docker, whitelist the host machine's public IP
|
|
|
|
---
|
|
|
|
## Secrets Storage
|
|
|
|
### Environment Variables (Required)
|
|
|
|
All secrets must be stored in environment variables:
|
|
|
|
```bash
|
|
# Local development
|
|
cp .env.example .env
|
|
chmod 600 .env # Restrict file permissions
|
|
|
|
# Docker deployment
|
|
docker run --env-file .env tradefinder
|
|
```
|
|
|
|
### What NOT to Do
|
|
|
|
| Violation | Risk |
|
|
|-----------|------|
|
|
| Commit `.env` to git | Keys exposed in repo history forever |
|
|
| Hardcode keys in source | Keys exposed to anyone with code access |
|
|
| Log API keys | Keys visible in log files |
|
|
| Share testnet keys | Still bad practice, builds bad habits |
|
|
|
|
### .gitignore
|
|
|
|
Ensure these patterns are in `.gitignore`:
|
|
```gitignore
|
|
.env
|
|
.env.*
|
|
!.env.example
|
|
*.pem
|
|
*.key
|
|
secrets/
|
|
```
|
|
|
|
---
|
|
|
|
## Logging Security
|
|
|
|
### Sensitive Data Handling
|
|
|
|
```python
|
|
# BAD - Never log secrets
|
|
logger.info(f"API Key: {api_key}")
|
|
|
|
# GOOD - Mask sensitive data
|
|
logger.info(f"API Key: {api_key[:4]}...{api_key[-4:]}")
|
|
|
|
# BEST - Don't log at all
|
|
logger.info("API credentials loaded successfully")
|
|
```
|
|
|
|
### Structlog Configuration
|
|
|
|
```python
|
|
# Filter sensitive fields from logs
|
|
def mask_sensitive(_, __, event_dict):
|
|
sensitive_keys = ['api_key', 'secret', 'password', 'token']
|
|
for key in sensitive_keys:
|
|
if key in event_dict:
|
|
event_dict[key] = "***MASKED***"
|
|
return event_dict
|
|
```
|
|
|
|
---
|
|
|
|
## Network Security
|
|
|
|
### API Endpoints
|
|
|
|
| Environment | Base URL | Notes |
|
|
|-------------|----------|-------|
|
|
| Testnet | `https://testnet.binancefuture.com` | Safe for testing |
|
|
| Production | `https://fapi.binance.com` | Real money |
|
|
|
|
### Request Signing
|
|
|
|
All authenticated requests must be signed:
|
|
```python
|
|
import hmac
|
|
import hashlib
|
|
|
|
def sign_request(params: dict, secret: str) -> str:
|
|
query_string = urlencode(params)
|
|
signature = hmac.new(
|
|
secret.encode('utf-8'),
|
|
query_string.encode('utf-8'),
|
|
hashlib.sha256
|
|
).hexdigest()
|
|
return signature
|
|
```
|
|
|
|
### Rate Limiting
|
|
|
|
Respect Binance rate limits to avoid IP bans:
|
|
| Limit Type | Value |
|
|
|------------|-------|
|
|
| Request weight | 2400/minute |
|
|
| Order rate | 300/minute |
|
|
| WebSocket connections | 5/second |
|
|
|
|
---
|
|
|
|
## Docker Security
|
|
|
|
### Container Isolation
|
|
|
|
```yaml
|
|
# docker-compose.yml security settings
|
|
services:
|
|
engine:
|
|
security_opt:
|
|
- no-new-privileges:true
|
|
read_only: true
|
|
tmpfs:
|
|
- /tmp
|
|
user: "1000:1000" # Non-root user
|
|
```
|
|
|
|
### Secrets in Docker
|
|
|
|
```yaml
|
|
# Use Docker secrets (production)
|
|
secrets:
|
|
binance_api_key:
|
|
file: ./secrets/binance_api_key.txt
|
|
binance_secret:
|
|
file: ./secrets/binance_secret.txt
|
|
|
|
services:
|
|
engine:
|
|
secrets:
|
|
- binance_api_key
|
|
- binance_secret
|
|
```
|
|
|
|
---
|
|
|
|
## Operational Security
|
|
|
|
### Pre-Deployment Checklist
|
|
|
|
- [ ] API keys have NO withdrawal permission
|
|
- [ ] Production keys are IP-whitelisted
|
|
- [ ] `.env` is not in git history
|
|
- [ ] Logs do not contain secrets
|
|
- [ ] Container runs as non-root
|
|
- [ ] Redis is not exposed to public network
|
|
- [ ] DuckDB file has restricted permissions
|
|
|
|
### Monitoring for Compromise
|
|
|
|
Watch for:
|
|
- Unexpected positions or orders
|
|
- API calls from unknown IPs (check Binance API logs)
|
|
- Unusual account balance changes
|
|
- Failed authentication attempts
|
|
|
|
### Incident Response
|
|
|
|
If keys are compromised:
|
|
1. **Immediately** delete API key in Binance console
|
|
2. Check for unauthorized trades/withdrawals
|
|
3. Generate new API key with fresh permissions
|
|
4. Review how compromise occurred
|
|
5. Update security practices
|
|
|
|
---
|
|
|
|
## Testing Security
|
|
|
|
### Testnet Isolation
|
|
|
|
- Always start with testnet credentials
|
|
- Verify `TRADING_MODE=testnet` before any trade logic
|
|
- Production code should fail-safe if mode is unclear
|
|
|
|
```python
|
|
def validate_mode(config: Config) -> None:
|
|
if config.trading_mode == TradingMode.LIVE:
|
|
if not config.binance_api_key:
|
|
raise ValueError("Production API key required for live trading")
|
|
if config.binance_testnet_api_key:
|
|
logger.warning("Testnet keys present in live mode - ignoring")
|
|
```
|
|
|
|
### Paper Trading
|
|
|
|
For in-house simulation (no API needed):
|
|
- Use simulated order fills
|
|
- No actual API calls
|
|
- Safe for strategy development
|
|
|
|
---
|
|
|
|
## Dependency Security
|
|
|
|
### Regular Updates
|
|
|
|
```bash
|
|
# Check for security vulnerabilities
|
|
pip audit
|
|
|
|
# Update dependencies
|
|
pip install --upgrade -r requirements.txt
|
|
```
|
|
|
|
### Pinned Versions
|
|
|
|
Use exact versions in production:
|
|
```toml
|
|
# pyproject.toml
|
|
dependencies = [
|
|
"ccxt>=4.2.0,<5.0.0", # Pin major version
|
|
"pydantic>=2.5.0,<3.0.0",
|
|
]
|
|
```
|
|
|
|
---
|
|
|
|
## Summary
|
|
|
|
| Category | Requirement |
|
|
|----------|-------------|
|
|
| API Keys | No withdrawal permission, IP whitelisted |
|
|
| Secrets | Environment variables only, never committed |
|
|
| Logging | Mask all sensitive data |
|
|
| Network | HTTPS only, signed requests |
|
|
| Container | Non-root, read-only where possible |
|
|
| Monitoring | Watch for unauthorized activity |
|