test_unified_target_probe.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. import importlib.util
  2. import json
  3. from pathlib import Path
  4. import tempfile
  5. import unittest
  6. ROOT = Path(__file__).resolve().parents[1]
  7. spec = importlib.util.spec_from_file_location('target_probe', ROOT / 'scripts/probe-unified-target.py')
  8. probe = importlib.util.module_from_spec(spec)
  9. spec.loader.exec_module(probe)
  10. class Connection:
  11. def __init__(self, row):
  12. self.row = row
  13. self.statements = []
  14. self.closed = False
  15. self.rolled_back = False
  16. def execute(self, sql):
  17. self.statements.append(sql)
  18. return self
  19. def fetchone(self):
  20. return self.row
  21. def rollback(self):
  22. self.rolled_back = True
  23. def close(self):
  24. self.closed = True
  25. class ProbeTests(unittest.TestCase):
  26. def setUp(self):
  27. self.temp = tempfile.TemporaryDirectory(prefix='ksf-target-probe-')
  28. self.addCleanup(self.temp.cleanup)
  29. self.config = Path(self.temp.name) / 'config.json'
  30. self.config.write_text(json.dumps({'schema': 'ksf.unified-db.v1', 'appId': 'FKieRbIoGt_main',
  31. 'database': 'FKieRbIoGt_master', 'connection': {'service': 'ksfunified'}}))
  32. self.config.chmod(0o600)
  33. self.frozen_root = Path(self.temp.name) / 'frozen-r2'
  34. runtime = self.frozen_root / 'server/voc-library/unified_store.py'
  35. runtime.parent.mkdir(parents=True)
  36. runtime.write_bytes((ROOT / 'docs/unified-database-migration-20261109/release-r2/package/server/voc-library/unified_store.py').read_bytes())
  37. def test_mixed_report_is_exposed_without_changing_guards_or_config(self):
  38. before = self.config.read_bytes()
  39. connections, calls = [], []
  40. def connect(**kwargs):
  41. calls.append(kwargs)
  42. db = kwargs.get('dbname', 'FKieRbIoGt_master')
  43. connection = Connection((db, 'FKieRbIoGt_admin', 'FKieRbIoGt_admin', 'on', '17.9', 0))
  44. connections.append(connection)
  45. return connection
  46. value = probe.run(self.config, self.frozen_root, connect)
  47. self.assertFalse(value['targetIdentityVerified'])
  48. self.assertFalse(value['configMatchesPackage'])
  49. self.assertEqual(value['serviceIdentity']['database'], 'FKieRbIoGt_master')
  50. self.assertEqual(value['runtimeConnectionIdentity']['database'], 'FKieRbIoGtmaster')
  51. self.assertNotIn('dbname', calls[0])
  52. self.assertEqual(calls[1]['dbname'], 'FKieRbIoGtmaster')
  53. self.assertEqual(self.config.read_bytes(), before)
  54. for args, connection in zip(calls, connections):
  55. self.assertEqual(args['options'], '-c default_transaction_read_only=on')
  56. self.assertTrue(connection.closed and connection.rolled_back)
  57. self.assertEqual(len(connection.statements), 1)
  58. self.assertTrue(connection.statements[0].startswith('SELECT '))
  59. def test_corrected_runtime_matches_existing_service_identity(self):
  60. def connect(**kwargs):
  61. return Connection(('FKieRbIoGt_master', 'FKieRbIoGt_admin', 'FKieRbIoGt_admin', 'on', '17.9', 0))
  62. value = probe.run(self.config, ROOT, connect)
  63. self.assertTrue(value['targetIdentityVerified'])
  64. self.assertEqual(value['databaseWrites'], 0)
  65. def test_connection_error_does_not_expose_credentials(self):
  66. def fail(**kwargs):
  67. raise RuntimeError('postgresql://user:fixture-secret@host/database')
  68. value = probe.run(self.config, ROOT, fail)
  69. self.assertFalse(value['ok'])
  70. self.assertNotIn('fixture-secret', json.dumps(value))
  71. self.assertEqual(value['databaseWrites'], 0)
  72. def test_wrong_application_is_rejected_before_connection(self):
  73. value = json.loads(self.config.read_bytes())
  74. value['appId'] = 'other-app'
  75. self.config.write_text(json.dumps(value))
  76. def forbidden(**kwargs):
  77. self.fail('connection must not be attempted')
  78. with self.assertRaisesRegex(ValueError, 'CONFIG_APPLICATION_MISMATCH'):
  79. probe.run(self.config, ROOT, forbidden)
  80. if __name__ == '__main__':
  81. unittest.main()