ローカルスキャナーを使ったJenkinsのPRゲーティング
Aikido Local Scannerを使用すると、CIパイプラインでセキュリティゲートを適用できます。
クラウド接続されたワークスペース(GitHub、BitBucketなど)でもPRゲーティングを使用できます。CIのインテグレーションセクションをご覧ください。
PRゲーティングは、新しいコードがデフォルトブランチにマージされる前に、セキュリティ基準を満たしていることを保証します。スキャン対象はプルリクエストで導入された変更のみです。設定した重大度のしきい値以上の新しい問題が検出された場合、CIパイプラインは失敗します。
これにより、既存の検出結果は別途対処しつつ、新しい脆弱性の混入を防ぐことができます。
リリース時にチェックを適用したいチーム向けに、リリースゲーティングもサポートしています。
PRゲーティングを有効にするには、--fail-on <severity> オプションを追加して希望する重大度レベルを選択します。次に、--gating-mode pr オプションを追加して、PRゲーティングを実行することを指定します。また、ベースコミット(--base-commit-id <commit-id>)とヘッドコミット(--head-commit-id <commit-id>)も指定する必要があります。ベースコミットIDに対して以前にスキャンが実行されている場合は、スキャン結果がその結果と比較されます。そうでない場合は、デフォルトブランチでの最新のスキャン結果と比較されます。
Jenkins環境でのLocal Scannerのセットアップに関する一般的な情報については、こちらの記事をご覧ください。
仕組み
構成要素は3つあります。
- SCMとJenkinsの間のインテグレーション。
- Discover pull requests の動作を設定した Multibranch Pipelineジョブ。これにより、Jenkinsは開いている各プルリクエストをビルドします。PRビルドでは、Jenkinsはソースブランチをチェックアウトし、標準の変更リクエスト用環境変数(
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のセットアップ
プルリクエストのビルドには Multibranch Pipeline ジョブが必要です。
- Jenkinsで New Item → Multibranch Pipeline を選択し、名前を付けて OK を選択します。
- Branch Sources で、Add source → 使用しているSCMを選択 します。
- リポジトリ を選択します。
- 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ゲーティングステージを追加する
リポジトリのルートに Jenkinsfile を追加(または既存のものを拡張)します。以下のステージは プルリクエストのビルドでのみ 実行され、Gitからベースコミットとヘッドコミットを取得し、PRゲーティングモードでスキャナーを実行します。ゲートが失敗した場合にスキャナーがゼロ以外の終了コードを返すことで、ビルドが失敗します。
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でゲートの適用を設定してください。