diff --git a/PiHoleShell/PiHoleShell.psd1 b/PiHoleShell/PiHoleShell.psd1 index 12c97c9..431211d 100644 Binary files a/PiHoleShell/PiHoleShell.psd1 and b/PiHoleShell/PiHoleShell.psd1 differ diff --git a/PiHoleShell/PiHoleShell.psm1 b/PiHoleShell/PiHoleShell.psm1 index 20495c5..3d038d9 100644 --- a/PiHoleShell/PiHoleShell.psm1 +++ b/PiHoleShell/PiHoleShell.psm1 @@ -12,4 +12,25 @@ foreach ($File in $PublicFunctions) { foreach ($File in $PrivateFunctions) { . $File.FullName -} \ No newline at end of file +} + +Export-ModuleMember -Function @( + #Actions.ps1 + 'Update-PiHoleActionsGravity' ` + #Authentication.ps1 + 'Remove-PiHoleCurrentAuthSession' , 'Get-PiHoleCurrentAuthSession', 'Remove-PiHoleAuthSession', ` + #GroupManagement.ps1 + 'Get-PiHoleGroup', 'New-PiHoleGroup', 'Update-PiHoleGroup', 'Remove-PiHoleGroup', ` + #DnsControl.ps1 + 'Get-PiHoleDnsBlockingStatus', 'Set-PiHoleDnsBlocking', ` + #Config.ps1 + 'Get-PiHoleConfig', 'Get-PiHoleCurrentAuthSession', 'Remove-PiHoleAuthSession', ` + #Padd.ps1 + 'Get-PiHolePadd', ` + #Metrics.ps1 + 'Get-PiHoleStatsRecentBlocked', 'Get-PiHoleStatsQueryType', 'Get-PiHoleStatsTopDomain', 'Get-PiHoleStatsSummary', ` + #ListManagement.ps1 + 'Get-PiHoleList', 'Search-PiHoleListDomain', 'Add-PiHoleList', 'Remove-PiHoleList', ` + #FTLInformation.ps1 + 'Get-PiHoleInfoMessage', 'Get-PiHoleInfoHost' +) \ No newline at end of file diff --git a/PiHoleShell/Public/Actions.ps1 b/PiHoleShell/Public/Actions.ps1 new file mode 100644 index 0000000..7788c9a --- /dev/null +++ b/PiHoleShell/Public/Actions.ps1 @@ -0,0 +1,57 @@ +function Update-PiHoleActionsGravity { + <# +.SYNOPSIS +https://TODO + + #> + #Work In Progress + [CmdletBinding(SupportsShouldProcess = $true)] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] + param ( + [Parameter(Mandatory = $true)] + [System.URI]$PiHoleServer, + [Parameter(Mandatory = $true)] + [string]$Password, + [bool]$IgnoreSsl = $false, + [bool]$RawOutput = $false + ) + try { + $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl + + $Params = @{ + Headers = @{sid = $($Sid) } + Uri = "$($PiHoleServer.OriginalString)/api/action/gravity" + Method = "Post" + SkipCertificateCheck = $IgnoreSsl + ContentType = "application/json" + } + + if ($PSCmdlet.ShouldProcess("Pi-Hole server at $PiHoleServer", "Update gravity actions")) { + $Response = Invoke-RestMethod @Params + } + + if ($RawOutput) { + Write-Output $Response + } + + else { + $ObjectFinal = @() + $Object = $null + if ($Object) { + $ObjectFinal += $Object + } + Write-Output $ObjectFinal + } + } + + catch { + Write-Error -Message $_.Exception.Message + break + } + + finally { + if ($Sid) { + Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl + } + } +} \ No newline at end of file diff --git a/PiHoleShell/Public/Config.ps1 b/PiHoleShell/Public/Config.ps1 index 1ca4ad0..a938f07 100644 --- a/PiHoleShell/Public/Config.ps1 +++ b/PiHoleShell/Public/Config.ps1 @@ -31,8 +31,35 @@ https://TODO Write-Output $Response } else { - # $ObjectFinal = @() - # Write-Output $ObjectFinal | Select-Object -Unique + $ObjectFinal = @() + $Dns = [PSCustomObject]@{ + Upstreams = $Response.config.dns.upstreams + } + + $Dhcp = [PSCustomObject]@{ + Active = $Response.config.dhcp.active + Start = $Response.config.dhcp.start + End = $Response.config.dhcp.end + Hosts = $Response.config.dhcp.hosts + IgnoreUnknownClients = $Response.config.dhcp.ignoreUnknownClients + Ipv6 = $Response.config.dhcp.ipv6 + LeaseTime = $Response.config.dhcp.leaseTime + Logging = $Response.config.dhcp.logging + MultiDNS = $Response.config.dhcp.multiDNS + Netmask = $Response.config.dhcp.netmask + RapidCommit = $Response.config.dhcp.rapidCommit + Router = $Response.config.dhcp.router + } + + $Object = [PSCustomObject]@{ + Dns = $Dns + Dhcp = $Dhcp + } + + if ($Object) { + $ObjectFinal += $Object + } + Write-Output $ObjectFinal } } diff --git a/PiHoleShell/Public/ListManagement.ps1 b/PiHoleShell/Public/ListManagement.ps1 index 7366e3d..c50efce 100644 --- a/PiHoleShell/Public/ListManagement.ps1 +++ b/PiHoleShell/Public/ListManagement.ps1 @@ -65,11 +65,293 @@ https://TODO AbpEntries = $Item.abp_entries Status = $Item.status } + if ($Object) { + $ObjectFinal += $Object + } - $ObjectFinal += $Object } + Write-Output $ObjectFinal + } + } + + catch { + Write-Error -Message $_.Exception.Message + break + } + + finally { + if ($Sid) { + Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl + } + } +} + +function Search-PiHoleListDomain { + <# +.SYNOPSIS +https://TODO + + #> + #Work In Progress + [CmdletBinding()] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] + param ( + [Parameter(Mandatory = $true)] + [System.URI]$PiHoleServer, + [Parameter(Mandatory = $true)] + [string]$Password, + [Parameter(Mandatory = $true)] + [System.URI]$Domain, + [bool]$PartialMatch = $false, + [int]$MaxResults = 20, + [bool]$IgnoreSsl = $false, + [bool]$RawOutput = $false + ) + try { + $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl + + $Body = @{ + n = $MaxResults + partial = $PartialMatch + name = $GroupName + } + + $Params = @{ + Headers = @{sid = $($Sid) } + Uri = "$($PiHoleServer.OriginalString)/api/search/$Domain" + Method = "Get" + SkipCertificateCheck = $IgnoreSsl + Body = $Body + ContentType = "application/json" + } + + $Response = Invoke-RestMethod @Params + if ($RawOutput) { + Write-Output $Response + } + + else { + $ObjectFinal = @() + foreach ($Item in $Response.lists) { + } Write-Output $ObjectFinal + } + } + + catch { + Write-Error -Message $_.Exception.Message + break + } + + finally { + if ($Sid) { + Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl + } + } +} + +function Add-PiHoleList { + <# +.SYNOPSIS +https://TODO + + #> + #Work In Progress + [CmdletBinding()] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] + param ( + [Parameter(Mandatory = $true)] + [System.URI]$PiHoleServer, + [Parameter(Mandatory = $true)] + [string]$Password, + [bool]$IgnoreSsl = $false, + [System.Uri]$Address, + [Parameter(Mandatory = $true)] + [ValidateSet("Allow", "Block")] + [string]$Type, + [string]$Comment = $null, + [string[]]$Group = "Default", + [bool]$Enabled = $true, + [bool]$RawOutput = $false + ) + try { + $FindMatchingList = Get-PiHoleList -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl | Where-Object { $_.Address -eq $Address } + + if ($FindMatchingList) { + throw "List $Address already exists on $PiHoleServer! Please use Update-PiHoleList to update the list" + } + + $AllGroups = Get-PiHoleGroup -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl + $AllGroupsNames = @() + $AllGroupsIds = @() + foreach ($GroupItem in $Group) { + + $FoundGroup = $AllGroups | Where-Object { $_.Name -eq $GroupItem } + if ($FoundGroup) { + $AllGroupsNames += $FoundGroup.Name + $AllGroupsIds += $FoundGroup.Id + Write-Verbose -Message "Found Group $($FoundGroup.Name) with $($FoundGroup.Id)" + } + else { + throw "Cannot find $GroupItem on $PiHoleServer! Please use Get-PiHoleGroup to list all groups" + } + } + + $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl + + $Body = @{ + address = $Address + type = $Type + groups = [Object[]]($AllGroupsIds) + comment = $Comment + enabled = $Enabled + } + + $Params = @{ + Headers = @{sid = $($Sid) } + Uri = "$($PiHoleServer.OriginalString)/api/lists" + Method = "Post" + SkipCertificateCheck = $IgnoreSsl + Body = $Body | ConvertTo-Json -Depth 10 + ContentType = "application/json" + } + + $Response = Invoke-RestMethod @Params + + if ($Item.date_updated -eq 0) { + $DateUpdated = $null + } + else { + $DateUpdated = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.date_modified).LocalTime + } + + if ($RawOutput) { + Write-Output $Response + } + + else { + $ObjectFinal = @() + $Object = $null + foreach ($Item in $Response.lists) { + + $Object = [PSCustomObject]@{ + Address = $Item.address + Comment = $Item.comment + Groups = $AllGroupsNames + Enabled = $Item.enabled + Id = $Item.id + DateAdded = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.date_added).LocalTime + DateModified = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.date_modified).LocalTime + Type = $Item.type.SubString(0, 1).ToUpper() + $Item.type.SubString(1).ToLower() + DateUpdated = $DateUpdated + Number = $Item.number + InvalidDomains = $Item.invalid_domains + AbpEntries = $Item.abp_entries + Status = $Item.status + } + if ($Object) { + $ObjectFinal += $Object + } + + } + Write-Output $ObjectFinal + } + } + + catch { + Write-Error -Message $_.Exception.Message + break + } + + finally { + if ($Sid) { + Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl + } + } +} + +function Remove-PiHoleList { + <# +.SYNOPSIS +https://TODO + + #> + #Work In Progress (NEED TO FINISH) + [CmdletBinding(SupportsShouldProcess = $true)] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] + param ( + [Parameter(Mandatory = $true)] + [System.URI]$PiHoleServer, + [Parameter(Mandatory = $true)] + [string]$Password, + [bool]$IgnoreSsl = $false, + [System.Uri]$Address, + [string]$Type, + [bool]$RawOutput = $false + ) + try { + $Target = "Pi-Hole list $Address of type $Type" + if ($PSCmdlet.ShouldProcess($Target, "Remove list")) { + $FindMatchingList = Get-PiHoleList -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl | Where-Object { $_.Address -eq $Address } + + if ($FindMatchingList) { + + } + + $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl + + $Body = @( + @{ + item = $Address + type = $Type.ToLower() + } + ) + + #For some reason this needs to be here to make it an array + $Body = , $Body + $Params = @{ + Headers = @{sid = $($Sid) } + Uri = "$($PiHoleServer.OriginalString)/api/lists:batchDelete" + Method = "Post" + SkipCertificateCheck = $IgnoreSsl + Body = $Body | ConvertTo-Json -Depth 10 -Compress + ContentType = "application/json" + } + + $Response = Invoke-RestMethod @Params + + if ($RawOutput) { + Write-Output $Response + } + + else { + $ObjectFinal = @() + $Object = $null + foreach ($Item in $Response.lists) { + + $Object = [PSCustomObject]@{ + Address = $Item.address + Comment = $Item.comment + Groups = $AllGroupsNames + Enabled = $Item.enabled + Id = $Item.id + DateAdded = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.date_added).LocalTime + DateModified = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.date_modified).LocalTime + Type = $Item.type.SubString(0, 1).ToUpper() + $Item.type.SubString(1).ToLower() + DateUpdated = $DateUpdated + Number = $Item.number + InvalidDomains = $Item.invalid_domains + AbpEntries = $Item.abp_entries + Status = $Item.status + } + if ($Object) { + $ObjectFinal += $Object + } + + } + Write-Output $ObjectFinal + } } } diff --git a/PiHoleShell/Public/Padd.ps1 b/PiHoleShell/Public/Padd.ps1 new file mode 100644 index 0000000..7dc47a3 --- /dev/null +++ b/PiHoleShell/Public/Padd.ps1 @@ -0,0 +1,129 @@ +function Get-PiHolePadd { + <# +.SYNOPSIS +https://TODO + + #> + #Work In Progress + [CmdletBinding()] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] + param ( + [Parameter(Mandatory = $true)] + [System.URI]$PiHoleServer, + [Parameter(Mandatory = $true)] + [string]$Password, + [bool]$IgnoreSsl = $false, + [bool]$RawOutput = $false + ) + try { + $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl + + $Params = @{ + Headers = @{sid = $($Sid) } + Uri = "$($PiHoleServer.OriginalString)/api/padd" + Method = "Get" + SkipCertificateCheck = $IgnoreSsl + ContentType = "application/json" + } + + $Response = Invoke-RestMethod @Params + + if ($RawOutput) { + Write-Output $Response + } + + else { + $ObjectFinal = @() + $Object = $null + $IFaceV4RxBytes = [PSCustomObject]@{ + Value = $Response.iface.v4.rx_bytes.value + Unit = $Response.iface.v4.rx_bytes.unit + } + $IFaceV4TxBytes = [PSCustomObject]@{ + Value = $Response.iface.v4.tx_bytes.value + Unit = $Response.iface.v4.tx_bytes.unit + } + $IFaceV4 = [PSCustomObject]@{ + Addr = $Response.iface.v4.addr + RxBytes = $IFaceV4RxBytes + TxBytes = $IFaceV4TxBytes + NumAddrs = $Response.iface.v4.num_addrs + Name = $Response.iface.v4.name + GwAddr = $Response.iface.v4.gw_addr + } + $IFaceV6 = [PSCustomObject]@{ + Addr = $Response.iface.v6.addr + NumAddrs = $Response.iface.v6.num_addrs + Name = $Response.iface.v6.name + GwAddr = $Response.iface.b6.gw_addr + } + $IFace = [PSCustomObject]@{ + v4 = $IfaceV4 + v6 = $IfaceV6 + } + $Queries = [PSCustomObject]@{ + Total = $Response.queries.total + Blocked = $Response.queries.blocked + PercentBlocked = $Response.queries.percent_blocked + } + $Sensors = [PSCustomObject]@{ + CpuTemp = $Response.sensors.cpu_temp + HotLimit = $Response.sensors.hot_limit + Unit = $Response.sensors.unit + } + $Cache = [PSCustomObject]@{ + Size = $Response.cache.size + Inserted = $Response.cache.inserted + Evicted = $Reponse.cache.evicted + } + + $Object = [PSCustomObject]@{ + CpuPercent = $Response."%cpu" + MemoryPercent = $Response."%mem" + ActiveClients = $Response.active_clients + Blocking = $Response.blocking + Cache = $Cache + Config = [PSCustomObject]@{ + DhcpActive = $Response.config.dhcp_active + DhcpStart = $Response.config.dhcp_start + DhcpEnd = $Response.config.dhcp_end + DhcpIpv6 = $Response.config.dhcp_ipv6 + DnsDnssec = $Response.config.dns_dnssec + DnsDomain = $Response.config.dns_domain + DnsNumUpstreams = $Response.config.dns_num_upstreams + DnsPort = $Response.config.dns_port + DnsrevServerAactive = $Response.config.dns_revServer_active + PrivacyLevel = $Response.config.privacy_level + } + GravitySize = $Response.gravity_size + HostModel = $Response.host_model + IFace = $IFace + NodeName = $Response.node_name + Pid = $Response.pid + Queries = $Queries + RecentBlocked = $Response.recent_blocked + Sensors = $Sensors + System = $Response.system + TopBlocked = $Response.top_blocked + TopClient = $Response.top_client + TopDomain = $Response.top_domain + Version = $Response.version + } + if ($Object) { + $ObjectFinal += $Object + } + Write-Output $ObjectFinal + } + } + + catch { + Write-Error -Message $_.Exception.Message + break + } + + finally { + if ($Sid) { + Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl + } + } +} \ No newline at end of file