Providers/FreeIPA/Public/New-FreeIPAService.ps1
|
function New-FreeIPAService { <# .EXTERNALHELP TestEnvironment-Help.xml .SYNOPSIS Creates the seeded Kerberos services and delegation rules from Data\FreeIPAServices.csv and Data\FreeIPAServiceDelegation.csv #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] [OutputType([PSCustomObject])] param( [Parameter()] [string[]]$Principal, [Parameter()] [switch]$PassThru ) $connection = Get-FreeIPAConnection $marker = Get-FreeIPASeedMarker -Connection $connection $dataPath = Get-FreeIPADataPath $servicePath = Join-Path -Path $dataPath -ChildPath 'FreeIPAServices.csv' $serviceRows = @(Import-Csv -Path $servicePath -Encoding UTF8) $delegationRows = @(Import-Csv -Path (Join-Path -Path $dataPath -ChildPath 'FreeIPAServiceDelegation.csv') -Encoding UTF8) if ($Principal) { $serviceRows = @($serviceRows | Where-Object { $Principal -contains $_.Principal }) $unknown = @($Principal | Where-Object { $serviceRows.Principal -notcontains $_ }) if ($unknown) { throw "No definition in $servicePath for: $($unknown -join ', ')" } } $result = [PSCustomObject]@{ TotalServices = $serviceRows.Count CreatedServices = 0 UpdatedServices = 0 DelegationRulesCreated = 0 DelegationTargetsCreated = 0 MembershipsApplied = 0 Services = @() Errors = @() } $split = { param($value) @([string]$value -split ';' | Where-Object { $_ }) } $record = { param($problem) $result.Errors += $problem; Write-Error $problem } # 'HTTP/web01' -> 'HTTP/zz-test-web01.zz-test-lab.ipa.example.com', and with the realm for membership. $principalOf = { param($key) $type, $hostKey = $key -split '/', 2 '{0}/{1}' -f $type, (Resolve-FreeIPASeedName -Key $hostKey -Kind Host -Marker $marker -Connection $connection) } $qualified = { param($name) if ($connection.Realm) { '{0}@{1}' -f $name, $connection.Realm } else { $name } } $existingServices = @{} foreach ($entry in (Get-FreeIPASeededObject -Type Services -Connection $connection)) { $name = [string](@($entry.krbcanonicalname)[0]) $existingServices[($name -split '@')[0]] = $entry } $existingTargets = @{} foreach ($entry in (Get-FreeIPASeededObject -Type ServiceDelegationTargets -Connection $connection)) { $existingTargets[[string](@($entry.cn)[0])] = $entry } $existingRules = @{} foreach ($entry in (Get-FreeIPASeededObject -Type ServiceDelegationRules -Connection $connection)) { $existingRules[[string](@($entry.cn)[0])] = $entry } # --- Services ------------------------------------------------------------------------------- $services = [System.Collections.Generic.List[object]]::new() foreach ($row in $serviceRows) { $name = & $principalOf $row.Principal if (-not $PSCmdlet.ShouldProcess($name, 'Create FreeIPA service')) { continue } try { $options = @{} if ($row.AuthIndicators) { $options['krbprincipalauthind'] = [object[]]@(& $split $row.AuthIndicators) } if ($existingServices.ContainsKey($name)) { if ($options.Count -gt 0) { $null = Invoke-FreeIPARequest -Method 'service_mod' -Arguments $name -Options $options -Connection $connection -IgnoreError 'EmptyModlist' } $result.UpdatedServices++ } else { # Force, because the host is a record in the seed's own zone, not a machine. $options['force'] = $true $null = Invoke-FreeIPARequest -Method 'service_add' -Arguments $name -Options $options -Connection $connection $result.CreatedServices++ Write-Verbose "Created service $name" } if ($row.ManagedBy) { $managers = @(& $split $row.ManagedBy | ForEach-Object { Resolve-FreeIPASeedName -Key $_ -Kind Host -Marker $marker -Connection $connection }) $outcome = Add-FreeIPAMember -Method 'service_add_host' -Name $name -Members @{ host = $managers } -Connection $connection $result.MembershipsApplied += $outcome.Completed foreach ($problem in $outcome.Errors) { & $record $problem } } $services.Add([PSCustomObject]@{ Key = $row.Principal; Principal = $name }) } catch { & $record "Failed to create service '$name': $($_.Exception.Message)" } } # --- Delegation: targets first, then the rules that name them ----------------------------- foreach ($row in ($delegationRows | Where-Object Kind -eq 'Target')) { $name = Resolve-FreeIPASeedName -Key $row.Name -Marker $marker -Connection $connection if (-not $PSCmdlet.ShouldProcess($name, 'Create FreeIPA service delegation target')) { continue } try { if (-not $existingTargets.ContainsKey($name)) { $null = Invoke-FreeIPARequest -Method 'servicedelegationtarget_add' -Arguments $name -Connection $connection $result.DelegationTargetsCreated++ } $members = @(& $split $row.Members | ForEach-Object { & $qualified (& $principalOf $_) }) $outcome = Add-FreeIPAMember -Method 'servicedelegationtarget_add_member' -Name $name -Members @{ principal = $members } -Connection $connection $result.MembershipsApplied += $outcome.Completed foreach ($problem in $outcome.Errors) { & $record $problem } } catch { & $record "Failed to create delegation target '$name': $($_.Exception.Message)" } } foreach ($row in ($delegationRows | Where-Object Kind -eq 'Rule')) { $name = Resolve-FreeIPASeedName -Key $row.Name -Marker $marker -Connection $connection if (-not $PSCmdlet.ShouldProcess($name, 'Create FreeIPA service delegation rule')) { continue } try { if (-not $existingRules.ContainsKey($name)) { $null = Invoke-FreeIPARequest -Method 'servicedelegationrule_add' -Arguments $name -Connection $connection $result.DelegationRulesCreated++ } $members = @(& $split $row.Members | ForEach-Object { & $qualified (& $principalOf $_) }) $outcome = Add-FreeIPAMember -Method 'servicedelegationrule_add_member' -Name $name -Members @{ principal = $members } -Connection $connection $result.MembershipsApplied += $outcome.Completed foreach ($problem in $outcome.Errors) { & $record $problem } $targets = @(& $split $row.Targets | ForEach-Object { Resolve-FreeIPASeedName -Key $_ -Marker $marker -Connection $connection }) $outcome = Add-FreeIPAMember -Method 'servicedelegationrule_add_target' -Name $name -Members @{ servicedelegationtarget = $targets } -Connection $connection $result.MembershipsApplied += $outcome.Completed foreach ($problem in $outcome.Errors) { & $record $problem } } catch { & $record "Failed to create delegation rule '$name': $($_.Exception.Message)" } } $result.Services = $services.ToArray() Write-Verbose "Services: $($result.CreatedServices) created, $($result.UpdatedServices) updated, $($result.DelegationTargetsCreated) targets, $($result.DelegationRulesCreated) rules, $($result.Errors.Count) problems" if ($PassThru) { return $result } } |