Codefresh + Snyk = 迅速かつ安全なリリース
Antoine Arlaud
2018年12月11日
0 分で読めます現代のソフトウェア開発とは、コードを書くことです。ビルドでもリリースでもなく、開発です。コードを書き、マージし、ビルドして、リリースする。その流れの両側、つまりコードと自動化された工程の間にあるリポジトリの境界で、テストすることが重要です。変更をスムーズにパイプラインへ流すため、マージ前にテストすることを目指します。
パイプラインは、開発者が変更を初めてテストするためのものではありません。新しいリリースの出荷基準をコードが満たしていない場合に、それを止めるためのものです。ロケットが発射台にある間に行う最終チェックリストのようなものです。理想を言えば、パイプラインの実行中に修正が必要になるのは、すでに手遅れに近い状態です。開発中やマージ中に修正しておきたいところです。とはいえ、いつも理想どおりとは限りません。一般的な目安として、変更は開発段階で解決するよう努めましょう。
そのためには、できるだけ早い段階で、たとえば自分のマシンやコードリポジトリでテストし、フィードバックを得ましょう。もちろん、必要なテストを組み込んだパイプラインをまず構築する必要があります。そこで役立つのがCodefreshです。コンテナやKubernetesへのデプロイを通じてアプリをリリースするための、自動化されたパイプラインを構築できます。
これらのテストには、セキュリティが必須です。これは絶対に欠かせません。納得できない場合は、この記事を読むのをやめて、セキュリティチームや同僚、仲間、ミートアップの参加者、あるいは私たちに話を聞いてみてください。なぜ重要なのか、それぞれが説明します……ここで登場するのがSnykです。
これから5~10分で、Codefreshを使ってこのパイプラインを構築し、Snykによるセキュリティテストを組み込みます。テストは手短に済ませ、コーディングや機能のリリースに戻りましょう。CodefreshとSnykにはどちらも無料プランがあるため、費用をかけずに一緒に進められます。Codefreshのメンバーとウェビナーも行いました。動画をご覧になりたい方は、こちらからご確認ください。
サンプルのNodeアプリを作成し、DockerコンテナにしてDocker Hubにプッシュします。そこから別のパイプラインが起動し、出力をKubernetesアプリケーションとしてデプロイします。Codefreshはリポジトリにマージされた変更を検知してDockerイメージをビルドし、Snykのテストを実行して、生成された成果物を安全にリリースできるか判断します。
まず、アプリケーションとコンテナについて簡単に確認しましょう。コンテナインフラストラクチャ上で動作する一般的なアプリケーションの構成を、以下に示します。
パイプラインはGitHubリポジトリからアプリケーションのソースコードを取得し、Dockerコンテナにビルドします。Docker Hubにプッシュする前に、アプリケーションの依存関係とOSの依存関係の両方をテストし、セキュリティ上の問題がないか確認します。脆弱性がなければ、処理は問題なく進みます。

それでは、このパイプラインを実際に作ってみましょう。
1. CodefreshとSnyk.ioのアカウントを新規作成します。
2. Codefreshにリポジトリを追加します。
![[Codefreshのリポジトリダッシュボード。All、Private、Publicのフィルターと「Add New Repository」パネルが表示されている]](https://res.cloudinary.com/snyk/image/upload/f_auto,w_2560,q_auto/f_auto/q_auto/v1541595803/image30.png)
このデモでは、https://github.com/snyk-playground/codefresh-pipeline-snyk-app-docker-scanリポジトリを使います。

3. 次に、ビルド方法としてStart from templateを選択します。

ここではNodeJSアプリケーションを使います。これを選択して「次へ」をクリックしましょう。

今回は標準テンプレートを使います。必要に応じて自由に調整してください。
![Node.jsのセットアップ、依存関係のインストール、アプリケーションのコピー、[作成]ボタンを含む、編集可能なDockerfileの設定プレビュー](https://res.cloudinary.com/snyk/image/upload/f_auto,w_2560,q_auto/f_auto/q_auto/v1541595771/image22.png)
これで新しいリポジトリが追加されました。次はパイプラインを定義しましょう。

4. Create pipelineをクリックして、リポジトリをビルドします。
まず、必要な環境変数を定義します。シークレットは必ず暗号化しましょう。「SNYK_TOKEN」という新しい変数を追加します。

値はhttps://app.snyk.io/accountで確認できます。

その画面で、SNYK_ORGという変数も追加し、値にはURLの末尾部分を設定します。https://app.snyk.io/org/私の場合は、aarlaud-snyk-demoです。

Snykの設定は以上です。
次に、Codefreshレジストリからイメージを取得し、最終イメージをDocker Hubにプッシュするため、いくつか環境変数を追加します。
Codefreshがプライベートイメージレジストリにアクセスできるよう、次の変数を追加します(詳しくはhttps://codefresh.io/docs/docs/docker-registries/codefresh-registry/#generate-cfcr-login-tokenをご覧ください)。
CF_USER_NAME- Codefreshのユーザー名(例:私の場合はaarlaud)CFCR_ACCOUNT- 私の場合はユーザー名と同じaarlaudCFCR_LOGIN_TOKEN- https://g.codefresh.io/user/settingsでトークンを生成し、暗号化します。
Docker Hubとの連携では、最終的なDockerイメージのプッシュ先となるイメージ名を、次の変数に保存します。
IMAGE_NAME - 例:私の場合はaarlaudsnyk/trainingapp
変数は次のようになります。

最後に、Codefreshの「Integrations」セクションでDockerの設定を行います。

Docker Hubのアカウント(https://hub.docker.com/)が必要です。まだお持ちでない場合は作成し、Dockerレジストリとのインテグレーションを設定してください。

準備完了です。トリガーを確認すると、コミットごとにビルドが実行されることがわかります。このパイプラインはmasterブランチを基に作成したため、masterへのコミットだけがビルドをトリガーします。今のところはこれで十分です。ほかのブランチや環境向けに変更または複製するのも簡単です。

ワークフローを見ると、先ほど確認したDockerテンプレートが使われていることがわかります。いずれは、これをDockerfileに移したほうがよいかもしれません。

それでは、先に進む前に、期待どおりに動作するかビルドしてみましょう。

ビルドが開始されます。

アプリのビルドが完了しました。

Codefreshはこのイメージを、Codefreshアカウント内のプライベートDockerレジストリに自動的に保存します。「Images」セクションを見ると、ビルドしたばかりのDockerイメージを確認できます。

さらに、このイメージをDocker Hubにプッシュする前に、セキュリティ上の脆弱性がないことを確認したいと思います。
5. パイプラインに戻り、依存関係にセキュリティ上の脆弱性がないかテストするため、snyk testコマンドを追加します。
まずSnykをインストールし、重大度の高い問題があればビルドを失敗させるシンプルなコマンドで実行します。ワークフローを十分に把握するまでは、低または中程度の問題では失敗させないようにします。

保存してから再度ビルドを実行します。パイプラインに「Running Unit Tests」というステップが表示されます。何らかの問題があるため、おそらく失敗するでしょう。修正は後で行います。次に、アプリのOSコンポーネントについて、Dockerイメージ自体をスキャンしましょう。
Codefreshがアプリをビルドすると、イメージはプライベートレジストリにプッシュされます。そのイメージを取得してユニットテストを実行します。同じ手順を繰り返し、Dockerイメージを対象に2つ目のsnyk testを実行します。
そのためにCodefreshのコンポジションを使います。詳細はドキュメントをご覧ください。ここでは機能を増やすため、yamlに切り替えます。

yamlモードで、「version: ‘1.0’」の直後に次の3行を追加します。
この変更は見た目だけのもので、UIにバケットのようなセクションを作成します。既存のRunningUnitTestsセクションを少し変更し、SnykAppScanセクションを使うようにしましょう。タイトルを変更するだけでなく、UI上の適切なバケットに配置するためのstageセクションを追加し、環境変数を直接渡すことで、いくつかの部分を簡潔にしています。
次に、Dockerイメージのスキャン部分としてSnykScanImageセクションを追加します。ここでもStageはscanで、アプリケーションの依存関係をスキャンするステージと同じバケットに入ります。コンポジションのドキュメントにあるように、複数のサービスを実行してテストできます。
この場合、BuildingDockerImageはビルドステージのイメージ出力です。このイメージを外部からテストしたいので、以前ビルドした別のイメージaarlaudsnyk/snyk-container-scan-dockerを実行するスキャンサービスと組み合わせます。このイメージには、SnykでDockerイメージをテストするために必要な要素がまとめられています。ソースはこちらで確認できます。
上記のyamlファイルで注目すべきセクションは次のとおりです。
このイメージを使ってPythonコマンドを実行します。主に次の2つの処理を行います。
テスト対象のイメージをローカルに取得する
「snyk test --docker 」を実行する
このイメージは、次の環境変数が定義されている場合にCodefreshのレジストリからイメージを取得するように作られています。
CFCR_ACCOUNT
CF_USER_NAME
CFCR_LOGIN_TOKEN
これにより、ビルド直後のイメージをテストできます。そうでない場合は、代わりにDocker Hubからイメージを取得しようとします。
最後に、テストに合格した場合にこのイメージをプッシュできるよう、末尾にDocker Hubレジストリへのプッシュ処理を追加しましょう。
特別なことはありません。インテグレーションが設定されていれば、Codefreshを使って簡単にDocker Hubへプッシュできます(少し前に設定しました)。スキャンテストと区別するため、stageが「promote」になっている点に注目してください。
全体をまとめると、次のようになります。
6. まずは基準値を得るため、ビルドしてみましょう。組織の状態はかなり良好です。

少し待つと、次の結果が表示されます。

おっと、アプリに問題があるようです。セキュリティ上の問題があるものをリリースする前に、パイプラインが安全に停止しました。出力に示された修正手順に従って解決しましょう。package.jsonでqsパッケージをバージョン6.0.4に上げれば解決します。
もう一度実行しましょう。

qsの脆弱性は解消しました。やりました!ただし、今度はDockerイメージのOS依存関係に問題があるようです。

修正方法としてイメージのバージョンを上げることが示されています(Dockerセクションのsnyk.io/docsをご確認ください)。それではnode:10-alpineに更新して、もう一度試しましょう。

保存 → ビルド → ビルド中は腕立て伏せ!

やりました!これで新しいベースラインができ、アプリとコンテナをDocker Hubにリリースする、完全に機能するパイプラインが完成しました。
これでコーディングに戻れます。マージ前にsnyk testを実行し、変更をテストするか、SnykのGitHub PRインテグレーションを使って変更をテストしましょう。あとは変更が自動的にリリースされます。おまけに、最新機能も追加されています!
snyk monitorを使って、依存関係を継続的に監視しましょう。プロジェクトの面倒を見続けたい人はいません。snyk monitorを実行すれば、プロジェクトやDockerイメージの依存関係に新たな脆弱性が公表されたとき、Snykが自動的に通知します。snyk testのセクションの後にsnyk monitorを追加するだけです。

監視用スナップショットのURLが出力に表示されます。

snyk testに合格すれば(既知の問題がなければ)、Dockerの処理も自動的に行われます。監視用スナップショットへのリンクも表示されます。

Snyk組織のSnyk UIで、監視対象のプロジェクトを確認することもできます。

リポジトリのバッジをクリックして、Codefreshのパイプラインをご覧ください(https://github.com/snyk-playground/codefresh-pipeline-snyk-app-docker-scan)。
以上です!安全な開発を!
CTFを始めよう
オンデマンドのバーチャル入門ワークショップで、CTFチャレンジの解き方を学びましょう。



