見出し画像

COCOAの障害に学ぶ。ソフトウェアはリリースしたら終わりじゃない話

こんにちは、エンジニアのgamiです。

2021年2月3日に厚労省から発表された、新型コロナウイルス接触確認アプリCOCOA Android版の重大なバグが話題になっています。

濃厚接触があった場合でも、検知も通知もされない」というバグ自体の深刻さに加えて、バグが生じた9月末から4ヶ月間の間原因が特定されなかったという点に注目が集まっています。これほど社会的に重要なアプリで、アプリの機能が停止するに等しいバグが、長期間の間放置されるということは、ソフトウェア技術者の目から見ても異常に思えます。

大まかな問題点の整理は、YouTubeの動画でもまとめました。

この動画に関するTweetにも、比較的多くの反響がありました。

今回のnoteでは、動画で語り切れなかった本障害が発生した詳細な原因と、「ソフトウェアのリリース後にも気にしなければいけないこと」の具体的例について詳述したいと思います。


COCOAが直面したExposure Notification APIの更新スピード

そもそもCOCOAにとって重要な「濃厚接触を検知・通知する機能」の実現には、AndroidやiOSに組み込まれている「Exposure Notification API(EN API)」という仕組みが使われています。これはGoogleとAppleが新型コロナウイルス感染症の拡大を受けて共同で決めた仕様に従い、両OSにそれぞれ実装されているものです。

今回起きた障害も、直接的な原因はこのExposure Notification APIとやり取りする部分の実装にあったようです。

1. Exposure Notification APIの仕様は頻繁に変わっていた
2. 特にその過程の中でAndroid(Google)とiOS(Apple)のExposure Notification APIにとある実装上の差異が生じた
3. COCOAのとある設定値がAndroid版のExposure Notification APIでは想定されていない値になっており、意図しない値に上書きされていたこと
4. その結果、リスクスコアが常に濃厚接触として判定されないレベルの値になってしまっていた

COCOAというアプリ自体の機能はシンプルで機能レベルの仕様変更は比較的少なかったと思いますが、アプリが使っているAPIの仕様がガンガン変わるのでそれに追従する必要があり、それに対応し切れなかったという状況だったようです。

政府CIO補佐官の楠 正憲さんも、「Exposure Notification APIの更新が頻繁でトリッキーだったこと」が誤算だったとTweetしています。

バグをすぐ発見し直せる運用体制や仕組みが無かったことが問題

ソフトウェア開発に直接関わったことが無い人からすると、「バグが出た!問題だ!」となりがちです。しかし、「バグの無いソフトウェアは無い」と言われるように何かを作れば必ずバグは生まれます

もちろん、リリース後にバグが見つかるという自体を避けるために入念にテストしまくるということは可能です。しかし、考えうる全てのケースを想定してテストするのはコスト的に割に合わないこともあります。また、アプリケーションの外部にあるAPIの仕様変更によって、アプリケーション自体は何も変更されていないのにバグが生まれるということもあるわけです。

そうなると、「事前にバグをゼロにしよう」というのは不可能であり、普通は「リリース後に生じたバグはすぐ気付いて対処できるようにしよう」という方針が取られます。これは運用保守とかメンテナンスと言われる活動の一部で、Twitter上でも「メンテナンス軽視されがちだけど大事だよね」という話が盛り上がっていました。

今回の件も、ちゃんとログを取って調査できるようになっていれば「Android版だけ濃厚接触の検知数が明らかに少ない」とか「API側から出力される値がおかしい」といったことはすぐにわかったような気がします。この辺りの認識は関係者の中でもあったようですが、政府関連のプロジェクトというのもあって意思決定が遅くなりがちだったのかなという感じがします。

この前代未聞のバグを社会の学びに変えたい

一方で今回の障害は、次に挙げるような様々な事情がある中で発生したものです。それを平時かつ民間のソフトウェア開発と単純比較できるものではないと思います。

政府が開発したスマホアプリがここまで多くの人に使われた例はこれまで無く運用ノウハウが少ない
そもそもExposure Notification APIを使っているアプリが国に1つしかないので問題の切り分けが難しい
これまで行政改革の名の下に公務員を減らし続けてきた
さらに緊急事態の中であらゆるリソースが逼迫していた

このバグについて厚労省や開発会社を槍玉に上げて攻撃しても何も変わりません。そうではなく、再発を防止するための仕組みづくりや意識改革のきっかけとして利用すれば、同じ過ちを繰り返すリスクを下げることができるはずです。

同じ事態を繰り返さないためには、ソフトウェアのリリース後にどのようなリスクがあるのか、それにはどのように対処しなければいけないのか、という知識が広く浸透する必要があると思います。たとえば「APIの仕様変更に追従できずに重大なバグが混入する」というリスクが広く認知されていれば、「事前にAPIの挙動を確認するテストを入れておこう」とか「システム監視の仕組みを整備して、重要指標が急激に変化したらアラートが上がるようにしよう」みたいな事前の対策が取れていたかもしれません。

ソフトウェアのリリース後に潜むリスクを軽視するのは、政府に限らず、多くの民間企業にもある話です。(ピンとこない人は、あの悲しきセブンペイ事件を思い出してください。)しばしば、外注先にシステム開発や運用を丸投げしているようなケースでは、リスクを正しく捉えられずに対策が不十分になりがちです。

こうしたニュースが出る度に、「ソフトウェアはリリースして終わりじゃない」ということを広く伝え、社会の学びとして昇華したいという気持ちです。

ソフトウェア運用が直面する、不確実な要素たち

今回の障害については、平井デジタル改革担当大臣が「どうしてそういう状況になったのか、非常に私としても不思議です。そんなに難しいアプリではないし」と発言し、多くの開発者から冷ややかな目で見られていました。

ソフトウェアを使える状態にメンテナンスし続けることは、実はそれ自体かなり難易度の高いことです。もちろん難しさの感覚は人それぞれですが、この発言は技術者へのリスペクトを欠いた発言であると僕は感じました。ソフトウェアを「静的で変わらないもの」というイメージで捉えていると、感覚がズレてしまうのかもしれません。

ソフトウェア運用は、様々な不確実性に常に晒されています。パッと思いつくものを適当に10個くらい挙げてみます。これだけでも、「色々と考えることがあるなあ」ということが伝わると思います。

既存機能の仕様変更が必要になる
新機能追加が必要になる
既存のバグが見つかる
開発中に新たなバグを埋め込む
依存しているOSやツールの仕様変更に対応が必要になる
採用した技術に精通した技術者が少なく採用できない
技術者の学習スピードが思ったより伸びない
技術的負債が蓄積され開発スピードが落ちる
プロダクトマネジメントがうまく機能しない
決裁者にソフトウェア開発の理解が無く適切な合意形成ができない

COCOAの開発でも、限られたリソースの中で様々な不確実性に対応していたことが伺えます。

厚労省が公開している「アプリに関するこれまでの更新情報」を見ると、定期的にバグ修正や機能の改善・追加がされていたことがわかります。もちろん初期リリースで理想のアプリが出せればリリース後のこうした開発は要らなくなるはずですが、実際に使われてから明らかになる情報はとても多いので、いきなり完璧なアプリをリリースするというのは基本的には不可能です。

また今回のバグは、前述したようにExposure Notification APIの仕様変更を把握しきれなかったことが直接的な原因になったと見られています。現代のソフトウェアは単独で機能するということがほぼ無く、他のソフトウェアやサービスの力を借りて動くケースがほとんどです。特にスマートフォンアプリはAndroidやiOSなどのOSの機能に大きく依存しています。一般的なスマートフォンアプリ開発でも、AndroidやiOSの新しいバージョンがリリースされる度に「自分たちのアプリは新しいバージョンのOSで問題なく動くのか」を検証する必要があります。たとえば依存しているOSの機能が大きく変わっているのに何も対応しないと、OSをバージョンアップしたユーザーがアプリを全く使えなくなるということも普通にあるわけです。

他にも、「COCOAが使っているXamarinという開発プラットフォームがマイナーすぎて技術者を十分に確保できなかったのでは?」という意見も目にしました。Xamarinを採用したことがCOCOAの開発に与えた実際の影響については不明ですが、一般的に「どんな技術を採用するかによって、技術者の確保しやすさなどのリスクの大小が変わる」ということはあります。

仮に目に見える機能から「そんなに難しいアプリではない」と思えても、そのソフトウェア運用の裏には数々の不確実な要素が蠢いているわけです。現実は思ったよりも複雑で、それを無視して「〇〇という技術がクソ」とか「〇〇をすればOK」とか単純化しても何も解決しません。

不確実性に対処するための方法論

一方で、こうした不確実性に対してソフトウェア産業が何もしてこなかったかというと、決してそんなことはありません。テスト、システム監視、プロダクトマネジメント、チームビルディング、組織設計などなど、様々な領域でこうした不確実な要素に対処するための方法論が議論され、実装され、体系化されてきました。多くの開発プロジェクトが直面するようなメジャーな不確実性については、対処方法が確立されています

たとえば、『エンジニアリング組織論への招待』という本では、エンジニアリング自体を「効率よく不確実性を減らしていくために行うすべての活動」と定義し、個人のレベルから組織のレベルまで、様々なトピックが紹介されています。

あとはソフトウェアの開発や運用に関わる多くの人や組織がこうした知見を学び、実践していけばいいわけです。もちろん言うは易しですが、何が正解か全くわからない状況と比べれば、目指すべき方向がある程度明確になっているというのは幸せなことだと思います。

このnoteも、ソフトウェア産業が多くの技術者の血と汗と涙の上に積み上げてきた知見を社会に広めるための一助になれば嬉しいです。

余談: このバグの原因は2ヶ月前に特定されていた?

ちなみに、2020年11月末の時点で今回のバグの原因を突き止めていた人がいたというので、密かに話題になっています。

ここから先は完全に余談で、正式に報道や発表された内容ではないので、読みたい人だけ読んでください。

実はCOCOAは、そのソースコードがOSSとして公開されています。これは東京都の新型コロナ対策サイトのプロジェクトの進め方とは違って、かなり消極的な理由で公開されたものと見られています。

COCOAのベースとされているオープンソースプロジェクト「Covid19Radar」は、オープンソースライセンスであるMPLライセンスによって公開されているが、同ライセンスには改変内容の公開義務があり、COCOAがCovid19Radarをベースとしている場合は、これに基づいてCOCOA自身もソースコードを公開する必要があった。そのため、今回のソースコード公開はライセンス違反の解消が図られたとみられる。

その証拠に、cocoaのソースコードが公開されているGitHubリポジトリ上で立てられたissueやプルリクエスト(修正提案のこと)は開発者サイドからはほぼ無視されているように見えます。

一方、issue自体は誰でも追加できるようになっていて、たまに新しいissueが追加されています。今回話題になったのも、2020年11月25日に上げられたissueです。

このissueでは、まさに今回の障害の直接的な原因になったと見られるtransmission_risk_levelという設定値について、「現状は0が設定されているが、それだとAndroid版で接触が検知されないのでは?」という指摘がされています。

transmissionRiskScoreが1のときにriskScoreがminimumRiskScore以上になることはないので、transmission_risk_levelが0だと、現在のAndroid版では接触が検知されることはないと思われます。

この設定がバグの原因であるという正式な発表は現時点では出ていませんが、その後のissue上のやりとりを見ても、恐らくこの指摘は正しかったんじゃないかと思います。

改めてソースコードを公開し広くissueを募るというオープンソースソフトウェア開発の利点を強く感じましたし、開発者サイドがこれらのissue内容を受けて11月時点で調査していればここまで発見が遅れることは無かったのかもしれないと思うとやるせない気持ちになります。

こうした事例を見ると、公共性の高い重要なソフトウェアについては、すべてOSSとして開発し、広くオープンにissueやプルリクエストを募った方がいいのではないかという気がしてきます。もちろん固有の難しさはあると思いますが、東京都の新型コロナ対策サイトという強力な成功事例もあります。広く民間の開発者の力を借りることができれば、少なくとも品質保証の点ではかなり有利に開発を進められるんじゃないでしょうか?

ここから先は

0字
同僚と飲むビール1杯分の金額で、飲み会で愚痴るよりもきっと仕事が楽しくなる。そんなコラムを月に3〜4本お届けする予定です。

【初月無料】デジタル時代の歩き方について考えたことを発信します。ソフトウェアの時代とは何か。エンジニアの頭の中はどうなっているのか。NoC…

サポートをいただけると、喜びドリブンで発信量が増えます!初月無料のマガジン『仕事を楽しくするデジタルリテラシー読本』もおすすめです!