Local ScannerによるJenkinsのPR gating
Aikido Local Scannerを使うと、CIパイプラインにセキュリティゲートを設定できます。
PR gatingは、新しいコードがデフォルトブランチにマージされる前に、セキュリティ基準を満たしていることを保証します。プルリクエストで導入された変更のみをスキャンします。スキャンによって、設定した重要度のしきい値以上の新しい問題が検出された場合、CIパイプラインは失敗します。
これにより、既存の検出結果は別途対応しつつ、新しい脆弱性の混入を防ぐことができます。
PR gatingを有効にするには、--fail-on <severity> オプションを追加して希望の重要度レベルを選択します。次に、PR gatingを実行することを示す --gating-mode pr オプションを追加します。また、base(--base-commit-id <commit-id>)とhead commit(--head-commit-id <commit-id>)も指定する必要があります。base commit idに対して以前スキャンが実行されていた場合は、その結果と比較されます。実行されていない場合は、デフォルトブランチの最新スキャンと比較されます。
Jenkins環境でのLocal Scannerの設定に関する一般的な情報は、こちらの記事をご参照ください。
主な構成要素は3つあります。
- SCMとJenkinsとのインテグレーション。
- Discover pull requestsビヘイビアを持つMultibranch Pipelineジョブ。 これにより、Jenkinsは開いているプルリクエストごとにビルドを行います。PRビルドの際、Jenkinsはソースブランチをチェックアウトし、標準のchange-request環境変数(
CHANGE_ID、CHANGE_TARGET、CHANGE_BRANCH)を公開します。 Jenkinsfileから--gating-mode prで実行されるAikido Local Scanner。
PR opened/updated ──► SCM sends webhook ──► Jenkins Multibranch PR build │ ▼ aikido-local-scanner --gating-mode pr │ new issues ≥ --fail-on? ── yes ──► build FAILS │ │ no ▼ ▼ build status = FAILED build PASSES │ │ ▼ ▼ SCM blocks merge SCM checks passMultibranch Pipelineの設定
Section titled “Multibranch Pipelineの設定”プルリクエストのビルドには、Multibranch Pipelineジョブが必要です。
- JenkinsでNew Item → Multibranch Pipelineを選択し、名前を付けてOKを選択します。
- Branch SourcesでAdd source → Select your SCMを選択します。
- repositoryを選択します。
- BehaviorsでAdd → Discover pull requestsを選択し、Discover branchesを無効化します。
- Scan Multibranch Pipeline Triggersで、webhook trigger → Pull request opened or source branch updatedオプションを有効にします。
- Build Configurationはby Jenkinsfileのままにし、Script Path =
Jenkinsfileとします。 - Saveを選択します。Jenkinsはリポジトリをスキャンし、開いているプルリクエストごとにビルドを開始します。
JenkinsfileへのAikido PR gatingステージの追加
Section titled “JenkinsfileへのAikido PR gatingステージの追加”リポジトリのルートにJenkinsfileを追加(または既存のものを拡張)します。以下のステージはプルリクエストのビルド時のみ実行され、Gitからbaseとhead commitを取得し、PR gatingモードでスキャナーを実行します。ゲートが失敗した際にスキャナーが非ゼロで終了することで、ビルドが失敗します。
pipeline { agent any
environment { // Picks up credentials as setup in https://help.aikido.dev/code-scanning/local-code-scanning/jenkins-setup-for-local-code-scanning#id-1-get-your-authentication-token AIKIDO_API_KEY = credentials('aikido-local-scanner-api-key') AIKIDO_REPO_NAME = 'my-repo' }
stages { stage('Aikido PR Gating') { // CHANGE_ID is only set on pull request builds when { expression { env.CHANGE_ID != null } } steps { script { // Ensure the target (destination) branch is available locally sh "git fetch origin ${env.CHANGE_TARGET}"
// Head = tip of the PR source branch (what's being merged in) def headCommit = sh( script: 'git rev-parse HEAD', returnStdout: true ).trim()
// Base = tip of the destination branch (what it's merging into) def baseCommit = sh( script: "git rev-parse origin/${env.CHANGE_TARGET}", returnStdout: true ).trim()
echo "PR #${env.CHANGE_ID}: ${env.CHANGE_BRANCH} -> ${env.CHANGE_TARGET}" echo "Base commit: ${baseCommit}" echo "Head commit: ${headCommit}"
// Docker variant. The scanner exits non-zero when new issues // at or above --fail-on are found, which fails the build. sh """ docker run --rm \ -v "\$(pwd):/scan-target" \ aikidosecurity/local-scanner \ scan /scan-target \ --apikey "\$AIKIDO_API_KEY" \ --repositoryname "\$AIKIDO_REPO_NAME" \ --branchname "${env.CHANGE_BRANCH}" \ --gating-mode pr \ --fail-on critical \ --base-commit-id ${baseCommit} \ --head-commit-id ${headCommit} """ } } } }}Dockerの代わりにスキャナーのバイナリがエージェントにインストールされている場合は、docker run …ブロックを以下に置き換えてください。
sh """ aikido-local-scanner scan ./ \ --apikey "\$AIKIDO_API_KEY" \ --repositoryname "\$AIKIDO_REPO_NAME" \ --branchname "${env.CHANGE_BRANCH}" \ --gating-mode pr \ --fail-on critical \ --base-commit-id ${baseCommit} \ --head-commit-id ${headCommit}"""--fail-on criticalは重要度のしきい値を設定します。より厳格にゲートするには、high、medium、lowに変更してください。
必要に応じて、SCM側でゲートの強制設定を行ってください。