AD FS 2.0: Bulk Add Trust Relationships and Claim Rules for Testing
Overview
Included in this article is a Powershell script sample which allows bulk additions and deletions of test Claims Provider Trusts, Relying Party Trusts, and Claim Rules. These test trust relationships and claim rules may be useful for web testing in a lab environment.
Usage
Be sure to utilize Set-ExecutionPolicy to allow execution of Powershell scripts on your system.
Example
Set-ExecutionPolicy Unrestricted
Execute ADFS20BulkTestTrusts.ps1 from an administrative Powershell console window.
The prompts will ask which item type you would like to work with and how you would like to work with that item.
Example of adding 10 CP Trusts:
Note: Adding CP Trusts can take a considerable amount of time due to the certificate work the script performs when adding CP Trusts.
Example of removing 100 RP Trusts:
Example of adding 1000 Claim Rules to 100 RP Trusts:
Sample Code
Note: This sample is provided AS-IS with no warranties and confers no rights. This sample is meant for testing purposes in a development environment, and should never be executed in a production environment.
Paste the following code sample into a text editor and save as ADFS20BulkTestTrusts.ps1:
#SCRIPT TITLE - ADFS20BulkTestTrusts.ps1
#AUTHOR - Adam Conkle - Microsoft Corporation
#VERSION 1.0
#Write header info to the screen
Write-Host "`n AD FS 2.0: Add or Remove Bulk Test Claims Provider Trusts, Relying Party Trusts or Claim Rules"
Write-Host "`n IMPORTANT: This sample is provided AS-IS with no warranties and confers no rights." -ForegroundColor "yellow"
Write-Host "`n Trusts and rules will be created and removed following the naming convention: `"TestXY`","
Write-Host " where X = the number of trusts or rules you would like to add or remove,"
Write-Host " and Y = CP, RP, or Rule."
Write-Host "`n`tExample`n`tYou select options to add 3 RP trusts, and the result is`:"
Write-Host "`t`"Test1RP`", `"Test2RP`", `"Test3RP`"`n"
#Ignore errors and proceed
$ErrorActionPreference = "SilentlyContinue"
#Add the AD FS 2.0 PSH snap-in. Exit if it fails
If (!((Get-PSSnapin Microsoft.Adfs.Powershell).Name))
{
Write-Host " The AD FS 2.0 snap-in is not loaded`n`tAttempting to load it"
Add-PSSnapin Microsoft.Adfs.Powershell
If ((Get-PSSnapin Microsoft.Adfs.Powershell).Name)
{
Write-Host "`tSuccess" -ForeGroundColor "green"
}
Else
{
Write-Host "`tFailed to load AD FS 2.0 snap-in`n`tExiting" -ForeGroundColor "red"
Exit
}
}
#Initialize vars
$CPRPRule = "foo"
$AddorRemove = "foo"
$Iterations = 0
#Prompt for modification type
Write-Host " CP, RP, or Rule`?" -NoNewline
#allow for short-hand input
While (($CPRPRule -ne "CP") -and ($CPRPRule -ne "RP") -and ($CPRPRule -ne "C") -and ($CPRPRule -ne "R") -and ($CPRPRule -ne "Rule") -and ($CPRPRule -ne "CR") -and ($CPRPRule -ne "X"))
{
$CPRPRule = Read-Host " (CP/RP/Rule or X to exit)"
}
#Fix short-hand input
If (($CPRPRule -eq "C") -or ($CPRPRule -eq "R"))
{
$CPRPRule += "P"
}
ElseIf (($CPRPRule -eq "CR") -or ($CPRPRule -eq "Rule"))
{
$CPRPRule = "claim rule"
}
ElseIf ($CPRPRule -eq "X")
{
Write-Host " Exiting`n" -ForegroundColor "red"
Exit
}
$CPRPRule = ($CPRPRule).ToUpper()
#Prompt for add or remove
Write-Host " Add or Remove`?" -NoNewline
#Allow short-hand input
While (($AddorRemove -ne "Add") -and ($AddorRemove -ne "Remove") -and ($AddorRemove -ne "A") -and ($AddorRemove -ne "R") -and ($AddorRemove -ne "X"))
{
$AddorRemove = Read-Host " (Add/Remove or X to exit)"
}
#Fix short-hand input
If ($AddorRemove -eq "A")
{
$AddorRemove += "dd"
}
ElseIf ($AddorRemove -eq "R")
{
$AddorRemove += "emove"
}
ElseIf ($AddorRemove -eq "X")
{
Write-Host " Exiting`n" -ForegroundColor "red"
Exit
}
#If adding/removing claim rules, we need to know what they want to modify
#Options include: CP, RP, or the built-in AD CP Trust
If ($CPRPRule -eq "Claim Rule")
{
$RuleAction = "foo"
#Capitalize first letter to make it look nice
$AddorRemove = $AddorRemove.Replace($AddorRemove.Substring(0,1),($AddorRemove.Substring(0,1).ToUpper()))
Write-Host " $AddorRemove claim rules where`?" -NoNewline
#Allow short-hand input
While (($RuleAction -ne "ADCP") -and ($RuleAction -ne "CP") -and ($RuleAction -ne "RP") -and ($RuleAction -ne "AD") -and ($RuleAction -ne "C") -and ($RuleAction -ne "R") -and ($RuleAction -ne "A") -and ($RuleAction -ne "X"))
{
$RuleAction = Read-Host " (CP/RP/ADCP or X to exit)"
}
#Fix short-hand input
If (($RuleAction -eq "C") -or ($RuleAction -eq "R"))
{
$RuleAction += "P"
}
ElseIf (($RuleAction -eq "AD") -or ($RuleAction -eq "A"))
{
$RuleAction = "ADCP"
}
ElseIf ($RuleAction -eq "X")
{
Write-Host " Exiting`n" -ForegroundColor "red"
Exit
}
$RuleAction = $RuleAction.ToUpper()
#Prompt for number of CP or RP test trusts they would like to modify
#Does not apply to the built-in AD CP Trust since there is only one
If ($RuleAction -ne "ADCP")
{
$AddorRemove = $AddorRemove.ToLower()
Write-Host " How many $RuleAction would you like to $AddorRemove rules for`?" -NoNewline
$RuleIterations = Read-Host " (integer)"
while ($RuleIterations -notmatch "^\d+$")
{
$RuleIterations = Read-Host " (integer)"
}
}
}
#Prompt for number of objects they would like to add/remove
If ($CPRPRule -eq "claim rule") {$CPRPRule = $CPRPRule.ToLower()}
Write-Host " How many $CPRPRule would you like to $AddorRemove`?" -NoNewline
#Check for integer input
$Iterations = Read-Host " (integer)"
while ($Iterations -notmatch "^\d+$")
{
$Iterations = Read-Host " (integer)"
}
#Notify the user about the work to be done
If ($CPRPRule -eq "claim rule") {$CPRPRule = $CPRPRule.ToLower()}
If ($AddorRemove -eq "Add")
{
Write-Host " Adding $Iterations $CPRPRule"
}
Else
{
Write-Host " Removing $Iterations $CPRPRule"
}
#Add CP Trusts
If (($CPRPRule -eq "CP") -and ($AddorRemove -eq "Add"))
{
For ($Count = 1; $Count -le $Iterations; $Count++)
{
#Generate cert in local computer My store
$name = new-object -com "X509Enrollment.CX500DistinguishedName.1"
$name.Encode("CN=DO_NOT_TRUST_Test"+$Count+"CP", 0)
$key = new-object -com "X509Enrollment.CX509PrivateKey.1"
$key.ProviderName = "Microsoft RSA SChannel Cryptographic Provider"
$key.KeySpec = 1
$key.Length = 2048
$key.SecurityDescriptor = "D:PAI(A;;0xd01f01ff;;;SY)(A;;0xd01f01ff;;;BA)(A;;0x80120089;;;NS)"
$key.MachineContext = 1
$key.Create()
$serverauthoid = new-object -com "X509Enrollment.CObjectId.1"
$serverauthoid.InitializeFromValue("1.3.6.1.5.5.7.3.1")
$ekuoids = new-object -com "X509Enrollment.CObjectIds.1"
$ekuoids.add($serverauthoid)
$ekuext = new-object -com "X509Enrollment.CX509ExtensionEnhancedKeyUsage.1"
$ekuext.InitializeEncode($ekuoids)
$cert = new-object -com "X509Enrollment.CX509CertificateRequestCertificate.1"
$cert.InitializeFromPrivateKey(2, $key, "")
$cert.Subject = $name
$cert.Issuer = $cert.Subject
$cert.NotBefore = get-date
$cert.NotAfter = $cert.NotBefore.AddDays(365)
$cert.X509Extensions.Add($ekuext)
$cert.Encode()
$enrollment = new-object -com "X509Enrollment.CX509Enrollment.1"
$enrollment.InitializeFromRequest($cert)
$certdata = $enrollment.CreateRequest(0)
$enrollment.InstallResponse(2, $certdata, 0, "")
$Cert = @(dir cert: -Recurse | Where-Object { $_.subject -match "DO_NOT_TRUST_Test"+$Count+"CP" })[0]
#Add the new CP Trust using the new cert and name
$URI = "urn`:test`:test"+$Count+"CP"
$TrustName = "Test"+$Count+"CP"
Add-ADFSClaimsProviderTrust -Identifier $URI -Name $TrustName -TokenSigningCertificate $Cert
}
#Clean up the certs from the local machine My store
$store = new-object system.security.cryptography.x509certificates.x509Store 'My', 'LocalMachine'
$store.Open('ReadWrite')
$Certs = @(dir cert: -Recurse | Where-Object { $_.subject -like "*DO_NOT_TRUST_Test*" })
foreach ($cert in $certs) {$store.Remove($cert)}
$store.Close()
}
#Remove CP Trusts
ElseIf (($CPRPRule -eq "CP") -and ($AddorRemove -eq "Remove"))
{
For ($Count = 1; $Count -le $Iterations; $Count++)
{
$TrustName = "Test"+$Count+"CP"
Remove-ADFSClaimsProviderTrust -TargetName $TrustName
}
}
#Add RP Trusts
ElseIf (($CPRPRule -eq "RP") -and ($AddorRemove -eq "Add"))
{
For ($Count = 1; $Count -le $Iterations; $Count++)
{
$URI = "urn`:test`:test"+$Count+"RP"
$TrustName = "Test"+$Count+"RP"
Add-ADFSRelyingPartyTrust -Identifier $URI -Name $TrustName
}
}
#Remove RP Trusts
ElseIf (($CPRPRule -eq "RP") -and ($AddorRemove -eq "Remove"))
{
For ($Count = 1; $Count -le $Iterations; $Count++)
{
$TrustName = "Test"+$Count+"RP"
Remove-ADFSRelyingPartyTrust -TargetName $TrustName
}
}
#Add claim rule
ElseIf (($CPRPRule -eq "Claim Rule") -and ($AddorRemove -eq "Add"))
{
#Add claim rule for CP
If ($RuleAction -eq "CP")
{
#Loop through trusts
For ($TrustCount = 1; $TrustCount -le $RuleIterations; $TrustCount++)
{
#Get the original rule set to file
$RulesFile = "$env:TEMP\Test"+$TrustCount+"CP_Rules.txt"
$TrustName = "Test"+$TrustCount+"CP"
(Get-ADFSClaimsProviderTrust -Name $TrustName).AcceptanceTransformRules | Out-File $RulesFile
#Loop through number of rules and append to the original set
For ($RuleCount = 1; $RuleCount -le $Iterations; $RuleCount++)
{
$RuleName = "Test"+$RuleCount+"Rule"
"`@RuleName `= `"$RuleName`"
c`:`[Type == `"http://schemas.contoso.com/claims/test/ClaimType$RuleCount`"`]
`=`> issue`(claim `= c`)`;" | Out-File $RulesFile -Append
}
#Set the new rules to the trust
$TrustName = "Test"+$TrustCount+"CP"
Set-ADFSClaimsProviderTrust -TargetName $TrustName -AcceptanceTransformRulesFile $RulesFile
#Clean up
Remove-Item $RulesFile
}
}
#Add claim rule for RP
ElseIf ($RuleAction -eq "RP")
{
#Loop through trusts
For ($TrustCount = 1; $TrustCount -le $RuleIterations; $TrustCount++)
{
#Get original rule set to file
$RulesFile = "$env:TEMP\Test"+$TrustCount+"RP_Rules.txt"
$TrustName = "Test"+$TrustCount+"RP"
(Get-ADFSRelyingPartyTrust -Name $TrustName).IssuanceTransformRules | Out-File $RulesFile
#Loop through number of rules and append to the original set
For ($RuleCount = 1; $RuleCount -le $Iterations; $RuleCount++)
{
$RuleName = "Test"+$RuleCount+"Rule"
"`@RuleName `= `"$RuleName`"
c`:`[Type == `"http://schemas.contoso.com/claims/test/ClaimType$RuleCount`"`]
`=`> issue`(claim `= c`)`;" | Out-File $RulesFile -Append
}
#Set the new rules to the trust
$TrustName = "Test"+$TrustCount+"RP"
Set-ADFSRelyingPartyTrust -TargetName $TrustName -IssuanceTransformRulesFile $RulesFile
#Clean up
Remove-Item $RulesFile
}
}
#Add claim rule for the built-in AD CP Trust
ElseIf ($RuleAction -eq "ADCP")
{
#Get the original set of AD CP trust rules to file
$RulesFile = "$env:TEMP\ADCP_Rules.txt"
(Get-ADFSClaimsProviderTrust -Name "Active Directory").AcceptanceTransformRules | Out-File $RulesFile
#Loop through the rules and append to the original set
For ($RuleCount = 1; $RuleCount -le $Iterations; $RuleCount++)
{
$RuleName = "Test"+$RuleCount+"Rule"
"`@RuleName `= `"$RuleName`"
c`:`[Type == `"http://schemas.contoso.com/claims/test/ClaimType$RuleCount`"`]
`=`> issue`(claim `= c`)`;" | Out-File $RulesFile -Append
}
#Set the AD CP Trust with the new rule set
Set-ADFSClaimsProviderTrust -TargetName "Active Directory" -AcceptanceTransformRulesFile $RulesFile
Remove-Item $RulesFile
}
Else
{
#Catch bad options
Write-Host " Invalid action. Exiting`n" -ForegroundColor "red"
Exit
}
}
#Remove claim rules
ElseIf (($CPRPRule -eq "Claim Rule") -and ($AddorRemove -eq "Remove"))
{
#Remove claim rules from CP trusts
If ($RuleAction -eq "CP")
{
#Loop through trusts
For ($TrustCount = 1; $TrustCount -le $RuleIterations; $TrustCount++)
{
#Get the rules into an array
$RulesFile = "$env:TEMP\TestCP"+$TrustCount+"_Rules.txt"
$TrustName = "Test"+$TrustCount+"CP"
$RuleArray = ((Get-ADFSClaimsProviderTrust -Name $TrustName).AcceptanceTransformRules).Split(";")
#Loop through the rule array and add the delimiter back
For ($ElementCount = 0; $ElementCount -lt ($RuleArray.Count)-1; $ElementCount++)
{
$RuleArray[$ElementCount] += ";"
}
#Loop through rule names and add only keep names to a new array
For ($RuleCount = 1; $RuleCount -le $Iterations; $RuleCount++)
{
$RuleArray = $RuleArray | Where {$_ -notmatch "Test"+$RuleCount+"Rule"}
}
#Write the new rule set to file
$RuleArray | Out-File $RulesFile
#Set the new rule set to the trust
$TrustName = "Test"+$TrustCount+"CP"
Set-ADFSClaimsProviderTrust -TargetName $TrustName -AcceptanceTransformRulesFile $RulesFile
#Clean up
Remove-Item $RulesFile
}
}
#Remove claim rules from RP
ElseIf ($RuleAction -eq "RP")
{
#Loop through trusts
For ($TrustCount = 1; $TrustCount -le $RuleIterations; $TrustCount++)
{
#Get current rule set to array
$RulesFile = "$env:TEMP\TestRP"+$TrustCount+"_Rules.txt"
$TrustName = "Test"+$TrustCount+"RP"
$RuleArray = ((Get-ADFSRelyingPartyTrust -Name $TrustName).IssuanceTransformRules).Split(";")
#Loop through the rule array and add the delimiter back
For ($ElementCount = 0; $ElementCount -lt ($RuleArray.Count)-1; $ElementCount++)
{
$RuleArray[$ElementCount] += ";"
}
#Loop through rule names and add only keep names to a new array
For ($RuleCount = 1; $RuleCount -le $Iterations; $RuleCount++)
{
$RuleArray = $RuleArray | Where {$_ -notmatch "Test"+$RuleCount+"Rule"}
}
#Write the new rule set to file
$RuleArray | Out-File $RulesFile
#Set the new rule set to the trust
$TrustName = "Test"+$TrustCount+"RP"
Set-ADFSRelyingPartyTrust -TargetName $TrustName -IssuanceTransformRulesFile $RulesFile
#Clean-up
Remove-Item $RulesFile
}
}
#Remove claim rules from the built-in AD CP Trust
ElseIf ($RuleAction -eq "ADCP")
{
#Get the current rule set to array
$RulesFile = "$env:TEMP\ADCP_Rules.txt"
$RuleArray = ((Get-ADFSClaimsProviderTrust -Name "Active Directory").AcceptanceTransformRules).Split(";")
#Loop through the rule array and add the delimiter back
For ($ElementCount = 0; $ElementCount -lt ($RuleArray.Count)-1; $ElementCount++)
{
$RuleArray[$ElementCount] += ";"
}
#Loop through rule names and add only keep names to a new array
For ($RuleCount = 1; $RuleCount -le $Iterations; $RuleCount++)
{
$RuleArray = $RuleArray | Where {$_ -notmatch "Test"+$RuleCount+"Rule"}
}
#Write the new rule set to file
$RuleArray | Out-File $RulesFile
#Set the new rule set to the trust
Set-ADFSClaimsProviderTrust -TargetName "Active Directory" -AcceptanceTransformRulesFile $RulesFile
#Clean up
Remove-Item $RulesFile
}
Else
{
#Catch bad options
Write-Host " Invalid action. Exiting`n" -ForegroundColor "red"
Exit
}
}
Else
{
#Catch bad input
Write-Host "`tUnsupported input`n`tExiting`n" -ForegroundColor "red"
Exit
}
#Notify
Write-Host "`tDone`n" -ForegroundColor "green"
#################################################