Providers/FreeIPA/Public/New-FreeIPADnsZone.ps1
|
function New-FreeIPADnsZone { <# .EXTERNALHELP TestEnvironment-Help.xml .SYNOPSIS Creates the seed's own DNS zones and the records in them from Data\FreeIPADnsRecords.csv #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] [OutputType([PSCustomObject])] param( [Parameter()] [switch]$SkipRecords, [Parameter()] [switch]$PassThru ) $connection = Get-FreeIPAConnection $marker = Get-FreeIPASeedMarker -Connection $connection $zone = Get-FreeIPASeedZone -Marker $marker -Connection $connection $csvPath = Join-Path -Path (Get-FreeIPADataPath) -ChildPath 'FreeIPADnsRecords.csv' $rows = @(Import-Csv -Path $csvPath -Encoding UTF8) $result = [PSCustomObject]@{ DnsEnabled = $true ZonesCreated = 0 ZonesExisting = 0 RecordsCreated = 0 RecordsUpdated = 0 Zones = @() Errors = @() } $enabled = Invoke-FreeIPARequest -Method 'dns_is_enabled' -Connection $connection if (-not ($enabled -and $enabled.result -eq $true)) { $result.DnsEnabled = $false Write-Warning 'The realm has no DNS server, so no zone is created; the hosts will be records without addresses.' if ($PassThru) { return $result } return } $zones = [System.Collections.Generic.List[object]]::new() $ready = @{} foreach ($entry in @( @{ Name = $zone.Forward; Kind = 'Forward'; Options = @{ idnssoarname = $zone.Contact; idnsallowdynupdate = $false } } @{ Name = $zone.Reverse; Kind = 'Reverse'; Options = @{ idnssoarname = $zone.Contact; name_from_ip = $zone.Subnet } })) { if (-not $PSCmdlet.ShouldProcess($entry.Name, "Create FreeIPA $($entry.Kind.ToLowerInvariant()) DNS zone")) { continue } try { $shown = Invoke-FreeIPARequest -Method 'dnszone_show' -Arguments $entry.Name -Connection $connection -IgnoreError 'NotFound' if ($shown -and $shown.result) { $contact = ConvertFrom-FreeIPADnsName -Value $shown.result.idnssoarname if ($contact -ne $zone.Contact) { throw "Zone $($entry.Name) already exists with the contact '$contact', which is not the seed's; it is left alone." } $result.ZonesExisting++ } else { # The reverse zone is named from the subnet by the server, so its name is # not an argument; the forward zone's is. $arguments = @() if ($entry.Kind -eq 'Forward') { $arguments = @($entry.Name) } $null = Invoke-FreeIPARequest -Method 'dnszone_add' -Arguments $arguments -Options $entry.Options -Connection $connection $result.ZonesCreated++ Write-Verbose "Created DNS zone $($entry.Name)" } $ready[$entry.Kind] = $entry.Name $zones.Add([PSCustomObject]@{ Name = $entry.Name; Kind = $entry.Kind }) } catch { $message = "Failed to create DNS zone '$($entry.Name)': $($_.Exception.Message)" $result.Errors += $message Write-Error $message } } if (-not $SkipRecords) { # {prefix} and {zone} in the data become the session's prefix and the forward zone, # so an alias target is a seeded host's real name. $substitute = { param($text) ([string]$text).Replace('{prefix}', $marker.NamePrefix).Replace('{zone}', $zone.Forward) } foreach ($row in $rows) { if (-not $ready.ContainsKey($row.Zone)) { continue } $zoneName = $ready[$row.Zone] $attribute = '{0}record' -f $row.Type.ToLowerInvariant() $values = [object[]]@(($row.Data -split ';') | Where-Object { $_ } | ForEach-Object { & $substitute $_ }) if (-not $PSCmdlet.ShouldProcess("$($row.Name) $($row.Type) in $zoneName", 'Create FreeIPA DNS record')) { continue } try { $options = @{} $options[$attribute] = $values $shown = Invoke-FreeIPARequest -Method 'dnsrecord_show' -Arguments @($zoneName, $row.Name) -Connection $connection -IgnoreError 'NotFound' if ($shown -and $shown.result) { $null = Invoke-FreeIPARequest -Method 'dnsrecord_mod' -Arguments @($zoneName, $row.Name) -Options $options -Connection $connection -IgnoreError 'EmptyModlist' $result.RecordsUpdated++ } else { $null = Invoke-FreeIPARequest -Method 'dnsrecord_add' -Arguments @($zoneName, $row.Name) -Options $options -Connection $connection $result.RecordsCreated++ Write-Verbose "Created DNS record $($row.Name) $($row.Type) in $zoneName" } } catch { $message = "Failed to create DNS record '$($row.Name)' ($($row.Type)) in ${zoneName}: $($_.Exception.Message)" $result.Errors += $message Write-Error $message } } } $result.Zones = $zones.ToArray() Write-Verbose "DNS: $($result.ZonesCreated) zones created, $($result.RecordsCreated) records created, $($result.RecordsUpdated) updated, $($result.Errors.Count) problems" if ($PassThru) { return $result } } |