SuccessFactorsやWorkdayからオンプレActive Directoryへプロビジョニングすると、退職者やinactiveが「SkipReason: NotEffectivelyEntitled」で同期されず悩むことがあります。本記事ではフル同期と増分同期の設計差、毎晩Full再起動の落とし穴、退職者も含めて同期したい場合の別ジョブ構成、期限削除の現実的な運用まで具体的に整理します。
起きていることを一言で言うと:ログの表示が「割り当て不足」に見えてしまう
Microsoft Entra ID(旧Azure AD)のプロビジョニング ログで SkipReason: NotEffectivelyEntitled が出ると、つい「アプリに割り当てられていないから同期されないのでは?」と疑いがちです。ところが、HR起点(SAP SuccessFactors→Active Directory、Workday→Active Directory)のシナリオでは、“アプリ割り当て”が原因ではないケースが多く、このメッセージが誤解を生みやすいのがポイントです。
実際、運用現場ではこのスキップ理由が「対象外(スコープ外)」「非アクティブは設計上処理しない」「差分検知の前提が崩れている」など、複数の背景をまとめて“それっぽく”表示してしまうことがあります。表示自体が誤解を招きやすいため、将来的に改善予定だと案内されることもあります(表示のまま原因断定しないのが安全です)。
| よくある解釈 | 実際に多い原因 | まず見るべきポイント |
|---|---|---|
| アプリに割り当てていない | HR起点では割り当て連動でない場合がある | スコープ フィルターと「フル/増分」の運用 |
| ユーザーが削除された/存在しない | 退職・inactiveがフル同期で設計上スキップ | 退職の反映が「増分同期の変化検知」になっているか |
| 設定を少し変えれば直りそう | 根本は“設計の前提”(ベースライン vs 差分) | フル同期を頻繁に回していないか、ジョブが差分運用できているか |
そして厄介なのが、次のような“対処のつもりの変更”を入れた直後から、退職者(SuccessFactors側で inactive / terminated)や、future hire・休職などの inactive 扱いユーザーが同期対象から外れ、オンデマンドでもスキップされ続けるパターンです。
SkipOutOfScopeDeletionsをtrueに変更した- 「最新の有効な雇用レコードを取得する」スキーマ変更を入れた
- 毎晩
Fullパラメーター付きで同期ジョブを再起動している(毎晩フル同期)
結論から言うと、退職者の反映をフル同期でやろうとしていることが“設計とのズレ”になっている可能性が高いです。
フル同期と増分同期:役割が違うので「退職者の扱い」も違う
まず押さえるべきは、プロビジョニングのフル同期と増分同期は目的が異なるという点です。特に HR 起点では、フル同期は「今、管理すべきアクティブ従業員の基準線(ベースライン)を作る」色合いが強く、過去退職者まで大量に処理しない設計になっていることがあります。
| 観点 | フル同期(Full / 初回ベースライン) | 増分同期(Incremental) |
|---|---|---|
| 目的 | 現時点の“管理対象”の全体像を作る(基準線の作成) | 前回以降の変更だけを追従する(差分の反映) |
| 退職者・Inactiveの扱い | 設計上スキップされることがある(作成/更新対象にしない) | Active 1→0 の変化など、状態変化を検知して無効化等を実施 |
| 負荷・時間 | 大きい(母集団が大きいほど時間も増える) | 小さい(通常運用はこっちが主) |
| 実務での使いどころ | 初回導入、スコープ大変更、マッピング大改修の直後など | 日々の運用(退職・異動・属性変更の追従) |
ここで重要なのが、退職の反映(無効化・属性更新など)は「増分同期の変更検知」に依存する設計になっている点です。つまり、退職者を“作り直す”のではなく、「アクティブだった人が退職した」という変化を拾って処理します。
毎晩Fullで再起動すると、なぜ退職者が永遠にスキップされるのか
毎晩 Full を付けて同期ジョブを再起動すると、実質的に「毎晩、初回ベースラインを作り直す」状態になります。このとき、フル同期が inactive / terminated を設計上スキップする仕様だと、退職者は毎回スキップされ続けます。
| タイミング | 期待していること | 実際に起きがちなこと | ログに出やすいもの |
|---|---|---|---|
| 退職発生(SF側でActiveが0相当へ) | AD側でアカウント無効化・OU移動など | 増分同期が拾えば反映される | (拾えば)Update/Disable系のイベント |
| その夜にFull再起動 | 退職者の状態が反映される | フル同期が退職者を“対象外”としてスキップ | SkipReason: NotEffectivelyEntitled など |
| 翌日以降も毎晩Full | いつかは反映されるはず | 毎回ベースライン扱いになり、永遠にスキップ | 同じスキップが繰り返される |
この状態では、アプリの「割り当て必須」を NO にしても、Graph の secrets で SyncAll:false が見えても、根本がフル同期の設計差にあるため改善しないことがあります。特に HR 起点では、対象判定が「割り当て」ではなく「スコープ フィルターとソースデータ」になっていることが多い点が落とし穴です。
SkipOutOfScopeDeletions と SyncAll の位置づけを整理する
設定値の意味が曖昧なまま変更すると、かえって切り分けが難しくなります。ここでは“よく聞かれる2つ”を、期待しがちな効果と実際の影響に分けて整理します。
| 設定 | 期待しがちな効果 | 実際に影響しやすい領域 | 今回の症状(退職者がNotEffectivelyEntitledでスキップ)への効き方 |
|---|---|---|---|
SkipOutOfScopeDeletions | スキップが減る/退職者が処理される | スコープ外になったオブジェクトの削除・解除の扱い | 退職者を“積極的に処理する”スイッチではないため、直結しにくい |
SyncAll | 割り当てなしでも全員同期される | コネクタ実装によって意味が異なる(割り当て連動の有無) | HR起点で割り当て非連動なら、値を変えても改善しない可能性がある |
ここまでの整理を踏まえると、今回のように「毎晩Full再起動」を行っている場合、まず疑うべきは “退職の反映をフル同期で期待してしまっている” という運用設計です。
推奨アクション:退職者をフル同期で処理しようとしない
運用としての第一優先は、“毎晩Full再起動”を止めて、増分同期が継続して走る状態に戻すことです。フル同期は便利ですが、HR起点では「退職者を含めた全員のライフサイクル」を毎回再計算する用途に向きません。
運用の目安(現場で事故が少ない考え方)
- 初回導入:フル同期でベースラインを作る → 以降は増分同期で運用
- マッピング大改修:影響範囲を見極め、必要な場合のみフル同期(ただし退職者はスキップされ得る前提)
- 日々の退職/異動:増分同期に任せる(退職の反映は“状態変化”として拾わせる)
ポイント:「退職者が反映されない」問題に対してフル同期を頻繁に回すのは、火消しどころか“延焼”になりやすいです。退職処理は増分同期が拾う設計であることを前提に、まずは増分同期が正しく動いているかを確認します。
それでも増分同期で退職が反映されない場合の切り分け
増分同期に戻したのに退職が反映されない場合は、仕様だけでなく設定・データ・検知条件のいずれかにズレがある可能性があります。ここでは「明日から調べられる」粒度で、確認ポイントを整理します。
| 確認項目 | 見る場所 | 判断の目安 | よくある落とし穴 |
|---|---|---|---|
| ユーザーがスコープ内か | アプリのスコープ フィルター/条件 | 退職前は含まれ、退職後の扱いが想定どおりか | 「最新の有効な雇用レコード取得」の変更で、想定外に条件が外れる |
| 退職の判定に使う属性 | マッピング(例:activeEmploymentsCount、emplStatus 等) | Active 1→0 が検知できる設計になっているか | 属性が “null/空” になり、式が想定外の分岐をする |
accountDisabled の式 | AD属性マッピング | 退職時に True へ変わるか(式が逆転していないか) | 式を削除/上書きしてしまい、無効化が発火しない |
| 増分同期のウォーターマーク | 同期ジョブの状態/最終実行時刻 | 定期的に成功しているか、失敗で止まっていないか | Full再起動を繰り返して差分検知が成立しない |
| オンデマンド実行のログ | Provision on-demand | 入力データ(ソース属性)が退職状態になっているか | オンデマンドは「今の状態」を見に行くため、変化検知の代替にはならない |
特に見落としがちなのが、オンデマンド実行の位置づけです。オンデマンドは便利ですが「増分同期が拾うはずだった変化」を必ず再現できるわけではありません。退職の反映は“変化のタイミング”に依存する設計の場合、オンデマンドで現状を見てもスキップされることがあります。
ここまで確認しても挙動が合わない場合は、サポート ケースでの調査が現実的です。HR側データの揺れ(雇用レコードの複数存在、未来日付、復職など)と、コネクタ側の検知条件が噛み合っていないケースは、ログだけでは判断しにくいからです。
「退職者も全員同期したい」要件は、設定の小手先ではなく“ジョブ分割”が近道
退職後に AD 上で OU を移す運用や、数年後に SuccessFactors 側で匿名化される要件があると、退職者も含めて“全員”をプロビジョニング対象にしたくなります。しかし、SkipOutOfScopeDeletions や SyncAll といったパラメーター変更は、この要件に直結しないことが多いです。
SkipOutOfScopeDeletionsは「スコープ外になったオブジェクトを削除(または解除)するか」の振る舞いに関係しやすく、退職者を“積極的に処理する”スイッチではありません。SyncAllが見えても、HR起点での対象判定が「アプリ割り当て」ではないなら、これを変えても退職者問題に効かない可能性があります。
実務的に筋が良い回避策は、退職者専用のプロビジョニング ジョブを別に作る設計です。アクティブ従業員向けのジョブは“通常の人事運用”に最適化し、退職者は“退職者専用のルール”で扱います。
SuccessFactors→Active Directory:退職者専用ジョブの作り方(要点)
ここからは、退職者を「同期対象に含める」「退職後にOU移動させる」「将来の匿名化に追従する」といった要件を想定し、退職者専用ジョブの作り方を具体的にまとめます。名称や属性名は環境により異なるため、考え方と手順を押さえてください。
全体像:ジョブを2つに分ける
| ジョブ | 対象 | 主な目的 | 想定スコープ フィルター例 |
|---|---|---|---|
| 通常ジョブ(例:SF2AD-Active-Users) | 在籍・アクティブ | 入社・異動・属性変更を安定追従 | activeEmploymentsCount GREATER_THAN 0 |
| 退職者ジョブ(例:SF2AD-Terminated-Users) | 退職・Inactive | 無効化、OU移動、匿名化など退職後運用の追従 | activeEmploymentsFlag EQUALS 0 |
手順
- 退職者専用ジョブを新規作成
例:SF2AD-Terminated-Usersのように、目的が一目で分かる命名にします。 - 既定の
accountDisabledマッピングを一度外す
多くのテンプレートではactiveEmploymentsCountを使ってaccountDisabledを制御しています。退職者専用ジョブでは、このロジックを“退職者向けに”作り直す前提で、一度削除(または無効化)します。 - Advanced で SuccessFactors 属性リストを編集し、
activeEmploymentsCountを別名にリネーム
例:activeEmploymentsCount→activeEmploymentsFlag
ここでの意図は、「JSONPath(データの取り方)」は維持しつつ、後続のマッピングやフィルターで意味を分けて扱えるようにすることです(JSONPath自体を変えるのではなく“名前だけ”変えるイメージです)。 accountDisabledをactiveEmploymentsFlagベースで再マッピング
例:activeEmploymentsFlagが 0 ならaccountDisabledを True(無効化)にする、など。
在籍者ジョブと退職者ジョブで、同じ概念の属性を別の意図で使う場合は、式が衝突しないように注意します。- スコープ フィルターを「退職者のみ」にする
例:activeEmploymentsFlag EQUALS 0
退職者専用ジョブは“退職者だけ”に限定します。通常ジョブと対象が被ると、同じユーザーを2つのジョブが奪い合い、想定外の更新が起きやすくなります。 parentDistinguishedNameのマッピングで退職後にOU移動
退職者をOU=Terminated,DC=example,DC=localのような退職者OUに集約すると、権限・GPO・棚卸し・削除判定が一気に楽になります。
OU移動の式は「部門・会社コード・退職理由」など運用に合わせて分岐させても良いですが、最初は単純化をおすすめします。- Provision on-demand でテストし、ログで意図どおりか確認
“退職者”のテストユーザーで、無効化・OU移動・属性更新(匿名化用の属性含む)が想定どおりかを確認します。
退職者ジョブでよく入れるマッピング例
| 目的 | AD側の代表的な属性 | 例 | 注意点 |
|---|---|---|---|
| 無効化 | accountDisabled | 退職なら True | 通常ジョブの式と衝突しないように |
| OU移動 | parentDistinguishedName | 退職者OUへ固定または条件分岐 | OU権限(作成/移動)が不足すると失敗しやすい |
| 将来の匿名化追従 | 拡張属性(例:extensionAttribute など) | 匿名化後に空になる属性を別属性へ退避 | 匿名化で“識別子が消える”前に、AD側のキー設計を確認 |
2ジョブ運用を成功させるための設計ポイント
退職者専用ジョブは強力ですが、設計を雑にすると「同一ユーザーを2ジョブで更新」「OUが行ったり来たり」「片方で無効化、片方で有効化」などの事故が起きます。以下のポイントは最初に押さえておくと、後からの手戻りが減ります。
- スコープを絶対に重ねない:在籍者ジョブは在籍者だけ、退職者ジョブは退職者だけ。例外を作らない。
- 同じ属性を両方で書き換えない:どうしても必要なら、どちらが最終的に勝つか(更新順)を運用で固定する。
- 退職者OUに集約する:削除や棚卸しの後工程が劇的に簡単になる。
- 匿名化を見越した「キー」設計:将来、HR側の姓名・メールが変わっても同一人物として追跡できる属性(従業員番号など)をAD側に保持する。
Workday→ADで future hire / 休職が同期されない場合も、考え方は同じ
Workday→Active Directory でも、future hire や休職などが「inactive 扱い」になり、NotEffectivelyEntitled でスキップされることがあります。一方、Workday→Azure AD(Workday→Entra ID)では同じユーザーが同期できるなど、挙動差が見えるケースもあります。
この場合も、根っこは「その連携が何を“管理対象”とみなすか」にあります。Workday→AD のテンプレートや実装が“現役社員のID配布”に寄っているなら、inactive(future hireを含む)をスキップするのは筋が通ります。
運用要件として future hire もADに作りたい場合は、SuccessFactors と同様にfuture hire 専用のジョブ(またはスコープ)を設け、OUや属性を分けて管理するのが安全です。Workday 側の状態遷移(future→active など)が増分同期でどう検知されるかは環境差が出やすいため、ログとデータを合わせて確認し、必要ならサポートで仕様確認を行うのが確実です。
「退職後○日で削除したい」「スコープ変更で退職者が復活する」への現実的アプローチ
退職後 7日・14日といった期限でADから削除したい要件はよくあります。しかし、プロビジョニングのスコープ フィルターは“相対日付(今からn日)”の計算ができない、または制限が多いことがあります。utcNow() のような現在日時参照ができない場合、フィルターだけで「退職後14日経過」を表現するのは難しいです。
期限削除は「プロビジョニング外」に出すと運用が安定する
厳密な期限管理が必要なら、次のように責務を分離すると事故が減ります。
- プロビジョニング:退職時点で無効化・退職者OUへ移動・退職日を属性へ書き込む
- 期限削除(別仕組み):AD側の定期ジョブ(PowerShell / Runbook / タスクスケジューラ)で退職日+n日を判定し、削除またはアーカイブ
例えば「退職日」を AD の拡張属性(例:extensionAttribute1)に YYYY-MM-DD で保存しておけば、AD側のジョブで日付計算ができます。
PowerShellによる期限削除の例(安全に試すためのWhatIf付き)
以下は考え方の例です。実運用では必ずテストOUで検証し、監査ログやバックアップ方針も含めて設計してください。
Import-Module ActiveDirectory
$targetOu = "OU=Terminated,DC=example,DC=local"
$retentionDays = 14
# 例:extensionAttribute1 に "2025-12-01" の形式で退職日が入っている想定
Get-ADUser -SearchBase $targetOu -Filter * -Properties extensionAttribute1 |
Where-Object {
$_.extensionAttribute1 -match '^\d{4}-\d{2}-\d{2}$' -and
([datetime]::ParseExact($_.extensionAttribute1, 'yyyy-MM-dd', $null)).AddDays($retentionDays) -lt (Get-Date)
} |
ForEach-Object {
# まずは削除ではなく確認(-WhatIf)から
Remove-ADUser -Identity $_ -Confirm:$false -WhatIf
}
いきなり削除が怖い場合は、まずは「別OUへ移動」「グループから外す」「ホームフォルダをアーカイブ」など段階を踏む運用にすると、復旧の難易度を下げられます。
スコープ変更のたびにフル同期が走って“退職者が復活”して見える場合
スコープ変更やマッピング変更のタイミングでフル同期が走り、過去の退職者が再作成されたように見える場合は、次の観点で切り分けが必要です。
- フル同期で退職者がスキップされる設計か:スキップが仕様なら「復活」は別要因(削除済みオブジェクトの再作成など)
- 無効化判定の属性が揺れていないか:
activeEmploymentsCountかemplStatusかで結果が変わることがある - アンカー(突合キー)が安定しているか:メールアドレス等、後で変わる値をキーにすると“別人扱い”で再作成が起きやすい
この領域は構成依存が大きく、仕様どおりか/回帰・不具合かの切り分けが必要になることが多いです。再現条件(いつから、何を変えて、どのユーザーで)を整理し、プロビジョニング ログと合わせてサポートで調査するのが最短です。
まとめ:この手のトラブルで押さえるべき3つの軸
- ログの文言に引きずられない:
NotEffectivelyEntitledは“割り当て不足”とは限らない - フル同期と増分同期を混同しない:退職は「変化」を拾う設計。毎晩Fullは退職者をスキップさせやすい
- 退職者を積極的に扱うならジョブ分割:退職者専用ジョブでOU移動・匿名化追従・期限削除の前段を整える
HR起点のID連携は、テンプレートどおりに動かせば「現役社員のID配布」は高い確率でうまくいきます。一方で、退職者や future hire など“例外”を扱い始めた瞬間に、同期方式(フル/増分)とスコープ設計の理解が問われます。まずは運用を増分同期中心に戻し、それでも要件が満たせない部分は「ジョブ分割」や「期限削除の外出し」で、無理なく要件を満たす設計に寄せるのが堅実です。

コメント