読者です 読者をやめる 読者になる 読者になる

しばやん雑記

ASP.NET とメイドさんが大好きなフリーランスのプログラマーのブログ

Azure CDN がカスタムドメインでの HTTPS に対応したので試してみた

Azure CDN

ぶちぞう RD 曰く、6 年ぐらい待ったという Azure CDN のカスタムドメインでの HTTPS 対応を早速試しました。ドメイン承認プロセスがあるので、ちゃんとドキュメントには予め目を通しておきましょう。

前提条件として Azure CDN エンドポイントを作成して、カスタムドメインを追加しておく必要があります。わかりやすいように CDN エンドポイントが有効になるまで待った方が良さそうです。

カスタムドメインを追加すると、HTTPS を有効にする設定が出てきます。

f:id:shiba-yan:20170209231803p:plain

設定を On にして保存すると、ドメイン承認用のメールが admin@domain というアドレスに送信されます。最初はドキュメントをちゃんと読まなかったので、受信できないドメインを追加していました。

しばらくすると DigiCert からメールが届きます。載っているリンクをブラウザで開きます。

f:id:shiba-yan:20170209232244p:plain

リンク先は以下のような画面が表示されるので、名前を入力して送信します。

f:id:shiba-yan:20170209232103p:plain

ここまではよくある HTTPS 証明書の作成プロセスですね。ここまでくればポータルの表示が Enabling に変わって、Azure CDN 側で証明書の登録プロセスが走ります。

ドキュメントには証明書が反映されるまで 6-8 時間とありましたが、今回は 24 時間ほどかかりました。ありえないぐらい遅かったので、使う場合には注意する必要がありそうです。

f:id:shiba-yan:20170209232329p:plain

丸一日が経過した後、ようやく証明書が反映されました。無料で使えるのは結構ありがたいです。

f:id:shiba-yan:20170209231646p:plain

証明書を見ると、ちゃんと登録したカスタムドメインが追加されていることが分かります。

f:id:shiba-yan:20170209233012p:plain

待ち時間が許容できる場合には、証明書の発行や更新など全て無料で使えるので選択肢としてはありだと思います。秘密鍵の管理も要らないし、更新も自動で行われるみたいです。

Azure CDN Premium Verizon の場合は Rule Engine で URL Rewrite が使えるので、Blob Storage では使えないデフォルトドキュメントっぽいことを実現できます。

この Stack Overflow の回答が完璧だったので、実際に Rule を追加して試しています。

f:id:shiba-yan:20170209232742p:plain

Blob Storage を静的サイトとして使う場合にデフォルトドキュメントと HTTPS が課題になっていましたが、Azure CDN を被せることで両方とも一度に解決できます。

高い可用性を持つ静的な Web サイトとして運用する場合にはかなり良いと思いました。

AMI 向けに Sysprep 応答ファイルを使ってタイムゾーンとシステムロケールの設定を行う

AWS Windows

Windows Server の AMI を作成する時に必要な sysprep を実行すると、デフォルトではタイムゾーンが UTC でシステムロケールが en-US になってしまうので、sysprep の応答ファイルを用意して変更してみます。

AWS のドキュメントに sysprep と応答ファイルについて記載があります。

SystemLocale と TimeZone を変更して、sysprep を実行すれば上手くいきそうな感じです。

EC2 の Windows Server AMI を使うと、デフォルトの応答ファイルが予め用意されているので、それに対して変更を行ってから sysprep をすることにします。User Data で実行したいので PowerShell で書きます。

PowerShell で名前空間付きの XML を扱う場合の方法は、以下のページを参考にしました。

Sysprep の応答ファイルは 2012 R2 と 2016 で特に変わっていないので、関数として切り出しておきました。実際に書いたコードは以下のような感じです。

function Update-SysprepAnswerFile($answerFile)
{
    [xml] $document = Get-Content $answerFile -Encoding UTF8

    $ns = New-Object System.Xml.XmlNamespaceManager($document.NameTable)
    $ns.AddNamespace("u", $document.DocumentElement.NamespaceURI)

    $settings = $document.SelectSingleNode("//u:settings[@pass='oobeSystem']", $ns)

    $international = $settings.SelectSingleNode("u:component[@name='Microsoft-Windows-International-Core']", $ns)
    $shell = $settings.SelectSingleNode("u:component[@name='Microsoft-Windows-Shell-Setup']", $ns)

    $international.SystemLocale = "ja-JP"
    $international.UserLocale = "ja-JP"

    $shell.TimeZone = "Tokyo Standard Time"

    $document.Save($answerFile)
}

XPath で応答ファイルの要素を引っ張ってきて、要素の値を書き換えて保存するだけのコードです。なんとなく SystemLocale だけではなく UserLocale も ja-JP に変更しておきました。

TimeZone の値は tzutil で指定するものと同じなので、少し書き方に注意したいです。

Windows Server 2012 R2 までは EC2Config を使って sysprep を実行しますが、Windows Server 2016 では EC2Launch を使う形に変更されたので、それぞれの OS 向けにスクリプトを変更して記載しておきます。

Windows Server 2012 R2

EC2ConfigService の中に存在する sysprep2008.xml が応答ファイルです。sysprep 自体も ec2config.exe にパラメータを渡して実行します。

function Update-SysprepAnswerFile
{
   # 省略
}

Update-SysprepAnswerFile "$env:ProgramFiles\Amazon\Ec2ConfigService\sysprep2008.xml"

# Execute sysprep
& "$env:ProgramFiles\Amazon\Ec2ConfigService\ec2config.exe" -sysprep

割とシンプルなスクリプトになりました。このスクリプトを実行して作成した AMI を使ってインスタンスを起動すると、システムログに設定した言語やタイムゾーンの情報が表示されています。

f:id:shiba-yan:20170202000804p:plain

ちゃんと ja-JP Tokyo Standard Time になっています。

リモートデスクトップで接続して確認しても、設定が変更されていることが確認できました。

f:id:shiba-yan:20170202003910p:plain

日本語言語パックをインストールしてから UILanguage を設定すると日本語にも出来る気がします。

Windows Server 2016

EC2Launch では PowerShell ベースになっているので、手順が少し変わっています。公式ドキュメントに sysprep の手順が書いてあるので、まずは熟読しておきました。

応答ファイルのパスも変わっているので、少し注意したいです。特に InitializeInstance.ps1 の Schedule パラメータを忘れないようにしたいです。ダメなイメージが完成します。

function Update-SysprepAnswerFile
{
   # 省略
}

Update-SysprepAnswerFile "$env:ProgramData\Amazon\EC2-Windows\Launch\Sysprep\Unattend.xml"

# Execute sysprep
cd "$env:ProgramData\Amazon\EC2-Windows\Launch\Scripts"
.\InitializeInstance.ps1 -Schedule
.\SysprepInstance.ps1

2012 R2 の時と同じようにイメージを作成して、新しくインスタンスを作成するとシステムログに設定した言語とタイムゾーンが表示されているので、変更されてるのが分かります。

f:id:shiba-yan:20170202000705p:plain

そしてリモートデスクトップで接続して、システムロケールが変わっていることを確認しました。

f:id:shiba-yan:20170202003836p:plain

システムロケールの設定は再起動が必要になるので自動化がいまいちやりにくい部分でしたが、sysprep を使って AMI を作成する場合では User Data を使って自動化が行えます。

以前書いた Elastic Beanstalk 向けの Custom AMI と同じように CI で作れそうです。

特に Elastic Beanstalk はベースとなる AMI を変更できないので、User Data を使って Custom AMI を作成しないと辛い部分が出てきそうです。ebextensions は割とすぐに限界が来ました。

Visual Studio 2017 での NuGet アップデートが良い感じだった

Visual Studio NuGet

全然追っていなかったのですが Visual Studio 2017 で NuGet 周りにこれまでで一番手が入るようです。NuGet のリリース以来、最大のアップデートと言ってもいい感じがします。

packages.config ではなくて MSBuild での PackageReference が、これまでの .NET Framework プロジェクトでも使えるようになるみたいです。.NET Core に限らず使えるのはかなり良さそうです。

NuGet – .NET Framework, UWP, .NET Core and other .NET projects can now use PackageReference instead of packages.config for NuGet dependencies.

Announcing .NET Core, .NET Native and NuGet Updates in VS 2017 RC | .NET Blog

NuGet の設定からデフォルトのフォーマットを変更出来るようになっています。

f:id:shiba-yan:20170201003649p:plain

設定を変更しても、既存のプロジェクトのフォーマットが変換されるわけではないです。

.NET Framework のコンソールアプリケーションに WindowsAzure.Storage をインストールすると、参照が PackageReference を使った方がすっきりと分かりやすくなっています。

f:id:shiba-yan:20170201004052p:plain

ゼロから追加する分には問題ないですが、ASP.NET アプリケーションなどテンプレートで用意されているものに関しては、packages.config のままになってしまうので、マイグレーション用のツールを書きました。

ビルドしてプロジェクトファイルのパスを渡すと、ある程度まではいい感じに変換します。

単純に packages.config から変換するのではなく、パッケージ間の依存関係を調べて最小限のパッケージだけを参照するようにしています。

実際に ASP.NET MVC アプリケーションのプロジェクトを変換すると以下のようになります。

f:id:shiba-yan:20170201004211p:plain

Web API のパッケージが 1 つだけになっていたり、シンプルになっています。

しかしまだ .NET Core の参照表示のように、それぞれの NuGet パッケージの依存関係をツリーで表示することは出来ないみたいです。右クリックで削除も出来ないので、地味にこれは不便です。

f:id:shiba-yan:20170201005358p:plain

RTM までに .NET Core と同じ機能まで持っていってくれると非常にありがたいです。

とはいえ、Visual Studio 2015 までより大幅に改善されているので、早く移行したいです。