report_datasource_credentials.py 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. """Read-only audit of legacy Neo4j DataSource credential state."""
  2. import argparse
  3. import json
  4. SUPPORTED_TYPES = {"postgresql", "postgres", "mysql"}
  5. def inspect_legacy_datasources(session):
  6. records = session.run(
  7. """
  8. MATCH (n:DataSource)
  9. RETURN elementId(n) AS legacy_id, properties(n) AS properties
  10. ORDER BY legacy_id
  11. """
  12. )
  13. report = []
  14. for record in records:
  15. properties = dict(record["properties"])
  16. issues = []
  17. uid = properties.get("uid")
  18. has_plaintext = any(
  19. properties.get(key)
  20. for key in (
  21. "username",
  22. "password",
  23. "conn_str",
  24. "connection_string",
  25. "connection_url",
  26. )
  27. )
  28. if not uid:
  29. issues.append("missing_uid")
  30. if has_plaintext:
  31. issues.append("plaintext_credentials")
  32. if (
  33. not has_plaintext
  34. and (
  35. not properties.get("credential_ref")
  36. or not properties.get("credential_version")
  37. )
  38. ):
  39. issues.append("missing_credential_reference")
  40. if str(properties.get("type") or "").lower() not in SUPPORTED_TYPES:
  41. issues.append("unsupported_database_type")
  42. if any(
  43. not properties.get(key)
  44. for key in ("host", "port", "database")
  45. ):
  46. issues.append("incomplete_connection_definition")
  47. if issues:
  48. report.append(
  49. {
  50. "data_source_uid": str(uid) if uid else None,
  51. "issues": issues,
  52. }
  53. )
  54. return report
  55. def main():
  56. parser = argparse.ArgumentParser(
  57. description="Report legacy DataSource credential issues"
  58. )
  59. parser.parse_args()
  60. from app.services.neo4j_driver import neo4j_driver
  61. with neo4j_driver.get_session() as session:
  62. for item in inspect_legacy_datasources(session):
  63. print(json.dumps(item, ensure_ascii=False))
  64. if __name__ == "__main__":
  65. main()