Jenkins セキュリティトラブルシューティング: アクセス拒否と認可エラー

Jenkinsで「アクセス拒否」や認可エラーに直面していませんか?この包括的なガイドでは、一般的なセキュリティ問題の診断と解決方法を解説します。認証と認可の違い、セキュリティレルムと戦略設定の確認方法、システムログの解釈、CSRF保護の問題への対処法を学びます。実践的なトラブルシューティング手順、緊急アクセス手順、Jenkinsインスタンスを保護するための重要なベストプラクティスを紹介し、認可されたアクセスと堅牢なCI/CDパイプラインを確保します。

Jenkins セキュリティトラブルシューティング: アクセス拒否と認可エラー

Jenkinsのアクセス問題は、誰かがデプロイ、失敗したビルドの再実行、または本番環境の修正を必要とするときに発生することが多いため、ストレスが溜まります。エラーメッセージは「アクセス拒否」、「権限がありません」、「403 No valid crumb」、「anonymous is missing Overall/Read」、または単にユーザーをログインページに戻す場合があります。これらのメッセージは似ていますが、Jenkinsセキュリティの異なる部分を示しています。

Jenkinsセキュリティトラブルシューティングを迅速に行うには、3つの質問を分離することが重要です。Jenkinsはユーザーを認識しましたか?Jenkinsは適切な権限を付与しましたか?リクエストはJenkinsのリクエスト保護を通過しましたか?認証、認可、CSRF保護は別々のレイヤーです。これらを1つの曖昧な「ログイン問題」として扱うと時間の無駄になります。

Jenkinsセキュリティの基礎を理解する

トラブルシューティングに入る前に、Jenkinsセキュリティの核となる概念である認証と認可を理解することが重要です。

認証と認可

  • 認証: これはユーザーの身元を確認するプロセスです。「あなたは誰ですか?」という質問に答えます。ユーザー名とパスワードでログインすると、Jenkinsはセキュリティレルムに対してあなたを認証しています。
  • 認可: これは認証されたユーザーが何を許可されているかを決定するプロセスです。「ここで何ができますか?」という質問に答えます。Jenkinsがあなたが誰かを認識すると、認可戦略に基づいて権限をチェックし、ジョブの表示、システムの設定、ビルドの開始などが可能かどうかを判断します。

Jenkinsセキュリティレルム(認証)

セキュリティレルムは、Jenkinsがユーザーをどのように認証するかを定義します。一般的なオプションは次のとおりです。

  • Jenkins独自のユーザーデータベース: ユーザーはJenkins内で直接作成および管理されます。
  • LDAP: 既存のLDAPサーバー(例:Active Directory)と統合してユーザーを認証します。
  • Unixユーザー/グループデータベース: 基盤となるオペレーティングシステムのユーザーアカウントに対して認証します。
  • SAML / OAuth: シングルサインオンのためにIDプロバイダーと統合します。

Jenkins認可戦略

認可戦略は、認証されたユーザーが何をできるかを定義します。主な戦略は次のとおりです。

  • ログインユーザーは何でもできる: シンプルですが、通常は本番環境には広すぎます。ログインできる人は誰でも管理権限を持つことになります。
  • レガシーモード: 古いインストールとの互換性のために保持されています。本番システムでは避けてください。
  • マトリックスベースのセキュリティ: グローバルおよびプロジェクト固有のコンテキストにわたって、個々のユーザー/グループに対するきめ細かい権限制御を可能にします。
  • プロジェクトベースのマトリックス認可戦略: マトリックスベースのセキュリティの拡張で、プロジェクト固有の権限がグローバル設定を上書きできるようにします。
  • ロールベース戦略プラグイン: ユーザーをロールに割り当て、ロールを特定の権限(グローバル、フォルダー、またはプロジェクトレベル)に割り当てることで、権限管理を簡素化する人気のプラグインです。

「アクセス拒否」エラーにつながる一般的なシナリオ

「アクセス拒否」または同様の認可エラーは、通常、次のいずれかの状況から発生します。

  1. 誤った資格情報: 単純なユーザー名またはパスワードの入力ミス。
  2. ユーザーが見つからない: ログインしようとしているユーザーが、設定されたセキュリティレルムに存在しません。
  3. 権限不足: ユーザーは認証されていますが、要求されたアクション(例:ジョブの表示、システム設定の構成)を実行するために必要な認可が不足しています。
  4. セキュリティレルム設定の問題: 外部認証ソース(例:LDAPサーバーダウン、バインドDNの誤り)への接続に関する問題。
  5. CSRF保護: Jenkinsの組み込みクロスサイトリクエストフォージェリ保護が、正当なプログラムによるリクエスト(例:スクリプトや外部ツールからのリクエスト)をブロックしています。
  6. プラグインの競合または設定ミス: セキュリティ関連のプラグイン(例:ロールベース戦略)が誤って設定されているか、別のプラグインと競合しています。
  7. Jenkinsアップグレードの問題: メジャーなJenkinsアップグレード後、セキュリティ設定の調整が必要になることがあります。

「アクセス拒否」と認可エラーのトラブルシューティング

これらの問題を診断して解決するための体系的なアプローチを見ていきましょう。

ステップ1: 認証の確認(ユーザーは認識されていますか?)

  • 資格情報を確認する: ユーザー名とパスワードが正しいことを確認します。簡単に聞こえますが、これが原因であることがよくあります。

  • 既知の有効なアカウントでテストする: 管理者アカウントがある場合は、それでログインしてみてください。管理者アカウントが機能する場合、問題は特定のユーザーの認証または認可にある可能性が高いです。管理者アカウントも失敗する場合は、より広範なセキュリティレルムの問題を示しています。

  • セキュリティレルム設定を確認する: Manage Jenkins > Configure Global Securityに移動します。

    • Jenkins独自のユーザーデータベース: Manage Jenkins > Manage Usersでユーザーが存在するか確認します。
    • LDAP: LDAPサーバーのURL、Manager DN、Manager Password、User Search Baseを確認します。JenkinsサーバーがLDAPサーバーに到達できることを確認します(ネットワーク接続を確認)。利用可能な場合は「Test LDAP settings」ボタンを確認します。
    # 例: JenkinsサーバーからLDAP接続をテストする(LDAPサーバー/ポートに置き換えてください)
    nc -vz ldap.example.com 389
    

ステップ2: 認可設定の確認(ユーザーは何ができますか?)

ユーザーが認証されたら、次のステップは正しい権限を持っていることを確認することです。

  • アクティブな認可戦略を特定する: Manage Jenkins > Configure Global Securityに移動し、選択されている認可戦略を確認します。

  • マトリックスベースのセキュリティ:

    • Configure Global Securityページでグローバル権限マトリックスを確認します。ユーザーまたはユーザーが属するグループが必要なグローバル権限(例:Overall/ReadJob/Read)を持っていることを確認します。
    • プロジェクトベースのマトリックス認可が有効になっている場合は、個々のジョブ設定でオーバーライドを確認します。ユーザーはグローバルなRead権限を持っていても、特定のプロジェクトで明示的に拒否されている可能性があります。
  • ロールベース戦略プラグイン:

    • Manage Jenkins > Manage and Assign Roles(またはプラグインバージョンによっては類似の場所)に移動します。
    • ロールが適切な権限(例:global rolesproject rolesfolder roles)で定義されていることを確認します。
    • ユーザーが正しいロールに割り当てられていることを確認します。
  • ヒント: 「Who Am I?」リンクを使用する: ログイン後(制限されたアクセスでも)、右上のユーザー名をクリックし、「Who Am I?」をクリックします。このページには現在のユーザーの詳細と権限が表示され、デバッグに非常に役立ちます。

ステップ3: Jenkinsシステムログを調べる

Jenkinsログは、内部で何が起こっているかについての詳細な洞察を得るための最良の友です。

  • 場所: Jenkinsログは通常、$JENKINS_HOME/logs/jenkins.logにあります。Manage Jenkins > System Logからも表示できます(権限がある場合)。

  • 検索するキーワード: Access Deniedauthentication failedauthorization failurepermission deniedSecurityFilterAuthenticationManagerAuthorizationStrategyを探します。

    # 例: 最近のJenkinsログから一般的なセキュリティ用語を検索する
    grep -Ei 'access denied|authentication|authorization|permission|crumb|csrf' "$JENKINS_HOME/logs/jenkins.log"
    

設定を変更する前にエラーを読む

正確なテキストが重要です。anonymous is missing the Overall/Read permissionは、通常、Jenkinsがリクエストをログインユーザーに関連付けなかったことを意味します。これは、ブラウザセッションの有効期限が切れたり、リバースプロキシがCookieをドロップしたり、APIトークンが送信されなかったり、スクリプトが間違った認証方法を使用したりした場合に発生する可能性があります。Jenkinsがリクエストを匿名として見ている場合、ユーザーにより多くの権限を付与しても役に立ちません。

user is missing Job/Buildは、認証は成功したが認可が失敗したことを意味します。その場合は、認可戦略、フォルダー権限、プロジェクトマトリックス設定、ロール割り当てを確認してください。フォルダーベースのJenkins設定では、最初にフォルダーを確認してください。ユーザーがグローバルな読み取りアクセス権を持っていても、1つのフォルダー内で権限が不足している可能性があります。

No valid crumb was included in the requestはCSRF保護を示しています。これは、ユーザー名とパスワードのみを使用してJenkinsにPOSTするスクリプトでよく見られます。最新の自動化では、通常、APIトークンを使用し、/crumbIssuer/api/jsonからクラムを取得するか、クラムを正しく処理するクライアント/ライブラリを使用する必要があります。1つのスクリプトを動作させるためだけにCSRF保護を無効にしないでください。

プラグインのアップグレード後のAccess Deniedは、多くの場合、プラグインが以前よりも特定の権限をチェックし始めたか、UIリンクが別の権限で保護されたページに移動したことを意味します。タイミングがアップグレードと一致する場合は、プラグインの変更ログを確認してください。マトリックスセキュリティからロールベースのセキュリティに切り替えた後に問題が発生した場合は、ロール名が同じ意味を持つと想定するのではなく、古い権限と新しいロールを1つずつ比較してください。

安全なトラブルシューティングの順序

通常のブラウザログインから始めてください。古いCookieがテストを混乱させないように、プライベートウィンドウを使用してください。ユーザーがログインできない場合は、セキュリティレルムに焦点を当ててください:ローカルのJenkinsユーザーデータベース、LDAP、Active Directory、SAML、OAuth、または設定されているプロバイダー。ユーザー名の形式が変更されていないか確認してください。一部のIDプロバイダーはjaneを送信し、一部は[email protected]を送信し、一部はユーザーが入力するユーザー名のように見えない安定したIDを送信します。

ログインが機能する場合は、ユーザーのプロファイルと、利用可能であれば「Who Am I?」ページを開いてください。Jenkinsが認識するユーザーIDとグループ名を確認してください。これは、グループメンバーシップがIDチームの期待と一致しない可能性があるLDAPやSSOで特に役立ちます。グループマッピングが欠落していると、多くのユーザーから一度に権限が削除される可能性があります。

次に、既知の管理者アカウントでテストしてください。管理者がアクションを実行できる場合、インスタンスはおそらく正常であり、影響を受けるユーザーに権限が不足しています。管理者も失敗する場合は、より広範な設定の問題、プラグインの障害、リバースプロキシの問題、または壊れたクラム/セッションの動作を探してください。

次に、影響を受ける最小のオブジェクトを確認してください。ユーザーが1つのジョブをビルドできない場合、グローバルセキュリティを変更することから始めないでください。そのジョブ、そのフォルダー、継承された権限、ロールパターン、およびプロジェクトベースのマトリックスエントリを確認してください。team-a/.*のようなロールパターンは、正規表現が大文字と小文字を区別するか、狭く書きすぎている場合、Team-A/service-apiのように名前が変更されたフォルダーと一致しません。

APIトークン、クラム、および自動化の失敗

多くのJenkinsセキュリティインシデントは、人間のログイン問題ではありません。これらは、以前は機能していたが現在は失敗するスクリプトです。最初に確認する必要があるのは、スクリプトが実際のパスワードではなくAPIトークンを使用しているかどうかです。APIトークンはローテーションが容易で、運用上のスコープを安全に設定できます。

単純なリクエストは次のようになります。

curl -u "deploy-bot:${JENKINS_TOKEN}" \
  "https://jenkins.example.com/job/service-api/build?token=unused"

クラムを必要とするPOSTリクエストの場合は、最初にクラムを取得します。

CRUMB=$(curl -s -u "deploy-bot:${JENKINS_TOKEN}" \
  "https://jenkins.example.com/crumbIssuer/api/json" |
  jq -r '.crumbRequestField + ":" + .crumb')

curl -X POST -u "deploy-bot:${JENKINS_TOKEN}" \
  -H "$CRUMB" \
  "https://jenkins.example.com/job/service-api/build"

一部のJenkins設定では、APIトークンで認証されたリクエストをクラムチェックから除外しますが、他の設定ではバージョンやプラグインによっては依然としてクラムが必要です。異なる環境からの仮定をコピーするのではなく、インスタンスに対してテストしてください。

サービスアカウントの場合は、自動化に必要な権限のみを付与してください。デプロイメントトリガーには、1つのフォルダーに対するJob/Buildが必要な場合があります。おそらくOverall/Administerは必要ありません。同じトークンが10の無関係なスクリプトで使用されている場合は、個別のサービスユーザーに分割して、すべてを壊すことなく1つをローテーションまたは無効化できるようにします。

Jenkinsセキュリティのように見えるリバースプロキシの問題

JenkinsがNginx、Apache、ロードバランサー、またはIngressコントローラーの背後にある場合、セッションおよびクラムエラーはプロキシレイヤーから発生する可能性があります。Jenkinsが正しい外部URL、スキーム、ホスト、およびヘッダーを受信していることを確認してください。一般的な症状は、ログインが1つのページで機能し、次のページで失敗することです。これは、Cookieが間違ったホストにスコープされているか、JenkinsがリクエストをHTTPと見なしているのにブラウザがHTTPSを使用しているためです。

Manage Jenkins > Systemの下のJenkins URLを確認してください。これはユーザーが実際に開くURLと一致する必要があります。プロキシの場合は、X-Forwarded-ProtoX-Forwarded-Hostなどのヘッダーが正しく渡されていることを確認してください。WebSocketまたはエージェント接続が関係している場合は、ブラウザログインとは別にそれらのパスを確認してください。

ロードバランスされたコントローラーは特別な警告サインです。通常のJenkinsコントローラーはステートフルです。複数の独立したJenkinsコントローラーを1つのURLの背後に配置し、セッション、キュー状態、ジョブ状態がステートレスなWebアプリのように動作することを期待しないでください。Jenkinsの高可用性には、それ用に設計された製品またはアーキテクチャが必要であり、汎用のラウンドロビンロードバランサーではありません。

インスタンスを悪化させずに緊急アクセスする

全員がロックアウトされた場合は、ファイルを編集する前に一時停止してください。可能であれば、最初に$JENKINS_HOMEのバックアップまたはスナップショットを取得してください。セキュリティ設定はXMLファイルに保存されており、急いで編集すると復旧が難しくなる可能性があります。

通常の緊急回避パスは、config.xmlで一時的にセキュリティを無効にし、Jenkinsを再起動し、アクセスを回復し、UIからセキュリティ設定を修正し、すぐにセキュリティを再度有効にすることです。これは緊急時のアクションとして扱うべきであり、日常的な回避策ではありません。セキュリティが無効になっている間はネットワークアクセスを制限してください。変更内容を記録してください。インシデント中に公開された可能性のある資格情報をローテーションしてください。

Configuration as Codeを使用している場合は、UIにパッチを適用してソースファイルを忘れないでください。次のリロードで修正が元に戻る可能性があります。CasC YAMLを更新し、レビューし、アクセスが復元されたら通常のプロセスを通じて適用してください。

繰り返されるロックアウトを防ぐ

少なくとも2つの人間の管理者アカウントまたはグループを維持し、できれば異なる復旧パスでバックアップしてください。すべての管理者が1つのSSOグループに依存しており、そのグループマッピングが壊れた場合、誰もUIからJenkinsを修正できません。

認可モデルを平易な言葉で文書化してください。「開発者は自分のフォルダー内のジョブを読み取り、ビルドできます。リリースエンジニアはデプロイメントジョブを設定できます。プラットフォーム管理者はJenkinsを管理します。」これは、何百ものチェックボックスがあるマトリックスのスクリーンショットよりも役立ちます。

フォルダーの移動、プラグインの変更、SSOの変更、Jenkinsのアップグレード後に権限を確認してください。セキュリティ問題は、無害に見える名前変更やIDプロバイダーのクリーンアップの後に発生することがよくあります。

最後に、古い資格情報を削除する前に、サービスアカウントトークンをテストしてください。主要な自動化アカウントをチェックする短い監査スクリプトは、デプロイメントウィンドウを節約できます。セキュリティトラブルシューティングは、ログイン、権限評価、リクエスト保護、またはJenkinsの前のプロキシのどこで問題が発生したかを把握していると、はるかに簡単になります。