Tool: Audit für öffentliche Google Drive Dateien
Übersicht
Dieses Skript dient der Sicherheitsüberprüfung des eigenen Google Drive Accounts. Es erstellt einen hierarchischen Bericht aller öffentlichen Inhalte.
Funktionen:
- Strukturierte Ansicht: Erkennt, wenn ganze Ordner freigegeben sind, und listet die enthaltenen Dateien logisch eingerückt darunter auf.
- Erkennung: Findet Dateien mit Status "Jeder mit Link" oder "Öffentlich im Web".
- Datenschutz: Listet nur Dateien auf, deren Eigentümer Sie sind.
Voraussetzung
Das Skript nutzt die Google Drive API v3, um große Mengen an Dateien schnell zu verarbeiten und Ordnerstrukturen zu erkennen.
Einrichtung (Einmalig)
- Öffnen Sie den Skript-Editor auf script.google.com.
- Klicken Sie links auf Dienste (Services)
+. - Wählen Sie Drive API aus.
- WICHTIG: Stellen Sie sicher, dass Version v3 ausgewählt ist.
- Klicken Sie auf Hinzufügen.
Das Skript
/**
* SKRIPT: Audit öffentlicher Google Drive Dateien (Hierarchisch)
* VERSION: 3.0 (Tree-View & Parent-Detection)
* * ZWECK:
* Listet öffentliche Dateien auf und gruppiert sie logisch unter ihren Ordnern,
* falls der Ordner ebenfalls öffentlich ist.
*/
function generatePublicFileReportTree() {
// --- 1. SETUP ---
var timestamp = new Date().toLocaleString();
var spreadsheet = SpreadsheetApp.create("Sicherheitsbericht: Öffentliche Struktur (" + timestamp + ")");
var sheet = spreadsheet.getActiveSheet();
Logger.log("Starte Scan... Daten werden gesammelt.");
// --- 2. DATEN ABFRUFEN ---
// 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;
// API Abfrage: Wir brauchen zusätzlich 'id' und 'parents' für die Struktur
do {
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, allowFileDiscovery))"
});
var files = result.files;
if (files && files.length > 0) {
for (var i = 0; i < files.length; i++) {
var file = files[i];
// Prüfen ob öffentlich (Filterung)
if (isPublic(file.permissions)) {
// Datei für die spätere Verarbeitung speichern
// Wir fügen eine leere 'children'-Liste hinzu für potentielle Unterdateien
file.children = [];
file.isPublicFound = true; // Markierung
allItemsMap[file.id] = file;
count++;
}
}
}
pageToken = result.nextPageToken;
} while (pageToken);
Logger.log(count + " öffentliche Elemente gefunden. Baue Hierarchie...");
// --- 3. HIERARCHIE BAUEN ---
// Wir gehen alle gefundenen Dateien durch und schauen, ob ihr "Eltern-Ordner" auch in der Liste ist.
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 VORBEREITEN (Rekursiv) ---
var outputRows = [];
outputRows.push(["Dateiname (Struktur)", "Typ", "Link", "Zugriffsart"]); // Header
// Funktion zum rekursiven Durchlaufen des Baums
function processNode(node, depth) {
// 1. Zugriffsart bestimmen
var accessType = getAccessTypeLabel(node.permissions);
// 2. Einrückung für den Namen basteln (Visuelle Hierarchie)
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";
// 3. Zeile hinzufügen
outputRows.push([visualName, typeLabel, node.webViewLink, accessType]);
// 4. Kinder verarbeiten (falls vorhanden)
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 wir (Ordner zuerst)
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).setValues(outputRows);
sheet.getRange("A1:D1").setFontWeight("bold");
sheet.setFrozenRows(1);
// Spalte A etwas breiter machen für die Einrückung
sheet.setColumnWidth(1, 400);
}
Logger.log("Fertig! Bericht erstellt: " + spreadsheet.getUrl());
}
// Hilfsfunktion: Prüft Berechtigung
function isPublic(perms) {
if (!perms) return false;
for (var i=0; i<perms.length; i++) {
if (perms[i].type === 'anyone') return true;
}
return false;
}
// Hilfsfunktion: Text für Tabelle
function getAccessTypeLabel(perms) {
if (!perms) return "";
for (var i=0; i<perms.length; i++) {
if (perms[i].type === 'anyone') {
return perms[i].allowFileDiscovery ? "Öffentlich (Suchbar)" : "Jeder mit Link";
}
}
return "Unbekannt";
}
Ausführung
- Wählen Sie oben die Funktion
generatePublicFileReportTree. - Starten Sie das Skript.
- Prüfen Sie das Protokoll für den Link zur Tabelle.
Ergebnis: In der Tabelle sehen Sie nun eine Struktur wie:
- Öffentlicher Projektordner
└─ Unterordner A└─ Datei 1└─ Datei 2
└─ Präsentation X
- Einzeln freigegebene Datei Y