AAD ConnectでExchange属性が同期されない

ディレクトリ同期(AAD Sync含む)を利用する環境下において、Exchange Onlineで利用されるユーザーなどの情報は全てオンプレミスのActive Directoryから同期され、管理されます。

このため、アドレス帳非表示やふりがななど、メールボックスの動作を制御する一部の属性はオンプレミス側で設定し、同期する必要があります。オンプレミスにExchange Serverが無い場合は、その設定用にスキーマ拡張のみして属性を設定するというTIPSは比較的昔から存在していました。
20161210_01

こういった環境のユーザーがAAD Connectに移行すると、アドレス帳非表示の設定が消えるなどの影響が出る可能性があり、注意が必要です。

なぜかと言いますと、AAD Connectはマルチフォレスト(特にリソースフォレストモデルのExchange環境)のサポートを行うために、デフォルトの同期ルールが以前と変わっています。

具体的には、ユーザーの属性を取得する際に、Exchange関連の属性は[mailNickname]が存在するフォレストから取得するようになっています。

従来:
Azure Active Directory に同期した属性値のリスト

AAD Connect:
Azure AD Connect Sync: 既定の構成について

MailNicknameは、Exchangeにおける[Alias]として利用されている物であり、Exchange関連のオブジェクトであれば必須のパラメータとなっています。しかし、ADSIエディタなどでアドレス帳非表示を制御するmsExchHideFromAddressListsなどの属性を加える運用を行っている場合、mailNicknameには値が入っていないというケースが多くあります。

PowerShellから、Exchange属性であるmsExchHideFromAddressListsを同期しているルールを確認すると、[In from AD – User Exchange]というルールで同期されており、そのフィルタの条件はmailNicknameがNOTNULLということが分かります。
20161210_02

Get-ADSyncRule | ? {$_.AttributeFlowMappings -like "*msExchHideFromAddressLists*" -and $_.SourceObjectType -eq "user"} |  ft Name,Identifier
(Get-ADSyncRule -Identifier [上記で表示されたID]).ScopeFilter.ScopeConditionList

同様に、ルールエディタからも確認ができます。
20161210_03 20161210_04

※このルールはExchangeのスキーマ拡張がされていない環境では作成されません。また、マルチフォレスト、マルチドメイン環境では複数作成されます。

さて、では対応するためにどうしていけばいいかですが、アプローチとしては2つあります。

  1. [In from AD – User Exchange]のデフォルトルールを変更し、mailNicknameによる条件フィルタ自体を削除する
  2. [In from AD – User Exchange]をコピーして新たなルールを作成し、条件をmailNickname = NULLにする

いずれも、全ユーザーに対してExchange関連属性を設定するという意味では同じですが、今後ソフトウェア更新をした際にデフォルト設定が変わる可能性があるリスクを考えると2番の方がメンテナンス性は良いかと個人的には考えてます。(1で実装する場合も、実際には元の設定は無効化し、コピーしたルールに手を加えます)

手順ですが、Syncroniztion Rule Editorを管理者として起動し、[In from AD – User Exchange]のEditを選択する。この際、[YES:既存のルールのコピーを作成し、オリジナルのルールを無効化する][No:既存のルールの変更を続ける]の確認が表示されるので、[はい(Y)]を選択する。
20161210_05 20161210_09

Precedenceに既存と重複せず、元のルールより低い(数値の大きい)値を設定する。(ここでは200とした。)Scoping Filterの項目を開き、プルダウンのISNOTNULLをISNULLに変更する。
20161210_06 20161210_07

もう一度[In from AD – User Exchange]の[Edit]を選択し、今度は[いいえ(N)]を選択してオリジナルのルールを開く。[Disabled]のチェックを外して保存。
20161210_08

なお、既定の構成に手を加える場合は、以下の記事を一読されることをお勧め致します。 Azure AD Connect Sync: 既定の構成を変更するためのベスト プラクティス

DirSyncのAADConnectへのアップグレードが失敗する

ディレクトリ同期ツールをAAD Connectにインプレースアップグレードする際、以下のような画面が出てアップグレードに失敗することがあります。
gw-00003 gw-00004

参照されるログファイルを確認すると、以下のエラーが記録されています。

[11:27:39.819] [ 18] [ERROR] PerformConfigurationPageViewModel: Caught exception while installing synchronization service.
Exception Data (Raw): System.Exception: Synchronization Service をインストールできません。詳細については、イベント ログを参照してください。 ---> System.DirectoryServices.AccountManagement.NoMatchingPrincipalException: Group 'FIMSyncAdmins' was not found.
 場所 Microsoft.Azure.ActiveDirectory.Synchronization.Framework.AccountManagementAdapter.GetGroupBySamAccountName(String groupSamAccountName)

FIMSyncAdminsグループが見つからないというエラーです。確かに、FIMSyncAdminsグループができたのはパスワード同期が実施できるようになった辺りのバージョンなので、ローカルには存在していませんでした。
gw-00006

グループが無いのがエラーの原因と記載されていますので、単純にメンバーは空で良いのでグループを作ってみます。(説明はMIISAdminから適当にコピーしましたが、無くても問題ないです)
gw-00007

これでインストールを行ったところ、問題なく実施ができるようになります。
gw-00009

ちなみに、FIMSyncAdminsグループにはオンプレミスのADとディレクトリ情報をやり取りするアカウント AAD_<nnnnnnnnnnnn>とAAD Connectのインストールに利用したアカウントがデフォルトでメンバーとして登録されます。

また、Microsoftから提示されている標準手順のうち、並列デプロイの方式を利用してもアップグレードは可能ですので、オブジェクトの数や作業の手間などを考えて、どうアップグレードするか決めるといいと思います。

PowerShellから全社員に予定を投入したい

この投稿は PowerShell Advent Calendar 2016 に参加しています。

Facebookでリスクエストを貰ったので、PowerShellから全社員のメールボックスに創立記念日の予定を入れるPowerShellを作ってみたいと思います。

Exchangeでは、各種管理用のPowerShellコマンドレットが用意されておりますが、各ユーザーのメールボックスのアイテムを直接操作するコマンドは基本的には有りません。

ただし、EWS(Exchange Web Services)というAPIが用意されておりますので、そちらを利用する事によりメールボックスにアプローチできます。また、その際にアプリケーション偽装(ApplicationImpersonation)権限を利用する事により、「そのユーザーに成り代わって」そのアイテムを利用できます。

今回は、目的が明確ですので一番近いサンプルスクリプトとして以下のstack overflowに回答例として提示されているスクリプトを元に、作成用のコマンドを作ってみます。

How to import meetings into office365 (EWS and Powershell?)

変更している所は赤字で記載します。

function Create-Appointment
{
    [CmdletBinding()]
    param(
        [Parameter(Position=0, Mandatory=$true)] [string]$MailboxName,
        [Parameter(Position=1, Mandatory=$true)] [string]$Subject,
        [Parameter(Position=2, Mandatory=$true)] [DateTime]$Start,
        [Parameter(Position=3, Mandatory=$true)] [DateTime]$End,
        [Parameter(Position=4, Mandatory=$true)] [AllowEmptyString()] [string]$Location,
        [Parameter(Position=5, Mandatory=$true)] [AllowEmptyString()] [string]$Body,
        [Parameter(Position=6, Mandatory=$true)] [Boolean]$IsAllDayEvent,
        [Parameter(Position=7, Mandatory=$true)] [PSCredential]$Credentials
    )
    Begin
    {
        $EWSDLL = (($(Get-ItemProperty -ErrorAction SilentlyContinue -Path Registry::$(Get-ChildItem -ErrorAction SilentlyContinue -Path 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Exchange\Web Services'|Sort-Object Name -Descending| Select-Object -First 1 -ExpandProperty Name)).'Install Directory') + "Microsoft.Exchange.WebServices.dll")
        if (Test-Path $EWSDLL)
        {
            Import-Module $EWSDLL
        }
        else
        {
            "$(get-date -format yyyyMMddHHmmss):"
            "This script requires the EWS Managed API 1.2 or later."
            "Please download and install the current version of the EWS Managed API from"
            "http://go.microsoft.com/fwlink/?LinkId=255472"
            ""
            "Exiting Script."
            exit
        }

        $ExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP2
        $service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService($ExchangeVersion)
        $creds = New-Object System.Net.NetworkCredential($Credentials.UserName.ToString(),$Credentials.GetNetworkCredential().password.ToString())
        $service.Credentials = $creds
        $Provider=New-Object Microsoft.CSharp.CSharpCodeProvider
        $Compiler=$Provider.CreateCompiler()
        $Params=New-Object System.CodeDom.Compiler.CompilerParameters
        $Params.GenerateExecutable=$False
        $Params.GenerateInMemory=$True
        $Params.IncludeDebugInformation=$False
        $Params.ReferencedAssemblies.Add("System.DLL") | Out-Null
$TASource=@'
  namespace Local.ToolkitExtensions.Net.CertificatePolicy{
    public class TrustAll : System.Net.ICertificatePolicy {
      public TrustAll() { 
      }
      public bool CheckValidationResult(System.Net.ServicePoint sp,
        System.Security.Cryptography.X509Certificates.X509Certificate cert, 
        System.Net.WebRequest req, int problem) {
        return true;
      }
    }
  }
'@ 
        $TAResults=$Provider.CompileAssemblyFromSource($Params,$TASource)
        $TAAssembly=$TAResults.CompiledAssembly
        $TrustAll=$TAAssembly.CreateInstance("Local.ToolkitExtensions.Net.CertificatePolicy.TrustAll")
        [System.Net.ServicePointManager]::CertificatePolicy=$TrustAll
        $service.AutodiscoverUrl($MailboxName,{$true})
        #"Using CAS Server : " + $Service.url
        $service.ImpersonatedUserId = new-object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $MailboxName)
        $folderid= new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Calendar,$MailboxName)
        $Calendar = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)
        $Appointment = New-Object Microsoft.Exchange.WebServices.Data.Appointment -ArgumentList $service
        $Appointment.Start = $Start
        $Appointment.End = $End
        $Appointment.Subject = $Subject
        $Appointment.Location = $Location
        $Appointment.Body = $Body
        $Appointment.IsAllDayEvent = $IsAllDayEvent
        $Appointment.Save($Calendar.Id,[Microsoft.Exchange.WebServices.Data.SendInvitationsMode]::SendToNone)
    }
}
こちらを実行するためには、まず実行するアカウント(ここでは、仮にews_userとします)にApplicationImpersonation権限を付与します。ExchangeにPower Shellで接続し、以下のコマンドレットを実行します。
New-ManagementRoleAssignment –Name:EWSCalendarApplication -Role:ApplicationImpersonation –User:ews_user

続いて、PowerShellを実行するコンピュータにEWS Managed APIをインストールします。

PowerShellを開き、上記コードを実行し、Create-AppointmentのFunctionを登録します。

最後に、以下のコマンドを実行します。最初の行では実行アカウントのID/PASSを入力します。

$LiveCred = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $LiveCred -Authentication Basic -AllowRedirection
Import-PSSession $Session -AllowClobber

$results = Get-Mailbox -RecipientTypeDetails UserMailbox -ResultSize Unlimited | select WindowsEmailAddress

foreach ($result in $results){
    Create-Appointment -MailboxName $result.WindowsEmailAddress -Subject "創立記念日" -Start "2017/07/01" -End "2017/07/01" -Body $null -Location $null -IsAllDayEvent $true -Credential $LiveCred
}

これで、来年の7/1に終日イベントとして[創立記念日]が全ユーザーMBXに作成されます。

 

他にも、これを応用すれば会議室の利用状況を集計したり、役員の今日の予定の印刷用の元データを抜いたりできます。

また、このコマンドを行うには対象となるメールボックスが先に作成されている必要があります。メールボックスはNew-Mailboxコマンドなどで作成した時点では実体は作成されていません。ユーザー自身のログイン以外にも、以下の様な動作を行う事により作成されますので、エラーが出て登録出来ないメールボックスには試してみると良いでしょう。

  1. メールの受信(例えば、メールの開通通知などの名目でテストメールを送る)
  2. 受信トレイルールの作成(管理者がNew-InboxRuleコマンドレットで作成できます。ダミーのルールを作成し、すぐに消せば影響は無いと思います)

Office 365で儲けられるエンジニアとは

この投稿は Office 365 Advent Calendar 2016 に参加しています。

先日開催された第17回Office 365勉強会セッション中においても少しお話をさせて頂いたのですが、Microsoftのパートナーの立場から言うと、既にOffice 365は機能やサービス内容の説明だけでは新規ユーザーがゲットできなくなってきました。(逆に言うと、それだけ導入が進んだ)

普段このblogでは技術的なことばかりを書かせて頂いておりますが、今回は少し趣向を変えて、どうやっていけば、これからもOffice 365でご飯を食べられるエンジニアでいられるのかを書いてみたいと思います。

一言でいうと、

Office 365を通じてお客様のワークスタイルを変え、生産性を向上させ続けられるエンジニア

かなと自分では思っています。ちょっと漠然としていますが、広い意味での「導入支援」ですね。ただ、単に技術的な要件に留まらず、これまでの経緯や周辺領域の動きと合わせて今後Microsoftがどういう方向にこの機能(サービス)を持って行こうとしているのか、どう使ったら生産性が上がると思って設計しているかなどを含め、自分の言葉で語れる人物。

例えば、思いつくままに書いてみますが、お客様への導入の中で出てくる以下の様なことが常に鮮度の高い情報を持って答えられる人かなと思っています。

  • SharePoint/Groups/Exchange/Teams/Yammer/Skype for Businessなど、いっぱい有るけどどうやって使い分ければ良いの?
  • サービスを導入したらインターネット接続環境はどういった物を用意すれば良いの?(帯域、セッション数、冗長性など)
  • サービスに接続するクライアントは何を使えば良いの?シーンによって使い分けるとしたらどういう使い分け?
  • アクセス制御はするべき?するならどこまですれば良い?
  • うちの現在定めているセキュリティポリシーとの整合性はどう取っていけば良い?
  • 監査はどういったことを何処までやれば良いの?事前に利用する社員と合意しておくべき項目はある?
  • BYODを認める場合、その条件や取り交わすべき誓約書など、社内規程の整備はどう進めれば良い?
  • 365日24時間仕事ができるようになってしまうが、業務時間外のメール等の確認に対して労使でどう合意すれば良い?
  • 他の同業他社はどこまでOffice365を使いこなしてどう業務に活かしているの?
  • セキュリティにはどこまでお金をかけてどのレベルまで取り組めば良いの?
  • 社内で自立的に対応していけるようにする運用体制はどう作っていったら良い?

書いていてなんですが、自分も全然できていないので、もう少しアンテナ高くして頑張って精進していきたいです。

第17回Office 365勉強会に登壇します

今週の土曜日に品川の日本Microsoftで開催される第17回Office 365勉強会に登壇させて頂きます。

今回は、既に導入がかなり進んでいるということもあって、なかなか改めて話題に上がることも少ないExchange Onlineにスポットを当ててみようということで、Exchange Online特集になっております。

私のセッションでは、
「意外と知らない最近のExchange Online」
ということで、ここ数年で追加された、もしくは追加予定のExchange Onlineの新機能や仕様変更についてお話ししたいと思います。

お時間のある方は是非ご参加頂けると幸いです。

Microsoft MVPを再受賞しました

おかげさまで、MicrosoftのMVPアワードをOffice Servers and Servicesの分野で受賞しました。
2012年にOffice 365で初受賞して以来、5年連続での受賞となります。

これも偏にblogやコミュニティ運営などでご協力を頂いている皆さまの応援のおかげと感謝しております。

これからもよろしくお願い致します。

MVP_Logo_Horizontal_Secondary_Blue286_RGB_300ppi

Exchange 2013/2016の更新失敗時の対応

Exchange Server 2013 / 2016の累積更新プログラム(CU)を初めとする更新プログラムの適用においては、インストール開始時にExchange関連のサービスが停止されるのみならず、自動起動の状態が「無効」として設定されます。
20160719_01

これにより、インストール中に故障が発生してOS再起動した場合などにおいても、更新が中途半端になされた状態でExchange Serverが立ち上がって全体の動作に悪影響を及ぼすなどの事が無いように設計されております。

反面、これも万能ではなく、意図せずサービスが無効化された状態のままインストーラーが終了(しかも再開ができない)してしまうケースが比較的に多く存在します。再現性は無いのですが、以下私が遭遇したケースです。

  • インストーラーが異常終了してしまった
  • 途中でハードウェア障害でOSが再起動した
  • 厳密な名前の検証を無効化せずに中間更新プログラム(IU)を適用した
  • SCCM経由で他の更新プログラムと一緒にExchangeの更新プログラムをインストールした

正常に動作しているサーバーのサービスの状態と見比べながら戻すのが一番単純な方法ですが、特に時間に追われているメンテナンス作業などの場合は途方に暮れることになってしまいます。

こうしたケースにおいて覚えておいた方が良いコマンドがあるので紹介します。

① PowerShellを管理者モードで開く
② インストールディレクトリのBin(C:\Program Files\Microsoft\Exchange Server\V15\Bin)に移動
③ .\ServiceControl.ps1 AfterPatch

更新プログラム適用の処理において、実際にはどういった処理がされているかは C:\ExchangeSetupLogs\ExchangeSetup.log にも詳細が記録されておりますので、そちらを参考にしても良いかと思います。

Exchange2013のマルウェア対策をProxy経由で更新

インターネットへの直接接続が無い環境でのExchange 2013組み込みのマルウェア対策のパターンファイル更新についてメモ。

Exchange Server 2010の頃のFPE(Forefront Protection for Exchange)はGUIで設定できる項目があったのですが、Exchange Server 2013では標準に組み込まれて、Exchange管理シェル(EMS)からも設定することができません。

winhttpで設定することもできるのですが、意外とBypass-listを書くのが面倒だったりするので、FPEの頃のようにパターンファイル更新のみ特定のProxyサーバ経由で実行するように設定できます。

  1. http://forefrontdl.microsoft.com/server/scanengineupdate に対して、認証なしで接続できるようにProxyサーバを設定
  2. PowerShellを管理者として開いて以下のコマンドを実行する
Add-PSSnapin Microsoft.Forefront.Filtering.Management.PowerShell
Set-ProxySettings -Enabled $true -Server [ProxyサーバのIP] -Port [Proxyサーバのポート]

しばらく待てば更新が開始されます。即時で実行したい場合は、以下のコマンドで。

cd 'c:\Program Files\Microsoft\Exchange Server\v15\scripts\'
.\Update-MalwareFilteringServer.ps1 -Identity [対象のExchangeサーバのFQDN]

ExpressRoute for Office365の期待とギャップ

先日、Microsoftより以下のようなメッセージが示されました。

Azure ExpressRoute is not required or recommended for Office 365 except where mandated to use direct networking for regulatory purposes or where a network assessment for Skype for Business connectivity requires it

また、先日のde:codeのイベントのExpressRoute for Office 365関連の講演においても、しきりに「ExpressRouteはセキュリティ向上のためのソリューションではありません」というメッセージを出しており、少し自分的に違和感を覚えておりました。

今回はExpressRoute for Office 365と聴いてイメージする物と、実際のサービス導入後の構成のギャップについて少し整理したいと思います。

まず、標準のOffice 365の構成が下図の左側だとします。ExpressRouteでOffice 365に直接接続出来るようになると聴くと、何となく以下の問題が解決されるように思えます。(右側のイメージ)

  1. インターネット上に機密情報を置くことへの不安
  2. インターネットアクセスが急増することによる回線、NW機器やProxyサーバーなどのパフォーマンスの不安
  3. インターネットアクセスのログのモニタリングやOffice365側のURL/IPアドレスの増減に対応する運用負荷に関する不安

20160601_01

確かにExpressRoute for Office 365を入れると、いくつかの問題点は解消されるのですが、実際にはいくつかの点でギャップが発生します。

簡単に纏めると以下の図上の3点になると思います。

20160601_02まず、ExpressRoute for Office 365を利用しても、主にCDNから配信されてくるデータはインターネット経由でしか取得できないため、①ExpressRouteの他にもインターネット接続を必要とする という点がございます。これにより、インターネット接続経由でOffice 365の一部の通信は継続するため、その運用管理負荷は無くなりません。

また、ExpressRoute経由で接続するのはテナントではなくIPアドレス単位になる為、②他社テナントにもExpressRouteを経由して接続できてしまいます。構成によっては、自社の管理下にあるFirewallやProxyなどをバイパスして外部のクラウドに接続できてしまうことになります。

更に、ExpressRouteを契約しても接続元IPの制限ができるようになる訳では無いので、③ExpressRouteを経由しないインターネットからもこれまで通り利用できてしまいます。

 

勿論、②はSharePoint OnlineであればテナントごとにURL空間が異なるので、そこを意識して.pacファイルで制御するなどすれば、ある程度は制御できると思いますし、③はAD FSを入れれてクラウドIDの利用を制限すれば社外からの認証を抑制することもできます。

ただ、こう言ったFit & Gapを整理していくと、Azureとは違ってOffice 365にExpressRoute接続すべき(したい)シーンというのは、かなり限定されるのではと個人的に感じます。

【登壇情報】6/25 Cloud Samurai 2016

6/25(土)に日本Microsoft品川本社で行われるInteract x Cloud Samurai 2016 Summerに登壇させて頂く事になりました。

タイトルは【オンプレミス x Exchange Server 2016 という選択肢】ということで、Exchange Onlineではなくサーバ製品であるExchange Server 2016について話をさせて頂きたいと思います。

Microsoft_Exchange_2016[1]

Exchange Serverってそれなりにまだ出ているみたいだけど、普段なかなか勉強会で話を聴く機会がないよね…って話がありまして、誰も喋らないのであればじゃあ私が、ということで枠を頂きました。

内容としてはまだこれから考えていくのですが、なるべく具体的に、実際に役に立つ内容となるようにしたいと思ってます。今考えてる(というか、自分が聴きたい内容なのですが)トピックは、以下の感じです。全部喋れるかわかりませんが…。こういった事が聴きたいとかのリクエストもあれば是非御連絡下さい。

  • Exchange Onlineとはどういった違いがあるの?
  • 実際作るとどういったH/W構成になるの?
  • 構築や運用で気をつけるべき所とかあるの?
  • 価格はどれくらい?
  • 2010とか2013とどう違うの?

お時間が許すようであればご参加頂ければ幸いです。