【Azure】Linux仮想マシンを公開鍵認証で作成

# 概要
仮想マシンを毎回ポータルページから作成するのは面倒になったので
スクリプトで作成するように。
PowerShellのスクリプトで仮想マシン(Linux)作成時にSSHログイン認証を公開鍵認証方式で設定する。

# 作業環境
| 環境要素名 |  |
| ---------- | ------ |
| 作業OS     | Windows8.1 |
| 証明書作成OS | Linux (Raspbian) |
| Azure PowerShell | 0.8.16 |

 - opensslインストール済み
 - 秘密鍵作成済み

## 公開鍵(証明書)の作成

Azureで仮想マシン作成時に登録する公開鍵は`ssh-keygen`で作成した形式だと使えない。
OpenSSLを利用して、既存秘密鍵(id_rsa)からアップロード用証明書(myCert.pem)を作成。
今回はRaspberryPiを利用。

```shell-session
$ openssl req -x509 -key ~/.ssh/id_rsa -nodes -days 365 -newkey rsa:2048 -out myCert.pem
```
途中で国名、会社名等を聞かれるが適当に回答する。

証明書のフィンガープリントを出力することもでき、これをスクリプトのフィンガープリントに書くことでも登録可能
(今回はPowerShellのGet-PfxCertificateを使用している)

```
$ openssl x509 -in myCert.pem -sha1 -noout -fingerprint
SHA1 Fingerprint=XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
```

## 仮想マシンの作成

#### Linuxのディストリビューション選択
以下の形式で検索

```
> get-azureVMImage | where {$_.ImageName -like "*[検索条件]*"} | select ImageName
```

今回はCentOS系を利用するのでOpenLogicを検索して、CentOS7.1を選択した。

```
> get-azureVMImage | where {$_.ImageName -like "*OpenLogic*"} | select ImageName

ImageName
---------
5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-65-20150128
5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-65-20150325
5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-65-20150605
5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-65-20150904
5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-66-20150128
5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-66-20150325
5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-66-20150605
5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-66-20150706
5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-66-20150731
5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-67-20150815
5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-70-20150128
5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-70-20150325
5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-70-20150605
5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-70-20150904
5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-71-20150410
5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-71-20150605
5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-71-20150731 <--- これを使用する
```

#### 仮想マシンを作成
仮想マシン作成用スクリプトを用意。今回は以下のスクリプトを作成。
(PowerShellをよく理解していないのでスクリプトの書き方は適当)
[公式ページ](https://azure.microsoft.com/ja-jp/documentation/articles/virtual-machines-ps-create-preconfigure-linux-vms/)を参考にしている。


```shell-session:createvm.ps1
$ErrorActionPreference = "Stop" # 例外時のデフォルト処理を変更

$imageName="5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-71-20150731" # イメージ名
$vmname="xxxxxx"           # 仮想マシン名
$vmsize="Small"            # 仮想マシンサイズ <Small, Medium, Large, ExtraLarge, A5, A6, A7, A8, A9>
$vnetname="xxxxxx"         # 仮想ネットワーク名(仮想ネットワークは事前に作成しておく)
$subnet="xxxxxx"           # サブネット名
$privateIP="192.168.0.4"   # プライベートIP
$svcname="xxxxxx"          # サービス名
$certpath="C:\tmp\myCert.pem" # Azureに登録する公開鍵(を含んだ証明書)のパス
$location="Japan East"     # サービスロケーション
$publicport="xxxxx"        # VMのssh接続用エンドポイント

try
{
  # サービス名のサービスが存在しない場合は作成する
  Get-AzureService -ServiceName $svcname
}
catch
{
  "サービスが存在しません。新しいサービスを作成します..."
  New-AzureService -ServiceName $svcname -Location $location
}

try
{
    # 仮想マシンのイメージ選択
    $image=Get-AzureVMImage | where {$_.ImageName -eq $imageName} | select -ExpandProperty ImageName -First 1
    $vm1=New-AzureVMConfig -Name $vmname -InstanceSize $vmsize -ImageName $image
    # Linuxユーザの作成・パスワード・公開鍵認証用公開鍵を登録
    Add-AzureCertificate  -ServiceName $svcname -CertToDeploy $certpath
    # 初期ログインユーザ名とパスワードの入力を促すダイアログを表示し、入力値をセット
    $cred=Get-Credential -Message "Type the name and password of the initial Linux account."
    $sshpubkeypath="/home/" + $cred.GetNetworkCredential().Username + "/.ssh/authorized_keys"
    $myLxCert = New-AzureSSHKey -PublicKey -Fingerprint (Get-PfxCertificate -FilePath $certpath).Thumbprint -Path $sshpubkeypath
    # パスワード認証・公開鍵認証有り(-NoSSHPasswordオプションでパスワード認証禁止も可能)
    $vm1 | Add-AzureProvisioningConfig -Linux -LinuxUser $cred.GetNetworkCredential().Username -SSHPublicKeys $myLxCert -Password $cred.GetNetworkCredential().Password 
    # 仮想マシンを割り当てる仮想ネットワークのサブネットを指定
    $vm1 | Set-AzureSubnet -SubnetNames $subnet
    # 固定IPの設定
    $vm1 | Set-AzureStaticVNetIP -IPAddress $privateIP
    # エンドポイント設定
    $vm1 | Set-AzureEndpoint -Name "SSH" -Protocol tcp -LocalPort 22 -PublicPort $publicport
}
catch [Exception]
{
    Write-Host $_.exception
    exit
}

# 仮想マシンの作成
New-AzureVM –ServiceName $svcname -VMs $vm1 -VNetName $vnetname

```

実行

```
> .\createvm.ps1
```

途中でダイアログが出るので、Linuxユーザ名・パスワードを入力して、OK
![dialog1](http://i.imgur.com/KpPysIO.png)

作成に成功したらTeraTerm等でログインし、
`/home/ユーザ名/.ssh/authorized_keys`に公開鍵が登録されていることを確認できればOK。


以上です。誤っている箇所がありましたらご指摘いただけますと幸いです。

# 参考
 - [Azure PowerShell を使用して Linux ベースの仮想マシンを作成と事前構成する](https://azure.microsoft.com/ja-jp/documentation/articles/virtual-machines-ps-create-preconfigure-linux-vms/)
 - [Creating secure Linux VMs in Azure with SSH key pairs](http://www.jeff.wilcox.name/2013/06/secure-linux-vms-with-ssh-certificates/)
 - [Use PowerShell to Create a Linux VM in Azure](http://mikefrobbins.com/2015/03/12/use-powershell-to-create-a-linux-vm-in-azure/)
 - [New-AzureSSHKey](https://msdn.microsoft.com/ja-jp/library/azure/dn495200.aspx)
 - [Azure 上の Linux における SSH の使用方法](https://azure.microsoft.com/ja-jp/documentation/articles/virtual-machines-linux-use-ssh-key/)