kubestronautへの道 ~CKS編 その10 killer coda「Container Hardening」~

tech article

今日覚えて帰ること

Container Hardeningとは

コンテナのセキュリティを強化すること。具体的な方法は多種多様であるが、例えば以下のような対策が当てはまる。

  • コンテナ内にシークレットを残さない
  • root権限を与えない
  • 不要なバイナリを残さない

思ったよりネット上に情報が落ちていなかった。

Container Hardening

Harden a given Docker Container

There is a Dockerfile at /root/image/Dockerfile .

It’s a simple container which tries to make a curl call to an imaginary api with a secret token, the call will 404 , but that’s okay.

  1. Use specific version 20.04 for the base image
  2. Remove layer caching issues with apt-get
  3. Remove the hardcoded secret value 2e064aad-3a90–4cde-ad86–16fad1f8943e . The secret value should be passed into the container during runtime as env variable TOKEN
  4. Make it impossible to podman exec , docker exec or kubectl exec into the container using bash

You can build the image using

cd /root/image
podman build .

コンテナのセキュリティを強化しましょうという問題ですね。

もともと存在するDockerfileの中身はこちら

FROM ubuntu
RUN apt-get update
RUN apt-get -y install curl
ENV URL https://google.com/this-will-fail?secret-token=
CMD ["sh", "-c", "curl --head $URL=2e064aad-3a90-4cde-ad86-16fad1f8943e"]

ではまず1番の「Use specific version 20.04 for the base image」から。

こちらはubuntuのバージョンを指定しろと言っています。
コンテナを使用するメリットの一つに、どのような環境でも同じように動く、というものがあります。
これは、コンテナがホストに依存せずに同じ状態を保つことが出来るからです。

ベースイメージのバージョンを指定しない場合、ビルドの際には最新のバージョンがインストールされます。
これではビルドするタイミングによって同じDockerfileからコンテナをビルドしたとしてもバージョンが変わってしまう可能性があります。
環境ごとの再現性を高めるために、バージョンは指定しておきましょう。

以下のように指定します。

FROM ubuntu:20.04
RUN apt-get update
RUN apt-get -y install curl
ENV URL https://google.com/this-will-fail?secret-token=
CMD ["sh", "-c", "curl --head $URL=2e064aad-3a90-4cde-ad86-16fad1f8943e"]

続いて2番の「Remove layer caching issues with apt-get

これは何を言ってるかというと、apt-get updateとapt-get -y install curlを別のRUNコマンドではなく、同じRUNコマンドで実行せよ、と言っています。
なぜかというと、別のコマンドとして実行してしまうと別のレイヤーになってしまい、 apt-get update ではキャッシュを使用しているのに apt-get -y install curl ではキャッシュを使用せず、依存関係がうまく解決できない、ということが発生しうるからです。

レイヤーについては以下の記事が参考になります。

Dockerコンテナのレイヤ構造とは? - Qiita
はじめにDockerfileを書く際のベストプラクティスにもあるように、Dockerfileを作成する際の一般的なガイドラインとして「レイヤの数を最小にすること」というのがあります。普段Docke…

以下のように変更します。

FROM ubuntu:20.04
RUN apt-get update && apt-get -y install curl
ENV URL https://google.com/this-will-fail?secret-token=
CMD ["sh", "-c", "curl --head $URL=2e064aad-3a90-4cde-ad86-16fad1f8943e"]

続いて3番の「Remove the hardcoded secret value 2e064aad-3a90–4cde-ad86–16fad1f8943e . The secret value should be passed into the container during runtime as env variable TOKEN

こちらはシークレットをコンテナに持たせず、コンテナを立ち上げるときに環境変数として渡せ、と言っています。

Dockerfileに直接シークレットを含めると、イメージを共有する際やリポジトリにプッシュする際にシークレットが漏洩してしまうリスクがあります。環境変数として実行時に渡すことで、このリスクを軽減できます。

また、同じイメージを使用して異なるシークレット値を簡単に渡すことができるため、異なる環境(例えば、開発環境、本番環境)で同じイメージを使う場合に便利です。

FROM ubuntu:20.04
RUN apt-get update && apt-get -y install curl
ENV URL https://google.com/this-will-fail?secret-token=
CMD ["sh", "-c", "curl --head $URL$TOKEN"]

実行時は以下のようにして環境変数を渡します。

podman build -t app .
podman run -e TOKEN=2e064aad-3a90-4cde-ad86-16fad1f8943e app

最後に4番「Make it impossible to podman exec , docker exec or kubectl exec into the container using bash

これはbashを使ってコンテナに入れないようにしなさい、と言っています。
以下のようにすればよいです。

FROM ubuntu:20.04
RUN apt-get update && apt-get -y install curl
ENV URL https://google.com/this-will-fail?secret-token=
RUN rm /usr/bin/bash
CMD ["sh", "-c", "curl --head $URL$TOKEN"]

このようにファイルを削除してからビルドする、という方法もありますが、そもそもベースイメージに無駄なファイルが存在しない軽量のものを使用する、という手もあります。

タイトルとURLをコピーしました