• システム開発に関わる内容をざっくりと書いていく

Jenkins パイプラインが権限エラーで落ちるときの切り分け

Jenkins のパイプラインが権限エラーで落ちる。ログには Permission denied と出るが、拒否されている対象はスクリプトだったりワークスペースだったり認証情報だったりとバラバラで、ここを分けずに権限を足し続けると迷子になる。まず「何が・どこで拒否されたか」をログから特定するのが先。

先に結論

  • スクリプトが起動しない Permission denied は、実行ビット無し・所有者ズレが本命
  • ワークスペースへ書けない系は、jenkins ユーザーと手動実行・Docker 実行の所有者が混ざった跡が多い
  • Git / SSH で落ちる場合は、秘密鍵のパーミッションと Credentials の権限範囲を見る
  • docker コマンドが拒否されるのは、ソケット(/var/run/docker.sock)への権限不足が定番
  • 権限を広く開けるその場しのぎは対処ではなく穴。最小権限でピンポイントに直す

エラーの出方で分ける

  • script.sh: Permission denied → 実行ビットか shebang の問題
  • cannot create file / 書き込みエラー → ワークスペースの所有者・権限
  • Authentication failed / Permission denied (publickey) → 認証情報まわり
  • permission denied while trying to connect to the Docker daemon socket → Docker ソケット権限
  • ジョブの実行自体が弾かれる → Jenkins の権限マトリクス / フォルダ権限

実行ビットと shebang

Git 管理下のスクリプトは、コミット時点で実行ビットが落ちていることがよくある。ジョブ内で bash script.sh の形で呼ぶか、リポジトリ側でビットを付けて切り分ける。

git update-index --chmod=+x script.sh
# 応急確認だけなら
sh script.sh

もう1つの定番が、Windows で編集したスクリプトの改行コード(CRLF)で shebang が壊れ、bad interpreter 系になるケース。権限エラーと似た出方をするので、改行コードも一緒に疑う。

ワークスペースの所有者ズレ

エージェント上で root 権限の Docker を回したり、手動で root のままビルドしたりすると、ワークスペース内に root 所有のファイルが残り、次のジョブが jenkins ユーザーで書けなくなる。

  • 失敗したワークスペースで ls -la を見て、所有者が混ざっていないか確認する
  • 対処は chown -R jenkins:jenkins で揃えるのが基本
  • 切り分けとしてワークスペースを消して再実行する手もある(ジョブ履歴ではなく作業領域だけ)
  • そもそもエージェント上で手動作業をしない、が再発防止として一番効く

認証情報(Credentials)まわり

  • SSH 秘密鍵はパーミッションが緩いとクライアント側に拒否される。Credentials に登録した鍵自体の正しさも疑う
  • known_hosts 未登録で対話プロンプト待ちになり、タイムアウトや認証失敗に見えることがある
  • Git のトークン / 認証情報は対象リポジトリへの権限(読み取り・サブモジュール含む)があるか確認する
  • 認証情報の ID をジョブ間で取り違えていないかも地味に多い

Docker と sudo

  • Docker ソケットを使うなら、jenkins ユーザーを docker グループに入れるのが定石。ただしこれは実質 root 相当の権限だと理解して使う
  • sudo が必要な処理は sudoers でコマンドを絞る。NOPASSWD の範囲を広げない
  • 「とりあえず 777」は次回の事故の種。誰が・何に・なぜ必要かで決める

Jenkins 側の権限設定

  • 全体権限(Overall)とアイテム権限(Job/Build など)は別物。パイプライン実行に必要な最小限を割り当てる
  • フォルダ単位で権限を分けている場合、移動したジョブが権限を失うことがある
  • スクリプト承認(Script Approval)待ちで止まっているケースは、権限エラーではなく承認フロー側の問題

予防

  • エージェントは使い捨て(コンテナ / 一時ノード)に寄せ、状態と所有者ズレを持ち込まない
  • 権限は「足りない分だけ足す」を徹底し、変更理由をジョブ定義や手順書に残す
  • 失敗ログの最初の拒否行を必ず見る。末尾のスタックトレースだけ追わない

ざっくりまとめ

  • 拒否の対象(ファイル / ワークスペース / 認証 / ソケット / Jenkins 本体)をログで分ける
  • スクリプトは実行ビット、ワークスペースは所有者、Docker はソケット権限が本命
  • 広く開けるのではなく、最小権限でピンポイントに直す

関連記事