秘密情報をコンテナイメージに入れない

DockerBeginner
オンラインで実践に進む

はじめに

コンテナイメージから削除したファイルも、前のイメージ層には残っている場合があります。また、Git の無視ルールは、ビルド時に Docker が受け取る内容を制御しません。

このラボでは、用意されたイメージを調べ、ビルドへの入力を制限し、新しいイメージのすべての層を検証します。ワーカーと Docker のワークフローは、前のラボと同じです。認証情報はすべて架空のローカルテスト用データで、キャッシュ済みベースと確認用ヘルパーは用意されています。

用意されたビルド入力を確認する

このステップでは、ソース管理の無視ルールと、Docker のビルド入力を区別します。

cd /home/labex/project/ticket-image
ls -a

ls -a は、ドットで始まるファイルも表示します。このプロジェクトには、ワーカー、公開設定、入力/出力ディレクトリ、private.env、debug.txt があります。最後の 2 つはローカルの非公開入力であり、提供用ファイルではありません。

cat .gitignore

Git は、2 つの非公開ファイル名を無視します。これは Git の追跡ワークフローに影響しますが、Docker のビルドコンテキストには影響しません。

cat .dockerignore

このファイルは現在空です。**.dockerignore** は、Docker がビルドコンテキストを受け取るときに、どのパスを除外するかを制御します。Git に無視されているファイルでも、Docker のビルドには送信される場合があります。

cat Dockerfile

COPY . /app/ は、利用可能なコンテキスト全体をコピーします。後の RUN rm ... は、最終的なファイルシステムから非公開ファイルを取り除きますが、それより前のイメージ層を元に戻すものではありません。

イメージ層に隠れたコピーを見つける

このステップでは、最終的なファイルシステムと、保存されたイメージ層を比較します。

用意された旧タグ ticket-image:legacy は、この Dockerfile からビルドされています。一度限りの確認用コンテナを実行します。--rm は、ls の終了後にこの一時コンテナを自動的に削除します。このコマンドは、イメージのデフォルトのワーカー起動を上書きします。

sudo docker run --rm ticket-image:legacy ls -a /app

最終的な /app に、private.env や debug.txt は表示されないはずです。ワーカーと公開設定は残っています。

docker history は、イメージのビルド命令を表示します。--no-trunc は、命令のテキストを省略せずに表示します。

sudo docker history --no-trunc ticket-image:legacy

広い範囲のコピーに続いて削除があることを確認してください。履歴は順序を説明しますが、すべてのファイルの内容を示すものではありません。用意された course-image-scan ヘルパーは、この実際のイメージを保存し、保存されたすべての層とイメージ設定を読み取ります。

sudo course-image-scan ticket-image:legacy

前の層にある非公開ファイル名と、マスクされた対象の練習用認証情報を示す検出結果が表示されるはずです。終了コード 1 は検出ありを意味し、2 または CHECK ERROR は確認の失敗を意味します。このヘルパーの固定された範囲は、列挙された非公開ファイル名と、この偽の認証情報であり、本番用の包括的な秘密情報スキャナーではありません。

後の層で削除しても、前の層のバイト列は消えません。そのため、最終的なファイルシステムの ls に問題がないだけでは不十分です。

非公開のビルド入力を除外する

このステップでは、ローカルの非公開ファイルを残しながら、Docker のコンテキストから除外します。

nano .dockerignore

次の完全なファイルを使います。

private.env
debug.txt
input/
output/

各行は、除外するパスまたはディレクトリです。これらのパターンは、非公開設定、デバッグ資料、実行時データをビルド入力から取り除きます。ワーカーと config.public は引き続き利用できます。

Ctrl+O、Enter で保存し、Ctrl+X で終了します。ローカルの非公開ファイルは削除しないでください。パスの無視は、含める範囲を制限するものであり、ローカル設定を破棄するものではありません。

Dockerfile のコピー範囲を限定する

このステップでは、イメージに必要な入力を明示します。

以前の削除命令は不要になりました。除外されたファイルは利用できないため、その命令は失敗するはずです。Dockerfile を開きます。

nano Dockerfile

次の完全なファイルを使います。

FROM desklite-base:1.37.0
WORKDIR /app
COPY worker.sh config.public /app/
USER nobody
CMD ["sh", "/app/worker.sh"]

COPY worker.sh config.public /app/ は、必要な 2 つの業務ファイルだけを列挙します。前のラボの USER nobody と元の起動コマンドは維持してください。Ctrl+O、Enter、Ctrl+X で保存して終了します。

2 つの制御は連携して働きます。.dockerignore は利用可能なビルド入力を制限し、明示的な COPY はこのイメージに含めるものを制限します。どちらも、秘密情報が層に入った後で削除する方法には頼っていません。

新しい成果物をビルドして確認する

このステップでは、古い証拠の意味を変えるのではなく、新しくビルドした提供用イメージを確認します。

sudo docker build -t ticket-image:delivery .

ローカルのビルドが成功するはずです。新しいタグは ticket-image:legacy とは別です。

sudo course-image-scan ticket-image:delivery

保存されたすべての層とイメージ設定について、PASS が表示されるはずです。この対象を限定した結果は、考えられるすべての秘密情報や脆弱性を検出したと主張するものではありません。

次に、コンテキストを独立して確認します。

sudo course-context-check .

この用意されたヘルパーは、固定の COPY . プローブで一時イメージをビルドし、同じ実際の層の確認を行ってから、その一時イメージを削除します。PASS になるはずです。これにより、非公開ファイルが、狭くした提供用 COPY から省かれただけでなく、コンテキストから除外されたことを示せます。

旧イメージには、元の検出結果が残っている場合があります。安全な提供用成果物を再ビルドしても、すでに配布したイメージが書き換わったり、漏えいした認証情報が失効したりするわけではありません。実際の漏えいでは、前に学んだ認証情報の置き換えと、古いコピーの適切な後処理が必要です。ここで対象とする Token は意図的に偽のものであり、合格条件の対象は新しい提供用イメージです。

新しいイメージから元のレポート処理を実行する

このステップでは、非公開のビルド入力を取り除いても、ワーカーに必要なファイルと動作が維持されたことを示します。

出力ディレクトリは、すでに UID 65534 が所有し、アクセスを限定した書き込み権限が設定されています。前のラボの非 root ワーカーとバインドマウントのワークフローを再び使います。

sudo docker run -d --name ticket-image-worker --network none --mount type=bind,src=/home/labex/project/ticket-image/input,dst=/data/input,readonly --mount type=bind,src=/home/labex/project/ticket-image/output,dst=/data/output ticket-image:delivery
sudo docker exec ticket-image-worker id -u

65534 が表示されるはずです。

sudo docker logs ticket-image-worker

mode=report と tickets=2 が表示されるはずです。最初の行は必要な公開設定から、2 行目は元の入力を読み取って実際のレポートを書き込む処理から得られます。

sudo docker exec ticket-image-worker cat /data/output/report.txt

tickets=2 が表示されるはずです。ワーカーには、読み取り専用の入力と書き込み可能な出力が引き続きあり、イメージ内の非公開設定は必要ありません。

ローカルのソースと提供用の証拠を確認する

このステップでは、ローカルの非公開入力と、安全な提供用成果物の両方を維持して終えます。

内容を表示せずに、非公開のソースファイルを一覧表示します。

ls -l private.env debug.txt

両方が引き続きローカルに存在する必要があります。削除すると、意図したビルド境界の演習を回避してしまいます。

sudo course-image-scan ticket-image:delivery
sudo docker ps

提供用のスキャンが合格し、ticket-image-worker が実行中であるはずです。コースのチェックでは、実際のビルドコンテキストも調べ、実行中のイメージ ID を確認し、元のレポートを検証します。別途提出する調査ファイルはありません。

まとめ

実際の Docker ビルド入力を制限し、必要な業務ファイルだけをコピーし、保存されたすべての層とイメージ設定を確認して、元の非 root ワーカーを維持しました。最終的なファイルシステムに問題がないだけでは、この境界を確認することはできませんでした。