若手エンジニアのブログ

若手エンジニアのブログ

文系出身の若手女子エンジニアによる技術ブログ。
日々の経験や学びをアウトプットするためにブログを書いています。
バックエンド(Java+SpringFramework)を経てインフラエンジニアになりました。
今は育休中につき、本で勉強したことを中心にアウトプットしています。

大変お久しぶりですm(__)m

去年5月に育休明けで仕事復帰して以来の投稿かも?

そして今は2人目を妊娠しており、今年の5月半ばからまた産休でしばらくお仕事はお休みする予定です(^-^;

 

仕事と1人目の子育て・家事と、妊娠による異常な身体の疲れとで、

今はAmeba自体を開けないことが多いのですが…、

引き続き自分のペースで更新したいと思いますので、どうぞよろしくお願いいたします^^

 

 

さて、次回産休までのお仕事では、AWS案件に携わらせてもらっているので、

久しぶりの投稿はAWSネタでいきたいと思います。

 

今日は、ECSコンテナの読み取り専用化について。

 

もくじ

1.読み取り専用コンテナとは

2.コンテナを読み取り専用にするメリット

3.コンテナを読み取り専用にする方法

4.読み取り専用化時の注意点(←特にこれ大事)

 

1.読み取り専用コンテナとは

読み取り専用(ReadOnly)コンテナとは、文字通り、

コンテナ内で一切の書き込みができないコンテナのことである。

 

書き込みができないといことはつまり、コンテナ内において、例えば以下が一切できないということになる。

 ・ディレクトリやファイルの作成、編集、移動や名称変更、削除等の処理

 ・アプリケーションやミドルウェアの動作によるファイル書き込み

 ・ログのファイル出力

 ・ソフトウェアのインストール

 

ちなみに、コンテナのもととなるDockerfile内では、これら書き込み処理は可能である。

あくまでも、Dockerfileをもとに作成したDockerイメージを、読み取り専用としてデプロイした場合(読み取り専用コンテナとした場合)、

コンテナの起動・実行中に、上記のような一切の書き込みが不可となるということだ。

 

 

2.コンテナを読み取り専用にするメリット

コンテナを読み取り専用とする理由は、セキュリティ対策である。

 

コンテナは読み取り専用であるため、

コンテナに対する攻撃者がいたとしても、不正なファイルの作成、書き換え、削除等ができない。

コンテナ内へのファイルダウンロード処理もできないので、

マルウェアに感染させるようなファイルを、コンテナ内に不正に配置することもできなくなる。

 

また、コンテナを読み取り専用とすることで、コンテナ内部へのexecができなくなる。

AWSの公式ドキュメントにも明記有り。コンテナ内部へのexec実行過程で、コンテナ内への書き込み処理が一部発生することが理由の模様。)

exec実行不可により、内部不正を含めて、攻撃者がコンテナ内に入り込んで不正操作をすることが、物理的にできなくなる。

 

このように、セキュリティ対策観点から、本番環境で動くコンテナは、

可能な限り読み取り専用にするほうが良いと言える。

 

 

3.コンテナを読み取り専用にする方法

実際にコンテナを読み取り専用とする方法だが、コンテナのタスク定義で1つ定義するだけで可能である。

 

具体的には、マネジメントコンソールの場合、

読取り専用ルートファイルシステムの「読み取り専用」のチェックボックスにチェックをつけるだけだ。

 

JSONファイルの場合は、「readonlyRootFilesystem」パラメータ値をtrueに設定する。

 

 

上記設定だけで、コンテナ自体は読み取り専用となる。

ただし、コンテナの動作に必要な書き込みもいくつかあると思う。

例えばアプリケーションのプロセスIDの書き込みや、

コンテナ起動時に新たなファイルを作成しないといけない等はあるあるのはず。

 

そういった、「書き込みの必要なファイル」は、

それらファイルの格納先ディレクトリを、書き込み可能な外部ボリュームにマウントさせておく必要がある。

 

そうしないと、コンテナを読み取り専用としたことで必要な書き込みができず、

アプリケーションが正常起動しない→コンテナの起動に失敗する…

という現象が発生する。(私も何度これで苦しめられたことか…)

 

ボリュームのマウントは、同じくタスク定義で可能である。

 

ボリュームは必要な数だけ作成し、マウントする。

ボリュームの種別はEFS、バインドマウントのいずれでも問題ないが、

例えばPID情報など他のコンテナと共有する必要がないものはバインドマウント、

複数のコンテナと共有したいファイルを含む場合はEFSといった使い分けができる。

 

 

加えて、コンテナの実行ユーザーが、ボリュームのアクセス権を持っていないと、

当たり前だがボリュームをマウントしていても書き込みできない。

 

アクセス権を付与するには、コンテナイメージのもととなるDockerfile内で、

コンテナの実行ユーザーで VOLUME コマンドを実行し、あらかじめボリュームマウントしておくことも必要となる。

※Dockerfileは、例えば以下のように定義する。

USER app_user

VOLUME /var/app/testapp

 

 

コンテナの読み取り専用化自体は簡単だが、

必要な書き込み先として、ボリュームのマウントおよびアクセス権の付与も別途必要となることを忘れないようにしたい。(自戒を込めて。)

 

 

4.注意点

最後に、コンテナの読み取り専用化において、特に注意すべき(と筆者が思う)点を、3つ挙げておく。

 

①ファイルレスマルウェア対策にはならない

「ファイルレスマルウェア」とは、文字通りファイルを介さないマルウェアのことである。

通常のマルウェアは、コンテナ上のファイルへの不正な書き込みや、不正なファイルのダウンロード処理を伴い感染する。

ところがファイルレスマルウェアは、ファイルではなくメモリ上への書き込みにより感染するものとなる。

 

コンテナの読み取り専用化は、あくまでもファイルに対する書き込みの禁止であり、

メモリの書き込みは通常通りできる。(というかメモリに書き込めないとどうしようもない)

 

つまり、コンテナの読み取り専用化は、ファイルレスマルウェアに対しては対策にはならない点に注意したい。(通常のマルウェア対策にはなる)

 

 

②コンテナのログは必ず外出しする

コンテナ内のファイルへの書き込みができないということは、コンテナ内にあるログファイルにも書き込みができないということである。

 

そもそもコンテナは、プロセスが終了するとコンテナ自体も終了し、コンテナ内に保存していたファイル等は全て消えてしまう。

その意味でもログの出力先は、コンテナ内に保管するログファイルであってはならない。

 

読み取り専用化したコンテナの場合は、コンテナ内での書き込みが不可となるため、ログを残せないどころか、ログを出力できずエラーとなってしまう。

 

ECSであれば、ログをCloudWatchに出力する(CloudWatchに出力したい場合は、標準出力/標準エラー出力をログ出力先とする必要がある)か、

3.コンテナを読み取り専用にする方法でも記載した、マウントしたボリュームをログ出力先とするかがよくある手段だと思う。

※ECSのログ出力方式例は以前の記事をご参照。

 

 

③コンテナの動作上、必要な書き込みがある場合は、あらかじめボリュームをマウントする

これは3.コンテナを読み取り専用にする方法で詳しく書いたので、そちらを参照してほしい。

 

今回は以上!