diff --git a/files/dashboard/index.php b/files/dashboard/index.php
index 8d137eb..25b13e6 100644
--- a/files/dashboard/index.php
+++ b/files/dashboard/index.php
@@ -1,7 +1,38 @@
+
+
+
-
-
-
-
-
-
-
-
-
+ Group Name:
+
+ Query
+
+';
$group = urlencode($_GET['group']);
- $url = "http://10.34.115.140:5000/gpo?group=$group";
+ $url = "http://172.17.0.1:5000/gpo?group=$group";
// query API
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
@@ -80,22 +107,34 @@ if (isset($_GET['group'])) {
}
ksort($gpoMap, SORT_STRING | SORT_FLAG_CASE);
if($numResults > 0){
- echo 'Total results: '.$numResults.' ';
- echo '
';
- echo 'GPO Administrators vnc_admin ';
+ echo 'Total results: '.$numResults.'
+';
+ echo '
+';
+ echo 'GPO Administrators vnc_admin
+';
foreach ($gpoMap as $gpoName => $cols) {
// Remove duplicates and build comma‑separated lists
$adminGroups = implode(' ', array_unique($cols['administrators']));
$vncGroups = implode(' ', array_unique($cols['vnc_admin']));
-
- echo '';
- echo "{$gpoName} ";
- echo "{$adminGroups} ";
- echo "{$vncGroups} ";
- echo ' ';
+ $linkedOUs = implode("\n", getLinkedOUs($gpoName));
+ echo '
+';
+ echo "
+
+";
+ echo " {$adminGroups}
+";
+ echo " {$vncGroups}
+";
+ echo '
+';
}
- echo '
';
+ echo '
+';
}
else{
echo 'No results found for query
'.$_GET['group'].' .
';
@@ -103,7 +142,23 @@ if (isset($_GET['group'])) {
}
}
+
+// if you click on a GPO name, print all OUs
+else if (isset($_GET['gpo'])) {
+ echo 'OUs linked to GPO '.$_GET['gpo'].':
';
+ $LinkedOUs = getLinkedOUs($_GET['gpo']);
+ echo implode(" ", $LinkedOUs);
+ echo ' Return Home ';
+
+}
else {
+ echo '
+
+';
echo "
No group specified.
";
}
echo "
";
diff --git a/files/restricted-group-check.ps1 b/files/restricted-group-check.ps1
index a200355..44e03d7 100644
--- a/files/restricted-group-check.ps1
+++ b/files/restricted-group-check.ps1
@@ -5,7 +5,7 @@
Import-Module GroupPolicy -ErrorAction Stop
Import-Module ActiveDirectory -ErrorAction Stop
$TargetOU = "OU=NA,OU=Manufacturing,OU=Tesla Systems,DC=teslamotors,DC=com"
-$OutputFile = "C:\Users\matanderson\gpo.yaml"
+$OutputFile = "C:\Users\matanderson\gpo\gpo-update.yaml"
# Add-Content -Path $OutputFile -Value $line
if (Test-Path $OutputFile) {
Remove-Item -Path $OutputFile -Force
@@ -34,10 +34,9 @@ if ($targetOUObj) {
# ------------------------------------------------------------------
# 2. Build a hashtable: GPO_GUID => list of OU DNs it is linked to
-# This is entirely opaque voodoo, i have no idea what's going on
# ------------------------------------------------------------------
-$gpoLinks = @{}
+$gpoLinks = @{}
foreach ($ou in $ouObjects) {
if ($ou.gPLink) {
@@ -59,6 +58,8 @@ if (-not $gpoLinks.Count) {
exit
}
+
+
Write-Host "Found $($gpoLinks.Count) distinct GPO(s) linked in the OU tree."
Add-Content -Path $OutputFile -Value " gpo_links: $($gpoLinks.Count)"
@@ -66,18 +67,28 @@ Add-Content -Path $OutputFile -Value " gpo_links: $($gpoLinks.Count)"
# 3. For each GPO, get an XML report and pull RestrictedGroup nodes
# ----------------------------------------------------
+
Add-Content -Path $OutputFile -Value " configured_gpos:"
foreach ($gpoGuid in $gpoLinks.Keys) {
try {
$gpo = Get-GPO -Guid $gpoGuid -ErrorAction Stop
}
catch {
- Write-Warning "Unable to retrieve GPO $gpoGuid - skipping."
+ Write-Warning "Unable to retrieve GPO $gpoGuid – skipping."
continue
}
Write-Host "GPO: $($gpo.DisplayName)"
Add-Content -Path $OutputFile -Value " $($gpo.DisplayName):"
+ # -------- Linked OUs ----------
+ $linkedOUs = $gpoLinks[$gpoGuid]
+ Write-Host "Linked OUs:"
+ Add-Content -Path $OutputFile -Value " Linked_OUs:"
+ foreach ($ouDn in $linkedOUs) {
+ Write-Host "$ouDn"
+ Add-Content -Path $OutputFile -Value " - $ouDn"
+ }
+
# Pull the XML report
try {
$xmlString = Get-GPOReport -Guid $gpoGuid -ReportType Xml -ErrorAction Stop
@@ -86,9 +97,8 @@ foreach ($gpoGuid in $gpoLinks.Keys) {
Write-Warning "Unable to generate XML report for $($gpo.DisplayName)."
continue
}
-
$xml = [xml]$xmlString
-
+ # process the XML data
$ns = New-Object System.Xml.XmlNamespaceManager ($xml.NameTable)
$ns.AddNamespace('m', 'http://www.microsoft.com/GroupPolicy/Settings') # default namespace
$ns.AddNamespace('q1', 'http://www.microsoft.com/GroupPolicy/Settings/Security')
diff --git a/templates/app.py b/templates/app.py
index f9355b4..9f214ed 100644
--- a/templates/app.py
+++ b/templates/app.py
@@ -37,6 +37,42 @@ def get_groups():
})
return jsonify(gpos)
+@app.route("/linked_ous", methods=["GET"])
+def linked_ous():
+ gpo_name = request.args.get("gpo")
+ if not gpo_name:
+ return jsonify({"error": "Missing 'gpo' query parameter"}), 400
+ linked = []
+ # The YAML is a list of dictionaries – iterate over them
+
+ for top in data or []:
+ cfg = top.get("configured_gpos", {})
+ if not isinstance(cfg, dict):
+ continue
+
+ # Grab the value for the requested GPO – it can be a dict *or* a list
+ gpo_entry = cfg.get(gpo_name)
+ if gpo_entry is None:
+ continue
+
+ # Case 1: direct dict → look for Linked_OUs key
+ if isinstance(gpo_entry, dict):
+ if "Linked_OUs" in gpo_entry:
+ ous = gpo_entry["Linked_OUs"]
+ if isinstance(ous, list):
+ linked.extend(ous)
+ continue
+
+ # Case 2: list of dicts → find the dict that has the Linked_OUs key
+ if isinstance(gpo_entry, list):
+ for sub in gpo_entry:
+ if isinstance(sub, dict) and "Linked_OUs" in sub:
+ ous = sub["Linked_OUs"]
+ if isinstance(ous, list):
+ linked.extend(ous)
+
+ return jsonify(linked)
+
# test route
@app.route('/test', methods=['GET'])
def test():