LoginSignup
4

More than 3 years have passed since last update.

DockleやTrivyをCircle CIのDocker Orbと組み合わせてセキュアなコンテナを継続的に作るっ!

Posted at

概要

Circle CIの「circleci/docker」というOrbを使って、以下を実践してみました!ʕ◔ϖ◔ʔ

  • コンテナのビルド
  • DockleTrivyを使って、ビルドしたコンテナイメージをチェック
    • OSや依存パッケージが脆弱性を含んでいないかをチェック
    • ベストプラクティスに準拠したセキュアなコンテナになっているかをチェック
  • 上記チェック結果がPassなら、docker hubにコンテナイメージを登録

上述のサンプルを紹介しつつ、設定ファイル.circleci/config.ymlを書く際のポイントなどを説明します。この記事を読み終わった時に、あなたにとってセキュアなコンテナのビルドがより身近なものになっていたら嬉しいなぁと思います!

ゆっくり見ていってね!(o´・з・)o

読んでほしい人

  • DockleTrivyといったコンテナチェックツールに興味がある方
  • CIでのコンテナチェックに興味がある方
  • CircleCIのOrbという仕組みに興味がある方
  • CircleCIを含むCI/CDに知見がある方(マサカリ、お願いします!m(_ _)m)

etc..

作ったもの

まずは、実践した内容の雰囲気を掴んでいただくため、実際に作ったサンプルをごらんください。٩(ˊᗜˋ*)و

Dockle on CircleCI

Trivy on CircleCI

準備

ログイン

まずはCircleCIdocker hubにログインできるようにしましょう。

リントツールを使って手元でチェック

ケモケモ「よっしゃ出来た!CircleCIさん、がっつりビルド頼むわ!!」
CircleCI「記法がinvalidやで。Failやで。」
スクリーンショット 2020-02-20 20.45.16.png
ケモケモ「Oh... (´・ω・`)」

せっかく書いた.circleci/config.ymlが、記法の間違いなどビルドできないと辛いですね。そういった問題を未然に防ぐため、コミットする前にcircleciツールでチェックしちゃいましょうヽ(=´▽`=)ノ。

まずはインストール!

以下のコマンドで.circleci/config.ymlが動きそうかチェックします。

circleci config validate

詳しくは「CircleCI のコンフィグのバリデーション」をご覧ください。

Dockleをインストール

CIで継続的に実行するのが本記事の目的ではありますが、便利なツールですし手元でコミット前にチェックするのは良い習慣ですのでインストールしましょう。

公式の Installation で各種プラットフォーム向けのインストール方法が書かれているので、好きな方法でインストールします。

使い方も簡単で、チェックしたいコンテナイメージの名前を指定して実行するだけです。めちゃシンプル!

$ dockle {YOUR_IMAGE_NAME}

チェックしてくれるポイントは Checkpoint Summary にまとまってます。

Trivyをインストール

こちらもやはり手元で実行できるようにインストールしましょう。先のDockle同様にGo言語製のツールですので、非常に多くのプラットフォームで実行可能です。

公式の Installation を見ながらインストールします。
簡単に使えます。シンプルです。

$ trivy {YOUR_IMAGE_NAME}

実行結果のサンプルが Examples に多数掲載されているのでチェキです。:eyes:

Orb選び

この記事のサブテーマとしてCircle CIのOrbを積極的に使います。まずは、目的にあったOrbを CircleCI Orb Registry で探してみましょう。

スクリーンショット 2020-02-20 23.10.33.png

今回はコンテナのビルドとプッシュをしたいのでdockerで検索してみました(上図)。CERTIFIEDマークのcircleci/dockerを使ってみましょう。

Orb: circleci/docker

https://circleci.com/orbs/registry/orb/circleci/docker
スクリーンショット 2020-02-20 23.13.19.png

Orbの説明ページでは、Orbの機能を呼び出すための方法について以下の情報が記載されています。

  • 冒頭のクイックスタートガイドで、.circleci/config.ymlにどう書けば使い始められるか説明してる
  • 左のカラムに並ぶUsage Examplesで、需要が高そうな使い方に対してjobやworkflowの書き方を実例と共に説明してる
  • 左のカラムに並ぶJobsで、job名やパラメータの指定方法を説明してる
  • 左のカラムに並ぶCommandsで、command名やパラメータの指定方法を説明してる

クイックスタートガイド

以下を書くだけでOrbの力を使えるようになります。パネェ₍₍ (ง ˙ω˙)ว ⁾⁾

version: 2.1

orbs:
  docker: circleci/docker@0.5.20

Usage Examples

比較的シンプルな、以下のサンプルが参考になります。

  • standard-build-and-push
    • Orbの定義済みのjobであるpublishを使ったサンプル。
    • コンテナのbuildとpushをまとめて実施してくれる。便利。
  • build-push-digest
    • Orbの定義済みのcommandであるcheckbuildを使ったサンプル。
    • docker.hubへのログインチェックや、build、pushなど、順を追って実施したい時に参考になる。

今回は、上記build-push-digestをベースに作っていきます。

Executor

Orbの実態は、CI/CDにすぐ組み込んで便利に使えるようCircleCIやパートナー企業が作ってくれたカスタムコンテナイメージです。

では、このcircleci/dockerのベースイメージはどんなものなのでしょう?今回のサンプルで使う「Executor - docker」でSourceを確認することでわかります。

スクリーンショット 2020-02-21 0.15.53.png

circleci/python 」を使っているようです。このイメージを作るDockerfileは「 CircleCI-Public / circleci-dockerfiles 」にあります。追加で依存パッケージなどを使いたい場合、コンテナの素性が関係してくる場合があるので心の片隅に置いておきます。

書き始めよう

かなり入念に、CircleCIの設定を書くための準備とOrbの機能を確認しました。そろそろ実際にconfig.ymlを書き始めましょう。

まずはOrbだけで書いてみる

まずはOrbの機能だけでCIの骨子を組み立てましょう。Orbの各種機能を呼び出す方法を整理すると、以下のような感じです。

上述のサンプルなどをベースにザクッと書いてみたのが以下です。

version: 2.1

orbs:
  docker: circleci/docker@0.5.20

jobs:
  # ビルドしたりテストしたりするジョブ。
  build-and-test:
    executor: docker/docker
    steps:
      - setup_remote_docker
      - checkout
      # コンテナレジストリにログイン可能かチェックします。
      - docker/check

      # コンテナをビルドします。
      - docker/build:
          image: ${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}

      # ! DockleとTrivyを使ったコンテナのtestを書く予定地です。

workflows:
  # ビルドしたりテストしたり、masterにマージされたらlatestコンテナを更新するワークフロー。
  build-and-deploy:
    jobs:
      # masterを含む全てのブランチで実行するジョブ。
      - build-and-test

      # masterでだけ実行されるジョブ。latestのコンテナイメージをレジストリに登録、更新する。
      - docker/publish:
          image: ${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}
          tag: 'latest'
          requires:
            - build-and-test
          filters:
            branches:
              only: master

  # gitのタグがついたらビルドとテストをして、タグ付きのコンテナをレジストリに登録するワークフロー。
  deploy-tags:
    jobs:
      - build-and-test:
          filters:
            branches:
              ignore: /.*/
            tags:
              only: /^v.*/
      - docker/publish:
          image: ${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}
          tag: ${CIRCLE_TAG}
          # 「build-and-test」のジョブが成功した時だけ、このジョブを実行するよ。
          requires:
            - build-and-test
          filters:
            branches:
              ignore: /.*/
            tags:
              only: /^v.*/

なお、commandのdocker/checkは、イメージをpushするコンテナレジストリ(標準でdocker hub)にログイン可能かをチェックしてくれます。ログイン情報は、あらかじめ環境変数としてCircle CIに登録しておきます。ジョブの実行結果のログでは、ちゃんと伏せ字になりますので安心です。詳しくは プロジェクト内で環境変数を設定する を参照してください。

DockleTrivyをCIに組み込む

実はDockleTrivyも、どちらも公式でCircleCIの実行サンプルを公開しています。

これらのサンプルを上述のOrbベースのCI設定に組み込みます。その際、ツールのインストールを行う箇所がそのままでは使えません。circleci/dockerのOrbとは、executorとして使っているコンテナイメージのOSが異なるためです。それらの違いも踏まえて実際に動作することを確認した設定内容が以下です。

version: 2.1

orbs:
  docker: circleci/docker@0.5.20

jobs:
  build-and-test:
    executor: docker/docker
    steps:
      - setup_remote_docker
      - checkout
      - docker/check
      - docker/build:
          image: ${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}

      # (追加)Dockleをインストールしてスキャン実行!
      - run:
          name: Install dockle
          command: |
             VERSION=$(
               curl --silent "https://api.github.com/repos/goodwithtech/dockle/releases/latest" | \
               grep '"tag_name":' | \
               sed -E 's/.*"v([^"]+)".*/\1/'
             )
             wget https://github.com/goodwithtech/dockle/releases/download/v${VERSION}/dockle_${VERSION}_Linux-64bit.tar.gz
             tar zxvf dockle_${VERSION}_Linux-64bit.tar.gz
             sudo mv dockle /usr/local/bin
      - run:
          name: Scan the image with dockle
          command: dockle --exit-code 1 ${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}:${CIRCLE_SHA1}

      # (追加)Trivyをインストールしてスキャン実行!
      - run:
          name: Install trivy
          command: |
            VERSION=$(
                curl --silent "https://api.github.com/repos/aquasecurity/trivy/releases/latest" | \
                grep '"tag_name":' | \
                sed -E 's/.*"v([^"]+)".*/\1/'
            )
            wget https://github.com/aquasecurity/trivy/releases/download/v${VERSION}/trivy_${VERSION}_Linux-64bit.tar.gz
            tar zxvf trivy_${VERSION}_Linux-64bit.tar.gz
            sudo mv trivy /usr/local/bin
      - run:
          name: Scan the image with trivy
          command: trivy --exit-code 0 --no-progress ${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}:${CIRCLE_SHA1}

workflows:
  build-and-deploy:
    jobs:
      - build-and-test
(後略)

実際に動かしてみるとこんな感じになります。

スクリーンショット 2020-02-27 21.36.15.png

良いですね、バッチリチェックできています。:tada:
DockleTrivy両方を使ったconfig.ymlの完成形は こちら を御覧ください。

まとめ

CIを使ったコンテナの作成とレジストリへの登録は、Kubernetesクラスタへのデプロイを想定したGitOpsなどで必須となる重要なポイントだと感じています。これらの技術をProduction環境へ適用することを考えるならば、使用するコンテナ自体の脆弱性チェックはもはや避けては通れない課題です。

今回は、極力余計なものは省いて「いかに楽して脆弱性チェックの機構をCIに取り込むか」という点を意識して実践したつもりです。本記事はCircle CIを使った例でしたが、DockleTrivyの公式ドキュメントにもあるように Travis CI など多数のCI環境で同様の「コンテナ脆弱性チェック」の仕組みを実現することが可能です。

この記事が、コンテナのセキュリティを意識し始めた私のような方にとって、少しでも役立つものになっていることを願っていますʕ◔ϖ◔ʔ

おまけ

Circle CI関連の資料ばかりなのですが、有益だなぁと思ったリンクを載っけときます(ΦωΦ)

  • セキュリティ機能

    • Circle CIのセキュリティに関する取り組みについて書いてあります。セキュリティを懸念する上司やチームメンバーに説明する際の資料として良さそう。
  • 定義済み環境変数

    • Circle CIのジョブで使える定義済みの環境変数。リポジトリ名やタグ名など、比較的よく使いそうな情報が多数揃ってる。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4