【要約】ElementTreeでDMARCレポートを集計したら、53%のデータが無言で消えていた [Zenn_Python] | Summary by TechDistill
> Source: Zenn_Python
Execute Primary Source
// Problem
開発者がDMARCレポートを集計する際、XMLの名前空間の有無によってデータが静かに消失する問題に直面した。集計スクリプトを実行してもエラーは発生せず、終了コードも0のまま、本来の47%のデータしか処理されない事態となった。具体的には以下の課題が挙げられる。
- ・XMLのルート要素に既定の名前空間(xmlns)があると、
findall('record')が空リストを返す。 - ・パース自体は成功するため、例外が発生せず、異常に気づく手がかりがない。
- ・集計結果の不整合により、SPFやDKIMの設定不備という誤ったセキュリティ判断を招く恐れがある。
// Approach
送信元によって名前空間の有無が異なるため、全要素から名前空間を剥がして統一的に扱う手法を採用した。標準ライブラリのみで完結させ、堅牢性を高めるために以下のステップで実装した。
- ・
strip_ns関数を実装し、全要素のタグから{namespace}部分を動的に削除する。 - ・
dkim要素などの欠落によるAttributeErrorを防ぐため、要素の存在確認を行う。 - ・
sampled_out(統計的サンプリング対象外)を、実際のDMARC失敗とは区別して集計する。 - ・
policy_evaluated(アライメント込みの判定)とauth_results(生の認証結果)を明確に区別して扱う。
// Result
名前空間の処理を修正したことで、欠落していた53.3%のデータを復元し、正確な集計が可能となった。これにより、誤ったセキュリティ判断を回避し、実態に即した運用ができるようになった。
- ・総メッセージ数が264通から565通へと正しくカウントされた。
- ・DMARC pass率が48.5%から75.9%へと修正され、正しい評価が可能になった。
- ・
policy_evaluatedを活用することで、アライメント不一致による失敗を正確に特定できるようになった。
Senior Engineer Insight
> XMLパースにおける「静かな失敗」は、大規模運用において致命的な誤判断を招く。
findallが空を返しても例外が出ない仕様を理解し、読み込んだレコード数を必ずログに出すべきだ。また、セキュリティ指標の集計では、サンプリングやアライメントの概念を混同しない実装が求められる。標準ライブラリで名前空間を剥がす手法は、依存関係を増やさず実用的な判断と言える。