DSCResources/MSFT_SPTrustedSecurityTokenIssuer/MSFT_SPTrustedSecurityTokenIssuer.psm1
$script:SPDscUtilModulePath = Join-Path -Path $PSScriptRoot -ChildPath '..\..\Modules\SharePointDsc.Util' Import-Module -Name $script:SPDscUtilModulePath function Get-TargetResource { [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param ( [Parameter(Mandatory = $true)] [String] $Name, [Parameter()] [String] $Description, [Parameter()] [String] $RegisteredIssuerNameIdentifier, [Parameter()] [String] $RegisteredIssuerNameRealm, [Parameter()] [String] $SigningCertificateThumbprint, [Parameter()] [String] $SigningCertificateFilePath, [Parameter()] [String] $MetadataEndPoint, [Parameter()] [System.Boolean] $IsTrustBroker = $true, [Parameter()] [ValidateSet("Present", "Absent")] [String] $Ensure = "Present", [Parameter()] [System.Management.Automation.PSCredential] $InstallAccount ) Write-Verbose -Message "Getting SPTrustedSecurityTokenIssuer '$Name' settings" $result = Invoke-SPDscCommand -Credential $InstallAccount ` -Arguments @($PSBoundParameters, $MyInvocation.MyCommand.Source) ` -ScriptBlock { $params = $args[0] $eventSource = $args[1] $spTrust = Get-SPTrustedSecurityTokenIssuer -Identity $params.Name ` -ErrorAction SilentlyContinue if ($spTrust) { $description = $spTrust.Description $registeredIssuerNameIdentifier = $spTrust.RegisteredIssuerName.Split("@")[0] $registeredIssuerNameRealm = $spTrust.RegisteredIssuerName.Split("@")[1] $signingCertificateThumbprint = $spTrust.SigningCertificate.Thumbprint $metadataEndPoint = $spTrust.MetadataEndPoint.OriginalString # Get-SPTrustedSecurityTokenIssuer does not return a property IsTrustBroker. But value of property IsSelfIssuer is the complement of IsTrustBroker $isTrustBroker = $false if ($spTrust.IsSelfIssuer -eq $false) { $isTrustBroker = $true } $currentState = "Present" # If the signing certificate is specified to Get method from its filepath, it must be retrieved to compare its thumbprint with # the one set in the SPTrustedSecurityTokenIssuer ($signingCertificateThumbprint) if ($params.SigningCertificateFilePath) { Write-Verbose -Message "Getting signing certificate from file system path '$($params.SigningCertificateFilePath)'" $cert = $null try { $cert = New-Object -TypeName "System.Security.Cryptography.X509Certificates.X509Certificate2" ` -ArgumentList @($params.SigningCertificateFilePath) } catch { $message = ("Signing certificate was not found in path '$($params.SigningCertificateFilePath)'.") Add-SPDscEvent -Message $message ` -EntryType 'Error' ` -EventID 100 ` -Source $eventSource throw $message } if ($cert.Thumbprint -match $signingCertificateThumbprint) { # Signing certificate is conform to the one specified # Set signingCertificateThumbprint and signingCertificateFilePath to same value as passed to Get # so that Test method sees this is conform if (-not $params.SigningCertificateThumbprint) { $signingCertificateThumbprint = $cert.Thumbprint } $signingCertificateFilePath = $params.SigningCertificateFilePath Write-Verbose -Message "Existing signing certificate in SPTrustedSecurityTokenIssuer '$($params.Name)' has the same thumbprint as the signing certificate passed in parameter, as expected." } } # If parameter RegisteredIssuerNameRealm is null, it means that registeredIssuerNameRealm of the existing trust should be equal to the SPAuthenticationRealm if ([string]::IsNullOrEmpty($params.RegisteredIssuerNameRealm)) { $farmAuthenticationRealm = Get-SPAuthenticationRealm if ($registeredIssuerNameRealm -match $farmAuthenticationRealm) { # RegisteredIssuerNameRealm in the SPTrustedSecurityTokenIssuer is conform to expected value (SPAuthenticationRealm) # Set it to $params.RegisteredIssuerNameRealm so that Test method sees this is conform $registeredIssuerNameRealm = $params.RegisteredIssuerNameRealm Write-Verbose -Message "Existing registeredIssuerNameRealm in SPTrustedSecurityTokenIssuer '$($params.Name)' is set with the SPAuthenticationRealm of the farm, as expected." } } } else { $description = "" $registeredIssuerNameIdentifier = "" $registeredIssuerNameRealm = "" $signingCertificateThumbprint = "" $signingCertificateFilePath = "" $metadataEndPoint = "" $isTrustBroker = $false $currentState = "Absent" } return @{ Name = $params.Name Description = $description RegisteredIssuerNameIdentifier = $registeredIssuerNameIdentifier RegisteredIssuerNameRealm = $registeredIssuerNameRealm SigningCertificateThumbprint = $signingCertificateThumbprint SigningCertificateFilePath = $signingCertificateFilePath MetadataEndPoint = $metadataEndPoint IsTrustBroker = $isTrustBroker Ensure = $currentState } } return $result } function Set-TargetResource { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [String] $Name, [Parameter()] [String] $Description, [Parameter()] [String] $RegisteredIssuerNameIdentifier, [Parameter()] [String] $RegisteredIssuerNameRealm, [Parameter()] [String] $SigningCertificateThumbprint, [Parameter()] [String] $SigningCertificateFilePath, [Parameter()] [String] $MetadataEndPoint, [Parameter()] [System.Boolean] $IsTrustBroker = $true, [Parameter()] [ValidateSet("Present", "Absent")] [String] $Ensure = "Present", [Parameter()] [System.Management.Automation.PSCredential] $InstallAccount ) Write-Verbose -Message "Setting SPTrustedSecurityTokenIssuer '$Name' settings" $PSBoundParameters.IsTrustBroker = $IsTrustBroker $CurrentValues = Get-TargetResource @PSBoundParameters if ($Ensure -eq "Present") { if ($PSBoundParameters.ContainsKey("SigningCertificateThumbprint") -and ` $PSBoundParameters.ContainsKey("MetadataEndPoint")) { $message = ("Cannot use both parameters SigningCertificateThumbprint and MetadataEndPoint at the same time.") Add-SPDscEvent -Message $message ` -EntryType 'Error' ` -EventID 100 ` -Source $MyInvocation.MyCommand.Source throw $message } if ($PSBoundParameters.ContainsKey("SigningCertificateFilePath") -and ` $PSBoundParameters.ContainsKey("MetadataEndPoint")) { $message = ("Cannot use both parameters SigningCertificateFilePath and MetadataEndPoint at the same time.") Add-SPDscEvent -Message $message ` -EntryType 'Error' ` -EventID 100 ` -Source $MyInvocation.MyCommand.Source throw $message } if ($PSBoundParameters.ContainsKey("SigningCertificateThumbprint") -eq $false -and ` $PSBoundParameters.ContainsKey("SigningCertificateFilePath") -eq $false -and ` $PSBoundParameters.ContainsKey("MetadataEndPoint") -eq $false) { $message = ("At least one of the following parameters must be specified: " + ` "SigningCertificateThumbprint, SigningCertificateFilePath, MetadataEndPoint.") Add-SPDscEvent -Message $message ` -EntryType 'Error' ` -EventID 100 ` -Source $MyInvocation.MyCommand.Source throw $message } if ($PSBoundParameters.ContainsKey("MetadataEndPoint") -and ` $PSBoundParameters.ContainsKey("RegisteredIssuerNameIdentifier")) { $message = ("Cannot use both parameters MetadataEndPoint and RegisteredIssuerNameIdentifier at the same time.") Add-SPDscEvent -Message $message ` -EntryType 'Error' ` -EventID 100 ` -Source $MyInvocation.MyCommand.Source throw $message } if ($PSBoundParameters.ContainsKey("MetadataEndPoint") -and ` $PSBoundParameters.ContainsKey("RegisteredIssuerNameRealm")) { $message = ("Cannot use both parameters MetadataEndPoint and RegisteredIssuerNameRealm at the same time.") Add-SPDscEvent -Message $message ` -EntryType 'Error' ` -EventID 100 ` -Source $MyInvocation.MyCommand.Source throw $message } $PSBoundParameters.Add("CurrentValues", $CurrentValues) $null = Invoke-SPDscCommand -Credential $InstallAccount ` -Arguments @($PSBoundParameters, $MyInvocation.MyCommand.Source) ` -ScriptBlock { $params = $args[0] $eventSource = $args[1] $runParams = @{ } if ($params.Description) { $runParams.Add("Description", $params.Description) } if ($params.IsTrustBroker -eq $true) { $runParams.Add("IsTrustBroker", $null) } if ($params.MetadataEndPoint) { # Configure OAuth trust automatically using metadata file specified in parameter MetadataEndPoint $runParams.Add("MetadataEndPoint", $params.MetadataEndPoint) } else { # Configure OAuth trust with specified certificate and a RegisteredIssuerName if ($params.SigningCertificateFilePath) { Write-Verbose -Message "Getting signing certificate from file system path '$($params.SigningCertificateFilePath)'" try { $cert = New-Object -TypeName "System.Security.Cryptography.X509Certificates.X509Certificate2" ` -ArgumentList @($params.SigningCertificateFilePath) } catch { $message = ("Signing certificate was not found in path '$($params.SigningCertificateFilePath)'.") Add-SPDscEvent -Message $message ` -EntryType 'Error' ` -EventID 100 ` -Source $eventSource throw $message } if ($params.SigningCertificateThumbprint) { if (-not ($params.SigningCertificateThumbprint -eq $cert.Thumbprint)) { $message = "Imported certificate thumbprint ($($cert.Thumbprint)) does not match expected thumbprint ($($params.SigningCertificateThumbprint))." Add-SPDscEvent -Message $message ` -EntryType 'Error' ` -EventID 100 ` -Source $eventSource throw $message } } } else { Write-Verbose -Message ("Getting signing certificate with thumbprint " + ` "$($params.SigningCertificateThumbprint) from the certificate store 'LocalMachine\My'") if ($params.SigningCertificateThumbprint -notmatch "^[A-Fa-f0-9]{40}$") { $message = ("Parameter SigningCertificateThumbprint does not match valid format '^[A-Fa-f0-9]{40}$'.") Add-SPDscEvent -Message $message ` -EntryType 'Error' ` -EventID 100 ` -Source $eventSource throw $message } $cert = Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object -FilterScript { $_.Thumbprint -match $params.SigningCertificateThumbprint } if (!$cert) { $message = ("Signing certificate with thumbprint $($params.SigningCertificateThumbprint) " + ` "was not found in certificate store 'LocalMachine\My'.") Add-SPDscEvent -Message $message ` -EntryType 'Error' ` -EventID 100 ` -Source $eventSource throw $message } } if ([string]::IsNullOrEmpty($params.RegisteredIssuerNameRealm)) { Write-Verbose -Message "RegisteredIssuerNameRealm is not specified, use Get-SPAuthenticationRealm instead." $registeredIssuerNameRealm = Get-SPAuthenticationRealm } else { $registeredIssuerNameRealm = $params.RegisteredIssuerNameRealm } $registeredIssuerName = "$($params.RegisteredIssuerNameIdentifier)@$registeredIssuerNameRealm" $runParams.Add("RegisteredIssuerName", $registeredIssuerName) $runParams.Add("Certificate", $cert) } if ($params.CurrentValues.Ensure -eq "Absent") { $runParams.Add("Name", $params.Name) Write-Verbose -Message "Creating SPTrustedSecurityTokenIssuer '$($params.Name)'" New-SPTrustedSecurityTokenIssuer @runParams } else { $runParams.Add("Identity", $params.Name) $runParams.Add("Confirm", $false) Write-Verbose -Message "Updating SPTrustedSecurityTokenIssuer '$($params.Name)'" Write-Verbose -Message "New Values: $(Convert-SPDscHashtableToString -Hashtable $runParams)" Set-SPTrustedSecurityTokenIssuer @runParams } } } else { if ($CurrentValues.Ensure -eq "Present") { Write-Verbose "Removing SPTrustedSecurityTokenIssuer '$Name'" $null = Invoke-SPDscCommand -Credential $InstallAccount ` -Arguments $PSBoundParameters ` -ScriptBlock { $params = $args[0] $runParams = @{ Identity = $params.Name Confirm = $false } Remove-SPTrustedSecurityTokenIssuer @runParams } } } } function Test-TargetResource { [CmdletBinding()] [OutputType([Boolean])] param ( [Parameter(Mandatory = $true)] [String] $Name, [Parameter()] [String] $Description, [Parameter()] [String] $RegisteredIssuerNameIdentifier, [Parameter()] [String] $RegisteredIssuerNameRealm, [Parameter()] [String] $SigningCertificateThumbprint, [Parameter()] [String] $SigningCertificateFilePath, [Parameter()] [String] $MetadataEndPoint, [Parameter()] [System.Boolean] $IsTrustBroker = $true, [Parameter()] [ValidateSet("Present", "Absent")] [String] $Ensure = "Present", [Parameter()] [System.Management.Automation.PSCredential] $InstallAccount ) Write-Verbose -Message "Testing SPTrustedSecurityTokenIssuer '$Name' settings" $PSBoundParameters.Ensure = $Ensure $PSBoundParameters.IsTrustBroker = $IsTrustBroker if ($PSBoundParameters.ContainsKey("SigningCertificateThumbprint") -and ` $PSBoundParameters.ContainsKey("MetadataEndPoint")) { $message = ("Cannot use both parameters SigningCertificateThumbprint and MetadataEndPoint at the same time.") Add-SPDscEvent -Message $message ` -EntryType 'Error' ` -EventID 100 ` -Source $MyInvocation.MyCommand.Source throw $message } if ($PSBoundParameters.ContainsKey("SigningCertificateFilePath") -and ` $PSBoundParameters.ContainsKey("MetadataEndPoint")) { $message = ("Cannot use both parameters SigningCertificateFilePath and MetadataEndPoint at the same time.") Add-SPDscEvent -Message $message ` -EntryType 'Error' ` -EventID 100 ` -Source $MyInvocation.MyCommand.Source throw $message } if ($PSBoundParameters.ContainsKey("SigningCertificateThumbprint") -eq $false -and ` $PSBoundParameters.ContainsKey("SigningCertificateFilePath") -eq $false -and ` $PSBoundParameters.ContainsKey("MetadataEndPoint") -eq $false) { $message = ("At least one of the following parameters must be specified: " + ` "SigningCertificateThumbprint, SigningCertificateFilePath, MetadataEndPoint.") Add-SPDscEvent -Message $message ` -EntryType 'Error' ` -EventID 100 ` -Source $MyInvocation.MyCommand.Source throw $message } if ($PSBoundParameters.ContainsKey("MetadataEndPoint") -and ` $PSBoundParameters.ContainsKey("RegisteredIssuerNameIdentifier")) { $message = ("Cannot use both parameters MetadataEndPoint and RegisteredIssuerNameIdentifier at the same time.") Add-SPDscEvent -Message $message ` -EntryType 'Error' ` -EventID 100 ` -Source $MyInvocation.MyCommand.Source throw $message } if ($PSBoundParameters.ContainsKey("MetadataEndPoint") -and ` $PSBoundParameters.ContainsKey("RegisteredIssuerNameRealm")) { $message = ("Cannot use both parameters MetadataEndPoint and RegisteredIssuerNameRealm at the same time.") Add-SPDscEvent -Message $message ` -EntryType 'Error' ` -EventID 100 ` -Source $MyInvocation.MyCommand.Source throw $message } # If RegisteredIssuerNameRealm was not set, it won't be present in the $PSBoundParameters # But it must be added to be actually tested by Test-SPDscParameterState if ($PSBoundParameters.ContainsKey("RegisteredIssuerNameRealm") -eq $false) { $PSBoundParameters.Add("RegisteredIssuerNameRealm", "") } if ($PSBoundParameters.ContainsKey("SigningCertificateFilePath") -and ` -not ($PSBoundParameters.ContainsKey("SigningCertificateThumbprint"))) { Write-Verbose "Retrieving thumbprint of SigningCertificateThumbprint" $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 $cert.Import($SigningCertificateFilePath) Write-Verbose "Thumbprint is $($cert.Thumbprint)" $PSBoundParameters.SigningCertificateThumbprint = $cert.Thumbprint } # If SigningCertificateThumbprint was not set, it won't be present in the $PSBoundParameters # Since it is set in the Get method, it must be added to be tested correctly by Test-SPDscParameterState if ($PSBoundParameters.ContainsKey("SigningCertificateThumbprint") -eq $false) { $PSBoundParameters.Add("SigningCertificateThumbprint", "") } # If SigningCertificateFilePath was not set, it won't be present in the $PSBoundParameters # Since it is set in the Get method, it must be added to be tested correctly by Test-SPDscParameterState if ($PSBoundParameters.ContainsKey("SigningCertificateFilePath") -eq $false) { $PSBoundParameters.Add("SigningCertificateFilePath", "") } # If MetadataEndPoint was not set, it won't be present in the $PSBoundParameters # But it must be added to be actually tested by Test-SPDscParameterState if ($PSBoundParameters.ContainsKey("MetadataEndPoint") -eq $false) { $PSBoundParameters.Add("MetadataEndPoint", "") $valuesToCheck = @("Ensure", "Description", "RegisteredIssuerNameIdentifier", "RegisteredIssuerNameRealm", "SigningCertificateThumbprint", "IsTrustBroker") } else { # If MetadataEndPoint is set, the only property that really matters is MetadataEndPoint $valuesToCheck = @("Ensure", "Description", "MetadataEndPoint", "IsTrustBroker") } $CurrentValues = Get-TargetResource @PSBoundParameters Write-Verbose -Message "Current Values: $(Convert-SPDscHashtableToString -Hashtable $CurrentValues)" Write-Verbose -Message "Target Values: $(Convert-SPDscHashtableToString -Hashtable $PSBoundParameters)" $result = Test-SPDscParameterState -CurrentValues $CurrentValues ` -Source $($MyInvocation.MyCommand.Source) ` -DesiredValues $PSBoundParameters ` -ValuesToCheck $valuesToCheck Write-Verbose -Message "Test-TargetResource returned $result" return $result } Export-ModuleMember -Function *-TargetResource |