コンテントトラストのサンドボックスで遊ぶ

読む時間の目安: 4 分

このページでは、コンテントトラストを試用できるサンドボックスについて、その設定と利用方法を説明します。 サンドボックスはコンテントトラストの操作を、ローカルにおいて設定し試してみることができるものです。 本番環境のイメージに影響を与えることはありません。

サンドボックスの作業を進める前に、コンテントトラストの概要 をよく読んでおいてください。

前提条件

ここに示す手順においては、Linux または macOS を利用しているものとします。 サンドボックスは、ローカルマシン上、仮想マシン上のいずれにおいても動作します。 そのローカルマシンあるいは仮想マシン上においては、docker コマンドの実行権限が必要です。

サンドボックスを利用するためには 2 つの Docker ツールが必要です。 Docker Engine 1.10.0 以上と Docker Compose 1.6.0 以上です。 Docker Engine をインストールするには 対応するプラットフォームの一覧 から選んでください。 Docker Compose をインストールするには インストール手順の詳細 を参照してください。

サンドボックスの中には何があるか

コンテントトラストを単にインストールしただけの状態である場合、必要なのは Docker Engine クライアントと Docker Hub へアクセスできることだけです。 サンドボックスはコンテントトラストの本番環境をまねて実現しているため、以下のようなコンポーネントを追加設定します。

コンテナー 内容説明
trustsandbox Docker Engine の最新版と設定済み証明書が含まれているコンテナー。これがサンドボックスであり、dockerクライアントを使ってトラスト操作を試行するものです。
レジストリサーバー ローカルのレジストリサービス。
Notary サーバー トラスト管理のための重要な処理を行うサービス。

上はつまり、コンテントトラスト(Notary)サーバーとレジストリサーバーは自分で起動するということです。 Docker Hub を主に利用しているのであれば、上のコンポーネントを用意する必要はありません。 Docker Hub にはすべてビルドされ含まれています。 しかしサンドボックスの場合は、本番環境に似せたものを自分でビルドして利用します。

trustsandboxコンテナーでは、Docker Hub ではなく、ローカルのレジストリサーバーとやりとりをします。 日々使っているイメージリポジトリは、ここでは利用しないということです。 サンドボックスで遊んでいる間は、イメージリポジトリは保護されます。

サンドボックスで遊ぶ際には、ルート鍵とリポジトリ鍵も生成します。 サンドボックスでは、trustsandboxコンテナー内部に、鍵データやファイルは何でも保存できるように設定されています。 サンドボックス内で生成する鍵は、お遊び用なので、コンテナーを削除するときに同時に削除します。

trustsandboxコンテナーにおいては docker-in-docker イメージを使います。 したがって、本物の Docker デーモンとの間でイメージをプッシュ、プルすることはなく、キャッシュを汚すことはありません。 イメージは、このコンテナーにアタッチされた匿名ボリュームに保存します。 そしてコンテナーを削除したときに同時に削除します。

サンドボックスのビルド

この節では Docker Compose を使ってtrustsandboxコンテナー、Notary サーバー、レジストリサーバーを設定してリンクさせる方法を説明します。

  1. 新たなディレクトリtrustsandboxを生成してそこに移動します。

     $ mkdir trustsandbox
     $ cd trustsandbox
    
  2. 好みのエディターを使ってdocker-compose.ymlというファイルを生成します。 たとえば vim を利用します。

     $ touch docker-compose.yml
     $ vim docker-compose.yml
    
  3. ファイルに以下の内容を追加します。

     version: "2"
     services:
       notaryserver:
         image: dockersecurity/notary_autobuilds:server-v0.5.1
         volumes:
           - notarycerts:/var/lib/notary/fixtures
         networks:
           - sandbox
         environment:
           - NOTARY_SERVER_STORAGE_TYPE=memory
           - NOTARY_SERVER_TRUST_SERVICE_TYPE=local
       sandboxregistry:
         image: registry:2.4.1
         networks:
           - sandbox
         container_name: sandboxregistry
       trustsandbox:
         image: docker:dind
         networks:
           - sandbox
         volumes:
           - notarycerts:/notarycerts
         privileged: true
         container_name: trustsandbox
         entrypoint: ""
         command: |-
             sh -c '
                 cp /notarycerts/root-ca.crt /usr/local/share/ca-certificates/root-ca.crt &&
                 update-ca-certificates &&
                 dockerd-entrypoint.sh --insecure-registry sandboxregistry:5000'
     volumes:
       notarycerts:
         external: false
     networks:
       sandbox:
         external: false
    
  4. ファイルを保存して閉じます。

  5. ローカルシステム上においてコンテナーを起動します。

     $ docker-compose up -d
    

    初回起動の際には docker-in-docker、Notary サーバー、レジストリの各イメージが Docker Hub からダウンロードされます。

サンドボックスで遊ぶ

設定がすべてできたので、trustsandboxコンテナー内に入って、Docker コンテントトラストの試しに使ってみます。 ホストマシンからtrustsandboxコンテナー内のシェルにアクセスします。

$ docker container exec -it trustsandbox sh
/ #

コンテントトラストの操作実行

trustsandboxコンテナー内から、イメージをプルしてみます。

  1. dockerイメージをダウンロードします。

     / # docker pull docker/trusttest
     docker pull docker/trusttest
     Using default tag: latest
     latest: Pulling from docker/trusttest
    
     b3dbab3810fc: Pull complete
     a9539b34a6ab: Pull complete
     Digest: sha256:d149ab53f8718e987c3a3024bb8aa0e2caadf6c0328f1d9d850b2a2a67f2819a
     Status: Downloaded newer image for docker/trusttest:latest
    
  2. サンドボックスレジストリにそのイメージをプッシュするために、タグづけを行ないます。

     / # docker tag docker/trusttest sandboxregistry:5000/test/trusttest:latest
    
  3. コンテントトラストを有効にします。

     / # export DOCKER_CONTENT_TRUST=1
    
  4. コンテントトラストサーバーを指定します。

     / # export DOCKER_CONTENT_TRUST_SERVER=https://notaryserver:4443
    

    この手順は、サンドボックスが独自のサーバーを利用しているために必要となるものです。 通常 Docker Hub を利用している場合、この手順は不要です。

  5. テストイメージをプルします。

     / # docker pull sandboxregistry:5000/test/trusttest
     Using default tag: latest
     Error: remote trust data does not exist for sandboxregistry:5000/test/trusttest: notaryserver:4443 does not have trust data for sandboxregistry:5000/test/trusttest
    

    エラーになりました。 そのコンテントがまだnotaryserverには存在していないからです。

  6. イメージをプッシュして、信頼された(trusted)イメージとしてサインします。

     / # docker push sandboxregistry:5000/test/trusttest:latest
     The push refers to a repository [sandboxregistry:5000/test/trusttest]
     5f70bf18a086: Pushed
     c22f7bc058a9: Pushed
     latest: digest: sha256:ebf59c538accdf160ef435f1a19938ab8c0d6bd96aef8d4ddd1b379edf15a926 size: 734
     Signing and pushing trust metadata
     You are about to create a new root signing key passphrase. This passphrase
     will be used to protect the most sensitive key in your signing system. Please
     choose a long, complex passphrase and be careful to keep the password and the
     key file itself secure and backed up. It is highly recommended that you use a
     password manager to generate the passphrase and keep it safe. There will be no
     way to recover this key. You can find the key in your config directory.
     Enter passphrase for new root key with ID 27ec255:
     Repeat passphrase for new root key with ID 27ec255:
     Enter passphrase for new repository key with ID 58233f9 (sandboxregistry:5000/test/trusttest):
     Repeat passphrase for new repository key with ID 58233f9 (sandboxregistry:5000/test/trusttest):
     Finished initializing "sandboxregistry:5000/test/trusttest"
     Successfully signed "sandboxregistry:5000/test/trusttest":latest
    

    レジストリに対してプッシュするのが初めてなので、Docker はルート鍵とリポジトリ鍵を生成します。 ここで鍵の暗号化を行うためのパスフレーズの入力を求められます。 これを行った後に再びプッシュすると、リポジトリに対するパスフレーズのみの入力が求められるだけです。 これにより鍵の復号化とイメージへのサインが可能となります。

  7. プッシュしたばかりのイメージをプルしてみます。

     / # docker pull sandboxregistry:5000/test/trusttest
     Using default tag: latest
     Pull (1 of 1): sandboxregistry:5000/test/trusttest:latest@sha256:ebf59c538accdf160ef435f1a19938ab8c0d6bd96aef8d4ddd1b379edf15a926
     sha256:ebf59c538accdf160ef435f1a19938ab8c0d6bd96aef8d4ddd1b379edf15a926: Pulling from test/trusttest
     Digest: sha256:ebf59c538accdf160ef435f1a19938ab8c0d6bd96aef8d4ddd1b379edf15a926
     Status: Downloaded newer image for sandboxregistry:5000/test/trusttest@sha256:ebf59c538accdf160ef435f1a19938ab8c0d6bd96aef8d4ddd1b379edf15a926
     Tagging sandboxregistry:5000/test/trusttest@sha256:ebf59c538accdf160ef435f1a19938ab8c0d6bd96aef8d4ddd1b379edf15a926 as sandboxregistry:5000/test/trusttest:latest
    

悪意あるイメージの確認

コンテントトラストが有効な状態において、壊れているデータをプルしようとしたら、どうなるでしょう。 この節においてはsandboxregistryにアクセスしてデータを改ざんし、その後にプルを試してみます。

  1. trustsandboxコンテナーとシェルアクセスをそのまま実行しておきます。

  2. ホストから対話を行うための端末画面を新たに開きます。 そしてsandboxregistryコンテナー内のシェルにアクセスします。

    $ docker container exec -it sandboxregistry bash
    root@65084fc6f047:/#
    
  3. プッシュしたtest/trusttestイメージのレイヤー一覧を表示します。

    root@65084fc6f047:/# ls -l /var/lib/registry/docker/registry/v2/repositories/test/trusttest/_layers/sha256
    total 12
    drwxr-xr-x 2 root root 4096 Jun 10 17:26 a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
    drwxr-xr-x 2 root root 4096 Jun 10 17:26 aac0c133338db2b18ff054943cee3267fe50c75cdee969aed88b1992539ed042
    drwxr-xr-x 2 root root 4096 Jun 10 17:26 cc7629d1331a7362b5e5126beb5bf15ca0bf67eb41eab994c719a45de53255cd
    
  4. このレイヤーの 1 つであるレジストリサーバーの保存ディレクトリに移動します。 (これは別ディレクトリにあります。)

    root@65084fc6f047:/# cd /var/lib/registry/docker/registry/v2/blobs/sha256/aa/aac0c133338db2b18ff054943cee3267fe50c75cdee969aed88b1992539ed042
    
  5. trusttestレイヤーに悪意のあるデータを追加します。

    root@65084fc6f047:/# echo "Malicious data" > data
    
  6. trustsandbox端末画面に戻ります。

  7. trusttestイメージの一覧を表示します。

    / # docker image ls | grep trusttest
    REPOSITORY                            TAG                 IMAGE ID            CREATED             SIZE
    docker/trusttest                      latest              cc7629d1331a        11 months ago       5.025 MB
    sandboxregistry:5000/test/trusttest   latest              cc7629d1331a        11 months ago       5.025 MB
    sandboxregistry:5000/test/trusttest   <none>              cc7629d1331a        11 months ago       5.025 MB
    
  8. ローカルのキャッシュからtrusttest:latestイメージを削除します。

    / # docker image rm -f cc7629d1331a
    Untagged: docker/trusttest:latest
    Untagged: sandboxregistry:5000/test/trusttest:latest
    Untagged: sandboxregistry:5000/test/trusttest@sha256:ebf59c538accdf160ef435f1a19938ab8c0d6bd96aef8d4ddd1b379edf15a926
    Deleted: sha256:cc7629d1331a7362b5e5126beb5bf15ca0bf67eb41eab994c719a45de53255cd
    Deleted: sha256:2a1f6535dc6816ffadcdbe20590045e6cbf048d63fd4cc753a684c9bc01abeea
    Deleted: sha256:c22f7bc058a9a8ffeb32989b5d3338787e73855bf224af7aa162823da015d44c
    

    Docker は、一度キャッシュされたイメージを再ダウンロードしません。 しかしここでは Docker がダウンロード実行するようにします。 レジストリからダウンロードされるイメージは改ざんされたものであり、不正なものであることからダウンロードは拒否されます。

  9. イメージを再びプルします。 キャッシュが存在しないため、レジストリからイメージがダウンロードされます。

    / # docker pull sandboxregistry:5000/test/trusttest
    Using default tag: latest
    Pull (1 of 1): sandboxregistry:5000/test/trusttest:latest@sha256:35d5bc26fd358da8320c137784fe590d8fcf9417263ef261653e8e1c7f15672e
    sha256:35d5bc26fd358da8320c137784fe590d8fcf9417263ef261653e8e1c7f15672e: Pulling from test/trusttest
    
    aac0c133338d: Retrying in 5 seconds
    a3ed95caeb02: Download complete
    error pulling image configuration: unexpected EOF
    

    プルは正常終了しません。 コンテントトラストシステムが、イメージ確認に失敗したからです。

サンドボックスでもっと遊ぶ

ここまでに手元のローカルシステムには、Docker コンテントトラストのサンドボックスができあがっています。 あれこれと自由に遊んでみて、どんな動きになるかを確認してください。 Docker に対してセキュリティに問題があることがわかったら、気がねなく security@docker.com へメールしてください。

サンドボックス環境のクリア

十分確認ができたら、起動したサービス、生成された匿名ボリュームなど一切を削除します。 Docker Compose ファイルを生成したディレクトリに入って、以下のコマンドを実行します。

    $ docker-compose down -v
trust, security, root, keys, repository, sandbox