Initial server source import

This commit is contained in:
sashatrask
2026-09-30 20:30:56 +03:00
commit 170dd941b9
498 changed files with 261563 additions and 0 deletions
+605
View File
@@ -0,0 +1,605 @@
import sys
sys.dont_write_bytecode = True
if not sys.dont_write_bytecode:
raise RuntimeError('result ingester could not disable bytecode writes')
import argparse
import json
import logging
import os
import time
from lifecycle_authority import require_active_supervisor_child
from paths import apply_path_config
from process_identity import current_process_identity, exact_process_identity_state
from result_bundle import (
ResultBundleError,
ResultBundleReader,
bundle_partial_relative_path,
)
from runtime_security import (
PrivatePathState,
durable_publish,
durable_unlink,
ensure_private_directory,
private_file_ready,
inspect_private_relative_path,
require_private_directory,
sha256_file,
)
from scanner_db import (
DockerCoverageDispositionConflictError,
DockerFindingAttributionLimitError,
ScanEventConflictError,
ScannerDB,
)
logger = logging.getLogger(__name__)
class ResultIngester:
def __init__(
self, db, bundle_root, supervisor_instance_id, lease_seconds=300, fault=None,
quarantine_max_items=10000, quarantine_max_bytes=1024 * 1024 * 1024,
metadata_retention_days=30, metadata_retirement_batch=100,
recover_expired_ready=False,
):
self.db = db
self.bundle_root = require_private_directory(bundle_root, create=False)
self.supervisor_instance_id = str(supervisor_instance_id)
self.lease_seconds = max(30, int(lease_seconds))
self.fault = fault
self.lease = None
self.recovery_after_id = 0
self.quarantine_max_items = max(0, int(quarantine_max_items))
self.quarantine_max_bytes = max(0, int(quarantine_max_bytes))
self.metadata_retention_seconds = max(1, int(metadata_retention_days)) * 86400
self.metadata_retirement_batch = min(500, max(1, int(metadata_retirement_batch)))
self.next_metadata_retirement = 0.0
self.recover_expired_ready = recover_expired_ready is True
def _inject(self, stage, value=None):
if self.fault is not None:
self.fault(stage, value)
def start(self):
self.db.require_runtime_safety_schema()
self.db.require_final_cutover()
identity = current_process_identity()
self.lease = self.db.acquire_pipeline_lease(
'result_ingester', self.supervisor_instance_id, identity,
lease_seconds=self.lease_seconds, initial_state='recovering',
)
if not self.lease:
raise RuntimeError('another result ingester owns the singleton advisory lock')
self.reconcile_terminal_artifacts()
self.retire_terminal_metadata()
self.recover()
if not self.heartbeat('ready'):
raise RuntimeError('result ingester ready lease publication failed')
return self
def heartbeat(self, state='ready', error=''):
return self.db.heartbeat_pipeline_lease(
'result_ingester', self.lease['generation'], self.lease['lease_token'],
lease_seconds=self.lease_seconds, state=state, error=error,
)
def stop(self, error=''):
if self.lease:
released = self.db.release_pipeline_lease(
'result_ingester', self.lease['generation'], self.lease['lease_token'],
state='failed' if error else 'released', error=error,
)
self.lease = None
return released
return True
def _path(self, relative):
normalized = str(relative or '').replace('/', os.sep)
path = os.path.abspath(os.path.join(self.bundle_root, normalized))
if os.path.commonpath((self.bundle_root, path)) != self.bundle_root or path == self.bundle_root:
raise ResultBundleError('bundle database path escapes its configured root')
return path
def _quarantine_path(self, reservation):
bundle_id = str(reservation['bundle_id'])
return os.path.join(
self.bundle_root, 'quarantine', bundle_id[:2], f'{bundle_id}.trb',
)
def _quarantine_relative_path(self, reservation):
bundle_id = str(reservation['bundle_id'])
return f'quarantine/{bundle_id[:2]}/{bundle_id}.trb'
def _ensure_quarantine_shard(self, reservation):
bundle_id = str(reservation['bundle_id'])
return ensure_private_directory(
os.path.join(self.bundle_root, 'quarantine', bundle_id[:2]),
reject_reparse=True,
)
def _inspect(self, relative_path):
return inspect_private_relative_path(self.bundle_root, relative_path)
def _defer_reservation_cleanup(self, reservation, error):
try:
self.db.defer_result_reservation_cleanup(reservation['id'], str(error))
except Exception:
logger.warning(
'reservation cleanup backoff could not be recorded: %s', reservation['id']
)
def reconcile_terminal_artifacts(self, max_pages=100):
if not hasattr(self.db, 'bundle_terminal_temp_artifacts'):
return
for _ in range(max(1, int(max_pages))):
rows = self.db.bundle_terminal_temp_artifacts(100)
if not rows:
return
progressed = False
for row in rows:
try:
inspection = self._inspect(row['relative_path'])
if inspection.state == PrivatePathState.UNKNOWN:
self.db.defer_pipeline_artifact_cleanup(
row['id'], inspection.detail or 'artifact storage state is unknown',
)
continue
if inspection.state == PrivatePathState.PRESENT:
if not private_file_ready(inspection.path):
self.db.defer_pipeline_artifact_cleanup(
row['id'], 'artifact is not an exact private file',
)
continue
durable_unlink(inspection.path)
inspection = self._inspect(row['relative_path'])
if inspection.state == PrivatePathState.ABSENT:
self.db.mark_pipeline_artifact_deleted(row['id'])
progressed = True
else:
self.db.defer_pipeline_artifact_cleanup(
row['id'], 'artifact unlink was not confirmed',
)
except OSError as exc:
try:
self.db.defer_pipeline_artifact_cleanup(row['id'], str(exc))
except Exception:
logger.warning(
'artifact cleanup backoff could not be recorded: %s', row['id']
)
continue
if not progressed:
return
if len(rows) < 100:
return
return
def retire_terminal_metadata(self):
if time.monotonic() < self.next_metadata_retirement:
return
self.next_metadata_retirement = time.monotonic() + 60
try:
self.db.retire_admission_intents(
self.metadata_retention_seconds, self.metadata_retirement_batch,
)
self.db.retire_deleted_pipeline_artifacts(
self.metadata_retention_seconds, self.metadata_retirement_batch,
)
except Exception as exc:
logger.warning('bounded terminal metadata retirement deferred: %s', type(exc).__name__)
def quarantine(self, reservation, ready_path, reason_code, detail):
ready_relative = str(reservation['ready_relative_path']).replace('\\', '/')
quarantine_relative = self._quarantine_relative_path(reservation)
self._ensure_quarantine_shard(reservation)
ready = self._inspect(ready_relative)
quarantine = self._inspect(quarantine_relative)
if ready.state == PrivatePathState.UNKNOWN or quarantine.state == PrivatePathState.UNKNOWN:
raise ResultBundleError('bundle quarantine path state is unknown')
if ready.state == PrivatePathState.PRESENT and quarantine.state == PrivatePathState.PRESENT:
raise ResultBundleError('both ready and quarantine paths exist for one reservation')
if ready.state == PrivatePathState.ABSENT and quarantine.state == PrivatePathState.ABSENT:
raise ResultBundleError('bundle disappeared before quarantine')
quarantine_path = quarantine.path
ensure_private_directory(os.path.dirname(quarantine_path), reject_reparse=True)
source_path = ready.path if ready.state == PrivatePathState.PRESENT else quarantine.path
if not private_file_ready(source_path):
raise ResultBundleError('bundle quarantine source is not an exact private file')
byte_count = os.path.getsize(source_path)
payload_hash = sha256_file(source_path) if byte_count else ''
relative = quarantine_relative
quarantine_id = self.db.quarantine_result_bundle(
reservation['id'], reason_code, detail, relative,
payload_sha256=payload_hash, byte_count=byte_count,
quarantine_max_items=self.quarantine_max_items,
quarantine_max_bytes=self.quarantine_max_bytes,
physical_confirmed=ready.state != PrivatePathState.PRESENT,
)
if ready.state == PrivatePathState.PRESENT:
durable_publish(ready.path, quarantine_path)
confirmed = self._inspect(quarantine_relative)
if confirmed.state != PrivatePathState.PRESENT:
raise ResultBundleError('bundle quarantine publication was not confirmed')
quarantine_id = self.db.quarantine_result_bundle(
reservation['id'], reason_code, detail, relative,
payload_sha256=payload_hash, byte_count=byte_count,
quarantine_max_items=self.quarantine_max_items,
quarantine_max_bytes=self.quarantine_max_bytes,
physical_confirmed=True,
)
return quarantine_id
def recover(self, page_size=100, max_pages=100):
pages = 0
while pages < max(1, int(max_pages)):
rows = self.db.active_result_reservations(self.recovery_after_id, page_size)
if not rows:
self.recovery_after_id = 0
return pages
pages += 1
for reservation in rows:
self.recovery_after_id = int(reservation['id'])
if (
reservation['state'] == 'scanning'
and str(reservation.get('assignment_kind') or 'local') == 'remote'
):
continue
ready_relative = str(reservation['ready_relative_path']).replace('\\', '/')
ready = self._inspect(ready_relative)
identity_state = None
if reservation['state'] == 'scanning':
identity_state = exact_process_identity_state(
reservation['producer_pid'], reservation['producer_creation_time'],
reservation['producer_executable'],
)
if (
ready.state == PrivatePathState.UNKNOWN
and identity_state in ('dead', 'reused')
):
try:
ensure_private_directory(
os.path.join(
self.bundle_root, 'ready',
str(reservation['bundle_id'])[:2],
),
reject_reparse=True,
)
ensure_private_directory(
os.path.join(
self.bundle_root, 'tmp',
str(reservation['bundle_id'])[:2],
),
reject_reparse=True,
)
ready = self._inspect(ready_relative)
except OSError as exc:
self._defer_reservation_cleanup(reservation, exc)
continue
quarantine_relative = self._quarantine_relative_path(reservation)
try:
self._ensure_quarantine_shard(reservation)
except OSError as exc:
self._defer_reservation_cleanup(reservation, exc)
continue
quarantine = self._inspect(quarantine_relative)
if quarantine.state == PrivatePathState.PRESENT:
try:
self.db.quarantine_result_bundle(
reservation['id'],
reservation.get('last_error_code') or 'recovered_quarantine',
reservation.get('last_error_detail') or 'recovered deterministic quarantine file',
quarantine_relative,
payload_sha256=sha256_file(quarantine.path),
byte_count=os.path.getsize(quarantine.path),
quarantine_max_items=self.quarantine_max_items,
quarantine_max_bytes=self.quarantine_max_bytes,
physical_confirmed=True,
)
except OSError as exc:
self._defer_reservation_cleanup(reservation, exc)
continue
if quarantine.state == PrivatePathState.UNKNOWN:
self._defer_reservation_cleanup(
reservation, quarantine.detail or 'quarantine state unknown',
)
continue
if ready.state == PrivatePathState.UNKNOWN:
self._defer_reservation_cleanup(
reservation, ready.detail or 'ready state unknown',
)
continue
prepared_quarantine = self.db.pending_result_bundle_quarantine(
reservation['id']
)
if prepared_quarantine and ready.state == PrivatePathState.PRESENT:
try:
self.quarantine(
reservation, ready.path,
prepared_quarantine['reason_code'],
prepared_quarantine.get('reason_detail') or 'recovered prepared quarantine',
)
except OSError as exc:
self._defer_reservation_cleanup(reservation, exc)
continue
if reservation['state'] == 'scanning':
if ready.state == PrivatePathState.PRESENT:
try:
metadata = ResultBundleReader(ready.path).validate()
recovered = metadata.as_dict()
recovered['relative_path'] = str(
reservation['ready_relative_path']
).replace('\\', '/')
marked_ready = self.db.mark_result_bundle_ready(
reservation['id'], recovered,
)
if (
not marked_ready
and self.recover_expired_ready
and identity_state in ('dead', 'reused')
):
self.db.recover_expired_result_bundle_ready(
reservation['id'], recovered,
)
except OSError as exc:
self._defer_reservation_cleanup(reservation, exc)
except (ValueError, ResultBundleError) as exc:
try:
self.quarantine(
reservation, ready.path, 'bundle_validation_failed', str(exc),
)
except OSError as cleanup_exc:
self._defer_reservation_cleanup(reservation, cleanup_exc)
continue
if identity_state in ('dead', 'reused'):
try:
ensure_private_directory(
os.path.join(self.bundle_root, 'ready', str(reservation['bundle_id'])[:2]),
reject_reparse=True,
)
ensure_private_directory(
os.path.join(self.bundle_root, 'tmp', str(reservation['bundle_id'])[:2]),
reject_reparse=True,
)
except OSError as exc:
self._defer_reservation_cleanup(reservation, exc)
continue
ready = self._inspect(ready_relative)
if ready.state != PrivatePathState.ABSENT:
continue
if identity_state in ('dead', 'reused'):
partial_relative = bundle_partial_relative_path(
reservation['bundle_id'], reservation['reservation_token'],
).replace(os.sep, '/')
partial = self._inspect(partial_relative)
if partial.state == PrivatePathState.UNKNOWN:
self._defer_reservation_cleanup(
reservation, partial.detail or 'partial state unknown',
)
continue
if partial.state == PrivatePathState.PRESENT:
if not private_file_ready(partial.path):
continue
try:
durable_unlink(partial.path)
except OSError as exc:
self._defer_reservation_cleanup(reservation, exc)
continue
partial = self._inspect(partial_relative)
if partial.state != PrivatePathState.ABSENT:
self._defer_reservation_cleanup(
reservation, 'partial unlink was not confirmed',
)
continue
self.db.refund_uncommitted_reservation(
reservation['id'],
{
'pid': reservation['producer_pid'],
'creation_time': reservation['producer_creation_time'],
'executable': reservation['producer_executable'],
},
f'producer identity is {identity_state} and exact ready path is absent',
partial_absence_confirmed=True,
)
elif reservation['state'] in ('ready', 'ingesting'):
if ready.state == PrivatePathState.ABSENT:
self.db.quarantine_result_bundle(
reservation['id'], 'ready_bundle_missing',
'database ready row has a definitively absent exact ready path',
'', byte_count=0,
quarantine_max_items=self.quarantine_max_items,
quarantine_max_bytes=self.quarantine_max_bytes,
physical_confirmed=True,
)
elif reservation['state'] == 'db_committed':
bundle = self.db.result_bundle_for_reservation(reservation['id'])
if not bundle:
continue
if ready.state == PrivatePathState.PRESENT:
if not private_file_ready(ready.path):
continue
try:
durable_unlink(ready.path)
except OSError as exc:
self._defer_reservation_cleanup(reservation, exc)
continue
ready = self._inspect(ready_relative)
if ready.state == PrivatePathState.ABSENT:
event = self.db.confirm_scan_event(
reservation['scan_event_id'], bundle['scan_event_hash'],
)
if event:
self.db.acknowledge_removed_bundle(
reservation['id'], reservation['scan_event_id'],
bundle['scan_event_hash'],
)
return pages
def process_one(self):
claimed = self.db.claim_ready_result_bundle(
self.lease['generation'], self.lease['lease_token'], self.lease_seconds,
)
if not claimed:
return False
reservation = claimed['reservation']
bundle = claimed['bundle']
ready_relative = str(bundle['relative_path']).replace('\\', '/')
ready = self._inspect(ready_relative)
try:
if bundle['state'] == 'db_committed':
event = self.db.confirm_scan_event(bundle['scan_event_id'], bundle['scan_event_hash'])
if not event:
raise ResultBundleError('db_committed bundle has no exact authoritative event')
else:
if ready.state == PrivatePathState.UNKNOWN:
return False
if ready.state == PrivatePathState.ABSENT:
self.db.quarantine_result_bundle(
reservation['id'], 'ready_bundle_missing',
'claimed ready bundle is definitively absent', '',
quarantine_max_items=self.quarantine_max_items,
quarantine_max_bytes=self.quarantine_max_bytes,
physical_confirmed=True,
)
return True
self._inject('before_validation', reservation)
reader = ResultBundleReader(ready.path)
validated = reader.validate()
self._inject('after_validation', validated)
if (
validated.bundle_id != str(bundle['bundle_id'])
or validated.scan_event_id != str(bundle['scan_event_id'])
or validated.scan_event_hash != str(bundle['scan_event_hash'])
or validated.actual_bytes != int(bundle['actual_bytes'])
):
raise ResultBundleError('validated bundle totals conflict with its claimed database row')
self._inject('before_db_commit', reservation)
self.db.ingest_result_bundle(reader, reservation, bundle)
self._inject('after_db_commit', reservation)
event = self.db.confirm_scan_event(bundle['scan_event_id'], bundle['scan_event_hash'])
self._inject('after_confirmation', event)
if not event:
raise ResultBundleError('database commit was not confirmed by exact event ID and hash')
ready = self._inspect(ready_relative)
if ready.state == PrivatePathState.UNKNOWN:
return False
if ready.state == PrivatePathState.PRESENT:
self._inject('before_unlink', reservation)
durable_unlink(ready.path)
self._inject('after_unlink', reservation)
ready = self._inspect(ready_relative)
if ready.state != PrivatePathState.ABSENT:
return False
self._inject('before_capacity_release', reservation)
if not self.db.acknowledge_removed_bundle(
reservation['id'], bundle['scan_event_id'], bundle['scan_event_hash'],
):
raise RuntimeError('bundle capacity acknowledgement was not fenced')
self._inject('after_capacity_release', reservation)
return True
except DockerCoverageDispositionConflictError as exc:
ready = self._inspect(ready_relative)
if ready.state == PrivatePathState.PRESENT:
try:
self.quarantine(
reservation, ready.path,
'docker_coverage_disposition_conflict', str(exc),
)
except OSError as cleanup_exc:
self._defer_reservation_cleanup(reservation, cleanup_exc)
return False
return True
except DockerFindingAttributionLimitError as exc:
ready = self._inspect(ready_relative)
if ready.state == PrivatePathState.PRESENT:
try:
self.quarantine(
reservation, ready.path,
'docker_attribution_limit_exceeded', str(exc),
)
except OSError as cleanup_exc:
self._defer_reservation_cleanup(reservation, cleanup_exc)
return False
return True
except ScanEventConflictError as exc:
ready = self._inspect(ready_relative)
if ready.state == PrivatePathState.PRESENT:
try:
self.quarantine(reservation, ready.path, 'scan_event_hash_conflict', str(exc))
except OSError as cleanup_exc:
self._defer_reservation_cleanup(reservation, cleanup_exc)
return False
return True
except (ResultBundleError, ValueError) as exc:
ready = self._inspect(ready_relative)
if ready.state == PrivatePathState.PRESENT:
try:
self.quarantine(reservation, ready.path, 'bundle_validation_failed', str(exc))
except OSError as cleanup_exc:
self._defer_reservation_cleanup(reservation, cleanup_exc)
return False
return True
raise
except OSError as exc:
self._defer_reservation_cleanup(reservation, exc)
return False
def parse_args():
parser = argparse.ArgumentParser(description='Singleton durable result bundle ingester')
parser.add_argument('--config', required=True)
return parser.parse_args()
def main():
metadata = require_active_supervisor_child(child_kind='result-ingester', require_dsn=True)
args = parse_args()
import yaml
with open(args.config, 'r', encoding='utf-8') as handle:
config = apply_path_config(yaml.safe_load(handle) or {}, args.config)
global_config = config.get('global') or {}
db = ScannerDB(db_url=global_config['database_url'], initialize=False)
if not db.enabled:
raise SystemExit('result ingester PostgreSQL connection is unavailable')
db.set_application_name('truf-result-ingester')
worker = ResultIngester(
db, global_config['result_bundle_dir'], metadata['instance_id'],
lease_seconds=int(((config.get('supervisor') or {}).get('result_ingester') or {}).get('lease_seconds', 300)),
quarantine_max_items=int(global_config.get('pipeline_quarantine_max_items', 10000)),
quarantine_max_bytes=int(global_config.get('pipeline_quarantine_max_bytes', 1024 * 1024 * 1024)),
metadata_retention_days=int(global_config.get('pipeline_metadata_retention_days', 30)),
metadata_retirement_batch=int(global_config.get('pipeline_metadata_retirement_batch', 100)),
)
error = ''
try:
worker.start()
idle = max(0.05, float(((config.get('supervisor') or {}).get('result_ingester') or {}).get('poll_sec', 0.2)))
next_heartbeat = time.monotonic() + worker.lease_seconds / 3
while True:
worker.retire_terminal_metadata()
worker.reconcile_terminal_artifacts(max_pages=1)
worker.recover(max_pages=1)
processed = worker.process_one()
if time.monotonic() >= next_heartbeat:
if not worker.heartbeat('ready'):
raise RuntimeError('result ingester heartbeat fence was lost')
next_heartbeat = time.monotonic() + worker.lease_seconds / 3
if not processed:
time.sleep(idle)
except KeyboardInterrupt:
pass
except BaseException as exc:
error = f'{type(exc).__name__}: {exc}'
raise
finally:
try:
worker.stop(error)
finally:
db.close()
if __name__ == '__main__':
main()