App Service on Linux に公開鍵認証で SSH する

はじめに

また「試してみた」です。
知ってる人は知ってそう。

役に立つかは未知数。

パスワード認証が煩わしかった。

前のエントリーで、App Service on LinuxVS Code Remote Development を使うために、Azure CLI で SSH トンネルを作る方法について触れました。

uncaughtexception.hatenablog.com

通常、App Service on LinuxSSH は、Web SSH 向けにパスワード認証のみが有効化されています。
例えば、node.js 10.14 の Blessed Image の sshd_config はこちらです。

# This is ssh server systemwide configuration file.
#
# /etc/sshd_config

Port            SSH_PORT
ListenAddress       0.0.0.0
LoginGraceTime      180
X11Forwarding       yes
Ciphers aes128-cbc,3des-cbc,aes256-cbc,aes128-ctr,aes192-ctr,aes256-ctr
MACs hmac-sha1,hmac-sha1-96
StrictModes         yes
SyslogFacility      DAEMON
PasswordAuthentication  yes
PermitEmptyPasswords    no
PermitRootLogin     yes
Subsystem sftp internal-sftp

github.com

認証情報も Dockerfile に直書きされています。

(snip)
RUN npm install -g pm2 \
     && mkdir -p /home/LogFiles /opt/startup \
     && echo "root:Docker!" | chpasswd \
(snip)

github.com

なので、VS Code Remote Development で App Service on Linuxディレクトリーを開くたびにパスワードを聞かれてしまいます。

これがメンドクサイ。

ちなみに Web App for Containers

カスタム コンテナーが使える Web App for Containers で Web SSH 接続を使う場合も、同様の認証情報を Dockerfile で指定するよう記載されています。

docs.microsoft.com

直接的な SSH 接続ができるのは、Azure プラットフォーム側からのみなので、認証情報が公開・固定されていても問題ないのかもしれません。

SSH の公開鍵認証を有効にする

基本的に、普通の SSH の設定と同じです。

なので、

  1. 公開鍵を /root/.ssh/authorized_keys (permission 注意) に追記
  2. PubkeyAuthentication yes/etc/ssh/sshd_config に追記
  3. service ssh restart で再起動

をすると、有効になるはずです。

ただし App Service on Linux では、再起動のたびに /home 以外のディレクトリーが初期化される 、という特性があるので、起動のたびに上記の公開鍵認証の有効化を行う必要があります。

スタートアップ コマンド

「起動のたびに」といえば、スタートアップ コマンドの出番です。

下記に、公開鍵認証の有効化に必要なスクリプトを抜粋しました。

mkdir /root/.ssh/
cat /home/PATH/TO/id_rsa >> /root/.ssh/authorized_keys

chmod 600 /root/.ssh/authorized_keys
chmod 700 /root/.ssh

echo "PubkeyAuthentication    yes" >> /etc/ssh/sshd_config
service ssh restart

公開鍵 は /home 以下に置いて、/home/PATH/TO/id_rsa を配置したパスに置き換えてください。

上記処理を含んだスクリプト/home 以下 (のどこか) において、下記スクリーンショットの個所にスタートアップ コマンドとして指定すると、起動時に公開鍵認証の有効化が行われます。

f:id:horihiro:20200209150034p:plain

試してみる

まずは、Azure CLISSH トンネルを作成します。

$ az webapp create-remote-connection --ids <resource_id> -p <port>
Opening tunnel on port: <port>
SSH is available { username: root, password: Docker! }
Ctrl + C to close

公開鍵認証有効化後も、認証情報が表示されますが、問題ありません。

次に別のターミナルを開いて、localhostSSH で接続します。

$ ssh root@localhost -p <port> -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null
Warning: Permanently added '[localhost]:<port>' (ECDSA) to the list of known hosts.
Last login: Sun Feb  9 05:20:17 2020 from 172.16.0.2
  _____
  /  _  \ __________ _________   ____
 /  /_\  \___   /  |  \_  __ \_/ __ \
/    |    \/    /|  |  /|  | \/\  ___/
\____|__  /_____ \____/ |__|    \___  >
        \/      \/                  \/
A P P   S E R V I C E   O N   L I N U X

Documentation: http://aka.ms/webapp-linux
NodeJS quickstart: https://aka.ms/node-qs
NodeJS Version : v10.17.0
Note: Any data outside '/home' is not persisted

root@6687088aa342:/home#

秘密鍵~/.ssh/id_rsa というパスにあれば、ログイン時にパスワードを聞かれずにそのままログインできます。

ログイン時のインタラクションがなくなったので、ssh 接続と同時に下記のようなコマンド実行もパスワード入力なしで出来るようになりました。

$ ssh root@localhost -p <port> -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null <command> 2>/dev/null

意外と何でもできて、いじり甲斐があります。