2012年9月26日水曜日

[WAAD] REST Client で Graph API を直接実行する

# 一部ご指摘をいただきましたので若干修正(Base64 encode ⇒ Base64 url encode)

Windows Azure Active Directory をアプリケーションから利用する際、 Windows プラットフォームであれば、Windows Azure Authentication Library(AAL)を利用することになると思いますが、折角 RESTful な Graph API があるので、汎用 REST Client を使って API へアクセスしてみたいと思います。

■準備
 TenantContextID、AppPrincipalId、SymmetricKey が必要となります。前回同様、CreateServicePrincipal.ps1を使って必要な値を取得します。

 用意が出来たらいよいよアクセスしますが、今回やろうとしていることの全体像を簡単に図にしておきます。

 まず Graph API を利用するために必要な認可を ACS で受け、ACS から取得した Access Token を持って Graph API を利用する、という流れになります。

 実際にやってみると以下のような手順になります。

■Graph API を利用するための Access Token を取得する(REST Client ⇒ ACS)

 初めに、Graph API へのアクセスを行うために必要な Access Token を ACS から取得する必要があります。
 そのためには ACS へ JSON Web Token(JWT)形式でリクエストを投げる必要があります。

 リクエスト先および内容は以下の通りです。

Target Endpointhttps://accounts.accesscontrol.windows.net/tokens/OAuth/2
MethodPOST
Request HeaderContent typeapplication/x-www-form-urlencoded
Request Bodygrant_typehttp://oauth.net/grant_type/jwt/1.0/bearer
assertion
(実際は Symmetric Key でデジタル署名したもの)
{
"alg": "HS256",
"typ": "JWT"
}
{
"aud": "00000001-0000-0000-c000-000000000000/accounts.accesscontrol.windows.net@[TenantContextId]",
"iss": "[AppPrincipalId]@[TenantContextId]",
"nbf": "[UNIX 時間で現在の時刻]",
"exp": "[UNIX 時間でTokenの有効期限]"
}
resourceresource : 00000002-0000-0000-c000-000000000000/directory.windows.net@[テナントID]

 Assertion の部分を作り方は少々面倒ですが、下記の通りです。

 ・ヘッダ部分を Base64 でエンコード

  文字列「{"alg": "HS256","typ": "JWT"}」をこのあたりのツールで Base64 URL エンコードします。

  結果、「eyJhbGciOiAiSFMyNTYiLCJ0eXAiOiAiSldUIn0」という文字列が得られます。



 ・ボディ部分を作成

  JWT を構成する、nbf(Not Before / 有効開始時刻)、exp(Expiration Time)クレームは UNIX 時刻(1970年からの経過秒数)で表すため、このあたりのツールを使って現在時刻および現在時刻+1時間を変換した値を取得します。

  例えば、2012年9月25日23時00分00秒~2012年9月26日00時00分00秒まで有効なトークンを作成するには、
  "nbf" : "1348581600",
  "exp" : "1348585200"
  というクレームを設定します。

  結果、以下の様な JWT ボディを作成します。
  {
   "aud": "00000001-0000-0000-c000-000000000000/accounts.accesscontrol.windows.net@[TenantContextId]",
   "iss": "[AppPrincipalId]@[TenantContextId]",
            "nbf": "1348581600",
            "exp": "1348585200"
  }

 ・ボディ部分を Base64 でエンコード

  先ほどのヘッダ部分と同様に生成した JWT のボディも Base64 URL エンコードします。

  結果、「eyJleHAiOiIxMzQ4NTU5MTY4IiwiYXVkIjoiM(以下略)」といった文字列が得られます。

 ・ヘッダ+ボディを連結した raw token と SymmetricKey でデジタル署名を生成

  ヘッダ部分とボディ部分を"."(ピリオド)で連結した raw token を作成し、SymmetricKey を Base64 デコードした文字列を使ってデジタル署名を生成します。

  良いオンラインツールがなかったので、以下の Java コードを作成し、署名を生成しました。
  ※Java であることに深い意味はありません。手元に eclipse が起動していた&Java のサンプルがあった、というだけです。
  ※どなたか良いオンラインツールがあれば教えてください。


import javax.crypto.spec.SecretKeySpec;
import javax.crypto.Mac;
import org.apache.commons.codec.binary.Base64;

public class GenerateSignature {

    private static byte[] signData(String signingKey, String rawToken) {
        SecretKeySpec secretKey = null;
        secretKey = new SecretKeySpec(Base64.decodeBase64(signingKey), "HmacSHA256");
        Mac mac;
        byte[] signedData = null;
        try {
            mac = Mac.getInstance("HmacSHA256");
            mac.init(secretKey);
            mac.update(rawToken.getBytes("UTF-8"));
            signedData = mac.doFinal();
        } catch (Exception e) {
            System.out.println("signData error");
        }        
        return signedData;
    }
    /**
     * @param args
     */
    public static void main(String[] args) {
        String signingkey = "Li7Awy53cq(以下略。SymmetricKey文字列)";
        String rawToken = "eyJhbGciOiJ(以下略。ヘッダ部分)).eyJleHAiOiIxMzQ4(以下略。ボディ部分)";
        String signature = Base64.encodeBase64String(signData(signingkey,rawToken));
        System.out.println(signature);
    }

}

 ・Assertion の生成

  生成した署名文字列を先ほどの raw token の後に同じく"."(ピリオド)で連結します。



 このようにして作成した Assertion を他のパラメータと一緒に ACS へ POST します。
 リクエストの POST は Chrome Extension の Advanced Rest Client を使いました。

 以下の様にパラメータをセットし、[Send request]ボタンをクリックします。


 うまくいくと、HTTP 200 が返ってきて、JSON 形式で Access Token が取得できます。




■取得した Access Token で Graph API を利用する(REST Client ⇒ Graph API)

 いよいよ Graph API を使います。

 リクエスト先および内容は以下の通りです。

Target Endpointhttps://directory.windows.net/[テナントドメイン名].onmicrosoft.com/Users
MethodGET
Request HeaderAuthorization取得した Access Token 文字列(bearer 以降)
x-ms-dirapi-data-contract-version0.8


 先ほどと同様に Advanced Rest Client にパラメータをセットして、[Send request]ボタンをクリックします。


 うまくいくと、HTTP 200 が返ってきて、ユーザ一覧が取得できます。



尚、書き込みを行う場合はロール設定が必要になるので、このあたりは次回以降で。。

2012年9月23日日曜日

[FIM] Active Directory への同期に必要な権限

昨日は .NET ラボさんの勉強会で FIM / AD FS2.0 のハンズオンを実施しました。
回線の混雑具合や時間配分的な問題で用意していたシナリオを終えることは無理があったのですが、いずれリベンジをしたいと思っています。

さて、ハンズオン環境を作る上で一つ入れ忘れていた設定があり参加者の方にご迷惑をかけた点があり、結構忘れがちな設定でもあるのでこの機に書いておこうと思います。


FIM をはじめアイデンティティ管理ツールを使って Active Directory 上のユーザを作成・変更・削除する、というシナリオは企業内ではごく一般的なものだと思います。

その際に、Active Directory 上のオブジェクトをメンテナンスするためのユーザとその権限をどうするのか?というポイントは慎重に検討する必要があります。

実際には Active Directory の管理者とアイデンティティ管理システムの管理者が同じ人や組織なので何も考えずに Domain Admins の権限を持ったユーザや Administrator ユーザそのものをアイデンティティ管理システム上に設定してしまったりしている例も多いと思いますが、出来れば必要最低限の権限を持ったユーザを使いたいところです。

結論から書くと、FIM の場合は以下の2つの権限が必要になります。
・デフォルトネーミングコンテキストに対するディレクトリ・レプリケーションの権限
・管理対象オブジェクトを格納する OU および子オブジェクトに対するフル・コントロール
※デフォルトネーミングコンテキストとは、LDAP 文字列でいうところの DC=xxx,DC=xxx にあたる部分です。

もちろん手動で Active Directory ユーザとコンピュータ から権限を設定することも可能ですが、特にディレクトリ・レプリケーション権限は特殊権限なので設定をするのが面倒です。
そこで通常は DSACLS.EXE を使った以下のようなスクリプト(PowerShell の例)を実行して一気に設定を入れてしまいます。
# Active Directory からネーミングコンテキストを取得
$RootDse = [ADSI] "LDAP://RootDSE"
$DefaultNamingContext = $RootDse.defaultNamingContext

# 対象ユーザの SID を取得
$UserPrincipal = New-Object Security.Principal.NTAccount("<NetBOISドメイン名>", "<利用するユーザ名>")
$SID = $UserPrincipal.Translate([System.Security.Principal.SecurityIdentifier]).Value

# ディレクトリ・レプリケーション権限を付与
DSACLS "$DefaultNamingContext" /G "$($SID):CA;Replicating Directory Changes";

# 対象 OU および子オブジェクトへのフル・コントロール権限を付与
DSACLS "<対象 OU 名>,$DefaultNamingContext" /G "$($SID):GA" /I:T 
勉強会でも話をしましたが、 FIM の設定は周辺を含め非常に面倒です。
このようなスクリプトをネタとして持っておいて使いまわす、というのがベストプラクティスなのだと思います。

2012年9月13日木曜日

[WAAD]スタンドアロンのテナントが作成可能に


これまでは Windows Azure Active Directory(WAAD) を使おうとすると、Office365 など WAAD をアイデンティティ基盤として利用するサービスを登録する必要がありましたが、今回まだプレビューですが直接 WAAD のみにサインアップすることが可能になりました。

これまで WAAD を使うのに何度も Office365 の評価版のサインアップをしていたのでこのように単体でサインアップできるようになったのは非常に便利です。

サインアップは以下のURLから実施します。

http://g.microsoftonline.com/0AX00en/5





ようやく Graph API を検証し始めているので、そのうち情報をアップしたいと思います。

2012年9月11日火曜日

[WAAD] Preview ポータルのLook & Feel

Windows Azure Active Directory の管理ポータルの Preview 版が出てきています。

https://activedirectory.windowsazure.com


今後はこのポータルから Office 365 などを含むアカウントの管理や設定を行うことになると思いますので、新しいポータルに慣れておきたいところです。

ということで、新旧ポータルの画面を単純に並べて比較しておきます。
(旧: Office365 の管理者ポータル。新: Windows Azure Active Directory 管理ポータル Preview)

トップ画面

【旧】

【新】今は Office365 の情報しか出ていませんが、今後は他のサービスに関する情報も表示されることになるんでしょうか。 ※ Windows Intune / Dynamics Online は触ったことがないので、今でもここに出てくるかは不明です。どなたか知ってますか?


ユーザ

【旧】


【新】シングルサインオンやディレクトリ同期が別メニューへ移動したので非常にシンプルになっています。

セキュリティグループ

【旧】

【新】

ドメイン

【旧】

【新】この辺りはあんまり変わりません。


シングルサインオンなど

旧ポータルではユーザの管理の中にあったメニューが「統合」メニューに別出しされています。

【新】すっきりしました。


と、ざっと並べてみました。
今後は新しいポータルで管理を行うことになると思いますので、早めに慣れておきましょう。
(という程違いはありませんが。。)

2012年9月8日土曜日

9/22 FIM/AD FSセミナの内容をチラっと

前回の投稿で告知させていただいた9/22のFIM/AD FSのセミナですが、ようやく資料とハンズオン環境の作成が一段落してきたので、チラっと。

登録ページはこちら。
http://kokucheese.com/event/index/51905/


この中の私のパートである、「FIM/ADFSのアーキテクチャ(仕組み)解説」ですがこんな目次です。



とりあえず、アイデンティティとかアイデンティティ管理とは何なのか?というあたりの基礎的なところを軽くお話し、その後 FIM と AD FS2.0 の仕組みを解説します。

FIM の仕組みの部分では、一番わかり難い(と思われる)同期規則がユーザにどのように火も付けられるのか?というあたり(コードレス・プロビジョニング)の仕組みを解説予定です。



AD FS 2.0 のパートは AD FS 2.0 自体が非常にシンプルな作りなので、どちらかと言うと SAML そのものの解説になる予定です。



とりあえずこんな感じで進めるので、ぜひご参加を。

2012年9月6日木曜日