Skip to content

Latest commit

 

History

History
298 lines (213 loc) · 8.38 KB

File metadata and controls

298 lines (213 loc) · 8.38 KB

Enclaved BitGo Express

A secure, mTLS-enabled cryptocurrency signing server with two operational modes: Enclaved Express (dedicated signer) and Master Express (API gateway with integrated signing capabilities).

Overview

This application provides secure cryptocurrency operations with mutual TLS (mTLS) authentication:

  • Enclaved Mode: Lightweight signing server for secure key operations
  • Master Express Mode: Full BitGo Express functionality with integrated signing
  • mTLS Security: Client certificate validation for secure communications
  • Flexible Configuration: Environment-based setup with file or variable-based certificates

Architecture

  • Enclaved Express (Port 3080): Focused signing operations with KMS integration
  • Master Express (Port 3081): Full BitGo API functionality with secure communication to Enclaved Express

Configuration

Configuration is managed through environment variables:

Required Settings

  • APP_MODE - Application mode (required: "enclaved" or "master-express")

Network Settings

  • BIND - Address to bind to (default: localhost)
  • TIMEOUT - Request timeout in milliseconds (default: 305000)
  • KEEP_ALIVE_TIMEOUT - Keep-alive timeout (optional)
  • HEADERS_TIMEOUT - Headers timeout (optional)

Enclaved Mode Specific

  • ENCLAVED_EXPRESS_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)
  • ENCLAVED_EXPRESS_URL - Enclaved Express server URL (required)
  • ENCLAVED_EXPRESS_CERT - Path to Enclaved Express server certificate (required)

TLS/mTLS Configuration

Both modes use the same TLS configuration variables:

TLS Mode

  • TLS_MODE - Set to either "mtls" or "disabled" (defaults to "mtls" if not set)

Certificate Configuration (required when TLS_MODE=mtls)

Option 1: Certificate Files

  • TLS_KEY_PATH - Path to private key file
  • TLS_CERT_PATH - Path to certificate file

Option 2: Environment Variables

  • TLS_KEY - Private key content (PEM format)
  • TLS_CERT - Certificate content (PEM format)

mTLS Settings (when TLS_MODE=mtls)

  • MTLS_REQUEST_CERT - Request client certificates (default: true)
  • ALLOW_SELF_SIGNED - Allow self-signed certificates (default: false)
  • MTLS_ALLOWED_CLIENT_FINGERPRINTS - Comma-separated list of allowed client certificate fingerprints (optional)

Logging and Debug

  • HTTP_LOGFILE - Path to HTTP request log file (optional, used by Morgan for HTTP access logs)

Quick Start

1. Generate Test Certificates

First, create self-signed certificates for testing:

# Generate private key
openssl genrsa -out server.key 2048

# Generate certificate
openssl req -new -x509 -key server.key -out server.crt -days 365 -subj "/CN=localhost"

2. Start Enclaved Express

export APP_MODE=enclaved
export KMS_URL=https://your-kms-service
export TLS_KEY_PATH=./server.key
export TLS_CERT_PATH=./server.crt
export MTLS_REQUEST_CERT=true
export ALLOW_SELF_SIGNED=true
npm start

4. Start Master Express

In a separate terminal:

export APP_MODE=master-express
export BITGO_ENV=test
export TLS_KEY_PATH=./server.key
export TLS_CERT_PATH=./server.crt
export ENCLAVED_EXPRESS_URL=https://localhost:3080
export ENCLAVED_EXPRESS_CERT=./server.crt
export MTLS_REQUEST_CERT=false
export ALLOW_SELF_SIGNED=true
npm start

5. Test the Connection

Test that Master Express can communicate with Enclaved Express:

curl -k -X POST https://localhost:3081/ping/enclavedExpress

Production Configuration

Security 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

Production Setup Example

Enclaved Express (Production)

export APP_MODE=enclaved
export KMS_URL=https://production-kms.example.com
export TLS_KEY_PATH=/secure/path/enclaved.key
export TLS_CERT_PATH=/secure/path/enclaved.crt
export MTLS_REQUEST_CERT=true
export ALLOW_SELF_SIGNED=false
export MTLS_ALLOWED_CLIENT_FINGERPRINTS=ABC123...,DEF456...
npm start

Master Express (Production)

export APP_MODE=master-express
export BITGO_ENV=prod
export TLS_KEY_PATH=/secure/path/master.key
export TLS_CERT_PATH=/secure/path/master.crt
export ENCLAVED_EXPRESS_URL=https://enclaved.internal.example.com:3080
export ENCLAVED_EXPRESS_CERT=/secure/path/enclaved.crt
export MTLS_REQUEST_CERT=true
export ALLOW_SELF_SIGNED=false
npm start

Container Deployment with Podman

First, build the container image:

# For Master Express (default port 3081)
npm run container:build

# For Enclaved Express (port 3080)
npm run container:build --build-arg PORT=3080

For local development, you'll need to run both the Enclaved Express and Master Express containers:

# Start Enclaved Express container
podman run -d \
  -p 3080:3080 \
  -v $(pwd)/certs:/app/certs:Z \
  -e APP_MODE=enclaved \
  -e BIND=0.0.0.0 \
  -e TLS_MODE=mtls \
  -e TLS_KEY_PATH=/app/certs/enclaved-express-key.pem \
  -e TLS_CERT_PATH=/app/certs/enclaved-express-cert.pem \
  -e KMS_URL=host.containers.internal:3000 \
  -e NODE_ENV=development \
  -e ALLOW_SELF_SIGNED=true \
  bitgo-onprem-express

# View logs
podman logs -f <container_id>

# Test the endpoint (note: using https)
curl -k -X POST https://localhost:3080/ping

# Start Master Express container
podman run -d \
  -p 3081:3081 \
  -v $(pwd)/certs:/app/certs:Z \
  -e APP_MODE=master-express \
  -e BIND=0.0.0.0 \
  -e TLS_MODE=mtls \
  -e TLS_KEY_PATH=/app/certs/test-ssl-key.pem \
  -e TLS_CERT_PATH=/app/certs/test-ssl-cert.pem \
  -e ENCLAVED_EXPRESS_URL=https://host.containers.internal:3080 \
  -e ENCLAVED_EXPRESS_CERT=/app/certs/enclaved-express-cert.pem \
  -e ALLOW_SELF_SIGNED=true \
  bitgo-onprem-express

# View logs
podman logs -f <container_id>

# Test the endpoints (note: using https and mTLS)
# For Enclaved Express
curl -k --cert certs/test-ssl-cert.pem --key certs/enclaved-express-key.pem -X POST https://localhost:3080/ping

# For Master Express
curl -k --cert certs/test-ssl-cert.pem --key certs/test-ssl-key.pem -X POST https://localhost:3081/ping

# Test the connection
curl -k -X POST https://localhost:3081/ping/enclavedExpress

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
  • The logs directory will be created with appropriate permissions if it doesn't exist

API Endpoints

Enclaved Express (Port 3080)

  • POST /ping - Health check
  • GET /version - Version information
  • POST /:coin/key/independent - Generate independent keychain

Master Express (Port 3081)

  • POST /ping - Health check
  • GET /version - Version information
  • POST /ping/enclavedExpress - Test connection to Enclaved Express
  • POST /api/:coin/wallet/generate - Generate wallet (with Enclaved Express integration)

Troubleshooting

Common Issues

1. Certificate Loading Errors

# Check certificate file paths and permissions
ls -la /path/to/certificates/
# Verify certificate format
openssl x509 -in certificate.crt -text -noout

2. mTLS Authentication Failures

  • Verify client certificates are provided
  • Check ALLOW_SELF_SIGNED setting matches certificate type
  • Confirm client certificate fingerprints are in allowlist
  • Ensure both services use compatible TLS settings

3. Connection Refused

  • Verify both services are running on correct ports
  • Check firewall settings
  • Confirm URLs use https:// prefix
  • Test basic connectivity with curl

4. Environment Variable Issues

# Check that required variables are set
env | grep -E "(APP_MODE|KMS_URL|ENCLAVED_EXPRESS|TLS_)"

Debug Mode

Enable debug logging for detailed troubleshooting:

DEBUG_NAMESPACE=enclaved:*,master:* npm run start

License

MIT