マシン上で、私(tlous
)は別のユーザーとしてシェルを開くためのアクセス権を与えられました(serviceAccount
)
実行中:Sudo su - serviceAccount
には、このserviceAccount
ユーザーとしてシェルを開くという望ましい効果があります。ここまでは順調ですね。
これは素晴らしいですが、シェルを開かずにこのユーザーとしてコマンドを実行したいと思います。
コマンドがwhoami
だとしましょう
私はもう試した:
Sudo -u serviceAccount whoami
申し訳ありませんが、ユーザーtlousはserviceAccountとして '/ usr/bin/whoami'を実行できません。
Sudo su - serviceAccount -c whoami
申し訳ありませんが、ユーザーtlousは '/ bin/su --serviceAccount -cwhoami'を実行できません...
そして他のバリエーション。何が足りないのですか?これはワンライナーで行うことができますか?その理由は、実際にこれをsshコマンドとして実行したいからです。ssh -t [email protected] Sudo su - serviceAccount -c whoami
おそらく、リモート側のsudoers
ファイルは、実行できる正確なコマンドを指定しており、それはsu - serviceAccount
です。 1つ以上の追加オプション(-c
など)を使用すると、コマンドが修飾されなくなります。どのソリューションでも、正確なsu - serviceAccount
コマンドを使用する必要があります。
それについて何かをする方法はありますが、それは完璧ではありません。サーバーでこれを実行することから始めます。
echo whoami | Sudo su - serviceAccount
(-S
のないSudo
は、リダイレクトにもかかわらず、端末を使用して(必要に応じて)パスワードを要求します)。
アプローチをより一般的にするには、サーバー上にスクリプトを作成します。
#!/bin/sh
printf '%s ' "@" | Sudo su - serviceAccount
su-ser
として保存し、実行可能にします。今、あなたはこれらをテストすることができます:
./su-ser whoami
./su-ser 'whoami; whoami'
./su-ser ls -l
./su-ser 'ls -l'
これらの引用符は、su
によって生成されたシェルには伝播されないことに注意してください。 printf
がスクリプトが取得する引数からコマンドを作成するたびに、これはstringとして渡され、最後のシェルによってparsedとして渡され、Wordの分割やグロブなどが行われます。これはこれらすべてを意味します
./su-ser echo 1 2 3
./su-ser echo "1 2 3"
./su-ser "echo 1 2 3"
1 2 3
を出力します。 quoted文字列を渡すには、引用符を引用する必要があります。例:
./su-ser 'echo "1 2 3"'
次のステップは、ローカルコンピューターからこのリモートスクリプトをトリガーすることです。
ssh -t [email protected] '"/path/to/su-ser" whoami'
Sudo
がパスワードを要求する場合に備えて、-t
が必要です。質問本文のssh
コマンドから、おそらくこれを理解していると言えます。
注ssh
もコマンドを作成しますstring。上記の引用は、/path/to/su-ser
にスペースが含まれている場合でも機能します。一方、パスにスペースがない場合(および、;
、*
などの文字がない場合)、完全に引用符で囲まれていないssh … /path/to/su-ser whoami
も機能します。
現時点では、適切な見積もりは簡単な作業ではありません。コマンドに何が起こるかを分析してみましょう。
ssh
は、引数を配列として取得します。シェルによって使用された引用符は、ここまで到達しません。ssh
は、リモート側に渡す引数を決定し、文字列を作成します(リモートスクリプトのprintf
と同様の方法で)。sshd
によって生成されたもの)によって解析されます。リモートシェルは、(現在)最も外側の引用符(存在する場合)を使用して、正しく解析します。su-ser
は、引数を配列として取得します。リモートシェルによって使用された見積もりは、ここまで到達しません。su-ser
は文字列を作成します。su
によって生成されます)。シェルは、(現在)最も外側の引用符(存在する場合)を使用して、正しく解析します。つまり、正しい結果を得るには、threeレベルの引用符が必要になる場合があります。のような単純なローカルコマンド
echo "1 2 3"
になります
ssh -t [email protected] "'/path/to/su-ser' 'echo \"1 2 3\"'"
エスケープされていない二重引用符はローカルシェルによって削除され、一重引用符はリモートシェルによって削除されます。最後に、エスケープされた二重引用符(実際には、ローカルシェルがエスケープされていないものを削除するとすぐにエスケープされなくなります)は、su
によって生成されたシェルに、複数のスペースを含む文字列がecho
に対する単一の引数であることを通知します。このように出力は
1 2 3
もう1つの問題は、リモートスクリプトがコマンドを最終シェルのstdinに渡すため、そのstdinを別の目的に簡単に使用できないことです。例えば。 cat; whoami
(試してみてください)は、入力した行を出力します(で終了します) Ctrl+D)、次にwhoami
の出力。ただし、これをサーバーで実行する場合:
./su-ser 'cat; whoami'
cat
はすぐに終了します。これは機能するはずです:
./su-ser 'cat /dev/tty; whoami'
(繰り返しますが、 Ctrl+Dcat
を終了します)。次に、この動作を比較します。
./su-ser '
whoami
whoami
whoami
'
これに:
./su-ser '
whoami
cat
whoami
'
同じストリームがcat
とシェルにフィードします。それは良いことではありません。 Sudo
はデフォルトで追加のファイル記述子を閉じ、新しい最小限の環境を設定するため、実際のコマンドと実際のstdinに別々のチャネルを確立するのは簡単ではない場合があります。 I guess一時ファイル/ fifosを使用した矛盾は機能しますが、これは非常に毛深いので、試してみません。
したがって、スクリプトで十分な場合と不十分な場合があります。実行する必要のあるコマンドによって異なります。これで、いくつかの制限がわかりました。幸運を。