docs: comprehensive vault setup guide for all machines
Complete reference for setting up vault access on Mac/Windows/Linux. Covers all issues encountered during Mac setup: - Line ending fixes (CRLF → LF) - SOPS_AGE_KEY_FILE environment configuration - Age key installation and permissions - Common errors and solutions Includes quick setup for Howard's machines (ACG-Tech03L, HOWARD-HOME). Successfully validated on Mikes-MacBook-Air - all 4 tiers working. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
522
.claude/VAULT-SETUP-GUIDE.md
Normal file
522
.claude/VAULT-SETUP-GUIDE.md
Normal file
@@ -0,0 +1,522 @@
|
||||
# Vault Setup Guide - Multi-Machine Reference
|
||||
|
||||
**Last Updated:** 2026-04-21
|
||||
**Tested On:** Mikes-MacBook-Air.local (Mac), DESKTOP-0O8A1RL (Windows)
|
||||
**Purpose:** Complete guide for setting up vault access on any machine
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The vault repository contains encrypted credentials (SOPS files) required for remediation-tool to acquire tokens. This guide covers full setup from scratch on any machine.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before starting, you need:
|
||||
- ClaudeTools repository cloned
|
||||
- Network access to Gitea server (http://172.16.3.20:3000)
|
||||
- Gitea credentials (username: azcomputerguru, password: see below)
|
||||
- Age key (private key shared across team - see below)
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference - Credentials
|
||||
|
||||
### Gitea Password
|
||||
```
|
||||
Gptf*77ttb123!@#-git
|
||||
```
|
||||
|
||||
### Age Private Key
|
||||
```
|
||||
# created: 2026-03-30T13:53:19-07:00
|
||||
# public key: age1qz7ct84m50u06h97artqddkj3c8se2yu4nxu59clq8rhj945jc0s5excpr
|
||||
AGE-SECRET-KEY-1DE3V6V0ZLLZ45A7GA77M79CTN4LZQMTRCURP8VRGNLV6T2FSZEEQXUW2EU
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Installation Steps
|
||||
|
||||
### Step 1: Install Dependencies
|
||||
|
||||
**Mac (Homebrew):**
|
||||
```bash
|
||||
brew install sops age jq
|
||||
```
|
||||
|
||||
**Windows (Chocolatey):**
|
||||
```powershell
|
||||
choco install sops age jq
|
||||
```
|
||||
|
||||
**Windows (Manual):**
|
||||
- Download SOPS: https://github.com/mozilla/sops/releases
|
||||
- Download age: https://github.com/FiloSottile/age/releases
|
||||
- Download jq: https://jqlang.github.io/jq/download/
|
||||
- Add to PATH
|
||||
|
||||
**Linux (apt):**
|
||||
```bash
|
||||
sudo apt install age jq
|
||||
# SOPS from GitHub releases (not in apt)
|
||||
wget https://github.com/mozilla/sops/releases/download/v3.12.2/sops-v3.12.2.linux.amd64 -O /usr/local/bin/sops
|
||||
chmod +x /usr/local/bin/sops
|
||||
```
|
||||
|
||||
### Step 2: Clone Vault Repository
|
||||
|
||||
**Mac/Linux:**
|
||||
```bash
|
||||
git clone http://azcomputerguru@172.16.3.20:3000/azcomputerguru/vault.git ~/vault
|
||||
# Password when prompted: Gptf*77ttb123!@#-git
|
||||
```
|
||||
|
||||
**Windows:**
|
||||
```cmd
|
||||
git clone http://azcomputerguru@172.16.3.20:3000/azcomputerguru/vault.git D:\vault
|
||||
REM Password when prompted: Gptf*77ttb123!@#-git
|
||||
```
|
||||
|
||||
**Important:** Must use real terminal, not Claude Code shell (auth prompts don't work in Claude Code).
|
||||
|
||||
### Step 3: Configure Age Key
|
||||
|
||||
**Mac/Linux:**
|
||||
```bash
|
||||
mkdir -p ~/.config/sops/age
|
||||
cat > ~/.config/sops/age/keys.txt << 'AGEEOF'
|
||||
# created: 2026-03-30T13:53:19-07:00
|
||||
# public key: age1qz7ct84m50u06h97artqddkj3c8se2yu4nxu59clq8rhj945jc0s5excpr
|
||||
AGE-SECRET-KEY-1DE3V6V0ZLLZ45A7GA77M79CTN4LZQMTRCURP8VRGNLV6T2FSZEEQXUW2EU
|
||||
AGEEOF
|
||||
chmod 600 ~/.config/sops/age/keys.txt
|
||||
```
|
||||
|
||||
**Windows (PowerShell):**
|
||||
```powershell
|
||||
$KeyDir = "$env:USERPROFILE\.config\sops\age"
|
||||
New-Item -ItemType Directory -Force -Path $KeyDir | Out-Null
|
||||
|
||||
$KeyContent = @"
|
||||
# created: 2026-03-30T13:53:19-07:00
|
||||
# public key: age1qz7ct84m50u06h97artqddkj3c8se2yu4nxu59clq8rhj945jc0s5excpr
|
||||
AGE-SECRET-KEY-1DE3V6V0ZLLZ45A7GA77M79CTN4LZQMTRCURP8VRGNLV6T2FSZEEQXUW2EU
|
||||
"@
|
||||
|
||||
Set-Content -Path "$KeyDir\keys.txt" -Value $KeyContent -NoNewline
|
||||
```
|
||||
|
||||
**Windows (Git Bash):**
|
||||
```bash
|
||||
mkdir -p /c/Users/$USER/.config/sops/age
|
||||
cat > /c/Users/$USER/.config/sops/age/keys.txt << 'AGEEOF'
|
||||
# created: 2026-03-30T13:53:19-07:00
|
||||
# public key: age1qz7ct84m50u06h97artqddkj3c8se2yu4nxu59clq8rhj945jc0s5excpr
|
||||
AGE-SECRET-KEY-1DE3V6V0ZLLZ45A7GA77M79CTN4LZQMTRCURP8VRGNLV6T2FSZEEQXUW2EU
|
||||
AGEEOF
|
||||
```
|
||||
|
||||
### Step 4: Configure SOPS Environment Variable
|
||||
|
||||
**Mac (zsh):**
|
||||
```bash
|
||||
echo 'export SOPS_AGE_KEY_FILE=~/.config/sops/age/keys.txt' >> ~/.zshenv
|
||||
source ~/.zshenv
|
||||
```
|
||||
|
||||
**Mac (bash):**
|
||||
```bash
|
||||
echo 'export SOPS_AGE_KEY_FILE=~/.config/sops/age/keys.txt' >> ~/.bash_profile
|
||||
source ~/.bash_profile
|
||||
```
|
||||
|
||||
**Windows (PowerShell - permanent):**
|
||||
```powershell
|
||||
[Environment]::SetEnvironmentVariable("SOPS_AGE_KEY_FILE", "$env:USERPROFILE\.config\sops\age\keys.txt", "User")
|
||||
```
|
||||
|
||||
**Windows (Git Bash):**
|
||||
```bash
|
||||
echo 'export SOPS_AGE_KEY_FILE=~/.config/sops/age/keys.txt' >> ~/.bashrc
|
||||
source ~/.bashrc
|
||||
```
|
||||
|
||||
**Linux:**
|
||||
```bash
|
||||
echo 'export SOPS_AGE_KEY_FILE=~/.config/sops/age/keys.txt' >> ~/.bashrc
|
||||
source ~/.bashrc
|
||||
```
|
||||
|
||||
### Step 5: Fix vault.sh Line Endings (If Needed)
|
||||
|
||||
**If you see error: `env: bash\r: No such file or directory`**
|
||||
|
||||
This means vault.sh has Windows line endings (CRLF). Fix with:
|
||||
|
||||
**Mac/Linux:**
|
||||
```bash
|
||||
# Using perl (always available)
|
||||
perl -pi -e 's/\r\n/\n/g' ~/vault/scripts/vault.sh
|
||||
|
||||
# Or using dos2unix if installed
|
||||
dos2unix ~/vault/scripts/vault.sh
|
||||
```
|
||||
|
||||
**Windows (Git Bash):**
|
||||
```bash
|
||||
dos2unix /d/vault/scripts/vault.sh
|
||||
```
|
||||
|
||||
**Make executable:**
|
||||
```bash
|
||||
chmod +x ~/vault/scripts/vault.sh # Mac/Linux
|
||||
chmod +x /d/vault/scripts/vault.sh # Windows Git Bash
|
||||
```
|
||||
|
||||
### Step 6: Add vault_path to identity.json
|
||||
|
||||
**Edit ClaudeTools identity.json:**
|
||||
|
||||
**Mac:**
|
||||
```bash
|
||||
# File: ~/ClaudeTools/.claude/identity.json
|
||||
# Add this field:
|
||||
"vault_path": "/Users/azcomputerguru/vault"
|
||||
```
|
||||
|
||||
**Windows:**
|
||||
```bash
|
||||
# File: D:\ClaudeTools\.claude\identity.json
|
||||
# Add this field:
|
||||
"vault_path": "D:/vault"
|
||||
```
|
||||
|
||||
**Linux:**
|
||||
```bash
|
||||
# File: ~/ClaudeTools/.claude/identity.json
|
||||
# Add this field:
|
||||
"vault_path": "/home/<username>/vault"
|
||||
```
|
||||
|
||||
**Full example:**
|
||||
```json
|
||||
{
|
||||
"user": "mike",
|
||||
"full_name": "Mike Swanson",
|
||||
"email": "mike@azcomputerguru.com",
|
||||
"role": "admin",
|
||||
"machine": "Mikes-MacBook-Air",
|
||||
"mode": "general",
|
||||
"last_updated": "2026-04-19T08:40:00Z",
|
||||
"vault_path": "/Users/azcomputerguru/vault"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Verification Steps
|
||||
|
||||
### Test 1: Verify SOPS Can Decrypt
|
||||
|
||||
**Mac/Linux:**
|
||||
```bash
|
||||
sops --decrypt ~/vault/msp-tools/computerguru-security-investigator.sops.yaml | head -10
|
||||
```
|
||||
|
||||
**Windows:**
|
||||
```bash
|
||||
sops --decrypt D:/vault/msp-tools/computerguru-security-investigator.sops.yaml | head -10
|
||||
```
|
||||
|
||||
**Expected output:** YAML content starting with `kind: entra-app`
|
||||
|
||||
**If you see:** `Failed to get the data key` → Age key not configured correctly
|
||||
|
||||
### Test 2: Verify vault.sh Works
|
||||
|
||||
**Mac/Linux:**
|
||||
```bash
|
||||
~/vault/scripts/vault.sh get-field msp-tools/computerguru-security-investigator.sops.yaml credentials.client_id
|
||||
```
|
||||
|
||||
**Windows:**
|
||||
```bash
|
||||
bash D:/vault/scripts/vault.sh get-field msp-tools/computerguru-security-investigator.sops.yaml credentials.client_id
|
||||
```
|
||||
|
||||
**Expected output:** `bfbc12a4-f0dd-4e12-b06d-997e7271e10c`
|
||||
|
||||
### Test 3: Verify Token Acquisition
|
||||
|
||||
**Mac/Linux:**
|
||||
```bash
|
||||
cd ~/ClaudeTools/.claude/skills/remediation-tool/scripts
|
||||
./get-token.sh grabblaw.com investigator
|
||||
```
|
||||
|
||||
**Windows:**
|
||||
```bash
|
||||
cd D:\ClaudeTools\.claude\skills\remediation-tool\scripts
|
||||
bash get-token.sh grabblaw.com investigator
|
||||
```
|
||||
|
||||
**Expected output:** JWT token starting with `eyJ0eXAiOiJKV1Qi...`
|
||||
|
||||
### Test 4: Test All Tiers
|
||||
|
||||
**Mac/Linux/Windows (Git Bash):**
|
||||
```bash
|
||||
for tier in investigator investigator-exo user-manager tenant-admin; do
|
||||
echo "Testing tier: $tier"
|
||||
./get-token.sh grabblaw.com $tier | head -c 50
|
||||
echo "..."
|
||||
echo "---"
|
||||
done
|
||||
```
|
||||
|
||||
**Expected:** JWT tokens for all 4 tiers (defender will fail - not consented in grabblaw.com)
|
||||
|
||||
---
|
||||
|
||||
## Common Issues and Solutions
|
||||
|
||||
### Issue 1: "Device not configured" when cloning vault
|
||||
|
||||
**Symptom:**
|
||||
```
|
||||
fatal: could not read Password for 'http://azcomputerguru@172.16.3.20:3000': Device not configured
|
||||
```
|
||||
|
||||
**Cause:** Git cannot prompt for password in Claude Code shell
|
||||
|
||||
**Solution:** Clone in real terminal (Terminal.app, PowerShell, etc.)
|
||||
|
||||
### Issue 2: "env: bash\r: No such file or directory"
|
||||
|
||||
**Symptom:** vault.sh won't execute, complains about `bash\r`
|
||||
|
||||
**Cause:** Windows line endings (CRLF) in vault.sh
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
perl -pi -e 's/\r\n/\n/g' ~/vault/scripts/vault.sh
|
||||
chmod +x ~/vault/scripts/vault.sh
|
||||
```
|
||||
|
||||
### Issue 3: "Failed to get the data key"
|
||||
|
||||
**Symptom:** SOPS can't decrypt files
|
||||
|
||||
**Cause:** Age key not found or SOPS_AGE_KEY_FILE not set
|
||||
|
||||
**Solution:**
|
||||
1. Verify age key exists: `cat ~/.config/sops/age/keys.txt`
|
||||
2. Set environment variable: `export SOPS_AGE_KEY_FILE=~/.config/sops/age/keys.txt`
|
||||
3. Add to shell RC file for persistence
|
||||
|
||||
### Issue 4: "vault_path not set in identity.json"
|
||||
|
||||
**Symptom:** get-token.sh fails with vault_path error
|
||||
|
||||
**Cause:** Missing vault_path field in .claude/identity.json
|
||||
|
||||
**Solution:** Add `"vault_path": "/path/to/vault"` to identity.json
|
||||
|
||||
### Issue 5: Python "pipefail: invalid option name"
|
||||
|
||||
**Symptom:** vault.sh fails on Mac with pipefail error
|
||||
|
||||
**Cause:** macOS ships with old bash (3.2) that doesn't support `set -o pipefail`
|
||||
|
||||
**Solution:** Already fixed in vault.sh - ensure you have latest version
|
||||
|
||||
### Issue 6: "command not found: sops"
|
||||
|
||||
**Symptom:** SOPS not in PATH
|
||||
|
||||
**Cause:** SOPS not installed or not in PATH
|
||||
|
||||
**Solution:**
|
||||
- Mac: `brew install sops`
|
||||
- Windows: `choco install sops` or add to PATH manually
|
||||
- Linux: Download from GitHub releases
|
||||
|
||||
---
|
||||
|
||||
## What Gets Installed
|
||||
|
||||
After successful setup, these files/directories exist:
|
||||
|
||||
### Mac/Linux
|
||||
```
|
||||
~/.config/sops/age/keys.txt # Age private key
|
||||
~/vault/ # Vault repository
|
||||
~/vault/.sops.yaml # SOPS config
|
||||
~/vault/msp-tools/*.sops.yaml # Encrypted credentials (6 files)
|
||||
~/vault/scripts/vault.sh # Vault CLI wrapper
|
||||
~/ClaudeTools/.claude/identity.json # Contains vault_path
|
||||
~/.zshenv (or ~/.bashrc) # Contains SOPS_AGE_KEY_FILE
|
||||
```
|
||||
|
||||
### Windows
|
||||
```
|
||||
C:\Users\<user>\.config\sops\age\keys.txt # Age private key
|
||||
D:\vault\ # Vault repository
|
||||
D:\vault\.sops.yaml # SOPS config
|
||||
D:\vault\msp-tools\*.sops.yaml # Encrypted credentials (6 files)
|
||||
D:\vault\scripts\vault.sh # Vault CLI wrapper
|
||||
D:\ClaudeTools\.claude\identity.json # Contains vault_path
|
||||
Environment variable: SOPS_AGE_KEY_FILE # System environment
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Vault Repository Structure
|
||||
|
||||
```
|
||||
vault/
|
||||
├── .sops.yaml # SOPS encryption config
|
||||
├── README.md # Vault documentation
|
||||
├── scripts/
|
||||
│ ├── vault.sh # CLI wrapper
|
||||
│ └── yaml-query.py # YAML parser (yq fallback)
|
||||
├── msp-tools/
|
||||
│ ├── computerguru-security-investigator.sops.yaml # Tier 1: Graph read
|
||||
│ ├── computerguru-exchange-operator.sops.yaml # Tier 2: EXO write
|
||||
│ ├── computerguru-user-manager.sops.yaml # Tier 3: Graph user write
|
||||
│ ├── computerguru-tenant-admin.sops.yaml # Tier 4: Graph admin
|
||||
│ ├── computerguru-defender-addon.sops.yaml # Tier 5: MDE only
|
||||
│ └── computerguru-management.sops.yaml # Legacy (deprecated)
|
||||
├── infrastructure/
|
||||
├── clients/
|
||||
├── services/
|
||||
└── projects/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Security Notes
|
||||
|
||||
### Age Key Security
|
||||
|
||||
**The age private key decrypts ALL vault secrets. Treat it like a master password.**
|
||||
|
||||
- Never commit to git repositories
|
||||
- Never share in plaintext over unsecured channels
|
||||
- File permissions: 600 (owner read/write only)
|
||||
- Store in `.config/sops/age/` (standard location)
|
||||
|
||||
### Gitea Credentials
|
||||
|
||||
- Password: `Gptf*77ttb123!@#-git`
|
||||
- Used for vault repo clone/pull/push
|
||||
- Same credentials on all machines
|
||||
- Consider using SSH keys instead of HTTPS for better security
|
||||
|
||||
### SOPS Files
|
||||
|
||||
- Encrypted at rest with age
|
||||
- Only `credentials`, `password`, `secret`, `api_key`, `token` fields are encrypted
|
||||
- Metadata (kind, name, description) is plaintext
|
||||
- Encrypted regex defined in `.sops.yaml`
|
||||
|
||||
---
|
||||
|
||||
## Maintenance
|
||||
|
||||
### Pulling Latest Vault Changes
|
||||
|
||||
**Mac/Linux:**
|
||||
```bash
|
||||
cd ~/vault
|
||||
git pull origin main
|
||||
```
|
||||
|
||||
**Windows:**
|
||||
```bash
|
||||
cd D:\vault
|
||||
git pull origin main
|
||||
```
|
||||
|
||||
**Run this periodically to get:**
|
||||
- New SOPS files
|
||||
- Updated credentials
|
||||
- Vault script improvements
|
||||
|
||||
### Rotating Age Key
|
||||
|
||||
If the age key needs to be rotated:
|
||||
|
||||
1. Generate new age key: `age-keygen -o new-key.txt`
|
||||
2. Re-encrypt all SOPS files with new key
|
||||
3. Distribute new key to all machines
|
||||
4. Update `.config/sops/age/keys.txt` on each machine
|
||||
5. Update `.sops.yaml` with new public key
|
||||
|
||||
**Note:** This is a team-wide operation requiring coordination.
|
||||
|
||||
---
|
||||
|
||||
## Multi-Machine Status
|
||||
|
||||
| Machine | Vault Status | Notes |
|
||||
|---------|--------------|-------|
|
||||
| DESKTOP-0O8A1RL (Windows) | ✓ WORKING | Original setup, all tiers tested |
|
||||
| Mikes-MacBook-Air (Mac) | ✓ WORKING | Full setup completed 2026-04-21 |
|
||||
| ACG-Tech03L (Howard) | PENDING | Needs vault clone + age key setup |
|
||||
| HOWARD-HOME | PENDING | Needs vault clone + age key setup |
|
||||
|
||||
---
|
||||
|
||||
## For Howard (ACG-Tech03L Setup)
|
||||
|
||||
Howard, when you're ready to set up remediation-tool:
|
||||
|
||||
### Quick Setup (Git Bash)
|
||||
|
||||
```bash
|
||||
# 1. Clone vault
|
||||
git clone http://azcomputerguru@172.16.3.20:3000/azcomputerguru/vault.git D:/vault
|
||||
# Password: Gptf*77ttb123!@#-git
|
||||
|
||||
# 2. Install age key
|
||||
mkdir -p ~/.config/sops/age
|
||||
cat > ~/.config/sops/age/keys.txt << 'AGEEOF'
|
||||
# created: 2026-03-30T13:53:19-07:00
|
||||
# public key: age1qz7ct84m50u06h97artqddkj3c8se2yu4nxu59clq8rhj945jc0s5excpr
|
||||
AGE-SECRET-KEY-1DE3V6V0ZLLZ45A7GA77M79CTN4LZQMTRCURP8VRGNLV6T2FSZEEQXUW2EU
|
||||
AGEEOF
|
||||
|
||||
# 3. Set environment variable (PowerShell)
|
||||
# Run this in PowerShell (not Git Bash):
|
||||
[Environment]::SetEnvironmentVariable("SOPS_AGE_KEY_FILE", "$env:USERPROFILE\.config\sops\age\keys.txt", "User")
|
||||
|
||||
# 4. Add vault_path to identity.json
|
||||
# Edit C:\claudetools\.claude\identity.json
|
||||
# Add: "vault_path": "D:/vault"
|
||||
|
||||
# 5. Fix line endings if needed
|
||||
dos2unix /d/vault/scripts/vault.sh
|
||||
chmod +x /d/vault/scripts/vault.sh
|
||||
|
||||
# 6. Test
|
||||
bash C:/claudetools/.claude/skills/remediation-tool/scripts/get-token.sh grabblaw.com investigator
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- **SOPS:** https://github.com/mozilla/sops
|
||||
- **age:** https://github.com/FiloSottile/age
|
||||
- **Vault repo:** http://172.16.3.20:3000/azcomputerguru/vault
|
||||
- **ClaudeTools repo:** http://172.16.3.20:3000/azcomputerguru/claudetools
|
||||
|
||||
---
|
||||
|
||||
**Last tested:** 2026-04-21 on Mikes-MacBook-Air.local
|
||||
**Status:** Complete and validated - all 4 tiers working
|
||||
**Maintainer:** Mike Swanson
|
||||
Reference in New Issue
Block a user