Re_Backend/docs/GOOGLE_SECRET_MANAGER_SETUP.md

278 lines
8.4 KiB
Markdown

# Google Secret Manager Integration Guide
This guide explains how to integrate Google Cloud Secret Manager with your Node.js application to securely manage environment variables.
## Overview
The Google Secret Manager integration allows you to:
- Store sensitive configuration values (passwords, API keys, tokens) in Google Cloud Secret Manager
- Load secrets at application startup and merge them with your existing environment variables
- Maintain backward compatibility with `.env` files for local development
- Use minimal code changes - existing `process.env.VARIABLE_NAME` access continues to work
## Prerequisites
1. **Google Cloud Project** with Secret Manager API enabled
2. **Service Account** with Secret Manager Secret Accessor role
3. **Authentication** - Service account credentials configured (via `GCP_KEY_FILE` or default credentials)
## Setup Instructions
### 1. Enable Secret Manager API
```bash
gcloud services enable secretmanager.googleapis.com --project=YOUR_PROJECT_ID
```
### 2. Create Secrets in Google Secret Manager
Create secrets using the Google Cloud Console or gcloud CLI:
```bash
# Example: Create a database password secret
echo -n "your-secure-password" | gcloud secrets create DB_PASSWORD \
--project=YOUR_PROJECT_ID \
--data-file=-
# Example: Create a JWT secret
echo -n "your-jwt-secret-key" | gcloud secrets create JWT_SECRET \
--project=YOUR_PROJECT_ID \
--data-file=-
# Grant service account access to secrets
gcloud secrets add-iam-policy-binding DB_PASSWORD \
--member="serviceAccount:YOUR_SERVICE_ACCOUNT@YOUR_PROJECT.iam.gserviceaccount.com" \
--role="roles/secretmanager.secretAccessor" \
--project=YOUR_PROJECT_ID
```
### 3. Configure Environment Variables
Add the following to your `.env` file:
```env
# Google Secret Manager Configuration
USE_GOOGLE_SECRET_MANAGER=true
GCP_PROJECT_ID=your-project-id
# Optional: Prefix for all secret names (e.g., "prod" -> looks for "prod-DB_PASSWORD")
GCP_SECRET_PREFIX=
# Optional: JSON file mapping secret names to env var names
GCP_SECRET_MAP_FILE=./secret-map.json
```
**Important Notes:**
- Set `USE_GOOGLE_SECRET_MANAGER=true` to enable the integration
- `GCP_PROJECT_ID` must be set (same as used for GCS/Vertex AI)
- `GCP_KEY_FILE` should already be configured for other GCP services
- When `USE_GOOGLE_SECRET_MANAGER=false` or not set, the app uses `.env` file only
### 4. Secret Name Mapping
By default, secrets in Google Secret Manager are automatically mapped to environment variables:
- Secret name: `DB_PASSWORD` → Environment variable: `DB_PASSWORD`
- Secret name: `db-password` → Environment variable: `DB_PASSWORD` (hyphens converted to underscores, uppercase)
- Secret name: `jwt-secret-key` → Environment variable: `JWT_SECRET_KEY`
#### Custom Mapping (Optional)
If you need custom mappings, create a JSON file (e.g., `secret-map.json`):
```json
{
"db-password-prod": "DB_PASSWORD",
"jwt-secret-key": "JWT_SECRET",
"okta-client-secret-prod": "OKTA_CLIENT_SECRET"
}
```
Then set in `.env`:
```env
GCP_SECRET_MAP_FILE=./secret-map.json
```
### 5. Secret Prefix (Optional)
If all your secrets share a common prefix:
```env
GCP_SECRET_PREFIX=prod
```
This will look for secrets named `prod-DB_PASSWORD`, `prod-JWT_SECRET`, etc.
## How It Works
1. **Application Startup:**
- `.env` file is loaded first (provides fallback values)
- If `USE_GOOGLE_SECRET_MANAGER=true`, secrets are fetched from Google Secret Manager
- Secrets are merged into `process.env`, overriding `.env` values if they exist
- Application continues with merged environment variables
2. **Fallback Behavior:**
- If Secret Manager is disabled or fails, the app falls back to `.env` file
- No errors are thrown - the app continues with available configuration
- Logs indicate whether secrets were loaded successfully
3. **Existing Code Compatibility:**
- No changes needed to existing code
- Continue using `process.env.VARIABLE_NAME` as before
- Secrets from GCS automatically populate `process.env`
## Default Secrets Loaded
The service automatically attempts to load these common secrets (if they exist in Secret Manager):
**Database:**
- `DB_HOST`, `DB_PORT`, `DB_NAME`, `DB_USER`, `DB_PASSWORD`
**Authentication:**
- `JWT_SECRET`, `REFRESH_TOKEN_SECRET`, `SESSION_SECRET`
**SSO/Okta:**
- `OKTA_DOMAIN`, `OKTA_CLIENT_ID`, `OKTA_CLIENT_SECRET`, `OKTA_API_TOKEN`
**Email:**
- `SMTP_HOST`, `SMTP_PORT`, `SMTP_USER`, `SMTP_PASSWORD`
**Web Push (VAPID):**
- `VAPID_PUBLIC_KEY`, `VAPID_PRIVATE_KEY`
**Logging:**
- `LOKI_HOST`, `LOKI_USER`, `LOKI_PASSWORD`
### Loading Custom Secrets
To load additional secrets, modify the code:
```typescript
// In server.ts or app.ts
import { googleSecretManager } from './services/googleSecretManager.service';
// Load default secrets + custom ones
await googleSecretManager.loadSecrets([
'DB_PASSWORD',
'JWT_SECRET',
'CUSTOM_API_KEY', // Your custom secret
'CUSTOM_SECRET_2'
]);
```
Or load a single secret on-demand:
```typescript
import { googleSecretManager } from './services/googleSecretManager.service';
const apiKey = await googleSecretManager.getSecretValue('CUSTOM_API_KEY', 'API_KEY');
```
## Security Best Practices
1. **Service Account Permissions:**
- Grant only `roles/secretmanager.secretAccessor` role
- Use separate service accounts for different environments
- Never grant `roles/owner` or `roles/editor` to service accounts
2. **Secret Rotation:**
- Rotate secrets regularly in Google Secret Manager
- The app automatically uses the `latest` version of each secret
- No code changes needed when secrets are rotated
3. **Environment Separation:**
- Use different Google Cloud projects for dev/staging/prod
- Use `GCP_SECRET_PREFIX` to namespace secrets by environment
- Never commit `.env` files with production secrets to version control
4. **Access Control:**
- Use IAM policies to control who can read secrets
- Enable audit logging for secret access
- Regularly review secret access logs
## Troubleshooting
### Secrets Not Loading
**Check logs for:**
```
[Secret Manager] Google Secret Manager is disabled (USE_GOOGLE_SECRET_MANAGER != true)
[Secret Manager] GCP_PROJECT_ID not set, skipping Google Secret Manager
[Secret Manager] Failed to load secrets: [error message]
```
**Common issues:**
1. `USE_GOOGLE_SECRET_MANAGER` not set to `true`
2. `GCP_PROJECT_ID` not configured
3. Service account lacks Secret Manager permissions
4. Secrets don't exist in Secret Manager
5. Incorrect secret names (check case sensitivity)
### Service Account Authentication
Ensure service account credentials are available:
- Set `GCP_KEY_FILE` to point to service account JSON file
- Or configure Application Default Credentials (ADC)
- Test with: `gcloud auth application-default login`
### Secret Not Found
If a secret doesn't exist in Secret Manager:
- The app logs a debug message and continues
- Falls back to `.env` file value
- This is expected behavior - not all secrets need to be in GCS
### Debugging
Enable debug logging by setting:
```env
LOG_LEVEL=debug
```
This will show detailed logs about which secrets are being loaded.
## Example Configuration
**Local Development (.env):**
```env
USE_GOOGLE_SECRET_MANAGER=false
DB_PASSWORD=local-dev-password
JWT_SECRET=local-jwt-secret
```
**Production (.env):**
```env
USE_GOOGLE_SECRET_MANAGER=true
GCP_PROJECT_ID=re-platform-workflow-dealer
GCP_SECRET_PREFIX=prod
GCP_KEY_FILE=./credentials/service-account.json
# DB_PASSWORD and other secrets loaded from GCS
```
## Migration Strategy
1. **Phase 1: Setup**
- Create secrets in Google Secret Manager
- Keep `.env` file with current values (as backup)
2. **Phase 2: Test**
- Set `USE_GOOGLE_SECRET_MANAGER=true` in development
- Verify secrets are loaded correctly
- Test application functionality
3. **Phase 3: Production**
- Deploy with `USE_GOOGLE_SECRET_MANAGER=true`
- Monitor logs for secret loading success
- Remove sensitive values from `.env` file (keep placeholders)
4. **Phase 4: Cleanup**
- Remove production secrets from `.env` file
- Ensure all secrets are in Secret Manager
- Document secret names and mappings
## Additional Resources
- [Google Secret Manager Documentation](https://cloud.google.com/secret-manager/docs)
- [Secret Manager Client Library](https://cloud.google.com/nodejs/docs/reference/secret-manager/latest)
- [Service Account Best Practices](https://cloud.google.com/iam/docs/best-practices-service-accounts)