クライアントアクセスルールによるIP制限

今までと同じポリシーで利用したいということで、Exchange Online で IP アドレス制限を掛けたいという話は良く聞きます。これまでは、AD FSを利用したクレームルールを構成するか、Azure AD Premiumの条件付きアクセスの機能を利用する、あるいはサードパーティのツールを利用するなどして制御するしかありませんでした。

いずれも新規でサーバを立てるなり、追加でライセンスを購入するということでコストの掛かるソリューションでしたが、Exchange Onlineに実装された(現在、まだ全てのテナントで利用可能ではありませんが)クライアントアクセスルールを利用する事により、標準機能としてこれを実装できるようになりました。

Exchange Online のクライアント アクセス規則

また、この機能は現在 AD FS などを利用してIPアドレス制限を掛けている環境においても、その不足する部分を補完する存在になり得ますので、是非この機能は注目して頂ければと思います。

Continue reading

ドメインとAzureADテナントの紐づけを調べる

今回はちょっとトリッキーなTipsです。

色々なテナントをテストで利用していて、ふと「あれ、この独自ドメイン紐づけていたのどのテナントだっけ」となったり、「あの会社確かOffice 365使っていると言っていたけどテナント(xxx.onmicrosoft.com)どこだろう」…と調べたくなることがあると思います。

こういったときには、Exchangeの管理シェルからGet-FederationInformationコマンドで調べられます。Exchange Onlineに接続し、以下のコマンドを実行してみます。

[PS] C:\>(Get-FederationInformation -DomainName mirogo-shoji.com -BypassAdditionalDomainValidation).DomainNames

Domain
------
mirogo.onmicrosoft.com
mirogo-shoji.com

この例では、mirogo-shoji.com のドメインが紐づけられているテナントは mirogo.onmicrosoft.com だということが分かります。逆の場合(特定の xxx.onmicrosoft.com に紐づけられているのはどんな独自ドメインか)も同様のコマンドで調べられます。

なお、この例では Autodiscover のDNSをきちんとOffice 365用に設定していないと調べられません。

その場合は、ちょっと面倒ですが、Exchange Server(バージョンはいくつでも良いです)を1台立てて、そのサーバ上のHostsファイルに autodiscover.[調べたいドメイン名] を autodiscover.outlook.com のどれかのIP(例えば40.100.154.56)に向けるように設定して、コマンドを実行すれば大丈夫です。

Office 365プロダクトのサービス一覧を調べる

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

Office 365ですが、どんどん日々進化しておりE3やE5のSuiteに含まれるサービスも増えていっています。また、今年はMicrosoft 365など、更なるバンドルライセンスも増えてきました。

6年以上前にblogのエントリーを書いた際と比較すると、例えばOffice 365 E3に含まれるパッケージは以下の様にサービス数でいうと3倍以上になりました。

今回は、現時点(2017.12.03)での各ライセンスとそれに含まれるサービスを調査してみました。

調査方法は、ライセンスプラン(SKUとも呼ばれます)と、それに含まれるライセンスプランをGet-MsolAccountコマンドレットを使って調査しました。また、対応する名前は管理者ポータルから確認しています。

結果、以下のリストの通りの出力となりました。

プラン一覧(50個/CSV)Download 2017/12/03更新
サービス一覧(85個/CSV)Download 2017/12/03更新

詳細は以下の通りです。

Continue reading

第18回 Office365勉強会が開催されます

3/11(土) 13:00より、飯田橋のIIJセミナールームをお借りして第18回のOffice 365勉強会が開催されます。

今回のテーマは ”Identity&Security” Office 365から広がるクラウドの世界とそのセキュリティ対策 ということで、私も話を是非聴きたいと思っていた著名なスピーカーの方々をお招きしてOffice 365とそれを取り巻くセキュリティ関連の最新情報をお話しして頂く予定となっております。

既に満席になっている可能性はありますが、毎回一定数のキャンセルは発生しますので、是非キャンセル待ちに登録を頂ければと思います。

詳細は こちら をご参照下さい。

 

AAD ConnectでExchange属性が同期されない(その2)

先日の記事を投稿したところ、友人より「GUIだと手順が面倒だし、美しくない」と優しいコメントを頂きましたので、PowerShellで書き直してみました。

これだと既存のコネクタが一時的にDisableになったりしませんし、後から自分で追加したカスタムルールということが明示できるので今後のソフトウェアのアップデートなどの際に分かりやすいかもしれません。

※こちらのスクリプトはExchangeスキーマを拡張していない環境では実施しないで下さい(参照先のルールが存在しませんので)。また、マルチドメイン環境には対応していません。

# Get Connector ID
$conID = (Get-ADSyncConnector | ? {$_.Type -eq "AD"} | select -first 1).Identifier.Guid

New-ADSyncRule `
  -Name 'Custom rule from AD(Exchange)' `
  -Description 'User object with Exchange schema in Active Directory. (without mailNickname)' `
  -Direction 'Inbound' `
  -Precedence 200 `
  -SourceObjectType 'user' `
  -TargetObjectType 'person' `
  -Connector $conID `
  -LinkType 'Join' `
  -SoftDeleteExpiryInterval 0 `
  -ImmutableTag 'Custom rule from AD(Exchange)' `
  -OutVariable syncRule

# Get attribute flow mapping from existing rule "In from AD - User Exchange"
$AttributeFlowMappings = (Get-ADSyncRule | ? {$_.Name -eq "In from AD - User Exchange"}).AttributeFlowMappings
foreach ($mapping in $AttributeFlowMappings){
  Add-ADSyncAttributeFlowMapping -SynchronizationRule $syncRule[0] $mapping
}

New-Object `
  -TypeName 'Microsoft.IdentityManagement.PowerShell.ObjectModel.ScopeCondition' `
  -ArgumentList 'mailNickname','','ISNULL' `
  -OutVariable condition

Add-ADSyncScopeConditionGroup `
  -SynchronizationRule $syncRule[0] `
  -ScopeConditions @($condition[0]) `
  -OutVariable syncRule

Add-ADSyncRule -SynchronizationRule $syncRule[0]

 

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

前回の投稿では、古いバージョンのディレクトリ同期ツールからAAD Connectへのアップグレードの際にエラーが出ないようにする手順について紹介させて頂きました。

しかしながら、気づかずにこちらを実施せずアップグレードをしてしまうと、結構悲惨な状態になります。[問題が発生したため、統合を完了できません – Syncronization Serviceをインストールできません。詳細については、イベントログを参照して下さい。]と表示され、アップグレードが失敗します。

ログを確認すると、

[21:38:17.249] [ 12] [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)
   場所 Microsoft.Azure.ActiveDirectory.Synchronization.Setup.SynchronizationServiceSetupTask.<>c__DisplayClass9.<ValidateOrCreateSyncServiceGroups>b__8()
   場所 Microsoft.Azure.ActiveDirectory.Synchronization.Framework.ActionExecutor.Execute(Action action, String description)
   場所 Microsoft.Azure.ActiveDirectory.Synchronization.Setup.SynchronizationServiceSetupTask.InstallCore(String logFilePath, String logFileSuffix)
   場所 Microsoft.Azure.ActiveDirectory.Synchronization.Framework.ActionExecutor.ExecuteWithSetupResultsStatus(SetupAction action, String description, String logFileName, String logFileSuffix)
   場所 Microsoft.Azure.ActiveDirectory.Synchronization.Setup.SetupBase.Install()
   --- 内部例外スタック トレースの終わり ---
   場所 Microsoft.Azure.ActiveDirectory.Synchronization.Setup.SetupBase.ThrowSetupTaskFailureException(String exceptionFormatString, String taskName, Exception innerException)
   場所 Microsoft.Azure.ActiveDirectory.Synchronization.Setup.SetupBase.Install()
   場所 Microsoft.Online.Deployment.OneADWizard.Providers.EngineSetupProvider.SetupSyncEngine(String setupFilesPath, String installationPath, String sqlServerName, String sqlInstanceName, String serviceAccountName, String serviceAccountDomain, String serviceAccountPassword, String groupAdmins, String groupBrowse, String groupOperators, String groupPasswordSet, Int32 numberOfServiceInstances, ProgressChangedEventHandler progressChanged, NetworkCredential& serviceAccountCredential, SecurityIdentifier& serviceAccountSid)
   場所 Microsoft.Online.Deployment.OneADWizard.Runtime.Stages.InstallSyncEngineStage.ExecuteInstallCore(ISyncEngineInstallContext syncEngineInstallContext, ProgressChangedEventHandler progressChangesEventHandler)
   場所 Microsoft.Online.Deployment.OneADWizard.Runtime.Stages.InstallSyncEngineStage.ExecuteInstall(ISyncEngineInstallContext syncEngineInstallContext, ProgressChangedEventHandler progressChangesEventHandler)
   場所 Microsoft.Online.Deployment.OneADWizard.UI.WizardPages.PerformConfigurationPageViewModel.ExecuteSyncEngineInstallCore(AADConnectResult& result)

と表示されており、FIMSyncAdminsグループが存在しない為に発生したエラーだということが推測されます。

しかしながら、FIMSyncAdminsグループを作成後に[再試行]をクリックしても、[指定されたファイルが見つかりません。]というエラーが表示されて、続行できません。参照されたログファイルを見ても、続きを実施する方法は分かりません。

しかも都合の悪いことに、前のバージョンのディレクトリ同期は既にアンインストールされており、切り戻しもできません。再度インストーラーを走らせると新規インストールになってしまいます。

全てデフォルト設定で利用していた場合はそれで良いかもしれませんが、同期フィルタなどを設定していた場合はどんな設定をしただろう…?って途方に暮れてしまうこともあるかと思います。

根気強くログファイルを見ていくと、見つけました!

[21:27:25.520] [ 10] [INFO ] AnalyzeDirSyncInstallation: Backing up DirSync upgrade settings to C:\Users\syncadm\AppData\Local\AADConnect\DirSyncSettings20161214-212725.xml.

どうやら、Appdata\Local\AADConnect配下に作業ファイルとして古い設定データがxmlで保存されているようです。(syncadmはAAD Connectのインストールを実行したユーザー名ですので、皆さんの環境に合わせて読み替えて下さい)

※OUの除外設定などもきちんと残っています。

これさえ分かれば、後は並列デプロイと同じ方式で移行を継続できます。

PS C:\> cd "C:\Program Files\Microsoft Azure Active Directory Connect\"
PS C:\Program Files\Microsoft Azure Active Directory Connect> .\AzureADConnect.exe /migrate

設定ファイルをインポートする画面が出ますので、先ほどのフォルダ配下の.xmlファイルを指定します。また、[既存のサービスアカウントを使用する]のチェックボックスを外して[次へ]を選択します。
 

ここから先は通常のアップグレードと同じです。Azure ADの管理者アカウントの情報を入力し、次にオンプレミスのActive DirectoryのEnterprise Adminsのアカウント情報を入力し、最後に[インストール]を実施します。

これでインストールは完了です。インストール後の状態は、ステージングモードというエクスポートのみ行わない状態になっています。

MIISClientなどで既存のフィルタがきちんと移行されているかを確認(新しいMIISClientのパスはC:\Program Files\Microsoft Azure AD Sync\UIShell\miisclient.exeです。実行には一度ログオフが必要です)した後に、ステージングモードを解除します。

Azure AD Connectを起動し、[構成][ステージングモードの構成][次へ]を選択。Azure ADの管理者情報を入力、[ステージングモードを有効にする]のチェックボックスを外して[次へ]をクリックし、最後に[構成]をクリックします。
 

これで、無事AAD Connectの環境に移行できました。

良いAADライフを!

AAD Connect更新時のSfB属性

AAD ConnectでExchange属性が同期されない の記事でオンプレミスのExchange関連のスキーマについて記載させて頂いた所、Skype for Business(Lync)関連のスキーマについてはどうなのかと質問を頂きましたので、簡単に調べた範囲で記載したいと思います。

オンプレミスのADスキーマがSkype for Business(Lync)用の拡張がされていた場合、以下の3つの同期ルールが作成されます。

・In from AD – User Lync
対象:user
以下の属性を同期する:
msRTCSIP-ApplicationOptions
msRTCSIP-DeploymentLocator
msRTCSIP-Line
msRTCSIP-OrganatorSid
msRTCSIP-OwnerUrn
msRTCSIP-PrimaryUserAddress
msRTCSIP-UserEnabled
msRTCSIP-OptionFlags

・In from AD – InetOrgPerson Lync
対象:inetOrgPerson
以下の属性を同期する:
msRTCSIP-ApplicationOptions
msRTCSIP-DeploymentLocator
msRTCSIP-Line
msRTCSIP-OwnerUrn
msRTCSIP-PrimaryUserAddress
msRTCSIP-UserEnabled
msRTCSIP-OptionFlags

・In from AD – Contact Lync
対象:contact
以下の属性を同期する:
msRTCSIP-DeploymentLocator
msRTCSIP-Line
msRTCSIP-PrimaryUserAddress
msRTCSIP-OptionFlags

20161214_01

msRTCSIP-OrganatorSid 以外の属性では、既存のディレクトリ同期ツールにおいては無条件で(存在する場合)同期されていました。

msRTCSIP-OrganatorSid については、リソースフォレストモデルでの展開の際に利用されるものですので、AAD Connectから新規で追加された同期ルールになります。

従いまして、Exchangeの様に特に同期する対象を限定するスコープなど設定されていないため、アップグレード前後で同期属性が変化することは、Skype for Business Serverをリソースフォレストモデルで展開していない限りはないと言えます。

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コマンドレットで作成できます。ダミーのルールを作成し、すぐに消せば影響は無いと思います)