10 Docker Image Security Best PracticesーPart 1

gavin.zhou
12 min readDec 23, 2019

--

Dockerイメージセキュリティのベストプラクティス 10のコツー第一章

今回は10のDockerイメージセキュリティのベストプラクティスをご紹介いたします。第一章では5つご紹介します。

この早見表のインストールでは、Dockerにフォーカスを当てて見ていきたいと思います。そして、もっとセキュアで質の高いDockerイメージプロセスについてのガイドラインを提示し、そのためのコツをご紹介したいと思っています。

こちらの最新の我々のDocker セキュリティレポートもチェックしてみてください。

DOCKER セキュリティのシフトレフト

早見表のダウンロード

それでは、我々のDockerイメージセキュリティのベストプラクティス トップ10を見ていきたいと思います。

1. Prefer minimal base images

しばしば、 「デフォルト」でFROM nodeを伴った Dockerfile を描くようなジェネリックなDockerコンテナイメージを使ったプロジェクトがスタートする場合があります。しかし、ノードイメージを指定する場合、完全にインストーされたDebian Stretchディストリビューションが構築する際に使われるイメージであるということを考慮する必要があります。もし自分のプロジェクトが一般的なシステムライブラリーやシス天寿ユーティリティが不要な場合、本格的なオペレーティングシステム(OS)をベースイメージとして使用することを避ける方がいいと思います。

Snykのオープンソースセキュリティレポート-2019では、Docker Hub上で取り上げられている多くのDockerコンテナが、知られている多くの脆弱性を含むということが分かります。例えば docker pull nodeのような一般的でポピュラーなダウンロードされたノードイメージを使う場合、システムライブラリに580個の脆弱性があることがわかっているアプリケーションにOSを実際に導入しています。

LEARN MORE ABOUT SECURING YOUR DOCKER IMAGES

オープンソースセキュリティレポート2019を読むとすぐ分かりますが、Docker Hubで調査した上位10のDockerイメージにはそれぞれ既知の脆弱性が含まれていました。プロジェクトの実行に必要なシステムツールとライブラリのみをバンドルした最小限のイメージを好むことにより、攻撃者に対する攻撃対象領域を最小限に抑え、安全なOSを確実に出荷できます。

自分のDOCKERイメージをよりセキュアにする方法についてもっと詳しく知りたい方はこちら

2. Least privileged user

Dockerfile が USERを特定しない場合、ルートユーザーを使ったコンテナを実行するようにデフォルトで設定されています。実際では、コンテナにルート権限が必要になる理由はありません。Dockerはデフォルトでルートユーザーを使うコンテナを走らせます。そのネームスペースが、走っている最中のコンテナの中でルートユーザーにマップされるとき、それは、コンテナはDockerホストへのルートアクセスを持っているかもしれないということを意味します。コンテナ上でアプリケーションをルートユーザーで実行すると、攻撃対象がさらに広がり、アプリケーション自体が利用することに対して脆弱な場合に特権昇格への簡単なパスが可能になります。

エクスポーズを最小限に抑えるために、アプリケーションのためのDockerイメージの中の専用ユーザーや専用グループを増やすためのopt-inをします。つまり、 Dockerfile の中で USER ディレクティブを使い、最小権限のアクセス権を持つアプリケーションをコンテナが走らせることを確認します。

特定のユーザーはそのイメージの中に存在しないかもしれません。 Dockerfileの中のインストラクションを使ってユーザーを生成します。

以下のデモンストレーションはそれの方法をジェネリックなUbuntuイメージに対して行う完璧な例です。

FROM ubuntuRUN mkdir /appRUN groupadd -r lirantal && useradd -r -s /bin/false -g lirantal lirantalWORKDIR /appCOPY . /appRUN chown -R lirantal:lirantal /appUSER lirantalCMD node index.js
  • パスワードなし、ホームディレクトリ セットなし、シェルなしのシステムユーザー (-r)を生成する
  • (groupaddを使って)事前に作っておいた既存のグループにユーザーを追加する
  • 作成したグループに関連付けて、finalアーギュメントセットを作成したいユーザー名に追加する

Node.jsやalpineイメージが大好きなのであれば、すでに一般的なユーザー向けにバンドルされています。こちらに、Node.jsの例を出しておきます:

FROM node:10-alpineRUN mkdir /appCOPY . /appRUN chown -R node:node /appUSER nodeCMD [“node”, “index.js”]

Node.jsアプリケーションを開発しているのであれば、公式な Docker and Node.js Best Practicesを見てみるといいと思います。

3. Sign and verify images to mitigate MITM attacks

Docker imagesのオーセンティシティ(信用度)は課題です。プロダクションの中でコードを走らせるコンテナとしてそれらのイメージを文字通り使っているため、そのイメージを物凄く信頼しています。そのため、プルするイメージがパブリッシャーによってプッシュされるとものだというものを確実にすること、そしてパーティが全く変更されないことが大切です。ワイヤ全体、Dockerクライアントとレジストリの間に変更は何度も繰り返されます。もしくは、不正イメージをプッシュするためにオーナーのアカウントのレジストリを攻撃することで変更が起こります。

Verify docker images

Dockerはデフォルトでオーセンティシティ(信用度)を有効にすることなくDockerイメージをプルできます。このように潜在的にその出どころや作成者が検証されていない所定のDockerイメージへエクスポーズします。

この方法を有効活用するために、Dockerイメージをプルする前に常にイメージを確認するようにしましょう。検証を試すには、次のコマンドでDocker Content Trustを一時的に有効にします:

export DOCKER_CONTENT_TRUST=1

次に、署名されていないことが分かっているイメージをプルしようとします。そのリクエストは拒否され、イメージはプルされません。

Sign docker images

出どころとオーセンティシティ(信用度)を検証できないイメージよりも、Docker Hubによって吟味されキュレーションされた信頼できるパートナーから提供されるDocker認定イメージを優先します。

Dockerはイメージに署名することを許可します。これによって、他の保護のレイヤーが使用できるようになります。イイメージに署名するために、 Docker Notaryを使用します。Notaryはあなたの代わりにイメージ署名を検証します。そして、そのイメージの署名が無効だった場合、走っているイメージをブロックします。

上記のようにDocker Content Trustが利用できない場合、Dockerイメージビルドはイメージに署名します。そのイメージに最初に署名されたととき、Dockerはユーザーに代わって ~/docker/trust の中のプライベートキーを生成し、保存します。このプライベートキーはイメージが構築されるときにはいつでも追加されるイメージに署名するために使われます。

署名されたイメージの設定についての詳しい説明はDocker’s official documentationをご覧ください。

4. Find, fix and monitor for open source vulnerabilities

Dockerコンテナのためにベースイメージを選択する際には、ベースイメージがバンドルされるセキュリティ面のリスクを間接的に負うことになります。オペレーティングシステムのセキュリティに関係しない不適切にコンフィギュアされたデフォルトである可能性があり、また、選択したベースイメージにバンドルされているシステムライブラリである可能性もあります。

最初のステップとしては、可能な限り最小限のベースイメージを利用しながら、問題なくアプリケーションを実行できるようにすることがよいでしょう。こうすることで、脆弱性への制限のあるエクスポーズによってアタックサーフェス(攻撃領域)を減らすことができます。その反面、それだけではaudit(監査)を走らせることはありませんし、また、使用しているベースイメージのバージョンについて開示される可能性のある将来の脆弱性から保護することもありません。

そのため、オープンソースソフトウェアで脆弱性から逃れるための唯一の方法は Snykのようなツールを使うことです。脆弱性の継続的なスキャンとモニタリングを追加することができます。脆弱性は使用中の全てのDockerイメージレイヤーに存在します。

既知の脆弱性をためのDockerイメージを以下のコマンドでスキャンします:

# fetch the image to be tested so it exists locally$ docker pull node:10# scan the image with snyk$ snyk test --docker node:10 --file=path/to/Dockerfile

既知の脆弱性に対するDockerイメージのモニタリングし、一旦新しい脆弱性がイメージの中で発見されれば、Snykが改善アドバイスを知らせてくれます。

$ snyk monitor --docker node:10

Snykユーザーによるスキャンをベースにして、44%のDockerイメージが既知の脆弱性をスキャンしたことが分かりました。そして、より新しくよりセキュアな利用可能なベースイメージが存在するのです。この改善アドアビスは、デベロッパーがDockerイメージをアップデートし、何かの対応ができるSnykにとってはユニークです。

SnykはまたすべてのDockerイメージの20%をスキャンしたということを発見しました。脆弱性の数を減らすために必要なのは、Dockerイメージの再構築のみです。 Snykのブログで、オープンソースセキュリティレポート2019について詳しく読んでください。

5. Don’t leak sensitive information to Docker images

時折、Dockerイメージの中でアプリケーションを構築する際に、SSHプライベートキーのようなプライベートリポジトリからコードをプルするようなものや、プライベートパッケージをインストールするトークンなどのシークレットが必要になる場合があります。もしDockerの中間コンテナの中にそれらをコピーするのであれば、後で削除した場合でも、追加されたレイヤーにキャッシュされます。 これらのトークンとキーは、 Dockerfileの外部で保管する必要があります。

Using multi-stage builds

Dockerのマルチステージビルドを利用するには、機密データがイメージビルドに到達しないように後で破棄される中間イメージレイヤーでシークレットを取得して管理します。次の例のように、コードを使用して、上記の中間層にシークレットを追加します。

FROM: ubuntu as intermediateWORKDIR /appCOPY secret/key /tmp/RUN scp -i /tmp/key build@acme/files .FROM ubuntuWORKDIR /appCOPY --from=intermediate /app .

Using Docker secret commands

Dockerのシークレットを管理する追加機能を使って、機密ファイルを取得することなくマウントします。次のようにしてみてください:

# syntax = docker/dockerfile:1.0-experimentalFROM alpine# shows secret from default secret locationRUN --mount=type=secret,id=mysecret cat /run/secrets/mysecre# shows secret from custom secret locationRUN --mount=type=secret,id=mysecret,dst=/foobar cat /foobar

Dockerのシークレットに関しては、彼らのサイトに詳しく書かれています。

Beware of recursive copy

構築されているイメージの中にファイルをコピーする場合、気を付けておいてほしいことがあります。例えば、次のコマンドがビルドコンテキストフォルダー全体をDockerイメージに繰り返しコピーすると、機密ファイルもコピーしてしまうことがあるということです:

COPY . .

もし、フォルダーの中に機密ファイルがあるのであれば、移動させるか .dockerignore を使って無視するようにしましょう。

private.keyappsettings.json

Orangesys.ioでは、kuberneteの運用、DevOps、監視のお手伝いをさせていただいています。ぜひ私たちにおまかせください

--

--

No responses yet