- Complete Cloudflare Terraform configuration (DNS, WAF, tunnels, access) - WAF Intelligence MCP server with threat analysis and ML classification - GitOps automation with PR workflows and drift detection - Observatory monitoring stack with Prometheus/Grafana - IDE operator rules for governed development - Security playbooks and compliance frameworks - Autonomous remediation and state reconciliation
442 lines
11 KiB
Markdown
442 lines
11 KiB
Markdown
# Multiple Accounts Configuration 🔐
|
||
|
||
## Overview
|
||
|
||
This project supports **multiple accounts for the same service**:
|
||
|
||
- Multiple GitHub accounts (personal, work, alt)
|
||
- Multiple Cloudflare accounts (prod, staging, dev)
|
||
- Multiple GitLab instances (internal, external)
|
||
|
||
Each account is:
|
||
|
||
1. Bound to a **unique environment variable name**, and
|
||
2. Exposed as a **separate MCP server** in `opencode.jsonc`.
|
||
|
||
> 🔒 **Security Note:** Never commit tokens to git. Keep them in your shell environment, a `.env` file that is `.gitignore`d, or a secrets manager.
|
||
|
||
---
|
||
|
||
## 1. Export Tokens with Unique Variable Names
|
||
|
||
Use descriptive names that encode both **service** and **purpose**.
|
||
|
||
**Pattern:**
|
||
`<SERVICE>_<RESOURCE>_<ENV or PURPOSE>`
|
||
|
||
Examples:
|
||
- `GITHUB_TOKEN_WORK`
|
||
- `CLOUDFLARE_API_TOKEN_PRODUCTION`
|
||
- `GITLAB_TOKEN_INTERNAL`
|
||
|
||
### Shell Export (for session-based or profile)
|
||
|
||
```bash
|
||
# GitHub – multiple accounts
|
||
export GITHUB_TOKEN_SECONDARY="ghp_another_token_here"
|
||
export GITHUB_TOKEN_WORK="ghp_work_account_token"
|
||
export GITHUB_TOKEN_PERSONAL="ghp_personal_account_token"
|
||
|
||
# Cloudflare – multiple accounts
|
||
export CLOUDFLARE_API_TOKEN_PRODUCTION="prod_token_here"
|
||
export CLOUDFLARE_ACCOUNT_ID_PRODUCTION="prod_account_id"
|
||
|
||
export CLOUDFLARE_API_TOKEN_STAGING="staging_token_here"
|
||
export CLOUDFLARE_ACCOUNT_ID_STAGING="staging_account_id"
|
||
|
||
# GitLab – multiple instances
|
||
export GITLAB_TOKEN_INTERNAL="glpat_internal_token"
|
||
export GITLAB_URL_INTERNAL="https://gitlab.internal.company.com"
|
||
|
||
export GITLAB_TOKEN_EXTERNAL="glpat_external_token"
|
||
export GITLAB_URL_EXTERNAL="https://gitlab.com"
|
||
```
|
||
|
||
### .env File (recommended for project isolation)
|
||
|
||
```bash
|
||
# .env (remember to add this to .gitignore)
|
||
CLOUDFLARE_API_TOKEN_PRODUCTION=prod_token
|
||
CLOUDFLARE_ACCOUNT_ID_PRODUCTION=prod_account_id
|
||
|
||
CLOUDFLARE_API_TOKEN_STAGING=staging_token
|
||
CLOUDFLARE_ACCOUNT_ID_STAGING=staging_account_id
|
||
```
|
||
|
||
Then load in shell:
|
||
|
||
```bash
|
||
set -a
|
||
source .env
|
||
set +a
|
||
```
|
||
|
||
---
|
||
|
||
## 2. Add MCP Entries in `opencode.jsonc`
|
||
|
||
Each account becomes its own MCP entry, wired to its own env vars:
|
||
|
||
```jsonc
|
||
// Secondary GitHub account
|
||
"github_secondary": {
|
||
"type": "local",
|
||
"command": ["npx", "-y", "@modelcontextprotocol/server-github"],
|
||
"environment": {
|
||
"GITHUB_PERSONAL_ACCESS_TOKEN": "{env:GITHUB_TOKEN_SECONDARY}"
|
||
},
|
||
"enabled": false
|
||
},
|
||
|
||
// Production Cloudflare account
|
||
"cloudflare_prod": {
|
||
"type": "local",
|
||
"command": ["npx", "-y", "@modelcontextprotocol/server-cloudflare"],
|
||
"environment": {
|
||
"CLOUDFLARE_API_TOKEN": "{env:CLOUDFLARE_API_TOKEN_PRODUCTION}",
|
||
"CLOUDFLARE_ACCOUNT_ID": "{env:CLOUDFLARE_ACCOUNT_ID_PRODUCTION}"
|
||
},
|
||
"enabled": false
|
||
},
|
||
|
||
// Staging Cloudflare account
|
||
"cloudflare_staging": {
|
||
"type": "local",
|
||
"command": ["npx", "-y", "@modelcontextprotocol/server-cloudflare"],
|
||
"environment": {
|
||
"CLOUDFLARE_API_TOKEN": "{env:CLOUDFLARE_API_TOKEN_STAGING}",
|
||
"CLOUDFLARE_ACCOUNT_ID": "{env:CLOUDFLARE_ACCOUNT_ID_STAGING}"
|
||
},
|
||
"enabled": false
|
||
},
|
||
|
||
// Internal GitLab instance
|
||
"gitlab_internal": {
|
||
"type": "local",
|
||
"command": ["npx", "-y", "@modelcontextprotocol/server-gitlab"],
|
||
"environment": {
|
||
"GITLAB_TOKEN": "{env:GITLAB_TOKEN_INTERNAL}",
|
||
"GITLAB_URL": "{env:GITLAB_URL_INTERNAL}"
|
||
},
|
||
"enabled": false
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 3. Enable Per-Agent (Recommended) or Globally
|
||
|
||
**Recommended:** Enable accounts per agent for isolation.
|
||
|
||
```jsonc
|
||
"agents": {
|
||
"cloudflare-ops": {
|
||
"tools": {
|
||
"cloudflare_prod": true, // Production account
|
||
"cloudflare_staging": true, // Staging account
|
||
"github_secondary": true, // Secondary GitHub
|
||
"gitlab_internal": true // Internal GitLab
|
||
}
|
||
},
|
||
"security-audit": {
|
||
"tools": {
|
||
"cloudflare_prod": true, // Only production for audits
|
||
"github_secondary": false // Disable secondary for security
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
Global enable (less strict, use sparingly):
|
||
|
||
```jsonc
|
||
"tools": {
|
||
"cloudflare_prod": true,
|
||
"github_secondary": true
|
||
}
|
||
```
|
||
|
||
> 🔑 **Principle:** Production credentials should only be wired into a few, tightly-scoped agents (e.g., `cloudflare-ops`, `security-audit`), not "playground" agents.
|
||
|
||
---
|
||
|
||
## 4. Best Practices
|
||
|
||
### Naming Conventions
|
||
|
||
Use suffixes that make intent obvious:
|
||
- `_PRODUCTION` / `_PROD` – Production environment
|
||
- `_STAGING` / `_STAGE` – Staging environment
|
||
- `_DEVELOPMENT` / `_DEV` – Development environment
|
||
- `_INTERNAL` – Internal/private instance
|
||
- `_EXTERNAL` – External/public instance
|
||
- `_WORK` / `_PERSONAL` – Work vs personal identity
|
||
- `_SECONDARY` / `_BACKUP` – Secondary/backup account
|
||
|
||
### Security Isolation
|
||
|
||
1. **Per-agent configuration** – Only give each agent the accounts it truly needs
|
||
2. **Environment separation** – Different tokens per environment (prod / stage / dev)
|
||
3. **Least privilege** – Grant minimal scopes to each token
|
||
4. **Token rotation** – Rotate regularly, especially production
|
||
|
||
> ⚠️ **Golden Rule:** Never give production tokens to "exploratory" or "play" agents; only to audited / narrow-scope agents (e.g., `security-audit`, `cloudflare-ops`).
|
||
|
||
### Example: Multi-Environment Setup
|
||
|
||
```bash
|
||
# .env file
|
||
# Production
|
||
export CLOUDFLARE_API_TOKEN_PRODUCTION="prod_token"
|
||
export CLOUDFLARE_ACCOUNT_ID_PRODUCTION="prod_account_id"
|
||
|
||
# Staging
|
||
export CLOUDFLARE_API_TOKEN_STAGING="staging_token"
|
||
export CLOUDFLARE_ACCOUNT_ID_STAGING="staging_account_id"
|
||
|
||
# Development
|
||
export CLOUDFLARE_API_TOKEN_DEVELOPMENT="dev_token"
|
||
export CLOUDFLARE_ACCOUNT_ID_DEVELOPMENT="dev_account_id"
|
||
```
|
||
|
||
```jsonc
|
||
// opencode.jsonc
|
||
"cloudflare_prod": {
|
||
"environment": {
|
||
"CLOUDFLARE_API_TOKEN": "{env:CLOUDFLARE_API_TOKEN_PRODUCTION}",
|
||
"CLOUDFLARE_ACCOUNT_ID": "{env:CLOUDFLARE_ACCOUNT_ID_PRODUCTION}"
|
||
}
|
||
},
|
||
"cloudflare_staging": {
|
||
"environment": {
|
||
"CLOUDFLARE_API_TOKEN": "{env:CLOUDFLARE_API_TOKEN_STAGING}",
|
||
"CLOUDFLARE_ACCOUNT_ID": "{env:CLOUDFLARE_ACCOUNT_ID_STAGING}"
|
||
}
|
||
},
|
||
"cloudflare_dev": {
|
||
"environment": {
|
||
"CLOUDFLARE_API_TOKEN": "{env:CLOUDFLARE_API_TOKEN_DEVELOPMENT}",
|
||
"CLOUDFLARE_ACCOUNT_ID": "{env:CLOUDFLARE_ACCOUNT_ID_DEVELOPMENT}"
|
||
}
|
||
}
|
||
```
|
||
|
||
## Cursor IDE Integration
|
||
|
||
### How Cursor Agent Works with Multiple Accounts
|
||
|
||
Cursor IDE itself uses a single account (your Cursor subscription), but Cursor Agent can access unlimited external service accounts via:
|
||
|
||
1. **Environment Variables** (loaded from `.env`)
|
||
2. **MCP Servers** (configured in `~/.cursor/mcp.json` or project-specific)
|
||
3. **Workspace-Specific Config** (each project folder can have different credentials)
|
||
|
||
### Configuring MCP in Cursor
|
||
|
||
**File:** `~/.cursor/mcp.json`
|
||
|
||
```json
|
||
{
|
||
"mcpServers": {
|
||
"github_work": {
|
||
"command": "npx",
|
||
"args": ["-y", "@modelcontextprotocol/server-github"],
|
||
"env": {
|
||
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_work_token_here"
|
||
}
|
||
},
|
||
"github_personal": {
|
||
"command": "npx",
|
||
"args": ["-y", "@modelcontextprotocol/server-github"],
|
||
"env": {
|
||
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_personal_token_here"
|
||
}
|
||
},
|
||
"cloudflare_prod": {
|
||
"command": "npx",
|
||
"args": ["-y", "@modelcontextprotocol/server-cloudflare"],
|
||
"env": {
|
||
"CLOUDFLARE_API_TOKEN": "prod_token",
|
||
"CLOUDFLARE_ACCOUNT_ID": "prod_account_id"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### Using Multiple Accounts in Cursor
|
||
|
||
Once configured, Cursor Agent can:
|
||
|
||
```
|
||
# In Cursor chat/command bar:
|
||
|
||
"Check production Cloudflare for drift"
|
||
→ Uses cloudflare_prod MCP
|
||
|
||
"Search my work GitHub for similar implementations"
|
||
→ Uses github_work MCP
|
||
|
||
"Compare personal and work repos for this pattern"
|
||
→ Uses both github_personal and github_work MCPs
|
||
```
|
||
|
||
### Workspace-Specific .env
|
||
|
||
Each project can have its own `.env`:
|
||
|
||
```bash
|
||
# /Users/sovereign/Desktop/CLOUDFLARE/.env
|
||
export CLOUDFLARE_API_TOKEN="client_a_token"
|
||
export GITLAB_TOKEN="client_a_gitlab_token"
|
||
|
||
# /Users/sovereign/Desktop/CLIENT_B/.env
|
||
export CLOUDFLARE_API_TOKEN="client_b_token"
|
||
export GITLAB_TOKEN="client_b_gitlab_token"
|
||
```
|
||
|
||
Cursor loads the appropriate `.env` when you switch workspaces.
|
||
|
||
## 5. Usage Examples
|
||
|
||
### Launching with Multiple Accounts
|
||
|
||
```bash
|
||
# Set tokens before launching
|
||
export GITHUB_TOKEN_SECONDARY="ghp_..."
|
||
export CLOUDFLARE_API_TOKEN_PRODUCTION="prod_..."
|
||
|
||
# Launch OpenCode
|
||
opencode
|
||
/init
|
||
```
|
||
|
||
Inside OpenCode:
|
||
|
||
```
|
||
/use github_secondary
|
||
Search for issues in my secondary GitHub account
|
||
|
||
/use cloudflare_prod
|
||
List all zones in the production Cloudflare account
|
||
```
|
||
|
||
### Agent-Specific Access
|
||
|
||
```bash
|
||
/agent cloudflare-ops
|
||
# Has: cloudflare_prod, cloudflare_staging, github_secondary
|
||
|
||
/agent security-audit
|
||
# Has: cloudflare_prod only (no staging, no personal GitHub)
|
||
```
|
||
|
||
### Cross-Account Validation
|
||
|
||
```bash
|
||
/agent cloudflare-ops
|
||
|
||
Compare configuration between production and staging accounts:
|
||
1. Query cloudflare_prod for all WAF rules
|
||
2. Query cloudflare_staging for all WAF rules
|
||
3. Show differences
|
||
4. Validate staging matches production baseline
|
||
```
|
||
|
||
## 6. Troubleshooting
|
||
|
||
### Token Not Working
|
||
|
||
1. **Verify the environment variable is set:**
|
||
```bash
|
||
echo "$GITHUB_TOKEN_SECONDARY"
|
||
```
|
||
|
||
2. **Check MCP configuration** in `opencode.jsonc`:
|
||
- Variable names match
|
||
- `{env:VARIABLE_NAME}` syntax is correct
|
||
|
||
3. **Restart OpenCode** after exporting tokens
|
||
|
||
### MCP Not Loading
|
||
|
||
1. **Check MCP status** inside OpenCode:
|
||
```
|
||
/mcp list
|
||
/mcp status github_secondary
|
||
```
|
||
|
||
2. **Validate token format:**
|
||
- GitHub: usually `ghp_...`
|
||
- GitLab: usually `glpat_...`
|
||
|
||
3. **Confirm agent config:**
|
||
- MCP is enabled for that agent in `agents[...].tools`
|
||
- Or globally enabled in `"tools"`
|
||
|
||
## 7. Security Considerations
|
||
|
||
### Token Storage
|
||
|
||
**✅ DO:**
|
||
- Store tokens in `.env` (gitignored)
|
||
- Use environment variables for credentials
|
||
- Rotate tokens every 90 days
|
||
- Use separate tokens for prod/staging/dev
|
||
|
||
**❌ DON'T:**
|
||
- Commit tokens to git
|
||
- Hardcode tokens in config files
|
||
- Share tokens via chat/email
|
||
- Use same token across environments
|
||
|
||
### Audit Trail
|
||
|
||
Log all multi-account operations:
|
||
|
||
```bash
|
||
# Enable audit logging in .env
|
||
export AUDIT_LOG_ENABLED=true
|
||
export AUDIT_LOG_PATH="./observatory/audit.log"
|
||
```
|
||
|
||
Operations using multiple accounts will be logged with account identifiers.
|
||
|
||
### Token Rotation
|
||
|
||
> 💡 **Future Enhancement:** Could integrate with `playbooks/TUNNEL-ROTATION-PROTOCOL.md` for automated token rotation policies.
|
||
|
||
## 8. Related Docs
|
||
|
||
- **AGENTS.md** – Agent configuration and usage
|
||
- **MCP_GUIDE.md** – Full MCP reference
|
||
- **GITLAB_CLOUDFLARE_AUTH.md** – Auth setup
|
||
- **.env.example** – Environment variable examples
|
||
- **COGNITION_FLOW.md** – How multi-account fits into cognition flow
|
||
|
||
---
|
||
|
||
## 9. Summary
|
||
|
||
### To add another account:
|
||
|
||
1. **Create a unique env var for the token**
|
||
- e.g., `GITHUB_TOKEN_SECONDARY`, `CLOUDFLARE_API_TOKEN_STAGING`
|
||
|
||
2. **Add an MCP entry in `opencode.jsonc` that uses `{env:...}`**
|
||
|
||
3. **Enable it per-agent (recommended) or globally**
|
||
|
||
4. **Keep naming and scopes clear** so you always know which token is doing what
|
||
|
||
🔐 **Key Point:**
|
||
One account = one env var = one MCP entry.
|
||
From there, agents decide which identities they're allowed to wield.
|
||
|
||
---
|
||
|
||
**Next Steps:**
|
||
- See **GITLAB_CLOUDFLARE_AUTH.md** for detailed token creation
|
||
- See **AGENTS.md** for agent-specific tool configuration
|
||
- See **.env.example** for complete environment template
|