2015年8月15日土曜日

[AADSync/MIM]プロキシサーバ経由でID同期を行う

こんにちは、富士榮です。

企業内からOffice365などのSaaSアプリケーションをAzure Active Active Directory(Azure AD)経由で使う場合、オンプレミスのActive Directory上のアカウントをAzure AD Sync(AADSync)やMicrosoft Identity Manager 2016(MIM)のAzure AD Connectorを使って同期するのが一般的なシナリオです。

しかし、ほとんどの企業のネットワークには厄介なことにプロキシサーバが配置されており、AADSyncなどクラウド上のサービスに直接通信を行うサーバーを導入する際、どこに配置するのか非常に悩んだり、面倒な申請を上げてプロキシのバイパス設定や、場合によってはネットワーク機器のフィルタリングやルーティング設定を変更する必要性が出てきたりします。

本格導入をする場合は、その辺りの環境の洗い出しや構成変更についても覚悟をもって構築作業をするのでしょうが、開発環境やテスト環境として使う場合はそこまで大掛かりな準備をする手間がかけられず、困ることが多いと思います。

そのようなケースにおいてAADSyncやMIMがプロキシサーバを参照して動作するための設定を行う必要があります。

ケースとして以下の3つのパターンに対応することが可能です。
1. 認証なしのプロキシサーバを使っている
2. BASIC認証が必要なプロキシサーバを使っている
3. NTLM認証が必要なプロキシサーバを使っている

それぞれについてどのように対応するか解説していきます。


1. 認証なしのプロキシサーバを使っている

このケースは比較的簡単です。
マイクロソフトのサポートサイトにも情報が記載されており、具体的には「C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\machine.config」にプロキシサーバに関するエントリを追加して再起動するだけです。

 サポートサイト
 https://support.microsoft.com/en-us/kb/3013032

以下のエントリをConfigurationブロックの最後に追記します。

<system.net>
  <defaultProxy>
    <proxy
      usesystemdefault="true"
      proxyaddress="http://[Proxyサーバアドレス]:[ポート番号]"
      bypassonlocal="true"
    />
  </defaultProxy>
</system.net>


2. BASIC認証が必要なプロキシサーバを使っている

ここからが少しトリッキーになってきます。
先のmachine.configには認証に使うユーザIDやパスワードを記載することが出来ないので、認証プロキシとAADSync/MIMの中間に認証なしのプロキシサーバを挟み、上位プロキシへフォワードさせる際に中間のプロキシサーバから認証情報をつける、ということを行います。


上位のプロキシサーバがBASIC認証を使う場合は、squidを使うことで対応することが可能です。
※尚、中間プロキシサーバの要件としては①http/httpsを上位プロキシサーバへフォワード出来ること、②フォワード時にBASIC認証に対応できることの2点なので、squid以外でも対応できるものがあるかもしれません。

今回はAADSyncサーバにWindows版のsquidを同居させました。

 Windows版squidのダウンロード

C:\squid以下にダウンロードしたモジュールを展開し、etcフォルダ以下のmime.conf.defaultをmime.confへリネームし、以下の内容のsquid.confを新規作成します。
(今回は限定的な用途なので、最低限のエントリだけしか記載していません。ログなど出したければsquid.conf.defaultを参考に追記してください)

acl all src all
acl localhost src 127.0.0.1/32
acl SSL_ports port 443
acl Safe_ports port 80
acl Safe_ports port 443
acl CONNECT method CONNECT
acl SSL method CONNECT
never_direct allow SSL
http_access deny !Safe_ports
http_access allow localhost
http_access deny all
http_port 8080
cache_peer [上位プロキシサーバのアドレス] parent [ポート番号] 0 login=[ユーザID]:[パスワード]


これでsquidを起動し、先のmachine.configのプロキシサーバ設定にlocalhostを指定すればAADSync/MIMはsquidを、squidは本来のプロキシを参照する形でインターネットへ接続できるようになります。


3. NTLM認証が必要なプロキシサーバを使っている

最後が、Windows統合認証を使っている認証プロキシです。ISAとかですね。(古)
この場合も考え方は同じですが、squidがWindows統合認証に対応していないので、Cntlmというフリーウェアを使うことで対応している例があるようです。

 Cntlmダウンロードページ

細かい方法は今回は省略しますが、Cntlmの設定ファイル(iniファイル)に認証に使うユーザ名、ドメイン名、パスワードを記載してサービスを起動、上位プロキシサーバを参照させる、という方法をとります。

旧Forefront Identity Manager(FIM)、現Directory ServicesのMVPも在籍しているオーストラリアのkloudという会社のblogで紹介されているので、詳しくはそちらを見てください。

 kloudのblog



尚、上記で紹介したのはあくまで開発・テスト時の使用にとどめておいた方が良いと思います。障害ポイントを増やすだけですし、思わぬトラブルが発生した時に切り分けが難しくなる場合もあると思われますので。

2015年8月14日金曜日

[Azure AD]App Model v2.0を利用して組織内外共用のアプリケーションを開発する

こんにちは、富士榮です。

近年は企業の働き方の変革が進み、業務アプリケーションについても企業組織内だけでなくグループ企業間で共用したり、サプライチェーンの中の関連企業との間で同じアプリケーションを共同利用するようなケースが増えてきています。

そうなってくると、Azure Active Directory(Azure AD)を使って認証するようなアプリケーションについても単一テナントに紐づけるのではなく、他のAzure ADテナントやマイクロソフトアカウントを使ってログインできるようにしたくなるところです。

これまでもマルチテナントアプリケーションとしてAzure AD上にアプリケーションを登録することは可能でしたが、Azureの管理ポータルのようにマイクロソフトアカウントを使ったログインまではできませんでした。今回Public Previewとして登場したApp Model v2.0ではその部分を補完してくれています。尚、中身はOAuth2.0およびOpenID Connectです。

 Active Directory Teamのブログでのアナウンス
  Now in public preview: The Converged Microsoft Account and Azure Active Directory Programming Model
   http://blogs.technet.com/b/ad/archive/2015/08/12/azure-ad-microsoft-account-preview-sign-in-personal-and-work-accounts-using-a-single-stack.aspx

 開発者向けドキュメント
  App Model v2.0 Preview: Auth Protocols - OAuth 2.0 & OpenID Connect
   https://azure.microsoft.com/en-us/documentation/articles/active-directory-v2-protocols/


早速、どのように動くのか確認してみます。

今回は、Azure ADの組織アカウントでも個人のマイクロソフトアカウントでもログインでき、個人のユーザ情報を表示するアプリケーションを作ってみます。尚、アプリケーションはAzure上にホストするWebアプリをVisual Studio OnlineでPHPを使って書いてみます。
ブラウザだけで何でもできるので非常に簡単です。


必要な作業は以下の通りです。
1. Azure App ServiceよりWebアプリを作成する
2. クライアントをアプリケーション登録ポータルから登録する
3. Visual Studio Onlineでアプリケーションを書く


では、準備を進めます。

1. Azure App ServiceよりWebアプリを作成する

この作業の最大の目的はURLを確定させることです。
ここで取得したURLをredirect_uriとしてアプリケーション登録するためです。

中身はなんでもいいので、とりあえずAzureの管理ポータルから簡易作成します。


URLのうちホスト名は[任意の名前].azurewebsites.netとなるので、他と重複しない名前を付けてください。


2. クライアントをアプリケーション登録ポータルから登録する

次にアプリケーションを登録します。
以下よりアプリケーション登録ポータルにログインし、アプリケーションを登録します。尚このポータルへはAzure ADの組織アカウントもしくはマイクロソフトアカウントでログインします。

 https://apps.dev.microsoft.com/

ログインすると右上に[アプリの追加]というボタンがあるので、ここをクリックして登録を開始します。


アプリケーションID(client_id)は自動的に割り当てられるので、まずは任意のアプリケーション名をつけます。



次にプラットフォームの項目より[プラットフォームの追加]をクリックしてアプリケーションのプラットフォームを選択します。今回はWebアプリケーションを選択します。



次にリダイレクトURIの設定を行うので、先に登録したアプリケーションのURLを使います。今回はこの後作成するPHPページをindex.phpとしたので、ここでは先ほどのホスト名+index.phpをリダイレクトURIとして登録しています。



次はアプリケーションシークレットを生成します。これがclient_secretになります。
アプリケーションシークレットの項目の[新しいパスワードを生成]をクリックし、生成されるclient_secretをメモしておきます。




最後にページ下部にある、[保存]をクリックしてアプリケーション登録は完了です。



3. Visual Studio Onlineでアプリケーションを書く

では、実際に動くアプリケーションを書いてみます。
先ほど書いたように今回はVisual Studio Onlineを使ってPHPアプリケーションを書きます。

まずは、先ほど作成したアプリケーションをAzure管理ポータル(今回は新ポータルを使っています)から開き[ツール]-[拡張機能]-[Visual Studio Online]の順に開きます。
※あらかじめ拡張機能としてVisual Studio Onlineを追加しています。


するとエディタが開くので右クリックで新規にindex.phpという名前でファイルを作成し、コードを書いていきます。


実際の使ったコードは以下の通りです(かなり手抜きですが・・・)。単純なcodeフローですね。ちなみにcodeからid_tokenを取得するところでcurlのエラー60番(SSLのVerificationエラー)が出るので、CURLOPT_SSL_VERIFYPEERをfalseにセットしています。マイクロソフト内部の通信のはずなんですが・・・。
<?php

// パラメータ類
$authorization_endpoint = 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize';
$token_endpoint = 'https://login.microsoftonline.com/common/oauth2/v2.0/token';
$client_id = '1ae7xxxxxxxxxxxx2b99';
$client_secret = 'ErxxxxxxxxxxxxxxW0jp';
$redirect_uri = 'https://pharaohphp.azurewebsites.net/index.php';
$response_type = 'code';
$state =  'hogehoge'; // 手抜き
$nonce = 'fogafoga'; // 手抜き

// codeの取得(codeがパラメータについてなければ初回アクセスとしてみなしています。手抜きです)
$req_code = $_GET['code'];
if(!$req_code){
    // 初回アクセスなのでログインプロセス開始
    // GETパラメータ関係
    $query = http_build_query(array(
        'client_id'=>$client_id,
        'response_type'=>$response_type,
        'redirect_uri'=> $redirect_uri,
        'scope'=>'openid',
        'state'=>$state,
        'nonce'=>$nonce
    ));
    // リクエスト
    header('Location: ' . $authorization_endpoint . '?' . $query );
    exit();
}

// POSTデータの作成
$postdata = array(
    'grant_type'=>'authorization_code',
    'client_id'=>$client_id,
    'code'=>$req_code,
    'client_secret'=>$client_secret,
    'redirect_uri'=>$redirect_uri
);

// TokenエンドポイントへPOST
$ch = curl_init($token_endpoint);
curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt( $ch, CURLOPT_POSTFIELDS, http_build_query($postdata));
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
$response = json_decode(curl_exec($ch));
curl_close($ch);

// id_tokenの取り出しとdecode
$id_token = explode('.', $response->id_token);
$payload = base64_decode(str_pad(strtr($id_token[1], '-_', '+/'), strlen($id_token[1]) % 4, '=', STR_PAD_RIGHT));
$payload_json = json_decode($payload, true);

// 整形と表示
print<<<EOF
    <html>
    <head>
    <meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
    <title>Obtained claims</title>
    </head>
    <body>
    <table border=1>
    <tr><th>Claim</th><th>Value</th></tr>
EOF;
    foreach($payload_json as $key => $value){
        print('<tr><td>'.$key.'</td><td>'.$value.'</td></tr>');
    }
print<<<EOF
    </table>
    </body>
    </html>
EOF;

?>



書いたコード自動的に保存されるので、これで準備はこれで終了です。


◆テストしてみる

いよいよ動かしてみます。
Azure ADの組織アカウントとマイクロソフトアカウントの両方でログインできて、ユーザ情報が取得できていればOKです。


まずはマイクロソフトアカウントでログインしてみます。

アプリケーションのURLを開くと、ログイン画面が出てくるのでログインアカウントの欄にマイクロソフトアカウント(メールアドレス)を入力します。


すると自動的にマイクロソフトアカウントのログインページに遷移が始まります。


ここでパスワードを入力してサインインします。



すると初回アクセスだとアプリケーションによるアクセス許可の同意画面が出てくるのでアクセスを許可します。



上手く動けばアプリケーションに遷移し、id_tokenに含まれるclaim(属性情報)が一覧で表示されます。




次はAzure ADの組織アカウントを使って同じことをしてみます。

先ほどと同じくアプリケーションを開き、今度はAzure AD上のアカウントを入力すると、Azure ADのログイン画面へ遷移しますので、パスワードを入れてサインインします。



すると同じく同意画面が出てきますのでアクセスを許可します。



同じく上手く動けばアプリケーションに遷移し、claim一覧が表示されます。マイクロソフトアカウントとAzure AD組織アカウントでは取得できる情報が若干異なるようです。




いかがでしょうか?
まだPreviewということでscopeが制限されていたりしますが、とりあえずログインまでは問題なく動くようですので、今後、外部アカウントと共同で業務を行う場合などはこのようなモデルでアプリケーションを開発するのも一つの選択肢となるかも知れません。

2015年8月13日木曜日

[Azure AD]OpenID ConnectのUserInfoエンドポイントを使ってユーザ情報を取得する

こんにちは、富士榮です。

今回はAzure Active Directory(Azure AD)からOpenID Connectを使ってユーザの属性情報を取得してみます。

先日のポストではASP.NETアプリケーションから属性を取得する方法として、id_tokenの中身をデコードする方法とGraph APIを使って問い合わせる方法を紹介しましたが、今回はOpenID ConnectのUserInfoエンドポイントから情報を取得します。


◆技術仕様

OpenID Connect1.0の仕様を見ると、UserInfoエンドポイントは以下のように定義されています。

UserInfo Endpoint は, 認証された End-User に関する Claim を返す OAuth 2.0 Protected Resource である. 要求された End-User のクレームを取得するため, クライアントは OpenID Connect Authentication を通して得られた Access Token を用いて UserInfo Endpoint に要求する. これらのクレームは通常, クレームの名前と値のペアのコレクションを含んだ JSON オブジェクトで表現される.

参考)OpenID Connect Core 1.0 日本語訳

同じく、UserInfoエンドポイントへのアクセスの流れがImplementer's Guideに記載されています。


参考)OpenID Connect Basic Client Implementer's Guide 1.0 日本語訳

今回は、このガイドに従いAzure ADのUserInfoエンドポイントからユーザの属性情報を取得してみます。


◆Azure ADのエンドポイント情報の確認

UserInfoを取得するにあたって必要なAzure ADのエンドポイント情報を/.well-known/openid-configurationエンドポイントで確認します。
普通にブラウザでエンドポイントにアクセスすると各種構成情報がJSON形式で表示され、エンドポイントのアドレスについても以下の通り確認できます。

エンドポイントアドレス
Authorizehttps://login.microsoftonline.com/common/oauth2/authorize
Tokenhttps://login.microsoftonline.com/common/oauth2/token
UserInfohttps://login.microsoftonline.com/common/openid/userinfo


参考)openid-configurationエンドポイント



◆Azure AD上にクライアント登録をする

OAuth2.0のリソースアクセスなので、当然クライアントを事前に登録しておく必要があります。Azure ADにおけるクライアント登録はディレクトリ設定の中のアプリケーションのメニューから行います。
アプリケーションはWebアプリケーションとして登録し、URLの返信(redirect_uri)およびクライアントID(client_id)、キー(client_secret)を取得しておきます。
今回はテスト用なのでredirect_uriは適当にhttp://localhostとかにしておき、あとはChrome ExtensionのAdvanced REST clientを使って動作確認をしています。






◆アクセスしてみる

さて、実際にアクセスしてみたいと思います。
流れとしては、先に紹介した仕様の通り、
1. Authorizationエンドポイントへアクセスしてcodeを取得する
2. TokenエンドポイントへcodeをPOSTしてaccess_tokenを取得する
3. 取得したaccess_tokenをAuthorizationヘッダにつけてUserInfoへアクセス、情報を取得する
という順に行います。


1. Authorizationエンドポイントへアクセスしてcodeを取得する

ブラウザを使って以下のGETリクエストを発行します。(改行は取り除いてください)

https://login.microsoftonline.com/common/oauth2/authorize?
    client_id=0856fxxxxxxxxxxx6bd0cf&
    response_type=code&
    redirect_uri=http%3A%2F%2Flocalhost&
    scope=openid&
    state=12345


すると、redirect_uriに指定したアドレスにクエリパラメータとしてcodeがついてきますので、値をコピーしておきます。

http://localhost/?
    code=AAABAAAAixxxxlWqrLsxILSH6fJ99WvmIAA&
    state=12345&
    session_state=9fac9xxxxx

尚、codeの有効期限は非常に短いのでこの後の作業は手早く行う必要があります。


2. TokenエンドポイントへcodeをPOSTしてaccess_tokenを取得する

ここからはAdvanced REST clientを使います。
先ほど取得したcodeおよびclient_id、client_secret、redirect_uriと合わせてgrant_typeにauthorization_codeを指定して、TokenエンドポイントへPOSTします。

https://login.microsoftonline.com/common/oauth2/token
    grant_type: authorization_code
    client_id:  0856fxxxxxxxxxxx6bd0cf
    code: AAABAAAAixxxxlWqrLsxILSH6fJ99WvmIAA
    redirect_uri: http://localhost
    client_secret: WjFotGxxxxxxxxx+imo=


すると、以下の様にaccess_token、refresh_token、id_tokenが返ってきます。

{
expires_in: "3600"
token_type: "Bearer"
expires_on: "1439454521"
access_token: "AAABAAAAixxxxxxxxWC0VQSAA"
refresh_token: "AAABAAAAxxxxxxxx6XIAA"
id_token: "eyJ0eXAiOiJKVxxxxxxxxEqegYSCaCaQrw"
}


もちろん以前紹介したようにid_tokenをデコードすればユーザの属性情報は取得できますが、あえてスルーします。

参考)id_tokenをデコードした結果
{
  "aud": "0856fxxxxxxxxxxx6bd0cf",
  "iss": "https://sts.windows.net/2c.......fff/",
  "iat": 1439450621,
  "nbf": 1439450621,
  "exp": 1439454521,
  "ver": "1.0",
  "tid": "2c.........fff",
  "oid": "785........4bed4",
  "upn": "jbecker@example.net",
  "sub": "NnF_CZAQ...............qoOv4",
  "given_name": "Jason",
  "family_name": "Becker",
  "name": "Jason Becker",
  "amr": [
    "pwd"
  ],
  "unique_name": "jbecker@example.net",
  "onprem_sid": "S-1-5-21-.........2-1618"
}



3. 取得したaccess_tokenをAuthorizationヘッダにつけてUserInfoへアクセスする

いよいよUserInfoエンドポイントへアクセスします。
前のステップで取得したaccess_tokenをAuthorizationヘッダにつけてGETリクエストを出せば良いので、同じくAdvanced REST clientでクエリを発行します。

https://login.microsoftonline.com/common/openid/userinfo
    Authorization: Bearer AAABAAAAixxxxxxxxWC0VQSAA

結果、以下とおりJSONでユーザの属性情報が取得できます。

{
tid: "2c.........fff"
oid: "785........4bed4"
upn: "jbecker@example.net"
sub: "NnF_CZAQ...............qoOv4"
given_name: "Jason"
family_name: "Becker"
name: "Jason Becker"
}


id_tokenの方が情報が多いですね・・・。

ちなみに、現状Azure ADでは一般的なOpenID ConnectのProviderの様にprofileやemailなどのscopeが使えず、openidのみしか指定できないので、取得するclaim(属性)を指定することは出来ません。


尚、本日アナウンスされたApp Model v2.0用のAPIバージョン(oauth2/v2.0/のエンドポイント)ではUserInfoへのアクセスがまだ使えないので、マイクロソフトアカウントに関する属性情報の取得はできません。

2015年8月12日水曜日

[雑記/Azure AD]MSDN特典でサポート・リクエスト作成ができない件

こんにちは、富士榮です。

今回はIdMにあんまり関係ない話題です。

◆概要

Azure Active Directory(Azure AD)に関するテクニカルな問題に関するサポートへの問い合わせをMSDNのアクセスID、契約IDで行おうとして見事にはまった話です。

結論はアクセスID、契約ID(7桁)の頭に「065」をつける必要がある、ということなのですが、どこにもこのような記述がなく、技術的な問い合わせをする前に、問い合わせ方法に関する問い合わせを別途行う必要があった、、という。。。

以下、顛末です。

◆MSDNのアクセスID、契約IDの取得

・MSDNの特典についてるアクセスIDと契約IDはアクティベーション(電話もしくはオンラインチャットのみで可能)を行うことで取得できます。
・即時発行はできないらしく、翌日メールで通知されました。
・通知されてきたアクセスID、契約ID(契約番号)は同じ番号で7桁のものでした。

こんなメールが来ます。

◆Azureの新ポータルより問い合わせ

・Azureに関連する問い合わせは新ポータルより行うことになります。(強制的に新ポータルに飛ばされます)
・今回はAzure ADに関する技術的な問い合わせをしたかったので、以下の順に登録します。
 リクエストの種類 : テクニカル
 サブスクリプション情報 : MSDNのサブスクリプション
 リソース : Active Directory
・次にサポートプランの選択をするのですが、初回問い合わせなので先ほどのアクセスID、契約IDを入力するのですが、上手く入力できません。


なぜかアクセスIDが無効とのこと。


◆途方に暮れた末、サポートに電話、先頭に「065」をつけると良いらしいとの裏技を聞く

・サポートの方と会話したところ、このポータルで入力するアクセスIDは10桁である必要があるそうです。。。
・MSDNから通知されたアクセスIDは7桁でしたので、先頭に「065」をつける必要があるらしいです。
・ちなみにアクセスIDだけでなく、入力上はエラーにならなかった契約IDについても「065」をつけないと[リンク]に失敗します。




◆無事にサポートプランが選択できるようになり、技術問い合わせが可能になる

・リンクに成功すると、サポートプランのプルダウンでプラン選択ができるようになります。






◆結論

・さすがに先頭に「065」をつける裏技があるとは想像すらできませんでした。Azure難しいです。


2015年8月8日土曜日

[Azure AD]Cloud App DiscoveryでシャドーITを検知する

こんにちは、富士榮です。

最近の企業の情報システム部門を見ていると、事業部門が使う業務アプリケーションについて、
・セキュリティを担保した上で使ってもらいたい
・そのためには何を使っているのかを把握し統制を効かせたい
・ただ、全部のアプリケーションを情報システム部門で管理する人的リソースがない
という状態になっているように感じます。
その結果として、いわゆる「シャドーIT」とか「野良IT」と言われる各事業部門側が個別にSaaSアプリケーションなどを契約し使っている状態が散見される状態となっている訳です。

本来はIDaaSなどをうまく活用して各SaaSアプリケーションのID部分だけでも情報システム部門で抑え込んでせめて退職済みアカウントでは使えない状態にする、などの統制を効かせる工夫をしたいところですが、すでに利用が始まってしまっているシャドーITの状態を把握するのは大企業になればなるほど困難になります。

※IDaaSの概要と情報システム部門での活用については先日始まった@ITの連載をご覧ください。
 企業のID管理/シングルサインオンの新しい選択肢「IDaaS」の活用:
  第1回 もはや企業のID管理で避けては通れない「IDaaS」とは?
  http://www.atmarkit.co.jp/ait/articles/1508/07/news034.html


と、いうことで今回はすでに業務部門に広まってしまったSaaSアプリケーション利用の状態を把握するために用意されているAzure ADの追加機能「Cloud App Discovery」について解説します。

◆Cloud App Discoveryとは

先に書いた通り、企業内からどのようなSaaSアプリケーションが実際に使われているのかを検出するためのツールで、Azure AD Premiumのライセンスが割り当てられている管理者が機能を使うことが出来ます。

仕組みとしては、組織内のコンピュータにCloud App Discovery用のエージェントをセットアップし、各コンピュータからのSaaSアプリケーションの利用状況をAzure ADに集める、という構成になっています。※エージェントモジュールは各Azure AD/Cloud App Discoveryテナント毎に証明書とセットでダウンロードされるので、System Centerやグループポリシーなどのクライアント構成ツールで各コンピュータに配布します。
※サービス解説ページより


◆Cloud App Discoveryの有効化

Azure Portalのマーケットプレイスより追加します。Azure Portalのマーケットプレイスを開くと「セキュリティ+ID」のセクションに「Azure AD Cloud App Discovery」があるので選択して作成します。




◆Cloud App Discoveryの設定:コンピュータへのエージェント導入

先にも書いた通り、通常はSCCMなどでモジュールを配布することになると思いますが、今回は手動でインストールしてみます。
Azure PortalからCloud App Discovery、クイックスタートを開くと「エージェントのダウンロード」というセクションがあり、ここからエージェントモジュールをダウンロードできます。現段階ではWindows 7以降のコンピュータに対応しているようです。



ダウンロードしたモジュールを解答し、セットアップファイルを実行するとGUIモードでエージェントをインストールできます。特に設定オプションはないのでそのままインストールします。





インストール後、PCのサービスの状態を見ると[SerresEndpointAgent]というサービスが動いていることがわかります。これがエージェントモジュールの実体です。


あとは放っておけばAzure AD上にクライアントが利用したSaaSアプリケーションの情報が集まってくるはずです。


◆Cloud App Discoveryの設定:収集対象アプリケーションの絞り込み

当然このままでも良いのですが、ある程度収集対象とするアプリケーションの種類を絞り込みたい場合もありますので、ポータル側で収集対象アプリケーションの絞り込み設定を行うことができます。

[設定]から[データコレクション]のセクションを開くと対象のアプリケーションの絞り込み設定を行うことが出来ます。
既定では2,100程度のアプリケーションが選択された状態になっていますので、必要なアプリケーションのみに絞り込むことが可能です。




◆収集結果の分析

ある程度データが集まるとCloud App Discovery上のグラフに、
・アプリケーションの利用数
・ユーザ数
・エージェントの導入数
が表示されてきます。

それぞれを展開するとどのようなアプリケーションを使ったのか、誰が使ったのか、どのコンピュータにエージェントが導入されているのかがわかります。





◆非管理対象のアプリケーションをAzure ADで管理する

アプリケーションの利用情報が収集できたら、管理対象にしたいアプリケーションを選択するとAzure ADのアプリケーション管理メニューへ移動できるので、事業部門へアナウンスし、アプリケーションとの連携設定を行い、あとはAzure ADを経由して使ってもらえば、通常のアプリケーションと同様にAzure ADのレポーティングで利用状況のモニタリングが可能になります。




最初からAzure ADなどのIDaaSを使ってすべてのアプリケーションを利用する、というように統制が効かせられる環境であれば特にこのような工夫は必要にはなりませんが、なかなかそのような状況はないと思いますので、まずはこのような形で利用実態を把握するところから始めるのが良いのかもしれません。

2015年8月4日火曜日

[MIM]Microsoft Identity Manager 2016がリリースされました

ついにForefront Identity Manager 2010(FIM)の後継であるMicrosoft Identity Manager 2016(MIM)が正式にリリースされました。

製品ページ)
 http://www.microsoft.com/en-us/server-cloud/products/microsoft-identity-manager/


以前のポストでも紹介したように、MIMでは以下の機能が目玉となっています。

  • 特権アカウント管理
  • 多要素認証を使ったセルフ・サービス・パスワード・リセット
  • Universal Windowsアプリでの証明書管理クライアントの提供
  • 最新プラットフォームのサポート


※画像はCTP4です。


MSDN等でもダウンロードできるようになっていますし上記製品ページから評価版も入手できるので、是非試してみましょう。

2015年8月3日月曜日

[Azure AD/ASP.NET]ユーザ属性を取得する2つの方法


こんにちは、富士榮です。

7/29のWindows10のリリースで盛り上がっていますが、その直前にひそかにリリースされていたVisual Studio 2015ではASP.NETのアイデンティティ関連機能が色々と拡張されています。

概要はVisual Studioの公式blogでアナウンスされているので、そこはそちらに任せておくとして、今回はASP.NET MVC5のプロジェクト・テンプレートが拡張されてGraph APIを使ってAzure ADのユーザ属性の取得がされるように変わっているのでその辺りの解説をしたいと思います。また、以前のバージョンから仕えましたが、SSO時のJWT(JSON Web Token)からClaim(属性)を取り出す方法について解説します。

 参考)Visual Studioの公式blog
  Identity Management Features in Visual Studio 2015
  http://blogs.msdn.com/b/visualstudio/archive/2015/07/22/identity-management-features-in-visual-studio-2015.aspx


◆ASP.NETでAzure ADからユーザ情報を取得する方法

先にも書きましたが、ASP.NETでAzure ADと連携するアプリケーションを開発する場合、以下の2つの方法で認証済みユーザの属性を取得することができます。

1.認証時にAzure ADで発行されるJWTに含まれるClaim(属性)を取得する
2.認証後、Graph APIを使ってディレクトリ(Azure AD)上のユーザ属性を取得する


早速それぞれの方法について解説します。


◆JWTに含まれるClaimを取得する

ASP.NETアプリケーションのプロジェクトを作成する際、認証の構成を設定できます。



ここでAzure ADのテナント情報を入れるとアプリケーション起動時にAzure ADを使って認証が行われるようになります。
その際、内部的な動作としてはOpenID Connectを使ったID連携が行われ、Azure ADからアプリケーションにJWTがPOSTされてきます。

POSTされるid_tokenの中身をJWT Decoderでデコードしてみると、以下のようなClaimが含まれていることがわかります。

{
  "aud": "0897xxxxxxxxx65c",
  "iss": "https://sts.windows.net/2c6xxxxxxxxxxxx1bfff/",
  "iat": 1438609784,
  "nbf": 1438609784,
  "exp": 1438613684,
  "ver": "1.0",
  "tid": "2c62f1axxxxxxxxxxxbb1bfff",
  "oid": "457ca53xxxxxxxxxe363dc73c",
  "upn": "nfujie@xxxxxxxxx.onmicrosoft.com",
  "sub": "ILvM1kZdv7kxxxxxxxxiPrw2fPusCk",
  "given_name": "Naohiro",
  "family_name": "Fujie",
  "name": "Naohiro Fujie",
  "amr": [
    "pwd"
  ],
  "unique_name": "nfujie@xxxxxxxx.onmicrosoft.com",
  "nonce": "63574206878.....snip....LTg0YmMtOGFkYmMyZTcwY2Yz",
  "c_hash": "QIsD2...snip...fYgA"
}


これを見るとユーザのUPN(userPrincipalName)や姓(surName)、名(giveName)などもid_tokenの中に含まれていることがわかります。
これらの属性をアプリケーションから取得することが出来れば、アプリケーション上でログインIDだけでなく、ユーザ表示名を表示してあげることが出来るようになるはずです。

では、早速取得してみます。
まず、Azure ADを使った認証がプロジェクト・テンプレート上でどのように実装されているのかを見てみます。
ソリューション・エクスプローラからApp_Startフォルダの中のStartup.Auth.csを開くと、Microsoft.Own.Security.OpenIdConnectを使ってAzure ADとのOpenID ConnectでのID連携を実装していることがわかります。


と、いうことは認証後、id_tokenに関する情報はOwinContextに入れられるはずなので、アプリケーションからはOwinContextの中身を検索することでClaim情報が取得できるはずです。

RequestのGetOwinContext()メソッド使ってContextを取得し、その中の認証およびユーザに関する情報をAuthenticationプロパティ/Authentication.Userプロパティから取得します。
あとは、取得したUserオブジェクトのClaimsコレクションからClaimを順番に取り出せばid_tokenの中身が取得できます。

具体的には以下のようなコードを書きます。

var ctx = Request.GetOwinContext();
var user = ctx.Authentication.User;
var response = ctx.Response;
response.ContentType = "text/html";
if (user.Identity.IsAuthenticated){
   foreach(var claim in user.Claims){
      response.Write(claim.Type + "=" + claim.Value + "<BR>");
   }
}




◆Graph APIを使ってAzure ADから属性を取得する

次はGraph APIを使って認証済みユーザの属性をAzure ADへ問い合わせ、取得する方法です。
プロジェクトの認証構成を行う際に、ディレクトリ情報の読み取り許可を与えることでGraph APIを使ってユーザ情報を取得できるようにプロジェクトが構成されます。


アプリケーションを起動し、Azure ADで認証後、画面右上に表示されるログインIDをクリックするとUserProfileが表示されます。



この部分の実装を見るとGraph APIを使ってユーザ属性を取得しています。
対象のソースはControllers以下のUserProfileControllers.csです。GraphClientが使用されていることがわかります。



実際はこのControllerから呼び出されるViewにuserオブジェクトを渡しているので、表示項目の見せ方については対象のViewであるViews/UserProfile/Index.cshtmlを見てみます。ここでは@Model.[属性名]という形で属性を取得してテーブルに埋め込んでいますので、好きな属性を指定してテーブルを拡張していくことで任意の属性を表示させることが可能です。(今回はJobTitle属性を追加しています)




どちらの方法が適しているのかは、どんな属性が必要なのかをベースに考えれば良いと思います。例えば役職や組織情報を使ってアクセス権制御を行いたければGraph APIを使う方法になると思いますし、単に名前を表示させるだけならJWTから取得する方が通信量が少ないので実装としては軽くなります。
※現状のAzure ADではid_tokenに含めるClaimのカスタマイズができないので、id_tokenにない属性を取得したければGraph APIを使うしか方法がありません。


いずれにしてもAzure ADを使った認証や属性取得がかなり楽に実装できるようになっていますので、あまりカスタムで頑張った実装をするよりもテンプレートにある仕組みを使ってアプリケーション開発をしていった方が今後はよさそうですね。