コンテンツへスキップ

Azure OSの自動アップグレード

こんな記事がありました。

OS のアップグレード処理について

http://msdn.microsoft.com/ja-jp/windowsazure/hh705141

これを見て、ロールのインスタンスを1つだけにしておいたため、ひどい目に会ったことを思い出しました。何の前触れもなく突然、WEBロールが30分もオフラインになりましたよ!

 

ゲストOSの自動アップグレードを防ぐためには、構成ファイルでosVersionに固定バージョンを設定すること。しかし、ホストOSのアップグレードはどうにもならないです。

このような件も踏まえ、本運用においてロールインスタンスは2つ以上が必須です。そして、2つ以上じゃないとコンピューティングに関するサービスレベルにも適用されず、インシデント時のサービスクレジット(料金割引)の請求もできません。

インプレース アップグレードの実行

http://technet.microsoft.com/ja-jp/library/gg457922.aspx

インスタンスを2つにすればコンピューティング課金は2倍。そこまで費用をかけてまで可用性を求めない、そんなあなたにはコチラ。1インスタンスでなるべく可用性を高める方法があります。

Windows Azure におけるアプリケーションの可用性の向上

http://msdn.microsoft.com/ja-jp/library/gg236576.aspx

AzureでSSL まとめ

中間証明書を各Webロールインスタンスにインストールするように構成することが重要。

1.証明書チェインをちゃんと考えてローカルPCにSSL環境を構成 → 2.pfxにエクスポート→ 3.Azureへpfxをインポート → 4.想定通りのチェインになっているか確認

Azureに証明書をインポートする際には.pfx形式でないとならない。そして、中間証明書が必要な場合は.pfxにそれら関連する証明書をすべて含めていなければならない。足りないからといって後から.cerファイル等で中間証明書を追加することはできない。つまり、.pfxを作る時はローカルPCにインストールしたSSL証明書をエクスポートするわけですが、Azureで構成したいとおりにローカルPCに証明書チェインが構成されてないと、思った通りにエクスポートされないです。

AzureでSSL ジオトラストのクロスルート用を含んだ4階層の証明書をWEBロールにインストールするように構成する

5.構成ファイルで証明書インストール先の設定 → 6.パッケージにしてデプロイ → 7.RDCで確認 → 8.実機で確認

構成ファイルでSSL証明書は[My]中間証明書は[CA]にインストールするように構成します。あとはデプロイするのみ!

AzureでSSL ジオトラストのクロスルート用を含んだ4階層の証明書をデプロイ

AzureでSSL ジオトラストのクロスルート用を含んだ4階層の証明書をWEBロールにインストールするように構成する

前回、4階層の証明書を配置することができましたが、それら証明書はWEBロールの各インスタンスにインストールされなければ意味がありません。

自前のサーバーで4階層にする場合は、下図のように証明書ストアの中間証明機関に2つの証明書をインストールするのですが、

WEBロールでもこうなるようにしたいのです。

httpsのエンドポイントやSSL証明書のインストールを構成する方法は、WindowsAzure SSL環境構築手順に載っていましたが中間証明書はどうしたらいいのかな、、、? 調べてみたところ、下記記事を見つけました。

How to install a chained SSL certificate

http://blogs.msdn.com/b/azuredevsupport/archive/2010/02/24/how-to-install-a-chained-ssl-certificate.aspx

Change the Store Name for the chained certificates (MyIntermediateCert and MyRootCert in this case) from My to CA. In this example the dialog will look like this:

つまり、[Store Name]欄にMyではなくCAを入力して証明書を追加すればよいということですね。早速、Visual StudioでクラウドプロジェクトのWEBロールのプロパティで証明書を設定する作業に取り掛かったのですが、証明書の選択が証明書ストアの個人から選択できませんよ?しょうがないので、構成ファイルを直接編集しました。サムプリントは管理ポータルで証明書を選択すると右側のペインに表示されるので、それをコピペできます。(サムプリントがデプロイしてある証明書のと異なっていると、パッケージをデプロイできません)

ServiceDefinition.csdef

<Certificates>
<Certificate name="MyDomain.com" storeLocation="LocalMachine" storeName="My" />
<Certificate name="GeoTrust DV SSL CA" storeLocation="LocalMachine" storeName="CA" />
<Certificate name="GeoTrust Global CA" storeLocation="LocalMachine" storeName="CA" />
</Certificates>

ServiceConfiguration.cscfg

<Certificates>
<Certificate name="Microsoft.WindowsAzure.Plugins.RemoteAccess.PasswordEncryption" thumbprint="(RDP用の証明書)" thumbprintAlgorithm="sha1" />
<Certificate name="MyDomain.com" thumbprint="(SSL証明書)" thumbprintAlgorithm="sha1" />
<Certificate name="GeoTrust DV SSL CA" thumbprint="BAE30B15DBB1544CF194D076B75B7BB9E3D6B760" thumbprintAlgorithm="sha1" />
<Certificate name="GeoTrust Global CA" thumbprint="7359755C6DF9A0ABC3060BCE369564C8EC4542A3" thumbprintAlgorithm="sha1" />
</Certificates>

すると、WEBロールのプロパティ画面の証明書タブはこうなります。

以上で構成は終了ですので、Azureへデプロイします。デプロイが完了してからリモートデスクトップでWEBロールインスタンスに接続し、証明書スナップインで証明書ストアを覗いてみると、、、

いたーーーー!!!

さてさて、ブラウザでWEBページを開き、アドレス欄にある鍵マークをクリックして証明書を表示してチェインを確認してみると、ちゃんと4階層になっています。

次に、最終目標である古いAndroid(初代レグザ)で確認。警告が出なくなり、WCFサービスにhttpsでアクセスできるようになりました!

AzureでSSL ジオトラストのクロスルート用を含んだ4階層の証明書をデプロイ

古いAndroidからSSLできなかったので、それを解決するまでの作業内容を書いていきます。

ジオトラストのクイックSSL プレミアムを使っています。

ジオトラストのサポートページに下記手順があったのでそれにしたがってセットアップしました。

WindowsAzure SSL環境構築手順

http://www.geotrust.co.jp/support/ssl/install/azure_ep.html

その結果、ブラウザから普通にSSLできるし、WEBサービスクライアントからもSSLで接続できました。しかし、後から気が付いたのですが、古いAndroid端末においてルート証明機関が信頼されていないような警告メッセージが出るではありませんか!

どうにかせねばならんので調査しました。まずジオトラスト関連のサポートページを漁ってみます。すると、Androidについて述べているページを発見しました。

ジオトラストSSLサーバー証明書のAndroidスマートフォン対応につきまして

http://valuessl.net/news/?p=439

Android搭載のスマートフォンでAndroid 2.2 よりも古いバージョンでは、新しいルート証明書「Geotrsut Global CA」を搭載していません。このためAndroid 2.2 よりも古いバージョンのスマートフォンでSSL通信をした場合には、エラーの警告が出ます。 ※Android 2.2 以降のバージョンでも機種によりましては、「Geotrsut Global CA」を搭載していないものもあります。

ジオトラスト社ではこれに対応するため、Android の古いバージョンが搭載している旧ルート証明書「Equifax Secure CA」から認証されたクロスルート証明書を提供しています。クロスルート証明書をインストールすることにより、「Equifax Secure Certificate Authority」と「Geotrsut Global CA」のどちらかを搭載していればSSL暗号化通信ができます。

クロスルート証明書やらをインストールすればいいそうです。ですが、あれ? WindowsAzure SSL環境構築手順でクロスルート証明書をインストールしたのに。。。さて、手順通りにやったはずなのに何故できてないのか、そもそも4階層でデプロイできているのかどうかを調査する必要があります。さしあたって、管理ポータルを確認してみます。WindowsAzure SSL環境構築手順でエクスポートした.pfxは関連するすべての証明書を含むようにしてるので、中間証明書も含まれています。ですので管理ポータルで1つの.pfxを選択して証明書を追加するいくつかの証明書が展開されます。(てか、.cerも追加できたらいいのに)

あれ?展開された証明書の発行先・発行元を辿っていくと、SSL証明書 – GeoTrust DV SSL CA – GeoTrust Global CA の3階層になってる? 4階層の場合は下記のようになるそうなんですが・・・

【Q】証明書の階層構造について

http://www.geotrust.co.jp/support/ssl/faq/900011/

4階層の場合

  • Equifax Secure Certificate Authority(ルート証明書:クライアント側)
    • GeoTrust Global CA(中間CA証明書 2階層目:サーバ側)
      • GeoTrust SSL CA / GeoTrust DV SSL CA(中間CA証明書 3階層目:サーバ側)
        • SSLサーバ証明書(お客様のサーバ証明書:サーバ側)

.pfxが展開された結果3階層になってしまっているということは、エクスポート時に既にそうなっているということですよね。エクスポート時には[関連する証明書をすべて含める]というオプションがありますが、自分でどの証明書を含めるかを選択することはできません。したがって、ローカルで4階層になるように、4階層の肝となるクロスルート用ファイルを関連させてやらねばエクスポートされません。

ではエクスポート元のローカルPCの証明書がどのような状況かmmc & 証明書スナップインで確認します。

WindowsAzure SSL環境構築手順どおりにインストールされています。

ローカルでは、GeoTrust Global CAはEquifax Secure Certificate Authorityによって証明されている。しかし、Azureでは自己証明だった。。。きっと自己証明の証明書がどこかにいるに違いないので、証明書検索で発行者にGeoTrust Global CAを入力して検索してみると、、、ありましたよ、ありました。サードパーティールート証明機関に。

こいつが邪魔なので、とりあえず信頼されていない証明書へ移動させた後、再度.pfxをエクスポートしてAzureへ追加してみると・・・!

GeoTrust Global CAはEquifax Secure Certificate Authorityによって証明されています!

次回へ続く(次回はWEBロールに中間証明書をインストールするよう設定します)

AppFabric サービスバスの接続プールを実装

Webロールをクライアント、オンプレミスにサービスという一般的な構成で構築しています。

サービスに頻繁に接続するのですが、サービスバスへ接続(チャネルオープン)するのって2秒程かかるんです。これって結構なオーバーヘッドですよね。

そこで、Globalに共有変数を設けてそこにオープン済みのをセットしておいて使いまわしていたんですが、ロックしたりしてるわけじゃないし同時に要求が来て同時に使われたらちょっと微妙ですし。チャネルが使用可能な状態でない場合は新しいチャネルをオープンしてるので今のところ大勢に影響はないのですが、やはりちゃんと接続プールが欲しい!ということで実装しました。

サービスバスといえども、エンドポイント側から見れば所詮のところWCFのいちバインディングにすぎないので、WCFの接続プールの実装サンプルはないか探したところ、ありましたありました。

A Sample for WCF Client Proxy Pooling

http://blogs.msdn.com/b/wenlong/archive/2007/11/14/a-sample-for-wcf-client-proxy-pooling.aspx

これはTake-return-create modelなのだそうです。

Poolのインスタンスはアプリケーション状態変数に保持するようにしました。

今のところバッチリ稼働しています。初回のオープン時は2秒ぐらいかかってしまいますが、そのあとはその接続を再利用するのでサクサクです。

効率的に再利用してくれるので、課金的にも優しいです。

SQL Azureで “A transport-level error has occurred when receiving results from the server.”

たまに出るんですよねぇ。

System.Data.SqlClient.SqlException
(0x80131904): A transport-level error has occurred when receiving results from
the server. (provider: TCP Provider, error: 0 – An existing connection was
forcibly closed by the remote host.)

特に長期間放置した場合。リトライするようにしました。

AppStoreからリリースしたアプリで、デバイストークンの取得ができずプッシュ通知ができない、、、

テストではばっちりOK、自信を持ってリリースしたのに、いざリリースしてみたらAPNsができなくてがっかり・・・という目に会いました。

App Storeからインストールしたアプリの挙動を見る限りでは、デバイストークンの取得ができていない様子でした。

もっと具体的な情報を拾えないとどうにもならないので、デバイスをMacに繋いでxcodeのオーガナイザのコンソールを横目で見つつアプリを動かしてみると、下記の怪しげなログが目につきました。

Sep 21 09:16:15 xxx-no-iPad SpringBoard[28] <Warning>:
No valid ‘aps-environment’ entitlement string found for application ‘<バンドル表示名>’:
(null). Notifications will not be delivered.

Sep 21 09:16:15 xxx-no-iPad <バンドル名>[1644] <Warning>:
Error:Error Domain=NSCocoaErrorDomain Code=3000
“アプリケーションの有効な“aps-environment”エンタイトルメント文字列が見つかりません” UserInfo=0x399420
{NSLocalizedDescription=アプリケーションの有効な“aps-environment”エンタイトルメント文字列が見つかりません}

検索しながら調査していると、下記ドキュメントに行き当たりました。

http://developer.apple.com/library/ios/#technotes/tn2265/_index.html
Technical Note TN2265
Troubleshooting Push Notifications
Registering for Push Notifications の Error Delegate Callback のところ

You can check your app’s code signing entitlements with the codesign tool. The value of the aps-environment or com.apple.developer.aps-environment entitlement should be either development or production. Run this command in Terminal pointing at your App Store distribution build:

$ codesign -d --entitlements - <YourAppName>.app

Check if there is an aps-environment or com.apple.developer.aps-environment code signing entitlement listed under Internal requirements. It would normally appear after the application-identifier (iOS) or com.apple.application-identifier (Mac OS X) entitlement.

NOTE: This is a useful test to perform on your distribution builds before submitting them to the App Store. The Application Loader or Xcode do not check if the push entitlement is missing.

If the aps-environment or com.apple.developer.aps-environment entitlement is missing, you probably created your distribution provisioning profile before you configured your App ID for push notifications using the iOS Provisioning Portal or the Mac Developer Certificate Utility. If your App ID has already been configured for push notifications, go into the Portal or the Developer Certificate Utility and download a new provisioning profile. It most likely will have the desired code signing entitlements in place. You can look at the profile with a text editor like TextEdit and search for Entitlements.

私の場合は下記手順となりました。

1.ターミナル でcodesignコマンドを.appに対して実行してみてaps-environmentのエントリーがあるかどうかを調べる。→ 有りませんでした(-_-) これが無いとダメなようなんです。

<dict>
<key>application-identifier</key>
<string>[App ID]</string>
<key>get-task-allow</key>
<false/>
<key>keychain-access-groups</key>
<array>
<string>[App ID]</string>
</array>
</dict>

念のため、テストに使ってた.appをcodesignコマンドで見てみると、しっかりとありました。

<dict>
<key>application-identifier</key>
<string>[App ID]</string>
<key>aps-environment</key>
<string>development</string>
<key>get-task-allow</key>
<true/>
<key>keychain-access-groups</key>
<array>
<string>[App ID]</string>
</array>
</dict>

iTunes Connect提出用と開発用では、コード署名用のプロビジョニングプロファイルが違うのですが、提出用のAppは実機でテストできないため、今回の憂き目に会いました。
(提出用はプロビジョニングポータルの[Provisioning]-[Distribution]で、開発用は[Development]で発行したプロファイルを使用してビルドします。)

さて、どうすれば提出用のにもaps-environmentを登場させられるかというと、

  1. プロビジョニングポータルの[App IDs]で、該当のアプリのApple Push Notification service が “Enabled for Production”になっているのを確認。
  2. [Provisioning]-[Distribution]で、既にあるプロファイルの[Actions]で[Edit]-[Duplicate]とポイントし、コピーを作る。★この新たに作られたコピーがPush通知対応してるっぽい!
  3. ダウンロードし、そのファイルをxcodeのオーガナイザのProvisioningへDrag & Drop。古いのは消してOK。
  4. xcodeでクリーンしてからビルド!

出来上がった.appをcodesignコマンドで確認してみると、

<dict>
<key>application-identifier</key>
<string>[App ID]</string>
<key>aps-environment</key>
<string>production</string>
<key>get-task-allow</key>
<false/>
<key>keychain-access-groups</key>
<array>
<string>[App ID]</string>
</array>
</dict>

どうやらOKそうですね。

この.appをiTunes Connectへアップしてみます。

きっとPush通知できるようになるはず!