فحص صحة Active Directory باستخدام إطار PowerShell

هذا هو الجزء الثاني من سلسلة مكونة من جزأين عن فحوصات صحة Active Directory. على الرغم من عدم الحاجة إلى القراءة، إذا كنت ترغب في معرفة كيفية بناء النص البرمجي PowerShell الذي ستتعلم عنه في هذا المقال، فنحن نشجعك على الاطلاع على بناء أداة فحص صحة Active Directory بالتفصيل: الجزء الأول.

في الجزء الأول، تعلمت عن العديد من الاختبارات المتعددة المختلفة ولماذا هي مهمة. دعونا الآن نجمعها جميعًا معًا ونبني أداة. في هذا الجزء، ستحول جميع فحوص صحة Active Directory المشروحة في الجزء الأول إلى إطار اختبار. ستتعلم أيضًا كيفية إخراج نتائج مختلف فحوص صحة Active Directory إلى أدوات مثل Pester وأداة المراقبة المسماة PRTG.

لمتابعة الشرح أو لرؤية النسخة النهائية من الأداة التي ستتعلم عنها في هذا المقال، قم بتنزيل النص البرمجي ADHealthCheck-NoResult.ps1 من GitHub.

تحديد الإخراج

بإمكانية وجود نوع كائن مشترك وطريقة سهلة لإنشائه، سيجعل من السهل بكثير تحويل نتائج الاختبار إلى الأداة التي تختارها.

لإنشاء إخراج موحَّد لجميع الأدوات المحتملة، اخترت استخدام فئة PowerShell. على الرغم من عدم الحاجة إليه، إلا أنه هو النهج الذي اخترت اتباعه هنا. النقطة الرئيسية هي ضمان أن جميع فحوص صحة Active Directory تعيد نفس نوع الإخراج.

A PowerShell class is a schema that defines how a PowerShell object should look and what it should do. Each line you see below represents a property the objects return will have. You can see below I’m planning on each AD health check to return ten properties.

Class AdhcResult {
    [string]$Source
    [string]$TestName
    [bool]$Pass
    $Was
    $ShouldBe
    [string]$Category
    [string]$SubCategory
    [string]$Message
    $Data
    [string[]]$Tags
}

لتسريع عملية إنشاء هذه الفئة، سأستخدم وظيفة مساعدة تسمى New-AdhcResult. تقوم هذه الوظيفة بإنشاء الفئة وكل ما تحتاجه لمتابعة العملية. ستقوم هذه الوظيفة بإخراج كائن من النوع [AdhcResult] مخصص.

تشغيل أداة فحص صحة AD

أولاً، قم بتنزيل ونسخ نص الفحص الخاص بصحة AD إلى مركز تحكم النطاق. قم بفتحه بواسطة PowerShell ISE وتشغيله. لن تقوم هذه الجزء من الأداة بإرجاع أي معلومات.

سيقوم النص بالتشغيل وتخزين نتيجة كل فحص في المتغير $TestResults كأجسام [AdhcResult] متعددة. ستستخدم هذه الأجسام لاحقًا لإنشاء تقارير أو إخراجها إلى أدوات مختلفة. يتيح لك تخزين نتائج فحص الصحة في متغير مثل هذا إمكانية إضافة المزيد من النتائج إذا اخترت إنشاء نتيجة أخرى واستخدام أمر New-AdHcResult.

بمجرد الانتهاء من تشغيل النص، يجب أن تكون الآن لديك مجموعة كاملة من كائنات فحص صحة AD مخزنة في المتغير $TestResults. يمكنك الآن تشغيل $TestResults من الوحدة ورؤية النتائج الخام.

عرض نتائج فحص صحة AD في الأدوات

نظرًا لأن جميع الفحوصات في نوع كائن مشترك، يمكنك تفحصها بشكل أفضل من خلال بعض الأدوات مثل Pester و PRTG.

في هذا القسم، ستتعلم كيفية إنشاء تقرير HTML باستخدام أداة تسمى extent وعرض التقرير في PRTG.

إنشاء ملف nUnit XML باستخدام Pester

أولاً، تحتاج إلى تحويل كائنات PowerShell إلى تنسيق يمكن لأدواتك فهمه. تفهم معظم الأدوات XML أو، بشكل أكثر تحديدًا، nUnit XML. هذا هو التنسيق الذي يمكنك استيراده إلى مجموعة متنوعة من الأدوات لعرض النتائج.

نظرًا لأنك تعمل مع PowerShell، ستستخدم إطار اختبار Pester لقراءة الإخراج من سكربت فحص صحة AD وتوليد ملف nUnit XML

ابدأ بتنزيل أحدث إصدار من Pester. يمكنك تنزيل Pester عن طريق تشغيل Install-Module في وحدة تحكم PowerShell مرتفعة. سيقوم الأمر أدناه بفرض تثبيت أحدث إصدار من Pester. نظرًا لأن الشهادة التي تم توقيع Pester بها متوفرة مع Windows 10، سنحتاج إلى استخدام المعلمة SkipPublisherCheck لتثبيته.

PS51> Install-Module Pester -Force -Verbose -SkipPublisherCheck

بمجرد توفر Pester، يمكنك بعد ذلك تشغيل السكربت وإنشاء مجموعة من اختبارات Pester بشكل ديناميكي.

ملاحظة: يمكنك أيضًا إنشاء اختبارات Pester بنفسك دون استخدام السكربت PowerShell الذي قدمته.

سيستخدم السكربت PowerShell أدناه Pester لإنشاء ملف nUnit XML من إخراج المتغير $TestResults المحدد في سكربت ADHealthCheck-NoResult.ps1.

احفظ هذا الملف بصيغة Pester.ps1 في نفس المجلد الذي يحتوي على نصيحة فحص صحة AD.

# نقطة المصدر في ملف ADHealthCheck
. $PSScriptRoot\ADHealthCheck-NoResult.ps1
$Grouped = $TestResults | Group-Object Category

Foreach($Category in $Grouped) {
    Describe -Name $Category.Name -Tags ($Category.Group.Tags | Select -Unique) {
        Foreach($Result in $Category.Group){
            Context "$($Result.Source) - $($Result.TestName)" {
                It -Name "Should've passed" {
                    $Result.Pass | Should -Be -ExpectedValue $True -Because $Result.data
                }
            }
        }
    }
}

أخيرًا، قم بتشغيل Invoke-Pester أدناه لاستدعاء ملف Pester.ps1 وحفظ النتائج بتنسيق NUnitXml.

PS51 > Invoke-Pester -Script @{Path = '.\Pester.ps1'} -OutputFile .\NunitReport.xml -OutputFormat NUnitXml

بناء تقرير HTML باستخدام أداة Extent

بمجرد الحصول على ملف XML لـ NUnit، يمكنك الآن استخدام هذا الملف لتمريره إلى أداة يمكنها تحويله إلى HTML. إحدى تلك الأدوات تسمى Extent. Extent هي أداة مفيدة لإنشاء تقارير HTML من ملفات Nunit XML.

أولاً، قم بتنزيل Extent إلى نفس الدليل الذي يحتوي على ملف NunitReport.xml الذي تم إنشاؤه سابقًا. ثم قم بتنفيذ الأوامر التالية في جلسة PowerShell. ستقوم هذه الأوامر بإنشاء الدليل لتخزين ملفات HTML ومن ثم تنفيذ extent.exe للقيام بالتحويل.

# إنشاء دليل التقرير
PS51> mkdir .\HTMLReports

# إنشاء التقرير
PS51> .\extent.exe -i .\NunitReport.xml -o .\HTMLReports\

عند الانتهاء، ستجد ملفي HTML في دليل HTMLReports. ستبدو هذه الملفات مشابهة لما يلي في اللقطات أدناه عند فتحها باستخدام مستعرض ويب.

HTML report for Pester test output
HTML report for Pester test output

تقديم نتائج فحص صحة AD إلى PRTG

PRTG هو أداة رصد شهيرة تم تطويرها بواسطة Paessler يمكنك استخدامها لمراقبة بنيتك التحتية وخدماتك. في هذا القسم، ستتعلم كيفية دفع نتائج فحص الصحة إلى PRTG بمجرد تشغيل نص الفحص الصحي.

يستغرق دفع النتائج إلى PRTG المزيد من الجهد بدلاً من السماح للأداة بجلب المعلومات، ولكنك سترى في النهاية أن الإعداد يستحق الوقت المستغرق.

المتطلبات الأساسية

لإعداد PRTG بنجاح كأداة لرصد سكربت فحص صحة AD المدرج في هذا المقال، تأكد من أن لديك:

  • PRTG مثبتة ومكونة
  • تم إعداد جميع مراقبي المجال في PRTG
  • سكربت PowerShell Send-AdhcResultToPrtg.ps1 المُحمل من GitHub
  • عنوان URL ومنفذ جهاز استشعار PRTG

إذا كنت قد قمت بإكمال كل من المتطلبات الأساسية، يمكنك بعد ذلك اتباع التعليمات خطوة بخطوة أدناه حول كيفية نقل نتائج فحص صحة AD إلى PRTG كما أنني أوصي.

  1. أنشئ جهازًا في PRTG ب اسم Domain أو أي اسم تفضله.
  2. أنشئ جهاز استشعار Advanced HTTP push بـ IdentityToken قيمته directory-adhealthcheck. يرجى مراعاة أن هذا حساس لحالة الأحرف!
  3. لكل جهاز تحكم في مراقبة النطاق في PRTG، أنشئ جهاز استشعار Advanced HTTP push. لكل IdentityToken، ألصق كل جهاز استشعار ب -adhealthcheck مثل dc01-adhealthcheck.
  4. أضف محتويات نص Send-AdhcResultToPrtg.ps1 إلى نهاية النص ADHealthCheck-NoResult.ps1 الذي غطيناه.
  5. قم بتغيير المتغير $PRTGUrl إلى عنوان URL ومنفذ مستشعر PRTG الخاص بك.
  6. قم بتنفيذ النص.

بعد الانتهاء، يجب أن يقوم النص بإرسال حالة الآن إلى مستشعرات PRTG الخاصة بك كما هو موضح أدناه.

PRTG sensors showing AD health

جدولة النص الخاص بفحص صحة Active Directory

مراقبة صحة Active Directory هي عملية مستمرة. يجب عليك تشغيل الاختبارات في كل الأوقات بدلاً من الحالات العرضية. دعنا نجدول النص الخاص بفحص صحة Active Directory لتشغيله في فترات زمنية متكررة.

أسهل طريقة لتلقيم هذه الفحوصات تلقائيًا هي عن طريق إضافة النص إلى جدول المهام والسماح له بالتشغيل تحت حساب مستخدم AD أو حساب Group-Managed Service Account.

استخدام حساب الخدمة المدارة بواسطة المجموعة (gMSA) هو الطريقة الأكثر أمانًا لتنفيذ المهام المجدولة بشكل آلي حيث يمكن لحسابات الكمبيوتر المحددة فقط جلب كلمة المرور من AD. ولكن قد لا تتوفر هذه الخاصية في بعض المنظمات.

إنشاء حساب مستخدم AD

دعنا نبدأ أولاً في تفكيك ما يلزم لإعداد حساب مستخدم AD لتشغيل المهمة المجدولة.

إذا كنت ستقوم بتشغيل مهمة مجدولة باسم حساب مستخدم، فلا تقم بتشغيلها باسم حسابك الخاص! قم دائمًا بإنشاء حساب مستخدم منفصل لهذا الغرض.

لتوفير الوقت، ستجد أدناه سكريبت PowerShell. هذا هو سكريبت مثالي يمكنك استخدامه لإنشاء حساب مستخدم AD ينتمي إلى مجموعة Domain Admins. يمكنك بعد ذلك استخدام هذا الحساب لتشغيل المهمة المجدولة.

# قم بتغيير هذا إلى وحدة التنظيم الخاصة بحسابات الخدمة الخاصة بك
$OU = "OU=Service Accounts,DC=contoso,DC=com"
# قم بتغيير هذا إلى كلمة المرور التي ترغب في استخدامها للحساب
$Password = "JägareTvå"
$SecureString = $Password | ConvertTo-SecureString -AsPlainText -Force
New-ADUser -Enabled $True -Path $OU -Name svcADHealthCheck -AccountPassword $SecureString
# قيد الحساب للعمل فقط على مراقبي النطاق
$DomainControllers = (Get-ADDomainController -Filter *).Name

Set-ADAccount -Identity svcADHealthCheck -LogonWorkstations ($DomainControllers -Join ",")

# جعله مسؤول نطاق (عذرًا)
Add-ADGroupMember -Identity "Domain Admins" -Members svcADHealthCheck

إنشاء حساب خدمة مُدار بواسطة المجموعة

يعتبر استخدام حساب خدمة مُدار بواسطة المجموعة أمرًا أكثر تعقيدًا إذا لم تكن تستخدم حساب خدمة مُدار بواسطة المجموعة في بيئتك بالفعل، ولكنه أكثر أمانًا.

إنشاء مفتاح جذر KDS

لإنشاء حساب خدمة مُدار بواسطة المجموعة لتشغيل سكريبت فحص AD، أضف أولاً مفتاح جذر KDS إذا لم يكن لديك واحدًا بالفعل. يمكنك التحقق مما إذا كان لديك مفتاح جذر KDS عن طريق تشغيل أمر PowerShell Get-KDSRootKey على مراقب النطاق.

إذا لم يكن لديك مفتاح جذر KDS، يمكنك إنشاء واحد عن طريق تشغيل Add-KDSRootKey -EffectiveImmediately تحت حساب مستخدم ينتمي إلى مجموعة Domain Admins AD على مراقب مجال يعمل بنظام 2012R2 أو أحدث.

يجب تكريت المفتاح إلى مراقبي المجال الآخرين ليتم التأثير بشكل كامل. يمكن العثور على مزيد من المعلومات حول هذه العملية في توثيق Microsoft.

إنشاء حساب gMSA

بمجرد إنشاء مفتاح جذر KDS، أنت جاهز لإنشاء حساب gMSA باستخدام PowerShell. فيما يلي مثال على نص يمكن استخدامه لإنشاء حساب gMSA مسموحًا فقط للمصادقة من مراقب مجال في مجموعة Domain Admins.

# قم بتغيير المجال الخاص بك
$Domain = "contoso.com"

$AccountName = "svcadhealthcheck"

# إنشاء GMSA يُسمى svcadhealthcheck (أو في الواقع svcadhealthcheck$) والسماح فقط لمراقبي المجال بجلب كلمة المرور
New-ADServiceAccount $AccountName -DNSHostName "$AccountName.$Domain" –PrincipalsAllowedToRetrieveManagedPassword "Domain Controllers"

# إضافة GMSA إلى Domain Admins
# لاحظ أننا نضيف الحساب بواسطة اسم SamAccount الحقيقي 'svcadhealthcheck$'
Add-ADGroupMember -Identity "Domain Admins" -Members "$AccountName`$"

تثبيت واختبار gMSA

الآن تم إنشاء gMSA، آخر خطوة هي تثبيته واختباره على جميع مراقبي النطاق. أحد الطرق لفعل ذلك هو باستخدام أمر PowerShell Invoke-Command. يمكنك أدناه رؤية سكريبت PowerShell الذي سيقوم بتثبيت gMSA على جميع مراقبي النطاق وضمان عمله بشكل صحيح.

# سيتم تشغيل هذا على جميع مراقبي النطاق
Invoke-Command -ComputerName (Get-ADDomainController -Filter *).Name -ScriptBlock {
    $Account = Get-ADServiceAccount -Filter { Name -eq 'svcadhealthcheck'}
    Install-ADServiceAccount $Account

    # يختبر ما إذا كانت GMSA تعمل على الكمبيوتر
    # يرجع $True إذا كانت الاختبارات سليمة
    $Test = Test-ADServiceAccount -Identity $Account.Name
    if($Test){
        Write-Output "GMSA test OK on $env:computername"
    }
    else {
        Write-Output "GMSA test FAILED on $env:computername"
    }

}

منح gMSA الإذن للتشغيل كمهمة دفعية

عندما يتم تثبيت gMSA، ستحتاج الآن إلى منحه إذن للتشغيل كمهمة دفعية على مراقبي النطاق. يحتاج الحساب إلى هذا الحق لأنه سيعمل بشكل مستقل في الخلفية في مهمة مجدولة.

يمكنك تعيين هذا الإذن عبر GPO موجودة أو عن طريق إنشاء GPO جديد وربطه بـ OU مراقبي النطاق. إذا لم يكن لديك بالفعل GPO للاستخدام، فإليك بعض الخطوات التي يمكنك اتخاذها لإنشاء واحد.

  1. قم بتشغيل محرر سياسة المجموعة على مراقب النطاق.
  2. انقر بزر الماوس الأيمن فوق OU مراقبي النطاق وحدد إنشاء GPO في هذا النطاق وربطه هنا.
  3. سمه DC – Logon as batch أو اسم آخر تفضله
  4. انقر بزر الماوس الأيمن فوق GPO وانقر تحرير.
  5. انتقل إلى تكوين الكمبيوتر –> إعدادات ويندوز –> إعدادات الأمان –> فهرسة حقوق المستخدم.
  6. النقر بزر الفأرة الأيسر تسجيل الدخول كوظيفة دفعية وانقر خصائص.
  7. انقر إضافة مستخدم أو مجموعة.
  8. انقر على أنواع الكائنات، حدد حسابات الخدمة فقط وانقر موافق.
  9. ابحث عن حساب الخدمة svcADHealthCheck الذي تم إنشاؤه مسبقًا، حدده وانقر موافق.

يجب أن تظهر الآن gMSA ضمن قائمة الكائنات AD كما هو موضح أدناه.

gMSA given rights to logon as a batch job

إنشاء المهمة المجدولة

الآن بعد أن تم إنشاء حساب لتشغيل المهام المجدولة، يمكنك الآن إنشاء المهمة المجدولة نفسها على خادم متصل بالنطاق من اختيارك.

يمكنك إنشاء المهمة المجدولة عبر الواجهة الرسومية ولكن ذلك يتطلب النقر الكثير! بدلاً من ذلك، أنصحك بإنشائها باستخدام PowerShell. لماذا؟ لأنه يمكنك ببساطة نسخ الكود الذي تراه أدناه والانتهاء منه.

أدناه ستجد اثنين من النصوص. النصوص متشابهة ولكن أحدهما يفترض وجود حساب مستخدم AD والآخر يفترض وجود gMSA. تأكد من استخدام النص الصحيح بناءً على الحساب الذي تستخدمه.

# استبدل بمسار النص البرمجي الخاص بك
$ScriptPath = "C:\Scripts\ADHealthCheck.ps1"
# استبدل باسم المستخدم للحساب الذي قمت بإنشائه لتشغيل المهمة
$UserName = "svdADHealthCheck"

# استبدل بكلمة المرور التي حددتها للحساب أعلاه
$Password = "JägareTvå!"
# قم بإنشاء الإجراء الذي يطلق النص البرمجي
$Action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-ExecutionPolicy bypass -File '$ScriptPath'"
# قم بإنشاء المؤثر الذي يبدأ المهمة
$Trigger = New-ScheduledTaskTrigger -Once -At "12:00" -RepetitionInterval (New-TimeSpan -Hours 12)
# قم بإنشاء الإعدادات للمهمة المجدولة
$Settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -RunOnlyIfNetworkAvailable -DontStopOnIdleEnd
# قم بإنشاء المهمة المجدولة باستخدام splat لتحسين القراءة
$Splat = @{
    User = "$env:USERDOMAIN\$UserName"
    Password = $Password
    TaskName = "ADHealthCheck"
    Action = $Action
    Trigger = $Trigger
    RunLevel = "Highest"
    Settings = $Settings
}
Register-ScheduledTask @Splat
# استبدل بمسار النص البرمجي الخاص بك
$ScriptPath = "C:\Scripts\ADHealthCheck.ps1"
# استبدل باسم المستخدم للحساب الذي قمت بإنشائه لتشغيل المهمة
$UserName = "svdADHealthCheck$"
# قم بإنشاء الإجراء الذي يطلق النص البرمجي
$Action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-ExecutionPolicy bypass -File '$ScriptPath'"
# قم بإنشاء المؤثر الذي يبدأ المهمة
$Trigger = New-ScheduledTaskTrigger -Once -At "12:00" -RepetitionInterval (New-TimeSpan -Hours 12)
# قم بإنشاء الإعدادات للمهمة المجدولة
$Settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -RunOnlyIfNetworkAvailable -DontStopOnIdleEnd

# قم بإنشاء الرئيسية التي تعرف GMSA
$Principal = New-ScheduledTaskPrincipal -UserID "$env:USERDOMAIN\$UserName" -LogonType Password -RunLevel Highest
# قم بإنشاء المهمة المجدولة باستخدام splat لتحسين القراءة
$Splat = @{
    Principal = $Principal
    TaskName = "ADHealthCheck"
    Action = $Action
    Trigger = $Trigger
    RunLevel = "Highest"
    Settings = $Settings
}
Register-ScheduledTask @Splat

لقد انتهيت! في هذا الوقت، ستنفذ المهمة المجدولة بالفاصل الزمني المحدد في أحد النصوص أعلاه.

ملخص

الهواء! إذا كنت قد تابعت حتى الآن من الجزء الأول، يجب أن تعرف الآن أن صحة AD موضوع عميق. هناك الكثير في هذا الموضوع الواحد حتى لا يمكن أن تغطيه حتى مدونتين طويلتين.

لكن، بحلول الآن، يجب أن يكون لديك ما يكفي من المعرفة والإطار السلطة-شل الجاهز الذي يمكنك توصيله بفحوص صحة الدليل النشط الأخرى كما تنشأ.

قراءة إضافية

Source:
https://adamtheautomator.com/active-directory-health-check-2/