rotate_passwords.py 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. import pymysql
  2. import os
  3. import secrets
  4. import string
  5. import subprocess
  6. def generate_password(length=16):
  7. characters = string.ascii_letters + string.digits + "!@#$%^&*"
  8. return ''.join(secrets.choice(characters) for _ in range(length))
  9. def update_env_file(passwords):
  10. env_file = '.env'
  11. lines = []
  12. if os.path.exists(env_file):
  13. with open(env_file, 'r') as f:
  14. lines = f.readlines()
  15. # Remove old password lines
  16. lines = [l for l in lines if not any(l.startswith(f"{k}=") for k in passwords.keys())]
  17. # Add new passwords
  18. for key, val in passwords.items():
  19. lines.append(f"{key}={val}\n")
  20. with open(env_file, 'w') as f:
  21. f.writelines(lines)
  22. print("✅ .env file updated with new synchronized passwords.")
  23. def main():
  24. print("🔄 Starting Password Synchronization Routine...")
  25. # 1. Connect to MySQL as root
  26. try:
  27. conn = pymysql.connect(
  28. host='192.168.130.170', # Assuming we run this from host to mapped port, or within a container network
  29. port=3307,
  30. user='root',
  31. password='root_pass',
  32. database='food_db'
  33. )
  34. except Exception as e:
  35. print(f"❌ Could not connect to MySQL: {e}")
  36. return
  37. # 2. Generate new passwords
  38. new_passwords = {
  39. 'DB_READER_PASS': generate_password(),
  40. 'DB_LOADER_PASS': generate_password(),
  41. 'DB_APP_AUTH_PASS': generate_password()
  42. }
  43. # 3. Update MySQL Users
  44. try:
  45. with conn.cursor() as cursor:
  46. cursor.execute("ALTER USER 'db_reader'@'%%' IDENTIFIED BY %s", (new_passwords['DB_READER_PASS'],))
  47. cursor.execute("ALTER USER 'db_loader'@'%%' IDENTIFIED BY %s", (new_passwords['DB_LOADER_PASS'],))
  48. cursor.execute("ALTER USER 'db_app_auth'@'%%' IDENTIFIED BY %s", (new_passwords['DB_APP_AUTH_PASS'],))
  49. cursor.execute("FLUSH PRIVILEGES")
  50. conn.commit()
  51. print("✅ Database user passwords rotated successfully.")
  52. except Exception as e:
  53. print(f"❌ Failed to alter database users: {e}")
  54. finally:
  55. conn.close()
  56. # 4. Update .env file so Docker Compose picks it up
  57. update_env_file(new_passwords)
  58. # 5. Gracefully restart client containers to sync connection
  59. print("🔄 Restarting App and Ingest containers to synchronize new credentials...")
  60. try:
  61. subprocess.run(["docker-compose", "up", "-d", "app"], check=True)
  62. # We don't necessarily need to restart ingest if it's manual, but we can recreate it if it was running.
  63. print("✅ Client containers synchronized with new database passwords!")
  64. except Exception as e:
  65. print(f"⚠️ Failed to restart docker containers: {e}")
  66. if __name__ == "__main__":
  67. main()