Providers/PingOne/Public/New-PingOneGroup.ps1
|
function New-PingOneGroup { <# .EXTERNALHELP TestEnvironment-Help.xml .SYNOPSIS Creates the seeded groups, nests them, and gives the dynamic ones their filters #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] [OutputType([PSCustomObject])] param( [Parameter()] [string[]]$Key, [Parameter()] [switch]$PassThru ) $connection = Get-PingOneConnection $marker = Get-PingOneSeedMarker -Prefix $connection.Prefix $rows = @(Import-Csv -LiteralPath (Join-Path (Get-PingOneDataPath) 'PingOneGroups.csv') -Encoding UTF8) if ($Key) { $rows = @($rows | Where-Object { $Key -contains $_.Key }) } $populationNameByKey = @{} foreach ($populationRow in (Import-Csv -LiteralPath (Join-Path (Get-PingOneDataPath) 'PingOnePopulations.csv') -Encoding UTF8)) { $populationNameByKey[$populationRow.Key] = Resolve-PingOneSeedName -Key $populationRow.Name ` -Kind DisplayName -Connection $connection } $populationId = @{} foreach ($population in (Invoke-PingOneRequest -Method GET -Path 'populations' -Paginate -Connection $connection)) { $populationId[[string]$population.name] = $population.id } $groupByName = @{} foreach ($group in (Invoke-PingOneRequest -Method GET -Path 'groups' -Paginate -Connection $connection)) { $groupByName[[string]$group.name] = $group } $created = [System.Collections.Generic.List[object]]::new() $reused = [System.Collections.Generic.List[object]]::new() $errors = [System.Collections.Generic.List[string]]::new() $idByKey = @{} foreach ($row in $rows) { $name = Resolve-PingOneSeedName -Key $row.Name -Kind DisplayName -Connection $connection if ($groupByName.ContainsKey($name)) { Write-Verbose "Group $name already exists; reusing" $idByKey[$row.Key] = $groupByName[$name].id $reused.Add([PSCustomObject]@{ Key = $row.Key; Name = $name; Id = $groupByName[$name].id }) continue } if (-not $PSCmdlet.ShouldProcess($name, 'Create PingOne group')) { continue } $body = @{ name = $name description = '{0} {1}' -f $row.Description, $marker.Tag } # A group scoped to a population. $scopedPopulationId = $null if ($row.Population) { $scopedName = $populationNameByKey[$row.Population] if ($scopedName -and $populationId.ContainsKey($scopedName)) { $scopedPopulationId = $populationId[$scopedName] } else { $errors.Add("Population '$($row.Population)' for group $name does not exist; run New-PingOnePopulation first") continue } } # The filter column names a shape rather than holding raw SCIM, because the population # ids it has to reference do not exist until the seed runs. switch ($row.UserFilter) { 'population' { $body['userFilter'] = 'population.id eq "{0}"' -f $scopedPopulationId } 'nobody' { # Valid, and matches no one. The username can never exist, because PingOne # refuses a username containing a space. $body['userFilter'] = 'username eq "{0}nobody matches this"' -f $marker.Prefix } default { if ($scopedPopulationId) { $body['population'] = @{ id = $scopedPopulationId } } } } try { $result = Invoke-PingOneRequest -Method POST -Path 'groups' -Body $body -Connection $connection $idByKey[$row.Key] = $result.id $created.Add([PSCustomObject]@{ Key = $row.Key; Name = $name; Id = $result.id; Filter = $body['userFilter'] }) Write-Verbose "Created group $name" } catch { $errors.Add("Could not create group ${name}: $($_.Exception.Message)") Write-Warning "Could not create group ${name}: $($_.Exception.Message)" } } # Nesting, once every group in the step exists, so the order of rows cannot matter. $nestingsApplied = 0 foreach ($row in $rows) { if (-not $row.Parent) { continue } $childId = $idByKey[$row.Key] $parentId = $idByKey[$row.Parent] if (-not $parentId) { $parentRow = @(Import-Csv -LiteralPath (Join-Path (Get-PingOneDataPath) 'PingOneGroups.csv') -Encoding UTF8 | Where-Object Key -eq $row.Parent) if ($parentRow) { $parentName = Resolve-PingOneSeedName -Key $parentRow[0].Name -Kind DisplayName -Connection $connection if ($groupByName.ContainsKey($parentName)) { $parentId = $groupByName[$parentName].id } } } if (-not $childId -or -not $parentId) { $errors.Add("Could not nest '$($row.Key)' in '$($row.Parent)': one of them does not exist") continue } if (-not $PSCmdlet.ShouldProcess("$($row.Key) -> $($row.Parent)", 'Nest PingOne group')) { continue } try { $null = Invoke-PingOneRequest -Method POST -Path "groups/$childId/memberOfGroups" ` -Body @{ id = $parentId } -Connection $connection -IgnoreError 'UNIQUENESS_VIOLATION' $nestingsApplied++ } catch { $errors.Add("Could not nest '$($row.Key)' in '$($row.Parent)': $($_.Exception.Message)") } } if ($PassThru) { return [PSCustomObject]@{ TotalGroups = @($rows).Count CreatedGroups = $created.Count ReusedGroups = $reused.Count NestingsApplied = $nestingsApplied Groups = (@($created) + @($reused)) Errors = $errors.ToArray() } } } |