‫次の1枚はこちら
‫これは大きいですね｡
‫避けられるなら､ コンテナ内でアプリをルートで実行しないでください｡
‫早速ですが､ ここでちょっとしたデモをやってみましょう｡
‫わかりました｡ Dockerを動かしている､ 少なくともそのはずだ｡
‫わかりました｡
‫そして､ もし私がただ走るだけなら...
‫Nginxを走らせて､ そのコンテナ上でdocker
‫topを実行すればいいんですね｡
‫ここで何を見るか？
‫コンテナ内では､ Nginxはrootでプロセスを起動し､
‫root以外のユーザーで新しいプロセスを作成しました｡
‫そのユーザーが101であることを確認します｡
‫これは､ MySQL､ Postgres､ Nginxなどのデーモンベースのプログラムの多くに共通することです｡
‫プログラミング言語でないものの多くは､ これを自動的に行います｡
‫だから､ これは安全なんです｡
‫これは､ Nginxがrootとして実行されないワーカープロセスを生成し､
‫作業の大部分を行うことを可能にします｡
‫つまり､ rootとして動作するマスタープロセスが1つありますが､ それが接続を受け付け､
‫作業の大部分を担っているわけではありません｡
‫そのほとんどが､
‫このワーカープロセスにあるのです｡ つまり､ Nginx に脆弱性がある場合､
‫Nginx の HTTP プロトコルを悪用しようとする接続が来ると､
‫このユーザでロックされる可能性があります｡
‫よほど深刻な脆弱性がない限り､
‫ほとんどの場合､ ここにアップされています｡
‫この下だと､ できることが限られてしまうんですね｡
‫仮にそのプロセスを何らかの形で引き継いだとしても､
‫ユーザーとしては限界がある｡
‫だから､ これでOKなんです｡
‫これでもコンテナ内ではtrue rootで実行されていないのです｡
‫PythonアプリやNodeアプリなど､
‫プログラミング言語のアプリを実行する場合､
‫コンテナ内のプログラミング言語がプログラムの仕組みを知らないため､ デフォルトでrootに設定されます｡
‫何をさせたいのかがわからない｡
‫だから､ デフォルトでrootをやることになり､ アプリケーションの互換性という意味合いが強くなります｡
‫私たちは､ これをデフォルトでセキュアにしたいと言うかもしれません｡
‫しかし､ Dockerは､ これらすべての公式コンテナが､ プログラミング言語のルートとして本当に実行されるように選択しました｡
‫それを確認しに行こう｡
‫おっとっと｡ それじゃなくて
‫Firefox｡
‫そこで､ たとえば「ハブ」に行ってみましょう｡
‫とりあえずNodeをやってみよう｡
‫これは多くの言語に共通することです｡
‫ここでは､ 例としてNodeを取り上げます｡
‫Nodeの内部で､
‫ここにあるDockerfileの1つに入ると｡
‫そして､ ユーザーを検索する｡
‫実際には何も見つかっていないことにお気づきでしょう｡
‫ここで追加するのはこのユーザーだけです｡
‫こうなっていることにお気づきでしょうか？
‫技術的にはNodeというグループを追加し､ Nodeというユーザーを追加しています｡
‫このファイルの残りを検索すると､ スタンザU S E
‫Rでそのユーザーに変更されることはないことがわかりますね｡
‫その中のどこかにユーザーノードが行として表示されているはずです｡
‫それが仕事だからやらないんです｡
‫そこで､ ダウンレベルのDockerfileで行うべきこと｡
‫ですから､
‫プログラミング言語の公式イメージから作成するDockerfileは､
‫彼らが作成したユーザーを活用すべきなのです｡
‫もし､
‫そのようなユーザーを作成していない場合は､ 同じ方法で自分で作成することができます｡ この小さな2行のものを盗んで､
‫ユーザーの好きなものに変えればいいんです｡
‫Python用なら､
‫Pythonユーザーとでも呼べばいいのかもしれませんね｡
‫もしそうしていると､ 実行するアプリケーションがコンテナ内でrootとして実行されなくなります｡
‫デフォルトでは､
‫標準的なNodeアプリを実行すると､ コンテナ内のrootユーザーを使用します｡
‫なぜ､ そんなに重要なのか？
‫まあ､ 2つありますね｡
‫1つは､ もし誰かがあなたのアプリケーションを突破してハッキングし､
‫ファイルシステムにアクセスすることができたとしたら､
‫その人は...｡ そのアプリケーションがルートであれば､
‫コンテナの中で､ やりたいことは何でもできるわけですね｡
‫ファイルシステムにファイルを書き込むことができる｡
‫そのコンテナの中で好きな時に実行できるプログラムをさらにインストールすることができるのだ｡
‫だから､ そんなことはしてほしくないんです｡
‫むしろ､ 非常に限定的であってほしい｡
‫だから､ アプリケーションが対応していれば､
‫こうしてください｡ 基本的にユーザーが利用できるようにするんですね｡
‫次に､ DockerConでの事例を紹介します｡
‫DockerConで､ 私はNode.NETについて一通り話をしました｡ jsで､ その中のひとつにユーザーに関する話題がありました｡
‫探してみますね｡
‫私がここで何をしたかを見てください｡ かなりシンプルなファイルです｡
‫これをリンクして入れるんです｡
‫このDockerfileでは
‫そこで､ このDockerfileでは...
‫ユーザーを作らなかったのは､ Nodeのイメージがすでに作ってくれていたからです｡
‫ユーザーノードに変更したところです｡
‫そして､ この2行でパッケージをインストールし､ 後で､
‫実行するのです｡
‫コピーコマンドでchownオプションを使い始めて､
‫ファイルがプログラムを実行するユーザーと同じユーザーになっていることを確認する必要があることにお気づきでしょう｡
‫そうでないと､
‫問題が発生する可能性がありますからね｡ 私のアプリケーションは､ おそらく... ファイルを読めないということは､
‫実行できないということですよね｡
‫だから､ そのパーミッションの変更が必要なんだ｡
‫コピーコマンドのワンライナーでできるんです｡
‫また､ アプリがコピーされるたびに､ 書き込みができるようにパーミッションを確認するために､
‫ディレクトリを作成し､ それをchowningしていることもおわかりいただけるでしょう｡
‫なぜなら､ このユーザーを変更した瞬間に､ このコピーコマンド､
‫具体的にはこの実行コマンドがそのユーザーとして実行されるからです｡
‫ディレクトリへの書き込み権限がなければ､
‫これも失敗する｡
‫つまり､ Dockerがこれをやってくれないのは､ あなたのものがおそらく壊れることを知っているからなのです｡
‫だから､ このような余計な手間をかける必要があるのです｡
‫でも､ そんなに難しいことではありません｡ 本当にそうなんです｡
‫このテストはおそらく1日ですべて行うことができます｡
‫そして､ システムをサーバー上で完全なCIと完全なテストを通して実行したいと思うでしょう｡
‫PHPはログファイルを大量に実行し､ ディスクに大量に書き込むのが好きです｡
‫本当に､ ユーザーのアップロードを許可しているものは､ ディスクに書き込むことになります｡
‫例えば､
‫WordPressでブログを運営している場合､ ファイルを書き込む際にパーミッションが正しく設定されていることを確認する必要があります｡
‫WordPressのブログは､ ユーザーがブログに画像をアップロードすると､
‫ディスクに書き込まれます｡
‫そのパーミッションがうまくいくかどうかを確認したいのです｡
‫だから､ 絶対にテストをする必要があるんです｡
‫これで､ アプリケーションはroot権限で実行されなくなります｡
‫だから､
‫コンテナの中で完全にコントロールすることはできない｡ もうひとつは､ LinuxやDockerに脆弱性があったとしても､
‫それもごくまれなことですが､ このコンテナから抜け出す可能性が低くなるからです｡
‫そんなことがあったのは､
‫まあ､ 私がよく知っているのは1回だけで､ 実はここに少し記録してあるんです｡
‫ダーティーCOW｡ Dirty COWはLinuxの脆弱性で､
‫コンテナから外に出られるというものでしたね｡
‫ここでユーザーを変更しても､
‫すべての問題が解決するわけではありませんが､
‫この問題が解決しないことは確かです｡
‫その他の脆弱性については､ おそらく防御できるはずです｡
‫しかし､ これはベストプラクティスです｡
‫セキュリティチームがいれば､ 「rootで動かすのはやめよう」と主張すると思うんです｡
‫だから､ そうするのでしょう｡