diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d44848e1..ba2c47488 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- SPTrustedIdentityTokenIssuer + - Added parameters to support OIDC authentication in SharePoint Server Subscription Edition - SPFarm - Suppress a useless reboot that was triggered once a server joined the farm - Suppress a useless 5 minutes sleep triggered once a server joined the farm diff --git a/SharePointDsc/DSCResources/MSFT_SPTrustedIdentityTokenIssuer/MSFT_SPTrustedIdentityTokenIssuer.psm1 b/SharePointDsc/DSCResources/MSFT_SPTrustedIdentityTokenIssuer/MSFT_SPTrustedIdentityTokenIssuer.psm1 index 697a5a64c..0a7354d00 100644 --- a/SharePointDsc/DSCResources/MSFT_SPTrustedIdentityTokenIssuer/MSFT_SPTrustedIdentityTokenIssuer.psm1 +++ b/SharePointDsc/DSCResources/MSFT_SPTrustedIdentityTokenIssuer/MSFT_SPTrustedIdentityTokenIssuer.psm1 @@ -12,14 +12,35 @@ function Get-TargetResource [String] $Description, - [Parameter(Mandatory = $true)] + # SAML-specific + [Parameter()] [String] $Realm, - [Parameter(Mandatory = $true)] + # SAML-specific + [Parameter()] [String] $SignInUrl, + [Parameter()] + [String] + $RegisteredIssuerName, + + # OIDC-specific + [Parameter()] + [String] + $AuthorizationEndPointUri, + + # OIDC-specific + [Parameter()] + [String] + $DefaultClientIdentifier, + + # OIDC-specific + [Parameter()] + [String] + $SignOutUrl, + [Parameter(Mandatory = $true)] [String] $IdentifierClaim, @@ -49,6 +70,7 @@ function Get-TargetResource [String] $ProviderSignOutUri, + # SAML-specific [Parameter()] [System.Boolean] $UseWReplyParameter = $false @@ -68,11 +90,21 @@ function Get-TargetResource $description = $spTrust.Description $realm = $spTrust.DefaultProviderRealm $signInUrl = $spTrust.ProviderUri.OriginalString + $registeredIssuerName = $spTrust.RegisteredIssuerName + if ($false -eq [String]::IsNullOrWhiteSpace($spTrust.AuthorizationEndPointUri)) + { + $authorizationEndPointUri = $spTrust.AuthorizationEndPointUri.ToString() + } + $defaultClientIdentifier = $spTrust.DefaultClientIdentifier + $signOutUrl = $spTrust.SignOutUrl $identifierClaim = $spTrust.IdentityClaimTypeInformation.InputClaimType $SigningCertificateThumbprint = $spTrust.SigningCertificate.Thumbprint $currentState = "Present" $claimProviderName = $sptrust.ClaimProviderName - $providerSignOutUri = $sptrust.ProviderSignOutUri.OriginalString + if ($false -eq [String]::IsNullOrWhiteSpace($spTrust.ProviderSignOutUri)) + { + $providerSignOutUri = $sptrust.ProviderSignOutUri.OriginalString + } $useWReplyParameter = $sptrust.UseWReplyParameter $spTrust.ClaimTypeInformation | ForEach-Object -Process { @@ -88,6 +120,10 @@ function Get-TargetResource $description = "" $realm = "" $signInUrl = "" + $registeredIssuerName = "" + $authorizationEndPointUri = "" + $defaultClientIdentifier = "" + $signOutUrl = "" $identifierClaim = "" $SigningCertificateThumbprint = "" $currentState = "Absent" @@ -101,6 +137,10 @@ function Get-TargetResource Description = $description Realm = $realm SignInUrl = $signInUrl + RegisteredIssuerName = $registeredIssuerName + AuthorizationEndPointUri = $authorizationEndPointUri + DefaultClientIdentifier = $defaultClientIdentifier + SignOutUrl = $signOutUrl IdentifierClaim = $identifierClaim ClaimsMappings = $claimsMappings SigningCertificateThumbprint = $SigningCertificateThumbprint @@ -127,14 +167,35 @@ function Set-TargetResource [String] $Description, - [Parameter(Mandatory = $true)] + # SAML-specific + [Parameter()] [String] $Realm, - [Parameter(Mandatory = $true)] + # SAML-specific + [Parameter()] [String] $SignInUrl, + [Parameter()] + [String] + $RegisteredIssuerName, + + # OIDC-specific + [Parameter()] + [String] + $AuthorizationEndPointUri, + + # OIDC-specific + [Parameter()] + [String] + $DefaultClientIdentifier, + + # OIDC-specific + [Parameter()] + [String] + $SignOutUrl, + [Parameter(Mandatory = $true)] [String] $IdentifierClaim, @@ -164,6 +225,7 @@ function Set-TargetResource [String] $ProviderSignOutUri, + # SAML-specific [Parameter()] [System.Boolean] $UseWReplyParameter = $false @@ -177,8 +239,8 @@ function Set-TargetResource { if ($CurrentValues.Ensure -eq "Absent") { - if ($PSBoundParameters.ContainsKey("SigningCertificateThumbprint") -and ` - $PSBoundParameters.ContainsKey("SigningCertificateFilePath")) + if ($true -eq $PSBoundParameters.ContainsKey("SigningCertificateThumbprint") -and + $true -eq $PSBoundParameters.ContainsKey("SigningCertificateFilePath")) { $message = ("Cannot use both parameters SigningCertificateThumbprint and SigningCertificateFilePath at the same time.") Add-SPDscEvent -Message $message ` @@ -188,8 +250,8 @@ function Set-TargetResource throw $message } - if (!$PSBoundParameters.ContainsKey("SigningCertificateThumbprint") -and ` - !$PSBoundParameters.ContainsKey("SigningCertificateFilePath")) + if ($false -eq $PSBoundParameters.ContainsKey("SigningCertificateThumbprint") -and + $false -eq $PSBoundParameters.ContainsKey("SigningCertificateFilePath")) { $message = ("At least one of the following parameters must be specified: " + ` "SigningCertificateThumbprint, SigningCertificateFilePath.") @@ -200,6 +262,71 @@ function Set-TargetResource throw $message } + # Ensure that at least one parameter is specified between Realm (SAML trust) or DefaultClientIdentifier (OIDC trust) + if ($false -eq $PSBoundParameters.ContainsKey("Realm") -and + $false -eq $PSBoundParameters.ContainsKey("DefaultClientIdentifier")) + { + $message = ("At least one of the following parameters must be specified: " + ` + "Realm (for SAML trust), DefaultClientIdentifier (for OIDC trust).") + Add-SPDscEvent -Message $message ` + -EntryType 'Error' ` + -EventID 100 ` + -Source $MyInvocation.MyCommand.Source + throw $message + } + + # Ensure that parameters Realm (SAML trust) or DefaultClientIdentifier (OIDC trust) are not both set + if ($true -eq $PSBoundParameters.ContainsKey("Realm") -and + $true -eq $PSBoundParameters.ContainsKey("DefaultClientIdentifier")) + { + $message = ("Parameters Realm (for SAML trust) and DefaultClientIdentifier (for OIDC trust) cannot be both set.") + Add-SPDscEvent -Message $message ` + -EntryType 'Error' ` + -EventID 100 ` + -Source $MyInvocation.MyCommand.Source + throw $message + } + + # SAML trust: If parameter Realm is set, then parameter SignInUrl is required + if ($true -eq $PSBoundParameters.ContainsKey("Realm") -and + $false -eq $PSBoundParameters.ContainsKey("SignInUrl")) + { + $message = ("Parameter Realm was set but SignInUrl is not set. Parameter SignInUrl required when Realm is set.") + Add-SPDscEvent -Message $message ` + -EntryType 'Error' ` + -EventID 100 ` + -Source $MyInvocation.MyCommand.Source + throw $message + } + + # OIDC trust: If parameter DefaultClientIdentifier is set, + # then parameters AuthorizationEndPointUri, RegisteredIssuerName and SignOutUrl are required + if ($true -eq $PSBoundParameters.ContainsKey("DefaultClientIdentifier") -and ( + $false -eq $PSBoundParameters.ContainsKey("AuthorizationEndPointUri") -or + $false -eq $PSBoundParameters.ContainsKey("RegisteredIssuerName") -or + $false -eq $PSBoundParameters.ContainsKey("SignOutUrl") )) + { + $message = ("Parameter DefaultClientIdentifier was set but AuthorizationEndPointUri, RegisteredIssuerName or SignOutUrl are not set." + ` + "Parameters AuthorizationEndPointUri, RegisteredIssuerName, DefaultClientIdentifier and SignOutUrl are required when DefaultClientIdentifier is set") + Add-SPDscEvent -Message $message ` + -EntryType 'Error' ` + -EventID 100 ` + -Source $MyInvocation.MyCommand.Source + throw $message + } + + $productVersion = Get-SPDscInstalledProductVersion + if ($true -eq $PSBoundParameters.ContainsKey("DefaultClientIdentifier") -and + ($productVersion.FileMajorPart -ne 16 -or $productVersion.FileBuildPart -le 13000)) + { + $message = ("OIDC parameters can only be used with SharePoint Server Subscription Edition.") + Add-SPDscEvent -Message $message ` + -EntryType 'Error' ` + -EventID 100 ` + -Source $MyInvocation.MyCommand.Source + throw $message + } + Write-Verbose -Message "Creating SPTrustedIdentityTokenIssuer '$Name'" $null = Invoke-SPDscCommand -Arguments @($PSBoundParameters, $MyInvocation.MyCommand.Source) ` -ScriptBlock { @@ -298,15 +425,33 @@ function Set-TargetResource throw $message } + $oidcSetup = $false + if ($false -eq [String]::IsNullOrWhiteSpace($params.RegisteredIssuerName)) + { + $oidcSetup = $true + } + $runParams = @{ } $runParams.Add("ImportTrustCertificate", $cert) $runParams.Add("Name", $params.Name) $runParams.Add("Description", $params.Description) - $runParams.Add("Realm", $params.Realm) - $runParams.Add("SignInUrl", $params.SignInUrl) + + if ($true -eq $oidcSetup) + { + $runParams.Add("RegisteredIssuerName", $params.RegisteredIssuerName) + $runParams.Add("AuthorizationEndPointUri", $params.AuthorizationEndPointUri) + $runParams.Add("DefaultClientIdentifier", $params.DefaultClientIdentifier) + $runParams.Add("SignOutUrl", $params.SignOutUrl) + } + else + { + $runParams.Add("Realm", $params.Realm) + $runParams.Add("SignInUrl", $params.SignInUrl) + $runParams.Add("UseWReply", $params.UseWReplyParameter) + } + $runParams.Add("IdentifierClaim", $params.IdentifierClaim) $runParams.Add("ClaimsMappings", $claimsMappingsArray) - $runParams.Add("UseWReply", $params.UseWReplyParameter) $trust = New-SPTrustedIdentityTokenIssuer @runParams if ($null -eq $trust) @@ -330,7 +475,7 @@ function Set-TargetResource } } - if ($params.ProviderSignOutUri) + if ($params.ProviderSignOutUri -and $false -eq $oidcSetup) { $installedVersion = Get-SPDscInstalledProductVersion # This property does not exist in SharePoint 2013 @@ -408,14 +553,35 @@ function Test-TargetResource [String] $Description, - [Parameter(Mandatory = $true)] + # SAML-specific + [Parameter()] [String] $Realm, - [Parameter(Mandatory = $true)] + # SAML-specific + [Parameter()] [String] $SignInUrl, + [Parameter()] + [String] + $RegisteredIssuerName, + + # OIDC-specific + [Parameter()] + [String] + $AuthorizationEndPointUri, + + # OIDC-specific + [Parameter()] + [String] + $DefaultClientIdentifier, + + # OIDC-specific + [Parameter()] + [String] + $SignOutUrl, + [Parameter(Mandatory = $true)] [String] $IdentifierClaim, @@ -445,6 +611,7 @@ function Test-TargetResource [String] $ProviderSignOutUri, + # SAML-specific [Parameter()] [System.Boolean] $UseWReplyParameter = $false @@ -452,8 +619,8 @@ function Test-TargetResource Write-Verbose -Message "Testing SPTrustedIdentityTokenIssuer '$Name' settings" - if ($PSBoundParameters.ContainsKey("SigningCertificateThumbprint") -and ` - $PSBoundParameters.ContainsKey("SigningCertificateFilePath")) + if ($true -eq $PSBoundParameters.ContainsKey("SigningCertificateThumbprint") -and + $true -eq $PSBoundParameters.ContainsKey("SigningCertificateFilePath")) { $message = ("Cannot use both parameters SigningCertificateThumbprint and SigningCertificateFilePath at the same time.") Add-SPDscEvent -Message $message ` @@ -463,8 +630,8 @@ function Test-TargetResource throw $message } - if ($PSBoundParameters.ContainsKey("SigningCertificateThumbprint") -eq $false -and ` - $PSBoundParameters.ContainsKey("SigningCertificateFilePath") -eq $false) + if ($false -eq $PSBoundParameters.ContainsKey("SigningCertificateThumbprint") -and + $false -eq $PSBoundParameters.ContainsKey("SigningCertificateFilePath")) { $message = ("At least one of the following parameters must be specified: " + ` "SigningCertificateThumbprint, SigningCertificateFilePath.") @@ -475,6 +642,71 @@ function Test-TargetResource throw $message } + # Ensure that at least one parameter is specified between Realm (SAML trust) or DefaultClientIdentifier (OIDC trust) + if ($false -eq $PSBoundParameters.ContainsKey("Realm") -and + $false -eq $PSBoundParameters.ContainsKey("DefaultClientIdentifier")) + { + $message = ("At least one of the following parameters must be specified: " + ` + "Realm (for SAML trust), DefaultClientIdentifier (for OIDC trust).") + Add-SPDscEvent -Message $message ` + -EntryType 'Error' ` + -EventID 100 ` + -Source $MyInvocation.MyCommand.Source + throw $message + } + + # Ensure that parameters Realm (SAML trust) or DefaultClientIdentifier (OIDC trust) are not both set + if ($true -eq $PSBoundParameters.ContainsKey("Realm") -and + $true -eq $PSBoundParameters.ContainsKey("DefaultClientIdentifier")) + { + $message = ("Parameters Realm (for SAML trust) and DefaultClientIdentifier (for OIDC trust) cannot be both set.") + Add-SPDscEvent -Message $message ` + -EntryType 'Error' ` + -EventID 100 ` + -Source $MyInvocation.MyCommand.Source + throw $message + } + + # SAML trust: If parameter Realm is set, then parameter SignInUrl is required + if ($true -eq $PSBoundParameters.ContainsKey("Realm") -and + $false -eq $PSBoundParameters.ContainsKey("SignInUrl")) + { + $message = ("Parameter Realm was set but SignInUrl is not set. Parameter SignInUrl required when Realm is set.") + Add-SPDscEvent -Message $message ` + -EntryType 'Error' ` + -EventID 100 ` + -Source $MyInvocation.MyCommand.Source + throw $message + } + + # OIDC trust: If parameter DefaultClientIdentifier is set, + # then parameters AuthorizationEndPointUri, RegisteredIssuerName and SignOutUrl are required + if ($true -eq $PSBoundParameters.ContainsKey("DefaultClientIdentifier") -and ( + $false -eq $PSBoundParameters.ContainsKey("AuthorizationEndPointUri") -or + $false -eq $PSBoundParameters.ContainsKey("RegisteredIssuerName") -or + $false -eq $PSBoundParameters.ContainsKey("SignOutUrl") )) + { + $message = ("Parameter DefaultClientIdentifier was set but AuthorizationEndPointUri, RegisteredIssuerName or SignOutUrl are not set." + ` + "Parameters AuthorizationEndPointUri, RegisteredIssuerName, DefaultClientIdentifier and SignOutUrl are required when DefaultClientIdentifier is set") + Add-SPDscEvent -Message $message ` + -EntryType 'Error' ` + -EventID 100 ` + -Source $MyInvocation.MyCommand.Source + throw $message + } + + $productVersion = Get-SPDscInstalledProductVersion + if ($true -eq $PSBoundParameters.ContainsKey("DefaultClientIdentifier") -and + ($productVersion.FileMajorPart -ne 16 -or $productVersion.FileBuildPart -le 13000)) + { + $message = ("OIDC parameters can only be used with SharePoint Server Subscription Edition.") + Add-SPDscEvent -Message $message ` + -EntryType 'Error' ` + -EventID 100 ` + -Source $MyInvocation.MyCommand.Source + throw $message + } + $CurrentValues = Get-TargetResource @PSBoundParameters Write-Verbose -Message "Current Values: $(Convert-SPDscHashtableToString -Hashtable $CurrentValues)" diff --git a/SharePointDsc/DSCResources/MSFT_SPTrustedIdentityTokenIssuer/MSFT_SPTrustedIdentityTokenIssuer.schema.mof b/SharePointDsc/DSCResources/MSFT_SPTrustedIdentityTokenIssuer/MSFT_SPTrustedIdentityTokenIssuer.schema.mof index 289b50cf1..804bf2a2e 100644 --- a/SharePointDsc/DSCResources/MSFT_SPTrustedIdentityTokenIssuer/MSFT_SPTrustedIdentityTokenIssuer.schema.mof +++ b/SharePointDsc/DSCResources/MSFT_SPTrustedIdentityTokenIssuer/MSFT_SPTrustedIdentityTokenIssuer.schema.mof @@ -13,8 +13,12 @@ class MSFT_SPTrustedIdentityTokenIssuer : OMI_BaseResource { [Key, Description("Name of the SPTrustedIdentityTokenIssuer")] String Name; [Required, Description("Description of the SPTrustedIdentityTokenIssuer")] String Description; - [Required, Description("Default Realm that is passed to identity provider")] String Realm; - [Required, Description("URL of the identity provider where user is redirected to for authentication")] String SignInUrl; + [Write, Description("Default Realm that is passed to identity provider")] String Realm; + [Write, Description("URL of the identity provider where user is redirected to for authentication")] String SignInUrl; + [Write, Description("Required for OIDC trust: Specify the identity of the issuer")] String RegisteredIssuerName; + [Write, Description("Required for OIDC trust: specify the sign-in URL of the issuer")] String AuthorizationEndPointUri; + [Write, Description("Required for OIDC trust: specify the client identifier of the issuer")] String DefaultClientIdentifier; + [Write, Description("Required for OIDC trust: specify the sign-out URL of the issuer")] String SignOutUrl; [Required, Description("Identity claim type that uniquely identifies the user")] String IdentifierClaim; [Required, Description("Array of MSFT_SPClaimTypeMapping to use with cmdlet New-SPClaimTypeMapping"), EmbeddedInstance("MSFT_SPClaimTypeMapping")] String ClaimsMappings[]; [Write, Description("Specify the thumbprint of the signing certificate, which must be located in certificate store LocalMachine\\My")] String SigningCertificateThumbprint; diff --git a/SharePointDsc/DSCResources/MSFT_SPTrustedIdentityTokenIssuer/readme.md b/SharePointDsc/DSCResources/MSFT_SPTrustedIdentityTokenIssuer/readme.md index 00d1bcec6..6719035cd 100644 --- a/SharePointDsc/DSCResources/MSFT_SPTrustedIdentityTokenIssuer/readme.md +++ b/SharePointDsc/DSCResources/MSFT_SPTrustedIdentityTokenIssuer/readme.md @@ -6,6 +6,12 @@ This resource is used to create or remove SPTrustedIdentityTokenIssuer in a SharePoint farm. +In SharePoint 2013 / 2016 / 2019, it can only be a SAML trust. +In SharePoint Subscription, it can be a SAML trust or an OIDC trust. + +For a SAML trust, the specific mandatory parameters are Realm, SignInUrl, +and either SigningCertificateThumbPrint or SigningCertificateFilePath. + Either parameter SigningCertificateThumbPrint or SigningCertificateFilePath must be set. If specifying both SigningCertificateThumbPrint and SigningCertificateFilePath, the certificate thumbprint will be verified @@ -21,6 +27,9 @@ certiificate store because SharePoint does not accept it. The SigningCertificateFilePath must be the file path to the public key of the signing certificate. +For an OIDC trust, the specific mandatory parameters are RegisteredIssuerName, +AuthorizationEndPointUri, DefaultClientIdentifier and SignOutUrl. + The ClaimsMappings property is an array of MSFT_SPClaimTypeMapping to use with cmdlet New-SPClaimTypeMapping. Each MSFT_SPClaimTypeMapping requires properties Name and IncomingClaimType. Property LocalClaimType is not diff --git a/tests/Unit/SharePointDsc/SharePointDsc.SPTrustedIdentityTokenIssuer.Tests.ps1 b/tests/Unit/SharePointDsc/SharePointDsc.SPTrustedIdentityTokenIssuer.Tests.ps1 index 693c41dc0..f375c790b 100644 --- a/tests/Unit/SharePointDsc/SharePointDsc.SPTrustedIdentityTokenIssuer.Tests.ps1 +++ b/tests/Unit/SharePointDsc/SharePointDsc.SPTrustedIdentityTokenIssuer.Tests.ps1 @@ -50,7 +50,7 @@ try InModuleScope -ModuleName $script:DSCResourceFullName -ScriptBlock { Describe -Name $Global:SPDscHelper.DescribeHeader -Fixture { BeforeAll { - Invoke-Command -ScriptBlock $Global:SPDscHelper.InitializeScript -NoNewScope + Invoke-Command -Scriptblock $Global:SPDscHelper.InitializeScript -NoNewScope # Mocks for all contexts Mock -CommandName Get-ChildItem -MockWith { @@ -133,7 +133,7 @@ try } # Test contexts - Context -Name "The SPTrustedLoginProvider does not exist but should, using a signing certificate in the certificate store" -Fixture { + Context -Name "The SAML SPTrustedLoginProvider does not exist but should, using a signing certificate in the certificate store" -Fixture { BeforeAll { $testParams = @{ Name = "Contoso" @@ -143,14 +143,14 @@ try IdentifierClaim = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" ClaimsMappings = @( (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ - Name = "Email" - IncomingClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" - } -ClientOnly) + Name = "Email" + IncomingClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" + } -ClientOnly) (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ - Name = "Role" - IncomingClaimType = "http://schemas.xmlsoap.org/ExternalSTSGroupType" - LocalClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" - } -ClientOnly) + Name = "Role" + IncomingClaimType = "http://schemas.xmlsoap.org/ExternalSTSGroupType" + LocalClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } -ClientOnly) ) SigningCertificateThumbprint = "123ABCFACE123ABCFACE123ABCFACE123ABCFACE" ClaimProviderName = "LDAPCP" @@ -174,7 +174,7 @@ try } } - Context -Name "The SPTrustedLoginProvider does not exist but should, using a signing certificate in the file path" -Fixture { + Context -Name "The SAML SPTrustedLoginProvider does not exist but should, using a signing certificate in the file path" -Fixture { BeforeAll { $testParams = @{ Name = "Contoso" @@ -184,14 +184,14 @@ try IdentifierClaim = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" ClaimsMappings = @( (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ - Name = "Email" - IncomingClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" - } -ClientOnly) + Name = "Email" + IncomingClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" + } -ClientOnly) (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ - Name = "Role" - IncomingClaimType = "http://schemas.xmlsoap.org/ExternalSTSGroupType" - LocalClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" - } -ClientOnly) + Name = "Role" + IncomingClaimType = "http://schemas.xmlsoap.org/ExternalSTSGroupType" + LocalClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } -ClientOnly) ) SigningCertificateFilePath = "F:\Data\DSC\FakeSigning.cer" ClaimProviderName = "LDAPCP" @@ -233,14 +233,14 @@ try IdentifierClaim = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" ClaimsMappings = @( (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ - Name = "Email" - IncomingClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" - } -ClientOnly) + Name = "Email" + IncomingClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" + } -ClientOnly) (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ - Name = "Role" - IncomingClaimType = "http://schemas.xmlsoap.org/ExternalSTSGroupType" - LocalClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" - } -ClientOnly) + Name = "Role" + IncomingClaimType = "http://schemas.xmlsoap.org/ExternalSTSGroupType" + LocalClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } -ClientOnly) ) SigningCertificateThumbprint = "123ABCFACE123ABCFACE123ABCFACE123ABCFACE" SigningCertificateFilePath = "F:\Data\DSC\FakeSigning.cer" @@ -265,14 +265,14 @@ try IdentifierClaim = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" ClaimsMappings = @( (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ - Name = "Email" - IncomingClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" - } -ClientOnly) + Name = "Email" + IncomingClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" + } -ClientOnly) (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ - Name = "Role" - IncomingClaimType = "http://schemas.xmlsoap.org/ExternalSTSGroupType" - LocalClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" - } -ClientOnly) + Name = "Role" + IncomingClaimType = "http://schemas.xmlsoap.org/ExternalSTSGroupType" + LocalClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } -ClientOnly) ) ClaimProviderName = "LDAPCP" ProviderSignOutUri = "https://adfs.contoso.com/adfs/ls/" @@ -295,14 +295,14 @@ try IdentifierClaim = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" ClaimsMappings = @( (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ - Name = "Email" - IncomingClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" - } -ClientOnly) + Name = "Email" + IncomingClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" + } -ClientOnly) (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ - Name = "Role" - IncomingClaimType = "http://schemas.xmlsoap.org/ExternalSTSGroupType" - LocalClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" - } -ClientOnly) + Name = "Role" + IncomingClaimType = "http://schemas.xmlsoap.org/ExternalSTSGroupType" + LocalClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } -ClientOnly) ) SigningCertificateThumbprint = "XX123ABCFACEXX" ClaimProviderName = "LDAPCP" @@ -326,14 +326,14 @@ try IdentifierClaim = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" ClaimsMappings = @( (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ - Name = "Email" - IncomingClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" - } -ClientOnly) + Name = "Email" + IncomingClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" + } -ClientOnly) (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ - Name = "Role" - IncomingClaimType = "http://schemas.xmlsoap.org/ExternalSTSGroupType" - LocalClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" - } -ClientOnly) + Name = "Role" + IncomingClaimType = "http://schemas.xmlsoap.org/ExternalSTSGroupType" + LocalClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } -ClientOnly) ) SigningCertificateThumbprint = "123ABCFACE123ABCFACE123ABCFACE123ABCFACE" ClaimProviderName = "LDAPCP" @@ -356,15 +356,171 @@ try } } - Context -Name "The SPTrustedLoginProvider does not exist but should, with a claims provider that exists on the farm" -Fixture { + Context -Name "A SAML SPTrustedLoginProvider is desired, but parameters for both OIDC and SAML trusts are set" -Fixture { BeforeAll { $testParams = @{ Name = "Contoso" Description = "Contoso" Realm = "https://sharepoint.contoso.com" + DefaultClientIdentifier = "fae5bd07-be63-4a64-a28c-7931a4ebf62b" SignInUrl = "https://adfs.contoso.com/adfs/ls/" IdentifierClaim = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" ClaimsMappings = @( + (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ + Name = "Email" + IncomingClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" + } -ClientOnly) + (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ + Name = "Role" + IncomingClaimType = "http://schemas.xmlsoap.org/ExternalSTSGroupType" + LocalClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } -ClientOnly) + ) + SigningCertificateThumbprint = "123ABCFACE123ABCFACE123ABCFACE123ABCFACE" + ClaimProviderName = "LDAPCP" + ProviderSignOutUri = "https://adfs.contoso.com/adfs/ls/" + Ensure = "Present" + } + } + + It "should fail validation of parameters" { + { Set-TargetResource @testParams } | Should -Throw "Parameters Realm (for SAML trust) and DefaultClientIdentifier (for OIDC trust) cannot be both set." + } + } + + Context -Name "A SPTrustedLoginProvider is desired, but neither property Realm nor DefaultClientIdentifier set" -Fixture { + BeforeAll { + $testParams = @{ + Name = "Contoso" + Description = "Contoso" + IdentifierClaim = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" + ClaimsMappings = @( + (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ + Name = "Email" + IncomingClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" + } -ClientOnly) + (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ + Name = "Role" + IncomingClaimType = "http://schemas.xmlsoap.org/ExternalSTSGroupType" + LocalClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } -ClientOnly) + ) + SigningCertificateThumbprint = "123ABCFACE123ABCFACE123ABCFACE123ABCFACE" + ClaimProviderName = "LDAPCP" + ProviderSignOutUri = "https://adfs.contoso.com/adfs/ls/" + Ensure = "Present" + } + } + + It "should fail validation of parameters" { + { Set-TargetResource @testParams } | Should -Throw "At least one of the following parameters must be specified: Realm (for SAML trust), DefaultClientIdentifier (for OIDC trust)." + } + } + + Context -Name "A SAML SPTrustedLoginProvider is desired, but property SignInUrl is not set" -Fixture { + BeforeAll { + $testParams = @{ + Name = "Contoso" + Description = "Contoso" + Realm = "https://sharepoint.contoso.com" + IdentifierClaim = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" + ClaimsMappings = @( + (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ + Name = "Email" + IncomingClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" + } -ClientOnly) + (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ + Name = "Role" + IncomingClaimType = "http://schemas.xmlsoap.org/ExternalSTSGroupType" + LocalClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } -ClientOnly) + ) + SigningCertificateThumbprint = "123ABCFACE123ABCFACE123ABCFACE123ABCFACE" + ClaimProviderName = "LDAPCP" + ProviderSignOutUri = "https://adfs.contoso.com/adfs/ls/" + Ensure = "Present" + } + } + + It "should fail validation of parameters" { + { Set-TargetResource @testParams } | Should -Throw "Parameter Realm was set but SignInUrl is not set. Parameter SignInUrl required when Realm is set." + } + } + + Context -Name "A OIDC SPTrustedLoginProvider is desired, but not all required OIDC properties are set" -Fixture { + BeforeAll { + $testParams = @{ + Name = "Contoso" + Description = "Contoso" + DefaultClientIdentifier = "fae5bd07-be63-4a64-a28c-7931a4ebf62b" + SignOutUrl = "https://adfs.contoso.com/adfs/oauth2/logout" + IdentifierClaim = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" + ClaimsMappings = @( + (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ + Name = "Email" + IncomingClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" + } -ClientOnly) + (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ + Name = "Role" + IncomingClaimType = "http://schemas.xmlsoap.org/ExternalSTSGroupType" + LocalClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } -ClientOnly) + ) + SigningCertificateThumbprint = "123ABCFACE123ABCFACE123ABCFACE123ABCFACE" + ClaimProviderName = "LDAPCP" + Ensure = "Present" + } + } + + It "should fail validation of parameters" { + { Set-TargetResource @testParams } | Should -Throw "Parameter DefaultClientIdentifier was set but AuthorizationEndPointUri, RegisteredIssuerName or SignOutUrl are not set.Parameters AuthorizationEndPointUri, RegisteredIssuerName, DefaultClientIdentifier and SignOutUrl are required when DefaultClientIdentifier is set" + } + } + + Context -Name "A OIDC SPTrustedLoginProvider is desired, but not all required OIDC properties are set" -Fixture { + BeforeAll { + $testParams = @{ + Name = "Contoso" + Description = "Contoso" + DefaultClientIdentifier = "fae5bd07-be63-4a64-a28c-7931a4ebf62b" + SignOutUrl = "https://adfs.contoso.com/adfs/oauth2/logout" + IdentifierClaim = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" + ClaimsMappings = @( + (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ + Name = "Email" + IncomingClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" + } -ClientOnly) + (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ + Name = "Role" + IncomingClaimType = "http://schemas.xmlsoap.org/ExternalSTSGroupType" + LocalClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } -ClientOnly) + ) + SigningCertificateThumbprint = "123ABCFACE123ABCFACE123ABCFACE123ABCFACE" + ClaimProviderName = "LDAPCP" + Ensure = "Present" + } + } + + It "should fail validation of parameters" { + { Set-TargetResource @testParams } | Should -Throw "Parameter DefaultClientIdentifier was set but AuthorizationEndPointUri, RegisteredIssuerName or SignOutUrl are not set.Parameters AuthorizationEndPointUri, RegisteredIssuerName, DefaultClientIdentifier and SignOutUrl are required when DefaultClientIdentifier is set" + } + } + + if ($Global:SPDscHelper.CurrentStubBuildNumber.Major -ne 16 -or + $Global:SPDscHelper.CurrentStubBuildNumber.Build -le 13000) + { + Context -Name "A OIDC SPTrustedLoginProvider is desired, but current version is not SharePoint Subscription" -Fixture { + BeforeAll { + $testParams = @{ + Name = "Contoso" + Description = "Contoso" + DefaultClientIdentifier = "fae5bd07-be63-4a64-a28c-7931a4ebf62b" + RegisteredIssuerName = "https://adfs.contoso.com/adfs" + AuthorizationEndPointUri = "https://adfs.contoso.com/adfs/oauth2/authorize" + SignOutUrl = "https://adfs.contoso.com/adfs/oauth2/logout" + IdentifierClaim = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" + ClaimsMappings = @( (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ Name = "Email" IncomingClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" @@ -374,6 +530,37 @@ try IncomingClaimType = "http://schemas.xmlsoap.org/ExternalSTSGroupType" LocalClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" } -ClientOnly) + ) + SigningCertificateThumbprint = "123ABCFACE123ABCFACE123ABCFACE123ABCFACE" + ClaimProviderName = "LDAPCP" + Ensure = "Present" + } + } + + It "should fail validation of current version of SharePoint" { + { Set-TargetResource @testParams } | Should -Throw "OIDC parameters can only be used with SharePoint Server Subscription Edition." + } + } + } + + Context -Name "The SAML SPTrustedLoginProvider does not exist but should, with a claims provider that exists on the farm" -Fixture { + BeforeAll { + $testParams = @{ + Name = "Contoso" + Description = "Contoso" + Realm = "https://sharepoint.contoso.com" + SignInUrl = "https://adfs.contoso.com/adfs/ls/" + IdentifierClaim = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" + ClaimsMappings = @( + (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ + Name = "Email" + IncomingClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" + } -ClientOnly) + (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ + Name = "Role" + IncomingClaimType = "http://schemas.xmlsoap.org/ExternalSTSGroupType" + LocalClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } -ClientOnly) ) SigningCertificateThumbprint = "123ABCFACE123ABCFACE123ABCFACE123ABCFACE" ClaimProviderName = "LDAPCP" @@ -382,23 +569,92 @@ try } Mock -CommandName Get-SPTrustedIdentityTokenIssuer -MockWith { + return $null + } + + Mock -CommandName New-SPTrustedIdentityTokenIssuer -MockWith { $sptrust = [pscustomobject]@{ - Name = $testParams.Name - ClaimProviderName = $testParams.ClaimProviderName + ImportTrustCertificate = $null + Name = "" + Description = "" + Realm = "" + SignInUrl = "" + UseWReply = "" + ProviderSignOutUri = "" + IdentifierClaim = "" + ClaimsMappings = $null + ClaimProviderName = "" } $sptrust | Add-Member -Name Update -MemberType ScriptMethod -Value { } return $sptrust } } - It "Should create the SPTrustedLoginProvider with claims provider set" { + It "Should call cmdlet New-SPTrustedIdentityTokenIssuer" { Set-TargetResource @testParams - $getResults = Get-TargetResource @testParams - $getResults.ClaimProviderName | Should -Be $testParams.ClaimProviderName + Assert-MockCalled New-SPTrustedIdentityTokenIssuer + } + } + + if ($Global:SPDscHelper.CurrentStubBuildNumber.Major -eq 16 -and + $Global:SPDscHelper.CurrentStubBuildNumber.Build -gt 13000) + { + Context -Name "The OIDC SPTrustedLoginProvider does not exist but should, with a claims provider that exists on the farm" -Fixture { + BeforeAll { + $testParams = @{ + Name = "Contoso" + Description = "Contoso" + DefaultClientIdentifier = "fae5bd07-be63-4a64-a28c-7931a4ebf62b" + RegisteredIssuerName = "https://adfs.contoso.com/adfs" + AuthorizationEndPointUri = "https://adfs.contoso.com/adfs/oauth2/authorize" + SignOutUrl = "https://adfs.contoso.com/adfs/oauth2/logout" + IdentifierClaim = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" + ClaimsMappings = @( + (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ + Name = "Email" + IncomingClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" + } -ClientOnly) + (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ + Name = "Role" + IncomingClaimType = "http://schemas.xmlsoap.org/ExternalSTSGroupType" + LocalClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } -ClientOnly) + ) + SigningCertificateThumbprint = "123ABCFACE123ABCFACE123ABCFACE123ABCFACE" + ClaimProviderName = "LDAPCP" + Ensure = "Present" + } + + Mock -CommandName Get-SPTrustedIdentityTokenIssuer -MockWith { + return $null + } + + Mock -CommandName New-SPTrustedIdentityTokenIssuer -MockWith { + $sptrust = [pscustomobject]@{ + ImportTrustCertificate = $null + Name = "" + Description = "" + RegisteredIssuerName = "" + AuthorizationEndPointUri = "" + DefaultClientIdentifier = "" + SignOutUrl = "" + IdentifierClaim = "" + ClaimsMappings = $null + ClaimProviderName = "" + } + $sptrust | Add-Member -Name Update -MemberType ScriptMethod -Value { } + return $sptrust + } + } + + It "Should call cmdlet New-SPTrustedIdentityTokenIssuer" { + Set-TargetResource @testParams + Assert-MockCalled New-SPTrustedIdentityTokenIssuer + } } } - Context -Name "The SPTrustedLoginProvider already exists and should not be changed" -Fixture { + Context -Name "The SAML SPTrustedLoginProvider already exists and should not be changed" -Fixture { BeforeAll { $testParams = @{ Name = "Contoso" @@ -408,14 +664,14 @@ try IdentifierClaim = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" ClaimsMappings = @( (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ - Name = "Email" - IncomingClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" - } -ClientOnly) + Name = "Email" + IncomingClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" + } -ClientOnly) (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ - Name = "Role" - IncomingClaimType = "http://schemas.xmlsoap.org/ExternalSTSGroupType" - LocalClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" - } -ClientOnly) + Name = "Role" + IncomingClaimType = "http://schemas.xmlsoap.org/ExternalSTSGroupType" + LocalClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } -ClientOnly) ) SigningCertificateThumbprint = "123ABCFACE123ABCFACE123ABCFACE123ABCFACE" ClaimProviderName = "LDAPCP" @@ -425,8 +681,9 @@ try Mock -CommandName Get-SPTrustedIdentityTokenIssuer -MockWith { $sptrust = [pscustomobject]@{ - Name = $testParams.Name - ClaimProviderName = $testParams.ClaimProviderName + Name = $testParams.Name + ProviderSignOutUri = $testParams.ProviderSignOutUri + ClaimProviderName = $testParams.ClaimProviderName } return $sptrust } @@ -442,7 +699,57 @@ try } } - Context -Name "The SPTrustedLoginProvider already exists but should be removed" -Fixture { + if ($Global:SPDscHelper.CurrentStubBuildNumber.Major -eq 16 -and + $Global:SPDscHelper.CurrentStubBuildNumber.Build -gt 13000) + { + Context -Name "The OIDC SPTrustedLoginProvider already exists and should not be changed" -Fixture { + BeforeAll { + $testParams = @{ + Name = "Contoso" + Description = "Contoso" + DefaultClientIdentifier = "fae5bd07-be63-4a64-a28c-7931a4ebf62b" + RegisteredIssuerName = "https://adfs.contoso.com/adfs" + AuthorizationEndPointUri = "https://adfs.contoso.com/adfs/oauth2/authorize" + SignOutUrl = "https://adfs.contoso.com/adfs/oauth2/logout" + IdentifierClaim = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" + ClaimsMappings = @( + (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ + Name = "Email" + IncomingClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" + } -ClientOnly) + (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ + Name = "Role" + IncomingClaimType = "http://schemas.xmlsoap.org/ExternalSTSGroupType" + LocalClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } -ClientOnly) + ) + SigningCertificateThumbprint = "123ABCFACE123ABCFACE123ABCFACE123ABCFACE" + ClaimProviderName = "LDAPCP" + Ensure = "Present" + } + + Mock -CommandName Get-SPTrustedIdentityTokenIssuer -MockWith { + $sptrust = [pscustomobject]@{ + Name = $testParams.Name + AuthorizationEndPointUri = $testParams.AuthorizationEndPointUri + ClaimProviderName = $testParams.ClaimProviderName + } + return $sptrust + } + } + + It "Should return present from the get method" { + $getResults = Get-TargetResource @testParams + $getResults.Ensure | Should -Be "Present" + } + + It "Should return true from the test method" { + Test-TargetResource @testParams | Should -Be $true + } + } + } + + Context -Name "The SAML SPTrustedLoginProvider already exists but should be removed" -Fixture { BeforeAll { $testParams = @{ Name = "Contoso" @@ -452,14 +759,14 @@ try IdentifierClaim = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" ClaimsMappings = @( (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ - Name = "Email" - IncomingClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" - } -ClientOnly) + Name = "Email" + IncomingClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" + } -ClientOnly) (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ - Name = "Role" - IncomingClaimType = "http://schemas.xmlsoap.org/ExternalSTSGroupType" - LocalClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" - } -ClientOnly) + Name = "Role" + IncomingClaimType = "http://schemas.xmlsoap.org/ExternalSTSGroupType" + LocalClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } -ClientOnly) ) SigningCertificateThumbprint = "123ABCFACE123ABCFACE123ABCFACE123ABCFACE" ClaimProviderName = "LDAPCP" @@ -516,7 +823,86 @@ try } } - Context -Name "The SPTrustedLoginProvider is desired, but the IdentifierClaim parameter does not match a claim type in ClaimsMappings" -Fixture { + if ($Global:SPDscHelper.CurrentStubBuildNumber.Major -eq 16 -and + $Global:SPDscHelper.CurrentStubBuildNumber.Build -gt 13000) + { + Context -Name "The OIDC SPTrustedLoginProvider already exists but should be removed" -Fixture { + BeforeAll { + $testParams = @{ + Name = "Contoso" + Description = "Contoso" + DefaultClientIdentifier = "fae5bd07-be63-4a64-a28c-7931a4ebf62b" + RegisteredIssuerName = "https://adfs.contoso.com/adfs" + AuthorizationEndPointUri = "https://adfs.contoso.com/adfs/oauth2/authorize" + SignOutUrl = "https://adfs.contoso.com/adfs/oauth2/logout" + IdentifierClaim = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" + ClaimsMappings = @( + (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ + Name = "Email" + IncomingClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" + } -ClientOnly) + (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ + Name = "Role" + IncomingClaimType = "http://schemas.xmlsoap.org/ExternalSTSGroupType" + LocalClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } -ClientOnly) + ) + SigningCertificateThumbprint = "123ABCFACE123ABCFACE123ABCFACE123ABCFACE" + ClaimProviderName = "LDAPCP" + Ensure = "Absent" + } + + Mock -CommandName Get-SPTrustedIdentityTokenIssuer -MockWith { + $sptrust = [pscustomobject]@{ + Name = $testParams.Name + } + $sptrust | Add-Member -Name Update -MemberType ScriptMethod -Value { } + return $sptrust + } + + Mock -CommandName Get-SPWebApplication -MockWith { + $spWebApp = [pscustomobject]@{ + Url = "http://webAppUrl" + } + $spWebApp | Add-Member -Name Update -MemberType ScriptMethod -Value { } + $spWebApp | Add-Member -Name GetIisSettingsWithFallback -MemberType ScriptMethod -Value { } + return $spWebApp + } + + Mock -CommandName Get-SPAuthenticationProvider -MockWith { + $spAP = [pscustomobject]@{ + LoginProviderName = "" + } + $spAP | Add-Member -Name Update -MemberType ScriptMethod -Value { } + $spAP | Add-Member -MemberType ScriptMethod ` + -Name GetType ` + -Value { + return @{ + FullName = "Microsoft.SharePoint.Administration.SPTrustedAuthenticationProvider" + } + } -PassThru -Force + return $spAP + } + + Mock -CommandName Remove-SPTrustedIdentityTokenIssuer -MockWith { } + } + + It "Should return absent from the get method" { + (Get-TargetResource @testParams).Ensure | Should -Be "Present" + } + + It "Should return true from the test method" { + Test-TargetResource @testParams | Should -Be $false + } + + It "Should remove the SPTrustedIdentityTokenIssuer" { + Set-TargetResource @testParams + Assert-MockCalled Remove-SPTrustedIdentityTokenIssuer + } + } + } + + Context -Name "The SAML SPTrustedLoginProvider is desired, but the IdentifierClaim parameter does not match a claim type in ClaimsMappings" -Fixture { BeforeAll { $testParams = @{ Name = "Contoso" @@ -526,14 +912,14 @@ try IdentifierClaim = "IdentityClaimTypeNotSpecifiedInClaimsMappings" ClaimsMappings = @( (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ - Name = "Email" - IncomingClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" - } -ClientOnly) + Name = "Email" + IncomingClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" + } -ClientOnly) (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ - Name = "Role" - IncomingClaimType = "http://schemas.xmlsoap.org/ExternalSTSGroupType" - LocalClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" - } -ClientOnly) + Name = "Role" + IncomingClaimType = "http://schemas.xmlsoap.org/ExternalSTSGroupType" + LocalClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } -ClientOnly) ) SigningCertificateThumbprint = "123ABCFACE123ABCFACE123ABCFACE123ABCFACE" ClaimProviderName = "LDAPCP" @@ -553,6 +939,48 @@ try } } + if ($Global:SPDscHelper.CurrentStubBuildNumber.Major -eq 16 -and + $Global:SPDscHelper.CurrentStubBuildNumber.Build -gt 13000) + { + Context -Name "The OIDC SPTrustedLoginProvider is desired, but the IdentifierClaim parameter does not match a claim type in ClaimsMappings" -Fixture { + BeforeAll { + $testParams = @{ + Name = "Contoso" + Description = "Contoso" + DefaultClientIdentifier = "fae5bd07-be63-4a64-a28c-7931a4ebf62b" + RegisteredIssuerName = "https://adfs.contoso.com/adfs" + AuthorizationEndPointUri = "https://adfs.contoso.com/adfs/oauth2/authorize" + SignOutUrl = "https://adfs.contoso.com/adfs/oauth2/logout" + IdentifierClaim = "IdentityClaimTypeNotSpecifiedInClaimsMappings" + ClaimsMappings = @( + (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ + Name = "Email" + IncomingClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" + } -ClientOnly) + (New-CimInstance -ClassName MSFT_SPClaimTypeMapping -Property @{ + Name = "Role" + IncomingClaimType = "http://schemas.xmlsoap.org/ExternalSTSGroupType" + LocalClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } -ClientOnly) + ) + SigningCertificateThumbprint = "123ABCFACE123ABCFACE123ABCFACE123ABCFACE" + ClaimProviderName = "LDAPCP" + Ensure = "Present" + } + + Mock -CommandName New-SPClaimTypeMapping -MockWith { + return [pscustomobject]@{ + InputClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" + } + } + } + + It "should fail validation of IdentifierClaim in the set method" { + { Set-TargetResource @testParams } | Should -Throw "IdentifierClaim does not match any claim type specified in ClaimsMappings." + } + } + } + Context -Name "Running ReverseDsc Export" -Fixture { BeforeAll { Import-Module (Join-Path -Path (Split-Path -Path (Get-Module SharePointDsc -ListAvailable).Path -Parent) -ChildPath "Modules\SharePointDSC.Reverse\SharePointDSC.Reverse.psm1")