今さらだけどLinux VirtualBox上の2008 R2 Server CoreからPowerShellでOffice365に接続してみた話

なぜこんな話になってしまったのか？そもそも何がしたかったのか？後で自分が悩みそうなので今のうちに忘れないよう残しておきます。まずQ&Aから。

## いきなりQ&A
- Q1.ゴールは？A.Office365をLinuxから管理したい。本当はLinux版PowerShellがあることを発見して、それでできないかって始めたものの、全然思い通りにならなくて、結局、今回のようになってしまいました。残念。
- Q2.何で今さら2008なの？A.たまたま手元にライセンスがあったから。あと古いほうが軽いかと思ったから。ちなみに今日の日付は2018年10月、2008R2のサポート期限は2020年4月。仕事だったら選択しないかなって思う、でもこれは仕事じゃないからOKかなって。現時点でもマイクロソフトのサイトから試用版もダウンロードできるし。
- Q3.何でServer Coreなの？A.Server Coreを使った事がなかったから。あと軽そうだったから。使うのPowerShellだけだし。
- Q4.なぜOffice365なの？A.PowerShellが使えるから。PowerShellからクラウドサービスを管理するってどんなんだろうって。面白そうじゃない。あとマイクロソフトだからドキュメントも充実してそうだし…。

## ざっと全体の流れ
今のところ以下のような流れとなっています。

ソフトウェアの準備 → 仮想マシンの作成 → 2008R2 Server Coreのインストール → リモートデスクトップの有効化 → 仮想マシンをheadlessで起動 → PowerShellの有効化 → PowerShellを5.1へアップグレード → Office365モジュールのインストール → （OpenSSHのインストール → SSHで接続） → PowerShellからOffice365！

長っていう感じですが、やりたいことはLinux（Lubuntu16）からOffice365をPowerShellで管理したいだけなので、もっと簡単にできる方法が見つかったら書きなおしていく予定です。

（追伸）OpenSSHの部分はあとで使うのやめました。

という訳でGo!です。

## 事前準備
今回Linuxホストで準備しておくものは以下の4つです。それらをインストール＆ダウンロードしておきます。

- 仮想化ソフトウェア
- .Net Framework 4.5（Windows版）
- Windows Management Framework (WMF) 5.1（Windows版） 

まず仮想化ソフトウェアです。仮想化ソフトウェアはVirtualBoxを使用しますので `sudo apt install virtualbox` でVirtualBoxをインストールします。
 
次の２つのファイルは https://docs.microsoft.com/ja-jp/powershell/wmf/5.1/install-configure からリンクを辿ってダウンロードします。2018/8/13の時点でダウンロードできたファイルは NDP452-KB2901907-x86-x64-AllOS-ENU.exe (.NetFramework4.5.2) と Win7AndW2K8R2-KB3191566-x64.zip (WMF5.1)  でした。 

Win7AndW2K8R2-KB3191566-x64.zip は `unzip Win7AndW2K8R2-KB3191566-x64.zip` で解凍しておきます。解凍すると Install-WMF5.1.ps1 と Win7AndW2K8R2-KB3191566-x64.msu が取り出せます。

## 仮想マシンの作成とOSのインストール
VirtualBoxを起動し仮想マシンを作成します。2008R2は64ビットなので仮想マシンを作成する際に「Windows 2008（64ビット）」を選択します。今回はメモリは1G、ディスクは32G、ネットワークはブリッジで作成しました。

仮想マシンが作成できたら、Windows2008R2のISOファイルを指定してブートし、インストール時に「Windows Server 2008 R2 Standard（Server Coreインストール）」を指定してServer Coreをインストールします。

これで2008R2のインストールは完了です。私の場合で10分そこそこでインストールは完了しました。なかなかいい感じの速度感です。

systeminfo コマンドで情報を見てみると2008R2のSP1であることが確認できました。taskmgr や diskpart 、 fsutil といったコマンドを使ってメモリ使用量やディスクの空きをチェックすることができます。初期状態でメモリ使用量は250Mくらい、ディスク使用量は3.7Gくらいでした。

この時点でメモリ割当とかを小さくしたりとか調整し過ぎるとこのインストールに時間が掛かってしまうこともあるので、この時点では余裕を持たせておいて、インストール後に負荷を考慮しながら、メモリ割当やExecution Cap（プロセッサの使用制限）あたりの値を調整するのがいいじゃないかなと思います。

## リモートデスクトップ
LinuxとWindows間でコピペできたりして便利なのでリモートデスクトップを有効にします。有効にするには sconfig コマンドを使用します。 sconfig を実行後、7)リモートデスクトップ -> E（有効にする） -> 2（任意のリモート デスクトップを実行しているクライアントを許可する (低セキュリティ)） で有効にできます。

```console:リモートデスクトップの有効化（Windowsゲスト）
C:\Users\Administrator>sconfig
===============================================================================
                         サーバー構成
===============================================================================

1) ドメイン/ワークグループ:                     ワークグループ:  WORKGROUP
2) コンピューター名:                            WIN-U1A37C3N0AF
3) ローカル管理者の追加
4) リモート管理の構成

5) Windows Update の設定:                        手動
6) 更新プログラムのダウンロードとインストール
7) リモート デスクトップ:                        有効 (すべてのクライアント)

8) ネットワーク設定
9) 日付と時刻

10) ユーザーのログオフ
11) サーバーの再起動
12) サーバーのシャットダウン
13) 終了してコマンド ラインに戻る

選択するオプションの番号を入力してください: 7

リモート デスクトップを有効(E)または無効(D)にしますか? (入力なし=キャンセル) E

1) ネットワーク レベル認証を使うリモート デスクトップを実行しているクライアントのみを許可する (高セキュリティ)
2) 任意のリモート デスクトップを実行しているクライアントを許可する (低セキュリティ)
選択するオプションの番号を入力してください: 2

リモート デスクトップを有効にしています...
```

リモートデスクトップで接続するためにLinux版のリモートデスクトップクライアントrdesktopを `sudo apt install rdesktop` でインストールします。 

インストールできたら以下のように入力して接続できることを確認します。-rでクリップボードとパスのリダイレクトとを有効にしています。そうするとLinuxとWindows間でクリップボードが共有できて、Windowsゲストから`\\tsclient\tmp`でLinuxホストの`/tmp`フォルダにアクセスできるようになります。

```console:リモートデスクトップで接続（Linuxホスト）
rdesktop -r clipboard:PRIMARYCLIPBOARD -r disk:tmp=/tmp -k ja -u Administrator -p パスワード ipアドレス
```

リモートデスクトップを使うとコピペできたりファイルコピーできたりと便利なので、これ以降の作業は全てリモートデスクトップで行います。

### VirtualBoxのコンソールを非表示に
リモートデスクトップが使えるようになるとVirtualBoxのコンソールがうっとおしいので非表示にします。まずはServer Core（Windowsゲスト）を `shutdown /s /t 0` でシャットダウンします。

シャットダウンできたら仮想マシンを起動する際に、「→スタート」アイコンの右側をクリックして「Headless Start」を選びます。それだけです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/128670/e9abe2d9-42be-9fc7-b297-8978aafa758b.png)

コマンドラインから行う場合は `VBoxManage list vms` で仮想マシンの名前を確認し、 `VBoxManage startvm 仮想マシン名 --type headless` で起動します。

しばらくしてServer Core（Windowsゲスト）が立ち上がったかなと思ったらリモートデスクトップで接続してみます。接続できたら成功です。

```console:headlessで接続（Linuxホスト）実行結果
$ VBoxManage list vms
"2008R2" {74a5da98-eef7-4da7-a821-0c77af58b1f9}

$ VBoxManage startvm "2008R2" --type headless
Waiting for VM "2008R2" to power on...
VM "2008R2" has been successfully started.
（少し待つ）
$ rdesktop -r clipboard:PRIMARYCLIPBOARD -r disk:tmp=/tmp -k ja -u Administrator -p **** **.**.**.*:
ERROR: CredSSP: Initialize failed, do you have correct kerberos tgt initialized ?
Connection established using SSL.
WARNING: Remote desktop does not support colour depth 24; falling back to 16

```

## PowerShell
続けてPowerShellを有効にします。有効にするには sconfig コマンドを使用します。 sconfig  を実行後、 4)リモート管理の構成 -> 2)Windows PowerShell を有効にする で有効にできます。

有効にすると「Windows PowerShellのインストールを完了するには再起動する必要があります。今すぐ再起動しますか？」となりますので「はい」をクリックし再起動します。

```console:PowerShellの有効化（Windowsゲスト）
C:\Users\Administrator>sconfig
===============================================================================
                         サーバー構成
===============================================================================

1) ドメイン/ワークグループ:                     ワークグループ:  WORKGROUP
2) コンピューター名:                            WIN-U1A37C3N0AF
3) ローカル管理者の追加
4) リモート管理の構成

5) Windows Update の設定:                        手動
6) 更新プログラムのダウンロードとインストール
7) リモート デスクトップ:                        有効 (すべてのクライアント)

8) ネットワーク設定
9) 日付と時刻

10) ユーザーのログオフ
11) サーバーの再起動
12) サーバーのシャットダウン
13) 終了してコマンド ラインに戻る

選択するオプションの番号を入力してください: 4

--------------------------------
  リモート管理の構成
--------------------------------

1) MMC リモート管理を許可する
2) Windows PowerShell を有効にする
3) サーバー マネージャーのリモート管理を許可する
4) Windows ファイアウォール設定を表示する

5) メイン メニューに戻る

選択するオプションの番号を入力してください: 2

Windows PowerShell を有効にしています...
リモート署名する Windows PowerShell 実行ポリシーを設定しています...
```

再起動するとPowerShellが使えるようになります。バージョンを確認してみたところ2.0のようです。バージョンは powershell コマンドでPowerShellを起動し $PSVersionTable を表示すると分かります。

```console:PowerShellのバージョン確認（Windowsゲスト）
C:\Users\Administrator>powershell
Windows PowerShell
Copyright (C) 2009 Microsoft Corporation. All rights reserved.

PS C:\Users\Administrator> $PSVersionTable

Name                           Value
----                           -----
CLRVersion                     2.0.50727.5420
BuildVersion                   6.1.7601.17514
PSVersion                      2.0
WSManStackVersion              2.0
PSCompatibleVersions           {1.0, 2.0}
SerializationVersion           1.1.0.1
PSRemotingProtocolVersion      2.1
```

## PowerShell5.1のインストール
PowerShell5.1のインストールするにはWMF5.1をインストールします。しかしWMF5.1をインストールするには.Net Framework 4.5.2が必要となって、.Net Framework 4.5.2をインストールするには.Net Framework 2.0が有効化されている必要があります。

なのでまずは dism コマンドを使用して.Net Framework 2.0を有効にします。

```console:.NetFramework2の有効化（Windowsゲスト）
dism /online /enable-feature /featurename:NetFx2-ServerCore
dism /online /enable-feature /featurename:NetFx2-ServerCore-WOW64
```

```console:.NetFramework2の有効化（Windowsゲスト）実行結果
C:\Users\Administrator>dism /online /enable-feature /featurename:NetFx2-ServerCore
展開イメージのサービスと管理ツール
バージョン: 6.1.7600.16385

イメージのバージョン: 6.1.7600.16385

機能を有効にしています
[==========================100.0%==========================]
操作は正常に完了しました。

C:\Users\Administrator>dism /online /enable-feature /featurename:NetFx2-ServerCore-WOW64
展開イメージのサービスと管理ツール
バージョン: 6.1.7600.16385

イメージのバージョン: 6.1.7600.16385

機能を有効にしています
[==========================100.0%==========================]
操作は正常に完了しました。
```

続けて .NET Framework 4.5.2 と WMF5.1をインストールするためのインストーラーをWindowsゲストにコピーします。

インストーラーは事前にLinuxホストでダウンロードしていますので、まずはそのファイル（ NDP452-KB2901907-x86-x64-AllOS-ENU.exe と Win7AndW2K8R2-KB3191566-x64.msu ）をLinuxホストの /tmp にコピーします。

コピーが終わったらWindowsゲストで以下のように実行してインストーラーをコピーします。

```console:ファイルのコピー（Windowsゲスト）
copy \\tsclient\tmp\NDP452-KB2901907-x86-x64-AllOS-ENU.exe
copy \\tsclient\tmp\Win7AndW2K8R2-KB3191566-x64.msu
```

NDP452-KB2901907-x86-x64-AllOS-ENU.exe を実行して .Net Framework 4.5.2 をインストールします。

```console:.NetFramework4.5.2のインストール（Windowsゲスト）
NDP452-KB2901907-x86-x64-AllOS-ENU.exe
```

.Net Framework 4.5.2のインストールが成功したらWMF5.1をインストールします。

```console:WMF5.1のインストール（Windowsゲスト）
Win7AndW2K8R2-KB3191566-x64.msu
```

PowerShellを起動しバージョンを確認し5.1になっていることを確認します。

```console:PowerShellのバージョンの確認（Windowsゲスト）
C:\Users\Administrator>powershell
Windows PowerShell
Copyright (C) 2016 Microsoft Corporation. All rights reserved.

PS C:\Users\Administrator> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.14409.1005
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.14409.1005
CLRVersion                     4.0.30319.34209
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
```
## Office365モジュールのインストール
Office365にアクセスするためのモジュールをインストールします。 powershell コマンドでPowerShellを起動し`Install-Module MSOnline`でインストールします。

```powershell:MSOnlineモジュールのインストール（Windowsゲスト）PowerShell上で実行
Install-Module MSOnline
```


```powershell:MSOnlineモジュールのインストール（Windowsゲスト）実行結果
C:\Users\Administrator>powershell
Windows PowerShell
Copyright (C) 2016 Microsoft Corporation. All rights reserved.

PS C:\Users\Administrator> Install-Module MSOnline

続行するには NuGet プロバイダーが必要です
PowerShellGet で NuGet ベースのリポジトリを操作するには、'2.8.5.201' 以降のバージョンの NuGet プロバイダーが必要です。NuGet プロバイダーは 'C:\Program Files\PackageManagement\ProviderAssemblies' または 'C:\Users\Administrator\AppData\Local\PackageManagement\ProviderAssemblies' に配置する必要があります。'Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force' を実行して NuGet プロバイダーをインストールすることもできます。今すぐ PowerShellGet で NuGet プロバイダーをインストールしてインポートしますか?
[Y] Yes  [N] No  [S] Suspend  [?] Help (default is "Y"): Y

信頼されていないリポジトリ
信頼されていないリポジトリからモジュールをインストールしようとしています。このリポジトリを信頼する場合は、Set-PSRepository コマンドレットを実行して、リポジトリの InstallationPolicy の値を変更してください。'PSGallery' からモジュールをインストールしますか?
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "N"): A
```

これでインストールは終わりです。本当に接続できるかテストしてみます。以下のコマンドをPowerShell上で実行してエラーが出ないことを確認します。

```powershell:Office365に接続（Windowsゲスト）PowerShell上で実行
$msolcred = ConvertTo-SecureString 'パスワード' -AsPlainText -Force | % { New-Object System.Management.Automation.PSCredential('ユーザー名', $_) } | % { Get-Credential $_ }
Connect-MsolService -credential $msolcred
Set-ExecutionPolicy RemoteSigned -Force
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $msolcred -Authentication Basic -AllowRedirection
Import-PSSession $Session  -AllowClobber -DisableNameChecking

```

エラがーでなければ大丈夫だと思いますが心配な場合は、 Get-MsolUser でユーザを表示してみたり、 Get-MsolAccountSku でライセンスプランを表示してみます。

## OpenSSH
使いたいのはPowerShellだけなのにリモートデスクトップで作業というのも、なんだかなーってことでWindowsゲストでsshdを動かして、Linuxホストからsshで接続してみたいと思います。

（追伸）sshで接続できることはできたのですがセッションがタイムアウトしてしまうと認証のダイアログを表示することができずフリーズ状態となってしまうことが分かったため使うのはやめました。後で参考になるかもしれないと残してあります。

### Windows版OpenSSHのダウンロード
https://github.com/PowerShell/Win32-OpenSSH/releases から64bit版をダウンロードします。現時点では v7.7.2.0p1-Beta が最新で OpenSSH-Win64.zip がダウンロードできました。ダウンロードしたファイルを `unzip OpenSSH-Win64.zip` で解凍します。

### Windows版OpenSSHのインストール
ダウンロード＆解凍したファイルを /tmp フォルダーにコピーしておきます。

```console:OpenSSHの解凍（Linuxホスト）
cp -rf ./OpenSSH-Win64 /tmp
```

リモートデスクトップで接続しOpenSSHのファイルをコピーします。今回は c:\Program Files\OpenSSH にコピーしています。

```console:ファイルコピー（Windowsゲスト）
cd "c:\Program Files"
md OpenSSH
cd OpenSSH
copy \\tsclient\tmp\OpenSSH-Win64\*
```

powershellを起動し、sshdのインストールスクリプトを実行、ファイヤーウォールポリシーの追加、サービスを起動、サービスの自動起動設定といった設定を行います。以下の作業はPowerShell上で実行します。

```powershell:インストール（Windowsゲスト）PowerShell上で実行
.\install-sshd.ps1
netsh advfirewall firewall add rule name=sshd dir=in action=allow protocol=TCP localport=22
net start sshd
Set-Service sshd -StartupType Automatic
Set-Service ssh-agent -StartupType Automatic
```

```powershell:インストール（Windowsゲスト）実行結果
C:\Program Files\OpenSSH>powershell
Windows PowerShell
Copyright (C) 2016 Microsoft Corporation. All rights reserved.

PS C:\Program Files\OpenSSH> .\install-sshd.ps1
[SC] SetServiceObjectSecurity SUCCESS
[SC] ChangeServiceConfig2 SUCCESS
[SC] ChangeServiceConfig2 SUCCESS
sshd and ssh-agent services successfully installed
PS C:\Program Files\OpenSSH> netsh advfirewall firewall add rule name=sshd
 dir=in action=allow protocol=TCP localport=22
OK
PS C:\Program Files\OpenSSH> Set-Service sshd -StartupType Automatic
PS C:\Program Files\OpenSSH> Set-Service ssh-agent -StartupType Automatic
```

### OpenSSHで接続
Windowsゲストでの設定ができたらLinuxホストから接続してみます。

```console:sshで接続（Linuxホスト）
ssh Administrator@ipアドレス
```

sshが使えるとscpを使ってファイルコピーもできるのでかなり便利になります。以下の例はLinuxホストからWindowsゲストにコピーしていますが、その逆も可能です。

```console:ファイルのコピーメモ（Linuxホスト）
#ホームディレクトリにファイルをコピー（Linuxホスト->Windowsゲスト）
scp ファイル名 Administrator@ipアドレス:

#Cドライブ直下にファイルのコピー（Linuxホスト->Windowsゲスト）
scp ファイル名 Administrator@ipアドレス:/c:/

#フォルダーのコピー（Linuxホスト->Windowsゲスト）
scp -r フォルダー名 Administrator@ipアドレス:/c:/
```

## なんとか終わった…
長かったですが、結局Windows入れてリモートデスクトップかーという感じになってしまいました。残念です。ま、というか疲れたので、今回のこれくらいにしておきたいと思います。

## あっライセンス認証は？
Office365の接続とは関係ないのでスルーしましたが忘れそうなのでメモです。Server Coreの場合はプロダクトキーの登録とライセンス認証は slmgr.vbs というコマンドを使って行うようです。`slmgr.vbs /dli` で今の状態を確認することができます。詳しい使い方は slmgr.vbs で検索すれば情報がそれなりに出てくるので参考にできると思います。

といいつつもまだやったことがないので、使い方が安定するまでは試用版のままで色々と試行錯誤して、安定したらプロダクトキー登録＆アクティベーションという流れになるかなって思っています。