其他安全防護功能

Credential Guard 可降低對衍生認證的攻擊,防止在其他地方使用遭竊的認證。 不過,即使衍生認證受到 Credential Guard 保護,裝置仍可能容易遭受特定攻擊。 這些攻擊可能包括濫用許可權,以及直接從遭入侵的裝置使用衍生認證、在啟用 Credential Guard 之前重複使用遭竊的認證,以及濫用管理工具和弱式應用程式設定。 因此,也必須部署額外的風險降低措施,讓網域環境更健全。

其他安全性資格

所有符合硬體、韌體和軟體基準保護的裝置都可以使用 Credential Guard。
符合更多資格的裝置可以提供額外的保護,進一步減少受攻擊面。

下表列出改善安全性的資格。 建議您符合其他資格,以強化 Credential Guard 可提供的安全性層級。

保護 需求 安全性優點
安全開機設定和管理 - 必須支援
BIOS 密碼或更強大的驗證 - 在 BIOS 設定中,必須設定
BIOS 驗證 - 必須支援受保護的 BIOS 選項,才能設定允許的開機裝置清單 (例如, 只從內部硬碟開機) 和開機裝置順序,覆寫 BOOTORDER 操作系統所做的修改
- 防止其他作業系統啟動
-防止對BIOS設定進行變更
硬體根信任平臺安全開機 - 必須支援 (平臺安全開機) 的開機完整性。 請參閱 System.Fundamentals.Firmware.CS.UEFISecureBoot.ConnectedStandby
- 硬體安全性測試介面下的 Windows 硬體相容性計劃需求 (必須實作 HSTI) 。 請參閱 硬體安全性可測試性規格
- 因開啟電源而產生的開機完整性 (平台安全開機) 可提供保護,來防範實際存在的攻擊者,並全面抵禦惡意程式碼。
- HSTI 為正確保護的晶元和平臺提供安全性保證
透過 Windows Update 更新韌體 - 韌體必須透過 Windows Update 和 UEFI 封裝更新來支援字段更新 有助於確保韌體更新是快速、安全且可靠的。
保護開機設定和管理 - 必要的 BIOS 功能:OEM 在製造時間
於安全開機 DB 中新增 ISV、OEM 或企業憑證的能力 - 必要設定:必須從安全開機資料庫移除 Microsoft UEFI CA。 允許支援第三方 UEFI 模組,但應針對特定 UEFI 軟體使用 ISV 提供的憑證或 OEM 憑證
- 企業可以選擇允許執行專屬 EFI 驅動程式/應用程式
- 從安全開機 DB 移除 Microsoft UEFI CA 可讓企業完全控制在操作系統開機之前執行的軟體
針對 UEFI 運行時間服務啟用 No-Execute (NX) 保護的 VBS - VBS 可在 UEFI 運行時間服務程式代碼和數據記憶體區域上啟用 NX 保護。 UEFI 執行階段服務程式碼必須支援唯讀網頁保護,而且 UEFI 執行階段服務的資料必須不能執行。 UEFI 執行時間服務必須符合下列需求:
- 實作 UEFI 2.6 EFI_MEMORY_ATTRIBUTES_TABLE。 此數據表
必須描述所有 UEFI 執行時間服務記憶體 (程式代碼和數據) - PE 區段必須在記憶體中對齊頁面, (非變動性記憶體) 中不需要。
- 記憶體屬性資料表必須正確地將程式代碼和數據標示為 RO/NX 由OS
設定 - 所有專案都必須包含屬性 EFI_MEMORY_ROEFI_MEMORY_XP或兩者。
- 上述兩個屬性都無法保留任何專案,表示可執行檔和可寫入的記憶體。 記憶體必須是可讀取、可執行或可寫入且不可執行
的, (請參閱此數據表之後的重要資訊)
- 如果有的話,UEFI 運行時間中的弱點會遭到封鎖而無法危害 VBS (例如 UpdateCapsuleSetVariable)
等函式 - 將受攻擊面從系統韌體縮減為 VBS。
SMM 保護的韌體支援 - Windows SMM 安全性風險降低資料表 (WSMT) 規格 包含 ACPI 數據表的詳細數據,該數據表是針對支援 Windows 虛擬化功能的 Windows 操作系統所建立。 - 防止 UEFI 運行時間服務中的潛在弱點,如果有的話,將會遭到封鎖,避免危害 VBS (,例如 UpdateCapsule 和 SetVariable)
- 將受攻擊面從系統韌體縮減為 VBS
- 封鎖針對 SMM 的其他安全性攻擊

重要

關於 VBS 啟用 UEFI 運行時間服務的 NX 保護

  • 它只適用於 UEFI 運行時間服務記憶體,而不適用於 UEFI 開機服務記憶體
  • VBS 會在 OS 分頁表上套用保護
  • 請勿使用可寫入和可執行檔的區段
  • 請勿嘗試直接修改可執行的系統記憶體
  • 不要使用動態程序代碼

將網域使用者限制為特定已加入網域的裝置

認證竊取攻擊可讓攻擊者從一部裝置竊取密碼,然後從另一部裝置使用這些密碼。 若使用者可在多個裝置上登入,則有心人士可能會使用任何裝置來竊取認證。 如何確保使用者只使用已啟用 Credential Guard 的裝置登入? 藉由部署驗證原則,將它們限制為已使用 Credential Guard 設定的特定已加入網域的裝置。 為了讓網域控制站得知使用者登入的來源裝置,必須使用 Kerberos 保護。

Kerberos 保護

Kerberos 保護是 RFC 6113 的一部分。 若裝置支援 Kerberos 保護,則系統會使用其 TGT 來保護使用者的持有證明,有助於減少字典攻擊行為。 Kerberos 保護亦提供簽署 KDC 錯誤的額外優勢,有助於減少致使發生諸如降級攻擊的資料竄改行為。

若要啟用 Kerberos 防護,將網域使用者限製為特定已加入網域的裝置:

  • 使用者必須位於執行 Windows Server 2012 R2 或更高版本的網域
  • 您必須設定位於這些網域的所有網域控制站,以支援 Kerberos 保護。 將 [宣告、複合驗證和 Kerberos 防護的 KDC 支援] 群組原則設定為 [支援] 或 [永遠提供宣告]。
  • 必須將使用者限制為的所有 Credential Guard 裝置設定為支援 Kerberos 防護。 在 [計算機設定] -[系統管理範本] ->[系統>] ->[Kerberos] 下,啟用 [Kerberos 用戶端支援宣告]、[複合驗證] 和 [Kerberos 防護] 群組原則 設定。

保護已加入網域的裝置秘密

由於加入網域的裝置也使用共用密碼來進行驗證,因此攻擊者也可以竊取這些密碼。 藉由透過 Credential Guard 來部署裝置憑證,即可保護私密金鑰。 然後,驗證原則可能會要求使用者登入使用這些憑證進行驗證的裝置。 這可防止使用遭竊裝置上的共用密碼,搭配遭竊的使用者密碼而以使用者身分進行登入。

加入網域的裝置憑證驗證具備下列需求:

  • 裝置帳戶位於 Windows Server 2012 網域功能層級或更高層級。
  • 位於這些網域中的所有網域控制站皆具有 KDC 憑證,符合嚴格的 KDC 驗證憑證需求:
    • KDC EKU 存在
    • DNS 網域名稱符合 SubjectAltName (SAN) 延伸的 DNSName 欄位
  • Windows 裝置有 CA 在企業存放區中發出域控制器憑證。
  • 建立一個處理程序,以類似於您建立使用者的身分識別和可信度的方式,確保裝置的身分識別和可信度,然後再為它們簽發智慧卡。

部署已加入網域的裝置憑證

若要確保含所需發行原則的憑證僅安裝在這些使用者必須使用的裝置上,您必須在每部裝置上手動部署它們。 將智慧卡簽發給使用者所使用的相同安全性程序應該也適用於裝置憑證。

例如,假設您僅想要在這些裝置上使用高保證原則。 使用 Windows Server Enterprise 憑證授權單位可建立新的範本。

建立新的證書範本

  1. 從 [憑證管理員] 控制台,以滑鼠右鍵按兩下 [ 證書範 > 本管理]
  2. 以滑鼠右鍵按兩下 [工作站驗證 > 重複範本]
  3. 以滑鼠右鍵按下新的範本,然後選取 [ 屬性]
  4. 在 [ 延伸模組] 索引標籤上 ,選取 [ 應用程式原則 > 編輯]
  5. 選取 [客戶端驗證],然後選取 [ 移除]
  6. 新增 ID-PKInit-KPClientAuth EKU。 選取 [新增 > ],然後指定下列值:
    • 名稱:Kerberos 用戶端驗證
    • 物件識別碼:1.3.6.1.5.2.3.4
  7. 在 [ 延伸模組] 索引標籤上 ,選取 [ 發佈原則 > 編輯]
  8. 在 [ 發行原則] 底下,選取 [高保證]
  9. 在 [ 主體名稱] 索引 標籤上,清除 [DNS 名稱 ] 複選框,然後選 取 [用戶主體名稱 (UPN) ] 複選框

然後在執行 Credential Guard 的裝置上,使用剛剛建立的憑證註冊裝置。

在憑證中註冊裝置

執行下列命令:

CertReq -EnrollCredGuardCert MachineAuthentication

注意

在註冊電腦驗證憑證之後,您必須重新啟動裝置。

如何使用憑證發行原則進行存取控制

自 Windows Server 2008 R2 網域功能層級開始,驗證機制保證的網域控制站支援提供了將憑證發行原則 OID 對應至通用安全性群組的方法。 具有宣告支援的 Windows Server 2012 網域控制站可將其對應至宣告。 若要深入了解驗證機制保證,請參閱 TechNet 上的 Windows Server 2008 R2 中的 AD DS 驗證機制保證逐步指南

查看可用的發行原則

  • get-IssuancePolicy.ps1 會顯示憑證授權單位上所有可用的發行原則。
    請從 Windows PowerShell 命令提示字元,執行下列命令:
.\get-IssuancePolicy.ps1 -LinkedToGroup:All

將發行原則連結至通用安全性群組

  • set-IssuancePolicyToGroupLink.ps1 會建立萬用安全性群組、建立組織單位,然後將發行原則連結到該萬用安全性群組。
    請從 Windows PowerShell 命令提示字元,執行下列命令:
.\set-IssuancePolicyToGroupLink.ps1 -IssuancePolicyName:"<name of issuance policy>" -groupOU:"<Name of OU to create>" -groupName:"<name of Universal security group to create>"

限制使用者登入

現在我們已完成下列事項:

  • 建立特殊憑證發行原則,以識別符合可讓使用者登入之所需部署條件的裝置
  • 將該原則對應至通用安全性群組或宣告
  • 提供方法讓域控制器在使用者登入期間使用 Kerberos 防護取得裝置授權數據。 接下來即是在網域控制站上設定存取檢查。 我們會使用驗證原則完成此動作。

驗證原則有下列需求︰

  • 使用者帳戶位於 Windows Server 2012 網域功能層級或更高網域。

建立驗證原則將使用者限制為特定的通用安全性群組

  1. 開啟 Active Directory 管理中心
  2. 取 [驗證 > ] [新增 > 驗證原則]
  3. 在 [ 顯示名稱] 方塊中,輸入此驗證原則的名稱
  4. 在 [ 帳戶] 標題下,選取 [ 新增]
  5. 在 [ 選取使用者、計算機或服務帳戶 ] 對話框中,輸入您想要限制的使用者帳戶名稱,然後選取 [ 確定]
  6. 在 [ 使用者登入 ] 標題下,選取 [ 編輯] 按鈕
  7. 取 [新增條件]
  8. 在 [編輯 存取控制 條件] 方塊中,確定其讀取每個>值的使用者>群組>成員,然後選取 [新增專案]
  9. 在 [ 選取使用者、計算機或服務帳戶] 對話框中,輸入您使用 set-IssuancePolicyToGroupLink 腳本建立的通用安全組名稱,然後選取 [ 確定]
  10. 選取 [確定] 以關閉 [編輯 存取控制 條件] 方塊
  11. 選取 [確定 ] 以建立驗證原則
  12. 選取 [Active Directory 管理中心]

注意

驗證原則強制執行原則限制時,使用者將無法使用未具備憑證且未使用適當發行原則部署該憑證的裝置來登入。 這同時適用於本機和遠端登入案例。 因此,強烈建議您在首次操作時僅稽核原則限制,以確保不會發生非預期的錯誤。

探索驗證因驗證原則而失敗

為了更輕易地運用驗證原則致使追蹤驗證功能失敗,僅有這些事件才存有操作記錄。 若要在域控制器上啟用記錄,請在 事件檢視器 中,流覽至 [應用程式和服務記錄檔\Microsoft\Windows\Authentication],以滑鼠右鍵按兩下 [AuthenticationPolicyFailures-DomainController],然後選取 [啟用記錄]

若要深入了解驗證原則事件,請參閱驗證原則與驗證原則定址接收器

附錄:指令碼

此處提供本主題中提及的指令碼清單。

取得憑證授權單位上可用的發行原則

將此指令碼檔案儲存為 get-IssuancePolicy.ps1。

#######################################
##     Parameters to be defined      ##
##     by the user                   ##
#######################################
Param (
$Identity,
$LinkedToGroup
)
#######################################
##     Strings definitions           ##
#######################################
Data getIP_strings {
# culture="en-US"
ConvertFrom-StringData -stringdata @'
help1 = This command can be used to retrieve all available Issuance Policies in a forest. The forest of the currently logged on user is targeted.
help2 = Usage:
help3 = The following parameter is mandatory:
help4 = -LinkedToGroup:<yes|no|all>
help5 = "yes" will return only Issuance Policies that are linked to groups. Checks that the linked Issuance Policies are linked to valid groups.
help6 = "no" will return only Issuance Policies that are not currently linked to any group.
help7 = "all" will return all Issuance Policies defined in the forest. Checks that the linked Issuance policies are linked to valid groups.
help8 = The following parameter is optional:
help9 = -Identity:<Name, Distinguished Name or Display Name of the Issuance Policy that you want to retrieve>. If you specify an identity, the option specified in the "-LinkedToGroup" parameter is ignored.
help10 = Output: This script returns the Issuance Policy objects meeting the criteria defined by the above parameters.
help11 = Examples:
errorIPNotFound = Error: no Issuance Policy could be found with Identity "{0}"
ErrorNotSecurity = Error: Issuance Policy "{0}" is linked to group "{1}" which is not of type "Security".
ErrorNotUniversal = Error: Issuance Policy "{0}" is linked to group "{1}" whose scope is not "Universal".
ErrorHasMembers = Error: Issuance Policy "{0}" is linked to group "{1}" which has a non-empty membership. The group has the following members:
LinkedIPs = The following Issuance Policies are linked to groups:
displayName = displayName : {0}
Name = Name : {0}
dn = distinguishedName : {0}
        InfoName = Linked Group Name: {0}
        InfoDN = Linked Group DN: {0}   
NonLinkedIPs = The following Issuance Policies are NOT linked to groups:
'@
}
##Import-LocalizedData getIP_strings
import-module ActiveDirectory
#######################################
##           Help                    ##
#######################################
function Display-Help {
    ""
    $getIP_strings.help1
    ""
$getIP_strings.help2
""
$getIP_strings.help3
"     " + $getIP_strings.help4
"             " + $getIP_strings.help5
    "             " + $getIP_strings.help6
    "             " + $getIP_strings.help7
""
$getIP_strings.help8
    "     " + $getIP_strings.help9
    ""
    $getIP_strings.help10
""
""    
$getIP_strings.help11
    "     " + '$' + "myIPs = .\get-IssuancePolicy.ps1 -LinkedToGroup:All"
    "     " + '$' + "myLinkedIPs = .\get-IssuancePolicy.ps1 -LinkedToGroup:yes"
    "     " + '$' + "myIP = .\get-IssuancePolicy.ps1 -Identity:""Medium Assurance"""
""
}
$root = get-adrootdse
$domain = get-addomain -current loggedonuser
$configNCDN = [String]$root.configurationNamingContext
if ( !($Identity) -and !($LinkedToGroup) ) {
display-Help
break
}
if ($Identity) {
    $OIDs = get-adobject -Filter {(objectclass -eq "msPKI-Enterprise-Oid") -and ((name -eq $Identity) -or (displayname -eq $Identity) -or (distinguishedName -like $Identity)) } -searchBase $configNCDN -properties *
    if ($OIDs -eq $null) {
$errormsg = $getIP_strings.ErrorIPNotFound -f $Identity
write-host $errormsg -ForegroundColor Red
    }
    foreach ($OID in $OIDs) {
        if ($OID."msDS-OIDToGroupLink") {
# In case the Issuance Policy is linked to a group, it is good to check whether there is any problem with the mapping.
            $groupDN = $OID."msDS-OIDToGroupLink"
            $group = get-adgroup -Identity $groupDN
    $groupName = $group.Name
# Analyze the group
            if ($group.groupCategory -ne "Security") {
$errormsg = $getIP_strings.ErrorNotSecurity -f $Identity, $groupName
                write-host $errormsg -ForegroundColor Red
            }
            if ($group.groupScope -ne "Universal") {
                $errormsg = $getIP_strings.ErrorNotUniversal -f $Identity, $groupName
write-host $errormsg -ForegroundColor Red
            }
            $members = Get-ADGroupMember -Identity $group
            if ($members) {
                $errormsg = $getIP_strings.ErrorHasMembers -f $Identity, $groupName
write-host $errormsg -ForegroundColor Red
                foreach ($member in $members) {
                    write-host "          "  $member -ForeGroundColor Red
                }
            }
        }
    }
    return $OIDs
    break
}
if (($LinkedToGroup -eq "yes") -or ($LinkedToGroup -eq "all")) {
    $LDAPFilter = "(&(objectClass=msPKI-Enterprise-Oid)(msDS-OIDToGroupLink=*)(flags=2))"
    $LinkedOIDs = get-adobject -searchBase $configNCDN -LDAPFilter $LDAPFilter -properties *
    write-host ""    
    write-host "*****************************************************"
    write-host $getIP_strings.LinkedIPs
    write-host "*****************************************************"
    write-host ""
    if ($LinkedOIDs -ne $null){
      foreach ($OID in $LinkedOIDs) {
# Display basic information about the Issuance Policies
          ""
  $getIP_strings.displayName -f $OID.displayName
  $getIP_strings.Name -f $OID.Name
  $getIP_strings.dn -f $OID.distinguishedName
# Get the linked group.
          $groupDN = $OID."msDS-OIDToGroupLink"
          $group = get-adgroup -Identity $groupDN
          $getIP_strings.InfoName -f $group.Name
          $getIP_strings.InfoDN -f $groupDN
# Analyze the group
          $OIDName = $OID.displayName
    $groupName = $group.Name
          if ($group.groupCategory -ne "Security") {
          $errormsg = $getIP_strings.ErrorNotSecurity -f $OIDName, $groupName
          write-host $errormsg -ForegroundColor Red
          }
          if ($group.groupScope -ne "Universal") {
          $errormsg = $getIP_strings.ErrorNotUniversal -f $OIDName, $groupName
          write-host $errormsg -ForegroundColor Red
          }
          $members = Get-ADGroupMember -Identity $group
          if ($members) {
          $errormsg = $getIP_strings.ErrorHasMembers -f $OIDName, $groupName
          write-host $errormsg -ForegroundColor Red
              foreach ($member in $members) {
                  write-host "          "  $member -ForeGroundColor Red
              }
          }
          write-host ""
      }
    }else{
write-host "There are no issuance policies that are mapped to a group"
    }
    if ($LinkedToGroup -eq "yes") {
        return $LinkedOIDs
        break
    }
}    
if (($LinkedToGroup -eq "no") -or ($LinkedToGroup -eq "all")) {  
    $LDAPFilter = "(&(objectClass=msPKI-Enterprise-Oid)(!(msDS-OIDToGroupLink=*))(flags=2))"
    $NonLinkedOIDs = get-adobject -searchBase $configNCDN -LDAPFilter $LDAPFilter -properties *
    write-host ""    
    write-host "*********************************************************"
    write-host $getIP_strings.NonLinkedIPs
    write-host "*********************************************************"
    write-host ""
    if ($NonLinkedOIDs -ne $null) {
      foreach ($OID in $NonLinkedOIDs) {
# Display basic information about the Issuance Policies
write-host ""
$getIP_strings.displayName -f $OID.displayName
$getIP_strings.Name -f $OID.Name
$getIP_strings.dn -f $OID.distinguishedName
write-host ""
      }
    }else{
write-host "There are no issuance policies which are not mapped to groups"
    }
    if ($LinkedToGroup -eq "no") {
        return $NonLinkedOIDs
        break
    }
}

注意

如果您無法執行此指令碼,請嘗試取代 ConvertFrom-StringData 參數之後的單引號。

將此指令碼檔案儲存為 set-IssuancePolicyToGroupLink.ps1。

#######################################
##     Parameters to be defined      ##
##     by the user                   ##
#######################################
Param (
$IssuancePolicyName,
$groupOU,
$groupName
)
#######################################
##     Strings definitions           ##
#######################################
Data ErrorMsg {
# culture="en-US"
ConvertFrom-StringData -stringdata @'
help1 = This command can be used to set the link between a certificate issuance policy and a universal security group.
help2 = Usage:
help3 = The following parameters are required:
help4 = -IssuancePolicyName:<name or display name of the issuance policy that you want to link to a group>
help5 = -groupName:<name of the group you want to link the issuance policy to>. If no name is specified, any existing link to a group is removed from the Issuance Policy.
help6 = The following parameter is optional:
help7 = -groupOU:<Name of the Organizational Unit dedicated to the groups which are linked to issuance policies>. If this parameter is not specified, the group is looked for or created in the Users container.
help8 = Examples:
help9 = This command will link the issuance policy whose display name is "High Assurance" to the group "HighAssuranceGroup" in the Organizational Unit "OU_FOR_IPol_linked_groups". If the group or the Organizational Unit do not exist, you will be prompted to create them.
help10 = This command will unlink the issuance policy whose name is "402.164959C40F4A5C12C6302E31D5476062" from any group.
MultipleIPs = Error: Multiple Issuance Policies with name or display name "{0}" were found in the subtree of "{1}"
NoIP = Error: no issuance policy with name or display name "{0}" could be found in the subtree of "{1}".
IPFound = An Issuance Policy with name or display name "{0}" was successfully found: {1}
MultipleOUs = Error: more than 1 Organizational Unit with name "{0}" could be found in the subtree of "{1}".
confirmOUcreation = Warning: The Organizational Unit that you specified does not exist. Do you want to create it?
OUCreationSuccess = Organizational Unit "{0}" successfully created.
OUcreationError = Error: Organizational Unit "{0}" could not be created.
OUFoundSuccess = Organizational Unit "{0}" was successfully found.
multipleGroups = Error: More than one group with name "{0}" was found in Organizational Unit "{1}".  
confirmGroupCreation = Warning: The group that you specified does not exist. Do you want to create it?
groupCreationSuccess = Univeral Security group "{0}" successfully created.
groupCreationError = Error: Univeral Security group "{0}" could not be created.
GroupFound = Group "{0}" was successfully found.
confirmLinkDeletion = Warning: The Issuance Policy "{0}" is currently linked to group "{1}". Do you really want to remove the link?
UnlinkSuccess = Certificate issuance policy successfully unlinked from any group.
UnlinkError = Removing the link failed.
UnlinkExit = Exiting without removing the link from the issuance policy to the group.
IPNotLinked = The Certificate issuance policy is not currently linked to any group. If you want to link it to a group, you should specify the -groupName option when starting this script.
ErrorNotSecurity = Error: You cannot link issuance Policy "{0}" to group "{1}" because this group is not of type "Security".
ErrorNotUniversal = Error: You cannot link issuance Policy "{0}" to group "{1}" because the scope of this group is not "Universal".
ErrorHasMembers = Error: You cannot link issuance Policy "{0}" to group "{1}" because it has a non-empty membership. The group has the following members:
ConfirmLinkReplacement = Warning: The Issuance Policy "{0}" is currently linked to group "{1}". Do you really want to update the link to point to group "{2}"?
LinkSuccess = The certificate issuance policy was successfully linked to the specified group.
LinkError = The certificate issuance policy could not be linked to the specified group.
ExitNoLinkReplacement = Exiting without setting the new link.
'@
}
# import-localizeddata ErrorMsg
function Display-Help {
""
write-host $ErrorMsg.help1
""
write-host $ErrorMsg.help2
""
write-host $ErrorMsg.help3
write-host "`t" $ErrorMsg.help4
write-host "`t" $ErrorMsg.help5
""
write-host $ErrorMsg.help6
write-host "`t" $ErrorMsg.help7
""
""
write-host $ErrorMsg.help8
""
write-host $ErrorMsg.help9
".\Set-IssuancePolicyToGroupMapping.ps1 -IssuancePolicyName ""High Assurance"" -groupOU ""OU_FOR_IPol_linked_groups"" -groupName ""HighAssuranceGroup"" "
""
write-host $ErrorMsg.help10
'.\Set-IssuancePolicyToGroupMapping.ps1 -IssuancePolicyName "402.164959C40F4A5C12C6302E31D5476062" -groupName $null '
""
}
# Assumption:  The group to which the Issuance Policy is going
#              to be linked is (or is going to be created) in
#              the domain the user running this script is a member of.
import-module ActiveDirectory
$root = get-adrootdse
$domain = get-addomain -current loggedonuser
if ( !($IssuancePolicyName) ) {
display-Help
break
}
#######################################
##     Find the OID object           ##
##     (aka Issuance Policy)         ##
#######################################
$searchBase = [String]$root.configurationnamingcontext
$OID = get-adobject -searchBase $searchBase -Filter { ((displayname -eq $IssuancePolicyName) -or (name -eq $IssuancePolicyName)) -and (objectClass -eq "msPKI-Enterprise-Oid")} -properties *
if ($OID -eq $null) {
$tmp = $ErrorMsg.NoIP -f $IssuancePolicyName, $searchBase  
write-host $tmp -ForeGroundColor Red
break;
}
elseif ($OID.GetType().IsArray) {
$tmp = $ErrorMsg.MultipleIPs -f $IssuancePolicyName, $searchBase  
write-host $tmp -ForeGroundColor Red
break;
}
else {
$tmp = $ErrorMsg.IPFound -f $IssuancePolicyName, $OID.distinguishedName
write-host $tmp -ForeGroundColor Green
}
#######################################
##  Find the container of the group  ##
#######################################
if ($groupOU -eq $null) {
# default to the Users container
$groupContainer = $domain.UsersContainer
}
else {
$searchBase = [string]$domain.DistinguishedName
$groupContainer = get-adobject -searchBase $searchBase -Filter { (Name -eq $groupOU) -and (objectClass -eq "organizationalUnit")}
if ($groupContainer.count -gt 1) {
$tmp = $ErrorMsg.MultipleOUs -f $groupOU, $searchBase
write-host $tmp -ForegroundColor Red
break;
}
elseif ($groupContainer -eq $null) {
$tmp = $ErrorMsg.confirmOUcreation
write-host $tmp " ( (y)es / (n)o )" -ForegroundColor Yellow -nonewline
$userChoice = read-host
if ( ($userChoice -eq "y") -or ($userChoice -eq "yes") ) {
new-adobject -Name $groupOU -displayName $groupOU -Type "organizationalUnit" -ProtectedFromAccidentalDeletion $true -path $domain.distinguishedName
if ($?){
$tmp = $ErrorMsg.OUCreationSuccess -f $groupOU
write-host $tmp -ForegroundColor Green
}
else{
$tmp = $ErrorMsg.OUCreationError -f $groupOU
write-host $tmp -ForeGroundColor Red
break;
}
$groupContainer = get-adobject -searchBase $searchBase -Filter { (Name -eq $groupOU) -and (objectClass -eq "organizationalUnit")}
}
else {
break;
}
}
else {
$tmp = $ErrorMsg.OUFoundSuccess -f $groupContainer.name
write-host $tmp -ForegroundColor Green
}
}
#######################################
##  Find the group               ##
#######################################
if (($groupName -ne $null) -and ($groupName -ne "")){
##$searchBase = [String]$groupContainer.DistinguishedName
$searchBase = $groupContainer
$group = get-adgroup -Filter { (Name -eq $groupName) -and (objectClass -eq "group") } -searchBase $searchBase
if ($group -ne $null -and $group.gettype().isarray) {
$tmp = $ErrorMsg.multipleGroups -f $groupName, $searchBase
write-host $tmp -ForeGroundColor Red
break;
}
elseif ($group -eq $null) {
$tmp = $ErrorMsg.confirmGroupCreation
write-host $tmp " ( (y)es / (n)o )" -ForegroundColor Yellow -nonewline
$userChoice = read-host
if ( ($userChoice -eq "y") -or ($userChoice -eq "yes") ) {
new-adgroup -samAccountName $groupName -path $groupContainer.distinguishedName -GroupScope "Universal" -GroupCategory "Security"
if ($?){
$tmp = $ErrorMsg.GroupCreationSuccess -f $groupName
write-host $tmp -ForegroundColor Green
}else{
$tmp = $ErrorMsg.groupCreationError -f $groupName
write-host $tmp -ForeGroundColor Red
break
}
$group = get-adgroup -Filter { (Name -eq $groupName) -and (objectClass -eq "group") } -searchBase $searchBase
}
else {
break;
}
}
else {
$tmp = $ErrorMsg.GroupFound -f $group.Name
write-host $tmp -ForegroundColor Green
}
}
else {
#####
## If the group is not specified, we should remove the link if any exists
#####
if ($OID."msDS-OIDToGroupLink" -ne $null) {
$tmp = $ErrorMsg.confirmLinkDeletion -f $IssuancePolicyName, $OID."msDS-OIDToGroupLink"
write-host $tmp " ( (y)es / (n)o )" -ForegroundColor Yellow -nonewline
$userChoice = read-host
if ( ($userChoice -eq "y") -or ($userChoice -eq "yes") ) {
set-adobject -Identity $OID -Clear "msDS-OIDToGroupLink"
if ($?) {
$tmp = $ErrorMsg.UnlinkSuccess
write-host $tmp -ForeGroundColor Green
}else{
$tmp = $ErrorMsg.UnlinkError
write-host $tmp -ForeGroundColor Red
}
}
else {
$tmp = $ErrorMsg.UnlinkExit
write-host $tmp
break
}
}
else {
$tmp = $ErrorMsg.IPNotLinked
write-host $tmp -ForeGroundColor Yellow
}
break;
}
#######################################
##  Verify that the group is         ##
##  Universal, Security, and         ##
##  has no members                   ##
#######################################
if ($group.GroupScope -ne "Universal") {
$tmp = $ErrorMsg.ErrorNotUniversal -f $IssuancePolicyName, $groupName
write-host $tmp -ForeGroundColor Red
break;
}
if ($group.GroupCategory -ne "Security") {
$tmp = $ErrorMsg.ErrorNotSecurity -f $IssuancePolicyName, $groupName
write-host $tmp -ForeGroundColor Red
break;
}
$members = Get-ADGroupMember -Identity $group
if ($members -ne $null) {
$tmp = $ErrorMsg.ErrorHasMembers -f $IssuancePolicyName, $groupName
write-host $tmp -ForeGroundColor Red
foreach ($member in $members) {write-host "   $member.name" -ForeGroundColor Red}
break;
}
#######################################
##  We have verified everything. We  ##
##  can create the link from the     ##
##  Issuance Policy to the group.    ##
#######################################
if ($OID."msDS-OIDToGroupLink" -ne $null) {
$tmp = $ErrorMsg.ConfirmLinkReplacement -f $IssuancePolicyName, $OID."msDS-OIDToGroupLink", $group.distinguishedName
write-host $tmp  "( (y)es / (n)o )" -ForegroundColor Yellow -nonewline
$userChoice = read-host
if ( ($userChoice -eq "y") -or ($userChoice -eq "yes") ) {
$tmp = @{'msDS-OIDToGroupLink'= $group.DistinguishedName}
set-adobject -Identity $OID -Replace $tmp
if ($?) {
$tmp = $Errormsg.LinkSuccess
write-host $tmp -Foreground Green
}else{
$tmp = $ErrorMsg.LinkError
write-host $tmp -Foreground Red
}
} else {
$tmp = $Errormsg.ExitNoLinkReplacement
write-host $tmp
break
}
}
else {
$tmp = @{'msDS-OIDToGroupLink'= $group.DistinguishedName}
set-adobject -Identity $OID -Add $tmp
if ($?) {
$tmp = $Errormsg.LinkSuccess
write-host $tmp -Foreground Green
}else{
$tmp = $ErrorMsg.LinkError
write-host $tmp -Foreground Red
}
}

注意

如果您無法執行此指令碼,請嘗試取代 ConvertFrom-StringData 參數之後的單引號。