"""Offline credential checks inside the configured container; never sends a push.""" import argparse import os from pathlib import Path import stat from firebase_admin import credentials from notifications import enabled class PreflightError(Exception): """Only fixed diagnostic codes, never credential/SDK exception contents.""" def check(expected_service_account): if not enabled(): raise PreflightError('push_disabled') project = os.environ.get('FIREBASE_PROJECT_ID', '') if not project: raise PreflightError('project_missing') path = Path(os.environ.get('GOOGLE_APPLICATION_CREDENTIALS', '')) if str(path) != '/run/secrets/firebase-service-account.json': raise PreflightError('container_path_mismatch') try: info = path.stat() if not stat.S_ISREG(info.st_mode): raise PreflightError('credential_not_a_file') if info.st_mode & 0o077: raise PreflightError('credential_permissions_too_broad') if not os.statvfs(path).f_flag & os.ST_RDONLY: raise PreflightError('credential_mount_not_read_only') credential = credentials.Certificate(str(path)) except PreflightError: raise except Exception: raise PreflightError('credential_missing_unreadable_or_invalid') from None if credential.project_id != project: raise PreflightError('credential_project_mismatch') if credential.service_account_email != expected_service_account: raise PreflightError('credential_service_account_mismatch') def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('--expected-service-account', required=True, help='Expected service-account email, not a token or key') args = parser.parse_args() try: check(args.expected_service_account) except PreflightError as error: print('FAIL: ' + str(error)) return 1 print('PASS: push enabled; read-only credential; project and service account match. ' 'No network request; IAM and delivery still require a smoke test.') return 0 if __name__ == '__main__': raise SystemExit(main())