maybe good

This commit is contained in:
HotSwapp
2025-08-08 15:55:15 -05:00
parent ab6f163c15
commit b257a06787
80 changed files with 19739 additions and 0 deletions

44
scripts/backup.sh Executable file
View File

@@ -0,0 +1,44 @@
#!/bin/bash
# Backup script for Delphi Database System
set -e
BACKUP_DIR="/app/backups"
DB_FILE="/app/data/delphi_database.db"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
BACKUP_FILE="${BACKUP_DIR}/delphi_backup_${TIMESTAMP}.db"
echo "🔄 Starting database backup..."
# Create backup directory if it doesn't exist
mkdir -p "$BACKUP_DIR"
# Check if database exists
if [ ! -f "$DB_FILE" ]; then
echo "❌ Database file not found: $DB_FILE"
exit 1
fi
# Create backup
echo "📦 Creating backup: $BACKUP_FILE"
cp "$DB_FILE" "$BACKUP_FILE"
# Verify backup
if [ -f "$BACKUP_FILE" ]; then
BACKUP_SIZE=$(stat -f%z "$BACKUP_FILE" 2>/dev/null || stat -c%s "$BACKUP_FILE" 2>/dev/null)
echo "✅ Backup created successfully"
echo " File: $BACKUP_FILE"
echo " Size: $BACKUP_SIZE bytes"
else
echo "❌ Backup failed"
exit 1
fi
# Clean up old backups (keep last 10)
echo "🧹 Cleaning up old backups..."
find "$BACKUP_DIR" -name "delphi_backup_*.db" -type f | sort -r | tail -n +11 | xargs -r rm -f
REMAINING_BACKUPS=$(find "$BACKUP_DIR" -name "delphi_backup_*.db" -type f | wc -l)
echo "📊 Remaining backups: $REMAINING_BACKUPS"
echo "🎉 Backup process completed!"

116
scripts/git-pre-commit-hook Executable file
View File

@@ -0,0 +1,116 @@
#!/bin/bash
# Pre-commit hook for Delphi Consulting Group Database System
# Prevents committing sensitive files and data
#
# To install: ln -s ../../scripts/git-pre-commit-hook .git/hooks/pre-commit
set -e
# Colors for output
RED='\033[0;31m'
YELLOW='\033[1;33m'
GREEN='\033[0;32m'
NC='\033[0m' # No Color
echo -e "${GREEN}🔍 Running security pre-commit checks...${NC}"
# Flag to track if any issues found
ISSUES_FOUND=0
# Function to report security issue
report_issue() {
echo -e "${RED}❌ SECURITY ISSUE: $1${NC}"
ISSUES_FOUND=1
}
# Function to report warning
report_warning() {
echo -e "${YELLOW}⚠️ WARNING: $1${NC}"
}
# Check for .env files
if git diff --cached --name-only | grep -E "\.env$|\.env\." > /dev/null; then
report_issue "Environment files (.env) contain secrets and should not be committed!"
echo " Files: $(git diff --cached --name-only | grep -E "\.env$|\.env\.")"
fi
# Check for database files
if git diff --cached --name-only | grep -E "\.(db|sqlite|sqlite3)$" > /dev/null; then
report_issue "Database files contain sensitive data and should not be committed!"
echo " Files: $(git diff --cached --name-only | grep -E "\.(db|sqlite|sqlite3)$")"
fi
# Check for backup files
if git diff --cached --name-only | grep -E "\.(backup|bak|dump)$|backups/" > /dev/null; then
report_issue "Backup files may contain sensitive data and should not be committed!"
echo " Files: $(git diff --cached --name-only | grep -E "\.(backup|bak|dump)$|backups/")"
fi
# Check for SSL certificates and keys
if git diff --cached --name-only | grep -E "\.(pem|key|crt|cert|p12|pfx)$" > /dev/null; then
report_issue "SSL certificates and private keys should not be committed!"
echo " Files: $(git diff --cached --name-only | grep -E "\.(pem|key|crt|cert|p12|pfx)$")"
fi
# Check for upload directories
if git diff --cached --name-only | grep -E "uploads/|user-uploads/" > /dev/null; then
report_issue "Upload directories may contain sensitive user documents!"
echo " Files: $(git diff --cached --name-only | grep -E "uploads/|user-uploads/")"
fi
# Check for local configuration files
if git diff --cached --name-only | grep -E "\-local\.|config\.local|settings\.local" > /dev/null; then
report_warning "Local configuration files detected - ensure they don't contain secrets"
echo " Files: $(git diff --cached --name-only | grep -E "\-local\.|config\.local|settings\.local")"
fi
# Check for common secret patterns in staged files
SECRET_PATTERNS=(
"password\s*=\s*['\"][^'\"]+['\"]"
"api_key\s*=\s*['\"][^'\"]+['\"]"
"secret_key\s*=\s*['\"][^'\"]+['\"]"
"token\s*=\s*['\"][^'\"]+['\"]"
"-----BEGIN (RSA )?PRIVATE KEY-----"
"-----BEGIN CERTIFICATE-----"
)
for pattern in "${SECRET_PATTERNS[@]}"; do
if git diff --cached | grep -qiE "$pattern"; then
report_warning "Potential secret detected in staged changes"
echo " Pattern: $pattern"
echo " Review your changes carefully!"
fi
done
# Check for large files (may be database dumps or uploads)
LARGE_FILES=$(git diff --cached --name-only | xargs -I {} stat -f%z {} 2>/dev/null | awk '$1 > 1048576 {count++} END {print count+0}')
if [ "$LARGE_FILES" -gt 0 ]; then
report_warning "$LARGE_FILES large files detected (>1MB) - ensure they're not sensitive data"
fi
# Check for Python cache files (should be in .gitignore but double-check)
if git diff --cached --name-only | grep -E "__pycache__|\.pyc$" > /dev/null; then
report_warning "Python cache files detected - these should be in .gitignore"
echo " Files: $(git diff --cached --name-only | grep -E "__pycache__|\.pyc$")"
fi
# If any security issues found, prevent commit
if [ $ISSUES_FOUND -eq 1 ]; then
echo -e "${RED}🚫 COMMIT BLOCKED: Security issues detected!${NC}"
echo ""
echo "To fix:"
echo "1. Remove sensitive files from staging: git reset HEAD <filename>"
echo "2. Add files to .gitignore if needed"
echo "3. Use environment variables for secrets"
echo "4. Run: python scripts/setup-security.py for proper configuration"
echo ""
echo "To bypass this check (NOT RECOMMENDED): git commit --no-verify"
exit 1
fi
# Show summary
echo -e "${GREEN}✅ Pre-commit security checks passed!${NC}"
echo "📝 Staged files: $(git diff --cached --name-only | wc -l)"
# Success - allow commit to proceed
exit 0

76
scripts/init-container.sh Executable file
View File

@@ -0,0 +1,76 @@
#!/bin/bash
# Initialization script for Delphi Database System Docker container
set -e
echo "🚀 Initializing Delphi Consulting Group Database System..."
# Create necessary directories
mkdir -p /app/data /app/uploads /app/backups /app/exports /app/logs
# Set permissions
chmod 755 /app/data /app/uploads /app/backups /app/exports
chmod 750 /app/logs
# Check if database exists
if [ ! -f "/app/data/delphi_database.db" ]; then
echo "📊 Database not found. Creating new database..."
# Initialize database tables
python -c "
from app.database.base import engine
from app.models import BaseModel
BaseModel.metadata.create_all(bind=engine)
print('✅ Database tables created successfully')
"
# Check if we should create admin user
if [ "${CREATE_ADMIN_USER}" = "true" ]; then
echo "👤 Creating default admin user..."
python -c "
from sqlalchemy.orm import sessionmaker
from app.database.base import engine
from app.models.user import User
from app.auth.security import get_password_hash
import os
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
db = SessionLocal()
try:
# Check if admin already exists
existing_admin = db.query(User).filter(User.username == 'admin').first()
if not existing_admin:
admin_user = User(
username=os.getenv('ADMIN_USERNAME', 'admin'),
email=os.getenv('ADMIN_EMAIL', 'admin@delphicg.local'),
full_name=os.getenv('ADMIN_FULLNAME', 'System Administrator'),
hashed_password=get_password_hash(os.getenv('ADMIN_PASSWORD', 'admin123')),
is_active=True,
is_admin=True
)
db.add(admin_user)
db.commit()
print('✅ Default admin user created')
print(f' Username: {admin_user.username}')
print(f' Email: {admin_user.email}')
print(' Password: See ADMIN_PASSWORD environment variable')
else:
print(' Admin user already exists, skipping creation')
finally:
db.close()
"
fi
else
echo "✅ Database found, skipping initialization"
fi
# Run database migrations if needed (future feature)
# echo "🔄 Running database migrations..."
# python -m alembic upgrade head
echo "🎉 Initialization complete!"
# Start the application
echo "🌟 Starting Delphi Database System..."
exec "$@"

47
scripts/install-git-hooks.sh Executable file
View File

@@ -0,0 +1,47 @@
#!/bin/bash
# Install Git hooks for Delphi Consulting Group Database System
set -e
echo "🔧 Installing Git hooks for enhanced security..."
# Check if we're in a git repository
if [ ! -d ".git" ]; then
echo "❌ Error: Not in a Git repository root directory"
echo " Please run this script from the project root where .git directory exists"
exit 1
fi
# Create hooks directory if it doesn't exist
mkdir -p .git/hooks
# Install pre-commit hook
if [ -f ".git/hooks/pre-commit" ]; then
echo "⚠️ Pre-commit hook already exists. Creating backup..."
mv .git/hooks/pre-commit .git/hooks/pre-commit.backup
fi
# Create symlink to our pre-commit hook
ln -sf ../../scripts/git-pre-commit-hook .git/hooks/pre-commit
# Make sure it's executable
chmod +x .git/hooks/pre-commit
echo "✅ Pre-commit hook installed successfully!"
echo ""
echo "🛡️ Security features enabled:"
echo " • Prevents committing .env files"
echo " • Blocks database files and backups"
echo " • Detects SSL certificates and keys"
echo " • Warns about potential secrets in code"
echo " • Checks for large files (potential data dumps)"
echo ""
echo "💡 The hook will run automatically before each commit."
echo " To bypass (NOT recommended): git commit --no-verify"
echo ""
echo "🧪 Test the hook:"
echo " 1. Try staging a .env file: touch .env && git add .env"
echo " 2. Run: git commit -m 'test'"
echo " 3. The commit should be blocked with a security warning"
echo ""
echo "✨ Your repository is now protected against accidental secret commits!"

56
scripts/restore.sh Executable file
View File

@@ -0,0 +1,56 @@
#!/bin/bash
# Restore script for Delphi Database System
set -e
BACKUP_DIR="/app/backups"
DB_FILE="/app/data/delphi_database.db"
echo "🔄 Starting database restore..."
# Check if backup file is provided
if [ -z "$1" ]; then
echo "📋 Available backups:"
ls -la "$BACKUP_DIR"/delphi_backup_*.db 2>/dev/null || echo " No backups found"
echo ""
echo "Usage: $0 <backup_file>"
echo "Example: $0 delphi_backup_20241207_143000.db"
exit 1
fi
BACKUP_FILE="$BACKUP_DIR/$1"
# Check if backup file exists
if [ ! -f "$BACKUP_FILE" ]; then
echo "❌ Backup file not found: $BACKUP_FILE"
echo "📋 Available backups:"
ls -la "$BACKUP_DIR"/delphi_backup_*.db 2>/dev/null || echo " No backups found"
exit 1
fi
# Create backup of current database before restore
if [ -f "$DB_FILE" ]; then
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
CURRENT_BACKUP="${BACKUP_DIR}/delphi_backup_before_restore_${TIMESTAMP}.db"
echo "💾 Creating backup of current database..."
cp "$DB_FILE" "$CURRENT_BACKUP"
echo "✅ Current database backed up to: $CURRENT_BACKUP"
fi
# Restore database
echo "🔄 Restoring database from: $BACKUP_FILE"
cp "$BACKUP_FILE" "$DB_FILE"
# Verify restore
if [ -f "$DB_FILE" ]; then
DB_SIZE=$(stat -f%z "$DB_FILE" 2>/dev/null || stat -c%s "$DB_FILE" 2>/dev/null)
echo "✅ Database restored successfully"
echo " File: $DB_FILE"
echo " Size: $DB_SIZE bytes"
else
echo "❌ Restore failed"
exit 1
fi
echo "🎉 Restore process completed!"
echo "⚠️ Please restart the application to ensure proper database connection."

195
scripts/setup-security.py Executable file
View File

@@ -0,0 +1,195 @@
#!/usr/bin/env python3
"""
Security setup script for Delphi Consulting Group Database System
Generates secure keys and helps configure environment variables
"""
import secrets
import string
import os
import sys
def generate_secret_key(length=32):
"""Generate a secure secret key"""
return secrets.token_urlsafe(length)
def generate_secure_password(length=16):
"""Generate a secure password with mixed characters"""
alphabet = string.ascii_letters + string.digits + "!@#$%^&*"
password = ''.join(secrets.choice(alphabet) for _ in range(length))
return password
def create_env_file():
"""Create a .env file with secure defaults"""
env_path = ".env"
if os.path.exists(env_path):
response = input(f"{env_path} already exists. Overwrite? (y/N): ").strip().lower()
if response != 'y':
print("Keeping existing .env file.")
return False
print("🔐 Generating secure configuration...")
# Generate secure values
secret_key = generate_secret_key(32)
admin_password = generate_secure_password(16)
# Get user inputs
print("\n📝 Please provide the following information:")
admin_username = input("Admin username [admin]: ").strip() or "admin"
admin_email = input("Admin email [admin@delphicg.local]: ").strip() or "admin@delphicg.local"
admin_fullname = input("Admin full name [System Administrator]: ").strip() or "System Administrator"
external_port = input("External port [6920]: ").strip() or "6920"
# Ask about password
use_generated = input(f"Use generated password '{admin_password}'? (Y/n): ").strip().lower()
if use_generated == 'n':
admin_password = input("Enter custom admin password: ").strip()
while len(admin_password) < 8:
print("Password must be at least 8 characters long!")
admin_password = input("Enter custom admin password: ").strip()
# Create .env content
env_content = f"""# Delphi Consulting Group Database System - Environment Variables
# Generated by setup-security.py on {__import__('datetime').datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
# ===== APPLICATION SETTINGS =====
APP_NAME=Delphi Consulting Group Database System
DEBUG=False
# ===== DATABASE CONFIGURATION =====
DATABASE_URL=sqlite:///data/delphi_database.db
# ===== SECURITY SETTINGS - GENERATED =====
SECRET_KEY={secret_key}
ACCESS_TOKEN_EXPIRE_MINUTES=30
ALGORITHM=HS256
# ===== ADMIN USER CREATION =====
CREATE_ADMIN_USER=true
ADMIN_USERNAME={admin_username}
ADMIN_EMAIL={admin_email}
ADMIN_PASSWORD={admin_password}
ADMIN_FULLNAME={admin_fullname}
# ===== SERVER SETTINGS =====
HOST=0.0.0.0
PORT=8000
EXTERNAL_PORT={external_port}
# ===== FILE STORAGE =====
UPLOAD_DIR=./uploads
BACKUP_DIR=./backups
# ===== PAGINATION =====
DEFAULT_PAGE_SIZE=50
MAX_PAGE_SIZE=200
# ===== LOGGING =====
LOG_LEVEL=INFO
# ===== PRODUCTION SECURITY =====
SECURE_COOKIES=False
SECURE_SSL_REDIRECT=False
# ===== CORS SETTINGS =====
CORS_ORIGINS=["http://localhost:{external_port}"]
# ===== RATE LIMITING =====
RATE_LIMIT_PER_MINUTE=100
LOGIN_RATE_LIMIT_PER_MINUTE=10
# ===== DOCKER SETTINGS =====
WORKERS=4
WORKER_TIMEOUT=120
# ===== BACKUP SETTINGS =====
BACKUP_RETENTION_COUNT=10
# ===== MONITORING & HEALTH CHECKS =====
HEALTH_CHECK_INTERVAL=30
HEALTH_CHECK_TIMEOUT=10
"""
# Write .env file
try:
with open(env_path, 'w') as f:
f.write(env_content)
# Set restrictive permissions
os.chmod(env_path, 0o600)
print(f"\n✅ Created {env_path} with secure configuration!")
print(f"📁 File permissions set to 600 (owner read/write only)")
print(f"\n🔐 Generated credentials:")
print(f" Secret Key: {secret_key[:10]}... (truncated)")
print(f" Admin Username: {admin_username}")
print(f" Admin Email: {admin_email}")
print(f" Admin Password: {admin_password}")
print(f" External Port: {external_port}")
print(f"\n⚠️ IMPORTANT SECURITY NOTES:")
print(f" • Keep the .env file secure and never commit it to version control")
print(f" • Change the admin password after first login")
print(f" • The secret key is used for JWT token signing")
print(f" • For production, consider using stronger passwords and key rotation")
return True
except Exception as e:
print(f"❌ Error creating .env file: {e}")
return False
def show_security_checklist():
"""Display security checklist"""
print("\n📋 PRODUCTION SECURITY CHECKLIST:")
checklist = [
"✓ Generated secure SECRET_KEY",
"✓ Set strong admin password",
"✓ Configured proper CORS origins",
"□ Set up SSL/HTTPS in production",
"□ Configure firewall rules",
"□ Set up regular backups",
"□ Enable monitoring/logging",
"□ Review user access permissions",
"□ Update Docker images regularly",
"□ Set up intrusion detection"
]
for item in checklist:
print(f" {item}")
def main():
print("🛡️ Delphi Database Security Setup")
print("=" * 40)
if len(sys.argv) > 1 and sys.argv[1] == "--key-only":
print("🔑 Generating secure secret key:")
print(generate_secret_key(32))
return
if len(sys.argv) > 1 and sys.argv[1] == "--password-only":
print("🔒 Generating secure password:")
print(generate_secure_password(16))
return
print("This script will help you set up secure configuration for the")
print("Delphi Consulting Group Database System.\n")
# Create .env file
if create_env_file():
show_security_checklist()
print(f"\n🚀 Next steps:")
print(f" 1. Review the generated .env file")
print(f" 2. Start the application: docker-compose up -d")
print(f" 3. Access: http://localhost:{os.getenv('EXTERNAL_PORT', '6920')}")
print(f" 4. Login with the generated admin credentials")
print(f" 5. Change the admin password after first login")
else:
print("\n❌ Setup failed or cancelled.")
sys.exit(1)
if __name__ == "__main__":
main()