さまざまなシェルコマンドを実行するPHPプログラムを作成しています。場合によっては、su
を呼び出す必要がありますが、設計上、昇格された特権パスワードの入力を求める必要があります。 PHPでpassthru()
を使用すると、これで問題なく動作します。
ssh
、su
、およびその他のシェルコマンドに依存しているため、プログラムに対してのみ機能テストを作成することを選択しました。したがって、PHPUnit内で本物を実行して、期待どおりに機能しているかどうかを確認したいと思います。
これにはSSHサーバーとユーザーアカウントの構成が必要なため、Dockerで実行するようにテストを設定しました。このアプローチは問題ないように見えます。イメージがビルドされ、実行されるとPHPUnitが呼び出され、終了します。 Dockerを介してTravisCIなどの呼び出しシステムに結果を返す方法があると思います。
ベースのDockerイメージとしてAlpineLinuxを選択しましたが、ターミナルの割り当てに問題があります。私は当初、PHPUnitが邪魔になっていると思っていましたが(この質問の元のバージョンを参照)、PHPで実行するか、コンソールで実行するかのいずれかで、SSHに絞り込みました。
これは正常に機能します。
_su -c whoami
_
ただし、これは行いません。
_ssh localhost -t 'su -c whoami'
_
私は得る:
su:正しく動作するにはsuidである必要があります
ローカルホストへの接続が閉じられました。
ssh
はローカルホストへのパスワードなしのアクセス(テスト目的)で設定されているため、入力する予定のパスワードはsu
のパスワードのみであることに注意してください。
ssh
のマニュアルでは、_-f
_がパスワードを要求する場所(スイッチは「コマンド実行の直前にsshにバックグラウンドに移動するように要求する」)に役立つと示唆しているので、これを試してみます。
_ssh localhost -t -f 'su -c whoami'
_
そして私は得る:
Stdinは端末ではないため、疑似端末は割り当てられません。
4275760bde94:〜$ su:正しく動作するにはsuidが必要です
ああ、別のエラー! OK、それで 私はこれらのアイデアを試しました 、特に端末を強制します:
_ssh localhost -tt -f 'su -c whoami'
_
Double-tはまだSUIDに関する苦情を出し、それでも機能しません。
ただし、Ubuntu開発マシン(自分自身へのPPKアクセスも構成されている)でこれを行うと、正常に機能します。
_$ ssh localhost -t 'su -c whoami'
Password:
root
Connection to localhost closed.
_
これにより、AlpineまたはBusyBoxのOpenSSHに問題があるように見えます。どうすればこれをさらに掘り下げることができますか?
1つの解決策は、別のベースディストリビューションに交換することです。Ubuntuは確かに正常に動作しますが、それは私のDockerイメージサイズを大幅に膨らませます(現在、合計で非常に素晴らしい68Mです)。ですから、できればアルパインを少し使い続けたいと思います。
Dockerがターミナルの作成や接続を妨げているのではないかと思いましたが、_docker exec -it container_name sh
_でインタラクティブなシェルを取得できるため、すぐにこれを割り引いてしまいました。さらに、Dockerシェル内の2つの別々のコマンドでssh
とsu
を実行できます。
BashがAlpineで利用可能であることに気付きましたが、これも役に立たなかったので、私は驚いています。
_/ $ apk add bash
bash-4.3$ bash
bash-4.3$ su nonpriv
bash-4.3$ ssh localhost whoami
nonpriv
bash-4.3$ ssh localhost 'su -c whoami'
su: must be suid to work properly
bash-4.3$ ssh localhost 'su -s /bin/bash -c whoami'
su: must be suid to work properly
bash-4.3$ ssh -t localhost 'su -s /bin/bash -c whoami'
su: must be suid to work properly
Connection to localhost closed.
bash-4.3$ ssh -tt localhost 'su -s /bin/bash -c whoami'
su: must be suid to work properly
Connection to localhost closed.
bash-4.3$ ssh -tf localhost 'su -s /bin/bash -c whoami'
Pseudo-terminal will not be allocated because stdin is not a terminal.
bash-4.3$ su: must be suid to work properly
bash-4.3$ ssh -ttf localhost 'su -s /bin/bash -c whoami'
bash-4.3$ su: must be suid to work properly
Connection to localhost closed.
_
私はこれがほぼ機能することを発見しました:
_/ $ ssh -t localhost "$( su -c whoami )"
sh: Password:: not found
sh: root: not found
Connection to localhost closed.
_
これは、標準のAlpine sh
Shellを使用し、前述のリンクにある"$()"
構文を使用しますが、これは完全には理解していません。 su
のプロンプトである_Password:
_を出力し、パスワードを待ちます。パスワードを入力すると、whoami
が実行され、root
が出力されます。
したがって、コマンドを実行しているように見えますが、すぐにwhoami
を実行してから、それをssh
に渡すのか(私が望むものではない)、またはコマンドを取得しているかどうかはわかりません。リモートシェルをローカルホストに接続してから実行します(これが私が意図していることです)。
いずれにせよ、stdout行をコマンド自体であるかのようにrunしようとしています。 SSH経由で実行された出力を印刷するだけでどうすればよいですか?
私の質問では、これはUbuntuコンテナーで機能すると推測し、それが正しいことが証明されました。興味深いことに、このコマンドでも「ターミナルから実行する必要があります」というエラーが表示されます。
su -c whoami
ただし、ここでは、SSHパスワードなしコマンドで端末が自分自身に明示的に割り当てられています。
ssh -t localhost 'su -c whoami'
残念ながら、新しいOSによって68Mのイメージが430Mに増えました。したがって、これをアルパインで機能させる新しい回答を受け取って、私は最も幸せになるはずです。