Skip to main content

Javaアプリケーション向けにGitHub ActionsでセキュアなCI/CDパイプラインを構築する

2022年6月27日

0 分で読めます

GitHub Actionsにより、GitHubプロジェクト向けのセキュアな継続的インテグレーション/継続的デリバリー(CI/CD)パイプラインを、これまで以上に簡単に構築できるようになりました。CI/CDパイプラインとGitHubリポジトリを統合することで、GitHub Actionsを使ってビルド、テスト、デプロイのパイプラインを自動化できます。リポジトリへのプルリクエストごとにビルドとテストを実行するワークフローや、マージ済みのプルリクエストを本番環境にデプロイするワークフローを作成できます。さらに、SnykをGitHub CI/CDに統合すれば、本番環境にリリースする前のビルド工程でセキュリティスキャンを自動化できます。

Java向けGitHub Actions CIパイプラインを設定する

GitHub Actionsのワークフローは、.github/workflowsフォルダに保存されるYAMLファイルです。ワークフローがまだない場合や、新しく追加する場合は、Actions、New workflowの順に選択します。

Workflowsセクション、「New workflow」ボタン、「All workflows」が選択されたGitHub Actionsのページ。

このJava Spring Bootプロジェクトでは、次のようにMavenを使ってCIパイプラインを作成しました。

name: Java CI with Maven

on:
 push:
   branches: [ master ]
 pull_request:
   branches: [ master ]
 workflow_dispatch:

jobs:
 build:

   runs-on: ubuntu-latest

   steps:
   - uses: actions/checkout@v2
   - name: Set up JDK 17
     uses: actions/setup-java@v1
     with:
       java-version: 17
   - name: Build with Maven
     run: mvn -B package --file pom.xml

このアクションは、masterブランチへのプッシュまたはプルリクエストのたびに実行されます。Ubuntuをベースにリポジトリをチェックアウトし、Java 17とMavenを使用するGitHub Actionのsetup-javaで、Javaのjarファイルをビルドします。構文に慣れていれば、このワークフローは比較的シンプルです。さまざまな活用方法について詳しくは、GitHub Actionsのドキュメントをご覧ください。

GitHub CI/CDにSnykを統合する

Snykを使うと、新しいJavaプロジェクトにセキュリティテストを統合できます。主な方法は2つありますが、まずは次の2点を準備しましょう。Snykアカウントにログインします。まだアカウントをお持ちでない場合は、無料で作成してください。次に、APIキーをGitHubリポジトリのシークレットSNYK_TOKENとして設定します。

方法1:GitHub ActionのビルドステップにSnyk CLIを統合する

Snyk CLIを使うと、現在のビルド内でセキュリティスキャンを自動実行できます。以下の手順に従い、Build with Mavenの後にいくつかのステップを追加して、設定を始めましょう。

 - name: Set up Node 14
   uses: actions/setup-node@v3
   with:
     node-version: 14
 - name: install Snyk CLI
   run: npm install -g snyk
 - name: run Snyk Open Source Test
   run: snyk test
 - name: run Snyk Code Test
   run: snyk code test

NodeJSバージョン14をセットアップし、npmでSnyk CLIをダウンロードします。次に、Snyk Open Sourceで依存関係を分析し、Snyk Codeで独自のコードに脆弱性がないかスキャンします。

次に、APIキーを含む環境変数としてSNYK_TOKENを宣言します。先ほど設定したシークレットSNYK_TOKENを参照するか、GitHub Actionのコード例をそのまま再利用できます。

env:
 SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}

この方法の利点は、アプリケーションのコンパイルとビルドが一度で済むことです。大規模なアプリケーションをビルドする際に、多くの時間を節約できます。一方、各ステップは順番に実行されるため、後半のステップで失敗すると効率が悪くなる場合があります。

方法2:Snykの定義済みGitHub Actionsを使ってCI/CDパイプラインを作成する

Snykは、プロジェクトの脆弱性をチェックするGitHub Actionsを一式提供しています。必要なアクションは、プログラミング言語やビルドツールによって異なります。ここでは、Javaプロジェクト向けに、以下のMavenベースのGitHub Actionを使います。

定義済みのアクションを使えば、アプリケーションのビルドに必要な前提条件が整い、コードのスキャンには最新のCLIバージョンが使われます。アプリケーションを何度か再ビルドすることになるものの、各アクションを個別に並行実行できる点は、この方法の大きなメリットです。

まず、依存関係をスキャンしましょう。Snykアカウントはすでに作成済みで、APIキーはSNYK_TOKENという名前のシークレットとして保存されています。そこで、ビルドジョブにステップを追加する代わりに、opensource-securityという新しいジョブを作成します。

opensource-security:
   runs-on: ubuntu-latest
   steps:
     - uses: actions/checkout@master
     - name: Run Snyk to check for vulnerabilities
       uses: snyk/actions/maven@master
       env:
         SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}

ドキュメントによると、デフォルトのコマンドはtestです。追加の設定をしなくても、依存関係に既知の脆弱性がないかアプリケーションをスキャンします。ネストされたプロジェクトに対応するために--all-projectsのような特定のCLI引数を設定する場合は、withキーワードを使い、プロパティにargsを指定します。

args、command、JSON出力に関するSnyk Maven Actionのプロパティ、デフォルト値、説明をまとめた表。

Snykで依存関係をスキャンしている間に、GitHub ActionでJavaコードの脆弱性もチェックしましょう。前の手順を繰り返して、そのための3つ目のジョブを設定し、commandプロパティにcode testを指定します。

 code-security:
   runs-on: ubuntu-latest
   steps:
     - uses: actions/checkout@master
     - name: Run Snyk to check for vulnerabilities
       uses: snyk/actions/maven@master
       env:
         SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
       with:
         command: code test

3つのジョブはすべて並行して実行されます。多くの場合、こちらのほうが効率的です。

GitHub CI/CDにセキュアな継続的デリバリーを追加する

次に、GitHub CI/CDのデプロイ、つまりデリバリーの部分を見ていきましょう。ビルドとテストが完了したら、パッケージをGitHubに公開します。ここでは、JavaプロジェクトでMaven Release Pluginを使います。

ビルドジョブと2つのセキュリティジョブがすべて正常に完了した場合にのみパッケージをリリースしたいため、リリースに必要なジョブの一覧をneedsプロパティに追加します。これにより、パッケージが完全にビルドされ、安全性が確認される前にデプロイされることを防げます。

release:
   needs: [opensource-security, code-security, build]
   runs-on: ubuntu-latest
   steps:
     - uses: actions/checkout@v2
     - name: Set up JDK 17
       uses: actions/setup-java@v1
       with:
         java-version: 17
     - name: Set Git user
       run: |
         git config user.email "ghactions@brianvermeer.nl"
         git config user.name "GitHub Actions"
     - name: Publish JAR
       run: mvn -B release:prepare release:perform -DskipTests
       env:
         GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Mavenのコマンドrelease:prepareとrelease:performは、リリースのバージョン番号が正しいことを確認し、実際にGitHubリポジトリへ公開します。Mavenで処理するため、pom.xmlファイルを次のように設定します。

  <scm>
       <developerConnection>scm:git:https://github.com/bmvermeer/ghaction-example.git</developerConnection>
       <tag>HEAD</tag>
   </scm>
   <distributionManagement>
       <repository>
           <id>github</id>
           <name>GitHub</name>
           <url>https://maven.pkg.github.com/bmvermeer/ghaction-example</url>
       </repository>
   </distributionManagement>

リリースしたばかりのアプリケーションに脆弱性がなくても、その状態がずっと続くとは限りません。さまざまな場所で新たな脆弱性が見つかる可能性があるため、アプリケーションのデプロイ後もコードと依存関係を継続的に監視することが重要です。

開発中のスキャンに加えて、Snykを使ってデプロイ後も依存関係を監視できます。リリースが完了したら、Snykの定義済みアクションを再び使い、今度はcommandプロパティにmonitorを指定します。

 opensource-monitor:
   needs: [release]
   runs-on: ubuntu-latest
   steps:
     - uses: actions/checkout@master
     - name: Run Snyk to check for vulnerabilities
       uses: snyk/actions/maven@master
       env:
         SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
       with:
         command: monitor

これにより、リリース後は変化しない依存関係ツリーがSnykに送信され、監視されます。SnykのUIでプロジェクトを確認できるようになり、使用中の依存関係に新たな脆弱性が見つかった場合は自動通知を受け取れます。公開したJavaプロジェクトに脆弱性がない状態を維持できます。

「nl.brianvermeer.snyk:ghaction-example」のプロジェクトダッシュボード。問題件数はすべて0件で、「レポートを表示」リンクが表示されている

GitHub Actionsにセキュリティを統合する

GitHub Actionsを使えば、GitHubプロジェクトのCI/CDパイプラインを簡単に作成できます。さらにSnykのアクションを使うことで、あらゆるアプリケーションに複数のレベルでセキュリティスキャンを簡単に統合できます。

本日作成したパイプラインを、GitHubでは次の図のように可視化できます。ジョブによっては並行して実行され、ほかのジョブの正常完了を待つものもあります。プロジェクト全体の例は、こちらのGitHubリポジトリでご確認ください。

pushをトリガーに、ビルド、セキュリティ、リリース、オープンソース監視の各ジョブが成功したGitHub Actionsワークフロー

今回はSnyk CodeとSnyk Open Sourceを使って、Javaのソースコードとパイプラインの依存関係をスキャンしました。さらに、Snyk ContainerでDockerファイルを、Snyk IaCでKubernetesファイルをスキャンすることもできます。

Snyk GitHub Actionsを使えば、GitHub Actionsのワークフローにスキャンを自動的に追加できます。プロジェクトに最適なアクションを組み合わせて、コードを今も将来も安全に保ちましょう。

キャプチャー・ザ・フラッグを始めよう

オンデマンドのバーチャル入門ワークショップを視聴して、キャプチャー・ザ・フラッグの課題の解き方を学びましょう。