Skip to main content

ロックファイルを使用したGitベースのGradleプロジェクトのセキュリティテストを改善

著者

Antonio Gomes

Blog illustrations Gradle

2020年12月7日

0 分で読めます

この1年、GitリポジトリからインポートしたGradleプロジェクトのテストについて、信頼性、精度、拡張性を高めるために改善を重ねてきました。

Gradleのロックファイルではなくマニフェストを解析するのは、終わりのない戦いであり、勝ち目はないと考えていました。build.gradleファイルを解析してGradleの複雑なモデルを解釈する方法は、さまざまな前提に依存する非決定的なアプローチです。1つまたは複数の依存関係の特定のバージョンや最大バージョンを厳密に指定する設定や、別ファイルでバージョンを定義している設定は、常に考慮されるとは限りません。また、この方法では、compile、test、runtimeなど、異なる設定コンテキストでGradleが解決して使用するものを明示的に宣言することはできません。こうした要因はすべて、結果の不正確さや不完全さにつながる可能性があります。

そのため、さまざまな依存関係管理ツールは、開発者が再現可能なビルドを実現できるよう、依存関係のロック機能を利用しています。たとえば、npm(package-lock.json)、yarn(yarn.lock)、RubyGems(Gemfile.lock)に加え、Gradleでもgradle.lockfileが利用できます。

Gradleのロックファイルを生成する方法

一般的なgradle.lockfileは次のようになります。

生成ファイルに関する警告と、バージョン2.12.1に固定されたLog4j APIおよびcoreのエントリを示すGradle依存関係ロックファイル。

ツリーやグラフ構造ではなく、使用中の直接依存関係と推移的依存関係をすべて含め、それぞれのバージョンと所属する設定を指定します。

単一プロジェクトまたは複数のサブプロジェクトを含むモノレポでロックファイルを生成するには、build.gradleを次のように編集します。

依存関係のロック設定と、依存関係ロックを解決して書き込むタスクが表示されたダークテーマのbuild.gradleエディター

ご覧のとおり、利用可能なすべての設定(annotationProcessor、compile、runtimeなど)を対象に、GradleでdependencyLockingを実行するよう指定しています。

コードを追加すると、Gradleがこちらの意図を理解できるようになります。

この例では設定は1つですが、通常は複数の設定があり、設定ごとに複数のロックファイルが生成される場合があります。信頼できる唯一の情報源を1つにするため、プロジェクトごとに1つのロックファイルを生成する方法を見ていきましょう。

ロックファイルを1つにまとめる

Gradle 6.0以降で利用できるGradle 7.0の機能プレビューを使うと、プロジェクトごとに1つのgradle.lockfileを生成し、さまざまな設定のロック状態をすべてまとめられます。この単一ロックファイル方式は、Gradle 7.0からデフォルトになります。

GradleのONE_LOCKFILE_PER_PROJECT機能プレビューが有効になったsettings.gradleを表示するコードエディター。

このルールを定義したら、次にターミナルでgradle resolveAndLockAll --write-locksコマンドを実行すると、以下のロックファイルが生成されます。

Visual Studio Codeに、Gradleプロジェクトと依存関係が記載されたgradle.lockfileが表示され、その横に`gradle resolveAndLockAll --write-locks`コマンドが表示されています。

上記から、次のことがわかります。

  • 各行は引き続き、GAV表記group:artifact:versionによる1つの依存関係を表します。

  • 各依存関係には、その依存関係が属する設定の一覧が記載されています。

  • 最後のempty行には、依存関係のない利用可能な設定の一覧が記載されています。

Gradleのロックファイルで何が便利になるのか

依存関係のロック機能を使うと、動的な依存関係バージョン(例:1.+や[1.0,2.0))を使用している場合に、管理できない推移的依存関係によって予期せぬエラーが発生するのを防げます。これは、いつの間にか発生し得るよくあるケースです。

ここでは、動的バージョンを指定した依存関係を含む小さなbuild.gradleファイルを例にします。

Java、Maven Central、Log4jアノテーションプロセッサの依存関係を含むGradleビルドファイルを表示したダークテーマのコードエディター。

gradle -q dependenciesコマンドを実行しても、出力は2.11でも2.14でもありません。以下の画像のとおり、Gradleは依存関係を2.13に解決しました。

annotationProcessor構成のGradle依存関係解決を示すターミナル出力。Log4j coreおよびAPIのバージョン2.13.3を含む。

ロックファイルに記録されている依存関係を確認すると、コマンドの出力がこのアプリケーションのロックファイルの状態と一致することを確認できます。

Gradleの依存関係ロックファイルのスクリーンショット。手動で編集するとビルドが壊れる可能性があるという警告と、その下にLog4jの依存関係エントリが表示されています。

それでは、結果を見てみましょう。

ここでは、動的バージョンの依存関係を含むbuild.gradleファイルを解析できなかったケースを紹介します。gradle.lockfileを使った場合の結果と比較してみましょう。

unparsed-gradle-repoのbuild.gradleファイルと依存関係タブを表示したSnykプロジェクトダッシュボード

gradle.lockfileを使った場合、結果は大幅に向上しています。前のケースでは0件だった依存関係を、直接・推移的なものを含めて24件特定し、合計33件の問題を報告できました。

build.gradleプロジェクトの依存関係ビュー。Gradleのロックファイルテストと、一覧表示されたパッケージの脆弱性およびライセンスの問題を表示

Gradleの依存関係ロックについて詳しく知りたい方は、公式ドキュメントをご覧ください。

このSnykの機能をぜひご活用ください。まだSnykアカウントをお持ちでない方は、無料で登録できます。

CTFを始めよう

オンデマンドのバーチャル入門ワークショップで、CTFチャレンジの解き方を学びましょう。

続きを読む

feature insights context
Blog

自律型攻撃はすでに始まっている。防御もそのスピードに追いつかなければならない。

自律型攻撃者によって、防御に使える時間は短くなっています。継続的な検出、修復、検証、予防で、セキュリティチームが攻撃に歩調を合わせる方法をご紹介します。

feature insights context
Blog

予防は、本質的に解決済みの問題なのでしょうか?

エージェントが生成するコードの予防策はアーキテクチャ上解決されていますが、開発を遅らせることなくセキュリティを守る制御を選ぶことが、依然として課題です。

Live Stream

修正エージェントをわかりやすく解説:見つけるより直すことが重要な理由

SnykのRemediation Agentが、セキュリティインテリジェンス、破壊可能性分析、検証を活用して、脆弱性をマージ可能なプルリクエストに変える仕組みをご覧ください。