Post-Tyranny-Tech-Infrastru.../scripts/generate-client-keys.sh
Pieter 071ed083f7 feat: Implement per-client SSH key isolation
Resolves #14

Each client now gets a dedicated SSH key pair, ensuring that compromise
of one client server does not grant access to other client servers.

## Changes

### Infrastructure (OpenTofu)
- Replace shared `hcloud_ssh_key.default` with per-client `hcloud_ssh_key.client`
- Each client key read from `keys/ssh/<client_name>.pub`
- Server recreated with new key (dev server only, acceptable downtime)

### Key Management
- Created `keys/ssh/` directory for SSH keys
- Added `.gitignore` to protect private keys from git
- Generated ED25519 key pair for dev client
- Private key gitignored, public key committed

### Scripts
- **`scripts/generate-client-keys.sh`** - Generate SSH key pairs for clients
- Updated `scripts/deploy-client.sh` to check for client SSH key

### Documentation
- **`docs/ssh-key-management.md`** - Complete SSH key management guide
- **`keys/ssh/README.md`** - Quick reference for SSH keys directory

### Configuration
- Removed `ssh_public_key` variable from `variables.tf`
- Updated `terraform.tfvars` to remove shared SSH key reference
- Updated `terraform.tfvars.example` with new key generation instructions

## Security Improvements

 Client isolation: Each client has dedicated SSH key
 Granular rotation: Rotate keys per-client without affecting others
 Defense in depth: Minimize blast radius of key compromise
 Proper key storage: Private keys gitignored, backups documented

## Testing

-  Generated new SSH key for dev client
-  Applied OpenTofu changes (server recreated)
-  Tested SSH access: `ssh -i keys/ssh/dev root@78.47.191.38`
-  Verified key isolation: Old shared key removed from Hetzner

## Migration Notes

For existing clients:
1. Generate key: `./scripts/generate-client-keys.sh <client>`
2. Apply OpenTofu: `cd tofu && tofu apply` (will recreate server)
3. Deploy: `./scripts/deploy-client.sh <client>`

For new clients:
1. Generate key first
2. Deploy as normal

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-17 19:50:30 +01:00

84 lines
2.2 KiB
Bash
Executable file

#!/usr/bin/env bash
#
# Generate SSH key pair for a client
#
# Usage: ./scripts/generate-client-keys.sh <client_name>
#
# This script generates a dedicated ED25519 SSH key pair for a client,
# ensuring proper isolation between client servers.
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Script directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
KEY_DIR="$PROJECT_ROOT/keys/ssh"
# Check arguments
if [ $# -ne 1 ]; then
echo -e "${RED}Error: Client name required${NC}"
echo "Usage: $0 <client_name>"
echo ""
echo "Example: $0 newclient"
exit 1
fi
CLIENT_NAME="$1"
# Validate client name (alphanumeric and hyphens only)
if ! [[ "$CLIENT_NAME" =~ ^[a-z0-9-]+$ ]]; then
echo -e "${RED}Error: Invalid client name${NC}"
echo "Client name must contain only lowercase letters, numbers, and hyphens"
exit 1
fi
# Check if key already exists
if [ -f "$KEY_DIR/$CLIENT_NAME" ]; then
echo -e "${YELLOW}⚠ Warning: SSH key already exists for client: $CLIENT_NAME${NC}"
echo ""
echo "Existing key: $KEY_DIR/$CLIENT_NAME"
echo ""
read -p "Overwrite existing key? This will break SSH access to the server! [yes/NO] " confirm
if [ "$confirm" != "yes" ]; then
echo "Aborted"
exit 1
fi
echo ""
fi
# Create keys directory if it doesn't exist
mkdir -p "$KEY_DIR"
echo -e "${BLUE}Generating SSH key pair for client: $CLIENT_NAME${NC}"
echo ""
# Generate ED25519 key pair
ssh-keygen -t ed25519 \
-f "$KEY_DIR/$CLIENT_NAME" \
-C "client-$CLIENT_NAME-deploy-key" \
-N ""
echo ""
echo -e "${GREEN}✓ SSH key pair generated successfully${NC}"
echo ""
echo "Private key: $KEY_DIR/$CLIENT_NAME"
echo "Public key: $KEY_DIR/$CLIENT_NAME.pub"
echo ""
echo "Key fingerprint:"
ssh-keygen -lf "$KEY_DIR/$CLIENT_NAME.pub"
echo ""
echo -e "${BLUE}Next steps:${NC}"
echo "1. Add client to tofu/terraform.tfvars"
echo "2. Apply OpenTofu: cd tofu && tofu apply"
echo "3. Deploy client: ./scripts/deploy-client.sh $CLIENT_NAME"
echo ""
echo -e "${YELLOW}⚠ IMPORTANT: Backup this key securely!${NC}"
echo " Store in password manager or secure backup location"
echo ""