Making this chunk of code a little cleaner. (Counting values).

I’m working with some values I have in an ADFS configuration. I’m trying to add values back in, based on values I’m pulling back out of a CLIXML file.

Manually, I can do the commands I need all day. I’m wanting to automate the process, but I’m lacking some of the skills to handle what I want to do. Any help is appreciated.

Here is the example of how to add SAMLEndpoints on a ClaimsProviderTrust:

$samlEndpoint1 = New-ADFSSamlEndpoint -Protocol 'SAMLAssertionConsumer' -Uri '' -Binding 'POST' -IsDefault $false -Index 0 $samlEndpoint2 = New-ADFSSamlEndpoint -Protocol 'SAMLAssertionConsumer' -Uri ''' -Binding 'POST' -IsDefault $true -Index 1 $samlEndpoint3 = New-ADFSSamlEndpoint -Protocol 'SAMLLogout' -Uri ''' -ResponseUri ''' -Binding 'Redirect' $samlEndpoint4 = New-ADFSSamlEndpoint -Protocol 'SAMLLogout' -Uri ''' -ResponseUri ''' -Binding 'POST'

Set-ADFSRelyingPartyTrust -TargetName samlpsite3-0 -SamlEndpoint @($samlEndpoint1, $samlEndpoint2, $samlEndpoint3, $samlEndpoint4)

The first lines build the variables, the last line applies them. Easy enough.

The challenge comes in for me, because nothing is static in the configurations, I’m not sure how to automate it in a script.

For example, it could have 1 endpoint, it could have 4 endpoints, etc.

Here is a sample:

Binding : Redirect
BindingUri : urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect
Index : 0
IsDefault : False
Location :
Protocol : SAMLSingleSignOn
ResponseLocation :

Binding : POST
BindingUri : urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST
Index : 0
IsDefault : False
Location :
Protocol : SAMLSingleSignOn
ResponseLocation :

I’m not sure how to determine how to count the endpoints, then add them back in based on the number.

I can get the total count with $v.SamlEndpoints.Count (in this example, it’s 2).

I was going to build several sections of code based on the count # like this:

If ($v.SamlEndpoints.Count -eq 1) {
$samlEndpoint1 = New-ADFSSamlEndpoint -Protocol $v.SamlEndpoints.Protocol -Uri $v.SamlEndpoints.Location -Binding $v.SamlEndpoints.Binding -IsDefault $v.SamlEndpoints.IsDefault -Index $v.SamlEndpoints.Index -ResponseUri $v.SamlEndpoints.ResponseLocation
Set-ADFSRelyingPartyTrust -TargetName samlpsite3-0 -SamlEndpoint @($samlEndpoint1)

ElseIf ($v.SamlEndpoints.Count -eq 2) {
$samlEndpoint1 = New-ADFSSamlEndpoint -Protocol $v.SamlEndpoints.Item(1).Protocol -Uri $v.SamlEndpoints.Item(1).Location -Binding $v.SamlEndpoints.Item(1).Binding -IsDefault $v.SamlEndpoints.Item(1).IsDefault -Index $v.SamlEndpoints.Item(1).Index -ResponseUri $v.SamlEndpoints.Item(1).ResponseLocation
$samlEndpoint1 = New-ADFSSamlEndpoint -Protocol $v.SamlEndpoints.Item(2).Protocol -Uri $v.SamlEndpoints.Item(2).Location -Binding $v.SamlEndpoints.Item(2).Binding -IsDefault $v.SamlEndpoints.Item(2).IsDefault -Index $v.SamlEndpoints.Item(2).Index -ResponseUri $v.SamlEndpoints.Item(2).ResponseLocation
Set-ADFSRelyingPartyTrust -TargetName samlpsite3-0 -SamlEndpoint @($samlEndpoint1, $samlEndpoint2)

Although I think that will work, it seems like there is a better way. Any suggestions?

I haven’t used the ADFS cmdlets you’re using, so I can’t say at this point whether there are any problems with that syntax. It looks like all you need is a foreach loop, though:

foreach ($endpoint in $v.SamlEndpoints)
    $samlEndpoint = New-ADFSSamlEndpoint -Protocol $endpoint.Protocol -Uri $endpoint.Location -Binding $endpoint.Binding -IsDefault $endpoint.IsDefault -Index $endpoint.Index -ResponseUri $endpoint.ResponseLocation    
    Set-ADFSRelyingPartyTrust -TargetName samlpsite3-0 -SamlEndpoint $samlEndpoint

This still looks a bit odd to me, though… $v.SamlEndpoints looks like it might already be a collection of the same types of objects returned by New-ADFSSamlEndpoint. If so, you could even ditch the loop and just do this with one command:

Set-ADFSRelyingPartyTrust -TargetName samlpsite3-0 -SamlEndpoint $v.SamlEndpoints

Actually, the way I wrote the foreach loop may not work, as it’s not exactly what you were doing with multiple endpoints (in my example, there was a separate call to Set-ADFSRelyingPartyTrust for each endpoint, instead of one call that passes in the whole list).

I’m not sure if that difference will matter, but just in case it does, here’s a way to use a foreach loop and still only make a single call to Set-ADFSRelyingPartyTrust (assuming you can’t just pass $v.SamlEndpoints to the cmdlet, as I mentioned). There are several ways you could write this to get identical results; this one just required the fewest changes to what I had already posted:

$endpoints = foreach ($endpoint in $v.SamlEndpoints)
    New-ADFSSamlEndpoint -Protocol $endpoint.Protocol -Uri $endpoint.Location -Binding $endpoint.Binding -IsDefault $endpoint.IsDefault -Index $endpoint.Index -ResponseUri $endpoint.ResponseLocation    

Set-ADFSRelyingPartyTrust -TargetName samlpsite3-0 -SamlEndpoint $endpoints

Thanks so much! That worked perfectly. Just incase anyone is looking for a way to export/import a Claims Provider Trust on AD FS 2.x, in full, here is my script I finished.

Created with: SAPIEN Technologies, Inc., PowerShell Studio 2012 v3.1.22

Created on: 8/30/2013 3:27 PM

Created by: Troy D. Helms

Filename: Import-CPTrust.ps1


#Imports the PS Object in full from an export file made using the following line:

Get-ADFSClaimProviderTrust -name “CPTrustName” | Export-CLIXML ExportedClaimsProviderTrust.xml

$CPTrust = Import-Clixml ExportedClaimsProviderTrust.xml

#Creates the “stub” ClaimsProviderTrust in ADFS with the most basic values. (It also puts in all TokenSigningCertificates at once!)
Add-ADFSClaimsProviderTrust -Identifier $CPTrust.Identifier -Name $CPTrust.Name -TokenSigningCertificate $CPTrust.TokenSigningCertificates

#Each of the following lines sets the values for the ClaimsProviderTrust if they aren’t null to match the original export.
If ($CPTrust.AcceptanceTransformRules) {Set-ADFSClaimsProviderTrust -TargetName $ -AcceptanceTransformRules $CPTrust.AcceptanceTransformRules}
If ($CPTrust.AllowCreate) {Set-ADFSClaimsProviderTrust -TargetName $ -AllowCreate $CPTrust.AllowCreate}
If ($CPTrust.EncryptedNameIdRequired) {Set-ADFSClaimsProviderTrust -TargetName $ -EncryptedNameIdRequired $CPTrust.EncryptedNameIdRequired}
If ($CPTrust.EncryptionCertificate) {Set-ADFSClaimsProviderTrust -TargetName $ -EncryptionCertificate $CPTrust.EncryptionCertificate}
If ($CPTrust.EncryptionCertificateRevocationCheck) {Set-ADFSClaimsProviderTrust -TargetName $ -EncryptionCertificateRevocationCheck $CPTrust.EncryptionCertificateRevocationCheck}
If ($CPTrust.MetadataUrl) {Set-ADFSClaimsProviderTrust -TargetName $ -MetadataUrl $CPTrust.MetadataUrl}
If ($CPTrust.MonitoringEnabled) {Set-ADFSClaimsProviderTrust -TargetName $ -MonitoringEnabled $CPTrust.MonitoringEnabled}
If ($CPTrust.Notes) {Set-ADFSClaimsProviderTrust -TargetName $ -Notes $CPTrust.Notes}
If ($CPTrust.ProtocolProfile) {Set-ADFSClaimsProviderTrust -TargetName $ -ProtocolProfile $CPTrust.ProtocolProfile}
If ($CPTrust.RequiredNameIdFormat) {Set-ADFSClaimsProviderTrust -TargetName $ -RequiredNameIdFormat $CPTrust.RequiredNameIdFormat}
If ($CPTrust.SamlAuthenticationRequestIndex) {Set-ADFSClaimsProviderTrust -TargetName $ -SamlAuthenticationRequestIndex $CPTrust.SamlAuthenticationRequestIndex}
If ($CPTrust.SamlAuthenticationRequestParameters) {Set-ADFSClaimsProviderTrust -TargetName $ -SamlAuthenticationRequestParameters $CPTrust.SamlAuthenticationRequestParameters}
If ($CPTrust.SamlAuthenticationRequestProtocolBinding) {Set-ADFSClaimsProviderTrust -TargetName $ -SamlAuthenticationRequestProtocolBinding $CPTrust.SamlAuthenticationRequestProtocolBinding}
If ($CPTrust.SignatureAlgorithm) {Set-ADFSClaimsProviderTrust -TargetName $ -SignatureAlgorithm $CPTrust.SignatureAlgorithm}
If ($CPTrust.SignedSamlRequestsRequired) {Set-ADFSClaimsProviderTrust -TargetName $ -SignedSamlRequestsRequired $CPTrust.SignedSamlRequestsRequired}
If ($CPTrust.SigningCertificateRevocationCheck) {Set-ADFSClaimsProviderTrust -TargetName $ -SigningCertificateRevocationCheck $CPTrust.SigningCertificateRevocationCheck}
If ($CPTrust.WSFedEndpoint) {Set-ADFSClaimsProviderTrust -TargetName $ -WSFedEndpoint $CPTrust.WSFedEndpoint}

#This creates the SAMLEndpoints if there are any.
If ($CPTrust.SamlEndpoints) {
$endpoints = foreach ($endpoint in $CPTrust.SamlEndpoints) {New-ADFSSamlEndpoint -Protocol $endpoint.Protocol -Uri $endpoint.Location -Binding $endpoint.Binding -IsDefault $endpoint.IsDefault -Index $endpoint.Index -ResponseUri $endpoint.ResponseLocation}

Set-ADFSClaimsProviderTrust -TargetName $ -SamlEndpoint $endpoints

#The only values I have yet to understand how to migrate on a ClaimsProviderTrust is the ClaimsOffered & the Organization data.
#Claims offered SHOULD work using something like this line:
#If ($CPTrust.ClaimsOffered) {Set-ADFSClaimsProviderTrust -TargetName $ -ClaimOffered $CPTrust.ClaimsOffered}
#However, I can’t make it work. Lots of trial and error, with no success. It’s not important for what I’m doing, but it would be nice to handle it.
#Organization information doesn’t seem to have a parameter on the Set-ADFSClaimsProviderTrust cmdlet to actually add it.
#I considered tossing that information into the NOTES section, since it’s informational only anyway.

Two suggestions for you. First, look at the help for Set-ADFSClaimsProviderTrust. As an example, look at ‘Get-Help Copy-Item -Full’ and pay attention to Accept pipeline input. If it shows True, by property name, then you can pass the object directly to the command (i.e. $CPTrust | Set-ADFSClaimsProviderTrust). The cmdlet should eliminate null values and process the passed params if the columns match the parameters (or Alias).

-Path <String[]>
    Specifies the path to the items to copy.
    Required?                    true
    Position?                    1
    Default value                
    Accept pipeline input?       <strong>true (ByValue, ByPropertyName)</strong> 
    Accept wildcard characters?  false

Second suggestion if the cmdlet does NOT accept pipeline, use a splat and run a single command for the targetname versus running a command for each parameter:

PS C:\Windows\system32> 
#Empty object to emulate data
#Note the different properties populated with null values
$CPTrust = @()
$CPTrust += New-Object –TypeName PSObject -Property `
            'AcceptanceTransformRules'= "rule";
            'AllowCreate'= "True";
            'EncryptedNameIdRequired'= $null;
            'EncryptionCertificate'= $null;
            'EncryptionCertificateRevocationCheck'= $null;
            'MetadataUrl'= $null;
            'MonitoringEnabled'= $null;
            'Notes'= "Example Splat";
            'ProtocolProfile'= "4";
            'RequiredNameIdFormat'= $null;
            'SamlAuthenticationRequestIndex'= $null;
            'SamlAuthenticationRequestParameters'= $null;
            'SamlAuthenticationRequestProtocolBinding'= $null;
            'SignatureAlgorithm'= "E=Mc2";
            'SignedSamlRequestsRequired'= "True";
            'SigningCertificateRevocationCheck'= "False";
            'WSFedEndpoint'= "MyEndPoint";})

$CPTrust += New-Object –TypeName PSObject -Property `
            'AcceptanceTransformRules'= "anotherrule";
            'AllowCreate'= $null;
            'EncryptedNameIdRequired'= "True";
            'EncryptionCertificate'= $null;
            'EncryptionCertificateRevocationCheck'= "False";
            'MetadataUrl'= "";
            'MonitoringEnabled'= $null;
            'Notes'= $null;
            'ProtocolProfile'= $null;
            'RequiredNameIdFormat'= $null;
            'SamlAuthenticationRequestIndex'= "2";
            'SamlAuthenticationRequestParameters'= $null;
            'SamlAuthenticationRequestProtocolBinding'= $null;
            'SignatureAlgorithm'= "E=Mc2";
            'SignedSamlRequestsRequired'= "True";
            'SigningCertificateRevocationCheck'= "False";
            'WSFedEndpoint'= "MyEndPoint";})

foreach ($row in $CPTrust) { 
    #Create empty hash table for Splatting
    $params = @{}
    foreach ($column in $row.PSObject.Properties) {
        #if the value is not null, add it to the Splat hash table
        if ($column.Value) {$params.add($column.Name,$column.Value)}
    #Set-ADFSClaimsProviderTrust $params

Name                           Value                                                                                                                                                                     
----                           -----                                                                                                                                                                     
TargetName                     MyTarget1                                                                                                                                                                 
SignatureAlgorithm             E=Mc2                                                                                                                                                                     
WSFedEndpoint                  MyEndPoint                                                                                                                                                                
Notes                          Example Splat                                                                                                                                                             
SigningCertificateRevocatio... False                                                                                                                                                                     
AcceptanceTransformRules       rule                                                                                                                                                                      
SignedSamlRequestsRequired     True                                                                                                                                                                      
AllowCreate                    True                                                                                                                                                                      
ProtocolProfile                4                                                                                                                                                                         

TargetName                     MyTarget2                                                                                                                                                                 
SamlAuthenticationRequestIndex 2                                                                                                                                                                         
SignatureAlgorithm             E=Mc2                                                                                                                                                                     
WSFedEndpoint                  MyEndPoint                                                                                                                                                                
EncryptedNameIdRequired        True                                                                                                                                                                      
SigningCertificateRevocatio... False                                                                                                                                                                     
AcceptanceTransformRules       anotherrule                                                                                                                                                               
SignedSamlRequestsRequired     True                                                                                                                                                                      
EncryptionCertificateRevoca... False