Tool: Vollständiges Audit aller Google Drive Freigaben
1. Übersicht & Funktion
Dieses SkriptTool dient der Sicherheitsüberprüfung des eigenen Google Drive Accounts. Es erstellt eineneine hierarchischenvollständige BerichtInventur aller öffentlichenDateien, Inhalte.die nicht privat sind.
Funktionen:Das Skript erkennt:
StrukturierteÖffentlicheAnsicht:Links:Erkennt, wenn ganze Ordner freigegeben sind, und listetDateien, dieenthaltenenfürDateienjedenlogischimeingerücktInternetdaruntersichtbarauf.sind.Erkennung:Personen-Zugriff:FindetDateien,Dateiendie gezielt mitStatusexternen"JederE-Mail-AdressenmitgeteiltLink" oder "Öffentlich im Web".wurden.Datenschutz:Ordner-Struktur:ListetDienurHierarchieDateienbleibtauf,erhaltenderen(welcheEigentümerDateiSieliegtsind.in welchem Ordner).
Das Ergebnis wird automatisch in eine neue Google Tabelle exportiert.
Voraussetzung2. Anleitung für Einsteiger (Schritt-für-Schritt)
Auch ohne Programmierkenntnisse können Sie dieses Tool in wenigen Minuten einrichten.
Schritt A: Das Skript nutzt die Google Drive API v3, um große Mengen an Dateien schnell zu verarbeiten und Ordnerstrukturen zu erkennen.
Einrichtung (Einmalig)erstellen
- Öffnen Sie
denIhr Skript-EditorGoogle auf script.google.com.Drive.
- Klicken Sie oben links auf
Dienste+ Neu > Mehr > Google Apps Script.
- Es öffnet sich ein neuer Tab mit einem Code-Editor.
- Geben Sie dem Projekt oben links einen Namen (z. B.
Sicherheits-Check).
Schritt B: Die "Drive API" aktivieren (WICHTIG!)
Sicherheits-Check).Damit das Skript schnell tausende Dateien scannen darf, muss ein spezieller Dienst aktiviert werden.
- Schauen Sie im Editor auf die linke Leiste.
- Klicken Sie neben dem Punkt „Dienste“ (Services) auf das
+.Zeichen. WählenScrollen Sie in der Liste zu Drive API und wählen Sie es aus.WICHTIG:Achtung: Stellen Sie sicher, dass im Dropdown-Menü unten die Version v3 ausgewählt ist.- Klicken Sie auf Hinzufügen.
- Unter "Dienste" erscheint nun "Drive".
Schritt C: Code einfügen
- Löschen Sie im Editor den kurzen Code, der dort bereits steht (
function myFunction...). - Kopieren Sie den Code aus dem untenstehenden Abschnitt "Das Skript".
- Fügen Sie ihn in den Editor ein.
- Klicken Sie oben auf das Disketten-Symbol 💾 (Speichern).
Schritt D: Ausführen & Genehmigen
- Stellen Sie sicher, dass oben in der Leiste die Funktion
generateFullSharingReportausgewählt ist. - Klicken Sie auf ▷ Ausführen.
- Nur beim ersten Mal: Google fragt nach Berechtigungen.
- Klicken Sie auf Berechtigungen überprüfen.
- Wählen Sie Ihr Google-Konto.
- Es erscheint oft eine Warnung ("Google hasn’t verified this app"). Das ist normal, da Sie das Skript selbst erstellt haben.
- Klicken Sie links unten auf Erweitert (Advanced).
- Klicken Sie ganz unten auf den Link „Zu ... (Name des Skripts) gehen (unsicher)“.
- Klicken Sie auf Zulassen (Allow).
Schritt E: Ergebnis prüfen
Das Skript läuft nun (unten sehen Sie ein gelbes Protokoll). Sobald dort „Fertig!“ steht, finden Sie direkt daneben den Link zur Google Tabelle mit Ihren Ergebnissen.
3. Das Skript
/**
* SKRIPT: Audit öffentlicheraller Google Drive DateienFreigaben (Hierarchisch)Personen & Links)
* VERSION: 3.4.0 (Tree-ViewFull Audit & Parent-Detection)Email-List)
* * ZWECK:
* Listet öffentlicheJEDE DateienDatei aufauf, die nicht rein privat ist.
* Zeigt Freigabestatus und gruppiertkonkrete sieE-Mail-Adressen logisch unter ihren Ordnern,an.
*
falls* derVORAUSSETZUNG:
Ordner* ebenfallsDienst öffentlich"Drive ist.API" (Version 3) muss aktiviert sein.
*/
function generatePublicFileReportTree(generateFullSharingReport() {
// --- 1. SETUP ---
// Erstellt die Zieltabelle mit aktuellem Zeitstempel
var timestamp = new Date().toLocaleString();
var spreadsheet = SpreadsheetApp.create("Sicherheitsbericht: ÖffentlicheAlle StrukturFreigaben (" + timestamp + ")");
var sheet = spreadsheet.getActiveSheet();
Logger.log("Starte vollständigen Scan... Daten werden gesammelt.");
// --- 2. DATEN ABFRUFENSAMMELN ---
// Wir nutzen eine Map (Dictionary), um Dateien später ihren Eltern zuzuordnen
var allItemsMap = {};
var rootItems = [];
// Dateien/Ordner, die keine öffentlichen Eltern haben (Top-Level)
var pageToken;
var count = 0;
do {
// API v3 Abfrage: WirHolt brauchenID, zusätzlichName, 'id'Link, Eltern und 'parents'detaillierte für die Struktur
do {Berechtigungen
var result = Drive.Files.list({
q: "'me' in owners and trashed = false",
pageSize: 1000,
pageToken: pageToken,
fields: "nextPageToken, files(id, name, mimeType, webViewLink, parents, permissions(type, role, emailAddress, allowFileDiscovery))"
});
var files = result.files;
if (files && files.length > 0) {
for (var i = 0; i < files.length; i++) {
var file = files[i];
// PrüfenBerechtigungen obanalysieren
öffentlichvar analysis = analyzePermissions(file.permissions);
// Wenn die Datei NICHT privat ist (Filterung)also irgendeine Freigabe hat), nehmen wir sie auf
if (isPublic(file.permissions))analysis.isShared) {
// Datei für die spätere Verarbeitung speichern
// Wir fügen eine leere 'children'-Liste hinzu für potentielle Unterdateien
file.children = [];
file.isPublicFoundanalysis = true; // Markierunganalysis;
allItemsMap[file.id] = file;
count++;
}
}
}
pageToken = result.nextPageToken;
} while (pageToken);
Logger.log(count + " öffentlichegeteilte Elemente gefunden. Baue Hierarchie.Struktur...");
// --- 3. HIERARCHIEHIERARCHIE-STRUKTUR BAUEN ---
// Wir gehen alle gefundenenOrdnet Dateien durchihren undEltern-Ordnern schauen,zu, obum ihreinen "Eltern-Ordner"Baum auchzu in der Liste ist.erstellen
for (var id in allItemsMap) {
var item = allItemsMap[id];
var parentId = (item.parents && item.parents.length > 0) ? item.parents[0] : null;
// Wenn der Parent auch in unserer "öffentlichen Liste" ist, ordnen wir das Item dort unter
if (parentId && allItemsMap[parentId]) {
allItemsMap[parentId].children.push(item);
} else {
// Wenn der Parent NICHT öffentlich ist (oder nicht existiert), ist dieses Item ein "Root" (Startpunkt)
rootItems.push(item);
}
}
// --- 4. AUSGABE VORBEREITENGENERIEREN (Rekursiv) ---
var outputRows = [];
outputRows.push(["Dateiname (Struktur)", "Typ", "Link", "Zugriffsart"Freigabe-Status", "Berechtigte Personen"]); // Header
// Funktion zum rekursiven Durchlaufen des Baums
function processNode(node, depth) {
// 1. Zugriffsart bestimmen
var accessType = getAccessTypeLabel(node.permissions);
// 2. Einrückung für denBaumansicht Namen basteln (Visuelle Hierarchie)berechnen
var indent = "";
for (var k=0; k<depth; k++) indent += " "; // 3 Leerzeichen pro Ebene
var visualName = indent + (depth > 0 ? "└─ " : "") + node.name;
var typeLabel = (node.mimeType === 'application/vnd.google-apps.folder') ? "Ordner" : "Datei";
//var 3.status Zeile= hinzufügennode.analysis.statusLabel;
var users = node.analysis.userList;
outputRows.push([visualName, typeLabel, node.webViewLink, accessType]status, users]);
// 4. Kinder verarbeitensortieren (fallsOrdner vorhanden)zuerst, dann alphabetisch)
if (node.children.length > 0) {
// Sortieren: Ordner zuerst, dann Dateien (alphabetisch)
node.children.sort(function(a, b) {
var aIsFolder = (a.mimeType === 'application/vnd.google-apps.folder');
var bIsFolder = (b.mimeType === 'application/vnd.google-apps.folder');
if (aIsFolder && !bIsFolder) return -1;
if (!aIsFolder && bIsFolder) return 1;
return a.name.localeCompare(b.name);
});
// Rekursion: Kinder mit depth + 1 aufrufen
for (var j=0; j<node.children.length; j++) {
processNode(node.children[j], depth + 1);
}
}
}
// Alle Root-Elemente starten
// Auch die Roots sortieren wirund (OrdnerProzess zuerst)starten
rootItems.sort(function(a, b) {
var aIsFolder = (a.mimeType === 'application/vnd.google-apps.folder');
var bIsFolder = (b.mimeType === 'application/vnd.google-apps.folder');
if (aIsFolder && !bIsFolder) return -1;
if (!aIsFolder && bIsFolder) return 1;
return a.name.localeCompare(b.name);
});
for (var i=0; i<rootItems.length; i++) {
processNode(rootItems[i], 0);
}
// --- 5. IN TABELLE SCHREIBEN ---
if (outputRows.length > 1) {
// Mehr als nur Header
sheet.getRange(1, 1, outputRows.length, 4)5).setValues(outputRows);
sheet.getRange("A1:D1"E1").setFontWeight("bold");
sheet.setFrozenRows(1); // Spalte A etwas breiter machen fürFixiert die EinrückungKopfzeile
sheet.setColumnWidth(1, 400); // Verbreitert die Namensspalte
sheet.setColumnWidth(5, 300); // Verbreitert die E-Mail Spalte
}
Logger.log("Fertig! Bericht erstellt:Bericht: " + spreadsheet.getUrl());
}
/**
* HILFSFUNKTION: Analysiert Berechtigungen einer Datei
* Priorisiert öffentliche Links über Personen-Freigaben
*/ Hilfsfunktion: Prüft Berechtigung
function isPublic(analyzePermissions(perms) {
var isShared = false;
var statusLabel = "Privat";
var userEmails = [];
if (!perms) return false;{
for (var i=i = 0; i < perms.length; i++) {
var p = perms[i];
if (perms[i].typep.role === 'anyone'owner') return true;
}
return false;
}continue; // Hilfsfunktion:Eigentümer Textignorieren
fürisShared Tabelle= functiontrue;
getAccessTypeLabel(perms)// {Priorisierung des Status-Labels (Warnung bei öffentlichen Links)
if (!perms) return "";
for (var i=0; i<perms.length; i++) {
if (perms[i].p.type === 'anyone') {
returnstatusLabel perms[i].= p.allowFileDiscovery ? "⚠️ Öffentlich (Suchbar)"im Web" : "⚠️ Jeder mit Link";
} else if (p.type === 'domain' && !statusLabel.includes("⚠️")) {
statusLabel = "🏢 Domain / Firma";
} else if ((p.type === 'user' || p.type === 'group')) {
var email = p.emailAddress || "Gruppe/Unbekannt";
userEmails.push(email);
}
}
}
// Fallback: Wenn Status noch "Privat" scheint, aber User drin sind
if (statusLabel === "Privat" && userEmails.length > 0) {
statusLabel = "🔒 Beschränkt (Personen)";
}
return {
isShared: isShared,
statusLabel: statusLabel,
userList: userEmails.join("Unbekannt", ")
};
}
Ausführung4. Ergebnisse interpretieren
WählenSkriptSienutztobeneinedieSicherheits-LogikFunktionbeigeneratePublicFileReportTree.der StartenAnzeige:SieEsdaswirdSkript.immer PrüfenderSie"gefährlichste"das(offenste)ProtokollStatusfürindenderLinkSpaltezur"Freigabe-Status"Tabelle.
Das
Ergebnis:Hier Insind Beispiele, wie typische Szenarien in der Tabelle sehendargestellt Siewerden:
Szenario eineA: StrukturDer wie:Misch-Fall (Link + Person)
Situation: Ein Ordner ist per Link für jeden erreichbar ("Jeder mit Link"), aber zusätzlich wurde die Person kollege@extern.de explizit eingeladen.
ÖffentlicherAnzeige:ProjektordnerDer Status warnt vor dem öffentlichen Link (da dies das größere Sicherheitsrisiko ist). Die E-Mail-Adresse wird trotzdem rechts gelistet, damit Sie wissen, wer Zugriff behält, falls Sie den Link entfernen.
| Dateiname | Typ | Freigabe-Status | Berechtigte Personen |
|---|---|---|---|
| Projekt Alpha | Ordner | ⚠️ Jeder mit Link | kollege@extern.de |
Szenario B: Nur bestimmte Personen
Situation: Die Datei ist privat (kein öffentlicher Link), wurde aber gezielt mit Kollegen geteilt.
Status└─Anzeige:UnterordnerDerA- zeigt
└─"Beschränkt",Dateida1nur Personen Zugriff haben.└─explizitDateigenannte2
-
Dateiname Typ Freigabe-Status Berechtigte Personen Gehaltsliste.pdf Datei 🔒 Beschränkt (Personen) └─chef@firma.de,Präsentationbuchhaltung@firma.deX EinzelnSzenario
freigegebeneC: Komplett ÖffentlichSituation: Die Datei
Yist im Web veröffentlicht und kann über Suchmaschinen (Google Suche) gefunden werden, ohne dass man den Link kennt.Dateiname Typ Freigabe-Status Berechtigte Personen Webseite-Logo Datei ⚠️ Öffentlich im Web Szenario D: Firmenweiter Zugriff (Domain)
Situation: (Nur bei Google Workspace Business-Konten) Die Datei ist für jeden innerhalb der eigenen Organisation auffindbar/aufrufbar, aber nicht für Externe.
Dateiname Typ Freigabe-Status Berechtigte Personen Urlaubsantrag Datei 🏢 Domain / Firma