{"id":19055390,"url":"https://github.com/evotecit/thedashboard","last_synced_at":"2025-04-24T04:20:15.210Z","repository":{"id":207644498,"uuid":"358398009","full_name":"EvotecIT/TheDashboard","owner":"EvotecIT","description":"TheDashboard is a PowerShell module that generates nice HTML dashboard that's main goal is to integrate multiple reports created by other PowerShell modules. It's main goal is to provide a single place to see all the information you need. It's not meant to be a replacement for other modules.","archived":false,"fork":false,"pushed_at":"2025-03-17T10:31:33.000Z","size":601,"stargazers_count":13,"open_issues_count":4,"forks_count":4,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-18T12:18:45.091Z","etag":null,"topics":["dashboard","html","powershell"],"latest_commit_sha":null,"homepage":"","language":"PowerShell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/EvotecIT.png","metadata":{"files":{"readme":"README.MD","changelog":"CHANGELOG.MD","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"PrzemyslawKlys","custom":["https://paypal.me/PrzemyslawKlys"]}},"created_at":"2021-04-15T21:32:44.000Z","updated_at":"2025-04-15T20:37:31.000Z","dependencies_parsed_at":"2024-01-11T21:24:53.436Z","dependency_job_id":"a65269e9-624f-40e0-9d0e-bd68924cfb06","html_url":"https://github.com/EvotecIT/TheDashboard","commit_stats":{"total_commits":164,"total_committers":1,"mean_commits":164.0,"dds":0.0,"last_synced_commit":"c829fdf6417afadfb37e323eb66230d62d8a53fd"},"previous_names":["evotecit/thedashboard"],"tags_count":33,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EvotecIT%2FTheDashboard","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EvotecIT%2FTheDashboard/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EvotecIT%2FTheDashboard/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EvotecIT%2FTheDashboard/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/EvotecIT","download_url":"https://codeload.github.com/EvotecIT/TheDashboard/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250560929,"owners_count":21450322,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dashboard","html","powershell"],"created_at":"2024-11-08T23:44:41.972Z","updated_at":"2025-04-24T04:20:15.176Z","avatar_url":"https://github.com/EvotecIT.png","language":"PowerShell","funding_links":["https://github.com/sponsors/PrzemyslawKlys","https://paypal.me/PrzemyslawKlys"],"categories":[],"sub_categories":[],"readme":"﻿\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://www.powershellgallery.com/packages/TheDashboard\"\u003e\u003cimg src=\"https://img.shields.io/powershellgallery/v/TheDashboard.svg\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.powershellgallery.com/packages/TheDashboard\"\u003e\u003cimg src=\"https://img.shields.io/powershellgallery/vpre/TheDashboard.svg?label=powershell%20gallery%20preview\u0026colorB=yellow\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/EvotecIT/TheDashboard\"\u003e\u003cimg src=\"https://img.shields.io/github/license/EvotecIT/TheDashboard.svg\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://www.powershellgallery.com/packages/TheDashboard\"\u003e\u003cimg src=\"https://img.shields.io/powershellgallery/p/TheDashboard.svg\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/EvotecIT/TheDashboard\"\u003e\u003cimg src=\"https://img.shields.io/github/languages/top/evotecit/TheDashboard.svg\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/EvotecIT/TheDashboard\"\u003e\u003cimg src=\"https://img.shields.io/github/languages/code-size/evotecit/TheDashboard.svg\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.powershellgallery.com/packages/TheDashboard\"\u003e\u003cimg src=\"https://img.shields.io/powershellgallery/dt/TheDashboard.svg\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://twitter.com/PrzemyslawKlys\"\u003e\u003cimg src=\"https://img.shields.io/twitter/follow/PrzemyslawKlys.svg?label=Twitter%20%40PrzemyslawKlys\u0026style=social\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://evotec.xyz/hub\"\u003e\u003cimg src=\"https://img.shields.io/badge/Blog-evotec.xyz-2A6496.svg\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.linkedin.com/in/pklys\"\u003e\u003cimg src=\"https://img.shields.io/badge/LinkedIn-pklys-0077B5.svg?logo=LinkedIn\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n# TheDashboard\n\n*TheDashboard* is a PowerShell module that generates nice HTML dashboard that's main goal is to integrate multiple reports created by other PowerShell modules. It's main goal is to provide a single place to see all the information you need. It's not meant to be a replacement for other modules, but rather a way to integrate them into a single place.\n\nA lot of modules that I've created over the years such as Tesimo, ADEssentials, GPOZaurr, or other external products such as PingCastle generate HTML output. While using those modules is great, it's not always easy to see all the information in one place. TheDashboard solves this problem.\n\n### Features \u0026 ToDo\n\nThe main feature of TheDashboard is to generate HTML report that can be used to see all the information in one place.\nWhile doing so, TheDashboard provides additional insights so that the picture of infrastructure is more complete.\n\n- Gages with quick overview:\n  - [x] Active Directory - Total number of computers\n  - [x] Active Directory - Total number of users\n  - [x] Active Directory - Total number of groups\n  - [x] Active Directory - Total number of group policies\n\n- Panels available for quick overview\n  - [ ] Active Directory - Users changed password in last XXX days\n  - [ ] Active Directory - Users with password never expires\n  - [ ] Active Directory - Users with password expired in last XXX days\n  - [ ] Active Directory - Users with password expiring in next XXX days\n  - [ ] Active Directory - Computers with password last set over XXX days ago\n\n### Examples\n\n#### Example 1\n\nFollowing example shows how to generate a dashboard\n\n```powershell\nStart-TheDashboard -HTMLPath \"$PSScriptRoot\\Reports\\Index.html\" -Logo 'https://evotec.xyz/wp-content/uploads/2021/04/Logo-evotec-bb.png' -ShowHTML {\n    # Gather data for gages\n    $Today = Get-Date\n    $Forest = Get-ADForest\n    $AllUsers = $Forest.Domains | ForEach-Object { Get-ADUser -Filter * -Properties 'DistinguishedName' -Server $_ }\n    $AllComputers = $Forest.Domains | ForEach-Object { Get-ADComputer -Filter * -Properties 'DistinguishedName' -Server $_ }\n    $AllGroups = $Forest.Domains | ForEach-Object { Get-ADGroup -Filter * -Server $_ }\n    $AllGroupPolicies = $Forest.Domains | ForEach-Object { Get-GPO -All -Domain $_ }\n\n    # Top level gages\n    New-DashboardGage -Label 'Users' -MinValue 0 -MaxValue 500 -Value $AllUsers.Count -Date $Today\n    New-DashboardGage -Label 'Computers' -MinValue 0 -MaxValue 200 -Value $AllComputers.Count -Date $Today\n    New-DashboardGage -Label 'Groups' -MinValue 0 -MaxValue 200 -Value $AllGroups.Count -Date $Today\n    New-DashboardGage -Label 'Group Policies' -MinValue 0 -MaxValue 200 -Value $AllGroupPolicies.Count -Date $Today\n\n    # Folder definitions\n    New-DashboardFolder -Name 'ActiveDirectory' -IconBrands gofore -UrlName 'ActiveDirectory' -Path $PSScriptRoot\\Reports\\ActiveDirectory\n    New-DashboardFolder -Name 'GroupPolicies' -IconBrands android -UrlName 'GPO' -Path $PSScriptRoot\\Reports\\GroupPolicies\n    New-DashboardFolder -Name 'DomainControllers' -IconBrands android -UrlName 'DomainControllers' -Path $PSScriptRoot\\Reports\\DomainControllers\n\n    # Global Replacements\n    New-DashboardReplacement -SplitOn \"_\" -AddSpaceToName\n    New-DashboardReplacement -BeforeSplit @{\n        'GPOZaurr'         = ''\n        'PingCastle-'      = ''\n        'Testimo'          = ''\n        'GroupMembership-' = ''\n        '_Regional'        = ' Regional'\n    }\n    New-DashboardReplacement -AfterSplit @{\n        'G P O'     = 'GPO'\n        'L A P S'   = 'LAPS'\n        'L D A P'   = 'LDAP'\n        'K R B G T' = 'KRBGT'\n        'I N S'     = 'INS'\n        'I T R X X' = 'ITRXX'\n        'A D'       = 'AD'\n        'D H C P'   = 'DHCP'\n        'D F S'     = 'DFS'\n        'D C'       = 'DC'\n    }\n    New-DashboardLimit -LimitItem 1 -IncludeHistory\n} -StatisticsPath \"$PSScriptRoot\\Dashboard.xml\" -Verbose -Online\n```\n\n![Image](/Data/TheDashboard2.png)\n\n#### Example 2\n\nFollowing example shows how to generate a dashboard\n\n```powershell\nStart-TheDashboard -HTMLPath \"$PSScriptRoot\\Reports\\Index.html\" -Logo 'https://evotec.xyz/wp-content/uploads/2021/04/Logo-evotec-bb.png' -ShowHTML {\n    $Today = Get-Date\n    $Forest = Get-ADForest\n    $AllUsers = $Forest.Domains | ForEach-Object { Get-ADUser -Filter * -Properties 'DistinguishedName' -Server $_ }\n    $AllComputers = $Forest.Domains | ForEach-Object { Get-ADComputer -Filter * -Properties 'DistinguishedName' -Server $_ }\n    $AllGroups = $Forest.Domains | ForEach-Object { Get-ADGroup -Filter * -Server $_ }\n    $AllGroupPolicies = $Forest.Domains | ForEach-Object { Get-GPO -All -Domain $_ }\n\n    New-DashboardGage -Label 'Users' -MinValue 0 -MaxValue 500 -Value $AllUsers.Count -Date $Today\n    New-DashboardGage -Label 'Computers' -MinValue 0 -MaxValue 200 -Value $AllComputers.Count -Date $Today\n    New-DashboardGage -Label 'Groups' -MinValue 0 -MaxValue 200 -Value $AllGroups.Count -Date $Today\n    New-DashboardGage -Label 'Group Policies' -MinValue 0 -MaxValue 200 -Value $AllGroupPolicies.Count -Date $Today\n    New-DashboardFolder -Name 'ADEssentials' -IconBrands gofore -UrlName 'ADEssentials' -Path $PSScriptRoot\\Reports\\ADEssentials {\n        New-DashboardReplacement -SplitOn \"_\" -AddSpaceToName\n        New-DashboardReplacement -BeforeSplit @{\n            'GPOZaurr'         = ''\n            'PingCastle-'      = ''\n            'Testimo'          = ''\n            'GroupMembership-' = ''\n            '_Regional'        = ' Regional'\n        }\n        New-DashboardReplacement -AfterSplit @{\n            'G P O'     = 'GPO'\n            'L A P S'   = 'LAPS'\n            'L D A P'   = 'LDAP'\n            'K R B G T' = 'KRBGT'\n            'I N S'     = 'INS'\n            'I T R X X' = 'ITRXX'\n            'A D'       = 'AD'\n        }\n    } -DisableGlobalReplacement\n    New-DashboardFolder -Name 'GPOZaurr' -IconBrands gofore -UrlName 'GPOzaurr' -Path $PSScriptRoot\\Reports\\GPOZaurr\n\n    New-DashboardReplacement -SplitOn \"_\" -AddSpaceToName\n    New-DashboardReplacement -BeforeSplit @{ 'GPOZaurr' = '' }\n    New-DashboardReplacement -BeforeSplit @{ 'GroupMembership-' = ''; '_Regional' = ' Regional' }\n    New-DashboardReplacement -BeforeSplit @{\n        'GPOZaurr'    = ''\n        'PingCastle-' = ''\n        'Testimo'     = ''\n    }\n    New-DashboardReplacement -AfterSplit @{ 'G P O' = 'GPO' }, @{  'L D A P' = 'LDAP' }\n    New-DashboardReplacement -AfterSplit @{ 'L A P S' = 'LAPS' }, @{  'K R B G T' = 'KRBGT' }\n    New-DashboardReplacement -AfterSplit @{ 'A D' = 'AD' }, @{  'I T R X X' = 'ITRXX' }, @{  'I N S' = 'INS' }\n} -StatisticsPath \"$PSScriptRoot\\Dashboard.xml\" -Verbose -Online -Force\n```\n\nGenerated HTML Dashboard\n\n![Image](/Data/TheDashboard1.png)\n\n\n\n### Hosting TheDashboard on IIS\n\nTheDashboard can be used on any type of server as it generates static files that can be served by any web server.\nIt can run on IIS, Apache, Nginx, or any other web server.\nHowever, IIS is the most common one and it's the one I'm going to use in this example.\nIIS is also the one that I'm most familiar with.\n\n#### Install IIS roles\nInstall all required roles (may be too much, but it works). If you think some roles are not needed, feel free to remove them (open PR/Issue).\n\n```powershell\n$Roles = @(\n    'Web-Server'\n    'Web-WebServer'\n    'Web-Common-Http'\n    'Web-Default-Doc'\n    'Web-Dir-Browsing'\n    'Web-Http-Errors'\n    'Web-Static-Content'\n    'Web-Http-Redirect'\n    'Web-DAV-Publishing'\n    'Web-Health'\n    'Web-Http-Logging'\n    'Web-Performance'\n    'Web-Stat-Compression'\n    'Web-Security'\n    'Web-Filtering'\n    'Web-IP-Security'\n    'Web-Url-Auth'\n    'Web-Windows-Auth'\n    'Web-App-Dev'\n    'Web-Net-Ext45'\n    'Web-Asp-Net45'\n    'Web-CGI'\n    'Web-ISAPI-Ext'\n    'Web-ISAPI-Filter'\n    'Web-WebSockets'\n    'Web-Mgmt-Tools'\n    'Web-Mgmt-Console'\n)\n\nInstall-WindowsFeature -Name $Roles\n```\n\n#### Enable Authentication\nOnce IIS is installed we need to make sure data is a little bit protected. Enable windows authentication and disable anonymous authentication\n\n```powershell\nWrite-Host Disable anonymous authentication\nSet-WebConfigurationProperty -Filter '/system.webServer/security/authentication/anonymousAuthentication' -Name 'enabled' -Value 'false' -PSPath 'IIS:\\Sites\\Default Web Site'\nWrite-Host Enable windows authentication\nSet-WebConfigurationProperty -Filter '/system.webServer/security/authentication/windowsAuthentication' -Name 'enabled' -Value 'true' -PSPath 'IIS:\\Sites\\Default Web Site'\n```\n\n#### Install certificate\n\n\n#### Force Redirect to HTTPS\nBy default HTTP is enabled and it's not a good idea to have it enabled. We need to force redirect to HTTPS. To do that we need to install URL Rewrite module and configure it.\n\nYou can download URL Rewrite from https://www.iis.net/downloads/microsoft/url-rewrite#additionalDownloads\n\n\n### Hosting TheDashboard on SharePoint Online\n\nTheDashboard can be hosted on SharePoint Online. It's a little bit more tricky than hosting it on IIS, but it's doable.\nFirst of all SharePoint doesn't hosts HTML files directly. It hosts ASPX files. So we need to convert all HTML files to ASPX files.\nSecondly, SharePoint doesn't like \"\u003c%\" in the content. It tries to interpret it as a server block.\nThis is a problem because some of the reports generated by PowerShell modules contain \"\u003c%\" in the content.\n\n\n### Help commands\n\n#### Convert all .html files to .aspx files or vice versa\n\n```powershell\n$ExtensionFrom = '.html'\n$ExtensionTo = '.aspx'\n\n#$ExtensionFrom = '.aspx'\n#$ExtensionTo = '.html'\n\n$Files = Get-ChildItem -Path $PSScriptRoot\\Reports -File -Recurse -Include \"*$ExtensionFrom\"\nforeach ($File in $Files) {\n    if ($File.Extension -eq $ExtensionFrom) {\n        # Rename extension to .aspx\n        $NewName = $File.FullName -replace \"$($ExtensionFrom)$\", $ExtensionTo\n        Rename-Item -Path $File.FullName -NewName $NewName -Force\n    }\n}\n```\n\n#### Fix potential SharePoint online error\n\nThis is a fix for a SharePoint error that occurs when APSX file contains \"\u003c%\"\n\n\u003e Sorry, something went wrong. An error occurred during the processing of /sites/TheDashboard/Shared Documents/Gpozaurr_GPOBrokenPartially_2024-03-27_025637.aspx. The server block is not well formed.\n\nThe reports created by several scripts (GPOZaurr/ADEssentials/Testimo) contain \"\u003c%\" in the content, which causes SharePoint to try and interpret it as a server block.\nIn modules created by Evotec this is used by the Enlighter.JS library and may be added to file content if not used with CDN resources (lack of `Online` switch).\nSince the enlighter.js library is put inside HTML directly it causes issues with SharePoint which tries to interpret it as a server block.\nThe script will replace \"\u003c%\" with \"\u003c-%\" in all files with the .aspx extension in the Reports folder.\nSince we don't really use Enlighter.JS capability that uses this regex it should not cause issues\n\nFirst get this module from PowerShell Gallery as it gets `Get-FileEncoding` function that's needed for this script\n\n```powershell\nInstall-Module PSSharedGoods -Force -Verbose\n```\n\nThen run the script. It will replace \"\u003c%\" with \"\u003c-%\" in all files with the .aspx extension in the Reports folder.\n\n```powershell\n# look for \u003c%, if it's part of this string\n$SearchString = [regex]::Escape(\"_|:|@|#|\u003c-|←|\u003c:|\u003c%|=|=\u003e|⇒|\u003e:\")\n\n# lets replace it with \"\u003c-%\", while it won't work, it will fix SharePoint error\n$ReplaceString = [regex]::Escape(\"_|:|@|#|\u003c-|←|\u003c:|\u003c-%|=|=\u003e|⇒|\u003e:\")\n\n$Directory = \"C:\\Users\\przemyslaw.klys\\Downloads\"\n$ExtensionFrom = '.aspx'\n$Files = Get-ChildItem -Path $Directory -File -Recurse -Include \"*$ExtensionFrom\"\nforeach ($File in $Files) {\n    if ($File.Extension -eq $ExtensionFrom) {\n        $Encoding = Get-FileEncoding -Path $File.FullName\n        # Replace \"\u003c%\" with \"\u003c-%\"\n        $FileContent = Get-Content -Raw -Path $File.FullName -Encoding $Encoding\n        if ($FileContent -match $SearchString) {\n            Write-Color -Text \"Replacing offensive characters in $($File.FullName)\" -Color Green\n            $FileContent -replace $SearchString, $ReplaceString | Set-Content -Path $File.FullName -Encoding $Encoding  #-WhatIf\n        }\n    }\n}\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevotecit%2Fthedashboard","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fevotecit%2Fthedashboard","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevotecit%2Fthedashboard/lists"}