Posted at

sudoで実行ユーザのPATHを引き継ぐ


はじめに

sudoで実行ユーザのPATHを引き継ぐ方法を検索すると、こちらの記事などがヒットし、それで目標は達成できます。

なぜできるのかということについて調べ、より良い解決策を得たため、記録しておきます。


環境

Ubuntu xenial


本文


secure_path

そもそも、なぜPATH環境変数は引き継がれないのでしょうか。それを知るにはsudoersファイルを見てみましょう。

すると、やはりこの行があると思います。

Defaults      secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/

sbin:/bin:/snap/bin"

これは一体どういう意味なのか、sudoのmanページを見てみます。


デフォルト設定 (Defaults)

かなりの設定オプションが、 一行以上の Default_Entry 行を指定することで実行時にデフォルトの値から変更可能だ。


Default_Type ::= 'Defaults' |

'Defaults' '@' Host_List |
'Defaults' ':' User_List |
'Defaults' '!' Cmnd_List |
'Defaults' '>' Runas_List

Default_Entry ::= Default_Type Parameter_List

Parameter_List ::= Parameter |
Parameter ',' Parameter_List

Parameter ::= Parameter '=' Value |
Parameter '+=' Value |
Parameter '-=' Value |
'!'* Parameter

つまり問題の行は、secure_path設定オプションを設定しているということです。ではsecure_path設定オプションとはなんなのか。


secure_path

sudo から実行されるあらゆるコマンドが使用するパス。 sudo を実行するユーザが、無難な PATH 環境変数 を使っているかどうか確信が持てないなら、 このオプションを使用するとよいだろう。もう一つの使用法は、 「root のパス」と「一般ユーザのパス」を別のものにしておきたい場合だ。 ユーザが exempt_group オプションで指定したグループに属していると、 そのユーザは secure_path の影響を受けない。 このオプションは、デフォルトではセットされていない。


ということで、これが設定されているとユーザのPATHが無視されるということですね。だから、これをコメントアウトしようという解決策が出るわけです。

しかし、このオプションは安全のために設定されているので、それをまるっと無視することは少しためらいます。

改めてmanページを見ますと、Defaults行について


その効果の及ぶ範囲は、あらゆるホストのすべてのユーザにすることもできるし、 ある特定のホストのすべてのユーザ、ある特定のユーザ、ある特定のコマンド、 ある特定のユーザとして実行するコマンドなどに限定することもできる。


とあるので、特定のユーザだけsecure_path設定オプションが適用されないようにするのがよいでしょう。更に、Defaults行の書式について

User_List ::= User |

User ',' User_List

User ::= '!'* user name |
'!'* #uid |
'!'* %group |
'!'* %#gid |
'!'* +netgroup |
'!'* %:nonunix_group |
'!'* %:#nonunix_gid |
'!'* User_Alias

とあるので、こう書くと良いでしょう。

Defaults:!exampleuser secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/

sbin:/bin:/snap/bin"

これでexampleuserだけsecure_path設定オプションが適用されないようになります。


他にやること

さて、secure_path設定オプションを外したわけですが、まだなにかやることがあるのでしょうか。よくある解決法としては次にenv_keep設定オプションでPATHが引き継がれるようにしていますが、これはなんなのか。


env_keep

env_reset オプションが有効になっているときでも、 ユーザの環境にそのまま保存される環境変数。このオプションによって、 sudo から生み出されるプロセスが受け取る環境を、 きめ細かく制御することが可能になる。このオプションの引き数は、 ダブルクォートで囲まれ、スペースで区切られたリストでもよく、 ダブルクォートなしの単一の値でもよい。 リストは、=, +=, -=, ! 演算子を使って、 それぞれ置き換えたり、追加したり、削除したり、無効にしたりすることができる。 保存される変数のグローバルなリストは、root ユーザが sudo に -V オプションを付けて実行したときに表示される。


とあります。確かに必要そうな気がしますが、ここはまずデフォルトの内容を確認しましょう。

$ sudo sudo -V

出力の「保護する環境変数」(ロケールによっては英語)を見てみますと、僕の環境では既にPATHが入っていました。つまり、env_keep設定オプションをいじる必要はないということです。

もし入っていない場合は設定する必要がありますが、ここでもユーザを絞っておきましょう。

Defaults:exampleuser    env_keep +=  "PATH"


まとめ

多分

Defaults:!exampleuser secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/

sbin:/bin:/snap/bin"

とするだけで十分です。