【Azure】Linux VMのSSHの公開鍵認証をデプロイ時に有効化する方法:Tech TIPS
LinuxにSSHでログインする際、パスワードではなく公開鍵で認証するのが一般的だ。では、AzureでLinuxの仮想マシンをデプロイする場合、最初からSSHの公開鍵認証を有効化しつつパスワード認証を禁止する具体的な方法は?
対象:Azure Virtual Machine(仮想マシン)、Linux、Bicep
LinuxにSSHでリモートからログインする際、認証にパスワードではなく公開鍵を利用するのが一般的になっている。特にインターネットから接続可能なサーバなどでは、パスワード認証は禁止して、より安全に運用できる公開鍵認証を有効化したいところだ。
本Tech TIPSでは、AzureでLinuxベースの仮想マシン(Virtual Machine、VM)をデプロイする際、最初から公開鍵認証を有効化しつつ、パスワード認証を禁止する方法を紹介する。デプロイにはBicepを用いる。また、すでに秘密鍵/公開鍵のペアが存在することを前提としている。
■執筆時の各種ツール/APIのバージョン
- Azure CLI: Ver. 2.50.0
- Bicep CLI: Ver. 0.19.5
- Bicepでのデプロイ時のAPIバージョン: 2022-11-01(仮想マシン生成)、2023-02-01(ネットワーク系リソース生成)
SSHで公開鍵認証のみ有効にしつつLinux VMをデプロイするには
AzureではLinuxの仮想マシンをデプロイする際、SSHでログインするためのユーザー名とともに、その公開鍵を指定できる。具体的には、仮想マシンのリソースを生成するところで、[properties]−[osProfile]−[linuxConfiguration]−[ssh]−[publicKeys]に、公開鍵とその保存先のパスを記載すればよい。
またパスワード認証を無効化するなら、[linuxConfiguration]に「disablePasswordAuthentication: true」を加える。
param location string = resourceGroup().location
param vmName string // 仮想マシンの名前
param adminUsername string // 管理アカウントのユーザー名
param adminPublicKey string = loadTextContent('id_rsa.pub') // RSA署名の公開鍵
// デフォルトでは、このBicepファイルと同じ場所にある「id_rsa.pub」に保存されている公開鍵が用いられる
// loadTextContent()では変数でファイル名を指定できないので注意
// リソース生成: 仮想マシン
resource vm 'Microsoft.Compute/virtualMachines@2022-11-01' = {
name: vmName
location: location
properties: {
osProfile: {
computerName: vmName
adminUsername: adminUsername
linuxConfiguration: { // Linux特有の設定
disablePasswordAuthentication: true // SSHでのパスワード認証を禁止
ssh: {
publicKeys: [
{
path: '/home/${adminUsername}/.ssh/authorized_keys' // 仮想マシン内での公開鍵の保存先
keyData: adminPublicKey // 公開鍵そのもの
}
]
}
}
}
}
}
// デプロイ後、確認のためにパラメータやプロパティを出力
output resouceType string = vm.type
output computerName string = vm.properties.osProfile.computerName
output adminUsername string = vm.properties.osProfile.adminUsername
output adminSSHPublicKey string = vm.properties.osProfile.linuxConfiguration.ssh.publicKeys[0].keyData
仮想マシンのサイズ(SKU)やOSイメージ、ストレージ、ネットワーク、タグなどの設定は省いているので、必要に応じて追加/変更してほしい。
※Microsoftのレファレンス: Microsoft.Compute virtualMachines
ネットワークセキュリティグループについては、最低限、SSHの受信を許可するためのセキュリティルール(受信ポートの規則)を追加する必要がある(もっとも、これは公開鍵認証に限らず、パスワード認証でも必要だ)。
// リソース生成: ネットワークセキュリティグループ
resource networkSecurityGroup 'Microsoft.Network/networkSecurityGroups@2023-02-01' = {
name: 'nsg-${vmName}'
location: location
properties: {
securityRules: [
{
name: 'allow-ssh'
properties: {
description: 'Allow the SSH Connection'
protocol: 'TCP'
sourcePortRange: '*'
destinationPortRange: '22' // SSHのデフォルトの着信ポート番号
destinationAddressPrefix: '*'
access: 'Allow' // 許可
priority: 1000
direction: 'Inbound' // 内向き
sourceAddressPrefixes: []
}
}
]
}
}
※Microsoftのレファレンス: Microsoft.Network networkSecurityGroups
またインターネット経由でLinux VMに接続するなら、パブリックIPアドレスも必要だ。
// ↓ホスト名を指定。デフォルトは「<仮想マシン名>-<ユニークな英数字>」
param hostName string = toLower('${vmName}-${uniqueString(resourceGroup().id)}')
@allowed([
'Basic' // 動的IPアドレスが必要ならこちらを選択
'Standard' // IPアドレスは固定のみ
])
param pipSKU string = 'Basic'
@allowed([
'Dynamic' // 動的IPアドレス
'Static' // 固定IPアドレス
])
param pipAllocationMethod string = pipSKU == 'Standard' ? 'Static' : 'Dynamic'
param pipIdleTimeoutInMinutes int // アイドル時のタイムアウト秒数を指定
// リソース生成: パブリックIPアドレス
resource publicIPAddress 'Microsoft.Network/publicIPAddresses@2023-02-01' = {
name: 'pip-${vmName}'
location: location
sku: {
name: pipSKU
}
properties: {
publicIPAllocationMethod: pipAllocationMethod
publicIPAddressVersion: 'IPv4'
dnsSettings: {
domainNameLabel: hostName // FQDNは「<ホスト名>.<Azureのドメイン>」になる
}
idleTimeoutInMinutes: pipIdleTimeoutInMinutes
}
}
// SSHクライアントのコマンドラインを出力
output sshCommand string = 'ssh ${adminUsername}@${publicIPAddress.properties.dnsSettings.fqdn} -i id_rsa'
※Microsoftのレファレンス: Microsoft.Network publicIPAddresses
その他、ネットワークインタフェースや仮想ネットワークなどのリソース生成については割愛するので、環境に合わせて適宜追加していただきたい。
さて、このようにしてデプロイすると、指定のユーザー名と公開鍵でのみログイン可能な状態でLinux VMが起動する。
上記スクリーンショットにある「sshCommand」は、OpenSSHクライアントで接続するためのコマンドラインを表している。前述したパブリックIPアドレスの生成時にホスト名を指定しておくと、このようにLinux VMの接続先のFQDNを確認できる。
デプロイしたLinux VMにSSHで接続するには
デプロイが完了したら、SSHクライアントから接続してみよう。OpenSSHの場合は、次のようなコマンドラインを実行する。
ssh <指定したユーザー名>@<デプロイしたVMのホスト名(FQDN)> -i <秘密鍵を収めたファイル>
すると、秘密鍵に設定したパスフレーズの入力が求められる。指示どおりに入力するとログインに成功するはずだ。
一方、前述のコマンドラインから「-i <秘密鍵を収めたファイル>」を省き、パスワード認証で接続しようとすると、以下のように失敗するはずだ。
デプロイ時に指定できる公開鍵の署名アルゴリズムはRSAのみ!?
AzureのLinux仮想マシンの場合、デプロイ時に指定できるSSHの公開鍵の署名アルゴリズムは「2048bit以上のRSA」に限られている。実際、Ed25519で署名した公開鍵を指定してデプロイすると、「The value of parameter linuxConfiguration.ssh.publicKeys.keyData is invalid.」というエラーが生じて、仮想マシンの生成に失敗してしまった。
もっとも、生成後のLinux VMでEd25519による鍵ペアに切り替えることは可能だ。例えば、Ed25519による公開鍵を「~/.ssh/authorized_keys」に追記すると、そのペアの秘密鍵をSSHクライアントに指定してログインできるようになる。
ここでAzureの「Microsoft.Compute virtualMachines/runCommands」というコマンド実行のためのリソースを活用すると、仮想マシンのデプロイと一緒に公開鍵の追記を実行できる。具体的には、前述の各リソースの記述に以下のrunComamndsリソースを追加すればよい。
// Ed25519署名の公開鍵
param adminEd25519PublicKey string = loadTextContent('id_ed25519.pub')
// デフォルトでは、このBicepファイルと同じ場所にある「id_ed25519.pub」に保存されている公開鍵が用いられる
// loadTextContent()では変数でファイル名を指定できないので注意
// Ed25519署名の公開鍵をauthorized_keysに追記するためのコマンドライン
var cmdLineAppendEd25519Key = 'echo \'${adminEd25519PublicKey}\' >> /home/${adminUsername}/.ssh/authorized_keys'
// リソース生成: 公開鍵を追記するためのコマンド実行
resource vmAppendEd25519Key 'Microsoft.Compute/virtualMachines/runCommands@2022-11-01' = {
parent: vm // コマンドを実行する仮想マシンのリソース
name: 'Append-Ed25519-Key'
location: location
properties: {
source: {
script: cmdLineAppendEd25519Key
}
}
}
// 実行したコマンドラインを出力
output runCommands string = runCmdAppendEd25519Key.properties.source.script
※Microsoftのレファレンス: Microsoft.Compute virtualMachines/runCommands
この方法だと、仮想マシンの生成時に指定したRSA署名の鍵をSSHで利用することなく、最初からEd25519署名の鍵でログインできるようになる。
■関連リンク
- Azure CLI で Azure Resource Manager (ARM) のデプロイ テンプレートを使用する方法(Microsoft Learn)
- 仮想マシンのリソースのレファレンス(Microsoft Learn)
- ネットワークセキュリティグループのリソースのレファレンス(Microsoft Learn)
- パブリックIPアドレスのリソースのレファレンス(Microsoft Learn)
- 仮想マシンでコマンドを実行するためのリソースのレファレンス(Microsoft Learn)
- マネージド実行コマンドを使用して Linux VM でスクリプトを実行する(Microsoft Learn)
Copyright© Digital Advantage Corp. All Rights Reserved.