DSCResources/MSFT_SPServiceAppSecurity/MSFT_SPServiceAppSecurity.psm1
function Get-TargetResource { [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param ( [Parameter(Mandatory = $true)] [System.String] $ServiceAppName, [Parameter(Mandatory = $true)] [ValidateSet("Administrators","SharingPermissions")] [System.String] $SecurityType, [Parameter()] [Microsoft.Management.Infrastructure.CimInstance[]] $Members, [Parameter()] [Microsoft.Management.Infrastructure.CimInstance[]] $MembersToInclude, [Parameter()] [System.String[]] $MembersToExclude, [Parameter()] [System.Management.Automation.PSCredential] $InstallAccount ) Write-Verbose -Message "Getting all security options for $SecurityType in $ServiceAppName" if ($Members -and (($MembersToInclude) -or ($MembersToExclude))) { throw ("Cannot use the Members parameter together with the MembersToInclude or " + ` "MembersToExclude parameters") } if (!$Members -and !$MembersToInclude -and !$MembersToExclude) { throw ("At least one of the following parameters must be specified: Members, " + ` "MembersToInclude, MembersToExclude") } $result = Invoke-SPDSCCommand -Credential $InstallAccount ` -Arguments $PSBoundParameters ` -ScriptBlock { $params = $args[0] $serviceApp = Get-SPServiceApplication -Name $params.ServiceAppName if ($null -eq $serviceApp) { return @{ ServiceAppName = "" SecurityType = $params.SecurityType InstallAccount = $params.InstallAccount } } switch ($params.SecurityType) { "Administrators" { $security = $serviceApp | Get-SPServiceApplicationSecurity -Admin } "SharingPermissions" { $security = $serviceApp | Get-SPServiceApplicationSecurity } } $members = @() foreach ($securityEntry in $security.AccessRules) { $user = $securityEntry.Name if ($user -like "i:*|*" -or $user -like "c:*|*") { $user = (New-SPClaimsPrincipal -Identity $user -IdentityType EncodedClaim).Value if ($user -match "^s-1-[0-59]-\d+-\d+-\d+-\d+-\d+") { $user = Resolve-SPDscSecurityIdentifier -SID $user } } $accessLevel = $securityEntry.AllowedRights.ToString() $accessLevel = $accessLevel.Replace("FullControl", "Full Control") $accessLevel = $accessLevel.Replace("ChangePermissions", "Change Permissions") $members += @{ Username = $user AccessLevel = $accessLevel } } return @{ ServiceAppName = $params.ServiceAppName SecurityType = $params.SecurityType Members = $members MembersToInclude = $params.MembersToInclude MembersToExclude = $params.MembersToExclude InstallAccount = $params.InstallAccount } } return $result } function Set-TargetResource { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [System.String] $ServiceAppName, [Parameter(Mandatory = $true)] [ValidateSet("Administrators","SharingPermissions")] [System.String] $SecurityType, [Parameter()] [Microsoft.Management.Infrastructure.CimInstance[]] $Members, [Parameter()] [Microsoft.Management.Infrastructure.CimInstance[]] $MembersToInclude, [Parameter()] [System.String[]] $MembersToExclude, [Parameter()] [System.Management.Automation.PSCredential] $InstallAccount ) Write-Verbose -Message "Setting all security options for $SecurityType in $ServiceAppName" if ($Members -and (($MembersToInclude) -or ($MembersToExclude))) { throw ("Cannot use the Members parameter together with the MembersToInclude or " + ` "MembersToExclude parameters") } if (!$Members -and !$MembersToInclude -and !$MembersToExclude) { throw ("At least one of the following parameters must be specified: Members, " + ` "MembersToInclude, MembersToExclude") } $CurrentValues = Get-TargetResource @PSBoundParameters if ([System.String]::IsNullOrEmpty($CurrentValues.ServiceAppName) -eq $true) { throw "Unable to locate service application $ServiceAppName" } Invoke-SPDSCCommand -Credential $InstallAccount ` -Arguments @($PSBoundParameters, $CurrentValues) ` -ScriptBlock { $params = $args[0] $CurrentValues = $args[1] $serviceApp = Get-SPServiceApplication -Name $params.ServiceAppName switch ($params.SecurityType) { "Administrators" { $security = $serviceApp | Get-SPServiceApplicationSecurity -Admin } "SharingPermissions" { $security = $serviceApp | Get-SPServiceApplicationSecurity } } if ($params.ContainsKey("Members") -eq $true) { foreach($desiredMember in $params.Members) { $isUser = Test-SPDSCIsADUser -IdentityName $desiredMember.Username if ($isUser -eq $true) { $claim = New-SPClaimsPrincipal -Identity $desiredMember.Username ` -IdentityType WindowsSamAccountName } else { $claim = New-SPClaimsPrincipal -Identity $desiredMember.Username ` -IdentityType WindowsSecurityGroupName } if ($CurrentValues.Members.Username -contains $desiredMember.Username) { if (($CurrentValues.Members | Where-Object -FilterScript { $_.Username -eq $desiredMember.Username } | Select-Object -First 1).AccessLevel -ne $desiredMember.AccessLevel) { Revoke-SPObjectSecurity -Identity $security ` -Principal $claim Grant-SPObjectSecurity -Identity $security ` -Principal $claim ` -Rights $desiredMember.AccessLevel } } else { Grant-SPObjectSecurity -Identity $security -Principal $claim -Rights $desiredMember.AccessLevel } } foreach($currentMember in $CurrentValues.Members) { if ($params.Members.Username -notcontains $currentMember.Username) { $isUser = Test-SPDSCIsADUser -IdentityName $desiredMember.Username if ($isUser -eq $true) { $claim = New-SPClaimsPrincipal -Identity $desiredMember.Username ` -IdentityType WindowsSamAccountName } else { $claim = New-SPClaimsPrincipal -Identity $desiredMember.Username ` -IdentityType WindowsSecurityGroupName } Revoke-SPObjectSecurity -Identity $security -Principal $claim } } } if ($params.ContainsKey("MembersToInclude") -eq $true) { foreach($desiredMember in $params.MembersToInclude) { $isUser = Test-SPDSCIsADUser -IdentityName $desiredMember.Username if ($isUser -eq $true) { $claim = New-SPClaimsPrincipal -Identity $desiredMember.Username ` -IdentityType WindowsSamAccountName } else { $claim = New-SPClaimsPrincipal -Identity $desiredMember.Username ` -IdentityType WindowsSecurityGroupName } if ($CurrentValues.Members.Username -contains $desiredMember.Username) { if (($CurrentValues.Members | Where-Object -FilterScript { $_.Username -eq $desiredMember.Username } | Select-Object -First 1).AccessLevel -ne $desiredMember.AccessLevel) { Revoke-SPObjectSecurity -Identity $security ` -Principal $claim Grant-SPObjectSecurity -Identity $security ` -Principal $claim ` -Rights $desiredMember.AccessLevel } } else { Grant-SPObjectSecurity -Identity $security ` -Principal $claim ` -Rights $desiredMember.AccessLevel } } } if ($params.ContainsKey("MembersToExclude") -eq $true) { foreach($excludeMember in $params.MembersToExclude) { if ($CurrentValues.Members.Username -contains $excludeMember) { $isUser = Test-SPDSCIsADUser -IdentityName $desiredMember.Username if ($isUser -eq $true) { $claim = New-SPClaimsPrincipal -Identity $desiredMember.Username ` -IdentityType WindowsSamAccountName } else { $claim = New-SPClaimsPrincipal -Identity $desiredMember.Username ` -IdentityType WindowsSecurityGroupName } Revoke-SPObjectSecurity -Identity $security -Principal $claim } } } switch ($params.SecurityType) { "Administrators" { $security = $serviceApp | Set-SPServiceApplicationSecurity -ObjectSecurity $security ` -Admin } "SharingPermissions" { $security = $serviceApp | Set-SPServiceApplicationSecurity -ObjectSecurity $security } } } } function Test-TargetResource { [CmdletBinding()] [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] [System.String] $ServiceAppName, [Parameter(Mandatory = $true)] [ValidateSet("Administrators","SharingPermissions")] [System.String] $SecurityType, [Parameter()] [Microsoft.Management.Infrastructure.CimInstance[]] $Members, [Parameter()] [Microsoft.Management.Infrastructure.CimInstance[]] $MembersToInclude, [Parameter()] [System.String[]] $MembersToExclude, [Parameter()] [System.Management.Automation.PSCredential] $InstallAccount ) Write-Verbose -Message "Testing all security options for $SecurityType in $ServiceAppName" $CurrentValues = Get-TargetResource @PSBoundParameters if ([System.String]::IsNullOrEmpty($CurrentValues.ServiceAppName) -eq $true) { return $false } if ($Members) { Write-Verbose -Message "Processing Members parameter" if ($null -eq $CurrentValues.Members) { Write-Verbose -Message "Security list does not match" return $false } if ($CurrentValues.Members.Count -eq 0) { if ($Members.Count -gt 0) { Write-Verbose -Message "Security list does not match" return $false } else { Write-Verbose -Message "Configured and specified security lists are both empty" return $true } } $differences = Compare-Object -ReferenceObject $CurrentValues.Members.Username ` -DifferenceObject $Members.Username if ($null -eq $differences) { Write-Verbose -Message "Security list matches - checking that permissions match on each object" foreach($currentMember in $CurrentValues.Members) { if ($currentMember.AccessLevel -ne ($Members | Where-Object -FilterScript { $_.Username -eq $currentMember.Username } | Select-Object -First 1).AccessLevel) { Write-Verbose -Message "$($currentMember.Username) has incorrect permission level. Test failed." return $false } } return $true } else { Write-Verbose -Message "Security list does not match" return $false } } $result = $true if ($MembersToInclude) { Write-Verbose -Message "Processing MembersToInclude parameter" foreach ($member in $MembersToInclude) { if (-not($CurrentValues.Members.Username -contains $member.Username)) { Write-Verbose -Message "$($member.Username) does not have access. Set result to false" $result = $false } else { Write-Verbose -Message "$($member.Username) already has access. Checking permission..." if ($member.AccessLevel -ne ($CurrentValues.Members | Where-Object -FilterScript { $_.Username -eq $member.Username } | Select-Object -First 1).AccessLevel) { Write-Verbose -Message "$($member.Username) has incorrect permission level. Test failed." return $false } } } } if ($MembersToExclude) { Write-Verbose -Message "Processing MembersToExclude parameter" foreach ($member in $MembersToExclude) { if ($CurrentValues.Members.Username -contains $member.Username) { Write-Verbose -Message "$member already has access. Set result to false" $result = $false } else { Write-Verbose -Message "$member does not have access. Skipping" } } } return $result } Export-ModuleMember -Function *-TargetResource |