Files
proxmox/docs/04-configuration/PHOENIX_VAULT_INTEGRATION_GUIDE.md
defiQUG fbda1b4beb
Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
docs: Ledger Live integration, contract deploy learnings, NEXT_STEPS updates
- ADD_CHAIN138_TO_LEDGER_LIVE: Ledger form done; public code review repo bis-innovations/LedgerLive; init/push commands
- CONTRACT_DEPLOYMENT_RUNBOOK: Chain 138 gas price 1 gwei, 36-addr check, TransactionMirror workaround
- CONTRACT_*: AddressMapper, MirrorManager deployed 2026-02-12; 36-address on-chain check
- NEXT_STEPS_FOR_YOU: Ledger done; steps completable now (no LAN); run-completable-tasks-from-anywhere
- MASTER_INDEX, OPERATOR_OPTIONAL, SMART_CONTRACTS_INVENTORY_SIMPLE: updates
- LEDGER_BLOCKCHAIN_INTEGRATION_COMPLETE: bis-innovations/LedgerLive reference

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 15:46:57 -08:00

451 lines
10 KiB
Markdown

# Phoenix Vault Integration Guide
**Last Updated:** 2026-01-31
**Document Version:** 1.0
**Status:** Active Documentation
---
**Date:** 2026-01-19
**Status:** ✅ Ready for Integration
**Purpose:** Guide for integrating Phoenix services with Vault cluster
---
## Overview
This guide provides step-by-step instructions for integrating Phoenix services (API, Portal, and other components) with the deployed Vault cluster.
---
## Prerequisites
- Vault cluster deployed and operational
- AppRole authentication configured
- AppRole credentials available
- Phoenix services ready for integration
---
## AppRole Credentials
AppRole credentials are stored in:
```
.secure/vault-credentials/phoenix-approle-credentials-YYYYMMDD.txt
```
**Phoenix API:**
- Role ID: `27f213e2-f15e-b6de-3cf4-db2f02029dd5`
- Secret ID: (stored in credentials file)
**Phoenix Portal:**
- Role ID: `70278dee-a85e-9007-c769-46b71a8c1460`
- Secret ID: (stored in credentials file)
---
## Integration Methods
### Method 1: Environment Variables (Recommended)
Set environment variables in your Phoenix service configuration:
```bash
export VAULT_ADDR=http://192.168.11.200:8200
export VAULT_ROLE_ID=<your-role-id>
export VAULT_SECRET_ID=<your-secret-id>
```
### Method 2: Configuration Files
Create a Vault configuration file (e.g., `vault-config.json`):
```json
{
"vault_addr": "http://10.160.0.40:8200",
"role_id": "<your-role-id>",
"secret_id": "<your-secret-id>"
}
```
**⚠️ Security:** Never commit configuration files with credentials to Git. Use environment variables or secure secret management.
---
## Phoenix API Integration
### Node.js/TypeScript Example
```typescript
import Vault from 'node-vault';
// Initialize Vault client
const vault = Vault({
endpoint: process.env.VAULT_ADDR || 'http://192.168.11.200:8200',
token: await authenticateWithAppRole(
process.env.VAULT_ROLE_ID!,
process.env.VAULT_SECRET_ID!
)
});
// Authenticate with AppRole
async function authenticateWithAppRole(roleId: string, secretId: string): Promise<string> {
const response = await fetch(`${process.env.VAULT_ADDR}/v1/auth/approle/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ role_id: roleId, secret_id: secretId })
});
const data = await response.json();
return data.auth.client_token;
}
// Get database credentials
async function getDatabaseCredentials() {
const response = await vault.read('secret/data/phoenix/database/postgres');
return {
username: response.data.data.username,
password: response.data.data.password,
host: response.data.data.host,
port: response.data.data.port,
database: response.data.data.database
};
}
// Get JWT secrets
async function getJWTSecrets() {
const response = await vault.read('secret/data/phoenix/api/jwt-secrets');
return {
accessTokenSecret: response.data.data['access-token-secret'],
refreshTokenSecret: response.data.data['refresh-token-secret']
};
}
```
### Python Example
```python
import hvac
import os
# Initialize Vault client
client = hvac.Client(url=os.getenv('VAULT_ADDR', 'http://10.160.0.40:8200'))
# Authenticate with AppRole
role_id = os.getenv('VAULT_ROLE_ID')
secret_id = os.getenv('VAULT_SECRET_ID')
client.auth.approle.login(role_id=role_id, secret_id=secret_id)
# Get database credentials
db_secrets = client.secrets.kv.v2.read_secret_version(path='phoenix/database/postgres')
db_config = db_secrets['data']['data']
# Get JWT secrets
jwt_secrets = client.secrets.kv.v2.read_secret_version(path='phoenix/api/jwt-secrets')
jwt_config = jwt_secrets['data']['data']
```
---
## Phoenix Portal Integration
Similar to API integration, but use the `phoenix-portal` AppRole:
```typescript
// Portal-specific Vault configuration
const vault = Vault({
endpoint: process.env.VAULT_ADDR || 'http://192.168.11.200:8200',
token: await authenticateWithAppRole(
process.env.VAULT_PORTAL_ROLE_ID!,
process.env.VAULT_PORTAL_SECRET_ID!
)
});
// Get JWT secrets for portal
const jwtSecrets = await vault.read('secret/data/phoenix/api/jwt-secrets');
```
---
## Secret Paths Reference
### Available Secret Paths
| Path | Description | Access Policy |
|------|-------------|---------------|
| `secret/data/phoenix/api/jwt-secrets` | JWT signing secrets | phoenix-api, phoenix-portal |
| `secret/data/phoenix/api/api-keys` | API keys | phoenix-api |
| `secret/data/phoenix/database/postgres` | PostgreSQL credentials | phoenix-api |
| `secret/data/phoenix/database/redis` | Redis credentials | phoenix-api |
| `secret/data/phoenix/keycloak/admin-credentials` | Keycloak admin | phoenix-api |
| `secret/data/phoenix/keycloak/oidc-secrets` | OIDC client secrets | phoenix-api |
| `secret/data/phoenix/services/blockchain` | Blockchain RPC/keys | phoenix-api |
| `secret/data/phoenix/services/integrations` | Integration tokens | phoenix-api |
### Reading Secrets
```bash
# Using Vault CLI
export VAULT_ADDR=http://192.168.11.200:8200
export VAULT_TOKEN=$(vault write -field=token auth/approle/login \
role_id=$VAULT_ROLE_ID secret_id=$VAULT_SECRET_ID)
# Read secret
vault kv get secret/phoenix/database/postgres
```
---
## Token Management
### Token Lifecycle
- **Token TTL:** 1 hour (default)
- **Token Max TTL:** 4 hours
- **Secret ID TTL:** 24 hours
### Token Renewal
Tokens should be renewed before expiration:
```typescript
// Renew token
async function renewToken(token: string): Promise<void> {
await fetch(`${process.env.VAULT_ADDR}/v1/auth/token/renew-self`, {
method: 'POST',
headers: {
'X-Vault-Token': token
}
});
}
```
### Automatic Token Refresh
Implement automatic token refresh in your services:
```typescript
class VaultClient {
private token: string | null = null;
private tokenExpiry: Date | null = null;
async getToken(): Promise<string> {
if (!this.token || this.isTokenExpired()) {
await this.authenticate();
}
return this.token!;
}
private isTokenExpired(): boolean {
if (!this.tokenExpiry) return true;
return new Date() >= this.tokenExpiry;
}
private async authenticate(): Promise<void> {
const response = await fetch(`${process.env.VAULT_ADDR}/v1/auth/approle/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
role_id: process.env.VAULT_ROLE_ID,
secret_id: process.env.VAULT_SECRET_ID
})
});
const data = await response.json();
this.token = data.auth.client_token;
this.tokenExpiry = new Date(Date.now() + data.auth.lease_duration * 1000);
}
}
```
---
## Error Handling
### Common Errors
**1. Authentication Failed**
```
Error: invalid role_id or secret_id
```
**Solution:** Verify AppRole credentials are correct.
**2. Permission Denied**
```
Error: permission denied
```
**Solution:** Check that the AppRole has the correct policy attached.
**3. Secret Not Found**
```
Error: no secret found at path
```
**Solution:** Verify the secret path exists and is accessible.
### Retry Logic
Implement retry logic for transient failures:
```typescript
async function getSecretWithRetry(path: string, maxRetries = 3): Promise<any> {
for (let i = 0; i < maxRetries; i++) {
try {
return await vault.read(path);
} catch (error) {
if (i === maxRetries - 1) throw error;
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
}
}
}
```
---
## Security Best Practices
1. **Never Hardcode Credentials**
- Use environment variables
- Use secure secret injection
- Rotate credentials regularly
2. **Use Least Privilege**
- Each service should only access secrets it needs
- Use separate AppRoles for different services
- Review policies regularly
3. **Monitor Access**
- Enable audit logging
- Monitor token usage
- Alert on suspicious activity
4. **Token Management**
- Implement automatic token renewal
- Handle token expiration gracefully
- Use short token TTLs
5. **Network Security**
- Use TLS in production
- Restrict network access to Vault
- Use firewall rules
---
## Testing Integration
### Test Script
```bash
#!/bin/bash
# Test Vault integration
export VAULT_ADDR=http://192.168.11.200:8200
export VAULT_ROLE_ID=<your-role-id>
export VAULT_SECRET_ID=<your-secret-id>
# Authenticate
TOKEN=$(vault write -field=token auth/approle/login \
role_id=$VAULT_ROLE_ID secret_id=$VAULT_SECRET_ID)
export VAULT_TOKEN=$TOKEN
# Test secret access
echo "Testing secret access..."
vault kv get secret/phoenix/api/jwt-secrets
vault kv get secret/phoenix/database/postgres
echo "✅ Integration test passed"
```
---
## Troubleshooting
### Cannot Connect to Vault
1. Check network connectivity:
```bash
curl http://10.160.0.40:8200/v1/sys/health
```
2. Verify Vault is unsealed:
```bash
vault status
```
3. Check firewall rules
### Authentication Fails
1. Verify credentials:
```bash
vault read auth/approle/role/phoenix-api/role-id
```
2. Check AppRole is enabled:
```bash
vault auth list
```
3. Verify policy is attached:
```bash
vault read auth/approle/role/phoenix-api
```
### Permission Denied
1. Check policy:
```bash
vault policy read phoenix-api-policy
```
2. Verify secret path:
```bash
vault kv list secret/phoenix/
```
3. Check token capabilities:
```bash
vault token capabilities secret/data/phoenix/api/jwt-secrets
```
---
## Migration from Existing Secrets
If migrating from existing `.env` files or other secret storage:
1. **Inventory Current Secrets**
- List all secrets currently in use
- Map to Vault paths
2. **Create Secrets in Vault**
```bash
vault kv put secret/phoenix/database/postgres \
username=current_username \
password=current_password \
host=current_host \
port=5432 \
database=phoenix
```
3. **Update Services**
- Replace `.env` file reading with Vault client
- Test thoroughly
- Deploy gradually
4. **Remove Old Secrets**
- Delete `.env` files after migration
- Update `.gitignore` if needed
---
## Related Documentation
- [Phoenix Vault Cluster Deployment](PHOENIX_VAULT_CLUSTER_DEPLOYMENT.md)
- [Vault TLS Configuration](VAULT_TLS_CONFIGURATION.md)
- [Master Secrets Inventory](MASTER_SECRETS_INVENTORY.md)
- [HashiCorp Vault Documentation](https://developer.hashicorp.com/vault/docs)
---
**Status:** ✅ Ready for Integration
**Last Updated:** 2026-01-19