その他の軽減策

Credential Guard では、派生資格情報に対する攻撃に対する軽減策が提供され、盗まれた資格情報が他の場所で使用されるのを防ぎます。 ただし、派生資格情報が Credential Guard によって保護されている場合でも、デバイスは特定の攻撃に対して脆弱な場合があります。 これらの攻撃には、特権の悪用や、侵害されたデバイスからの派生資格情報の直接の使用、Credential Guard を有効にする前に盗まれた資格情報の再利用、管理ツールと脆弱なアプリケーション構成の悪用などがあります。 このため、ドメイン環境をより堅牢にするために、追加の軽減策もデプロイする必要があります。

その他のセキュリティ資格

ハードウェア、ファームウェア、およびソフトウェアのベースライン保護を満たすすべてのデバイスで、Credential Guard を使用できます。
より多くの資格を満たすデバイスは、攻撃対象領域をさらに減らすために追加の保護を提供できます。

次の表に、セキュリティを強化するための修飾を示します。 Credential Guard が提供できるセキュリティのレベルを強化するために、追加の資格を満たすことをお勧めします。

保護 要件 セキュリティ上のメリット
セキュア ブートの構成と管理 - BIOS パスワードまたはより強力な認証をサポート
する必要があります - BIOS 構成では、BIOS 認証を設定
する必要があります- 許可されるブート デバイスの一覧 (たとえば、内部ハード ドライブからのブートのみ) とブート デバイスの順序を構成するための保護された BIOS オプションのサポートが必要です。オペレーティング システムによって行われた変更をオーバーライドしますBOOTORDER
- 他のオペレーティング システムの起動を禁止する
-BIOS 設定の変更を防止する
ハードウェア ルート信頼プラットフォームのセキュリティで保護されたブート - ブート整合性 (プラットフォーム セキュア ブート) がサポートされている必要があります。 「System.Fundamentals.Firmware.CS.UEFISecureBoot.ConnectedStandby
- ハードウェア セキュリティ テスト インターフェイス (HSTI) を実装する必要がある」の「Windows ハードウェア互換性プログラムの要件」を参照してください。 「ハードウェア セキュリティのテスト可能性の仕様」を参照してください
- 電源投入時からのブート整合性 (プラットフォームのセキュア ブート) によって、実際の攻撃者に対する保護やマルウェアに対する多層防御が実現されます。
- HSTI は、正しくセキュリティで保護されたシリコンとプラットフォームのセキュリティ保証を提供します
Windows Updateによるファームウェアの更新 - ファームウェアは、Windows Updateと UEFI カプセル化更新プログラムを使用したフィールド更新をサポートする必要があります 迅速、安全、かつ信頼性の高いファームウェア更新を実行できます。
ブート構成と管理のセキュリティ保護 - 必要な BIOS 機能: OEM が製造時
にセキュア ブート DB に ISV、OEM、またはエンタープライズ証明書を追加する機能 - 必要な構成: Microsoft UEFI CA を Secure Boot DB から削除する必要があります。 サード パーティの UEFI モジュールのサポートは許可されていますが、特定の UEFI ソフトウェアに ISV が提供する証明書または OEM 証明書を使用する必要があります
- エンタープライズは、独自の EFI ドライバー/アプリケーションの実行
を許可することができます - Secure Boot DB から Microsoft UEFI CA を削除すると、オペレーティング システムが起動する前に実行されるソフトウェアを完全に制御できます
UEFI ランタイム サービスの No-Execute (NX) 保護の VBS 有効化 - VBS では、UEFI ランタイム サービス コードとデータ メモリ領域で NX 保護が有効になります。 UEFI ランタイム サービス コードが読み取り専用のページ保護をサポートする必要があります。UEFI ランタイム サービス データを実行可能にすることはできません。 UEFI ランタイム サービスは、次の要件を満たす必要があります。
- UEFI 2.6 EFI_MEMORY_ATTRIBUTES_TABLEを実装します。 すべての UEFI ランタイム サービス メモリ (コードとデータ) は、この表
で説明する必要があります。PE セクションはメモリ内でページアラインされている必要があります (不揮発性ストレージでは必要ありません)。
- メモリ属性テーブルは、OS
による構成に関するコードとデータRO/NXを正しくマークする必要があります。すべてのエントリには、属性、、EFI_MEMORY_XPまたはその両方をEFI_MEMORY_RO含める必要があります。
- 上記のどちらの属性も含めず、実行可能と書き込み可能の両方のメモリを示すエントリは残されません。 メモリは、読み取り可能で実行可能であるか、書き込み可能で実行可能
でない必要があります (このテーブルの後の重要な情報を参照してください)
- UEFI ランタイムの脆弱性がある場合、VBS の侵害がブロックされます ( UpdateCapsuleSetVariable などの関数など)
- システム ファームウェアから VBS への攻撃対象を減らします。
SMM 保護のファームウェアサポート - Windows SMM セキュリティ軽減策テーブル (WSMT) 仕様 には、Windows 仮想化ベースの機能をサポートする Windows オペレーティング システムで使用するために作成された ACPI テーブルの詳細が含まれています。 - UEFI ランタイム サービスの潜在的な脆弱性 (存在する場合) から保護し、VBS の侵害をブロックします (UpdateCapsule や SetVariable などの関数など)
- システム ファームウェアから攻撃対象領域を VBS に減らす
- SMM に対する追加のセキュリティ攻撃をブロックする

重要

UEFI ランタイム サービスの NX 保護の VBS 有効化について:

  • これは UEFI ランタイム サービス メモリにのみ適用され、UEFI ブート サービス メモリには適用されません
  • 保護は、OS ページ テーブルに VBS によって適用されます
  • 書き込み可能なセクションと実行可能なセクションを使用しないでください
  • 実行可能システム メモリを直接変更しないでください
  • 動的コードを使用しない

ドメイン ユーザーを特定のドメイン参加済みデバイスに制限する

資格情報の盗難攻撃を行うことで、攻撃者は 1 つのデバイスからシークレットを盗み、そのシークレットを別のデバイスから使用できるようにます。 ユーザーが複数のデバイスにサインインできる場合、すべてのデバイスを使用して、資格情報を盗むことができます。 Credential Guard が有効になっているデバイスでのみユーザーがサインオンするようにするにはどうすればよいですか? Credential Guard で構成されている特定のドメイン参加済みデバイスに制限する認証ポリシーを展開します。 ユーザーがどのデバイスからサインオンするかを認識するドメイン コントローラーでは、Kerberos 防御を使用する必要があります。

Kerberos 防御

Kerberos 防御は、RFC 6113 の一部です。 デバイスが Kerberos 防御をサポートしている場合、その TGT を使用して、ユーザーの所有権の証明を保護し、オフライン辞書攻撃を軽減することができます。 Kerberos 防御は、さらに署名済み KDC エラーという利点も備えています。これにより、ダウングレード攻撃などの改ざんによる脅威が軽減されます。

ドメイン ユーザーを特定のドメイン参加済みデバイスに制限するために Kerberos 防御を有効にするには:

  • ユーザーは、Windows Server 2012 R2 以降を実行しているドメインに参加している必要があります。
  • これらのドメイン内のすべてのドメイン コントローラーは、Kerberos 防御をサポートするように構成されている必要があります。 [KDC で信頼性情報、複合認証、および Kerberos 防御をサポートする] グループ ポリシー設定を、[サポート] または [常に信頼性情報を提供する] に設定します。
  • ユーザーが Kerberos の防御をサポートするように構成する必要がある、Credential Guard を持つすべてのデバイス。 [コンピューターの構成] -[管理用テンプレート] ->>[System> -Kerberos] で、要求、複合認証、Kerberos 防御グループ ポリシー設定に対して Kerberos クライアントのサポートを有効にします。

ドメイン参加済みデバイス シークレットを保護する

ドメインに参加しているデバイスは認証用の共有シークレットも使用しているため、攻撃者はそれらのシークレットも盗むことができます。 Credential Guard と共にデバイス証明書を展開することによって、秘密キーを保護できます。 その後、認証ポリシーでは、ユーザーがこれらの証明書を使用して認証するデバイスにサインオンする必要があります。 これにより、デバイスから盗まれた共有シークレットを、盗まれたユーザー資格情報と共に使用して、ユーザーとしてサインオンすることを防止します。

ドメインに参加しているデバイスの証明書の認証には、次の要件があります。

  • デバイスのアカウントが、Windows Server 2012 のドメインの機能レベル、またはそれ以上のドメインに属している。
  • それらのドメイン内のすべてのドメイン コント ローラーが、厳密な KDC 証明書の検証要件を満たす KDC 証明書を備えている。
    • KDC EKU が存在する
    • DNS ドメイン名が SubjectAltName (SAN) 拡張の DNSName フィールドと一致する
  • Windows デバイスには、エンタープライズ ストアでドメイン コントローラー証明書を発行する CA があります。
  • ユーザーにスマート カードを発行する前にユーザーの ID と信頼性を確立する方法と同様の方法で、デバイスの ID と信頼性を確認するためのプロセスが確立されている。

ドメイン参加済みデバイス証明書を展開する

必要な発行ポリシーを持つ証明書が、ユーザーが使用する必要があるデバイスにのみインストールされるようにするには、それらの証明書を各デバイスに手動で展開する必要があります。 そのためには、ユーザーにスマート カードを発行する際に実行する手順と同じセキュリティ手順を、デバイスの証明書に適用する必要があります。

たとえば、これらのデバイスに対してのみ高保証ポリシーを使用するとします。 Windows Server Enterprise 証明機関を使用して、新しいテンプレートを作成します。

新しい証明書テンプレートを作成する

  1. Certificate Manager コンソールで、[証明書テンプレートの>管理] を右クリックします。
  2. [ワークステーション認証>の重複テンプレート] を右クリックします
  3. 新しいテンプレートを右クリックし、[プロパティ] を選択します
  4. [拡張機能] タブで、[アプリケーション ポリシーの>編集] を選択します
  5. [ クライアント認証] を選択し、[削除] を選択 します
  6. ID-PKInit-KPClientAuth EKU を追加します。 [新規追加] を>選択し、次の値を指定します。
    • 名前: Kerberos Client Auth
    • オブジェクト識別子: 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 のドメイン コント ローラーでは、これらの OID を要求にマップできます。 認証メカニズム保証について詳しくは、TechNet の「Authentication Mechanism Assurance for AD DS in Windows Server 2008 R2 Step-by-Step Guide」(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. [ユーザー、コンピューター、またはサービス アカウントの選択] ダイアログ ボックスで、制限するユーザー アカウントの名前を入力し、[OK] を選択します
  6. [ ユーザー サインオン ] 見出しで、[ 編集 ] ボタンを選択します
  7. [ 条件の追加] を選択します
  8. [Access Control条件の編集] ボックスで、各>値の [ユーザー > グループ > メンバー] が読み取られるようにし、[項目の追加] を選択します。
  9. [ユーザー、コンピューター、またはサービス アカウントの選択] ダイアログ ボックスで、set-IssuancePolicyToGroupLink スクリプトで作成したユニバーサル セキュリティ グループの名前を入力し、[OK] を選択します
  10. [OK] を選択して [Access Control条件の編集] ボックスを閉じます
  11. [ OK] を 選択して認証ポリシーを作成します
  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 パラメーターの後の単一引用符を置き換えてみてください。