trax/scripts/simple_key_manager.py

201 lines
7.4 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Simple API Key Manager - Consolidate keys without encryption
Quick solution to organize scattered API keys
"""
import os
import json
from pathlib import Path
from typing import Dict, List, Optional
from datetime import datetime
import argparse
from collections import defaultdict
class SimpleKeyManager:
"""Simple key management without encryption"""
def __init__(self):
self.workspace_root = Path(__file__).parent.parent.parent.parent
self.keys_file = self.workspace_root / "config" / "consolidated_keys.json"
self.keys_file.parent.mkdir(parents=True, exist_ok=True)
def scan_all_projects(self) -> Dict[str, Dict[str, str]]:
"""Scan all projects for .env files"""
projects = {
"root": self.workspace_root,
"trax": self.workspace_root / "apps" / "trax",
"youtube-summarizer": self.workspace_root / "apps" / "youtube-summarizer",
"pdf-translator": self.workspace_root / "pdf-translator",
"directus-mcp": self.workspace_root / "tools" / "directus-mcp-server",
}
all_keys = defaultdict(dict)
for project_name, project_path in projects.items():
env_file = project_path / ".env"
if env_file.exists():
with open(env_file, 'r') as f:
for line in f:
line = line.strip()
if line and not line.startswith('#'):
if '=' in line:
key, value = line.split('=', 1)
key = key.strip()
value = value.strip().strip('"').strip("'")
all_keys[key][project_name] = value
return dict(all_keys)
def consolidate(self):
"""Consolidate all keys and save to JSON"""
keys = self.scan_all_projects()
# Organize by category
categorized = {
"ai": {},
"services": {},
"database": {},
"settings": {},
"custom": {}
}
ai_prefixes = ["ANTHROPIC", "DEEPSEEK", "OPENAI", "PERPLEXITY", "OPENROUTER",
"GOOGLE_API", "XAI", "MISTRAL", "QWEN", "DASHSCOPE", "MODEL_STUDIO"]
service_prefixes = ["SLACK", "GITHUB", "GITEA", "YOUTUBE", "DIRECTUS", "MICROSOFT"]
db_prefixes = ["DATABASE", "REDIS", "POSTGRES"]
for key_name, values in keys.items():
# Pick the most common value or the one from root
if "root" in values:
final_value = values["root"]
else:
# Use the most frequent value
final_value = max(values.values(), key=lambda x: list(values.values()).count(x))
# Categorize
if any(key_name.startswith(prefix) for prefix in ai_prefixes):
categorized["ai"][key_name] = final_value
elif any(key_name.startswith(prefix) for prefix in service_prefixes):
categorized["services"][key_name] = final_value
elif any(key_name.startswith(prefix) for prefix in db_prefixes):
categorized["database"][key_name] = final_value
elif any(keyword in key_name for keyword in ["JWT", "SECRET", "TOKEN", "KEY"]):
categorized["settings"][key_name] = final_value
else:
categorized["custom"][key_name] = final_value
# Save to JSON
output = {
"consolidated_at": datetime.now().isoformat(),
"total_keys": sum(len(cat) for cat in categorized.values()),
"keys": categorized
}
with open(self.keys_file, 'w') as f:
json.dump(output, f, indent=2)
return output
def export_to_env(self, output_file: Path, filter_category: Optional[str] = None):
"""Export consolidated keys to .env format"""
if not self.keys_file.exists():
print("❌ No consolidated keys found. Run consolidate first.")
return
with open(self.keys_file, 'r') as f:
data = json.load(f)
with open(output_file, 'w') as f:
f.write(f"# Consolidated API Keys\n")
f.write(f"# Generated: {datetime.now().isoformat()}\n\n")
for category, keys in data["keys"].items():
if filter_category and category != filter_category:
continue
f.write(f"# {category.upper()} KEYS\n")
for key_name, value in sorted(keys.items()):
f.write(f"{key_name}={value}\n")
f.write("\n")
print(f"✅ Exported to {output_file}")
def report(self):
"""Generate a summary report"""
keys = self.scan_all_projects()
print("\n" + "=" * 60)
print("API KEY CONSOLIDATION REPORT")
print("=" * 60)
# Count keys by project
project_counts = defaultdict(int)
for key_name, values in keys.items():
for project in values.keys():
project_counts[project] += 1
print("\nKeys per project:")
for project, count in sorted(project_counts.items()):
print(f"{project}: {count} keys")
# Find conflicts
conflicts = []
for key_name, values in keys.items():
unique_values = set(values.values())
if len(unique_values) > 1:
conflicts.append(key_name)
if conflicts:
print(f"\n⚠️ {len(conflicts)} keys with conflicting values:")
for key in conflicts[:10]: # Show first 10
print(f"{key}")
print(f"\nTotal unique keys: {len(keys)}")
print("=" * 60)
def main():
parser = argparse.ArgumentParser(description="Simple API Key Manager")
subparsers = parser.add_subparsers(dest='command', help='Commands')
# Consolidate command
cons_parser = subparsers.add_parser('consolidate', help='Consolidate all keys')
# Export command
export_parser = subparsers.add_parser('export', help='Export to .env')
export_parser.add_argument('file', help='Output file path')
export_parser.add_argument('--category', help='Filter by category')
# Report command
report_parser = subparsers.add_parser('report', help='Show summary report')
args = parser.parse_args()
manager = SimpleKeyManager()
if args.command == 'consolidate':
result = manager.consolidate()
print(f"✅ Consolidated {result['total_keys']} keys to {manager.keys_file}")
print("\nKeys by category:")
for cat, keys in result["keys"].items():
print(f"{cat}: {len(keys)} keys")
elif args.command == 'export':
manager.export_to_env(Path(args.file), args.category)
elif args.command == 'report':
manager.report()
else:
# Default: consolidate and report
manager.report()
print("\nConsolidating keys...")
result = manager.consolidate()
print(f"\n✅ Saved to: {manager.keys_file}")
print("\nNext steps:")
print(f"1. Review: cat {manager.keys_file}")
print(f"2. Export: python3 {__file__} export .env")
print(f"3. Copy to projects as needed")
if __name__ == "__main__":
main()