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>
84 lines
2.2 KiB
Bash
Executable file
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 ""
|