Skip to main content

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Öffentliche Ansicht:Links: Erkennt, wenn ganze Ordner freigegeben sind, und listetDateien, die enthaltenenfür Dateienjeden logischim eingerücktInternet daruntersichtbar auf.sind.
  • Erkennung:Personen-Zugriff: FindetDateien, Dateiendie gezielt mit Statusexternen "JederE-Mail-Adressen mitgeteilt Link" oder "Öffentlich im Web".wurden.
  • Datenschutz:Ordner-Struktur: ListetDie nurHierarchie Dateienbleibt auf,erhalten deren(welche EigentümerDatei Sieliegt sind.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

  1. Öffnen Sie denIhr Skript-EditorGoogle auf script.google.com.Drive.
  2. 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!)

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 generateFullSharingReport ausgewä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

              Das

              WählenSkript Sienutzt obeneine dieSicherheits-Logik Funktionbei generatePublicFileReportTree.der StartenAnzeige: SieEs daswird Skript.immer Prüfender Sie"gefährlichste" das(offenste) ProtokollStatus fürin dender LinkSpalte zur"Freigabe-Status" Tabelle. priorisiert.

              Ergebnis:Hier Insind Beispiele, wie typische Szenarien in der Tabelle sehendargestellt Siewerden:

              nun

              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.

              • └─Anzeige: UnterordnerDer AStatus
                  zeigt
                • └─"Beschränkt", Dateida 1
                nur └─explizit Dateigenannte 2Personen Zugriff haben.
                Dateiname Typ Freigabe-Status Berechtigte Personen Gehaltsliste.pdf Datei 🔒 Beschränkt (Personen) └─chef@firma.de, Präsentationbuchhaltung@firma.de X Einzeln

                Szenario freigegebeneC: Komplett Öffentlich

                Situation: 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