--- title: Scripts for Certificate Issuance Policies in Credential Guard (Windows 10) description: Scripts listed in this topic for obtaining the available issuance policies on the certificate authority for Credential Guard on Windows 10. ms.prod: w10 ms.mktglfcycl: explore ms.sitesec: library ms.pagetype: security localizationpriority: high author: brianlic-msft --- # Credential Guard: Scripts for Certificate Authority Issuance Policies Here is a list of scripts mentioned in this topic. ## Get the available issuance policies on the certificate authority Save this script file as get-IssuancePolicy.ps1. ``` syntax ####################################### ## 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: 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:. 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 } } ``` > [!NOTE] > If you're having trouble running this script, try replacing the single quote after the ConvertFrom-StringData parameter.   ## Link an issuance policy to a group Save the script file as set-IssuancePolicyToGroupLink.ps1. ``` syntax ####################################### ## 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: help5 = -groupName:. 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:. 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 } } ``` > [!NOTE] > If you're having trouble running this script, try replacing the single quote after the ConvertFrom-StringData parameter.