セクションアナライザー開発

アナライザはDockerイメージとして出荷され、CIパイプラインコンテキスト内で実行されます。このガイドでは、アナライザ全体の開発とテストのプラクティスについて説明します。

共有モジュール

共通の動作やインターフェースのために、アナライザ間で共有されるGoモジュールが多数あります:

  • command Go パッケージは CLI インターフェイスを実装しています。
  • common プロジェクトは、ロギング、証明書処理、ディレクトリ検索機能のための雑多な共有モジュールを提供します。
  • report Go パッケージのReportFinding 構造体は JSON レポートをマーシャルします。
  • template プロジェクトは新しいアナライザーの足場となります。

分析器の使い方

アナライザはDockerイメージとして出荷されます。例えば、作業ディレクトリをスキャンするためにSemgrepDockerイメージを実行します:

  1. cd をスキャンしたいソースコードのディレクトリにコピーします。
  2. docker login registry.gitlab.com を実行し、ユーザー名と個人またはプロジェクトのアクセストークンを、少なくともread_registry のスコープで指定します。
  3. Dockerイメージを実行してください:

    docker run \
        --interactive --tty --rm \
        --volume "$PWD":/tmp/app \
        --env CI_PROJECT_DIR=/tmp/app \
        -w /tmp/app \
        registry.gitlab.com/gitlab-org/security-products/analyzers/semgrep:latest /analyzer run
    
  4. Dockerコンテナは、アナライザ・カテゴリに対応するレポート・ファイル名で、マウントされたプロジェクト・ディレクトリにレポートを生成します。例えば、SASTは gl-sast-report.json という名前のファイルを生成します。

アナライザの開発

アナライザーをアップデートするには

  1. Goソースコードを修正します。
  2. 新しいDockerイメージをビルドします。
  3. テストプロジェクトに対してアナライザーを実行します。
  4. 生成されたレポートを期待されるものと比較してください。

analyzer という名前のDockerイメージを作成する方法は以下の通りです:

docker build -t analyzer .

例えば、Secret Detectionをテストするには以下を実行します:

wget https://gitlab.com/gitlab-org/security-products/ci-templates/-/raw/master/scripts/compare_reports.sh
sh ./compare_reports.sh sd test/fixtures/gl-secret-detection-report.json test/expect/gl-secret-detection-report.json \
| patch -Np1 test/expect/gl-secret-detection-report.json && Git commit -m 'Update expectation' test/expect/gl-secret-detection-report.json
rm compare_reports.sh

自分の環境用にバイナリをコンパイルして、それを内部で実行することもできますが、analyzerun 、アナライザーの実行時依存関係が欠落しているため、おそらく動作しません。

以下はSpotBugsに基づいた例です:

go build -o analyzer
./analyzer search test/fixtures
./analyzer convert test/fixtures/app/spotbugsXml.Xml > ./gl-sast-report.json

実行基準

SASTを有効にするには、GitLab CI/CD設定に定義済みのテンプレートを含める必要があります。

以下の独立した基準によって、プロジェクトでどのアナライザーを実行する必要があるかが決まります:

  1. SAST テンプレートでは、rules:exists を使用して、特定のファイルの存在に基づいて実行する解析ツ ールを決定します。たとえば、Brakeman アナライザーは .rb ファイルとGemfile.
  2. 各分析ツールは、実際の分析を実行する前に、カスタマイズ可能な一致インターフェイスを実行します。例えばFlawfinder は C/C++ ファイルをチェックします。
  3. 一般的なファイル拡張子で実行されるいくつかのアナライザーでは、CI/CD変数に基づくチェックがあります。例えばKubernetesのマニフェストはYAMLで記述されているため、Kubesecは SCAN_KUBERNETES_MANIFESTS がtrueに設定されている場合にのみ実行されます

ステップ1は、プロジェクトに適していないアナライザーを実行するために費やされるコンピュートクォータの浪費を防ぐのに役立ちます。しかし、技術的な制約から、大規模なプロジェクトには使用できません。そのため、ステップ2は不一致の解析器が早期に終了できるようにするための最終チェックの役割を果たします。

分析装置のテスト方法

Dependency Scanning アナライザがダウンストリームパイプライン機能を使用して、テストプロジェクトを使用してアナライザをテストする方法をビデオで説明します:

How Sec leverages the downstream pipeline feature of GitLab to test analyzers end to end

ローカル変更のテスト

アナライザの共有モジュール (commandreport など) の内部変更をテストするには、go mod replace ディレクティブを使用して、リモートでタグ付けされたバージョンのコマンドを使用する代わりに、command をローカルの変更でロードすることができます。例えば

go mod edit -replace gitlab.com/gitlab-org/security-products/analyzers/command/v3=/local/path/to/command

また、go.mod ファイルを手動で更新することでも、同じ結果を得ることができます:

module gitlab.com/gitlab-org/security-products/analyzers/awesome-analyzer/v2

replace gitlab.com/gitlab-org/security-products/analyzers/command/v3 => /path/to/command

require (
    ...
    gitlab.com/gitlab-org/security-products/analyzers/command/v3 v2.19.0
)

Dockerでのローカル変更のテスト

Dockerをreplacego.mod

  1. command の内部をアナライザーのディレクトリにコピーします。cp -r /path/to/command path/to/analyzer/command.
  2. アナライザのDockerfile:COPY command /command にコピー文を追加します。
  3. replace ステートメントを更新して、上記のステップのCOPY ステートメントのコピー先と一致するようにします:replace gitlab.com/gitlab-org/security-products/analyzers/command/v3 => /command

アナライザ・スクリプト

analyzer-scriptsリポジトリには、ほとんどのアナライザーに対応するスクリプトがあります。GitLab CI のような環境でアナライザのビルドや実行、デバッグを行うことができ、特にアナライザの変更をローカルで検証するのに便利です。

詳細はプロジェクトのREADMEを参照ください。

バージョンアップとリリースプロセス

GitLabセキュリティ製品は、GitLab RailsのMAJOR.MINOR とは独立したバージョン管理システムを使用しています。全ての製品はセマンティック・バージョニングのバリエーションを使用し、Dockerイメージとして利用可能です。

Patch バージョンバンプは、内部ツール(すなわちbandit)のMinor バージョンバンプに対応する傾向があり、私たちのスキャナに対するより重要な変更のためにMinor バンプをより柔軟に予約することができます。ラッピングされたスキャナによる変更を壊す場合は、別のリポジトリに新しいアナライザを作成することを考慮する必要があります。

分析器はこの方式に従ってDockerイメージとしてリリースされます:

  • デフォルトブランチにプッシュすると、edge イメージタグが上書きされます。
  • 任意のawesome-feature ブランチにプッシュすると、それにマッチする awesome-featureイメージタグが生成されます。
  • 各 Git タグは、対応するMajor.Minor.Patch イメージタグを生成します。手動ジョブでは、対応するMajorlatest の画像タグを上書きして、このMajor.Minor.Patch を指すようにできます。

たいていの場合、MAJOR のイメージに依存するのが好ましいでしょう。 は、最新のアドバイザリやツールへのパッチで自動的に最新の状態に保たれます。同梱の CI テンプレートはメジャーバージョンに固定されていますが、ユーザはバージョンを直接上書きすることができます。

新しいanalyzer Dockerイメージをリリースするには、2つの異なるオプションがあります:

次の図は、新しいバージョンのanalyzerがリリースされたときに作成されるDockerタグを説明したものです:

graph LR A1[git tag v1.1.0]--> B1(run CI pipeline) B1 -->|build and tag patch| D1[1.1.0] B1 -->|tag minor| E1[1.1] B1 -->|retag major| F1[1] B1 -->|retag latest| G1[latest] A2[git tag v1.1.1]--> B2(run CI pipeline) B2 -->|build and tag patch| D2[1.1.1] B2 -->|retag minor| E2[1.1] B2 -->|retag major| F2[1] B2 -->|retag latest| G2[latest] A3[push to default branch]--> B3(run CI pipeline) B3 -->|build and tag edge| D3[edge]

私たちの継続的デプロイのフローでは、GitLab Railsアプリケーションに対応するものがない新しいコンポーネントについては、コンポーネントはいつでもリリースできます。コンポーネントが既存のアプリケーションに統合されるまでは、私たちの標準的なリリースサイクルやプロセスによってインテグレーションが妨げられることはありません。

手動リリースプロセス

  1. 新しいIRMA TRUpointのCHANGELOG.md 入力が正しいことを確認してください。
  2. リリース・ソース(通常はmaster またはmain ブランチ)にパイプラインが通っていることを確認してください。
  3. プロジェクト・ウィンドウの左側にある [デプロイ]メニューを選択し、[Windows] サブメニューを選択して、アナライザー・プロジェクトの新しいリリースを作成します。
  4. New release]を選択して、[New Release]ページを開きます。
    1. Create tag v2.4.2 タグ名**ドロップダウンに、CHANGELOG.md で使用したものと同じバージョンを入力します(例:v2.4.2 )。
    2. リリース・タイトル・テキスト・ボックスに、上記で使用したものと同じバージョンを入力します(例:v2.4.2 )。
    3. Release notes テキストボックスには、対応するバージョンの注釈をコピーしてCHANGELOG.md に貼り付けます。
    4. その他の設定はデフォルトのままにしてください。
    5. リリースの作成を選択します。

上記のプロセスに従って新しいリリースを作成すると、新しい Git タグがTag name で作成されます。これにより、指定されたタグのバージョンで新しいパイプラインがトリガーされ、新しいanalyzer Dockerイメージがビルドされます。

analyzerがanalyzer.yml テンプレート を使用している場合、上記の新規リリースプロセスの一部としてトリガーされたパイプラインは、自動的に新しいバージョンのanalyzer Dockerイメージをタグ付けし、デプロイします。

analyzerがanalyzer.yml テンプレートを使用していない場合は、手動で新しいバージョンのanalyzer Dockerイメージにタグ付けしてデプロイする必要があります:

  1. プロジェクトウィンドウの左側にあるCI/CDメニューを選択し、パイプラインサブメニューを選択します。
  2. 新しいパイプラインが、v2.4.2 のようなタグで実行されているはずです。
  3. パイプラインが完了すると、blocked の状態になります。
  4. ウィンドウの右側にあるManual job 再生ボタンを選択し、tag version アナライザーの新しいバージョンのDockerイメージにタグ付けしてデプロイします。

Gitタグを作成するタイミングは、あなたの最善の判断で決めてください。判断がつかない場合は、他の人の意見を聞いてください。

自動リリースプロセス

自動リリース処理を使用する前に、以下の処理を行う必要があります:

  1. CREATE_GIT_TAG: trueCI/CD 環境変数として設定します。
  2. CI/CD プロジェクト設定のVariables を確認してください。プロジェクトがすでにプロジェクトグループからGITLAB_TOKEN 環境変数を継承している場合を除き、complete read/write access to the APIプロジェクトアクセストークンを作成し、GITLAB_TOKEN をこのトークンを参照するCI/CD 環境変数 として設定します。

上記の手順が完了すると、自動リリース処理は以下のように実行されます:

  1. プロジェクトのメンテナーが MR をデフォルトブランチにマージします。
  2. デフォルトのパイプラインが起動し、upsert git tag ジョブが実行されます。
    • CHANGELOG.md の最新バージョンが Git タグのひとつにマッチする場合、ジョブは実行されません。
    • そうでない場合、このジョブはreleases API を使って新しいリリースと Git タグを自動的に作成します。バージョンとメッセージはプロジェクトのCHANGELOG.md ファイルの最新のエントリから取得されます。
  3. 新しい Git タグに対してパイプラインが自動的にトリガーされます。このパイプラインは、アナライザのlatestmajorminorpatch Dockerイメージをリリースします。

アナライザーをリリースした後の手順

  1. 新しいバージョンのアナライザーのDockerイメージがタグ付けされ、デプロイされたら、対応するテストプロジェクトでテストしてください。
  2. 関連するグループのSlackチャンネルでリリースをアナウンスしてください。メッセージの例

    ANALYZER_NAME ANALYZER_VERSION をリリースしました。LINK_TO_RELEASE

プッシュされた Git タグは絶対に削除しないでください。Go パッケージのレジストリで使われたりキャッシュされたりする可能性が高いからです。

コンテナイメージの場所

コンテナレジストリへの書き込みアクセス者を制限するため、すべてのイメージは以下の場所に公開されます。

  • グループhttps://gitlab.com/security-products/
  • プロジェクトパス:https://gitlab.com/security-products/<NAME>(例)
  • レジストリのアドレス:registry.gitlab.com/security-products/<NAME>[/<IMAGE_NAME>]:[TAG]
  • 権限
    • トップレベルグループ
      • メンテナー@gitlab-org/secure/managers,@gitlab-org/govern/managers
    • プロジェクトレベル
  • プロジェクトの設定
    • 可視性、プロジェクト機能、権限。
      • プロジェクトの可視性:公開。ユーザーがアクセスをリクエストできる」のチェックを外してください。
      • イシュー:無効にします。
      • リポジトリ:「プロジェクトメンバーのみ」に設定。無効にします:マージリクエスト、フォーク、Git LFS、パッケージ、CI/CD。
      • 残りの項目を無効にします:アナリティクス、要件、Wiki、スニペット、ページ、オペレーション。
    • サービスデスク: 無効

Sec Sectionの各グループが担当します:

  1. アーティファクトの非推奨および削除スケジュールの管理、およびそのためのイシューの作成。
  2. 新しい場所でのプロジェクトの作成と設定。
  3. リリースのアーティファクトを新しい場所にプッシュするビルドの設定。
  4. それぞれのサポート契約に従って、古い場所にあるイメージを削除したり保持したりします。

Goのセキュリティとビルドの修正

Goで実装されたセキュア・アナライザのDockerfileMINOR リビジョンではなく、MAJOR リリースのGoを参照する必要があります。これにより、分析器のコンパイルに使用されるGoのバージョンに、その時点で利用可能なすべてのセキュリティ修正が含まれていることが保証されます。たとえば、解析器のマルチステージ Dockerfile では、golang:1.15-alpine イメージを使用して解析器 CLI をビルドする必要がありますが、golang:1.15.4-alpine は使用しないでください。

Goのリビジョン(MINOR )がリリースされ、そのリビジョンにセキュ リティ修正が含まれる場合、プロジェクトのメンテナーは、Secureアナライザを再ビルド する必要があるかどうかを確認する必要があります。ビルドに使用された Go のバージョンは、リリースに対応するbuild ジョブのログに表示されます。

また、stringsコマンドを使ってGoのバイナリから抽出することもできます。解析器の最新のイメージが影響を受けるバージョンのGoでビルドされている場合は、再構築する必要があります。イメージを再構築するには、メンテナーは次のいずれかを行います:

  • 安定リリースに対応する Git タグの新しいパイプラインを起動します。
  • 新しい Git タグを作成し、BUILD の番号をインクリメントします。
  • デフォルトブランチのパイプラインをトリガーし、PUBLISH_IMAGES 変数に空でない値を設定します。

いずれにせよ、新しいDockerイメージがビルドされ、同じイメージタグで公開されます:MAJOR.MINOR.PATCHMAJOR

このワークフローでは、同じGoのリリース(MAJOR )のリビジョン(MINOR )間の完全な互換性を想定しています。互換性にイシューがある場合、プロジェクトパイプラインはテストを実行するときに失敗します。その場合、互換性の問題が解決するまで、DockerfileでMINOR リビジョンのGoを参照し、その例外を文書化する必要があるかもしれません。

Dockerfile 、GoのMINOR リビジョンはプロジェクトの変更履歴に記載されていません。

ビルドタグを使うのが理にかなっている場合があります。例えば、Dockerイメージを新しいレジストリにプッシュする場合などです。

再構築する Git タグ

新しいGitタグを作成してアナライザーを再構築する場合、新しいタグのバージョンは以前と同じMAJOR.MINOR.PATCHBUILDsemverで定義)番号がインクリメントされます。

例えば、アナライザーの最新リリースがv1.2.3 、対応するDockerイメージが影響を受けるバージョンのGoを使ってビルドされた場合、メンテナーはv1.2.3+1 イメージを再構築 v1.2.3+1するためのGitタグを作成します。v1.2.3+1 最新リリースが v1.2.3+1, であれば、v1.2.3+2 を作成します。

ビルド番号は自動的にイメージタグから削除されます。例として、gemnasium プロジェクトで Git タグv1.2.3+1 を作成すると、パイプラインがイメージを再構築し、gemnasium:1.2.3 としてプッシュします。

再構築のために作成された Git タグには、新しいビルドが必要な理由を説明するシンプルなメッセージが表示されます。例:Rebuild with Go 1.15.6 。このタグにはリリースノートはなく、リリースは作成されません。

Analyzerをリビルドするための新しいGitタグを作成するには、以下の手順に従います:

  1. 新しい Git タグを作成し、メッセージを指定します。

    git tag -a v1.2.3+1 -m "Rebuild with Go 1.15.6"
    
  2. タグをリポジトリにプッシュします

    git push origin --tags
    
  3. Git タグ用の新しいパイプラインが起動し、新しい画像がビルドされてタグが付けられます。
  4. master ブランチに対して新しいパイプラインを実行し、テスト一式を実行し、新しくタグ付けされたイメージに対して新しい脆弱性レポーターを生成します。上記のステップ3. でトリガーされたリリースパイプラインは、テストのサブセットのみを実行し、例えばContainer Scanning 分析を実行しないので、これは必要です。

毎月のリリースプロセス

毎月18日に行います。ただし、これはソフトな期限であり、数日後に行っても問題はありません。

まず、このリポジトリのスクリプトを使って、リリースのための新しいイシューを作成してください:./scripts/release_issue.rb MAJOR.MINOR 。このイシューがリリースの全プロセスを案内します。一般的には、以下の作業を行う必要があります:

依存関係の更新

アナライザー・ソースで使用されているすべての依存関係およびアップストリーム・スキャナー(もしあれば)は、主にセキュリティ修正と破壊的でない変更を含む月次ペースで更新されます。

  • 静的解析チームは、カスタム内部ツール(SastBot)を使用して、すべてのSASTアナライザの依存性管理を自動化しています。SastBotは、毎月8日にMRを生成し、静的解析チームのメンバーにディストリビューションを分配して、レビューを進めます。プロセスの詳細については、依存関係更新の自動化を参照してください。