Zjistit, co vše veřejně sdílíte ze svého Google Drive disku je až překvapivě složité. Ve vyhledávání lze vyhledat pouze soubory, které sdílíte s konkrétní osobou. Toto manuální vyhledávání se hodí, když chcete odebrat přístup konkrétnímu člověku, firmě. Ve výsledcích pak stačí označit vše a upravit sdílení. Jak ale záhy zjistíte, tímto způsobem nelze získat seznam veřejně sdílených souborů. Placený G Suit, který používám, v reportech v admin konzoli sice má reporty se sdílením, bohužel ty zobrazují pouze počet veřejně sdílených souborů. Chybí audit, kontrola toho, co je a co není sdílené. Přitom si myslím, že je to jedna ze základních funkcí, kterou by takový systém měl poskytovat. Situaci ještě komplikuje to, že soubor označen jako privátní, může být sdílen s konkrétním člověkem.

Finální Google App Script najdete na této adrese: https://gist.github.com/tvecera/36c84d4bf96f3546c6d885c03f3a8e1a

Google Apps Script

Řešení tohoto problému je již léta stejné. Spočívá ve využití řešení třetích stran a nebo v použití Google Apps skriptu, který projde všechny soubory a např. do Google Sheets vloží seznam všech souborů s informacemi o sdílení. Při snaze použít tyto skripty jsem bohužel narazil na několik problémů:

  • Délka běhu skriptu. Při větším počtu souborů skripty nijak neřeší délku běhu. Google Apps má omezení na délku běhu skriptu – 6 min. Pro některé varianty G Suit se plánuje navýšení na 30 min, ale i to je pro desítky tisíc souborů málo. Kvóty pro GAS najdete např. tady https://developers.google.com/apps-script/guides/services/quotas.
  • Omezení seznamu pouze na sdílené soubory. U většiny skriptů se do Google Sheet zapisují všechny soubory.

Pro pořádek je potřeba uvést, že existuje i několik placených služeb. Např. placený doplněk: Google Drive Auditor, nebo https://www.whohasaccess.com/ atd. Až na uvedený doplněk je s placenými službami problém v tom, že jim musíte dát přístup ke svým souborům na Google drive disku. Je pak jenom na vás, jestli prohlášením o bezpečnosti a ochraně soukromí budete důvěřovat.

Rozhodl jsem se napsat si vlastní Google Apps skript, který bude řešit tyto problémy. Inspirací mi byly tyto projekty, články.

Omezení seznamu pouze na sdílené soubory

Na svém Google Drive disku mám bezmála 90tis souborů, a nebylo myslitelné, aby vytvářený skript zapisoval do Google Sheet tabulky všechny soubory. V první verzi skript pouze kontroloval vlastnost File.getSharingAccess() != DriveApp.Access.PRIVATE. To se ukázalo jako nedostatečné. To, že soubor je označen jako privátní, ještě neznamená, že není s nikým sdílen. Znamená to pouze to, že soubor může být sdílen pouze s konkrétními osobami a není sdílen veřejně, nebo např. formou odkazu.

File.getSharingAccess Kdo má přístup Omezení  
DriveApp.Access.PRIVATE Soubor je možné sdílet pouze s konkrétními uživateli Největší  
DriveApp.Access.DOMAIN_WITH_LINK Soubor je možné sdílet prostřednictvím linku v rámci organizace    
DriveApp.Access.DOMAIN K souboru má přístup kdokoliv z organizace    
DriveApp.Access.ANYONE_WITH_LINK K souboru má přístup kdokoliv se znalostí linku    
DriveApp.Access.ANYONE Soubor je přístupný a viditelný pro kohokoliv Nejmenší  

Postup zjištění, jestli je soubor s někým sdílený

  1. File.getSharingAccess() != DriveApp.Access.PRIVATE
  2. file.getViewers().length > 1
  3. file.getViewers().length == 1 a file.getViewers().getEmail() != email přihlášeného uživatele
  4. file. getEditors().length > 1
  5. file. getEditors().length == 1 a file. getEditors().getEmail() != email přihlášeného uživatele

function isNonPrivate(file, email) {
    /* Soubor neni oznacen jako privatni */
    if (file.getSharingAccess() !== DriveApp.Access.PRIVATE) {
        return true;
    }

    /* Soubor muze prohlizet i jiny uzivatel nez ten, ktery spustil skript */
    var size = file.getViewers().length;
    if (size !== 0) {
        if (size > 1) {
            return true;
        } else if (size === 1 && file.getViewers()[0].getEmail() !== email) {
            return true;
        }
    }

    /* Soubor muze editovat i jiny uzivatel nez ten, ktery spustil skript */
    size = file.getEditors().length;
    if (size !== 0) {
        if (size > 1) {
            return true;
        } else if (size === 1 && file.getEditors()[0].getEmail() !== email) {
            return true;
        }
    }

    return false;
}

Délka běhu skriptu

Rychlost běhu Google Apps Skriptů není nijak závratná a projít několik desítek tisíc souborů může skriptu zabrat i několik hodin. Proto Google běh skritpu omezuje na 6 min. Po tomto čase je skript ukončen s chybovou hláškou. Naštěstí Google nabízí celkem jednoduché řešení. Třída File obsahuje metodu, která vrací token, který lze použít k obnovení iterace přes seznam souborů. Token je obvykle platný po dobu jednoho týdne. Při ukončení skriptu stačí tento token uložit přes PropertiesService.setProperty. Při dalším běhu programu si token načtete a přes DriveApp.continueFileIterator(token) může skript pokračovat na místě kde dříve skončil. Pro skript je ještě potřeba nastavit trigger, který bude pouštět funkci pro zpracování souborů každých 5 min (checkGoogleDrive).

Funkce pro zpracování souborů kontroluje délku svého běhu a po nastaveném intervalu se zpracování automaticky zastaví (4 min). Nastavený trigger zajistí, že se funkce volá každých 5min a postupně zpracuje všechny soubory.


/**
 * Pomocna funkce, ktera vyhodnoti, jestli od startu skriptu ubehla nastavena max. 
 * doba behu. 
 * @param start - cas kdy skript nastartoval
 * @returns {boolean} - true jestli beh skriptu prekrocil max. delku, jinak false
 */
function checkTime(start) {
    var now = new Date();
    return now.getTime() - start.getTime() > getConstans()['MAX_TIME'];
}

Kromě omezení délky běhu skriptu aplikuje Google omezení na množství výpočetního času, který může skript za celý den spotřebovat. V takovém případě pak začne skript končit na hlášku Service using too much computer time for one day. Je to ale dočasné a většinou po několika hodinách je možné skript opět spustit. Díky nastavenému triggeru se funkce pro zpracování souborů, z uloženého iterátoru, spouští každých 5 min a hned jak je to možné, funkce pokračuje se zpracováváním souborů.

Hlášení o chybách skriptu od Google
Hlášení o chybách skriptu od Google

Použití, instalace skriptu

Nejdříve si musíte založit Google Sheet dokument. Měl by mít tuto podobu:

Google Sheet
Google Sheet

Důležitý je hlavně první řádek. V případě, že chcete aby skript běžel jenom pro konkrétní adresář, stačí do buňky B1 vložit id adresáře. To získáte jednoduše tak, že jej okopírujete z URL adresy, při procházení na Google Drive. Adresa vypadá následovně: https://drive.google.com/drive/folders/0Bz7mCbCCJ3niAAt2dmVHWjdvcW8. Id adresáře je ta část za posledním lomítkem. Jestli chcete aby skript provedl audit nad všemi soubory, stačí, když buňka B1 zůstane prázdná. Hlavičku tabulky si pak můžete zvolit jakou chcete. Skript vkládá data až za poslední řádek s daty.

Pak je potřeba založit Google App skript, přes menu Tools / Script editor:

Script Editor
Script Editor

Nakopírujte skript a nastavte již dříve zmiňovaný trigger pro periodické spouštění funkce checkGoogleDrive. Nastavení triggerů se schovává pod ikonou stopek v toolbaru.

Nastavení triggeru
Nastavení triggeru

Po opětovném otevření Google Sheet dokumentu by se v menu měla objevit nový položka – Google Drive Audit. Běh svého skriptu můžete kontrolovat přes log v Stackdriver Logging z Google Cloud Platform. Nejrychleji se k logu dostanete přes Skript Editor – Menu View / Stackdriver logging.

Log z Google Cloud Platform
Log z Google Cloud Platform

Omezení skriptu

Běh skriptu je aktuálně hodně pomalý a za 4 min běhu zvládne skript zpracovat cca 500 souborů. Určitě by šlo skript více optimalizovat, bohužel ladění performance u Google App skriptů není jednoduché a zabere hodně času. Jelikož audit nepouštím každý den, menší rychlost mi moc nevadí. Vadit by to mohlo, kdyby jste se rozhodli použít toto řešení pro velké množství souborů, případně pro nějaké firemní nasazení. Pro tyto nasazení je určitě lepší využít přímé napojení přes Google Drive API z nějakého Java, NodeJS, Python programu.