The Hierarchy of Controls (or how to stop devs from dropping prod)

Hillel Wayne

ハザード対策の階層(あるいは開発者が本番環境を落とさないようにする方法)

原文は Hillel Wayne により に公開されました。 このブログを購読する

先日、機械系エンジニアの知人から職場の安全における重要な考え方であるHierarchy of Controls(HoC、日本語でいう「ハザード対策の階層」)について教えてもらいました。1

(出典)

人をハザードから守るために、システムの設計者はできる限り最も効果的な対策を用いるべきとされています。つまり、代替より除去、工学的対策より代替、といった具合に、より効果の高いものが優先されるということです。

このハザード対策の階層は、ソフトウェアエンジニアリングにも応用できるでしょうか。ソフトウェアの環境は物理的な環境とは異なりますが、抽出できるアイデアはあるかもしれません。試しに、駆け出しの開発者だった頃に私が引き起こした本番障害を例に、HoCを当てはめて考えてみましょう。

問題

10年ほど前、本番環境の不具合をデバッグしようとしていました。SSHでつないだ本番用のシェルと、ローカルの開発用シェルを並べて開いていたのですが、タブを間違えて、誤った方のシェルでクエリを実行してしまったのです。

こうして私は、新たな教訓を得ることになりました。本番データベースをバックアップから復元する方法、という教訓です。

プロセス安全の分野では、ハザードとは傷害を可能にするものすべてを指します。はしごは墜落を、油圧プレスは指の挟み込みを可能にします。私のケースでいえば、ハザードは権限が無制限に与えられた本番シェルであり、それが本番データの消失を可能にしていたわけです。具体的な傷害としては、(私がやったように)データベース自体を直接落とすことや、データベースに対してDELETEクエリを実行してしまうことが挙げられます。以降では、この2つの傷害を例に、さまざまなハザード対策について考えます。

前提として、断っておきたいこと

HoCは本来、人を機械から守るために作られたもので、機械を人から守るためのものではありません!概念の多くはうまく当てはまると思いましたが、PPE(個人用保護具)のあたりでは少し無理が出てきます。

また、ある対策がどのカテゴリに属するかについても、議論の余地は大いにあります。本稿を書くにあたっても、カテゴリ間の質的な違いを自分なりに整理しようとしていますが、これはあくまで素人なりの解釈であることをご承知おきください。

最後に、HoCが関心を寄せているのは傷害の「予防」であり、傷害からの「回復」ではないという点です。「定期的にデータベースのバックアップを取る」「障害後にポストモーテムを行う」といったソフトウェアのベストプラクティスは、この階層には当てはまりません。

対策の各段階

以下の引用はすべて、OSHAのHoCワークシートからの引用です。

除去

除去とは、ハザードがそもそも存在しない状態にすることです。

除去は、事故を防ぐ最も直接的な方法です。ハザード自体をなくしてしまうのです。OSHAの資料ではどれも同じ例が使われています。墜落事故を減らしたいなら、高所での作業自体をやめさせればいい、というわけです。私たちのケースに当てはめるなら、本番環境そのものをなくすか、データベース自体をなくすということになります。

どちらも現実的とは言えません。多くのHoCの資料がすぐに指摘しているように、適切な除去は往々にして不可能なのです。危険な物質を扱うのは、それがプロセスに不可欠だからです。「除去」という考え方が最も役立つのは、「その危険なものは本当に必要なのか?」と問い直すチェックとしてでしょう。不可欠なハザードは除去できませんが、そうでないものは除去できます。2020年にサポートが終了するまで、Adobe Flashはセキュリティ上の脆弱性の最大の温床の一つでした。身を守る最も簡単な方法は何だったか?Flashをアンインストールすることでした。

代替

代替とは、ハザードを低減するために物質プロセスを置き換えることを意味します。

除去とは異なり、代替はハザード自体は残しつつ、その危険性を下げます。ハザードが毒性の強い農薬なら、より毒性の低い農薬に置き換える。うるさい機械なら、より静かな機械に置き換える。ハザードがメモリ安全性のない言語なら、Rustを使う、といった具合です。

今回の問題で考えられる代替としては、2つほど思いつきます。一つは、本番シェルをより権限の弱いシェルに置き換えることです。例えば、ある「本番」サーバがデータベースの読み取り専用レプリカにしかアクセスできないようにすれば、DELETEクエリは何の効果も持たず、仮にデータベースを落としたとしてもデータは失われません。もう一つは、イベントソーシングのようなイミュータブル(不変)なレコードシステムを使うことです。そうすれば「データを削除する」という操作は「削除レコードをデータベースに追加する」という形になります。うっかり削除してしまっても、その上に「削除取消し」レコードを追加すれば簡単に元に戻せます。

工学的対策

工学的対策とは、ハザードが作業者に接触するのを防ぐことでばく露を低減するものです。ただし、作業者が仕事を続けられることは妨げません。

工学的対策は、ハザード自体の危険性はそのままに、追加の物理的な設計によって事故のリスクや重大性を緩和します。方法はいくらでもあります。作業者がハザードにさらされる必要性自体を減らす、ハザードが事故を引き起こす可能性を下げる、事故が傷害につながる可能性を下げる、といった具合です。

SawStop™ (出典)

除去や代替に比べ、工学的対策では創意工夫の余地がずっと大きくなります。考えられる工学的対策をいくつか挙げてみます。

  • 監視や可観測性が十分に整っていれば、そもそも本番環境にログインする必要がなくなるかもしれません。
  • より適切な権限ポリシーがあれば、そもそもデータベースを削除できないようにしたり、その操作には特別な開発者キーが必要になるようにしたりできます。
  • あるいは、ジュニアエンジニアはそもそも本番環境へのアクセス権を持たないようにするという手もあります。何かデバッグしたいことがあれば、より経験のある人に頼まなければなりません。
  • 自動ログアウトがあれば、本番用のターミナルを放置したまま、うっかりAlt+Tabで切り替えてしまう、といった事態を防げます。

工学的対策の中にも、効果が高いものと低いものがあります。悪名高い「弱い」対策が、確認ダイアログです。

$ ./drop_db.sh

This will drop database `production`.
To confirm, type y: [y/N]

この問題は、ローカル環境でこの操作を何度も実行していると、yを押すことが指に染みついてしまい、本番でも同じように押してしまって悲惨なことになる、という点です。

悪名高い「強い」対策が、「フルネーム」確認ボックスです。2

$ ./drop_db.sh

This will drop database `production`.
To confirm, type `production`:

指が覚えていたとしても、それはlocalと入力する癖であって、本番での実行はブロックされます。実際の例は、GitHubでリポジトリを削除しようとすると見ることができます。

OSHAの例の中には、工学的対策に見えるものが代替に思えたり、その逆だったりするものもあります。私なりの区別のヒューリスティックは、工学的対策は失敗しうるが、代替は失敗しないというものです。もし権限設定が間違っていて、実際にはデータベースの削除を防げなかったらどうでしょう?一方で、環境が読み取り専用レプリカにしか触れられないのであれば、何をしても書き込み用レプリカを破壊することはできません。たぶん。

もっとも、これは完璧なヒューリスティックではありません!CをRustに置き換えるのは代替とされますが、Rustの保証の一部はunsafeで回避できてしまいます。

管理的対策

管理的対策とは、作業者に適切な手順、トレーニング、警告を提供することで、作業のやり方を変えたり、作業者により多くの情報を与えたりするものです。

工学的対策がテクノロジーを変えるのに対し、管理的対策は人を変えます。テクノロジーとの関わり方を変えるような対策は、どちらのカテゴリにも入りうるため、私は「フルネーム」確認ボックスが管理的対策なのか工学的対策なのかについて長い議論をしました。どちらとも合理的に主張できます。

考えられる管理的対策をいくつか挙げます。

  • ジュニアは本番に接続してはならないという社内ポリシー
  • データベースをいかに簡単に落とせるかについての研修ビデオを見せる
  • 一度に開くターミナルは一つだけにする
  • 本番に接続する際は、必ず他の開発者とペアでなければならないとする
  • 労働時間や無理な追い込みを減らし、エンジニアの睡眠不足を解消する
  • 運用上の問題について定期的に机上演習を行う

OSHAはさらに、「自動警告」を管理的対策の一種に分類しています。例えば「本番環境にログインするとSlackにメッセージが投稿される」といったものです。

階層の中では、管理的対策は工学的対策よりも下位に位置づけられます。理由はいくつかあります。一つは、工学的対策はシステムに組み込まれているのに対し、管理的対策は社会的なものだということです。誰もがそれに従うためのトレーニングを受ける必要があります。二つ目は、私が見てきたHoCの例ではどれも、工学的対策は破るのに労力がかかるのに対し、管理的対策は守るのに労力がかかるという点です。急いでいたり、忘れていたり、注意が散漫だったりすると、守られない可能性があるのです。

一部の管理的対策は、工学的対策へと昇華させることができます。ジュニアエンジニアは本番にSSHしてはならないという社内ポリシーは管理的対策であり、誰もがルールを守ることに依存しています。一方で、ジュニアが必要なSSHキーを持っていないというセットアップは、工学的対策です。

個人用保護具

個人用保護具(PPE)には、作業者を保護するための衣服や器具が含まれます。

これは最も下位の対策です。人に装備を提供してハザードから保護するものです。PPEは傷害のリスクを減らすことも(反射ベストを着ていればフォークリフトに轢かれる可能性は低くなります)、重大性を減らすこともできます(ヘルメットは物が落ちてくるのを防ぎはしませんが、衝撃を和らげます)。

PPEは、ソフトウェアにおいて最も当てはまりにくい対策だと思います。まず第一に、HoCは人間を守るためのものなのに、ソフトウェアではシステムを守りたいわけです。では、ソフトウェアにおけるPPEとは、システムへの損害を防ぐために人が身につけるものなのか、それとも人からの損害を防ぐためにシステムが身につけるものなのか?「人用のPPE」の例としては、本番用のターミナルの背景を赤に、開発用のターミナルを青にする、といったものが考えられます。「システム用のPPE」の例として私が思いつくものは、どれも工学的対策と見なせるものばかりです。

第二に、PPEが工学的対策ではないのは、工学的対策がハザード自体を修正するのに対し、PPEは人とハザードの間に立つ第三の存在だからです。しかし、人とソフトウェアの間にあるものは、それ自体がまたソフトウェアなのです!「curlの代わりにPostmanを使う」といったことさえ、「真の」PPEというよりは工学的/管理的対策の混合のようなものです。

PPEがよりしっくりくる場面を2つ思いつきます。一つはセキュリティの分野で、安全なブラウザや2要素認証、パスワードマネージャーなどはすべてPPEの一種です。もう一つは、手根管症候群や腰痛、眼精疲労といった、ソフトウェア開発者にありがちな身体的な不調を減らすためのPPEです。これらが「しっくりくる」のは、人が傷害を受けるという、まさにHoCが本来想定していた状況だからです。

PPEが管理的対策より下位に置かれるのは、従業員がPPEを効果的に使うために規律と訓練を必要とするからです。現実世界では、PPEはかさばって不快なことが多く、90%の時間は実際には身を守っていません(危険にさらされていないためです)。ある論文によれば、調査対象となった建設現場の事故の65%で、負傷した作業者はPPEを着用していなかったとのことです。PPEの効果を最大化するには、人を訓練し、着用を徹底させる必要があり、それはすなわち、すでに管理的対策が整っていることが前提になるということです。

HoCに関する雑多なメモ

対策は組み合わせて使うもの

上位の対策ほど危険の除去に効果的ですが、実装は困難です。下位の対策は効果は低いものの、より汎用的で実装コストも安く済みます。

ソフトウェアは本質的に工学的対策が得意

まだこの考えを正確に言語化できているわけではないのですが、現実世界では、人は「自然なインターフェース」、つまり基本的に空間内に置かれた物体としてハザードと対峙します。油圧プレスを扱うなら、デフォルトで手を差し込めてしまう。傷害を防ぐためには、システムに追加の物理的な存在を加えたり、物理的な存在の正しい使い方を人に訓練したりする必要があるのです。

ソフトウェアでは、すべてのインターフェースは人工的に構築されたものです。ハザードは、私たちが害をなす能力を付け加えることによって生じます。だからこそ、傷害を起こす能力を減らすような別の形でインターフェースを構築したり、管理的対策を制約として強制するような形で構築したりする方が、比較的容易なのです。

これは以前の職場で実際にあったことです。利用パターン上、新バージョンのデプロイはピーク時間外に行うのが最も安全でした。「ピーク時間外にのみデプロイする」というのは管理的対策です。そこで私たちは、デプロイスクリプトに1行追加して、実行時刻をチェックし、ピーク時間帯であればエラーを出すようにしました。これは管理的対策を工学的対策に変えた例です。3

また、現実世界の工学的対策は高価であり、それが管理的対策やPPEが選ばれる大きな理由でもあります。しかしソフトウェアは物理的なシステムよりもはるかに迅速かつ安価に変更できます。そのため、工学的対策がより効果的になるのです。

(代替についても、同様のことが言えると思います。)

対策自体がハザードの発生源になりうる

上でリンクしたOSHAのワークシートを見ると、ここに興味深い欄があることに気づくでしょう。

(出典)

あらゆる対策手法は、職場に新たなリスクをもたらす可能性があります。管理的なアラームが多すぎるとアラーム疲れを引き起こし、重要なアラートが見逃されます。倉庫への立ち入りを禁止すれば、別のハザードのある場所を迂回せざるを得なくなるかもしれません。反射ベストは機械に巻き込まれる可能性があります。システム全体の安全性は包括的に考える必要があります。局所的な安全性の向上が、別の場所で問題を引き起こすことがあるのです。

これはソフトウェアでも同様です。Lorin Hochsteinは、講演の中で、Netflixの多くの障害がシステムを保護するためのソフトウェアによって引き起こされたことを語っています。

私の対策は、どのように新たなハザードを生み出す可能性があるでしょうか?

  • 追記専用データベースへの置き換えは、大幅な再教育やソフトウェアの変更を必要とし、ミスや新たなバグが生じる余地を広げてしまうかもしれません
  • 厳格なアクセスポリシーは、進行中の問題を修正しようとする際の足かせとなり、問題をより深刻化させるかもしれません
  • 管理的対策が多すぎると、人々は危険に対して警戒するのではなく、惰性で「形だけ」こなすようになってしまうかもしれません

対策によって引き起こされうる新たなハザードを特定するのは、既存のハザードを特定するよりも難しいと感じます。


以上がHoCの概要です。いい考えだと思います!

この記事が気に入ったら、ぜひニュースレターにご登録ください!毎週新しいエッセイをお届けしています。

私は企業向けに形式手法のトレーニングを行い、ソフトウェア開発をより速く、安く、安全にするお手伝いをしています。詳しくはこちらをご覧ください。


  1. いくつかの文献ではhazard controlsの階層(HoHC)と呼ばれていますが、NIOSHやOSHAといった機関ではHoCと呼ばれています。「interpreted language(インタプリタ言語)」と「interpreted programming language(インタプリタ型プログラミング言語)」のようなものだと思います。専門家向けに書くときはトピックが暗黙の前提になりますが、一般向けに書くときは明確にする必要がある、ということです。[return]
  2. この対策に共通の名前は見つけられていません。Discordで尋ねてみたところ、誰もが違う名前で呼んでいました。[return]
  3. はい、--forceフラグはありました。[return]

この記事は「muse-spark-1.2-contributor」を使用して翻訳されました。

コメント