# 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
