Azure の詳細
Azure Mobile Services によるセキュリティと ID の管理
Satya Nadella は、マイクロソフトの新たなビジョンを明確に定めた声明を発表し、「世界は "モバイル ファースト/クラウド ファースト" の時代に入った」と述べています。このような声明が出ても驚くことはありません。マイクロソフトがモバイル テクノロジとクラウド テクノロジを追求するようになって数年が経ちます。業界は変わり続け、IT リーダーには「私物デバイスの業務利用」(BYOD: Bring Your Own Device) という変革を求めるプレッシャーがかつてないほど高まっています。
企業にとっては、BYOD という勇気を持って立ち向かわなければならない新たな世界をサポートすることが最優先の課題です。今月は、基幹業務 (LOB) アプリケーションの開発者が iOS、Android、Windows Phone 向けにアプリを作成してサポートするのにクラウドがどのように役立つかを MSDN マガジンの読者と一緒に考えていきます。規模の大小を問わず、デイバイスの管理について企業が直面する課題を取り上げ、Microsoft Azure Mobile Services の OAuth 2.0 トークンを適切に管理するために必要な低レベルのネイティブ Objective-C コードを紹介します。今回の主な目的は、トークンをモバイル デバイスに安全に保管して、アプリを使用するたびにユーザーがログインしなければならない状況を回避することです。
LOB アプリの重要な特性
LOB アプリの作成を検討する場合には多くの課題があります。最も重要な課題の 1 つが ID 管理です (図 1 参照)。今回のテーマでは、ユーザーの ID だけでなく、デバイスの ID も対象になります。ユーザー ID とデバイス ID の 2 つの要素の組み合わせて複合 ID と呼ぶのが一般的です。LOB アプリでは通常、企業の機密リソースにアクセスすることになるため、2 つの ID を組み合わせて扱うのは当然です。
図 1. iOS 基幹業務 (LOB) アプリの概要
デバイス管理
集中管理型の IT で明らかなことの 1 つは、私物デバイスをなんらかの形式で強制的に管理統制する必要があることです。私物デバイスを完全にドメインに参加させるように、IT 部門が個人に強制できるのが理想です。管理統制の中でもあまり厳密ではないものを「社内参加」と呼びます。これは、デバイスを完全にドメインに参加させるよりも柔軟な統制と考えてかまいません。
IT 管理者の目標は、企業のリソースとデバイス自体との間に安全で暗号化された通信を確保することです。プロビジョニング プロセスの一環としてデバイスの証明書をインストールすることが、企業がデバイスを問題なく安全に管理する 1 つの方法です。
社内のプロビジョニング
社内プロビジョニング プロセスの最初の目標は、信頼できるディレクトリ サービスに対してユーザーを認証することです。デバイスのプロビジョニング (登録) を成功させるには、デバイスで JSON ベースのトークンを使用します。このトークンによって、ユーザーと企業ネットワークの間で安全な通信を確保できるようになります (図 2 参照)。
図 2 ユーザー認証に対応する社内プロビジョニング
階層化 ID
セキュリティの各レベルが及ぶ範囲を考えることが重要です (図 3 参照)。企業情報の中にはきわめて機密度の高い情報もあります。機密度の高いデータを保護する場合は、通常、追加の対策が必要です。
図 3 セキュリティの各レベルが及ぶ範囲
ユーザー認証については既によく知られています。セキュリティの最も基本的なレベルでは、ユーザーはユーザー名とパスワードを使用してログインします。2 番目のレベルは、おそらく多要素認証アプローチを求めるデバイス認証です。この場合、ユーザー ID とデバイス ID を組み合わせて (SMS チャレンジの使用など)、複合 ID を形成します。
ネットワーク位置認識
私物デバイスでアプリを実行する場合にもう 1 つ検討すべき重要な点は、ネットワーク位置認識 (NLA: Network Location Awareness) です。つまり、ネットワークの保護されたリソースへのアクセスを求める要求が着信した場合、その要求が企業ネットワークの外部から行われたものかどうかを判断できる必要があります。NLA によって、企業ネットワーク外部から行われた要求に対して多要素認証などの追加ルールを適用できるようになり、追加の保護層が提供されます。
通常、ネットワーク位置の透過性を実装することは、ある種のプロキシ Web サービスを DMZ に作成することを意味します。DMZ は 1 つのネットワークで、外部とのインターフェイスを持つ組織のサービスを、インターネットのような大規模で信頼できないネットワークに公開します。このようなプロキシを使用して追加のルールをトリガーすることで、ネットワーク上のプライベートなリソースを外部アクセスから隔離します。マイクロソフトは、このようなシナリオを実現する具体的なテクノロジを用意しています。詳細については、https://www.microsoft.com/ja-jp/server-cloud/solutions/mobile-device-management.aspx を参照してください。
ネイティブ iOS コードによる ID のサポート
ここでは、iOS のネイティブ機能を利用する低レベルでのテクニックについて説明します。ただ、説明に入る前に、Microsoft Azure Mobile Services について簡単に触れておきます。Microsoft Azure Mobile Services は、クライアント プログラムが共通して必要とする機能をいくつか提供します。対象となるクライアント プログラムは、iOS、Android、Windows Phone、ブラウザ ベースの HTML/JavaScript、または Windows のネイティブ アプリです。
REST API を呼び出すことができるクライアント プラットフォームであれば、Microsoft Azure Mobile Services を利用でき、サポート対象のクライアントにさまざまなレベルのライブラリ サポートが提供されます。他にも、フェデレーション ID、ストレージへのアクセス、オフライン データ同期、プッシュ通知などの機能もあります。バック エンドに実装する機能もあれば、フロント エンドに実装する機能もあります。バック エンドには、Microsoft .NET Framework または Node.js のいずれかを使用できます。
実装が困難なものの 1 つは、iOS デバイスにセキュリティ トークンを保存する機能です。トークンは、最初 Microsoft Azure Mobile Services によって提供されます。OS はこのトークンを保護し、暗号化する必要があります。さいわい、この機能は、iOS SDK に組み込まれている Keychain メカニズムによって実現されます。これによって、社員のデバイスにトークンを安全に保存できるようになります。これは完全にネイティブなアプローチです。つまり、コードはまったく再利用できません。
セキュリティ トークンをデバイスにローカル保存することにはメリットがあります。最も重要なメリットは、ユーザーが毎回ログインすることなく、アプリにアクセスできるようになることです。Microsoft Azure Mobile Services のアプリは、Active Directory、Azure Active Directory、Facebook、Twitter などのセキュリティ トークン プロバイダー (ID プロバイダー) をどれでも、またはすべて利用することができます。
ただし、トークンの有効期限についての考え方に違いがあります。Active Directory と Azure Active Directory では、トークンの有効期限を設定できますが、Twitter では設定できません。企業リソースへのアクセスを許可する認証には、トークンの有効期限を設定する機能が重要です。したがって、このレベルのアクセスには、Active Directory と Azure Active Directory が Twitter よりも優れた選択肢と言えます。
「基本から始める」という精神に倣い、今回は、Twitter 認証を使用するプロセスを説明します。Azure Active Directory については今後のコラムで取り上げる予定です。Xcode は、iOS アプリの開発に使用する IDE です。Xcode は Visual Studio に似ていますが、Visual Studio ほど高機能ではありません。iOS アプリのコーディング言語は従来どおり Objective-C です。
これらのテクニックの例として、まずは bit.ly/1vcxHMQ (英語) のチュートリアルを参照してください。この例では Twitter ID プロバイダー サービスを利用するフェデレーション認証を追加します。チュートリアルには、バック エンド モジュールとフロント エンド モジュールの両方が含まれています。バックエンドには .NET または JavaScript のいずれかを選択できるようになっています。フロント エンドには、Objective-C を使用するプロセスを採用しています。今回は、GitHub にある別のサンプル プロジェクト (iOS-LensRocket) のコードを一部借用して、Keychain 機能をサポートします。
Microsoft Azure Mobile Services によって提供されるフロント エンド Xcode プロジェクトに必要な変更はそれほど多くありません。必要なのは Keychain コードを追加することと、security.framework ライブラリのセキュリティの機能を追加することだけです。ユーザーがアプリを開始するときに、基本トークン管理ロジックが適用されます。アプリでは、まず、KeyChain API への呼び出しを行ってトークンをチェックします。トークンが存在すれば、それを取り出して使用します。ユーザーは Twitter への再ログインを求められません。
Xcode IDE で行うコードの変更は、以下のとおりです。
- 追加のライブラリにリンクする (詳細については、bit.ly/1x7Ajzz、英語を参照)
- Keychain 機能をサポートするために iOS-LensRocket のファイルをいくつか追加する
- コントローラーのコードを変更する
図 4 は、デバイスにキャッシュされたトークンを利用して SQL データベースへのアクセス制御を行うために、Microsoft Azure Mobile Services とネイティブ iOS コードを使用する方法の例を示しています。
図 4 iOS デバイスに認証トークンを保存する手順の概要
チュートリアルでは、クラウドでホストされている SQL データベースの読み込みと書き込みが可能なネイティブ iOS アプリを実行するところが示されています。Objective-C で記述された実行可能な Xcode プロジェクトを操作できるようになりますが、認証機能が不足しています。ここではこの認証機能について説明します。既存の実装では、Microsoft Azure Mobile Services によって提供されるアプリ キーを使用します。
// Initialize the Mobile Services client with your URL and key.
MSClient *client =
[MSClient clientWithApplicationURLString:@"https://msdnmagazine.azure-mobile.net/"
applicationKey:@"cctyYudYfxuczeRDMPcDBRCxDrOUIM73"];
このアプローチの問題点は明らかです。アプリのコードに機密情報を埋め込めば、必ずセキュリティのリスクを招きます。必要なのは、データベースの更新を実行する場合、ユーザーにログインさせることです。ただし、ユーザーに毎回ログインを求めるのは望まないので、認証トークンをデバイスにローカル保存するようにします。そこで、アプリの開始時に保存したトークンを取得するように iOS アプリを構成します。
大半の企業では、Facebook や Twitter などのソーシャル ベースの ID プロバイダーを利用することはありませんが、最初にこうしたプロバイダーの利用を理解しておくと、Active Directory を使用してオンプレミス ID を利用する際に核となる考え方を理解するのに役立ちます。また、多くのビジネス アプリはリレーショナル データベースを利用しており、Microsoft Azure Mobile Services はリレーショナル データベースをサポートするビルド済み機能を提供します。
まず、Microsoft Azure の管理ポータルとサードパーティの ID プロバイダー (今回は Twitter) で、基本的な作業をいくつか行います。Twitter のポータルでアプリのメタデータを作成し、Microsoft Azure Mobile Services のポータルで関連するメタデータを作成します。次に、アプリの URL を取得します。アプリの URL を Twitter にコピーし、Twitter API のキーを Microsoft Azure Mobile Services にコピーします。これによって、ID プロバイダーが Microsoft Azure Mobile Services にバインドされます (図 5 参照)。
図 5 Microsoft Azure Mobile Services と Twitter の関係
これに不可欠なのが、以下に示す手順のように、ポータルでモバイル アプリのメタデータを作成することです。
- 作成したモバイル アプリの URL を Microsoft Azure の管理ポータルから取得する。
- サインインして dev.twitter.com/apps/new (英語) ページに移動する。
- 新しい Twitter アプリを作成する。
- Twitter アプリの API キーと API シークレットを取得する。
- Microsoft Azure の管理ポータルに戻る。
- Twitter の API キーと API シークレットを貼り付ける。
ポータルでの作業
前述のようにに、バック エンドをビルドする場合の選択肢は 2 つあります。.NET Framework を選択する場合は、ユーザーが認証済みかどうかにかかわらず、すべてのユーザーに対するユース ケースの承認を Web API で適切に制御できます。Node.js を選択する場合は、ポータルによって宣言型のスクリプト化されたアプローチが提供されます。
実際に行う必要があるのは、Mac 上で実行中の Xcode IDE に戻ることです。Xcode IDE を使用して、モバイル デバイスで実行する LOB iOS アプリのソース コードを編集およびコンパイルします。
Xcode IDE では、以下に示すコード変更を行います。
- security.framework にライブラリ参照を追加する。
- 以下に示す 4 つのファイルを iOS-LensRocket (bit.ly/1pqvQ25、英語) からコピーする。
- KeyChainWrapper.h
- KeyChainWrapper.m
- LensRocketConstants.h
- LensRocketConstants.m
関係する主な関数/メソッドは 3 つあります。1 つ目は、loadAuthInfo への呼び出しを追加する viewDidLoad です。これは、以前ログインに成功して保存したトークンをメモリに読み込みます。ここでは、ユーザーに再ログインを求める代わりに、ディスクからトークンを読み込みます (図 6 参照)。
図 6 ネイティブ iOS コードに加える変更
#import "KeychainWrapper.h" // Add this line.
- (void)viewDidLoad
{
// Code omitted for brevity.
[self loadAuthInfo]; // Add this line.
}
// Code omitted for brevity.
////////////////////////////////////////////////////////////////////////////////
// Added viewDidAppear(), loadAuthInfo() below.
////////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------------------------------
// Event is viewDidAppear. When app becomes active, check credentials.
//
- (void)viewDidAppear:(BOOL)animated
{
////////////////////////////////////////////////////////////////////////////
// Check if current user is logged in. If not, log in to Twitter.
MSClient *client = self.todoService.client;
if(client.currentUser != nil) {
return;
}
[client loginWithProvider:@"twitter" controller:self animated:YES
completion:^(MSUser *user, NSError *error) {
[self saveAuthInfo];
[self refresh];
}];
}
// ----------------------------------------------------------------------------
// Save token locally.
// Leverage built-in iOS features called Keychain for user ID and tokenl storage
//
- (void) saveAuthInfo{
// Save the userId
[KeychainWrapper createKeychainValue:self.todoService.client.currentUser.userId
forIdentifier:@"userid"];
// Save the token itself
[KeychainWrapper
createKeychainValue:self.todoService.client.currentUser.
mobileServiceAuthenticationToken
forIdentifier:@"token"];
}
// ----------------------------------------------------------------------------
// Load the user ID and Token from the keychain. Avoid forcing user to log in again.
//
- (void)loadAuthInfo {
NSString *userid =
[KeychainWrapper keychainStringFromMatchingIdentifier:@"userid"];
if (userid) {
// Fetch the user ID and token from the Keychain.
NSLog(@"userid: %@", userid);
self.todoService.client.currentUser = [[MSUser alloc] initWithUserId:userid];
self.todoService.client.currentUser.mobileServiceAuthenticationToken =
[KeychainWrapper keychainStringFromMatchingIdentifier:@"token"];
}
}
アプリが可視 (アクティブ) になるときに呼び出される viewDidAppear 関数も追加しました。MSClient オブジェクトを使用して、ユーザーがログインしているかどうかをチェックします。ユーザーがまだログインしていなければ、Twitter へのログインを求め、ログイン後に Keychain 機能を使用して資格情報 (トークン) をディスクに保存します。これは、viewDidLoad に実装するのが適切です。
saveAuthInfo メソッドと loadAuthInfo メソッドでは、Keychain コードを単純に使用して、モバイル デバイスのディスクにトークンを保存し、モバイル デバイスのディスクからトークンを読み込みます。Keychain サービスの詳細については、bit.ly/1qqcNFm (英語) を参照してください。
認証の実装に関する 2 つ目のチュートリアル (https://azure.microsoft.com/ja-jp/documentation/articles/mobile-services-ios-get-started-users/) に従うこともできます。Twitter とは異なり、Azure Active Directory へのフェデレーションを許可する場合は、以下に示す同様の手順に従います。
- 作成したモバイル アプリの URL を Microsoft Azure の管理ポータルから取得する。
- Active Directory ページ (このページも Microsoft Azure の管理ポータルにあります) に移動する。
- 新しいアプリを作成する。
- クライアント ID とキーを取得する。
- Microsoft Azure の管理ポータルのモバイル アプリのページに戻る。
- Active Directory のクライアント ID とキーを貼り付ける。
オンプレミスの Active Directory とクラウドの Active Directory とのフェデレーションに関する詳細については、今後取り上げる予定です。それまでは、https://msdn.microsoft.com/ja-jp/library/azure/dn646737.aspx および https://azure.microsoft.com/ja-jp/documentation/articles/mobile-services-dotnet-backend-ios-adal-sso-authentication/ にある優れたコード サンプルを参照してください。
まとめ
社内での私物デバイスのサポートを求めるプレッシャーが高まるにつれて、このようなデバイスを保護する方法やトークンを処理する方法を理解することが開発者にとって重要になります。真に機密度の高い情報を保護するには、多くの場合、認証のためにユーザー名とパスワードを使用するアプローチを実装するだけでは不十分です。
すべてのセキュリティ機能をデバイスで完全に利用するには、ここで説明した iOS の Keychain サービスのようなネイティブ機能を利用することが必要になります。次回は、ID、データ同期、プッシュ通知を中心に企業の IT リーダーが直面するモバイル デバイスに関連する課題を引き続き取り上げます。
Bruno Terkaly は、マイクロソフトの開発者エバンジェリストです。彼の豊富な知識は、数多くのプラットフォーム、言語、フレームワーク、SDK および API を使用してコードを記述してきた、何年にも上る業界での経験に基づいています。彼は、特に Microsoft Azure プラットフォームを使用して、クラウド ベースのアプリケーション構築に関するコードの記述、ブログ投稿、およびライブ プレゼンテーションを行って時間を過ごしています。ブログは、blogs.msdn.com/b/brunoterkaly (英語) で公開されています。
Greg Oliver は、2010 年に Microsoft Azure の ISV 組織に参加しました。彼は、企業の移行計画および実装をサポートすることに多くの時間を費やしています。最近では、有名なコンシューマー ゲーム企業のクラウド プロバイダーを競合プロバイダーから移行する作業に取り組んでいます。マイクロソフトに参加する前は、新興企業のテクノロジ パートナーを務めていました。
この記事のレビューに協力してくれたマイクロソフト技術スタッフの Matthew Henderson に心より感謝いたします。