Providers/FreeIPA/Public/New-FreeIPACaAcl.ps1
|
function New-FreeIPACaAcl { <# .EXTERNALHELP TestEnvironment-Help.xml .SYNOPSIS Creates the seeded certificate authority access control rules from Data\FreeIPACaAcls.csv #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] [OutputType([PSCustomObject])] param( [Parameter()] [string[]]$AclName, [Parameter()] [switch]$PassThru ) $connection = Get-FreeIPAConnection $marker = Get-FreeIPASeedMarker -Connection $connection $csvPath = Join-Path -Path (Get-FreeIPADataPath) -ChildPath 'FreeIPACaAcls.csv' $rows = @(Import-Csv -Path $csvPath -Encoding UTF8) if ($AclName) { $rows = @($rows | Where-Object { $AclName -contains $_.Name }) $unknown = @($AclName | Where-Object { $rows.Name -notcontains $_ }) if ($unknown) { throw "No definition in $csvPath for: $($unknown -join ', ')" } } $result = [PSCustomObject]@{ TotalAcls = $rows.Count CreatedAcls = 0 UpdatedAcls = 0 MembershipsApplied = 0 Acls = @() Errors = @() } $split = { param($value) @([string]$value -split ';' | Where-Object { $_ }) } $named = { param($key) Resolve-FreeIPASeedName -Key $key -Marker $marker -Connection $connection } $hostNamed = { param($key) Resolve-FreeIPASeedName -Key $key -Kind Host -Marker $marker -Connection $connection } # 'HTTP/web01' -> 'HTTP/zz-test-web01.ipa.example.com@IPA.EXAMPLE.COM' $serviceNamed = { param($key) $type, $hostKey = $key -split '/', 2 $principal = '{0}/{1}' -f $type, (& $hostNamed $hostKey) if ($connection.Realm) { '{0}@{1}' -f $principal, $connection.Realm } else { $principal } } # A profile or a CA is only ever a stock object, and the row has to say so. $builtin = { param($value, $what) @(& $split $value | ForEach-Object { if ($_ -notlike 'builtin:*') { throw "A $what can only be referenced as builtin:<name>; got '$_'." } $_.Substring(8) }) } $existing = @{} foreach ($entry in (Get-FreeIPASeededObject -Type CaAcls -Connection $connection)) { $existing[[string](@($entry.cn)[0])] = $entry } $acls = [System.Collections.Generic.List[object]]::new() foreach ($row in $rows) { $name = & $named $row.Name if (-not $PSCmdlet.ShouldProcess($name, 'Create FreeIPA CA ACL')) { continue } try { $options = @{ description = ('{0} {1}' -f $row.Description, $marker.Marker).Trim() } foreach ($category in @( @{ Column = 'UserCategory'; Option = 'usercategory' }, @{ Column = 'HostCategory'; Option = 'hostcategory' }, @{ Column = 'ServiceCategory'; Option = 'servicecategory' }, @{ Column = 'ProfileCategory'; Option = 'ipacertprofilecategory' }, @{ Column = 'CaCategory'; Option = 'ipacacategory' })) { if ($row.($category.Column) -eq 'all') { $options[$category.Option] = 'all' } } if ($existing.ContainsKey($name)) { $null = Invoke-FreeIPARequest -Method 'caacl_mod' -Arguments $name -Options $options -Connection $connection -IgnoreError 'EmptyModlist' $result.UpdatedAcls++ } else { $null = Invoke-FreeIPARequest -Method 'caacl_add' -Arguments $name -Options $options -Connection $connection $result.CreatedAcls++ Write-Verbose "Created CA ACL $name" } $members = @( @{ Method = 'caacl_add_user'; Members = @{ user = @(& $split $row.Users); group = @(& $split $row.Groups | ForEach-Object { & $named $_ }) } } @{ Method = 'caacl_add_host'; Members = @{ host = @(& $split $row.Hosts | ForEach-Object { & $hostNamed $_ }); hostgroup = @(& $split $row.Hostgroups | ForEach-Object { & $named $_ }) } } @{ Method = 'caacl_add_service'; Members = @{ service = @(& $split $row.Services | ForEach-Object { & $serviceNamed $_ }) } } @{ Method = 'caacl_add_profile'; Members = @{ certprofile = @(& $builtin $row.Profiles 'certificate profile') } } @{ Method = 'caacl_add_ca'; Members = @{ ca = @(& $builtin $row.Cas 'certificate authority') } } ) foreach ($membership in $members) { $any = @($membership.Members.Values | ForEach-Object { $_ }).Count -gt 0 if (-not $any) { continue } $added = Add-FreeIPAMember -Method $membership.Method -Name $name -Members $membership.Members -Connection $connection $result.MembershipsApplied += $added.Completed foreach ($problem in $added.Errors) { $result.Errors += "CA ACL '$name': $problem" Write-Error "CA ACL '$name': $problem" } } if ($row.Enabled -eq 'FALSE') { $null = Invoke-FreeIPARequest -Method 'caacl_disable' -Arguments $name -Connection $connection -IgnoreError 'AlreadyInactive' } elseif ($existing.ContainsKey($name)) { $null = Invoke-FreeIPARequest -Method 'caacl_enable' -Arguments $name -Connection $connection -IgnoreError 'AlreadyActive' } $acls.Add([PSCustomObject]@{ Key = $row.Name; Name = $name; Enabled = ($row.Enabled -ne 'FALSE') }) } catch { $message = "Failed to create CA ACL '$name': $($_.Exception.Message)" $result.Errors += $message Write-Error $message } } $result.Acls = $acls.ToArray() Write-Verbose "CA ACLs: $($result.CreatedAcls) created, $($result.UpdatedAcls) updated, $($result.MembershipsApplied) memberships, $($result.Errors.Count) problems" if ($PassThru) { return $result } } |