Skip to main content

CIシステムでのCodeQL CLIの設定

継続的インテグレーションシステムをCodeQL CLIを実行するように設定し、CodeQL分析を行い、code scanningアラートとして表示させるために結果をGitHub Enterprise Cloudにアップロードできます。

Code scanning は、GitHub.com のすべてのパブリック リポジトリに使用できます。 Organization によって所有されるプライベート リポジトリで code scanning を使うには、GitHub Advanced Security のライセンスが必要です。 詳細については、「GitHub Advanced Security について」を参照してください。

CodeQL CLIでのCode scanningの結果の生成について

CIシステム内のサーバーでCodeQL CLIを利用できるようにして、確実にGitHub Enterprise Cloudで認証できるようにしたなら、データを生成する準備ができています。

結果を生成してGitHub Enterprise Cloudにアップロードするには、3つの異なるコマンドを使います。

  1. database create では、リポジトリのサポートされている各プログラミング言語の階層構造を表すために CodeQL データベースを作成します。
  2. database analyze では、クエリを実行して各 CodeQL データベースを分析し、結果を SARIF ファイルにまとめます。
  3. github upload-results では、結果の SARIF ファイルを GitHub Enterprise Cloud にアップロードします。そこで結果はブランチまたは pull request と照合され、code scanning アラートとして表示されます。

--help オプションを使用して、任意のコマンドのコマンドライン ヘルプを表示できます。

注: GitHub Enterprise Cloud の結果の code scanning として表示する SARIF データをアップロードすることは、GitHub Advanced Security が有効にされた組織が所有するリポジトリ、および GitHub.com 上のパブリック リポジトリでサポートされます。 詳細については、「リポジトリのセキュリティと分析の設定を管理する」を参照してください。

分析するCodeQLデータベースの作成

  1. 分析するコードをチェックアウトします。

    • ブランチの場合は、分析するブランチのヘッドをチェックアウトします。
    • pull request の場合は、pull request のヘッド コミットをチェックアウトするか、GitHub で生成された pull request のマージ コミットをチェックアウトします。
  2. コードベースの環境を設定し、依存関係が使用可能であることを確認します。 詳細については、CodeQL CLI のドキュメントの「コンパイルされていない言語のデータベースの作成」および 「コンパイル済み言語のデータベースの作成」を参照してください。

  3. コードベースのビルド コマンドを見つけます (ある場合)。 通常、これは CI システムの構成ファイルで使用できます。

  4. リポジトリのチェックアウト ルートから codeql database create を実行し、コードベースをビルドします。

    # Single supported language - create one CodeQL database
    codeql database create <database> --command<build> --language=<language-identifier>
    
    # Multiple supported languages - create one CodeQL database per language
    codeql database create <database> --command<build> \
          --db-cluster --language=<language-identifier>,<language-identifier>

    注: コンテナー化されたビルドを使用する場合は、ビルド タスクが行われるコンテナーで CodeQL CLI を実行する必要があります。

オプション必須使用法
<database>CodeQLデータベースを作成するディレクトリの名前と場所を指定します。 既存のディレクトリを上書きしようとすると、コマンドは失敗します。 また --db-cluster を指定した場合は、これが親ディレクトリであり、分析される言語ごとにサブディレクトリが作成されます。
--languageデータベースを作成する言語の識別子 (cpp`、`csharp`、`go`、`java`、`javascript`、および `python のいずれか) を指定します (TypeScript コードを分析するには javascript、Kotlin コードを分析するには java を使用します)。 --db-cluster と一緒に使用する場合は、オプションでコンマ区切りリストが受け入れられるか、複数指定できます。
--command推奨。 コードベースのビルド プロセスを呼び出すビルド コマンドまたはスクリプトを指定するために使用します。 コマンドは現在のフォルダーから、または定義されている場合は --source-root から実行されます。 Python および JavaScript または TypeScript の分析には不要です。
--db-cluster省略可能。 --language によって指定された言語ごとに 1 つのデータベースを生成するには、複数言語コードベースを使用します。
--no-run-unnecessary-builds推奨。 CodeQL CLIがビルドをモニターする必要がない場合に、言語のビルドコマンドを抑制するために使います(たとえばPythonやJavaScript/TypeScript)。
--source-root省略可能。 リポジトリのチェックアウト ルートの外部で CLI を実行する場合に使用します。 既定では、database create コマンドで現在のディレクトリがソース ファイルのルート ディレクトリであると見なされます。別の場所を指定するためにこのオプションを使用します。
--codescanning-config省略可能 (詳細) CodeQL データベースの作成方法と、後の手順で実行するクエリを指定する構成ファイルがある場合に使用します。 詳細については、「code scanning のカスタマイズ」と「database create」を参照してください。

詳細については、CodeQL CLI のドキュメントの「CodeQL データベースの作成」を参照してください。

単一言語の例

この例では、/checkouts/example-repo でチェックアウトされたリポジトリの CodeQL データベースを作成します。 JavaScript 抽出機能を使用して、リポジトリに JavaScript および TypeScript コードの階層表現を作成します。 結果のデータベースは /codeql-dbs/example-repo に格納されます。

$ codeql database create /codeql-dbs/example-repo --language=javascript \
    --source-root /checkouts/example-repo

> Initializing database at /codeql-dbs/example-repo.
> Running command [/codeql-home/codeql/javascript/tools/autobuild.cmd]
    in /checkouts/example-repo.
> [build-stdout] Single-threaded extraction.
> [build-stdout] Extracting
...
> Finalizing database at /codeql-dbs/example-repo.
> Successfully created database at /codeql-dbs/example-repo.

複数言語の例

この例では、/checkouts/example-repo-multi でチェックアウトされたリポジトリの CodeQL データベースを 2 つ作成します。 イベント プロセッサで使用されるものは次のとおりです。

  • --db-cluster: 複数の言語の分析を要求します。
  • --language: データベースを作成する言語を指定します。
  • --command: コードベースのビルド コマンド (ここでは make) をツールに伝えます。
  • --no-run-unnecessary-builds: 必要のない言語 (Python など) のビルド コマンドをスキップするようにツールに伝えます。

結果のデータベースは、/codeql-dbs/example-repo-multipython および cpp サブディレクトリに格納されます。

$ codeql database create /codeql-dbs/example-repo-multi \
    --db-cluster --language python,cpp \
    --command make --no-run-unnecessary-builds \
    --source-root /checkouts/example-repo-multi
Initializing databases at /codeql-dbs/example-repo-multi.
Running build command: [make]
[build-stdout] Calling python3 /codeql-bundle/codeql/python/tools/get_venv_lib.py
[build-stdout] Calling python3 -S /codeql-bundle/codeql/python/tools/python_tracer.py -v -z all -c /codeql-dbs/example-repo-multi/python/working/trap_cache -p ERROR: 'pip' not installed.
[build-stdout] /usr/local/lib/python3.6/dist-packages -R /checkouts/example-repo-multi
[build-stdout] [INFO] Python version 3.6.9
[build-stdout] [INFO] Python extractor version 5.16
[build-stdout] [INFO] [2] Extracted file /checkouts/example-repo-multi/hello.py in 5ms
[build-stdout] [INFO] Processed 1 modules in 0.15s
[build-stdout] <output from calling 'make' to build the C/C++ code>
Finalizing databases at /codeql-dbs/example-repo-multi.
Successfully created databases at /codeql-dbs/example-repo-multi.
$

CodeQLデータベースの分析

  1. CodeQLデータベースを作成してください(上記参照)。
  2. データベースに対して codeql database analyze を実行し、使用するパックまたはクエリを指定します。
    codeql database analyze <database> --format=<format> \
        --output=<output>  --download <packs,queries>

注: 1 つのコミットに対して複数の CodeQL データベースを分析する場合、このコマンドによって生成されるそれぞれの結果セットに対して SARIF カテゴリを指定する必要があります。 結果をGitHub Enterprise Cloudにアップロードする際には、code scanningはこのカテゴリを使ってそれぞれの言語に対する結果を別々に保存します。 この操作を忘れた場合は、各アップロードで前の結果が上書きされます。

codeql database analyze <database> --format=<format> \
    --sarif-category=<language-specifier> --output=<output> \
    <packs,queries>
オプション必須使用法
<database>分析するCodeQLデータベースを含むディレクトリのパスを指定します。
<packs,queries>実行する CodeQL パックまたはクエリを指定します。 code scanning に使用される標準クエリを実行するには、このパラメーターを省略します。 CodeQL CLI バンドルに含まれている他のクエリ スイートを確認する場合は、/<extraction-root>/qlpacks/codeql/<language>-queries/codeql-suites を参照してください。 独自のクエリ スイートの作成については、CodeQL CLI のドキュメントの「CodeQL クエリ スイートの作成」を参照してください。
--formatコマンドによって生成される結果ファイルの形式を指定します。 GitHub へのアップロードの場合、これは sarif-latest である必要があります。 詳細については、「code scanning の SARIF サポート」を参照してください。
--outputSARIF 結果ファイルを保存する場所を指定します。
--sarif-category単一データベースの分析の場合は省略可能です。 リポジトリ内の単一コミットに対して複数のデータベースを分析する場合に言語を定義するために必要です。 この分析の SARIF 結果ファイルに含めるカテゴリを指定します。 カテゴリは、同じツールとコミットに対する複数の分析を区別するために使用されますが、異なる言語またはコードの異なる部分で実行されます。
--sarif-add-query-help省略可能。 分析で使用されるカスタム クエリに対して使用可能なマークダウン レンダリング クエリ ヘルプを含める場合に使用します。 関連するクエリによってアラートが生成された場合は、SARIF 出力に含まれるカスタム クエリのクエリ ヘルプがすべてコード スキャン UI に表示されます。 詳細については、CodeQL CLI のドキュメントの「CodeQL CLI でのデータベースの分析」を参照してください。
<packs>省略可能。 CodeQL クエリ パックを分析に含めたい場合に使います。 詳細については、「CodeQL パックのダウンロードと使用」を参照してください。
--download省略可能。 CodeQL クエリ パックの一部がまだディスク上になく、クエリを実行する前にダウンロードする必要がある場合に使います。
--threads任意。 複数のスレッドを使用してクエリを実行する場合に使用します。 既定値は 1 です。 クエリの実行を高速化するために、より多くのスレッドを指定できます。 スレッドの数を論理プロセッサの数に設定するには、0 を指定します。
--verbose省略可能。 データベース作成プロセスから分析プロセスと診断データに関する詳細情報を取得するために使用します。

詳細については、CodeQL CLI のドキュメントの「CodeQL CLI でのデータベースの分析」を参照してください。

基本的な例

この例では、/codeql-dbs/example-repo で格納されている CodeQL データベースを分析し、結果を SARIF ファイル (/temp/example-repo-js.sarif) として保存します。 --sarif-category を使用して、結果を JavaScript として識別する追加の情報を SARIF ファイルに含めます。 これは、リポジトリ中の単一のコミットに対して分析するCodeQLデータベースが複数ある場合に不可欠です。

$ codeql database analyze /codeql-dbs/example-repo  \
    javascript-code-scanning.qls --sarif-category=javascript \
    --format=sarif-latest --output=/temp/example-repo-js.sarif

> Running queries.
> Compiling query plan for /codeql-home/codeql/qlpacks/codeql-javascript/AngularJS/DisablingSce.ql.
...
> Shutting down query evaluator.
> Interpreting results.

GitHub Enterprise Cloudへの結果のアップロード

注:

  • SARIF アップロードでは、アップロードごとに最大 5,000 件の結果がサポートされます。 この制限を超える結果はすべて無視されます。 ツールで生成される結果が多すぎる場合は、最も重要なルールまたはクエリの結果に焦点を当てるように構成を更新する必要があります。

  • SARIF アップロードでサポートされる gzip 圧縮の SARIF ファイルの最大サイズは、アップロードごとに 10 MB となります。 この制限を超えるアップロードはすべて拒否されます。 含まれる結果が多すぎるために SARIF ファイルが大きくなりすぎた場合は、最も重要なルールまたはクエリの結果に焦点を当てるように構成を更新する必要があります。

結果を GitHub Enterprise Cloud にアップロードする前に、以前に作成した GitHub Appまたは personal access token を CodeQL CLI に渡す最善の方法を決める必要があります (「CI システムでの CodeQL CLI のインストール」を参照)。 シークレット ストアの安全な使用に関する CI システムのガイダンスを確認することをお勧めします。 CodeQL CLIは以下をサポートします。

  • --github-auth-stdin オプションを使用し、標準入力を介して CLI にトークンを渡す (推奨)。
  • 環境変数 GITHUB_TOKEN にシークレットを保存し、--github-auth-stdin オプションを含めずに CLI を実行する。

CI サーバーの最も安全で信頼性の高い方法を決定した場合は、各 SARIF 結果ファイルで codeql github upload-results を実行し、トークンが環境変数 GITHUB_TOKEN で使用可能でない限り、--github-auth-stdin を含めます。

echo "$UPLOAD_TOKEN" | codeql github upload-results --repository=<repository-name> \
      --ref=<ref> --commit=<commit> --sarif=<file> \
      --github-auth-stdin
オプション必須使用法
--repositoryデータのアップロード先となるリポジトリの OWNER/NAME を指定します。 リポジトリがパブリックでなければ、オーナーは GitHub Advanced Security のライセンスを持つ Enterprise 内の Organization でなければならず、GitHub Advanced Security はリポジトリで有効化されていなければなりません。 詳細については、「リポジトリのセキュリティと分析の設定を管理する」を参照してください。
--refチェックアウトして分析した ref の名前を指定して、結果を正しいコードと照合できるようにします。 ブランチで refs/heads/BRANCH-NAME を使用するか、pull request のヘッド コミットで refs/pull/NUMBER/head を使用するか、pull request の GitHub で生成されたマージ コミットで refs/pull/NUMBER/merge を使用します。
--commit分析したコミットの完全な SHA を指定します。
--sarif読み込む SARIF ファイルを指定します。
--github-auth-stdin任意。 GitHub の REST API での認証用に作成された GitHub App または personal access token を標準入力で CLI に渡すために使います。 このトークンを使用して設定された GITHUB_TOKEN 環境変数にコマンドがアクセスできる場合、これは必要ありません。

詳細については、CodeQL CLI のドキュメントの「github upload-results」を参照してください。

基本的な例

この例では、SARIF ファイル temp/example-repo-js.sarif からリポジトリ my-org/example-repo に結果をアップロードします。 結果が main ブランチのコミット deb275d2d5fe9a522a0b7bd8b6b6a1c939552718 に対するものであることを code scanning API に伝えます。

$ echo $UPLOAD_TOKEN | codeql github upload-results --repository=my-org/example-repo \
    --ref=refs/heads/main --commit=deb275d2d5fe9a522a0b7bd8b6b6a1c939552718 \
    --sarif=/temp/example-repo-js.sarif --github-auth-stdin

アップロードが失敗しなければ、このコマンドからの出力はありません。 コマンドプロンプトは、アップロードが完了してデータ処理が開始された時点で戻ってきます。 小さなコードベースでは、すぐ後にGitHub Enterprise Cloud中のcode scanningアラートを調べることができるでしょう。 チェックアウトしたコードに応じて、アラートを直接 pull request に、またはブランチの [セキュリティ] タブで表示できます。詳細については、「pull request でのcode scanning アラートのトリアージ」および「リポジトリのcode scanning アラートを管理する」を参照してください。

CodeQL クエリ パックのダウンロードと使用

注: CodeQL パッケージ管理機能 (CodeQL パックを含む) は現在ベータ版であり、変更される可能性があります。

CodeQL CLI バンドルには、GitHub の専門家、セキュリティ研究者、コミュニティの共同作成者によって管理されるクエリが含まれます。 他の Organization によって開発されたクエリを実行する場合、CodeQL クエリ パックを使用すると、クエリを効率的かつ信頼性の高い方法でダウンロードして実行できます。 詳細については、「CodeQL によるコード スキャンについて」を参照してください。

CodeQL パックを使ってデータベースを分析する前に、GitHub Container registry から必要なパッケージをすべてダウンロードする必要があります。 これは、codeql database analyze コマンドの一部として --download フラグを使うことによって行うことができます。 パッケージが一般公開されていない場合は、認証に GitHub App または personal access token を使う必要があります。 詳細と例については、上記の「GitHub Enterprise Cloud への結果のアップロード」を参照してください。

オプション必須使用法
<scope/name@version:path>コンマ区切りリストを使用して、ダウンロードする 1 つまたは複数の CodeQL クエリ パックのスコープと名前を指定します。 必要に応じて、ダウンロードして解凍するバージョンを含めます。 既定では、このパックの最新バージョンがダウンロードされます。 必要に応じて、実行するクエリ、ディレクトリ、またはクエリ スイートへのパスを含めます。 パスが含まれていない場合、このパックの既定のクエリを実行します。
--github-auth-stdin任意。 GitHub の REST API での認証用に作成された GitHub App または personal access token を標準入力で CLI に渡します。 このトークンを使用して設定された GITHUB_TOKEN 環境変数にコマンドがアクセスできる場合、これは必要ありません。

基本的な例

この例では、codeql database analyze コマンドに --download オプションを付けて実行しています。

  1. 最新バージョンの octo-org/security-queries パックをダウンロードします。
  2. バージョン 1.0.1 とocto-org/optional-security-queries互換性のあるバージョンのパックをダウンロードします (この場合はバージョン 1.0.2 です)。 semver の互換性については、npm のセマンティック バージョンの範囲に関するドキュメントを参照してください。
  3. octo-org/security-queries の既定のクエリをすべて実行します。
  4. octo-org/optional-security-queries のクエリ queries/csrf.ql だけを実行します
$ echo $OCTO-ORG_ACCESS_TOKEN | codeql database analyze --download /codeql-dbs/example-repo \
    octo-org/security-queries \
    octo-org/optional-security-queries@~1.0.1:queries/csrf.ql \
    --format=sarif-latest --output=/temp/example-repo-js.sarif

> Download location: /Users/mona/.codeql/packages
> Installed fresh octo-org/security-queries@1.0.0
> Installed fresh octo-org/optional-security-queries@1.0.2
> Running queries.
> Compiling query plan for /Users/mona/.codeql/packages/octo-org/security-queries/1.0.0/potential-sql-injection.ql.
> [1/2] Found in cache: /Users/mona/.codeql/packages/octo-org/security-queries/1.0.0/potential-sql-injection.ql.
> Starting evaluation of octo-org/security-queries/query1.ql.
> Compiling query plan for /Users/mona/.codeql/packages/octo-org/optional-security-queries/1.0.2/queries/csrf.ql.
> [2/2] Found in cache: /Users/mona/.codeql/packages/octo-org/optional-security-queries/1.0.2/queries/csrf.ql.
> Starting evaluation of octo-org/optional-security-queries/queries/csrf.ql.
> [2/2 eval 694ms] Evaluation done; writing results to octo-org/security-queries/query1.bqrs.
> Shutting down query evaluator.
> Interpreting results.

CodeQL パックの直接ダウンロード

CodeQL パックをダウンロードしてすぐに実行しない場合、codeql pack download コマンドを使用できます。 これは、CodeQL クエリを実行するとき、インターネットへのアクセスをしないようにする場合、便利です。 CodeQL 分析を実行するとき、前の例と同じ方法でパック、バージョン、パスを指定できます。

echo $OCTO-ORG_ACCESS_TOKEN | codeql pack download <scope/name@version:path> <scope/name@version:path> ...

複数の GitHub コンテナー レジストリから CodeQL パックをダウンロードする

CodeQL パックが複数のコンテナー レジストリに存在する場合は、各パックを検索する場所を CodeQL CLI に示す必要があります。 詳細については、「code scanning のカスタマイズ」を参照してください。

CodeQL分析のためのCIの設定例

これは、2つのサポートされている言語を持つコードベースを分析し、結果をGitHub Enterprise Cloudにアップロードするために使うことができる一連のコマンドの例です。

# Create CodeQL databases for Java and Python in the 'codeql-dbs' directory
# Call the normal build script for the codebase: 'myBuildScript'

codeql database create codeql-dbs --source-root=src \
    --db-cluster --language=java,python --command=./myBuildScript

# Analyze the CodeQL database for Java, 'codeql-dbs/java'
# Tag the data as 'java' results and store in: 'java-results.sarif'

codeql database analyze codeql-dbs/java java-code-scanning.qls \
    --format=sarif-latest --sarif-category=java --output=java-results.sarif

# Analyze the CodeQL database for Python, 'codeql-dbs/python'
# Tag the data as 'python' results and store in: 'python-results.sarif'

codeql database analyze codeql-dbs/python python-code-scanning.qls \
    --format=sarif-latest --sarif-category=python --output=python-results.sarif

# Upload the SARIF file with the Java results: 'java-results.sarif'

echo $UPLOAD_TOKEN | codeql github upload-results --repository=my-org/example-repo \
    --ref=refs/heads/main --commit=deb275d2d5fe9a522a0b7bd8b6b6a1c939552718 \
    --sarif=java-results.sarif --github-auth-stdin

# Upload the SARIF file with the Python results: 'python-results.sarif'

echo $UPLOAD_TOKEN | codeql github upload-results --repository=my-org/example-repo \
    --ref=refs/heads/main --commit=deb275d2d5fe9a522a0b7bd8b6b6a1c939552718 \
    --sarif=python-results.sarif --github-auth-stdin

CIシステムでのCodeQL CLIのトラブルシューティング

ログと診断情報を見る

code scanningクエリスイートを使ってCodeQLデータベースを分析する際には、アラートに関する詳細情報を生成するのに加えて、CLIはデータベース生成ステップからの診断情報とサマリメトリクスを報告します。 アラートが少ないリポジトリでは、実際にコード中の問題が少ないのか、あるいはCodeQLデータベースの生成時にエラーがあったのかを判断するのにこの情報が役立つかもしれません。 codeql database analyze からさらに詳しい出力を得るには、--verbose オプションを使用します。

使用可能な診断情報の種類について詳しくは、「code scanning ログの表示」を参照してください。

Code scanningは、分析された言語の1つからの分析結果だけを表示します。

デフォルトでは、code scanningはリポジトリの分析ごとに1つのSARIF結果ファイルを期待します。 したがって、コミットから2つめのSARIF結果ファイルをアップロードすると、それはデータのオリジナルのセットの置き換えとして扱われます。

リポジトリ中の1つのコミットについての結果をcode scanning APIに複数アップロードしたい場合は、それぞれの結果をユニークなセットとして特定しなければなりません。 コミットごとに分析する CodeQL データセットを複数作成するリポジトリでは、--sarif-category オプションを使用して、そのリポジトリで生成するそれぞれの SARIF ファイルに言語または他の一意のカテゴリを指定します。

Python の抽出に関する問題

CodeQL CLI に対する Python 2 のサポートは非推奨になっています (具体的には、CodeQL データベース生成フェーズ (コード抽出))。

Python で記述されたコードで CodeQL CLI を使って CodeQL code scanning を実行する場合は、CI システムに Python 3 がインストールされていることを確認する必要があります。

参考資料