ディレクトリ同期の運用自動化

この記事は、Office 365 Advent Calendarに参加しています。

AD FSやディレクトリ同期を利用すると、オンプレミスのADとOffice365の間でシームレスな運用が可能になります。ただ、

  • 同期間隔が3時間
  • 同期後のサブスクリプションの割り当てが管理者が実行しなくてはならない

など、いくつか運用として管理者が対処を行わなければならない部分が存在します。

今回はディレクトリ同期で新規で作成されたユーザーに対してOffice365のプロビジョニング(サブスクリプションの割り当て)を自動で実施できるようにしたいと思います。特に社内でIdMなどを利用している場合などについては有用だと思います。

同期ユーザーの中でどのユーザーにライセンスを割り当てるかの判定は、各組織によって色々と実装方式は有ると思いますが、今回WAAD Premium のグループ管理機能と同じようにグループで判断したいと思います。

まずは、以下の内容のps1スクリプトファイルを作成して適当なフォルダに配置します。管理者のID、PassやSKU(Get-MsolAccountSkuコマンドで取得可能)、グループ名などは実際の環境に合わせて修正してください。今回はc:workscriptsautodirsync.ps1として保存します。

######################################################################
#
#    Office 365 Auto Provisioning Script for DirSync (autodirsync.ps1)
#       2013/12/11     https://blog.o365mvp.com/
#
######################################################################
$adminuser = "admin@contoso.onmicrosoft.com"     # TenantAdmin UserName
$adminpass = "P@ssw0rd"                          # TenantAdmin Passrord
$group = "Office365e3"                           # Target Group
$sku = "contoso:ENTERPRISEPACK"                  # Office365 SKU ID (cf.Get-MsolAccountSku)
$skuname = "E3"                                  # Office365 SKU name
$log = "c:workscriptsautodirsync.log"         # Log Filename

(Get-Date -Format "yyyy/MM/dd HH:mm:ss") + " Office 365 Auto Provisioning Script Start" | Out-File $log -Append

sleep 60                  # Wait for reflect DirSync information

Import-Module MSOnline
$password = ConvertTo-SecureString $adminpass -AsPlainText -Force
$LiveCred = New-Object System.Management.Automation.PSCredential $adminuser,$password
Connect-MsolService -Credential $LiveCred

$member = Get-MsolGroupMember -GroupObjectId (Get-MsolGroup -SearchString $group).ObjectId -All
$unlicensed = Get-MsolUser -UnlicensedUsersOnly
foreach ( $user in $unlicensed ){
    $result = $member | ? {$_.ObjectID -eq $user.ObjectID}
    if ($result) {
        (Get-Date -Format "yyyy/MM/dd HH:mm:ss") + " Add $skuname License to " + $user.UserPrincipalName | Out-File $log -Append
        Set-MsolUser -UserPrincipalName $user.UserPrincipalName -UsageLocation JP
        Set-MsolUserLicense -UserPrincipalName $user.UserPrincipalName -AddLicenses $sku
    }
}
(Get-Date -Format "yyyy/MM/dd HH:mm:ss") + " Office 365 Auto Provisioning Script Finished" | Out-File $log -Append

このスクリプトをディレクトリ同期が終了したタイミングで実行すれば良いので、今回はタスクのトリガーで実行したいと思います。バージョンにより異なりますが、サーバのイベントログを確認して、Directory Syncronizationサービスの4か114のExport完了のイベントログを特定します。
20131210_01 20131210_02

続いてはタスクスケジューラへの登録です。右の操作ペインから基本タスクの作成を選択してウィザードを起動します。
20131210_03

名前は適当に付けて、トリガーを「特定イベントのログへの記録時」にして、ソースやイベントIDは前の項目で特定したエクスポート完了時のイベントログを指定します。
20131210_04
20131210_05 20131210_06

実施するアクションはプログラムの開始にします。.ps1のスクリプトファイルをタスクから起動する場合は、プログラム/スクリプトの項目には c:windowssystem32WindowsPowerShellv1.0powershell.exe を、引数として -command [.ps1スクリプトのフルパス]を指定します。
 20131210_08 20131210_09 20131210_10

最後に、作成したタスクのプロパティを開いて、[ユーザーがログオンしているかどうかにかかわらず実行する]を選択して実行アカウントのパスワードを保存します。
20131210_11

これにより、デイレクトリ同期完了後、指定のグループ(上記ではOffice365e3)のメンバーでライセンスの割り当てられていないユーザーが存在した場合には自動的にライセンスが割り当てられるようになります。
20131210_12

実際の運用の中では、環境に応じてsleepの値を調整したりUsageLocationにJP以外が有ったり複数のサブスクリプションがある場合はその処理部分などを修正すれば良いかと思います。ライセンスの残数を見て閾値を下回ったら自動的にメールを飛ばすなども入れておくと楽になりますね。

ブラウザアクセス時のADFSによるIPアドレス制御

本投稿はOffice 365 Advent Calendarに参加しています。
「Office 365チームサイト活用ガイド 2013年版」が絶賛発売中のOffice 365 MVPの中村さんからバトンを頂きました。

今回は、Office365のアクセス制御の実現方法について述べたいと思います。

AD FSを利用すると、Office365に対するアクセス制御を行うことが可能です。Microsoftのサイトでも具体的な構成例などがいくつか紹介されています。

クライアントの場所に基づいた Office 365 サービスに対するアクセスの制限

アクセス制御ができるパターンは色々とあるのですが、いくつか制約事項もあります。その中で一番大きいと思われる物が、「ブラウザからのアクセス制御時に、クライアントのIPアドレスで制御ができない」ということになります。勿論、AD FSのクレームルールではなく、IISやその前のFirewallなどで完全にブロックすることは可能ですが、例えば以下の様なIPとADの情報を合わせた条件付けが必要な設定は実装できません。

  • 本社からの内部アクセスの他、特定グループ(例えば出向者、在宅勤務者)のユーザーは特定IP(例えば出向先、自宅)からのブラウザアクセスを許可する

これは、アクセス制御に利用する送信元IPの情報が付与される場所に依存しています。
20131203_06

上図の通り、IPアドレスであるグローバルIP:Aは「X-MS-Forwarded-Client-IP」に格納されてAD FSに渡されてきますが、この情報はExchange Onlineにより付与されます。この為、クライアントからAD FS Proxyに直接アクセスをするOWAやSharePoint Onlineへのアクセスの際には付与されません。

これは仕様上仕方の無いことなので、今までは上記のような構成で外部アクセスを制御する場合は、SSL-VPNで一回社内ネットワークに接続させるなどしてAD FSサーバへの直接の接続性を確保する必要がありました。(VPNをクライアントPCで張ってからブラウザでシングルサインオンをするイメージ)

今回は、一部の皆さまの熱い要望(?)にお答えしてこの制限を回避してみたいと思います。

まず、この情報がどうやってAD FSに伝わってくるかですが、上記Microsoftのサイトに以下の記載があります

サードパーティのプロキシを使用している場合は、HTTP ヘッダーの x-ms-proxy を送信するようにプロキシを構成し、プロキシ ホストの完全修飾 DNS 名の値を含める必要があります。

この情報から推測すると、これらの情報はHTTPS通信のパケット中のHTTPヘッダに埋め込まれて送信されているのではないかと考えられます。つまり、AD FS Proxyの手前にリバースProxyなどHTTPSを終端できる物を挟んで、そこで情報を挿入してあげれば良いのでは?という推測ができます。

というわけで検証です。まずは手軽なARRでリバースProxyを立てます。詳細なやり方は他の方のblogで色々紹介されているので流れだけ。IISのインストールされたサーバ上でiis.netのサイトからWeb Platform Installer使って簡単にインストールできます。
20131203_01

適当なサイトを作成してAD FS Proxyで利用している物と同じSSL証明書をバインドします。URL書き換えからリバースProxy向けの規則を作成してAD FS Proxyに要求を転送するように設定。SSLオフロードの設定は外します。そして、リバースProxyの設定からカスタムヘッダの名称をX-MS-Forwarded-Client-IPに変更し、TCPポートを含めるのチェックを外します。
20131203_03

というわけで接続をしてみると、以下の様な情報が取得できます。(AD FSの監査ログを有効にして取得しています)
20131203_04

非常に地味ですが、x-ms-endpoint-absolute-pathが/adfs/ls/(つまり、Passiveフェデレーション)なのにx-ms-forwarded-client-ipに値が入っています!

また、ARRはIISに追加するモジュールなので例えばAD FS Proxy上にインストールして、グローバルIPからの接続をARRのサイトで受けて、それを127.0.0.1のDefault Web Site配下のAD FS Proxyに渡して処理するということも可能です。
20131203_05

この構成において、Webブラウザ以外からのアクセスはIISのサイトではなくAD FS Proxyのアプリケーションが処理しているので、ARRの処理を通りません。つまり、Exchange Onlineから付与されてきたX-MS-Forwarded-Client-IPの情報は保持されます(つまり、影響無し)。また、LyncクライアントやPowerShell、Office ProPlusなどMEXへのアクセスについてもARRでIP情報を付与できないので、これまで同様にIPベースの制御は残念ながらできない形です。

というわけで、今回はさわりの部分だけなので軽くヒント的な物になってしまいましたが、何かの参考になれば幸いです。ちなみに、もちろんこちらの記事の内容はMicrosoftによってサポートされている物ではありませんのでいつ仕様が変わって利用できなくなるか分かりません。あくまで今の時点で検証レベルではできましたよ、という話です。

次はVisual C# MVPの瀬尾さんです。