Stopping Guest-Inviting-Guest Sprawl in Entra External Collaboration Settings | لما الـ Guest بيعزم Guest تاني: إزاي توقف فوضى التعاون الخارجي في Entra ID

لما الـ Guest بيعزم Guest تاني: إزاي توقف فوضى التعاون الخارجي في Entra ID

حكاية تينانت بدأ بـ 12 guest وخلص بـ 400، وإزاي تمسك الخيط من الأول قبل ما يتفلت.


المقدمة

حصل معايا الموضوع ده فعلاً في تينانت لعميل عنده شركة استشارات صغيرة. البداية كانت طبيعية جداً: قسم الـ Sales عزم شريك خارجي واحد على SharePoint site عشان يتشارك في عرض. المشكلة إن الشريك ده كان عنده صلاحية Invite Guest افتراضياً في التينانت بتاعه، فراح عازم اثنين من زمايله يساعدوه، وهما كل واحد عزم واحد تاني "للمراجعة"، وفي أسبوعين بقى عندك 40 guest جديد ولا أحد فاكر ليه أصلاً كل واحد فيهم موجود. المشكلة الحقيقية مش إن الـ external collaboration حاجة وحشة، هي أداة أساسية للشغل، لكن لو سايبها على Default Settings من غير حدود، هتلاقي نفسك بعد شهور مش عارف مين موجود في التينانت وليه، وده كابوس حقيقي وقت أي Access Review أو Audit.

💡 المتطلبات:
  • صلاحية Global Administrator أو External ID User Flow Administrator على الأقل عشان تعدل authorization policy
  • Entra ID P1 (أو P2 لو هتستخدم Entitlement Management و Access Reviews)
  • Microsoft Graph PowerShell SDK متوصل (Connect-MgGraph مع الصلاحيات المناسبة)
  • Log Analytics workspace متوصل بالـ Entra ID logs لو عايز تعمل مراقبة بـ KQL

ليه المشكلة دي بتحصل أصلاً

Default Setting في أي تينانت جديد إن "كل المستخدمين، وحتى الـ Guests نفسهم، يقدروا يعزموا مستخدمين خارجيين". يعني الـ Guest اللي انت عزمته أصلاً، ممكن يعزم غيره، وده بيتم بدون أي مراجعة أو موافقة منك. المشكلة تتضخم لأن مفيش أي نوتيفيكيشن تلقائي بتوصلك إن guest عزم guest تاني، ولو الـ Access Reviews مش مفعّلة، هتلاقي الـ guests دول متراكمين لشهور من غير أي تنظيف.

الفكرة الأساسية إن الحل مش "نمنع الـ external collaboration بالكامل"، ده هيوقف الشغل. الحل إنك تتحكم في مين يقدر يعزم، وتحدد نوع الحسابات اللي تقدر تنضم، وتراقب اللي بيحصل بدل ما تفاجأ به.

تحكم في مين يقدر يعزم guest أصلاً

الخطوة الأولى: شوف الوضع الحالي

Connect-MgGraph -Scopes "Policy.Read.All"

Get-MgPolicyAuthorizationPolicy | Select-Object AllowInvitesFrom, AllowedToSignUpEmailBasedSubscriptions

لو النتيجة رجعت everyone في AllowInvitesFrom، يعني أي مستخدم عادي، وحتى أي guest، يقدر يبعت دعوة. ده أخطر إعداد ممكن يفضل شغال بدون ما حد يلاحظه.

الخطوة الثانية: قصّر صلاحية الدعوة على الأدمنز فقط

Connect-MgGraph -Scopes "Policy.ReadWrite.Authorization"

Update-MgPolicyAuthorizationPolicy -AllowInvitesFrom "adminsAndGuestInviters"

القيم المتاحة في allowInvitesFrom هي: none، adminsAndGuestInviters، adminsGuestInvitersAndAllMembers، و everyone. لو عندك تينانت شركة عادية، أنصح تروح لـ adminsAndGuestInviters كنقطة انطلاق، وده بيمنع الـ Guests من عزم أي حد تاني نهائياً، وبيسيب صلاحية الدعوة للأدمنز والمستخدمين اللي أنت حددتهم كـ Guest Inviter Role بالاسم.

⚠️ لو عندك Microsoft Graph API مباشرة بدون PowerShell، الطلب بيكون:

PATCH https://graph.microsoft.com/v1.0/policies/authorizationPolicy/authorizationPolicy
Content-Type: application/json

{
  "allowInvitesFrom": "adminsAndGuestInviters"
}

الخطوة الثالثة: اضبط الـ Guest User Access Restrictions

ده إعداد مختلف عن الدعوة نفسها، وده بيحدد الـ Guest بعد ما ينضم، هو يقدر يشوف إيه من الـ directory. تلاقيه في External Identities > External collaboration settings في البورتال، تحت "Guest user access". اختار "Guest user access is restricted to properties and memberships of their own directory objects" لو مش محتاج الـ guests يتصفحوا باقي المستخدمين أو الجروبات.

استبدال الدعوة الحرة بـ Entitlement Management

لو عندك Entra ID P2، أفضل حل جذري هو إنك توقف الدعوة اليدوية بالكامل وتحول كل التعاون الخارجي لـ Access Packages. الميزة إن كل طلب انضمام بيعدي على approval workflow واضح، وله تاريخ انتهاء (expiration)، وبيتم مراجعته دورياً بـ Access Reviews، فمينفعش guest يفضل موجود "للأبد" من غير أي متابعة.

# مثال لعمل Access Package لجهة خارجية معينة عبر Graph
Connect-MgGraph -Scopes "EntitlementManagement.ReadWrite.All"

$params = @{
    displayName = "Partner Collaboration Access"
    description = "External partner access, reviewed quarterly"
    catalogId   = "<catalog-id>"
}
New-MgEntitlementManagementAccessPackage -BodyParameter $params

✅ لما تحول التعاون لـ Access Packages بـ expiration محددة (مثلاً 90 يوم مع تجديد تلقائي بعد approval)، الـ sprawl بيتحل من نفسه لأن أي guest مش نشط أو مش متجدد بيتشال أوتوماتيك.

مراقبة اللي بيحصل بالفعل عبر KQL

مش كل مشكلة تتحل بإعداد واحد، لازم كمان تعرف إذا كان في نشاط غريب في الدعوات. لو عندك الـ Entra ID logs متوصلة بـ Log Analytics أو Defender XDR advanced hunting، الكويري ده بيوريك كل عمليات دعوة الـ guests في آخر 7 أيام:

AuditLogs
| where TimeGenerated > ago(7d)
| where OperationName == "Invite external user"
| extend InitiatedBy = tostring(InitiatedBy.user.userPrincipalName)
| extend TargetUser = tostring(TargetResources[0].userPrincipalName)
| project TimeGenerated, InitiatedBy, TargetUser, Result
| summarize InvitesSent = count() by InitiatedBy
| sort by InvitesSent desc

لو لاقيت حساب guest واحد ظاهر في عمود InitiatedBy وباعت أكتر من دعوة أو اتنين، ده علم أحمر إن الحساب ده بيستخدم بشكل غير متوقع، حتى لو الإعدادات الأساسية متضبطة.

القيمة في allowInvitesFrom مين يقدر يعزم Guests مناسب لـ
everyone أي عضو أو Guest في التينانت مؤسسات تعليمية أو مفتوحة جداً، غير مناسب للشركات
adminsGuestInvitersAndAllMembers كل الأعضاء الداخليين فقط، الـ Guests ممنوعين شركات فيها تعاون خارجي متكرر وموثوق
adminsAndGuestInviters أدمنز والأشخاص المحددين بدور Guest Inviter فقط أغلب بيئات الشركات، توازن بين التحكم والمرونة
none أدمنز فقط بأدوار محددة بيئات عالية الحساسية أو Regulated industries

مشاكل شائعة وحلولها

المشكلة الحل
غيرت allowInvitesFrom لكن الـ guests لسه قادرين يدعوا تأكد إن التغيير اتطبق فعلاً بـ Get-MgPolicyAuthorizationPolicy، وشيك إن مفيش policy ثاني على مستوى الـ B2B collaboration settings بيطغى عليه
عندي guests قدام مش متأكد ليه اتعزموا أصلاً شغّل Access Review على مستوى الجروب أو الـ resource، وسيب المستخدمين الداخليين يأكدوا هل لسه محتاجين الوصول ولا لأ
شركاء بيشتكوا إنهم مش قادرين يعزموا زمايلهم زي زمان دي علامة صحية غير Bug، حولهم لـ Access Package عندهم Approval Workflow واضح بدل الدعوة الحرة
Guests قديمة نشطة من سنين ومحدش يعرف تشيلها ليه أصلاً فعّل Access Review دوري (كل 90 يوم) على كل الـ guests في التينانت، مش فقط على resource واحد

نصائح الأمان 🔐

  • خلي الـ Guest Inviter Role مربوطة بـ PIM بدل ما تكون Standing Assignment، عشان محدش يفضل معاه الصلاحية دايماً بدون احتياج
  • لو مضطر تسيب الدعوة مفتوحة لأعضاء داخليين، ضيف Conditional Access policy تفرض MFA على الـ guests بمجرد ما ينضموا، مش تعتمد على الشركة الأصلية بتاعتهم
  • راجع الـ Cross-tenant access settings مع الشركاء الأساسيين، وحدد Inbound/Outbound trust بدل ما تسيبه Default لكل الدنيا
  • متسيبش Access Package بدون expiration date، حتى لو الشريك دائم، خليها تتجدد بـ approval كل فترة
  • راقب الكويري بتاع KQL فوق كـ Scheduled Alert في Sentinel أو Defender، مش تفتحه يدوي بس وقت الشك

الخلاصة

مشكلة guest-inviting-guest مش حاجة تحصل بسبب هجوم أو ثغرة، هي نتيجة طبيعية لإعدادات افتراضية سايبة مفتوحة من غير حد يراجعها. الحل مش معقد تقنياً، بس محتاج قرار واضح إنك تتحكم في مين يعزم، بدل ما تسيب الباب مفتوح للكل.

  1. راجع قيمة allowInvitesFrom الحالية وقصّرها لـ adminsAndGuestInviters على الأقل
  2. حول التعاون المتكرر مع شركاء لـ Access Packages بـ expiration واضح بدل الدعوة اليدوية
  3. شغّل مراقبة دورية بـ KQL على عمليات الدعوة، ومتعتمدش على المراجعة اليدوية فقط
  4. فعّل Access Reviews دورية على كل الـ guests في التينانت، مش على resource واحد بس

إنت واجهت الموضوع ده في تينانت بتاعك قبل كده؟ شاركنا في التعليقات إزاي لقيت الـ sprawl عندك وإزاي عالجته.

Comments

Popular posts from this blog

Entra ID Free vs P1 vs P2: What You Actually Get at Each License Tier | Entra ID Free ولا P1 ولا P2: الفرق الحقيقي بين الباقات

Conditional Access Design Mistakes That Lock Admins Out of Microsoft Entra ID | لما الـ Conditional Access يقفل عليك الباب وأنت جوه Tenant

App Registrations vs Enterprise Applications in Entra ID: Permissions and Consent Explained | App Registration و Enterprise Application: مين بيعمل إيه في الـ Permissions والـ Consent؟