diff --git a/README.md b/README.md index 1f9136c..b98c484 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Advanced Wallet Manager +# Advanced Wallets A secure, mTLS-enabled cryptocurrency signing server with two operational modes: Advanced Wallet Manager (dedicated signer) and Master Express (API gateway with integrated signing capabilities). @@ -6,197 +6,190 @@ A secure, mTLS-enabled cryptocurrency signing server with two operational modes: This application provides secure cryptocurrency operations with mutual TLS (mTLS) authentication: -- **Advanced Wallet Manager Mode**: Lightweight signing server for secure key operations -- **Master Express Mode**: Full BitGo Express functionality with integrated signing +- **Advanced Wallet Manager Mode**: Lightweight keygen/signing server for secure key operations. Includes support for recovery. +- **Master Express Mode**: An express app that acts as the orchestrator between the Advanced Wallet Manager and BitGo APIs. - **mTLS Security**: Client certificate validation for secure communications - **Flexible Configuration**: Environment-based setup with file or variable-based certificates ## Architecture -- **Advanced Wallet Manager** (Port 3080): Focused signing operations with KMS integration +- **Advanced Wallet Manager** (Port 3080): Isolated signing server with no internet access, only connects to KMS API for key operations. - **Master Express** (Port 3081): Full BitGo API functionality with secure communication to Advanced Wallet Manager -## Configuration - -Configuration is managed through environment variables: - -### Required Settings - -- `APP_MODE` - Application mode (required: "advanced-wallet-manager" or "master-express") - -### Network Settings - -- `BIND` - Address to bind to (default: localhost) -- `IPC` - IPC socket file path (optional) -- `TIMEOUT` - Request timeout in milliseconds (default: 305000) -- `KEEP_ALIVE_TIMEOUT` - Keep-alive timeout (optional) -- `HEADERS_TIMEOUT` - Headers timeout (optional) - -#### Advanced Wallet Manager Mode Specific - -- `ADVANCED_WALLET_MANAGER_PORT` - Port to listen on (default: 3080) -- `KMS_URL` - KMS service URL (required) - -#### Master Express Mode Specific - -- `MASTER_EXPRESS_PORT` - Port to listen on (default: 3081) -- `BITGO_ENV` - BitGo environment (default: test) -- `BITGO_DISABLE_ENV_CHECK` - Disable environment check (default: true) -- `BITGO_AUTH_VERSION` - Authentication version (default: 2) -- `BITGO_CUSTOM_ROOT_URI` - Custom BitGo API root URI (optional) -- `BITGO_CUSTOM_BITCOIN_NETWORK` - Custom Bitcoin network (optional) -- `ADVANCED_WALLET_MANAGER_URL` - Advanced Wallet Manager URL (required) +## Installation -### TLS/mTLS Configuration +### Prerequisites -Both modes use the same TLS configuration variables: +- **Node.js** 22.1.0 or higher +- **npm** or **yarn** package manager +- **OpenSSL** for certificate generation +- **Docker** and **Docker Compose** (for containerized deployment) +- **Podman** (alternative to Docker for containerized deployment) -#### TLS Mode +### Setup -- `TLS_MODE` - Set to either "mtls" or "disabled" (defaults to "mtls" if not set) +1. **Clone the repository:** -#### mTLS Server Configuration (for incoming connections) +```bash +git clone +cd advanced-wallets +``` -- `SERVER_TLS_KEY_PATH` - Path to the private key for the mTLS server -- `SERVER_TLS_CERT_PATH` - Path to the certificate for the mTLS server -- `SERVER_TLS_KEY` - The private key as a string (alternative to `_PATH`) -- `SERVER_TLS_CERT` - The certificate as a string (alternative to `_PATH`) +2. **Install dependencies:** -#### mTLS Client Authentication Settings (for incoming connections) +```bash +npm install +``` -- `ALLOW_SELF_SIGNED` - Allow self-signed certificates (default: false) -- `MTLS_ALLOWED_CLIENT_FINGERPRINTS` - Comma-separated list of allowed client certificate fingerprints (optional) +3. **Build the project:** -#### Outbound mTLS to AWM (Master Express Mode only) +```bash +npm run build +``` -- `AWM_CLIENT_TLS_KEY_PATH` - Path to the client key that Master Express presents to the AWM -- `AWM_CLIENT_TLS_CERT_PATH` - Path to the client cert that Master Express presents to the AWM -- `AWM_CLIENT_TLS_KEY` - The client key as a string (alternative to `_PATH`) -- `AWM_CLIENT_TLS_CERT` - The client cert as a string (alternative to `_PATH`) -- `AWM_SERVER_CA_CERT_PATH` - Path to the CA certificate to verify the AWM server (required when TLS_MODE=mtls) -- `AWM_SERVER_CA_CERT` - The CA certificate as a string (alternative to `_PATH`) -- `AWM_SERVER_CERT_ALLOW_SELF_SIGNED` - Allow self-signed certificates from the AWM (default: false) -- **Required:** Client certificates must be explicitly provided for outbound mTLS connections +4. **Generate test certificates (optional):** -#### Outbound mTLS to KMS (AWM Mode only) +```bash +# Generate private key and certificate for testing +openssl genrsa -out demo.key 2048 +openssl req -new -x509 -key demo.key -out demo.crt -days 365 -subj "/CN=localhost" +``` -- `KMS_CLIENT_TLS_KEY_PATH` - Path to the client key that AWM presents to the KMS -- `KMS_CLIENT_TLS_CERT_PATH` - Path to the client cert that AWM presents to the KMS -- `KMS_CLIENT_TLS_KEY` - The client key as a string (alternative to `_PATH`) -- `KMS_CLIENT_TLS_CERT` - The client cert as a string (alternative to `_PATH`) -- `KMS_SERVER_CA_CERT_PATH` - Path to the CA certificate to verify the KMS server (required when TLS_MODE=mtls) -- `KMS_SERVER_CA_CERT` - The CA certificate as a string (alternative to `_PATH`) -- `KMS_SERVER_CERT_ALLOW_SELF_SIGNED` - Allow self-signed certificates from the KMS (default: false) -- **Required:** Client certificates must be explicitly provided for outbound mTLS connections +### Development Setup -### Logging and Debug +For local development, you can use nodemon for automatic restarts: -- `HTTP_LOGFILE` - Path to HTTP request log file (optional, used by Morgan for HTTP access logs) -- `NODE_ENV` - Node environment (development, production, test) -- `LOG_LEVEL` - Log level (silent, error, warn, info, http, debug) -- `RECOVERY_MODE` - Enable recovery mode (default: false) +```bash +# Install nodemon globally (if not already installed) +npm install -g nodemon -## Quick Start +# Start in development mode +npm start +``` -### 1. Generate Test Certificates +### Container Setup -First, create self-signed certificates for testing: +For containerized deployment, build the Docker images: ```bash -# Generate private key -openssl genrsa -out server.key 2048 +# Build Master Express (default port 3081) +npm run container:build -# Generate certificate -openssl req -new -x509 -key server.key -out server.crt -days 365 -subj "/CN=localhost" +# Build Advanced Wallet Manager (port 3080) +npm run container:build --build-arg PORT=3080 ``` -### 2. Start Advanced Wallet Manager +## Quick Start + +### 1. Start Advanced Wallet Manager ```bash export APP_MODE=advanced-wallet-manager export KMS_URL=https://your-kms-service -export KMS_SERVER_CA_CERT_PATH=./server.crt +export SERVER_TLS_KEY_PATH=./demo.key +export SERVER_TLS_CERT_PATH=./demo.crt +export KMS_CLIENT_TLS_KEY_PATH=./demo.key +export KMS_CLIENT_TLS_CERT_PATH=./demo.crt +export KMS_SERVER_CA_CERT_PATH=./demo.crt export KMS_SERVER_CERT_ALLOW_SELF_SIGNED=true -export SERVER_TLS_KEY_PATH=./server.key -export SERVER_TLS_CERT_PATH=./server.crt export CLIENT_CERT_ALLOW_SELF_SIGNED=true npm start ``` -### 3. Start Master Express +**Note:** KMS client certificates are required for outbound mTLS connections. For testing, we reuse the demo certificates, but in production, use separate certificates for security. -In a separate terminal: +### 2. Start Master Express ```bash export APP_MODE=master-express export BITGO_ENV=test -export SERVER_TLS_KEY_PATH=./server.key -export SERVER_TLS_CERT_PATH=./server.crt +export SERVER_TLS_KEY_PATH=./demo.key +export SERVER_TLS_CERT_PATH=./demo.crt export ADVANCED_WALLET_MANAGER_URL=https://localhost:3080 -export AWM_SERVER_CA_CERT_PATH=./server.crt +export AWM_CLIENT_TLS_KEY_PATH=./demo.key +export AWM_CLIENT_TLS_CERT_PATH=./demo.crt +export AWM_SERVER_CA_CERT_PATH=./demo.crt export AWM_SERVER_CERT_ALLOW_SELF_SIGNED=true export CLIENT_CERT_ALLOW_SELF_SIGNED=true npm start ``` -### 4. Test the Connection +**Note:** AWM client certificates are required for outbound mTLS connections to Advanced Wallet Manager. For testing, we reuse the demo certificates, but in production, use separate certificates for security. -Test that Master Express can communicate with Advanced Wallet Manager: +### 3. Test the Connection ```bash curl -k -X POST https://localhost:3081/ping/advancedWalletManager ``` -## Production Configuration +## Configuration -### Security Best Practices +### Core Settings -1. **Use CA-signed certificates** instead of self-signed -2. **Set `CLIENT_CERT_ALLOW_SELF_SIGNED=false`** in production -3. **Configure client certificate allowlisting** with `MTLS_ALLOWED_CLIENT_FINGERPRINTS` -4. **Use separate certificates** for each service -5. **Regularly rotate certificates** -6. **Secure private key storage** +| Variable | Description | Default | Required | +| ----------- | -------------------- | ------------- | ------------------------------------------------ | +| `APP_MODE` | Application mode | - | ✅ `advanced-wallet-manager` or `master-express` | +| `BIND` | Address to bind to | `localhost` | ❌ | +| `TIMEOUT` | Request timeout (ms) | `305000` | ❌ | +| `NODE_ENV` | Node environment | `development` | ❌ | +| `LOG_LEVEL` | Log level | `info` | ❌ | -### Production Setup Example +### Advanced Wallet Manager Settings -#### Advanced Wallet Manager (Production) +| Variable | Description | Default | Required | +| ------------------------------ | ----------------- | ------- | -------- | +| `ADVANCED_WALLET_MANAGER_PORT` | Port to listen on | `3080` | ❌ | +| `KMS_URL` | KMS service URL | - | ✅ | -```bash -export APP_MODE=advanced-wallet-manager -export KMS_URL=https://production-kms.example.com -export SERVER_TLS_KEY_PATH=/secure/path/awm-server.key -export SERVER_TLS_CERT_PATH=/secure/path/awm-server.crt -export KMS_CLIENT_TLS_KEY_PATH=/secure/path/awm-kms-client.key -export KMS_CLIENT_TLS_CERT_PATH=/secure/path/awm-kms-client.crt -export KMS_SERVER_CA_CERT_PATH=/secure/path/kms-ca.crt -export CLIENT_CERT_ALLOW_SELF_SIGNED=false -export MTLS_ALLOWED_CLIENT_FINGERPRINTS=ABC123...,DEF456... -npm start -``` +### Master Express Settings -**Note:** Client certificates for outbound connections must be separate from server certificates for security reasons. +| Variable | Description | Default | Required | +| ----------------------------- | --------------------------- | ------- | -------- | +| `MASTER_EXPRESS_PORT` | Port to listen on | `3081` | ❌ | +| `BITGO_ENV` | BitGo environment | `test` | ❌ | +| `ADVANCED_WALLET_MANAGER_URL` | Advanced Wallet Manager URL | - | ✅ | -#### Master Express (Production) +### TLS/mTLS Configuration -```bash -export APP_MODE=master-express -export BITGO_ENV=prod -export SERVER_TLS_KEY_PATH=/secure/path/master-server.key -export SERVER_TLS_CERT_PATH=/secure/path/master-server.crt -export AWM_CLIENT_TLS_KEY_PATH=/secure/path/master-awm-client.key -export AWM_CLIENT_TLS_CERT_PATH=/secure/path/master-awm-client.crt -export ADVANCED_WALLET_MANAGER_URL=https://advanced-wallet-manager.internal.example.com:3080 -export AWM_SERVER_CA_CERT_PATH=/secure/path/awm-ca.crt -export CLIENT_CERT_ALLOW_SELF_SIGNED=false -npm start -``` +#### Basic TLS Settings + +| Variable | Description | Default | +| ------------------- | ------------------------------- | ------- | +| `TLS_MODE` | TLS mode (`mtls` or `disabled`) | `mtls` | +| `ALLOW_SELF_SIGNED` | Allow self-signed certificates | `false` | + +#### Server Certificates (for incoming connections) + +| Variable | Description | Format | +| ---------------------- | -------------------------------- | ---------- | +| `SERVER_TLS_KEY_PATH` | Server private key file path | File path | +| `SERVER_TLS_CERT_PATH` | Server certificate file path | File path | +| `SERVER_TLS_KEY` | Server private key (alternative) | PEM string | +| `SERVER_TLS_CERT` | Server certificate (alternative) | PEM string | + +#### Client Authentication -**Note:** Client certificates for outbound connections must be separate from server certificates for security reasons. +| Variable | Description | Format | +| ---------------------------------- | --------------------------------------- | -------------------- | +| `MTLS_ALLOWED_CLIENT_FINGERPRINTS` | Allowed client certificate fingerprints | Comma-separated list | + +#### Outbound mTLS Certificates + +**For Master Express → Advanced Wallet Manager:** + +- `AWM_CLIENT_TLS_KEY_PATH` / `AWM_CLIENT_TLS_KEY` +- `AWM_CLIENT_TLS_CERT_PATH` / `AWM_CLIENT_TLS_CERT` +- `AWM_SERVER_CA_CERT_PATH` / `AWM_SERVER_CA_CERT` + +**For Advanced Wallet Manager → KMS:** + +- `KMS_CLIENT_TLS_KEY_PATH` / `KMS_CLIENT_TLS_KEY` +- `KMS_CLIENT_TLS_CERT_PATH` / `KMS_CLIENT_TLS_CERT` +- `KMS_SERVER_CA_CERT_PATH` / `KMS_SERVER_CA_CERT` ## Container Deployment with Podman -First, build the container image: +### Build Commands ```bash # For Master Express (default port 3081) @@ -206,6 +199,8 @@ npm run container:build npm run container:build --build-arg PORT=3080 ``` +### Run Containers + For local development, you'll need to run both the Advanced Wallet Manager and Master Express containers: ```bash @@ -257,7 +252,7 @@ curl -k --cert certs/test-ssl-cert.pem --key certs/test-ssl-key.pem -X POST http curl -k -X POST https://localhost:3081/ping/advancedWalletManager ``` -Notes: +**Notes:** - `host.containers.internal` is a special DNS name that resolves to the host machine from inside containers - The `:Z` option in volume mounts is specific to SELinux-enabled systems and ensures proper volume labeling @@ -279,12 +274,13 @@ The Docker Compose setup creates two isolated services: The setup creates two distinct networks: -1. **my-internal-network**: +1. **my-internal-network**: + - Internal bridge network with `internal: true` - Used for secure AWM isolation and MBE-to-AWM communication - No external internet access for security -2. **my-public-network**: +2. **my-public-network**: - Public bridge network - Used for external access to MBE APIs - Connected to host networking @@ -328,38 +324,66 @@ docker-compose down - `POST /ping/advancedWalletManager` - Test connection to Advanced Wallet Manager - `POST /api/:coin/wallet/generate` - Generate wallet (with Advanced Wallet Manager integration) -## Troubleshooting +## Production Security -### Common Issues +### Best Practices + +1. **Use CA-signed certificates** instead of self-signed +2. **Set `ALLOW_SELF_SIGNED=false`** in production +3. **Configure client certificate allowlisting** with `MTLS_ALLOWED_CLIENT_FINGERPRINTS` +4. **Use separate certificates** for each service +5. **Regularly rotate certificates** +6. **Secure private key storage** -#### 1. Certificate Loading Errors +### Production Example ```bash -# Check certificate file paths and permissions -ls -la /path/to/certificates/ -# Verify certificate format -openssl x509 -in certificate.crt -text -noout -``` +# Advanced Wallet Manager +export APP_MODE=advanced-wallet-manager +export KMS_URL=https://production-kms.example.com +export SERVER_TLS_KEY_PATH=/secure/awm-server.key +export SERVER_TLS_CERT_PATH=/secure/awm-server.crt +export KMS_CLIENT_TLS_KEY_PATH=/secure/awm-kms-client.key +export KMS_CLIENT_TLS_CERT_PATH=/secure/awm-kms-client.crt +export KMS_SERVER_CA_CERT_PATH=/secure/kms-ca.crt +export ALLOW_SELF_SIGNED=false +export MTLS_ALLOWED_CLIENT_FINGERPRINTS=ABC123...,DEF456... -#### 2. mTLS Authentication Failures +# Master Express +export APP_MODE=master-express +export BITGO_ENV=prod +export SERVER_TLS_KEY_PATH=/secure/master-server.key +export SERVER_TLS_CERT_PATH=/secure/master-server.crt +export AWM_CLIENT_TLS_KEY_PATH=/secure/master-awm-client.key +export AWM_CLIENT_TLS_CERT_PATH=/secure/master-awm-client.crt +export ADVANCED_WALLET_MANAGER_URL=https://awm.internal.example.com:3080 +export AWM_SERVER_CA_CERT_PATH=/secure/awm-ca.crt +export ALLOW_SELF_SIGNED=false +``` -- Verify client certificates are provided -- Check `CLIENT_CERT_ALLOW_SELF_SIGNED` setting matches certificate type -- Confirm client certificate fingerprints are in allowlist -- Ensure both services use compatible TLS settings +## Troubleshooting -#### 3. Connection Refused +### Common Issues -- Verify both services are running on correct ports -- Check firewall settings -- Confirm URLs use `https://` prefix -- Test basic connectivity with curl +| Issue | Solution | +| ---------------------------- | --------------------------------------------------- | +| Certificate loading errors | Check file paths, permissions, and format | +| mTLS authentication failures | Verify certificates, fingerprints, and TLS settings | +| Connection refused | Check ports, firewall, and URL format | +| Environment variable issues | Verify required variables are set | -#### 4. Environment Variable Issues +### Debug Commands ```bash -# Check that required variables are set +# Check certificate format +openssl x509 -in certificate.crt -text -noout + +# Verify environment variables env | grep -E "(APP_MODE|KMS_URL|ADVANCED_WALLET_MANAGER|TLS_)" + +# Test connectivity +curl -k -X POST https://localhost:3080/ping +curl -k -X POST https://localhost:3081/ping ``` ## License