Files
KohakuHub/scripts/generate_secret.py
2025-10-07 19:04:57 +08:00

184 lines
5.2 KiB
Python

#!/usr/bin/env python3
"""
Generate cryptographically secure random secrets for KohakuHub configuration.
Usage:
python generate_secret.py [length]
python generate_secret.py 32 # Generate 32-character secret
python generate_secret.py # Default: 64 characters
Use cases:
- KOHAKU_HUB_SESSION_SECRET
- KOHAKU_HUB_ADMIN_SECRET_TOKEN
- LAKEFS_AUTH_ENCRYPT_SECRET_KEY
- Any other secret configuration values
"""
import argparse
import secrets
import string
import sys
def generate_secret(length: int = 64, charset: str = "all") -> str:
"""Generate a cryptographically secure random secret.
Args:
length: Length of the secret to generate
charset: Character set to use ('all', 'alphanumeric', 'safe', 'base64')
Returns:
Random secret string
"""
if charset == "alphanumeric":
# Only letters and numbers (safe for all contexts)
alphabet = string.ascii_letters + string.digits
elif charset == "safe":
# URL-safe, DNS-safe: [a-zA-Z0-9.-_]
alphabet = string.ascii_letters + string.digits + ".-_"
elif charset == "base64":
# Base64-safe characters (URL-safe, no period)
alphabet = string.ascii_letters + string.digits + "-_"
else: # "all"
# All printable ASCII except quotes and backslash (shell-safe)
alphabet = string.ascii_letters + string.digits + "!#$%&()*+,-./:;<=>?@[]^_{|}~"
return "".join(secrets.choice(alphabet) for _ in range(length))
def generate_multiple_secrets():
"""Generate multiple secrets for common use cases."""
print("=" * 70)
print("KohakuHub Secret Generator - Multiple Secrets")
print("=" * 70)
print("\nGenerated secrets for common configuration values:\n")
secrets_config = [
("KOHAKU_HUB_SESSION_SECRET", 64, "all"),
("KOHAKU_HUB_ADMIN_SECRET_TOKEN", 64, "all"),
("LAKEFS_AUTH_ENCRYPT_SECRET_KEY", 32, "alphanumeric"),
]
for name, length, charset in secrets_config:
secret = generate_secret(length, charset)
print(f"{name}:")
print(f" {secret}")
print()
print("=" * 70)
print("Copy these values to your .env file or docker-compose.yml")
print("=" * 70)
def main():
parser = argparse.ArgumentParser(
description="Generate cryptographically secure random secrets",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
# Generate default 64-character secret
python generate_secret.py
# Generate 32-character secret
python generate_secret.py 32
# Generate alphanumeric-only secret (safer for some contexts)
python generate_secret.py 64 --charset alphanumeric
# Generate safe secret [a-zA-Z0-9.-_] (URL-safe, DNS-safe)
python generate_secret.py 64 --charset safe
# Generate base64-safe secret [a-zA-Z0-9-_] (URL-safe, no period)
python generate_secret.py 64 --charset base64
# Generate multiple secrets for all config values
python generate_secret.py --all
Common lengths:
32 - Good for most secrets (256 bits)
64 - Extra secure (512 bits) - recommended
128 - Maximum security (1024 bits)
Common use cases:
KOHAKU_HUB_SESSION_SECRET - 64 chars (all)
KOHAKU_HUB_ADMIN_SECRET_TOKEN - 64 chars (all)
LAKEFS_AUTH_ENCRYPT_SECRET_KEY - 32 chars (alphanumeric)
Database passwords - 32-64 chars (alphanumeric)
""",
)
parser.add_argument(
"length",
type=int,
nargs="?",
default=64,
help="Length of the secret (default: 64)",
)
parser.add_argument(
"--charset",
choices=["all", "alphanumeric", "safe", "base64"],
default="all",
help="Character set to use (default: all)",
)
parser.add_argument(
"--all",
action="store_true",
help="Generate multiple secrets for all common config values",
)
parser.add_argument(
"--copy",
action="store_true",
help="Copy secret to clipboard (requires pyperclip)",
)
args = parser.parse_args()
# Validate length
if args.length < 16:
print("Error: Secret length must be at least 16 characters", file=sys.stderr)
sys.exit(1)
if args.length > 512:
print(
"Warning: Secret length >512 is excessive and may cause issues",
file=sys.stderr,
)
# Generate multiple secrets mode
if args.all:
generate_multiple_secrets()
return
# Generate single secret
secret = generate_secret(args.length, args.charset)
# Print the secret
print("=" * 70)
print(f"Generated {args.length}-character secret ({args.charset} charset):")
print("=" * 70)
print()
print(secret)
print()
print("=" * 70)
print(f"Entropy: ~{args.length * 6} bits (secure)")
print("=" * 70)
# Copy to clipboard if requested
if args.copy:
try:
import pyperclip
pyperclip.copy(secret)
print("\n✓ Secret copied to clipboard!")
except ImportError:
print(
"\nNote: Install pyperclip to enable clipboard copy: pip install pyperclip"
)
if __name__ == "__main__":
main()