Jenkinsfile で sudo する方法

この記事は約6分で読めます。

Jenkinsfile からなんかしらのコマンドを sudo で実行させたいときがあります。
そういうときに設定やJenkinsfileをどう書けばいいのか、数パターンあるのでそれをまとめてみます。

スポンサーリンク

ユーザjenkinsの設定

まずはそもそもユーザ jenkins がsudoできるように設定が必要です。
下記のコマンドでまずユーザjenkins のパスワードを設定します。
パスワードは任意のパスワードでOKです。

$ sudo passwd jenkins

つぎに jenkins を sudo できるグループに追加します。Ubuntuのときは下記でOKです。
他のディストリビューションについてはググってみてください。

$ sudo usermod -aG sudo jenkins

ここまで来たら jenkins で sudo できるはずです。下記のように jenkins にスイッチして whoami してみてください。
root と返ってくるはずです。


$ su jenkins
$ sudo whoami
root
$ exit

ここまでは下記のどの方法をするにしもて必要な作業です。

スポンサーリンク

パスワード無しでsudoできるようにする

ユーザ jenkins ではパスワードなしでsudoできるようにしてしまう方法です。
力強すぎるのであまりおすすめはしませんが、まずは紹介します。

sudoの設定を変更する下記のコマンドを実行します。

$ sudo visudo

すべてのコマンドをパスワード無しで実行するには下記のように記述します。

Defaults:jenkins !requiretty
jenkins ALL=(ALL) NOPASSWD:ALL

全部のコマンドは必要ない場合は必要なコマンドだけパスワードなしにもできます。
下記の例ではコマンド /path/to/command だけパスワードなしにする設定です。
詳細は「sudoers NOPASSWD」でググると色々できてます。

Defaults:jenkins !requiretty
jenkins ALL=(ALL) NOPASSWD: /path/to/command
スポンサーリンク

expectコマンドを使う

対話的コマンドを自動化するツールに expectがあります。対話的なコマンドを自動化できるすぐれものです。ベースがTcl なので結構とっつきにくいです。

かなり難解ですが、下記のページが基本的な情報です。
https://linuxjm.osdn.jp/html/expect/man1/expect.1.html

Jenkinsfile にかくときはシェバンを /usr/bin/expect にすればOKです。下記の例はsudoするときの例でdす。
spawn がプロセス実行、expect がコマンドからのレス待ち、sendがコマンドへの入力です。下記のコードを見ればなんとなくわかるかと思います。
最後のexpectはプロンプトの「$」が表示されるのを待っています。

withCredentials([usernamePassword(credentialsId: 'user_jenkins', passwordVariable: 'jenkins_password', usernameVariable: 'jenkins_username')]) {
        sh """\
           |#!/usr/bin/expect -f
           |spawn sudo bash -c \"rm -rf *\"
           |expect -re "password for $jenkins_username"
           |send -- "$jenkins_password\\r"
           |expect "\$"
           """.stripMargin()}
スポンサーリンク

askpassを使う

これが一番おすすめです。askpass については下記のサイトの紹介されていました。

askpassのことを書いておく - なんかかきたい
askpassとは何なのか askpass とはその名の通り、プログラムからパスワードが必要になったときに呼ばれるプログラムのこと。 よくある使われ方としては、GTKのプログラムで特権が必要になった際に、sudo のパスワードを尋ねるための...

パスワードを標準出力に吐くスクリプトを作って、環境変数SUDO_ASKPASS にそのスクリプトのパスを設定すればOKです。
sudo するときに -A をつけます。

jenkinsfile の例

Jenkinsで書くと下記のようになります。
パスワードを吐くスクリプトをワークスペースにおいてしまうと、ブラウザからアクセスできてしまうので WORKSPACE_TMP を利用します。

withCredentials([usernamePassword(credentialsId: 'user_jenkins', passwordVariable: 'jenkins_password', usernameVariable: 'jenkins_username')]) {
    script {
        // パスワードを標準出力に吐き出すスクリプト作成
        // sudo には -A オプションが必要
        // WORKSPACEの下にスクリプトを置くと、そのスクリプトをブラウザから参照できてしまうので
        // WORKSPECE_TMP を利用している
       sh  "mkdir -p $env.WORKSPACE_TMP"
        String sudoAskpass = sh(returnStdout: true, returnStatus: false, script: "mktemp --tmpdir=${env.WORKSPACE_TMP}/ ${BUILD_TAG}.XXXXXXXXXX").trim()
        sh """\
           |#!/bin/bash -eu
           |echo -e '#!/bin/bash\\necho $jenkins_password' > $sudoAskpass
           |chmod u+x $sudoAskpass
           |export SUDO_ASKPASS=$sudoAskpass
           |sudo -A whoami
           |""".stripMargin()

        // もう一度sudoを使うにはexportが必要
        sh """\
           |#!/bin/bash -eu
           |export SUDO_ASKPASS=$sudoAskpass
           |sudo -A whoami
           |""".stripMargin()
        }
    }
}
スポンサーリンク

まとめ

Jenkinsfile からsudo する方法を説明しました。expect か askpass を使うのがいいかなと思います!

コメント