diff --git a/de/15.9/config/datastore/ds-slack.rst b/de/15.9/config/datastore/ds-slack.rst index 8958db12..dddfe568 100644 --- a/de/15.9/config/datastore/ds-slack.rst +++ b/de/15.9/config/datastore/ds-slack.rst @@ -14,8 +14,17 @@ Unterstützte Inhalte - Nachrichten in öffentlichen Kanälen - Nachrichten in privaten Kanälen +- Antwortnachrichten in Threads (abgerufen über ``conversations.replies``) - Dateianhänge (optional) +Folgendes ist nicht enthalten: + +- Systemereignis-Nachrichten (``channel_join``, ``channel_topic``, ``pinned_item`` usw.) werden + standardmäßig von der Indexierung ausgeschlossen (``ignore_system_events``) +- Direktnachrichten (DMs) und Gruppen-DMs +- Huddle-Transkripte und Clips (Slack bietet hierfür keine öffentliche API, daher können sie + nicht gecrawlt werden) + Voraussetzungen =============== @@ -136,6 +145,49 @@ Parameterliste - Nein - Maximale Anzahl von Einträgen im Kanal-Informations-Cache (Standard: ``10000``) +Erweiterte Parameter +~~~~~~~~~~~~~~~~~~~~ + +Die folgenden Parameter steuern das Verbindungs- und Wiederholungsverhalten, die feingranulare +Steuerung des Crawling-Umfangs sowie die Berechtigungssynchronisierung: + +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - Parameter + - Beschreibung + * - ``connection_timeout`` + - Verbindungstimeout für jede Slack-API-Anfrage (Millisekunden, Standard: ``20000``) + * - ``read_timeout`` + - Lesetimeout für jede Slack-API-Anfrage (Millisekunden, Standard: ``20000``) + * - ``max_retry_count`` + - Maximale Anzahl an Wiederholungsversuchen nach einer ``429``-Antwort (Rate Limit) oder einer ``5xx``-Antwort (Standard: ``3``) + * - ``retry_interval`` + - Wartezeit in Millisekunden bis zum ersten Wiederholungsversuch, wenn die Antwort keinen ``Retry-After``-Header enthält (Standard: ``3000``). Verdoppelt sich mit jedem weiteren Versuch, gedeckelt bei ``60000`` Millisekunden. Enthält die Antwort einen ``Retry-After``-Header, wird stattdessen dessen Wert (in Sekunden) verwendet + * - ``executor_timeout`` + - Wartezeit in Sekunden am Ende eines Crawls, bis in der Warteschlange verbleibende Aufgaben abgeschlossen sind, bevor der Abbruch erzwungen wird (Standard: ``60``) + * - ``exclude_archived`` + - Gibt an, ob archivierte Kanäle aus den Ergebnissen von ``conversations.list`` ausgeschlossen werden (Standard: ``false``). Bei ``true`` kann ein in ``channels`` per Name angegebener archivierter Kanal nicht mehr aufgelöst werden (Details siehe Fehlerbehebung) + * - ``ignore_system_events`` + - Gibt an, ob von Slack automatisch erzeugte Kanalverwaltungsnachrichten (``channel_join``, ``channel_topic``, ``pinned_item`` usw.) von der Indexierung ausgeschlossen werden (Standard: ``true``) + * - ``read_interval`` + - Wartezeit in Millisekunden nach der Verarbeitung jeder Nachricht oder Datei (Standard: ``0`` = keine Wartezeit). Damit lässt sich das Crawling bei einem Workspace mit strengem Rate Limit verlangsamen + * - ``max_content_length`` + - Maximale Anzahl an Zeichen, die die Inhaltsextraktion (Tika) aus einer Datei extrahieren darf (Standard: nicht gesetzt, es gilt dann das MIME-Typ-spezifische Limit von |Fess|). ``max_filesize`` ist das übertragungsseitige Limit, das Dateien anhand ihrer Größe bereits vor dem Download ablehnt, während ``max_content_length`` das extraktionsseitige Limit für die nach dem Download extrahierte Textmenge ist; beide wirken unabhängig voneinander. Ein kleineres ``max_filesize`` ersetzt ``max_content_length`` nicht (z. B. kann ein 1-MB-Archiv nach der Extraktion in weit mehr Text resultieren) + * - ``permission_sync`` + - Gibt an, ob die Mitgliedschaft in privaten Kanälen in Suchberechtigungen (Rollen) umgewandelt wird (Standard: ``false``). Details siehe Abschnitt "Berechtigungssynchronisierung (ACL)" weiter unten + * - ``default_permissions`` + - Zusätzliche Berechtigungen, die unabhängig von der Kanalmitgliedschaft allen indexierten Dokumenten zugewiesen werden (Format ``{user}``/``{group}``/``{role}``, kommagetrennt, Standard: leer). Wird nur angewendet, wenn ``permission_sync`` aktiviert ist + +.. note:: + + ``ignore_system_events`` hat den Standardwert ``true``. Selbst eine bestehende Crawl-Konfiguration, + die diesen Parameter nicht setzt, indexiert nach einem Upgrade von |Fess| keine + Systemereignis-Nachrichten wie ``channel_join`` mehr -- die Anzahl indexierter Dokumente sinkt + ohne Fehler oder Warnung. Setzen Sie ``ignore_system_events=false`` explizit, um diese + Nachrichten wie bisher zu indexieren. + Skript-Einstellungen -------------------- @@ -171,6 +223,8 @@ Verfügbare Felder - Permalink der Nachricht * - ``message.attachments`` - Fallback-Informationen zu Dateianhängen + * - ``message.roles`` + - Liste der Suchberechtigungen (Rollen), die diese Nachricht oder Datei sehen dürfen. Nur vorhanden, wenn ``permission_sync=true``. Wird im Skript nicht ``role=message.roles`` zugewiesen, werden die berechneten Rollen nie in das indexierte Dokument übernommen Slack-App konfigurieren ======================= @@ -191,26 +245,32 @@ Besuchen Sie https://api.slack.com/apps: Im Menü "OAuth & Permissions": -**Bot Token Scopes** hinzufügen: +**Fügen Sie zu den Bot Token Scopes hinzu**: -Nur für öffentliche Kanäle: +Basis-Scopes (immer erforderlich): - ``channels:history`` - Lesen von Nachrichten in öffentlichen Kanälen -- ``channels:read`` - Lesen von Informationen öffentlicher Kanäle +- ``channels:read`` - Lesen von Informationen zu öffentlichen Kanälen - ``users:read`` - Lesen von Benutzerinformationen (erforderlich für die Auflösung von Anzeigenamen) +- ``team:read`` - Lesen von Workspace-Informationen. ``team.info`` wird bei jedem Crawl aufgerufen, + daher ist dieser Scope erforderlich; ohne ihn weicht dieser Konnektor für jede Nachricht auf + einen zusätzlichen ``chat.getPermalink``-Aufruf aus, was die Anzahl der API-Aufrufe deutlich + erhöht -Private Kanäle einschließen (``include_private=true``): +Bei zusätzlicher Einbeziehung privater Kanäle (``include_private=true``): -- ``channels:history`` -- ``channels:read`` - ``groups:history`` - Lesen von Nachrichten in privaten Kanälen -- ``groups:read`` - Lesen von Informationen privater Kanäle -- ``users:read`` +- ``groups:read`` - Lesen von Informationen zu privaten Kanälen -Auch Dateien crawlen (``file_crawl=true``): +Beim zusätzlichen Crawlen von Dateien (``file_crawl=true``): - ``files:read`` - Lesen von Dateiinhalten +Bei zusätzlicher Synchronisierung von Berechtigungen privater Kanäle (``permission_sync=true``): + +- ``users:read.email`` - Lesen der E-Mail-Adressen von Mitgliedern (erforderlich für die + Berechtigungssynchronisierung) + 3. App installieren ------------------- @@ -235,6 +295,86 @@ Fügen Sie die App zu den zu crawlenden Kanälen hinzu: 4. Klicken Sie auf "App hinzufügen" 5. Fügen Sie die erstellte App hinzu +Berechtigungssynchronisierung (ACL) +=================================== + +Der Slack-Konnektor kann die Mitgliedschaft eines privaten Kanals in |Fess|-Suchberechtigungen +(Rollen) umwandeln, sodass nur die Mitglieder dieses Kanals dessen Inhalt durchsuchen können. +Diese Funktion ist standardmäßig deaktiviert. + +.. note:: + + ``permission_sync`` berechnet Rollen lediglich; es wendet sie nicht automatisch an. Erst + wenn Sie im Skript ``role=message.roles`` ergänzen, werden die berechneten Rollen in den + indexierten Dokumenten übernommen. Wird diese Zuordnung vergessen, entstehen dennoch die + zusätzlichen API-Aufrufe und übersprungenen privaten Kanäle, die ``permission_sync=true`` + verursacht -- ohne dass irgendeine Zugriffskontrolle stattfindet. + +Aktivierung +----------- + +1. Fügen Sie der Slack-App den Scope ``users:read.email`` hinzu (erforderlich zur Auflösung + der E-Mail-Adressen der Mitglieder) +2. Setzen Sie in den Parametern ``permission_sync=true`` +3. Fügen Sie im Skript ``role=message.roles`` hinzu + +Parameter: + +:: + + include_private=true + permission_sync=true + +Skript: + +:: + + role=message.roles + +Fail-Closed-Verhalten +--------------------- + +Ein privater Kanal wird in einem gegebenen Crawl überhaupt nicht indexiert, wenn einer der +folgenden Fälle zutrifft (dies ist ein "Fail-Closed"-Verhalten: das Risiko besteht in einer +Unter-Indexierung, niemals darin, Inhalte versehentlich für alle offenzulegen): + +- Das Abrufen der Mitgliederliste des Kanals ist fehlgeschlagen +- Die Mitgliederliste kam leer zurück (dies passiert, wenn der Bot-Benutzer des crawlenden + Tokens selbst kein Mitglied des privaten Kanals ist) +- Der Kanal hat Mitglieder, aber für keinen von ihnen konnte eine E-Mail-Adresse aufgelöst + werden (meist weil der Scope ``users:read.email`` fehlt) + +Öffentliche Kanäle rufen ``conversations.members`` niemals auf und gelten stets als für alle +sichtbar. + +Übereinstimmung des Principal-Namens +------------------------------------ + +Die Berechtigungsprüfung zur Suchzeit verwendet den |Fess|-Anmeldenamen (den Principal-Namen). +Da die von dieser Funktion berechneten Rollen aus Slack-E-Mail-Adressen abgeleitet werden, muss +der |Fess|-Anmeldename mit der Slack-E-Mail-Adresse übereinstimmen. Slack normalisiert +E-Mail-Adressen auf Kleinschreibung, halten Sie daher auch die |Fess|-Anmeldenamen in +Kleinschreibung. Eine Abweichung legt nicht die Inhalte eines anderen Benutzers offen -- sie +führt lediglich dazu, dass die Suchergebnisse des betroffenen Benutzers stets leer sind, was +leicht mit einem unabhängigen Fehler verwechselt werden kann. + +Weitere Hinweise +---------------- + +- Slack-Benutzergruppen (User Groups) werden nicht verwendet; Berechtigungen werden direkt aus + der E-Mail-Adresse jedes einzelnen Mitglieds berechnet +- Mit ``default_permissions`` können Sie unabhängig von der Kanalmitgliedschaft zusätzliche + Berechtigungen für jedes Dokument vergeben (wird nur angewendet, wenn ``permission_sync=true``) +- Bleibt ``permission_sync=false``, während ``include_private=true`` gesetzt ist, wird der + Inhalt privater Kanäle ausschließlich anhand der im Feld "Berechtigung" der + Datenspeicher-Konfiguration hinterlegten Berechtigungen indexiert; bleibt dieses Feld leer, + ist der Inhalt de facto für alle öffentlich +- Wird ``permission_sync`` erst nachträglich aktiviert, werden bereits durch einen früheren, + uneingeschränkten Crawl indexierte Inhalte nicht rückwirkend abgesichert. Um Rollen auf diese + Inhalte anzuwenden, setzen Sie ``permission_sync=true`` und ``role=message.roles`` und + crawlen Sie danach erneut. Ebenso entfernt eine spätere Deaktivierung von ``permission_sync`` + keine Rollen, die bereits auf zuvor indexierte Dokumente angewendet wurden + Anwendungsbeispiele =================== @@ -339,9 +479,59 @@ Skript: timestamp=message.timestamp url=message.permalink +Mit Berechtigungssynchronisierung crawlen +----------------------------------------- + +Beschränkt den Inhalt privater Kanäle so, dass nur die Mitglieder dieses Kanals ihn durchsuchen +können. Fügen Sie der Slack-App vorher den Scope ``users:read.email`` hinzu. + +Parameter: + +:: + + token=xoxb-your-slack-bot-token-here + channels=*all + include_private=true + permission_sync=true + +Skript: + +:: + + title=message.user + " #" + message.channel + content=message.text + created=message.timestamp + url=message.permalink + role=message.roles + +.. note:: + + Vergessen Sie ``role=message.roles``, werden die berechneten Rollen nie in den indexierten + Dokumenten übernommen. Details siehe "Berechtigungssynchronisierung (ACL)". + Fehlerbehebung ============== +Funktionsweise der Fehlerbehandlung +----------------------------------- + +Der Slack-Konnektor unterscheidet bei Slack-API-Fehlern drei Arten: + +- **Fatale Fehler**\ (``invalid_auth``, ``token_revoked``, ``account_inactive``, + ``missing_scope``, ``not_authed``, ``token_expired``): Das Token selbst ist unbrauchbar, + daher schlägt der gesamte Crawl-Job fehl +- **Vorübergehende Fehler**\ (``ratelimited``, ``internal_error``, ``fatal_error``, + ``service_unavailable``, ``request_timeout``): Löst sich der Fehler auch durch + Wiederholungsversuche nicht, schlägt der gesamte Crawl-Job fehl (zum Wiederholungsverhalten + siehe "API-Ratenbegrenzung" weiter unten) +- **Kanalbezogene Fehler**\ (``channel_not_found``, ``not_in_channel`` usw.): Nur dieser Kanal + wird mit einer Warnung übersprungen, das Crawling der übrigen Kanäle wird fortgesetzt + +In früheren Versionen konnte ein fataler Fehler dennoch als "erfolgreicher" Crawl gemeldet +werden, der stillschweigend null oder nur einen Teil der Dokumente indexierte. Diese +Dreiteilung stellt nun sicher, dass fatale und vorübergehende Fehler stets als Job-Fehlschlag +gemeldet werden. + Authentifizierungsfehler ------------------------ @@ -368,38 +558,50 @@ Kanal nicht gefunden 1. Überprüfen Sie, ob der Kanalname korrekt ist (# ist nicht erforderlich) 2. Überprüfen Sie, ob die App zum Kanal hinzugefügt wurde 3. Bei privaten Kanälen ``include_private=true`` setzen -4. Überprüfen Sie, ob der Kanal existiert und nicht archiviert ist +4. Prüfen Sie, ob ``exclude_archived=true`` gesetzt ist. Standardmäßig + (``exclude_archived=false``) werden auch archivierte Kanäle weiterhin aufgelistet und + gecrawlt; nur bei ``true`` kann ein in ``channels`` per Name angegebener archivierter + Kanal nicht mehr aufgelöst werden -Keine Nachrichten abrufbar --------------------------- +Nachrichten können nicht abgerufen werden +----------------------------------------- -**Symptom**: Crawling erfolgreich, aber 0 Nachrichten +**Symptom**: Der Crawl ist erfolgreich, aber es werden nur wenige oder gar keine Dokumente +indexiert **Zu überprüfen**: -1. Überprüfen Sie, ob die erforderlichen Scopes erteilt wurden: +1. ``ignore_system_events`` hat den Standardwert ``true``. Bestehen die Nachrichten eines + Kanals ausschließlich aus Systemereignissen wie ``channel_join``, werden für ihn null + Dokumente indexiert (siehe "Erweiterte Parameter") +2. Prüfen Sie, ob tatsächlich Nachrichten im Kanal vorhanden sind +3. Prüfen Sie, ob die App zum Kanal hinzugefügt wurde +4. Bei ``permission_sync=true`` wird ein privater Kanal, dessen Mitgliedschaft nicht + aufgelöst werden kann, in diesem Crawl nicht indexiert (Fail-Closed; siehe + "Berechtigungssynchronisierung (ACL)") - - ``channels:history`` - - ``channels:read`` - - Bei privaten Kanälen: ``groups:history``, ``groups:read`` +.. note:: -2. Überprüfen Sie, ob Nachrichten im Kanal existieren -3. Überprüfen Sie, ob die App zum Kanal hinzugefügt wurde -4. Überprüfen Sie, ob die Slack-App aktiviert ist + In früheren Versionen konnte ein fehlender Scope (``missing_scope``) den Crawl dennoch mit + null Nachrichten "erfolgreich" abschließen lassen. Fatale Fehler, einschließlich + ``missing_scope``, lassen den gesamten Crawl-Job jetzt fehlschlagen. Schlägt Ihr Job fehl, + prüfen Sie stattdessen den folgenden Abschnitt "Fehler wegen fehlender Berechtigungen". Fehler wegen fehlender Berechtigungen ------------------------------------- -**Symptom**: ``missing_scope`` +**Symptom**: ``missing_scope`` (lässt den gesamten Crawl-Job fehlschlagen) **Lösung**: 1. Fügen Sie die erforderlichen Scopes in den Slack-App-Einstellungen hinzu: - **Öffentliche Kanäle**: + **Basis**\ (immer erforderlich): - ``channels:history`` - ``channels:read`` + - ``users:read`` + - ``team:read`` **Private Kanäle**: @@ -410,6 +612,10 @@ Fehler wegen fehlender Berechtigungen - ``files:read`` + **Berechtigungssynchronisierung**\ (``permission_sync=true``): + + - ``users:read.email`` + 2. Installieren Sie die App neu 3. Starten Sie |Fess| neu @@ -423,22 +629,47 @@ Dateien werden nicht gecrawlt 1. Überprüfen Sie, ob der Scope ``files:read`` erteilt wurde 2. Überprüfen Sie, ob tatsächlich Dateien im Kanal gepostet wurden 3. Überprüfen Sie die Zugriffsberechtigungen für die Dateien +4. Eine Datei, die größer als ``max_filesize`` ist, wird nicht heruntergeladen (prüfen Sie + das Log auf eine Warnung) API-Ratenbegrenzung ------------------- -**Symptom**: ``rate_limited`` +**Symptom**: ``ratelimited`` (lässt den gesamten Crawl-Job fehlschlagen) **Lösung**: -1. Verlängern Sie das Crawl-Intervall -2. Reduzieren Sie die Anzahl der Kanäle -3. Teilen Sie in mehrere Datenspeicher auf und verteilen Sie die Zeitplanung +1. Erhöhen Sie ``max_retry_count`` und ``retry_interval``, falls die Standardwerte das + Problem nicht lösen +2. Setzen Sie ``read_interval``, um das Crawling zu verlangsamen +3. Reduzieren Sie die Anzahl der Kanäle, oder teilen Sie in mehrere Datenspeicher auf und + verteilen Sie die Zeitpläne + +Ein ``ratelimited``-Fehler der Slack-API wird automatisch wiederholt: entweder unter +Verwendung des ``Retry-After``-Header-Werts in Sekunden, sofern vorhanden, oder andernfalls +mit einem exponentiellen Backoff ausgehend von ``retry_interval`` (bis zu +``max_retry_count`` Versuchen, gedeckelt bei 60 Sekunden). Besteht die Ratenbegrenzung nach +Ausschöpfen aller Wiederholungsversuche weiterhin, schlägt der gesamte Crawl-Job fehl. + +Slack-API-Tiers (Obergrenzen für die Aufrufhäufigkeit): + +- Tier 1: 1+ Anfragen/Minute +- Tier 2: 20+ Anfragen/Minute -- ``conversations.list``, ``users.list`` (werden zu Beginn + jedes Crawls bedingungslos vollständig abgerufen, wodurch dieser Tier am ehesten + ausgeschöpft wird) +- Tier 3: 50+ Anfragen/Minute -- ``conversations.history``, ``conversations.replies``, + ``files.list`` +- Tier 4: 100+ Anfragen/Minute -- ``conversations.members`` (nur bei + ``permission_sync=true``), ``files.info`` (wird vom Crawling dieses Konnektors derzeit + nicht aufgerufen) -Slack-API-Limits: +.. note:: -- Tier 3-Methoden: 50+ Anfragen/Minute -- Tier 4-Methoden: 100+ Anfragen/Minute + Die Verschärfung der Slack-Ratenbegrenzung vom 29. Mai 2025 (Begrenzung von + ``conversations.history`` und ``conversations.replies`` auf 50+ Anfragen/Minute) gilt nur + für Apps, die außerhalb des Workspace verteilt werden, der sie erstellt hat, etwa über den + Slack Marketplace. Sie gilt nicht für eine interne, für |Fess| erstellte App, die nur in + dem Workspace installiert ist, der sie erstellt hat. Bei großen Nachrichtenmengen ---------------------------- @@ -449,7 +680,6 @@ Bei großen Nachrichtenmengen 1. Teilen Sie Kanäle auf und konfigurieren Sie mehrere Datenspeicher 2. Verteilen Sie die Crawl-Zeitplanung -3. Erwägen Sie Einstellungen zum Ausschließen alter Nachrichten Erweiterte Skript-Beispiele =========================== @@ -482,5 +712,7 @@ Weiterführende Informationen - :doc:`ds-overview` - Übersicht der Datenspeicher-Konnektoren - :doc:`ds-atlassian` - Atlassian-Konnektor - :doc:`../../admin/dataconfig-guide` - Leitfaden zur Datenspeicher-Konfiguration +- :doc:`../security-role` - Leitfaden zur rollenbasierten Suchkonfiguration - `Slack API Documentation `_ - `Slack Bot Token Scopes `_ +- `Slack API Rate Limits `_ diff --git a/en/15.9/config/datastore/ds-slack.rst b/en/15.9/config/datastore/ds-slack.rst index cd27defb..89ef540f 100644 --- a/en/15.9/config/datastore/ds-slack.rst +++ b/en/15.9/config/datastore/ds-slack.rst @@ -15,8 +15,16 @@ Supported Content - Public channel messages - Private channel messages +- Thread reply messages (retrieved via ``conversations.replies``) - File attachments (optional) +The following are out of scope: + +- System event messages (``channel_join``, ``channel_topic``, ``pinned_item``, etc.) are + excluded from indexing by default (``ignore_system_events``) +- Direct messages (DMs) and group DMs +- Huddle transcripts and Clips (Slack has no public API for these, so they cannot be crawled) + Prerequisites ============= @@ -137,6 +145,49 @@ Parameter List - No - Maximum number of entries in the channel information cache (default: ``10000``) +Advanced Parameters +~~~~~~~~~~~~~~~~~~~ + +The following parameters control connection and retry behavior, fine-grained crawl scope, and +permission synchronization: + +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - Parameter + - Description + * - ``connection_timeout`` + - Connection timeout for each Slack API request, in milliseconds (default: ``20000``) + * - ``read_timeout`` + - Read timeout for each Slack API request, in milliseconds (default: ``20000``) + * - ``max_retry_count`` + - Maximum number of retries after a ``429`` (rate limited) or ``5xx`` response (default: ``3``) + * - ``retry_interval`` + - Wait time, in milliseconds, before the first retry when the response carries no ``Retry-After`` header (default: ``3000``). Doubles with each further attempt, capped at ``60000`` milliseconds. When the response has a ``Retry-After`` header, that value (in seconds) is used instead + * - ``executor_timeout`` + - Seconds to wait, at the end of a crawl, for queued work to finish before forcing shutdown (default: ``60``) + * - ``exclude_archived`` + - Whether to exclude archived channels from the ``conversations.list`` results (default: ``false``). When set to ``true``, an archived channel specified by name in ``channels`` can no longer be resolved (see Troubleshooting for details) + * - ``ignore_system_events`` + - Whether to exclude Slack-generated channel administration messages (``channel_join``, ``channel_topic``, ``pinned_item``, etc.) from indexing (default: ``true``) + * - ``read_interval`` + - Wait time, in milliseconds, after processing each message or file (default: ``0`` = no wait). Use this to slow down the crawl against a rate-limited workspace + * - ``max_content_length`` + - Maximum number of characters the content extractor (Tika) may extract from a file (default: unset, deferring to Fess's per-MIME-type limit). ``max_filesize`` is the transfer-side limit that rejects files by size before download, while ``max_content_length`` is the extraction-side limit on the amount of text extracted after download; the two work independently. Lowering ``max_filesize`` does not substitute for ``max_content_length`` (for example, a 1MB archive can expand into far more text once extracted) + * - ``permission_sync`` + - Whether to convert private channel membership into search permissions (roles) (default: ``false``). See "Permission Synchronization (ACL)" below for details + * - ``default_permissions`` + - Additional permissions applied to every indexed document regardless of channel membership (``{user}``/``{group}``/``{role}`` format, comma-separated, default: empty). Applied only when ``permission_sync`` is enabled + +.. note:: + + ``ignore_system_events`` defaults to ``true``. Even an existing crawl configuration that + does not set this parameter will, after upgrading |Fess|, stop indexing system event + messages such as ``channel_join`` -- the number of indexed documents will drop with no + error or warning. Set ``ignore_system_events=false`` explicitly to keep indexing these + messages as before. + Script Configuration -------------------- @@ -172,6 +223,8 @@ Available Fields - Message permalink * - ``message.attachments`` - Attachment fallback information + * - ``message.roles`` + - The list of search permissions (roles) allowed to see this message or file. Present only when ``permission_sync=true``. Unless the script maps ``role=message.roles``, the computed roles are never reflected in the indexed document Slack App Configuration ======================= @@ -194,24 +247,28 @@ In the "OAuth & Permissions" menu: **Add to Bot Token Scopes**: -For public channels only: +Base scopes (always required): - ``channels:history`` - Read public channel messages - ``channels:read`` - Read public channel information - ``users:read`` - Read user information (required for display name resolution) +- ``team:read`` - Read workspace information. ``team.info`` is called on every crawl, so this + scope is required; without it, this connector falls back to an extra + ``chat.getPermalink`` call for every message, greatly increasing the number of API calls -When including private channels (``include_private=true``): +When also including private channels (``include_private=true``): -- ``channels:history`` -- ``channels:read`` - ``groups:history`` - Read private channel messages - ``groups:read`` - Read private channel information -- ``users:read`` When also crawling files (``file_crawl=true``): - ``files:read`` - Read file content +When also synchronizing private channel permissions (``permission_sync=true``): + +- ``users:read.email`` - Read member email addresses (required for permission synchronization) + 3. Install the App ------------------ @@ -236,6 +293,82 @@ Add the app to target channels for crawling: 4. Click "Add apps" 5. Add the created app +Permission Synchronization (ACL) +================================ + +The Slack Connector can convert a private channel's membership into |Fess| search +permissions (roles), so that only that channel's members can search its content. This +feature is disabled by default. + +.. note:: + + ``permission_sync`` only computes roles; it does not apply them automatically. Only after + you add ``role=message.roles`` to the script are the computed roles reflected in indexed + documents. Forgetting this mapping still pays for the extra API calls and skipped private + channels that ``permission_sync=true`` causes, while providing no access control at all. + +Enabling It +----------- + +1. Add the ``users:read.email`` scope to the Slack App (required to resolve member email addresses) +2. Set ``permission_sync=true`` in the parameters +3. Add ``role=message.roles`` to the script + +Parameters: + +:: + + include_private=true + permission_sync=true + +Script: + +:: + + role=message.roles + +Fail-Closed Behavior +-------------------- + +A private channel is not indexed at all in a given crawl if any of the following applies +(this fails closed: the risk is under-indexing, never accidentally exposing content to +everyone): + +- Retrieving the channel's member list failed +- The member list came back empty (this happens when the crawling token's own bot user is + not itself a member of the private channel) +- The channel has members, but none of their email addresses could be resolved (usually + because the ``users:read.email`` scope is missing) + +Public channels never call ``conversations.members`` and are always treated as visible to +everyone. + +Principal Name Matching +----------------------- + +Search-time permission checks use the |Fess| login name (the principal name). Because the +roles this feature computes are derived from Slack email addresses, the |Fess| login name +must match the Slack email address. Slack normalizes email addresses to lowercase, so keep +|Fess| login names lowercase as well. A mismatch does not expose another user's content -- +it simply means the affected user's searches always return zero results, which can be easy +to mistake for an unrelated bug. + +Other Notes +----------- + +- Slack user groups are not used; permissions are computed directly from each member's + email address +- ``default_permissions`` lets you grant additional permissions to every document regardless + of channel membership (applied only when ``permission_sync=true``) +- Leaving ``permission_sync=false`` while setting ``include_private=true`` indexes private + channel content using only the permissions configured on the data store's "Permission" + field; if that field is left empty, the content is effectively public to everyone +- Enabling ``permission_sync`` later does not retroactively secure content already indexed + by an earlier, unrestricted crawl. To apply roles to that content, set + ``permission_sync=true`` and ``role=message.roles``, then re-crawl. Likewise, disabling + ``permission_sync`` afterward does not remove roles already applied to previously indexed + documents + Usage Examples ============== @@ -340,9 +473,57 @@ Script: timestamp=message.timestamp url=message.permalink +Crawl With Permission Sync +-------------------------- + +Restrict private channel content so that only that channel's members can search it. Add the +``users:read.email`` scope to the Slack App beforehand. + +Parameters: + +:: + + token=xoxb-your-slack-bot-token-here + channels=*all + include_private=true + permission_sync=true + +Script: + +:: + + title=message.user + " #" + message.channel + content=message.text + created=message.timestamp + url=message.permalink + role=message.roles + +.. note:: + + If you forget ``role=message.roles``, the computed roles are never reflected in the + indexed documents. See "Permission Synchronization (ACL)" for details. + Troubleshooting =============== +How Error Handling Works +------------------------ + +The Slack Connector treats Slack API errors as one of three kinds: + +- **Fatal errors** (``invalid_auth``, ``token_revoked``, ``account_inactive``, + ``missing_scope``, ``not_authed``, ``token_expired``): the token itself cannot be used, so + the entire crawl job fails +- **Transient errors** (``ratelimited``, ``internal_error``, ``fatal_error``, + ``service_unavailable``, ``request_timeout``): if retrying does not resolve the error, the + entire crawl job fails (see "API Rate Limiting" below for the retry behavior) +- **Channel-scoped errors** (``channel_not_found``, ``not_in_channel``, etc.): only that + channel is skipped with a warning, and crawling continues with the next channel + +In earlier versions, a fatal error could still be reported as a "successful" crawl that +silently indexed zero or only some documents. This three-way split now ensures that fatal +and transient errors are always reported as a job failure. + Authentication Error -------------------- @@ -369,38 +550,47 @@ Channel Not Found 1. Verify channel name is correct (# is not needed) 2. Verify app is added to the channel 3. For private channels, set ``include_private=true`` -4. Verify channel exists and is not archived +4. Check whether ``exclude_archived=true`` is set. By default (``exclude_archived=false``), + archived channels are still listed and crawled; only when set to ``true`` does an archived + channel specified by name in ``channels`` fail to resolve Cannot Retrieve Messages ------------------------ -**Symptom**: Crawl succeeds but 0 messages found +**Symptom**: Crawl succeeds, but few or no documents are indexed **Check**: -1. Verify required scopes are granted: +1. ``ignore_system_events`` defaults to ``true``. If a channel's messages are all system + events such as ``channel_join``, zero documents are indexed for it (see "Advanced + Parameters") +2. Verify messages actually exist in the channel +3. Verify app is added to the channel +4. With ``permission_sync=true``, a private channel whose membership cannot be resolved is + not indexed in that crawl (fail-closed; see "Permission Synchronization (ACL)") - - ``channels:history`` - - ``channels:read`` - - For private channels: ``groups:history``, ``groups:read`` +.. note:: -2. Verify messages exist in the channel -3. Verify app is added to the channel -4. Verify Slack app is enabled + In earlier versions, a missing scope (``missing_scope``) could still let the crawl + "succeed" with zero messages. Fatal errors, including ``missing_scope``, now fail the + entire crawl job. If your job is failing, check "Insufficient Permissions Error" below + instead of this section. Insufficient Permissions Error ------------------------------ -**Symptom**: ``missing_scope`` +**Symptom**: ``missing_scope`` (fails the entire crawl job) **Resolution**: 1. Add required scopes in Slack App settings: - **Public channels**: + **Base** (always required): - ``channels:history`` - ``channels:read`` + - ``users:read`` + - ``team:read`` **Private channels**: @@ -411,6 +601,10 @@ Insufficient Permissions Error - ``files:read`` + **Permission synchronization** (``permission_sync=true``): + + - ``users:read.email`` + 2. Reinstall the app 3. Restart |Fess| @@ -424,22 +618,42 @@ Cannot Crawl Files 1. Verify ``files:read`` scope is granted 2. Verify files are actually posted in the channel 3. Verify file access permissions +4. A file larger than ``max_filesize`` is not downloaded (check the log for a warning) API Rate Limiting ----------------- -**Symptom**: ``rate_limited`` +**Symptom**: ``ratelimited`` (fails the entire crawl job) **Resolution**: -1. Increase crawl interval -2. Reduce number of channels -3. Split into multiple data stores and distribute schedules +1. If the default ``max_retry_count`` and ``retry_interval`` do not resolve it, increase them +2. Set ``read_interval`` to slow down the crawl +3. Reduce the number of channels, or split into multiple data stores and distribute schedules + +A Slack API ``ratelimited`` error is retried automatically: using the ``Retry-After`` +header's value, in seconds, when present, or otherwise an exponential backoff starting from +``retry_interval`` (up to ``max_retry_count`` attempts, capped at 60 seconds). If the error +persists after every retry is exhausted, the entire crawl job fails. + +Slack API tiers (call-frequency limits): -Slack API limits: +- Tier 1: 1+ requests/minute +- Tier 2: 20+ requests/minute -- ``conversations.list``, ``users.list`` (fetched + unconditionally in full at the start of every crawl, making this the tier most likely to + be exhausted) +- Tier 3: 50+ requests/minute -- ``conversations.history``, ``conversations.replies``, + ``files.list`` +- Tier 4: 100+ requests/minute -- ``conversations.members`` (only when + ``permission_sync=true``), ``files.info`` (not currently called by this connector's crawl) + +.. note:: -- Tier 3 methods: 50+ requests/minute -- Tier 4 methods: 100+ requests/minute + Slack's May 29, 2025 rate limit tightening (limiting ``conversations.history`` and + ``conversations.replies`` to 50+ requests/minute) applies only to apps distributed outside + the workspace that created them, such as through the Slack Marketplace. It does not apply + to an internal app created for |Fess| that is installed only in the workspace that created + it. Large Number of Messages ------------------------ @@ -450,7 +664,6 @@ Large Number of Messages 1. Split channels and configure multiple data stores 2. Distribute crawl schedules -3. Consider settings to exclude old messages Advanced Script Examples ======================== @@ -483,5 +696,7 @@ Reference Information - :doc:`ds-overview` - Data Store Connector Overview - :doc:`ds-atlassian` - Atlassian Connector - :doc:`../../admin/dataconfig-guide` - Data Store Configuration Guide +- :doc:`../security-role` - Role-Based Search Configuration - `Slack API Documentation `_ - `Slack Bot Token Scopes `_ +- `Slack API Rate Limits `_ diff --git a/es/15.9/config/datastore/ds-slack.rst b/es/15.9/config/datastore/ds-slack.rst index 28d5f76f..bcf176ab 100644 --- a/es/15.9/config/datastore/ds-slack.rst +++ b/es/15.9/config/datastore/ds-slack.rst @@ -2,45 +2,54 @@ Conector de Slack ================================== -Vision General +Visión General ============== El conector de Slack proporciona funcionalidad para obtener mensajes de canales del espacio de trabajo de Slack -y registrarlos en el indice de |Fess|. +y registrarlos en el índice de |Fess|. Esta funcionalidad requiere el plugin ``fess-ds-slack``. Contenido Soportado =================== -- Mensajes de canales publicos +- Mensajes de canales públicos - Mensajes de canales privados +- Mensajes de respuesta en hilos (obtenidos mediante ``conversations.replies``) - Archivos adjuntos (opcional) +Lo siguiente queda fuera del alcance: + +- Los mensajes de eventos del sistema (``channel_join``, ``channel_topic``, ``pinned_item``, + etc.) se excluyen de la indexación de forma predeterminada (``ignore_system_events``) +- Mensajes directos (DM) y DM de grupo +- Transcripciones de Huddle y Clips (Slack no ofrece una API pública para estos, por lo que no + se pueden rastrear) + Requisitos Previos ================== -1. Se requiere la instalacion del plugin -2. Se requiere la creacion de una Slack App y configuracion de permisos -3. Se requiere la obtencion del OAuth Access Token +1. Se requiere la instalación del plugin +2. Se requiere la creación de una Slack App y configuración de permisos +3. Se requiere la obtención del OAuth Access Token -Instalacion del Plugin +Instalación del Plugin ---------------------- -Instale desde "Sistema" -> "Plugins" en la pantalla de administracion: +Instale desde "Sistema" -> "Plugins" en la pantalla de administración: 1. Descargue ``fess-ds-slack-X.X.X.jar`` desde Maven Central -2. Cargue e instale desde la pantalla de gestion de plugins +2. Cargue e instale desde la pantalla de gestión de plugins 3. Reinicie |Fess| -O consulte :doc:`../../admin/plugin-guide` para mas detalles. +O consulte :doc:`../../admin/plugin-guide` para más detalles. -Metodo de Configuracion +Método de Configuración ======================= -Configure desde la pantalla de administracion en "Rastreador" -> "Almacen de datos" -> "Nuevo". +Configure desde la pantalla de administración en "Rastreador" -> "Almacén de datos" -> "Nuevo". -Configuracion Basica +Configuración Básica -------------------- .. list-table:: @@ -56,7 +65,7 @@ Configuracion Basica * - Habilitado - Activado -Configuracion de Parametros +Configuración de Parámetros --------------------------- :: @@ -66,25 +75,25 @@ Configuracion de Parametros file_crawl=false include_private=false -Lista de Parametros +Lista de Parámetros ~~~~~~~~~~~~~~~~~~~ .. list-table:: :header-rows: 1 :widths: 25 15 60 - * - Parametro + * - Parámetro - Requerido - - Descripcion + - Descripción * - ``token`` - - Si + - Sí - OAuth Access Token de la Slack App * - ``channels`` - No - Canales a rastrear (separados por comas, o ``*all``). Si no se especifica, se obtienen todos los canales (mismo comportamiento que ``*all``) * - ``file_crawl`` - No - - Rastrear archivos tambien (predeterminado: ``false``) + - Rastrear archivos también (predeterminado: ``false``) * - ``include_private`` - No - Incluir canales privados (predeterminado: ``false``) @@ -129,15 +138,58 @@ Lista de Parametros - Número de usuarios por página de API (predeterminado: ``100``) * - ``user_cache_size`` - No - - Número máximo de entradas en el caché de información de usuarios (predeterminado: ``10000``) + - Número máximo de entradas en la caché de información de usuarios (predeterminado: ``10000``) * - ``bot_cache_size`` - No - - Número máximo de entradas en el caché de información de bots (predeterminado: ``10000``) + - Número máximo de entradas en la caché de información de bots (predeterminado: ``10000``) * - ``channel_cache_size`` - No - - Número máximo de entradas en el caché de información de canales (predeterminado: ``10000``) + - Número máximo de entradas en la caché de información de canales (predeterminado: ``10000``) + +Parámetros Avanzados +~~~~~~~~~~~~~~~~~~~~ + +Los siguientes parámetros controlan el comportamiento de conexión y reintentos, el ámbito +detallado del rastreo, y la sincronización de permisos: + +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - Parámetro + - Descripción + * - ``connection_timeout`` + - Tiempo de espera de conexión para cada solicitud a la API de Slack (milisegundos, predeterminado: ``20000``) + * - ``read_timeout`` + - Tiempo de espera de lectura para cada solicitud a la API de Slack (milisegundos, predeterminado: ``20000``) + * - ``max_retry_count`` + - Número máximo de reintentos tras una respuesta ``429`` (límite de tasa) o ``5xx`` (predeterminado: ``3``) + * - ``retry_interval`` + - Tiempo de espera en milisegundos antes del primer reintento cuando la respuesta no incluye un encabezado ``Retry-After`` (predeterminado: ``3000``). Se duplica en cada intento posterior, con un tope de ``60000`` milisegundos. Si la respuesta incluye un encabezado ``Retry-After``, se usa ese valor (en segundos) en su lugar + * - ``executor_timeout`` + - Segundos de espera, al finalizar un rastreo, para que se completen las tareas pendientes en la cola antes de forzar el cierre (predeterminado: ``60``) + * - ``exclude_archived`` + - Si se deben excluir los canales archivados de los resultados de ``conversations.list`` (predeterminado: ``false``). Con ``true``, un canal archivado especificado por nombre en ``channels`` ya no puede resolverse (véase Solución de Problemas para más detalles) + * - ``ignore_system_events`` + - Si se deben excluir de la indexación los mensajes de administración de canal generados automáticamente por Slack (``channel_join``, ``channel_topic``, ``pinned_item``, etc.) (predeterminado: ``true``) + * - ``read_interval`` + - Tiempo de espera en milisegundos tras procesar cada mensaje o archivo (predeterminado: ``0`` = sin espera). Úselo para ralentizar el rastreo frente a un espacio de trabajo con un límite de tasa estricto + * - ``max_content_length`` + - Número máximo de caracteres que el extractor de contenido (Tika) puede extraer de un archivo (predeterminado: sin definir, se aplica entonces el límite de |Fess| específico para cada tipo MIME). ``max_filesize`` es el límite del lado de la transferencia que rechaza archivos por tamaño antes de la descarga, mientras que ``max_content_length`` es el límite del lado de la extracción sobre la cantidad de texto extraído después de la descarga; ambos funcionan de forma independiente. Reducir ``max_filesize`` no sustituye a ``max_content_length`` (por ejemplo, un archivo comprimido de 1MB puede expandirse a mucho más texto al extraerse) + * - ``permission_sync`` + - Si se debe convertir la membresía de canales privados en permisos de búsqueda (roles) (predeterminado: ``false``). Véase "Sincronización de Permisos (ACL)" más adelante para más detalles + * - ``default_permissions`` + - Permisos adicionales aplicados a todos los documentos indexados independientemente de la membresía del canal (formato ``{user}``/``{group}``/``{role}``, separados por comas, predeterminado: vacío). Se aplica solo cuando ``permission_sync`` está habilitado + +.. note:: -Configuracion de Script + ``ignore_system_events`` tiene como valor predeterminado ``true``. Incluso una configuración + de rastreo existente que no defina este parámetro dejará, tras actualizar |Fess|, de indexar + mensajes de eventos del sistema como ``channel_join`` -- el número de documentos indexados + disminuirá sin ningún error ni advertencia. Especifique ``ignore_system_events=false`` + explícitamente para seguir indexando estos mensajes como antes. + +Configuración de Script ----------------------- :: @@ -157,7 +209,7 @@ Campos Disponibles :widths: 30 70 * - Campo - - Descripcion + - Descripción * - ``message.title`` - Título (cadena vacía para mensajes, nombre y título del archivo para entradas de archivo) * - ``message.text`` @@ -165,15 +217,17 @@ Campos Disponibles * - ``message.user`` - Nombre para mostrar del remitente del mensaje (si no está configurado, se resuelve en el orden de nombre real, nombre de usuario y luego ID de usuario) * - ``message.channel`` - - Nombre del canal donde se envio el mensaje + - Nombre del canal donde se envió el mensaje * - ``message.timestamp`` - - Fecha/hora de envio del mensaje + - Fecha/hora de envío del mensaje * - ``message.permalink`` - Enlace permanente del mensaje * - ``message.attachments`` - - Informacion de respaldo de archivos adjuntos + - Información de respaldo de archivos adjuntos + * - ``message.roles`` + - Lista de permisos de búsqueda (roles) autorizados a ver este mensaje o archivo. Solo está presente cuando ``permission_sync=true``. A menos que el script asigne ``role=message.roles``, los roles calculados nunca se reflejan en el documento indexado -Configuracion de Slack App +Configuración de Slack App ========================== 1. Crear Slack App @@ -183,39 +237,45 @@ Acceda a https://api.slack.com/apps: 1. Haga clic en "Create New App" 2. Seleccione "From scratch" -3. Ingrese el nombre de la aplicacion (ej: Fess Crawler) +3. Ingrese el nombre de la aplicación (ej: Fess Crawler) 4. Seleccione el espacio de trabajo 5. Haga clic en "Create App" 2. Configurar OAuth & Permissions --------------------------------- -En el menu "OAuth & Permissions": +En el menú "OAuth & Permissions": **Agregue a Bot Token Scopes**: -Para solo canales publicos: +Ámbitos básicos (siempre requeridos): -- ``channels:history`` - Lectura de mensajes de canales publicos -- ``channels:read`` - Lectura de informacion de canales publicos +- ``channels:history`` - Lectura de mensajes de canales públicos +- ``channels:read`` - Lectura de información de canales públicos - ``users:read`` - Lectura de información de usuario (requerido para resolución de nombre para mostrar) +- ``team:read`` - Lectura de información del espacio de trabajo. ``team.info`` se invoca en cada + rastreo, por lo que este ámbito es obligatorio; sin él, este conector recurre a una llamada + adicional a ``chat.getPermalink`` por cada mensaje, incrementando notablemente el número de + llamadas a la API -Para incluir canales privados (``include_private=true``): +Al incluir también canales privados (``include_private=true``): -- ``channels:history`` -- ``channels:read`` - ``groups:history`` - Lectura de mensajes de canales privados -- ``groups:read`` - Lectura de informacion de canales privados -- ``users:read`` +- ``groups:read`` - Lectura de información de canales privados -Para rastrear archivos tambien (``file_crawl=true``): +Al rastrear también archivos (``file_crawl=true``): - ``files:read`` - Lectura de contenido de archivos -3. Instalar la Aplicacion +Al sincronizar también los permisos de canales privados (``permission_sync=true``): + +- ``users:read.email`` - Lectura de las direcciones de correo de los miembros (requerido para + la sincronización de permisos) + +3. Instalar la Aplicación ------------------------- -En el menu "Install App": +En el menú "Install App": 1. Haga clic en "Install to Workspace" 2. Verifique los permisos y haga clic en "Permitir" @@ -223,7 +283,7 @@ En el menu "Install App": .. note:: Normalmente se usa el Bot User OAuth Token que comienza con ``xoxb-``, - pero tambien se puede usar el User OAuth Token que comienza con ``xoxp-`` en los parametros. + pero también se puede usar el User OAuth Token que comienza con ``xoxp-`` en los parámetros. 4. Agregar a Canales -------------------- @@ -232,17 +292,98 @@ Agregue la App a los canales que desea rastrear: 1. Abra el canal en Slack 2. Haga clic en el nombre del canal -3. Seleccione la pestana "Integraciones" -4. Haga clic en "Agregar una aplicacion" -5. Agregue la aplicacion creada +3. Seleccione la pestaña "Integraciones" +4. Haga clic en "Agregar una aplicación" +5. Agregue la aplicación creada + +Sincronización de Permisos (ACL) +================================ + +El conector de Slack puede convertir la membresía de un canal privado en permisos de búsqueda +(roles) de |Fess|, de modo que solo los miembros de ese canal puedan buscar su contenido. Esta +función está deshabilitada de forma predeterminada. + +.. note:: + + ``permission_sync`` solo calcula los roles; no los aplica automáticamente. Solo después de + agregar ``role=message.roles`` al script, los roles calculados se reflejan en los documentos + indexados. Olvidar este mapeo igualmente incurre en las llamadas adicionales a la API y en la + omisión de canales privados que provoca ``permission_sync=true``, sin proporcionar ningún + control de acceso. + +Habilitarlo +----------- + +1. Agregue el ámbito ``users:read.email`` a la Slack App (requerido para resolver las + direcciones de correo de los miembros) +2. Establezca ``permission_sync=true`` en los parámetros +3. Agregue ``role=message.roles`` al script + +Parámetros: + +:: + + include_private=true + permission_sync=true + +Script: + +:: + + role=message.roles + +Comportamiento de Fallo Cerrado (Fail-Closed) +--------------------------------------------- + +Un canal privado no se indexa en absoluto en un rastreo dado si se da alguno de los siguientes +casos (esto es un comportamiento "fail-closed": el riesgo es una indexación incompleta, nunca +exponer contenido accidentalmente a todos): + +- No se pudo obtener la lista de miembros del canal +- La lista de miembros volvió vacía (esto ocurre cuando el propio usuario bot del token de + rastreo no es miembro de ese canal privado) +- El canal tiene miembros, pero no se pudo resolver la dirección de correo de ninguno de ellos + (generalmente porque falta el ámbito ``users:read.email``) + +Los canales públicos nunca invocan ``conversations.members`` y siempre se consideran visibles +para todos. + +Coincidencia del Nombre de Principal +------------------------------------ + +La verificación de permisos en tiempo de búsqueda utiliza el nombre de inicio de sesión de +|Fess| (el nombre de principal). Dado que los roles que calcula esta función se derivan de las +direcciones de correo de Slack, el nombre de inicio de sesión de |Fess| debe coincidir con la +dirección de correo de Slack. Slack normaliza las direcciones de correo a minúsculas, por lo +que mantenga también en minúsculas los nombres de inicio de sesión de |Fess|. Una discrepancia +no expone el contenido de otro usuario -- simplemente hace que las búsquedas del usuario +afectado siempre devuelvan cero resultados, lo cual puede confundirse fácilmente con un error +no relacionado. + +Otras Notas +----------- + +- No se utilizan los grupos de usuarios (User Group) de Slack; los permisos se calculan + directamente a partir de la dirección de correo de cada miembro +- ``default_permissions`` le permite otorgar permisos adicionales a todos los documentos + independientemente de la membresía del canal (se aplica solo cuando ``permission_sync=true``) +- Dejar ``permission_sync=false`` mientras se establece ``include_private=true`` indexa el + contenido de canales privados usando únicamente los permisos configurados en el campo + "Permiso" del almacén de datos; si ese campo se deja vacío, el contenido queda efectivamente + público para todos +- Habilitar ``permission_sync`` más tarde no asegura de forma retroactiva el contenido ya + indexado por un rastreo anterior sin restricciones. Para aplicar roles a ese contenido, + establezca ``permission_sync=true`` y ``role=message.roles``, y vuelva a rastrear. Del mismo + modo, deshabilitar ``permission_sync`` más adelante no elimina los roles ya aplicados a los + documentos indexados previamente Ejemplos de Uso =============== -Rastrear Canales Especificos +Rastrear Canales Específicos ---------------------------- -Parametros: +Parámetros: :: @@ -265,7 +406,7 @@ Script: Rastrear Todos los Canales -------------------------- -Parametros: +Parámetros: :: @@ -286,7 +427,7 @@ Script: Rastrear Incluyendo Canales Privados ------------------------------------ -Parametros: +Parámetros: :: @@ -306,9 +447,9 @@ Script: url=message.permalink Rastrear Incluyendo Archivos ------------------------------ +---------------------------- -Parametros: +Parámetros: :: @@ -326,8 +467,8 @@ Script: created=message.timestamp url=message.permalink -Incluir Informacion Detallada de Mensajes -------------------------------------------- +Incluir Información Detallada de Mensajes +----------------------------------------- Script: @@ -340,13 +481,62 @@ Script: timestamp=message.timestamp url=message.permalink -Solucion de Problemas +Rastrear con Sincronización de Permisos +--------------------------------------- + +Restringe el contenido de canales privados de modo que solo los miembros de ese canal puedan +buscarlo. Agregue de antemano el ámbito ``users:read.email`` a la Slack App. + +Parámetros: + +:: + + token=xoxb-your-slack-bot-token-here + channels=*all + include_private=true + permission_sync=true + +Script: + +:: + + title=message.user + " #" + message.channel + content=message.text + created=message.timestamp + url=message.permalink + role=message.roles + +.. note:: + + Si olvida ``role=message.roles``, los roles calculados nunca se reflejarán en los documentos + indexados. Véase "Sincronización de Permisos (ACL)" para más detalles. + +Solución de Problemas ===================== -Error de Autenticacion +Cómo Funciona el Manejo de Errores +---------------------------------- + +El conector de Slack clasifica los errores de la API de Slack en tres tipos: + +- **Errores fatales**\ (``invalid_auth``, ``token_revoked``, ``account_inactive``, + ``missing_scope``, ``not_authed``, ``token_expired``): el token en sí no se puede usar, por + lo que falla todo el trabajo de rastreo +- **Errores transitorios**\ (``ratelimited``, ``internal_error``, ``fatal_error``, + ``service_unavailable``, ``request_timeout``): si los reintentos no resuelven el error, falla + todo el trabajo de rastreo (véase "Límite de Tasa de API" más adelante para el comportamiento + de reintento) +- **Errores por canal**\ (``channel_not_found``, ``not_in_channel``, etc.): solo se omite ese + canal con una advertencia, y el rastreo continúa con el siguiente canal + +En versiones anteriores, un error fatal aún podía reportarse como un rastreo "exitoso" que +indexaba silenciosamente cero documentos o solo algunos. Esta división en tres tipos ahora +garantiza que los errores fatales y transitorios siempre se reporten como un fallo del trabajo. + +Error de Autenticación ---------------------- -**Sintoma**: ``invalid_auth`` o ``not_authed`` +**Síntoma**: ``invalid_auth`` o ``not_authed`` **Verificar**: @@ -356,51 +546,61 @@ Error de Autenticacion - Bot User OAuth Token: comienza con ``xoxb-`` - User OAuth Token: comienza con ``xoxp-`` -3. Verificar que la aplicacion este instalada en el espacio de trabajo +3. Verificar que la aplicación esté instalada en el espacio de trabajo 4. Verificar que se hayan otorgado los permisos necesarios Canal No Encontrado ------------------- -**Sintoma**: ``channel_not_found`` +**Síntoma**: ``channel_not_found`` **Verificar**: 1. Verificar que el nombre del canal sea correcto (sin #) -2. Verificar que la aplicacion este agregada al canal +2. Verificar que la aplicación esté agregada al canal 3. Para canales privados, establecer ``include_private=true`` -4. Verificar que el canal exista y no este archivado +4. Verifique si ``exclude_archived=true`` está configurado. De forma predeterminada + (``exclude_archived=false``), los canales archivados se siguen listando y rastreando; solo + al establecerlo en ``true`` deja de poder resolverse un canal archivado especificado por + nombre en ``channels`` No se Pueden Obtener Mensajes ----------------------------- -**Sintoma**: El rastreo tiene exito pero hay 0 mensajes +**Síntoma**: El rastreo tiene éxito, pero se indexan pocos documentos o ninguno **Verificar**: -1. Verificar que se hayan otorgado los ambitos necesarios: +1. ``ignore_system_events`` tiene como valor predeterminado ``true``. Si los mensajes de un + canal son todos eventos del sistema como ``channel_join``, no se indexará ningún documento + para él (véase "Parámetros Avanzados") +2. Verificar que existan mensajes en el canal +3. Verificar que la aplicación esté agregada al canal +4. Con ``permission_sync=true``, un canal privado cuya membresía no pueda resolverse no se + indexa en ese rastreo (fail-closed; véase "Sincronización de Permisos (ACL)") - - ``channels:history`` - - ``channels:read`` - - Para canales privados: ``groups:history``, ``groups:read`` +.. note:: -2. Verificar que existan mensajes en el canal -3. Verificar que la aplicacion este agregada al canal -4. Verificar que la Slack App este habilitada + En versiones anteriores, un ámbito faltante (``missing_scope``) aún podía dejar que el + rastreo "tuviera éxito" con cero mensajes. Los errores fatales, incluido ``missing_scope``, + ahora hacen fallar todo el trabajo de rastreo. Si su trabajo está fallando, consulte "Error + de Permisos Insuficientes" más adelante en lugar de esta sección. Error de Permisos Insuficientes --------------------------------- +------------------------------- -**Sintoma**: ``missing_scope`` +**Síntoma**: ``missing_scope`` (hace fallar todo el trabajo de rastreo) -**Solucion**: +**Solución**: -1. Agregar los ambitos necesarios en la configuracion de la Slack App: +1. Agregar los ámbitos necesarios en la configuración de la Slack App: - **Canales Publicos**: + **Básico**\ (siempre requerido): - ``channels:history`` - ``channels:read`` + - ``users:read`` + - ``team:read`` **Canales Privados**: @@ -411,52 +611,80 @@ Error de Permisos Insuficientes - ``files:read`` -2. Reinstalar la aplicacion + **Sincronización de Permisos**\ (``permission_sync=true``): + + - ``users:read.email`` + +2. Reinstalar la aplicación 3. Reiniciar |Fess| No se Pueden Rastrear Archivos -------------------------------- +------------------------------ -**Sintoma**: No se obtienen archivos aunque ``file_crawl=true`` +**Síntoma**: No se obtienen archivos aunque ``file_crawl=true`` **Verificar**: -1. Verificar que se haya otorgado el ambito ``files:read`` +1. Verificar que se haya otorgado el ámbito ``files:read`` 2. Verificar que realmente se hayan publicado archivos en el canal 3. Verificar los permisos de acceso a los archivos +4. Un archivo que supere ``max_filesize`` no se descarga (verifique el registro en busca de + una advertencia) -Limite de Tasa de API +Límite de Tasa de API --------------------- -**Sintoma**: ``rate_limited`` +**Síntoma**: ``ratelimited`` (hace fallar todo el trabajo de rastreo) + +**Solución**: + +1. Si los valores predeterminados de ``max_retry_count`` y ``retry_interval`` no resuelven el + problema, auméntelos +2. Establezca ``read_interval`` para ralentizar el rastreo +3. Reduzca el número de canales, o divida en varios almacenes de datos y distribuya los + horarios -**Solucion**: +Un error ``ratelimited`` de la API de Slack se reintenta automáticamente: usando el valor del +encabezado ``Retry-After``, en segundos, cuando está presente, o en su defecto un retroceso +exponencial a partir de ``retry_interval`` (hasta ``max_retry_count`` intentos, con un tope de +60 segundos). Si el límite de tasa persiste tras agotar todos los reintentos, falla todo el +trabajo de rastreo. -1. Aumentar el intervalo de rastreo -2. Reducir el numero de canales -3. Dividir en multiples almacenes de datos y distribuir la programacion +Niveles (tiers) de la API de Slack (límites de frecuencia de llamadas): -Limites de la API de Slack: +- Nivel 1: 1+ solicitudes/minuto +- Nivel 2: 20+ solicitudes/minuto -- ``conversations.list``, ``users.list`` (se obtienen por + completo de forma incondicional al inicio de cada rastreo, lo que hace que este nivel sea el + más propenso a agotarse) +- Nivel 3: 50+ solicitudes/minuto -- ``conversations.history``, ``conversations.replies``, + ``files.list`` +- Nivel 4: 100+ solicitudes/minuto -- ``conversations.members`` (solo cuando + ``permission_sync=true``), ``files.info`` (actualmente no invocado por el rastreo de este + conector) -- Metodos de nivel 3: 50+ solicitudes/minuto -- Metodos de nivel 4: 100+ solicitudes/minuto +.. note:: + + El endurecimiento del límite de tasa de Slack del 29 de mayo de 2025 (que limita + ``conversations.history`` y ``conversations.replies`` a 50+ solicitudes/minuto) se aplica + solo a aplicaciones distribuidas fuera del espacio de trabajo que las creó, como a través + del Slack Marketplace. No se aplica a una aplicación interna creada para |Fess| que se + instala únicamente en el espacio de trabajo que la creó. Gran Volumen de Mensajes -------------------------- +------------------------ -**Sintoma**: El rastreo tarda mucho tiempo o se agota el tiempo de espera +**Síntoma**: El rastreo tarda mucho tiempo o se agota el tiempo de espera -**Solucion**: +**Solución**: -1. Dividir los canales y configurar multiples almacenes de datos -2. Distribuir la programacion de rastreo -3. Considerar una configuracion para excluir mensajes antiguos +1. Dividir los canales y configurar múltiples almacenes de datos +2. Distribuir la programación de rastreo Ejemplos Avanzados de Script -============================== +============================ Procesamiento de Mensajes --------------------------- +------------------------- Digest de mensajes largos: @@ -477,11 +705,13 @@ Formato del nombre del canal: created=message.timestamp url=message.permalink -Informacion de Referencia +Información de Referencia ========================= -- :doc:`ds-overview` - Vision general de conectores de almacen de datos +- :doc:`ds-overview` - Visión general de conectores de almacén de datos - :doc:`ds-atlassian` - Conector de Atlassian -- :doc:`../../admin/dataconfig-guide` - Guia de configuracion de almacen de datos +- :doc:`../../admin/dataconfig-guide` - Guía de configuración de almacén de datos +- :doc:`../security-role` - Guía de configuración de búsqueda basada en roles - `Slack API Documentation `_ - `Slack Bot Token Scopes `_ +- `Slack API Rate Limits `_ diff --git a/fr/15.9/config/datastore/ds-slack.rst b/fr/15.9/config/datastore/ds-slack.rst index 4c26df47..ce27f12d 100644 --- a/fr/15.9/config/datastore/ds-slack.rst +++ b/fr/15.9/config/datastore/ds-slack.rst @@ -2,38 +2,47 @@ Connecteur Slack ================================== -Apercu +Aperçu ====== -Le connecteur Slack fournit la fonctionnalite permettant de recuperer les messages +Le connecteur Slack fournit la fonctionnalité permettant de récupérer les messages des canaux d'un espace de travail Slack et de les enregistrer dans l'index |Fess|. -Cette fonctionnalite necessite le plugin ``fess-ds-slack``. +Cette fonctionnalité nécessite le plugin ``fess-ds-slack``. Contenu pris en charge ====================== - Messages des canaux publics -- Messages des canaux prives +- Messages des canaux privés +- Messages de réponse dans les fils de discussion (récupérés via ``conversations.replies``) - Fichiers joints (optionnel) -Prerequis +Les éléments suivants ne sont pas pris en charge : + +- Les messages d'événements système (``channel_join``, ``channel_topic``, ``pinned_item``, + etc.) sont exclus de l'indexation par défaut (``ignore_system_events``) +- Les messages directs (DM) et les DM de groupe +- Les transcriptions Huddle et les Clips (Slack ne propose pas d'API publique pour ceux-ci, + ils ne peuvent donc pas être crawlés) + +Prérequis ========= 1. L'installation du plugin est requise -2. La creation et la configuration des permissions de l'application Slack sont necessaires +2. La création et la configuration des permissions de l'application Slack sont nécessaires 3. L'obtention du OAuth Access Token est requise Installation du plugin ------------------------- +---------------------- -Installez depuis l'interface d'administration via "Systeme" -> "Plugins" : +Installez depuis l'interface d'administration via "Système" -> "Plugins" : -1. Telechargez ``fess-ds-slack-X.X.X.jar`` depuis Maven Central -2. Telechargez et installez depuis l'interface de gestion des plugins -3. Redemarrez |Fess| +1. Téléchargez ``fess-ds-slack-X.X.X.jar`` depuis Maven Central +2. Téléchargez et installez depuis l'interface de gestion des plugins +3. Redémarrez |Fess| -Ou consultez :doc:`../../admin/plugin-guide` pour plus de details. +Ou consultez :doc:`../../admin/plugin-guide` pour plus de détails. Configuration ============= @@ -47,16 +56,16 @@ Configuration de base :header-rows: 1 :widths: 25 75 - * - Element + * - Élément - Exemple * - Nom - Company Slack * - Nom du gestionnaire - SlackDataStore - * - Active + * - Activé - Oui -Configuration des parametres +Configuration des paramètres ---------------------------- :: @@ -66,14 +75,14 @@ Configuration des parametres file_crawl=false include_private=false -Liste des parametres +Liste des paramètres ~~~~~~~~~~~~~~~~~~~~ .. list-table:: :header-rows: 1 :widths: 25 15 60 - * - Parametre + * - Paramètre - Requis - Description * - ``token`` @@ -81,13 +90,13 @@ Liste des parametres - OAuth Access Token de l'application Slack * - ``channels`` - Non - - Canaux cibles du crawl (separes par des virgules, ou ``*all``). Si non spécifié, tous les canaux sont récupérés (même comportement que ``*all``) + - Canaux cibles du crawl (séparés par des virgules, ou ``*all``). Si non spécifié, tous les canaux sont récupérés (même comportement que ``*all``) * - ``file_crawl`` - Non - - Crawler egalement les fichiers (par defaut : ``false``) + - Crawler également les fichiers (par défaut : ``false``) * - ``include_private`` - Non - - Inclure les canaux prives (par defaut : ``false``) + - Inclure les canaux privés (par défaut : ``false``) * - ``number_of_threads`` - Non - Nombre de threads de traitement parallèle (par défaut : ``1``) @@ -137,6 +146,49 @@ Liste des parametres - Non - Nombre maximum d'entrées dans le cache des informations de canal (par défaut : ``10000``) +Paramètres avancés +~~~~~~~~~~~~~~~~~~ + +Les paramètres suivants contrôlent le comportement de connexion et de nouvelle tentative, le +périmètre fin du crawl, ainsi que la synchronisation des permissions : + +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - Paramètre + - Description + * - ``connection_timeout`` + - Délai de connexion pour chaque requête à l'API Slack (millisecondes, par défaut : ``20000``) + * - ``read_timeout`` + - Délai de lecture pour chaque requête à l'API Slack (millisecondes, par défaut : ``20000``) + * - ``max_retry_count`` + - Nombre maximal de nouvelles tentatives après une réponse ``429`` (limite de débit) ou ``5xx`` (par défaut : ``3``) + * - ``retry_interval`` + - Temps d'attente en millisecondes avant la première nouvelle tentative lorsque la réponse ne comporte pas d'en-tête ``Retry-After`` (par défaut : ``3000``). Double à chaque nouvelle tentative, plafonné à ``60000`` millisecondes. Si la réponse comporte un en-tête ``Retry-After``, cette valeur (en secondes) est utilisée à la place + * - ``executor_timeout`` + - Secondes d'attente, à la fin d'un crawl, pour que les tâches restant en file d'attente se terminent avant de forcer l'arrêt (par défaut : ``60``) + * - ``exclude_archived`` + - Détermine si les canaux archivés doivent être exclus des résultats de ``conversations.list`` (par défaut : ``false``). Avec ``true``, un canal archivé spécifié par son nom dans ``channels`` ne peut plus être résolu (voir Dépannage pour plus de détails) + * - ``ignore_system_events`` + - Détermine si les messages d'administration de canal générés automatiquement par Slack (``channel_join``, ``channel_topic``, ``pinned_item``, etc.) doivent être exclus de l'indexation (par défaut : ``true``) + * - ``read_interval`` + - Temps d'attente en millisecondes après le traitement de chaque message ou fichier (par défaut : ``0`` = pas d'attente). À utiliser pour ralentir le crawl face à un espace de travail fortement limité en débit + * - ``max_content_length`` + - Nombre maximal de caractères que l'extracteur de contenu (Tika) peut extraire d'un fichier (par défaut : non défini, la limite par type MIME propre à |Fess| s'applique alors). ``max_filesize`` est la limite côté transfert qui rejette les fichiers selon leur taille avant le téléchargement, tandis que ``max_content_length`` est la limite côté extraction sur la quantité de texte extraite après le téléchargement ; les deux agissent indépendamment. Réduire ``max_filesize`` ne remplace pas ``max_content_length`` (par exemple, une archive de 1 Mo peut se développer en un texte bien plus volumineux une fois extraite) + * - ``permission_sync`` + - Détermine si l'appartenance à un canal privé doit être convertie en permissions de recherche (rôles) (par défaut : ``false``). Voir « Synchronisation des permissions (ACL) » ci-dessous pour plus de détails + * - ``default_permissions`` + - Permissions supplémentaires appliquées à tous les documents indexés, indépendamment de l'appartenance au canal (format ``{user}``/``{group}``/``{role}``, séparés par des virgules, par défaut : vide). Appliqué uniquement lorsque ``permission_sync`` est activé + +.. note:: + + ``ignore_system_events`` vaut ``true`` par défaut. Même une configuration de crawl existante + qui ne définit pas ce paramètre cessera, après une mise à niveau de |Fess|, d'indexer les + messages d'événements système tels que ``channel_join`` -- le nombre de documents indexés + diminuera sans aucune erreur ni avertissement. Spécifiez explicitement + ``ignore_system_events=false`` pour continuer à indexer ces messages comme auparavant. + Configuration du script ----------------------- @@ -150,7 +202,7 @@ Configuration du script url=message.permalink Champs disponibles -~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~ .. list-table:: :header-rows: 1 @@ -165,26 +217,28 @@ Champs disponibles * - ``message.user`` - Nom d'affichage de l'expéditeur du message (si non défini, résolu dans l'ordre du nom réel, du nom d'utilisateur, puis de l'identifiant utilisateur) * - ``message.channel`` - - Nom du canal ou le message a ete envoye + - Nom du canal où le message a été envoyé * - ``message.timestamp`` - Date et heure d'envoi du message * - ``message.permalink`` - Lien permanent du message * - ``message.attachments`` - - Informations de fallback des fichiers joints + - Informations de repli des fichiers joints + * - ``message.roles`` + - Liste des permissions de recherche (rôles) autorisées à voir ce message ou ce fichier. Présent uniquement lorsque ``permission_sync=true``. Sauf si le script assigne ``role=message.roles``, les rôles calculés ne sont jamais répercutés dans le document indexé Configuration de l'application Slack ==================================== -1. Creation de l'application Slack +1. Création de l'application Slack ---------------------------------- -Accedez a https://api.slack.com/apps : +Accédez à https://api.slack.com/apps : 1. Cliquez sur "Create New App" -2. Selectionnez "From scratch" +2. Sélectionnez "From scratch" 3. Entrez le nom de l'application (ex: Fess Crawler) -4. Selectionnez l'espace de travail +4. Sélectionnez l'espace de travail 5. Cliquez sur "Create App" 2. Configuration OAuth & Permissions @@ -194,55 +248,142 @@ Dans le menu "OAuth & Permissions" : **Ajoutez les Bot Token Scopes suivants** : -Pour les canaux publics uniquement : +Scopes de base (toujours requis) : - ``channels:history`` - Lecture des messages des canaux publics - ``channels:read`` - Lecture des informations des canaux publics - ``users:read`` - Lecture des informations utilisateur (requis pour la résolution des noms d'affichage) +- ``team:read`` - Lecture des informations de l'espace de travail. ``team.info`` est appelé à + chaque crawl, ce scope est donc requis ; sans lui, ce connecteur se rabat sur un appel + supplémentaire à ``chat.getPermalink`` pour chaque message, ce qui augmente fortement le + nombre d'appels à l'API -Pour inclure les canaux prives (``include_private=true``) : +Pour inclure également les canaux privés (``include_private=true``) : -- ``channels:history`` -- ``channels:read`` -- ``groups:history`` - Lecture des messages des canaux prives -- ``groups:read`` - Lecture des informations des canaux prives -- ``users:read`` +- ``groups:history`` - Lecture des messages des canaux privés +- ``groups:read`` - Lecture des informations des canaux privés -Pour crawler egalement les fichiers (``file_crawl=true``) : +Pour crawler également les fichiers (``file_crawl=true``) : - ``files:read`` - Lecture du contenu des fichiers +Pour synchroniser également les permissions des canaux privés (``permission_sync=true``) : + +- ``users:read.email`` - Lecture des adresses e-mail des membres (requis pour la + synchronisation des permissions) + 3. Installation de l'application -------------------------------- Dans le menu "Install App" : 1. Cliquez sur "Install to Workspace" -2. Verifiez les permissions et cliquez sur "Autoriser" +2. Vérifiez les permissions et cliquez sur "Autoriser" 3. Copiez le "Bot User OAuth Token" (commence par ``xoxb-``) .. note:: Normalement, utilisez le Bot User OAuth Token qui commence par ``xoxb-``, - mais le User OAuth Token qui commence par ``xoxp-`` peut egalement etre utilise dans les parametres. + mais le User OAuth Token qui commence par ``xoxp-`` peut également être utilisé dans les paramètres. 4. Ajout aux canaux ---------------------- +------------------- -Ajoutez l'application aux canaux a crawler : +Ajoutez l'application aux canaux à crawler : 1. Ouvrez le canal dans Slack 2. Cliquez sur le nom du canal -3. Selectionnez l'onglet "Integrations" +3. Sélectionnez l'onglet "Intégrations" 4. Cliquez sur "Ajouter des applications" -5. Ajoutez l'application creee +5. Ajoutez l'application créée + +Synchronisation des permissions (ACL) +===================================== + +Le connecteur Slack peut convertir l'appartenance à un canal privé en permissions de recherche +(rôles) |Fess|, de sorte que seuls les membres de ce canal puissent en rechercher le contenu. +Cette fonctionnalité est désactivée par défaut. + +.. note:: + + ``permission_sync`` se contente de calculer les rôles ; il ne les applique pas + automatiquement. Ce n'est qu'après avoir ajouté ``role=message.roles`` au script que les + rôles calculés sont répercutés dans les documents indexés. Oublier ce mappage entraîne tout + de même les appels API supplémentaires et les canaux privés ignorés que provoque + ``permission_sync=true``, sans fournir le moindre contrôle d'accès. + +Activation +---------- + +1. Ajoutez le scope ``users:read.email`` à l'application Slack (requis pour résoudre les + adresses e-mail des membres) +2. Définissez ``permission_sync=true`` dans les paramètres +3. Ajoutez ``role=message.roles`` au script + +Paramètres : + +:: + + include_private=true + permission_sync=true + +Script : + +:: + + role=message.roles + +Comportement Fail-Closed +------------------------ + +Un canal privé n'est pas indexé du tout lors d'un crawl donné si l'un des cas suivants se +présente (il s'agit d'un comportement « fail-closed » : le risque est une sous-indexation, +jamais une exposition accidentelle du contenu à tout le monde) : + +- La récupération de la liste des membres du canal a échoué +- La liste des membres est revenue vide (cela se produit lorsque l'utilisateur bot du token de + crawl n'est lui-même pas membre de ce canal privé) +- Le canal a des membres, mais aucune de leurs adresses e-mail n'a pu être résolue (le plus + souvent parce que le scope ``users:read.email`` est manquant) + +Les canaux publics n'appellent jamais ``conversations.members`` et sont toujours considérés +comme visibles par tous. + +Correspondance du nom de principal +---------------------------------- + +Les vérifications de permission au moment de la recherche utilisent le nom de connexion |Fess| +(le nom de principal). Étant donné que les rôles calculés par cette fonctionnalité sont dérivés +des adresses e-mail Slack, le nom de connexion |Fess| doit correspondre à l'adresse e-mail +Slack. Slack normalise les adresses e-mail en minuscules ; conservez donc également les noms de +connexion |Fess| en minuscules. Une incohérence n'expose pas le contenu d'un autre utilisateur +-- elle a simplement pour effet que les recherches de l'utilisateur concerné renvoient toujours +zéro résultat, ce qui peut facilement être confondu avec un bug sans rapport. + +Autres remarques +---------------- + +- Les groupes d'utilisateurs (User Group) Slack ne sont pas utilisés ; les permissions sont + calculées directement à partir de l'adresse e-mail de chaque membre +- ``default_permissions`` permet d'accorder des permissions supplémentaires à tous les + documents, indépendamment de l'appartenance au canal (appliqué uniquement lorsque + ``permission_sync=true``) +- Laisser ``permission_sync=false`` tout en définissant ``include_private=true`` indexe le + contenu des canaux privés en utilisant uniquement les permissions configurées dans le champ + « Permission » du Data Store ; si ce champ est laissé vide, le contenu devient de fait + public pour tous +- Activer ``permission_sync`` ultérieurement ne sécurise pas rétroactivement le contenu déjà + indexé par un crawl antérieur sans restriction. Pour appliquer des rôles à ce contenu, + définissez ``permission_sync=true`` et ``role=message.roles``, puis relancez un crawl. De + même, désactiver ``permission_sync`` par la suite ne supprime pas les rôles déjà appliqués + aux documents indexés précédemment Exemples d'utilisation ====================== -Crawler des canaux specifiques +Crawler des canaux spécifiques ------------------------------ -Parametres : +Paramètres : :: @@ -263,9 +404,9 @@ Script : url=message.permalink Crawler tous les canaux ----------------------------- +----------------------- -Parametres : +Paramètres : :: @@ -283,10 +424,10 @@ Script : created=message.timestamp url=message.permalink -Crawler en incluant les canaux prives --------------------------------------- +Crawler en incluant les canaux privés +------------------------------------- -Parametres : +Paramètres : :: @@ -301,14 +442,14 @@ Script : title=message.user + " #" + message.channel digest=message.text - content=message.text + "\nPièce jointe: " + message.attachments + content=message.text + "\nPièce jointe : " + message.attachments created=message.timestamp url=message.permalink Crawler en incluant les fichiers -------------------------------- -Parametres : +Paramètres : :: @@ -326,7 +467,7 @@ Script : created=message.timestamp url=message.permalink -Inclure des informations detaillees sur les messages +Inclure des informations détaillées sur les messages ---------------------------------------------------- Script : @@ -340,69 +481,129 @@ Script : timestamp=message.timestamp url=message.permalink -Depannage -====================== +Crawler avec synchronisation des permissions +-------------------------------------------- + +Restreint le contenu des canaux privés de sorte que seuls les membres de ce canal puissent le +rechercher. Ajoutez au préalable le scope ``users:read.email`` à l'application Slack. + +Paramètres : + +:: + + token=xoxb-your-slack-bot-token-here + channels=*all + include_private=true + permission_sync=true + +Script : + +:: + + title=message.user + " #" + message.channel + content=message.text + created=message.timestamp + url=message.permalink + role=message.roles + +.. note:: + + Si vous oubliez ``role=message.roles``, les rôles calculés ne seront jamais répercutés dans + les documents indexés. Voir « Synchronisation des permissions (ACL) » pour plus de détails. + +Dépannage +========= + +Fonctionnement de la gestion des erreurs +---------------------------------------- + +Le connecteur Slack classe les erreurs de l'API Slack en trois catégories : + +- **Erreurs fatales**\ (``invalid_auth``, ``token_revoked``, ``account_inactive``, + ``missing_scope``, ``not_authed``, ``token_expired``) : le token lui-même est inutilisable, + ce qui fait échouer l'ensemble du job de crawl +- **Erreurs transitoires**\ (``ratelimited``, ``internal_error``, ``fatal_error``, + ``service_unavailable``, ``request_timeout``) : si les nouvelles tentatives ne résolvent pas + l'erreur, l'ensemble du job de crawl échoue (voir « Limitation de débit API » ci-dessous pour + le comportement de nouvelle tentative) +- **Erreurs propres à un canal**\ (``channel_not_found``, ``not_in_channel``, etc.) : seul ce + canal est ignoré avec un avertissement, et le crawl se poursuit avec le canal suivant + +Dans les versions précédentes, une erreur fatale pouvait tout de même être rapportée comme un +crawl « réussi » qui indexait silencieusement zéro document, ou seulement une partie d'entre +eux. Cette répartition en trois catégories garantit désormais que les erreurs fatales et +transitoires sont toujours rapportées comme un échec du job. Erreur d'authentification ------------------------- -**Symptome** : ``invalid_auth`` ou ``not_authed`` +**Symptôme** : ``invalid_auth`` ou ``not_authed`` -**Points a verifier** : +**Points à vérifier** : -1. Verifier si le token a ete correctement copie -2. Verifier le format du token : +1. Vérifier si le token a été correctement copié +2. Vérifier le format du token : - Bot User OAuth Token : commence par ``xoxb-`` - User OAuth Token : commence par ``xoxp-`` -3. Verifier si l'application est installee dans l'espace de travail -4. Verifier si les permissions necessaires sont accordees +3. Vérifier si l'application est installée dans l'espace de travail +4. Vérifier si les permissions nécessaires sont accordées Canal introuvable ------------------------- +----------------- -**Symptome** : ``channel_not_found`` +**Symptôme** : ``channel_not_found`` -**Points a verifier** : +**Points à vérifier** : -1. Verifier si le nom du canal est correct (# n'est pas necessaire) -2. Verifier si l'application a ete ajoutee au canal -3. Pour les canaux prives, definir ``include_private=true`` -4. Verifier si le canal existe et n'est pas archive +1. Vérifier si le nom du canal est correct (# n'est pas nécessaire) +2. Vérifier si l'application a été ajoutée au canal +3. Pour les canaux privés, définir ``include_private=true`` +4. Vérifiez si ``exclude_archived=true`` est défini. Par défaut (``exclude_archived=false``), + les canaux archivés sont toujours listés et crawlés ; ce n'est que lorsqu'il est défini sur + ``true`` qu'un canal archivé spécifié par son nom dans ``channels`` ne peut plus être résolu -Impossible de recuperer les messages +Impossible de récupérer les messages ------------------------------------ -**Symptome** : Le crawl reussit mais 0 messages +**Symptôme** : Le crawl réussit, mais peu ou aucun document n'est indexé -**Points a verifier** : +**Points à vérifier** : -1. Verifier si les scopes necessaires sont accordes : +1. ``ignore_system_events`` vaut ``true`` par défaut. Si les messages d'un canal sont + uniquement des événements système tels que ``channel_join``, aucun document n'est indexé + pour ce canal (voir « Paramètres avancés ») +2. Vérifier si des messages existent réellement dans le canal +3. Vérifier si l'application a été ajoutée au canal +4. Avec ``permission_sync=true``, un canal privé dont l'appartenance ne peut pas être résolue + n'est pas indexé lors de ce crawl (fail-closed ; voir « Synchronisation des permissions + (ACL) ») - - ``channels:history`` - - ``channels:read`` - - Pour les canaux prives : ``groups:history``, ``groups:read`` +.. note:: -2. Verifier si des messages existent dans le canal -3. Verifier si l'application a ete ajoutee au canal -4. Verifier si l'application Slack est active + Dans les versions précédentes, un scope manquant (``missing_scope``) pouvait encore laisser + le crawl « réussir » avec zéro message. Les erreurs fatales, y compris ``missing_scope``, + font désormais échouer l'ensemble du job de crawl. Si votre job échoue, consultez plutôt + « Erreur de permission insuffisante » ci-dessous. Erreur de permission insuffisante --------------------------------- -**Symptome** : ``missing_scope`` +**Symptôme** : ``missing_scope`` (fait échouer l'ensemble du job de crawl) **Solution** : -1. Ajouter les scopes necessaires dans les parametres de l'application Slack : +1. Ajouter les scopes nécessaires dans les paramètres de l'application Slack : - **Canaux publics** : + **Base**\ (toujours requis) : - ``channels:history`` - ``channels:read`` + - ``users:read`` + - ``team:read`` - **Canaux prives** : + **Canaux privés** : - ``groups:history`` - ``groups:read`` @@ -411,54 +612,82 @@ Erreur de permission insuffisante - ``files:read`` -2. Reinstaller l'application -3. Redemarrer |Fess| + **Synchronisation des permissions**\ (``permission_sync=true``) : + + - ``users:read.email`` + +2. Réinstaller l'application +3. Redémarrer |Fess| Impossible de crawler les fichiers ---------------------------------- -**Symptome** : Les fichiers ne sont pas recuperes meme avec ``file_crawl=true`` +**Symptôme** : Les fichiers ne sont pas récupérés même avec ``file_crawl=true`` -**Points a verifier** : +**Points à vérifier** : -1. Verifier si le scope ``files:read`` est accorde -2. Verifier si des fichiers sont effectivement postes dans le canal -3. Verifier les permissions d'acces aux fichiers +1. Vérifier si le scope ``files:read`` est accordé +2. Vérifier si des fichiers sont effectivement postés dans le canal +3. Vérifier les permissions d'accès aux fichiers +4. Un fichier dépassant ``max_filesize`` n'est pas téléchargé (vérifiez le log pour un + avertissement) -Limitation de debit API +Limitation de débit API ----------------------- -**Symptome** : ``rate_limited`` +**Symptôme** : ``ratelimited`` (fait échouer l'ensemble du job de crawl) **Solution** : -1. Augmenter l'intervalle de crawl -2. Reduire le nombre de canaux -3. Repartir en plusieurs data stores avec des planifications differentes +1. Si les valeurs par défaut de ``max_retry_count`` et ``retry_interval`` ne résolvent pas le + problème, augmentez-les +2. Définissez ``read_interval`` pour ralentir le crawl +3. Réduisez le nombre de canaux, ou répartissez en plusieurs Data Store avec des + planifications différentes + +Une erreur ``ratelimited`` de l'API Slack est automatiquement réessayée : en utilisant la +valeur de l'en-tête ``Retry-After``, en secondes, lorsqu'elle est présente, ou sinon selon un +recul exponentiel à partir de ``retry_interval`` (jusqu'à ``max_retry_count`` tentatives, +plafonné à 60 secondes). Si la limitation de débit persiste après épuisement de toutes les +tentatives, l'ensemble du job de crawl échoue. + +Niveaux (tiers) de l'API Slack (limites de fréquence d'appel) : + +- Niveau 1 : 1+ requêtes/minute +- Niveau 2 : 20+ requêtes/minute -- ``conversations.list``, ``users.list`` (récupérées + intégralement et inconditionnellement au début de chaque crawl, ce qui rend ce niveau le + plus susceptible d'être épuisé) +- Niveau 3 : 50+ requêtes/minute -- ``conversations.history``, ``conversations.replies``, + ``files.list`` +- Niveau 4 : 100+ requêtes/minute -- ``conversations.members`` (uniquement lorsque + ``permission_sync=true``), ``files.info`` (non appelé actuellement par le crawl de ce + connecteur) -Limites de l'API Slack : +.. note:: -- Methodes Tier 3 : 50+ requetes/minute -- Methodes Tier 4 : 100+ requetes/minute + Le durcissement de la limitation de débit Slack du 29 mai 2025 (limitant + ``conversations.history`` et ``conversations.replies`` à 50+ requêtes/minute) ne s'applique + qu'aux applications distribuées en dehors de l'espace de travail qui les a créées, par + exemple via le Slack Marketplace. Il ne s'applique pas à une application interne créée pour + |Fess| et installée uniquement dans l'espace de travail qui l'a créée. Cas de nombreux messages --------------------------- +------------------------ -**Symptome** : Le crawl prend du temps ou expire +**Symptôme** : Le crawl prend du temps ou expire **Solution** : -1. Diviser les canaux et configurer plusieurs data stores -2. Repartir le calendrier de crawl -3. Envisager une configuration pour exclure les anciens messages +1. Diviser les canaux et configurer plusieurs Data Store +2. Répartir le calendrier de crawl -Exemples d'utilisation avancee des scripts +Exemples d'utilisation avancée des scripts ========================================== Traitement des messages ----------------------- -Resume des messages longs : +Résumé des messages longs : :: @@ -477,11 +706,13 @@ Formatage du nom du canal : created=message.timestamp url=message.permalink -Informations de reference +Informations de référence ========================= -- :doc:`ds-overview` - Apercu des connecteurs Data Store +- :doc:`ds-overview` - Aperçu des connecteurs Data Store - :doc:`ds-atlassian` - Connecteur Atlassian - :doc:`../../admin/dataconfig-guide` - Guide de configuration Data Store +- :doc:`../security-role` - Guide de configuration de la recherche basée sur les rôles - `Slack API Documentation `_ - `Slack Bot Token Scopes `_ +- `Slack API Rate Limits `_ diff --git a/ja/15.9/config/datastore/ds-slack.rst b/ja/15.9/config/datastore/ds-slack.rst index cc111150..d0aa632b 100644 --- a/ja/15.9/config/datastore/ds-slack.rst +++ b/ja/15.9/config/datastore/ds-slack.rst @@ -15,8 +15,16 @@ Slackコネクタは、Slackワークスペースのチャンネルメッセー - パブリックチャンネルのメッセージ - プライベートチャンネルのメッセージ +- スレッドの返信メッセージ(``conversations.replies`` で取得します) - ファイル添付(オプション) +以下は対象外です: + +- システムイベントメッセージ(``channel_join``、``channel_topic``、``pinned_item`` など)は + 既定で索引対象から除外されます(``ignore_system_events``) +- ダイレクトメッセージ(DM)およびグループDM +- Huddleの文字起こしとClips(Slackに公式APIが存在しないため対応できません) + 前提条件 ======== @@ -137,6 +145,47 @@ Slackコネクタは、Slackワークスペースのチャンネルメッセー - いいえ - チャンネル情報キャッシュの最大エントリ数(デフォルト: ``10000``) +高度なパラメーター +~~~~~~~~~~~~~~~~~~ + +以下のパラメーターは接続・リトライの挙動やクロール対象の細かい制御、権限同期を扱います: + +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - パラメーター + - 説明 + * - ``connection_timeout`` + - 各Slack APIリクエストの接続タイムアウト(ミリ秒、デフォルト: ``20000``) + * - ``read_timeout`` + - 各Slack APIリクエストの読み取りタイムアウト(ミリ秒、デフォルト: ``20000``) + * - ``max_retry_count`` + - ``429``\ (レート制限)または ``5xx`` 応答を受けたときの最大リトライ回数(デフォルト: ``3``) + * - ``retry_interval`` + - 応答に ``Retry-After`` ヘッダーが無い場合の、最初のリトライまでの待機時間(ミリ秒、デフォルト: ``3000``)。リトライごとに倍増し、``60000`` ミリ秒で頭打ちになります。``Retry-After`` ヘッダーがある場合はその値(秒)が優先されます + * - ``executor_timeout`` + - クロール終了時に、キューに残っている処理の完了を待つ秒数(デフォルト: ``60``)。この秒数を過ぎると強制終了します + * - ``exclude_archived`` + - ``conversations.list`` の取得結果からアーカイブ済みチャンネルを除外するか(デフォルト: ``false``)。 ``true`` にすると、``channels`` にチャンネル名で指定したアーカイブ済みチャンネルが名前解決できなくなります(詳細はトラブルシューティングを参照) + * - ``ignore_system_events`` + - Slackが自動生成するチャンネル管理系のメッセージ(``channel_join``、``channel_topic``、``pinned_item`` など)を索引対象から除外するか(デフォルト: ``true``) + * - ``read_interval`` + - メッセージまたはファイルを1件処理するごとに待機する時間(ミリ秒、デフォルト: ``0`` =待機なし)。レート制限が厳しいワークスペースに対してクロール速度を落とす場合に使用します + * - ``max_content_length`` + - コンテンツ抽出(Tika)が1ファイルから抽出できる最大文字数(デフォルト: 未設定=MIMEタイプ別の既定上限に委ねる)。 ``max_filesize`` はダウンロード前にファイルサイズで弾く転送量の上限、``max_content_length`` はダウンロード後に抽出するテキスト量の上限で、それぞれ独立して働きます。 ``max_filesize`` を小さくしても、``max_content_length`` の代わりにはなりません(例: 1MBの圧縮ファイルでも、展開後は遥かに大きなテキストになり得ます) + * - ``permission_sync`` + - プライベートチャンネルのメンバーシップを検索用の権限(ロール)に変換するかどうか(デフォルト: ``false``)。詳細は後述の「権限同期(ACL)」を参照してください + * - ``default_permissions`` + - チャンネルメンバーシップに関わらず、索引されたすべての文書に付与する追加の権限(``{user}``/``{group}``/``{role}`` 形式、カンマ区切り、デフォルト: 空)。``permission_sync`` が有効な場合にのみ適用されます + +.. note:: + + ``ignore_system_events`` の既定値は ``true`` です。このパラメーターを指定していない既存の + クロール設定でも、|Fess| をアップグレードすると ``channel_join`` などのシステムイベント + メッセージが索引されなくなり、エラーや警告なしに索引される文書数が減ります。従来どおり + システムイベントも索引したい場合は、``ignore_system_events=false`` を明示的に指定してください。 + スクリプト設定 -------------- @@ -172,6 +221,8 @@ Slackコネクタは、Slackワークスペースのチャンネルメッセー - メッセージのパーマリンク * - ``message.attachments`` - 添付ファイルのフォールバック情報 + * - ``message.roles`` + - このメッセージまたはファイルを閲覧できる検索権限(ロール)の一覧。``permission_sync=true`` の場合のみ存在するフィールドです。スクリプトで ``role=message.roles`` と指定しない限り、計算した権限は索引される文書に反映されません Slack App設定 ============= @@ -194,24 +245,28 @@ https://api.slack.com/apps にアクセス: **Bot Token Scopes**\ に以下を追加: -パブリックチャンネルのみの場合: +基本スコープ(常に必要): - ``channels:history`` - パブリックチャンネルメッセージの読み取り - ``channels:read`` - パブリックチャンネル情報の読み取り - ``users:read`` - ユーザー情報の読み取り(表示名の解決に必要) +- ``team:read`` - ワークスペース情報の読み取り。``team.info`` を毎回呼び出すため必須です。 + このスコープが無いと、メッセージ1件ごとに ``chat.getPermalink`` を追加で呼び出すように + なり、API呼び出し数が大幅に増加します -プライベートチャンネルも含める場合(``include_private=true``): +プライベートチャンネルも含める場合(``include_private=true``)に追加: -- ``channels:history`` -- ``channels:read`` - ``groups:history`` - プライベートチャンネルメッセージの読み取り - ``groups:read`` - プライベートチャンネル情報の読み取り -- ``users:read`` -ファイルもクロールする場合(``file_crawl=true``): +ファイルもクロールする場合(``file_crawl=true``)に追加: - ``files:read`` - ファイルコンテンツの読み取り +プライベートチャンネルの権限を同期する場合(``permission_sync=true``)に追加: + +- ``users:read.email`` - メンバーのメールアドレスの読み取り(権限同期に必須) + 3. アプリのインストール ----------------------- @@ -236,6 +291,79 @@ https://api.slack.com/apps にアクセス: 4. 「アプリを追加する」をクリック 5. 作成したアプリを追加 +権限同期(ACL) +=============== + +Slackコネクタは、プライベートチャンネルのメンバーシップを |Fess| の検索権限(ロール)に変換し、 +そのチャンネルのメンバーだけが内容を検索できるようにする機能を提供します。既定では無効です。 + +.. note:: + + ``permission_sync`` は権限(ロール)を計算するだけで、自動的には適用されません。スクリプトに + ``role=message.roles`` を指定して初めて、計算した権限が索引される文書に反映されます。この + 指定を忘れると、``permission_sync=true`` によるAPI呼び出しの増加やプライベートチャンネルの + スキップだけが発生し、アクセス制御は一切行われません。 + +有効化する +---------- + +1. Slack Appに ``users:read.email`` スコープを追加します(メンバーのメールアドレス解決に必須) +2. パラメーターに ``permission_sync=true`` を設定します +3. スクリプトに ``role=message.roles`` を追加します + +パラメーター: + +:: + + include_private=true + permission_sync=true + +スクリプト: + +:: + + role=message.roles + +フェイルクローズ動作 +-------------------- + +次のいずれかに該当するプライベートチャンネルは、そのクロールでは索引されません(内容が誤って +公開されるのではなく、索引しない方向に倒す「フェイルクローズ」の動作です): + +- チャンネルのメンバー一覧の取得に失敗した +- メンバー一覧が0件だった(クロールに使うトークンのボットユーザー自身がそのプライベート + チャンネルに参加していない場合に発生します) +- メンバーはいるが、誰のメールアドレスも解決できなかった(``users:read.email`` スコープの + 不足が主な原因です) + +パブリックチャンネルは ``conversations.members`` を呼び出さず、常に全員が閲覧できるものとして +扱われます。 + +プリンシパル名の一致 +-------------------- + +検索時の権限判定は |Fess| のログイン名(プリンシパル名)で行われます。この機能が計算する権限は +Slackのメールアドレスから作られるため、|Fess| のログイン名とSlackのメールアドレスを一致させる +必要があります。Slackはメールアドレスを小文字に正規化するため、|Fess| 側のログイン名も小文字に +しておいてください。一致しない場合、他人の文書が見えてしまうのではなく、該当ユーザーの検索結果 +が常に0件になります(原因が分かりにくいため注意してください)。 + +その他の注意点 +-------------- + +- Slackのユーザーグループ(User Group)は使用しません。権限は個々のメンバーのメールアドレス + から直接計算します +- ``default_permissions`` で、チャンネルメンバーシップに関わらずすべての文書に付与する追加の + 権限を指定できます(``permission_sync=true`` の場合のみ適用) +- ``permission_sync=false`` のまま ``include_private=true`` にすると、プライベートチャンネル + の内容はデータストア設定の「権限」欄の設定だけで索引されます。この欄が空の場合、実質的に + 全員に公開されます +- 既に索引済みのワークスペースで ``permission_sync`` を後から有効にしても、過去に索引された + 文書に遡って権限は付与されません。適用するには、``permission_sync=true`` と + ``role=message.roles`` を設定した上で再クロールしてください。同様に、``permission_sync`` + を後から無効にしても、既に付与された権限が索引済みの文書から自動的に取り除かれることは + ありません + 使用例 ====== @@ -340,9 +468,57 @@ https://api.slack.com/apps にアクセス: timestamp=message.timestamp url=message.permalink +権限を同期してクロール +---------------------- + +プライベートチャンネルの内容を、そのチャンネルのメンバーだけが検索できるようにします。 +事前に ``users:read.email`` スコープをSlack Appに追加してください。 + +パラメーター: + +:: + + token=xoxb-your-slack-bot-token-here + channels=*all + include_private=true + permission_sync=true + +スクリプト: + +:: + + title=message.user + " #" + message.channel + content=message.text + created=message.timestamp + url=message.permalink + role=message.roles + +.. note:: + + ``role=message.roles`` を書き忘れると、計算した権限は索引される文書に反映されません。 + 詳細は「権限同期(ACL)」を参照してください。 + トラブルシューティング ====================== +エラー処理の仕組み +------------------ + +Slackコネクタは、Slack APIのエラーを次の3種類に分けて扱います: + +- **致命的エラー**\ (``invalid_auth``、``token_revoked``、``account_inactive``、 + ``missing_scope``、``not_authed``、``token_expired``): トークン自体が使えない状態のため、 + クロールジョブ全体を失敗させます +- **一時的エラー**\ (``ratelimited``、``internal_error``、``fatal_error``、 + ``service_unavailable``、``request_timeout``): リトライしても解消しない場合、クロール + ジョブ全体を失敗させます(リトライの挙動は後述の「APIレート制限」を参照) +- **チャンネル単位のエラー**\ (``channel_not_found``、``not_in_channel`` など): そのチャンネル + だけを警告付きでスキップし、他のチャンネルのクロールは継続します + +以前のバージョンでは、致命的エラーが発生してもクロールが「成功」と扱われ、結果的に0件や +一部だけが索引される「サイレントな部分成功」が起きていました。現在はこの3分類に従い、 +致命的・一時的なエラーは必ずジョブの失敗として報告されます。 + 認証エラー ---------- @@ -369,38 +545,47 @@ https://api.slack.com/apps にアクセス: 1. チャンネル名が正しいか確認(# は不要) 2. アプリがチャンネルに追加されているか確認 3. プライベートチャンネルの場合、``include_private=true`` を設定 -4. チャンネルが存在し、アーカイブされていないか確認 +4. ``exclude_archived=true`` を設定していないか確認してください。既定(``exclude_archived=false``) + ではアーカイブ済みチャンネルも一覧に含まれ、クロールされます。``true`` にした場合のみ、 + ``channels`` にチャンネル名で指定したアーカイブ済みチャンネルが名前解決できなくなります メッセージが取得できない ------------------------ -**症状**: クロールは成功するがメッセージが0件 +**症状**: クロールは成功したが、索引される文書が少ない、または0件 **確認事項**: -1. 必要なスコープが付与されているか確認: +1. ``ignore_system_events`` の既定値は ``true`` です。チャンネル内のメッセージが + ``channel_join`` などのシステムイベントだけの場合、索引される文書は0件になります + (「高度なパラメーター」を参照) +2. チャンネルに実際にメッセージが投稿されているか確認 +3. アプリがチャンネルに追加されているか確認 +4. ``permission_sync=true`` の場合、プライベートチャンネルのメンバー取得に失敗すると、 + そのチャンネルはこのクロールでは索引されません(フェイルクローズ。「権限同期(ACL)」を参照) - - ``channels:history`` - - ``channels:read`` - - プライベートチャンネルの場合: ``groups:history``、``groups:read`` +.. note:: -2. チャンネルにメッセージが存在するか確認 -3. アプリがチャンネルに追加されているか確認 -4. Slackアプリが有効になっているか確認 + 以前のバージョンでは、スコープ不足(``missing_scope``)が発生してもクロールが成功したまま + メッセージ0件になっていました。現在は ``missing_scope`` を含む致命的エラーが発生すると、 + クロールジョブ自体が失敗します。ジョブが失敗している場合は、この節ではなく次の + 「権限不足エラー」を確認してください。 権限不足エラー -------------- -**症状**: ``missing_scope`` +**症状**: ``missing_scope``\ (クロールジョブ全体が失敗します) **解決方法**: 1. Slack App設定で必要なスコープを追加: - **パブリックチャンネル**: + **基本**\ (常に必要): - ``channels:history`` - ``channels:read`` + - ``users:read`` + - ``team:read`` **プライベートチャンネル**: @@ -411,6 +596,10 @@ https://api.slack.com/apps にアクセス: - ``files:read`` + **権限同期**\ (``permission_sync=true``): + + - ``users:read.email`` + 2. アプリを再インストール 3. |Fess| を再起動 @@ -424,22 +613,40 @@ https://api.slack.com/apps にアクセス: 1. ``files:read`` スコープが付与されているか確認 2. チャンネルに実際にファイルが投稿されているか確認 3. ファイルのアクセス権限を確認 +4. ``max_filesize`` を超えるファイルはダウンロードされません(ログの警告を確認) APIレート制限 ------------- -**症状**: ``rate_limited`` +**症状**: ``ratelimited``\ (クロールジョブ全体が失敗します) **解決方法**: -1. クロール間隔を長くする -2. チャンネル数を減らす -3. データストアを複数に分割してスケジュール分散 +1. ``max_retry_count``、``retry_interval`` の既定値で解決しない場合は値を増やす +2. ``read_interval`` を設定してクロール速度を落とす +3. チャンネル数を減らす、またはデータストアを複数に分割してスケジュールを分散する + +Slack APIの ``ratelimited`` エラーは、``Retry-After`` ヘッダーがあればその秒数、無ければ +``retry_interval`` を起点に倍増するバックオフ(``max_retry_count`` 回まで、最大60秒)で +自動的にリトライされます。リトライを使い切ってもレート制限が解消しない場合、クロール +ジョブ全体が失敗します。 + +Slack APIのTier(呼び出し可能回数の上限): -Slack APIの制限: +- Tier 1: 1+ リクエスト/分 +- Tier 2: 20+ リクエスト/分 — ``conversations.list``、``users.list``\ (クロール開始時に + 無条件で全件取得するため、最も枯渇しやすい) +- Tier 3: 50+ リクエスト/分 — ``conversations.history``、``conversations.replies``、 + ``files.list`` +- Tier 4: 100+ リクエスト/分 — ``conversations.members``\ (``permission_sync=true`` のとき + のみ)、``files.info``\ (このコネクタのクロール処理は現時点でこのAPIを呼び出しません) + +.. note:: -- Tier 3メソッド: 50+ リクエスト/分 -- Tier 4メソッド: 100+ リクエスト/分 + 2025年5月29日のSlackのレート制限強化(``conversations.history``、``conversations.replies`` + の2メソッドを50+リクエスト/分に制限)は、Slack Marketplaceなど社外に配布されたアプリのみが + 対象です。|Fess| 用に作成する、配布しない社内アプリ(作成したワークスペースにのみインストール + するアプリ)には適用されません。 大量のメッセージがある場合 -------------------------- @@ -450,7 +657,6 @@ Slack APIの制限: 1. チャンネルを分割して複数のデータストアを設定 2. クロールスケジュールを分散 -3. 古いメッセージを除外する設定を検討 スクリプトの応用例 ================== @@ -483,5 +689,7 @@ Slack APIの制限: - :doc:`ds-overview` - データストアコネクタ概要 - :doc:`ds-atlassian` - Atlassianコネクタ - :doc:`../../admin/dataconfig-guide` - データストア設定ガイド +- :doc:`../security-role` - 検索権限(ACL)の設定ガイド - `Slack API Documentation `_ - `Slack Bot Token Scopes `_ +- `Slack API Rate Limits `_ diff --git a/ko/15.9/config/datastore/ds-slack.rst b/ko/15.9/config/datastore/ds-slack.rst index ece9cc6d..d18ff1c9 100644 --- a/ko/15.9/config/datastore/ds-slack.rst +++ b/ko/15.9/config/datastore/ds-slack.rst @@ -11,12 +11,20 @@ Slack 커넥터는 Slack 워크스페이스의 채널 메시지를 가져와서 이 기능을 사용하려면 ``fess-ds-slack`` 플러그인이 필요합니다. 지원 콘텐츠 -============== +=========== - 퍼블릭 채널 메시지 - 프라이빗 채널 메시지 +- 스레드 답글 메시지(``conversations.replies`` 로 가져옵니다) - 파일 첨부(옵션) +다음은 대상 외입니다: + +- 시스템 이벤트 메시지(``channel_join``, ``channel_topic``, ``pinned_item`` 등)는 기본적으로 + 색인 대상에서 제외됩니다(``ignore_system_events``) +- 다이렉트 메시지(DM) 및 그룹 DM +- Huddle의 녹취록과 Clips(Slack에 공개 API가 없어 크롤링할 수 없습니다) + 전제조건 ======== @@ -25,7 +33,7 @@ Slack 커넥터는 Slack 워크스페이스의 채널 메시지를 가져와서 3. OAuth Access Token 취득이 필요합니다 플러그인 설치 ------------------------- +------------- 관리 화면의 "시스템" → "플러그인"에서 설치합니다: @@ -36,12 +44,12 @@ Slack 커넥터는 Slack 워크스페이스의 채널 메시지를 가져와서 또는 자세한 내용은 :doc:`../../admin/plugin-guide` 를 참조하세요. 설정 방법 -======== +========= 관리 화면에서 "크롤러" → "데이터 스토어" → "새로 만들기"에서 설정합니다. 기본 설정 --------- +--------- .. list-table:: :header-rows: 1 @@ -57,7 +65,7 @@ Slack 커넥터는 Slack 워크스페이스의 채널 메시지를 가져와서 - 켬 파라미터 설정 ----------------- +------------- :: @@ -67,7 +75,7 @@ Slack 커넥터는 Slack 워크스페이스의 채널 메시지를 가져와서 include_private=false 파라미터 목록 -~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~ .. list-table:: :header-rows: 1 @@ -137,8 +145,64 @@ Slack 커넥터는 Slack 워크스페이스의 채널 메시지를 가져와서 - 아니오 - 채널 정보 캐시의 최대 항목 수(기본값: ``10000``) +고급 파라미터 +~~~~~~~~~~~~~ + +아래 파라미터는 연결·재시도 동작, 세밀한 크롤링 범위 제어, 권한 동기화를 다룹니다: + +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - 파라미터 + - 설명 + * - ``connection_timeout`` + - 각 Slack API 요청의 연결 타임아웃(밀리초, 기본값: ``20000``) + * - ``read_timeout`` + - 각 Slack API 요청의 읽기 타임아웃(밀리초, 기본값: ``20000``) + * - ``max_retry_count`` + - ``429``\ (레이트 리밋) 또는 ``5xx`` 응답을 받았을 때의 최대 재시도 횟수(기본값: ``3``) + * - ``retry_interval`` + - 응답에 ``Retry-After`` 헤더가 없는 경우, 첫 재시도까지의 대기 시간(밀리초, 기본값: + ``3000``). 재시도할 때마다 두 배로 늘어나며 ``60000`` 밀리초에서 상한에 도달합니다. + ``Retry-After`` 헤더가 있으면 해당 값(초)이 우선합니다 + * - ``executor_timeout`` + - 크롤링 종료 시 대기열에 남은 작업이 완료될 때까지 기다리는 시간(초, 기본값: ``60``). + 이 시간을 초과하면 강제 종료됩니다 + * - ``exclude_archived`` + - ``conversations.list`` 의 결과에서 아카이브된 채널을 제외할지 여부(기본값: ``false``). + ``true`` 로 설정하면 ``channels`` 에 채널명으로 지정한 아카이브된 채널을 이름으로 + 확인할 수 없게 됩니다(자세한 내용은 문제 해결 참조) + * - ``ignore_system_events`` + - Slack이 자동 생성하는 채널 관리 계열 메시지(``channel_join``, ``channel_topic``, + ``pinned_item`` 등)를 색인 대상에서 제외할지 여부(기본값: ``true``) + * - ``read_interval`` + - 메시지 또는 파일을 1건 처리할 때마다 대기하는 시간(밀리초, 기본값: ``0`` = 대기 없음). + 레이트 리밋이 엄격한 워크스페이스에 대해 크롤링 속도를 늦출 때 사용합니다 + * - ``max_content_length`` + - 콘텐츠 추출(Tika)이 파일 1건에서 추출할 수 있는 최대 문자 수(기본값: 미설정 = MIME + 타입별 |Fess| 기본 상한을 따름). ``max_filesize`` 는 다운로드 전에 파일 크기로 걸러내는 + 전송량의 상한이고, ``max_content_length`` 는 다운로드 후 추출하는 텍스트양의 상한으로, + 각각 독립적으로 동작합니다. ``max_filesize`` 를 줄여도 ``max_content_length`` 를 + 대신할 수는 없습니다(예: 1MB의 압축 파일이라도 압축 해제 후에는 훨씬 많은 텍스트가 + 될 수 있습니다) + * - ``permission_sync`` + - 프라이빗 채널의 멤버십을 검색용 권한(역할)으로 변환할지 여부(기본값: ``false``). + 자세한 내용은 뒤에 나오는 "권한 동기화(ACL)"를 참조하세요 + * - ``default_permissions`` + - 채널 멤버십과 무관하게 색인되는 모든 문서에 부여할 추가 권한(``{user}``/``{group}``/ + ``{role}`` 형식, 쉼표 구분, 기본값: 비어 있음). ``permission_sync`` 가 활성화된 경우에만 + 적용됩니다 + +.. note:: + + ``ignore_system_events`` 의 기본값은 ``true`` 입니다. 이 파라미터를 지정하지 않은 기존 + 크롤링 설정이라도, |Fess| 를 업그레이드하면 ``channel_join`` 등의 시스템 이벤트 메시지가 + 더 이상 색인되지 않게 되어, 오류나 경고 없이 색인되는 문서 수가 줄어듭니다. 이전과 동일하게 + 시스템 이벤트도 색인하려면 ``ignore_system_events=false`` 를 명시적으로 지정하세요. + 스크립트 설정 --------------- +------------- :: @@ -150,7 +214,7 @@ Slack 커넥터는 Slack 워크스페이스의 채널 메시지를 가져와서 url=message.permalink 사용 가능한 필드 -~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~ .. list-table:: :header-rows: 1 @@ -172,12 +236,16 @@ Slack 커넥터는 Slack 워크스페이스의 채널 메시지를 가져와서 - 메시지의 퍼머링크 * - ``message.attachments`` - 첨부 파일의 폴백 정보 + * - ``message.roles`` + - 이 메시지 또는 파일을 볼 수 있는 검색 권한(역할) 목록. ``permission_sync=true`` 인 + 경우에만 존재하는 필드입니다. 스크립트에서 ``role=message.roles`` 를 지정하지 않으면 + 계산된 권한은 색인되는 문서에 반영되지 않습니다 Slack App 설정 -============= +============== 1. Slack App 생성 ------------------- +----------------- https://api.slack.com/apps 에 접속: @@ -188,32 +256,36 @@ https://api.slack.com/apps 에 접속: 5. "Create App" 클릭 2. OAuth & Permissions 설정 ----------------------------- +--------------------------- "OAuth & Permissions" 메뉴에서: **Bot Token Scopes**\ 에 다음을 추가: -퍼블릭 채널만의 경우: +기본 스코프(항상 필요): - ``channels:history`` - 퍼블릭 채널 메시지 읽기 - ``channels:read`` - 퍼블릭 채널 정보 읽기 - ``users:read`` - 사용자 정보 읽기(표시 이름 해결에 필요) +- ``team:read`` - 워크스페이스 정보 읽기. ``team.info`` 를 크롤링할 때마다 호출하므로 이 + 스코프는 필수입니다. 이 스코프가 없으면 이 커넥터는 메시지 1건마다 ``chat.getPermalink`` + 를 추가로 호출하게 되어 API 호출 수가 크게 늘어납니다 -프라이빗 채널도 포함하는 경우(``include_private=true``): +프라이빗 채널도 포함하는 경우(``include_private=true``)에 추가: -- ``channels:history`` -- ``channels:read`` - ``groups:history`` - 프라이빗 채널 메시지 읽기 - ``groups:read`` - 프라이빗 채널 정보 읽기 -- ``users:read`` -파일도 크롤링하는 경우(``file_crawl=true``): +파일도 크롤링하는 경우(``file_crawl=true``)에 추가: - ``files:read`` - 파일 콘텐츠 읽기 +프라이빗 채널의 권한을 동기화하는 경우(``permission_sync=true``)에 추가: + +- ``users:read.email`` - 멤버의 이메일 주소 읽기(권한 동기화에 필수) + 3. 앱 설치 ------------------------ +---------- "Install App" 메뉴에서: @@ -226,7 +298,7 @@ https://api.slack.com/apps 에 접속: 파라미터에서는 ``xoxp-``\ 로 시작하는 User OAuth Token도 사용 가능합니다. 4. 채널에 추가 ---------------------- +-------------- 크롤링 대상 채널에 App을 추가: @@ -236,11 +308,83 @@ https://api.slack.com/apps 에 접속: 4. "앱 추가" 클릭 5. 생성한 앱 추가 +권한 동기화(ACL) +================ + +Slack 커넥터는 프라이빗 채널의 멤버십을 |Fess| 의 검색 권한(역할)으로 변환하여, 해당 채널의 +멤버만 콘텐츠를 검색할 수 있도록 하는 기능을 제공합니다. 기본값은 비활성화입니다. + +.. note:: + + ``permission_sync`` 는 권한(역할)을 계산할 뿐, 자동으로 적용하지는 않습니다. 스크립트에 + ``role=message.roles`` 를 추가해야만 계산된 권한이 색인되는 문서에 반영됩니다. 이 매핑을 + 잊으면 ``permission_sync=true`` 로 인한 API 호출 증가와 프라이빗 채널 건너뛰기만 발생할 + 뿐, 접근 제어는 전혀 이루어지지 않습니다. + +활성화 방법 +----------- + +1. Slack App에 ``users:read.email`` 스코프를 추가합니다(멤버의 이메일 주소 확인에 필수) +2. 파라미터에 ``permission_sync=true`` 를 설정합니다 +3. 스크립트에 ``role=message.roles`` 를 추가합니다 + +파라미터: + +:: + + include_private=true + permission_sync=true + +스크립트: + +:: + + role=message.roles + +페일 클로즈(Fail-Closed) 동작 +----------------------------- + +다음 중 하나에 해당하는 프라이빗 채널은 해당 크롤링에서 전혀 색인되지 않습니다(콘텐츠가 +잘못 공개되는 대신 색인하지 않는 방향으로 처리하는 "페일 클로즈" 동작입니다): + +- 채널의 멤버 목록 취득에 실패한 경우 +- 멤버 목록이 0건이었던 경우(크롤링에 사용하는 토큰의 봇 사용자 자신이 해당 프라이빗 채널에 + 참가하지 않은 경우 발생합니다) +- 멤버는 있지만 그중 누구의 이메일 주소도 확인할 수 없었던 경우(주로 ``users:read.email`` + 스코프 부족이 원인입니다) + +퍼블릭 채널은 ``conversations.members`` 를 호출하지 않으며 항상 모두가 볼 수 있는 것으로 +간주됩니다. + +프린시펄 이름 일치 +------------------ + +검색 시 권한 판정은 |Fess| 의 로그인 이름(프린시펄 이름)으로 이루어집니다. 이 기능이 +계산하는 권한은 Slack의 이메일 주소로부터 만들어지므로, |Fess| 의 로그인 이름과 Slack의 +이메일 주소를 일치시켜야 합니다. Slack은 이메일 주소를 소문자로 정규화하므로, |Fess| 쪽의 +로그인 이름도 소문자로 해 두십시오. 일치하지 않는 경우 다른 사람의 문서가 보이는 것이 아니라, +해당 사용자의 검색 결과가 항상 0건이 됩니다(원인을 파악하기 어려우므로 주의하세요). + +기타 주의사항 +------------- + +- Slack의 사용자 그룹(User Group)은 사용하지 않습니다. 권한은 각 멤버의 이메일 주소로부터 + 직접 계산합니다 +- ``default_permissions`` 로 채널 멤버십과 무관하게 모든 문서에 부여할 추가 권한을 지정할 + 수 있습니다(``permission_sync=true`` 인 경우에만 적용) +- ``permission_sync=false`` 인 채로 ``include_private=true`` 로 설정하면, 프라이빗 채널의 + 콘텐츠는 데이터 스토어 설정의 "권한" 항목 설정만으로 색인됩니다. 이 항목이 비어 있으면 + 사실상 모두에게 공개됩니다 +- 이미 색인된 워크스페이스에서 ``permission_sync`` 를 나중에 활성화하더라도, 이전에 색인된 + 문서에 소급하여 권한이 부여되지는 않습니다. 적용하려면 ``permission_sync=true`` 와 + ``role=message.roles`` 를 설정한 뒤 다시 크롤링하십시오. 마찬가지로 ``permission_sync`` + 를 나중에 비활성화하더라도, 이미 적용된 권한이 색인된 문서에서 자동으로 제거되지는 않습니다 + 사용 예 -====== +======= 특정 채널 크롤링 --------------------------- +---------------- 파라미터: @@ -263,7 +407,7 @@ https://api.slack.com/apps 에 접속: url=message.permalink 모든 채널 크롤링 ----------------------------- +---------------- 파라미터: @@ -284,7 +428,7 @@ https://api.slack.com/apps 에 접속: url=message.permalink 프라이빗 채널 포함 크롤링 --------------------------------------- +------------------------- 파라미터: @@ -306,7 +450,7 @@ https://api.slack.com/apps 에 접속: url=message.permalink 파일 포함 크롤링 ------------------------- +---------------- 파라미터: @@ -327,7 +471,7 @@ https://api.slack.com/apps 에 접속: url=message.permalink 상세 메시지 정보 포함 ----------------------------- +--------------------- 스크립트: @@ -340,11 +484,59 @@ https://api.slack.com/apps 에 접속: timestamp=message.timestamp url=message.permalink +권한을 동기화하여 크롤링 +------------------------ + +프라이빗 채널의 콘텐츠를 해당 채널의 멤버만 검색할 수 있도록 합니다. 사전에 Slack App에 +``users:read.email`` 스코프를 추가하세요. + +파라미터: + +:: + + token=xoxb-your-slack-bot-token-here + channels=*all + include_private=true + permission_sync=true + +스크립트: + +:: + + title=message.user + " #" + message.channel + content=message.text + created=message.timestamp + url=message.permalink + role=message.roles + +.. note:: + + ``role=message.roles`` 를 빠뜨리면 계산된 권한이 색인되는 문서에 반영되지 않습니다. + 자세한 내용은 "권한 동기화(ACL)"를 참조하세요. + 문제 해결 -====================== +========= + +오류 처리 방식 +-------------- + +Slack 커넥터는 Slack API 오류를 다음 세 가지로 구분하여 처리합니다: + +- **치명적 오류**\ (``invalid_auth``, ``token_revoked``, ``account_inactive``, + ``missing_scope``, ``not_authed``, ``token_expired``): 토큰 자체를 사용할 수 없는 + 상태이므로 크롤링 작업 전체를 실패로 처리합니다 +- **일시적 오류**\ (``ratelimited``, ``internal_error``, ``fatal_error``, + ``service_unavailable``, ``request_timeout``): 재시도해도 해소되지 않으면 크롤링 작업 + 전체를 실패로 처리합니다(재시도 동작은 뒤의 "API 속도 제한" 참조) +- **채널 단위 오류**\ (``channel_not_found``, ``not_in_channel`` 등): 해당 채널만 경고와 + 함께 건너뛰고, 다른 채널의 크롤링은 계속됩니다 + +이전 버전에서는 치명적 오류가 발생해도 크롤링이 "성공"으로 처리되어, 결과적으로 0건 또는 +일부만 색인되는 "조용한 부분 성공"이 발생했습니다. 현재는 이 세 가지 분류에 따라 치명적· +일시적 오류는 반드시 작업 실패로 보고됩니다. 인증 오류 ----------- +--------- **증상**: ``invalid_auth`` 또는 ``not_authed`` @@ -360,7 +552,7 @@ https://api.slack.com/apps 에 접속: 4. 필요한 권한이 부여되어 있는지 확인 채널을 찾을 수 없음 ------------------------- +------------------- **증상**: ``channel_not_found`` @@ -369,38 +561,48 @@ https://api.slack.com/apps 에 접속: 1. 채널명이 올바른지 확인(#은 불필요) 2. 앱이 채널에 추가되어 있는지 확인 3. 프라이빗 채널인 경우 ``include_private=true`` 설정 -4. 채널이 존재하고 아카이브되지 않았는지 확인 +4. ``exclude_archived=true`` 를 설정하지 않았는지 확인하세요. 기본값 + (``exclude_archived=false``)에서는 아카이브된 채널도 목록에 포함되어 크롤링됩니다. + ``true`` 로 설정한 경우에만 ``channels`` 에 채널명으로 지정한 아카이브된 채널을 이름으로 + 확인할 수 없게 됩니다 메시지를 가져올 수 없음 ------------------------- +----------------------- -**증상**: 크롤링은 성공하지만 메시지가 0개 +**증상**: 크롤링은 성공했지만 색인되는 문서가 적거나 0건 **확인 사항**: -1. 필요한 범위가 부여되어 있는지 확인: +1. ``ignore_system_events`` 의 기본값은 ``true`` 입니다. 채널 내 메시지가 + ``channel_join`` 등의 시스템 이벤트뿐인 경우, 해당 채널은 색인되는 문서가 0건이 됩니다 + ("고급 파라미터" 참조) +2. 채널에 실제로 메시지가 게시되어 있는지 확인 +3. 앱이 채널에 추가되어 있는지 확인 +4. ``permission_sync=true`` 인 경우, 프라이빗 채널의 멤버 취득에 실패하면 해당 채널은 이번 + 크롤링에서 색인되지 않습니다(페일 클로즈. "권한 동기화(ACL)" 참조) - - ``channels:history`` - - ``channels:read`` - - 프라이빗 채널인 경우: ``groups:history``, ``groups:read`` +.. note:: -2. 채널에 메시지가 존재하는지 확인 -3. 앱이 채널에 추가되어 있는지 확인 -4. Slack 앱이 활성화되어 있는지 확인 + 이전 버전에서는 스코프 부족(``missing_scope``)이 발생해도 크롤링이 성공한 채로 메시지 + 0건이 되는 경우가 있었습니다. 현재는 ``missing_scope`` 를 포함한 치명적 오류가 발생하면 + 크롤링 작업 자체가 실패합니다. 작업이 실패하고 있다면 이 절이 아니라 다음의 "권한 부족 + 오류"를 확인하세요. 권한 부족 오류 -------------- -**증상**: ``missing_scope`` +**증상**: ``missing_scope``\ (크롤링 작업 전체가 실패합니다) **해결 방법**: -1. Slack App 설정에서 필요한 범위 추가: +1. Slack App 설정에서 필요한 스코프 추가: - **퍼블릭 채널**: + **기본**\ (항상 필요): - ``channels:history`` - ``channels:read`` + - ``users:read`` + - ``team:read`` **프라이빗 채널**: @@ -411,38 +613,60 @@ https://api.slack.com/apps 에 접속: - ``files:read`` + **권한 동기화**\ (``permission_sync=true``): + + - ``users:read.email`` + 2. 앱 재설치 3. |Fess| 재시작 파일을 크롤링할 수 없음 --------------------------- +----------------------- **증상**: ``file_crawl=true``\ 인데도 파일이 가져와지지 않음 **확인 사항**: -1. ``files:read`` 범위가 부여되어 있는지 확인 +1. ``files:read`` 스코프가 부여되어 있는지 확인 2. 채널에 실제로 파일이 게시되어 있는지 확인 3. 파일의 액세스 권한 확인 +4. ``max_filesize`` 를 초과하는 파일은 다운로드되지 않습니다(로그의 경고를 확인하세요) API 속도 제한 ------------- -**증상**: ``rate_limited`` +**증상**: ``ratelimited``\ (크롤링 작업 전체가 실패합니다) **해결 방법**: -1. 크롤링 간격을 늘림 -2. 채널 수를 줄임 -3. 데이터 스토어를 여러 개로 분할하여 스케줄 분산 +1. ``max_retry_count``, ``retry_interval`` 의 기본값으로 해결되지 않으면 값을 늘림 +2. ``read_interval`` 을 설정하여 크롤링 속도를 늦춤 +3. 채널 수를 줄이거나, 데이터 스토어를 여러 개로 분할하여 스케줄을 분산 -Slack API 제한: +Slack API의 ``ratelimited`` 오류는 ``Retry-After`` 헤더가 있으면 그 초수, 없으면 +``retry_interval`` 을 기점으로 두 배씩 늘어나는 백오프(``max_retry_count`` 회까지, 최대 +60초)로 자동으로 재시도됩니다. 재시도를 모두 사용해도 속도 제한이 해소되지 않으면 크롤링 +작업 전체가 실패합니다. -- Tier 3 메서드: 50+ 요청/분 -- Tier 4 메서드: 100+ 요청/분 +Slack API의 Tier(호출 가능 횟수의 상한): + +- Tier 1: 1+ 요청/분 +- Tier 2: 20+ 요청/분 — ``conversations.list``, ``users.list``\ (크롤링 시작 시 무조건 + 전량 취득하므로 가장 고갈되기 쉽습니다) +- Tier 3: 50+ 요청/분 — ``conversations.history``, ``conversations.replies``, + ``files.list`` +- Tier 4: 100+ 요청/분 — ``conversations.members``\ (``permission_sync=true`` 일 때만), + ``files.info``\ (이 커넥터의 크롤링에서는 현재 호출되지 않습니다) + +.. note:: + + 2025년 5월 29일자 Slack의 레이트 리밋 강화(``conversations.history``, + ``conversations.replies`` 두 메서드를 50+ 요청/분으로 제한)는 Slack Marketplace 등 + 생성한 워크스페이스 밖으로 배포되는 앱에만 적용됩니다. |Fess| 용으로 만들어, 생성한 + 워크스페이스에만 설치하는 사내 앱에는 적용되지 않습니다. 대량의 메시지가 있는 경우 --------------------------- +------------------------- **증상**: 크롤링에 시간이 오래 걸리거나 타임아웃됨 @@ -450,13 +674,12 @@ Slack API 제한: 1. 채널을 분할하여 여러 데이터 스토어 설정 2. 크롤링 스케줄 분산 -3. 오래된 메시지를 제외하는 설정 고려 스크립트 응용 예 -======================== +================ 메시지 가공 ----------------- +----------- 긴 메시지 요약: @@ -478,10 +701,12 @@ Slack API 제한: url=message.permalink 참고 정보 -======== +========= - :doc:`ds-overview` - 데이터 스토어 커넥터 개요 - :doc:`ds-atlassian` - Atlassian 커넥터 - :doc:`../../admin/dataconfig-guide` - 데이터 스토어 설정 가이드 +- :doc:`../security-role` - 역할 기반 검색 설정 가이드 - `Slack API Documentation `_ - `Slack Bot Token Scopes `_ +- `Slack API Rate Limits `_ diff --git a/zh-cn/15.9/config/datastore/ds-slack.rst b/zh-cn/15.9/config/datastore/ds-slack.rst index 4fa5b890..b4fcfb06 100644 --- a/zh-cn/15.9/config/datastore/ds-slack.rst +++ b/zh-cn/15.9/config/datastore/ds-slack.rst @@ -11,12 +11,20 @@ Slack连接器提供从Slack工作区获取频道消息并注册到 此功能需要 ``fess-ds-slack`` 插件。 支持的内容 -============== +========== - 公共频道消息 - 私有频道消息 +- 线程回复消息(通过 ``conversations.replies``\ 获取) - 文件附件(可选) +以下内容不在支持范围内: + +- 系统事件消息(``channel_join``、``channel_topic``、``pinned_item``\ 等)默认会从索引中 + 排除(``ignore_system_events``) +- 私信(DM)及群组私信 +- Huddle的转录内容和Clips(Slack未提供公开API,因此无法爬取) + 前提条件 ======== @@ -25,7 +33,7 @@ Slack连接器提供从Slack工作区获取频道消息并注册到 3. 需要获取OAuth Access Token 插件安装 ------------------------- +-------- 从管理界面的「系统」→「插件」进行安装: @@ -57,7 +65,7 @@ Slack连接器提供从Slack工作区获取频道消息并注册到 - 开 参数设置 ----------------- +-------- :: @@ -67,7 +75,7 @@ Slack连接器提供从Slack工作区获取频道消息并注册到 include_private=false 参数列表 -~~~~~~~~~~~~~~~~ +~~~~~~~~ .. list-table:: :header-rows: 1 @@ -93,13 +101,13 @@ Slack连接器提供从Slack工作区获取频道消息并注册到 - 并行处理线程数(默认: ``1``) * - ``max_filesize`` - 否 - - 爬取文件的最大大小(字节, 默认: ``10000000``) + - 爬取文件的最大大小(字节,默认: ``10000000``) * - ``ignore_error`` - 否 - 发生错误时继续处理(默认: ``true``) * - ``supported_mimetypes`` - 否 - - 允许的MIME类型(正则表达式, 默认: ``.*``) + - 允许的MIME类型(正则表达式,默认: ``.*``) * - ``include_pattern`` - 否 - 包含URL的正则表达式模式 @@ -137,8 +145,60 @@ Slack连接器提供从Slack工作区获取频道消息并注册到 - 否 - 频道信息缓存的最大条目数(默认: ``10000``) +高级参数 +~~~~~~~~ + +以下参数用于控制连接与重试行为、精细的爬取范围,以及权限同步: + +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - 参数 + - 说明 + * - ``connection_timeout`` + - 每次Slack API请求的连接超时时间(毫秒,默认: ``20000``) + * - ``read_timeout`` + - 每次Slack API请求的读取超时时间(毫秒,默认: ``20000``) + * - ``max_retry_count`` + - 收到 ``429``\ (速率限制)或 ``5xx`` 响应时的最大重试次数(默认: ``3``) + * - ``retry_interval`` + - 当响应中没有 ``Retry-After`` 头时,首次重试前的等待时间(毫秒,默认: ``3000``)。每次 + 重试后翻倍,上限为 ``60000``\ 毫秒。若响应包含 ``Retry-After`` 头,则优先使用该值 + (单位: 秒) + * - ``executor_timeout`` + - 爬取结束时,等待队列中剩余任务完成的秒数(默认: ``60``)。超过此时间将强制终止 + * - ``exclude_archived`` + - 是否从 ``conversations.list`` 的结果中排除已归档的频道(默认: ``false``)。设为 + ``true``\ 时,在 ``channels`` 中按频道名指定的已归档频道将无法解析(详情参见故障排除) + * - ``ignore_system_events`` + - 是否将Slack自动生成的频道管理类消息(``channel_join``、``channel_topic``、 + ``pinned_item``\ 等)从索引中排除(默认: ``true``) + * - ``read_interval`` + - 每处理一条消息或文件后的等待时间(毫秒,默认: ``0``\ ,即不等待)。可用于在速率限制 + 严格的工作区中降低爬取速度 + * - ``max_content_length`` + - 内容提取(Tika)从单个文件中可提取的最大字符数(默认: 未设置,此时遵循 |Fess| + 按MIME类型划分的默认上限)。``max_filesize`` 是下载前按文件大小拦截的传输量上限, + ``max_content_length`` 是下载后提取文本量的上限,两者各自独立生效。调小 + ``max_filesize`` 并不能替代 ``max_content_length``\ (例如,1MB的压缩文件解压后可能 + 产生远大于此的文本量) + * - ``permission_sync`` + - 是否将私有频道的成员关系转换为搜索用权限(角色)(默认: ``false``)。详情参见后文 + 「权限同步(ACL)」 + * - ``default_permissions`` + - 无论频道成员关系如何,都授予所有已索引文档的附加权限(``{user}``/``{group}``/ + ``{role}``\ 格式,逗号分隔,默认: 空)。仅在启用 ``permission_sync`` 时生效 + +.. note:: + + ``ignore_system_events`` 的默认值为 ``true``\ 。即使是未设置此参数的现有爬取配置,在升级 + |Fess| 后,也会不再索引 ``channel_join`` 等系统事件消息——索引的文档数量会在没有任何错误 + 或警告的情况下减少。若希望像以前一样继续索引系统事件,请显式指定 + ``ignore_system_events=false``\ 。 + 脚本设置 --------------- +-------- :: @@ -150,7 +210,7 @@ Slack连接器提供从Slack工作区获取频道消息并注册到 url=message.permalink 可用字段 -~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~ .. list-table:: :header-rows: 1 @@ -172,12 +232,15 @@ Slack连接器提供从Slack工作区获取频道消息并注册到 - 消息的永久链接 * - ``message.attachments`` - 附件文件的回退信息 + * - ``message.roles`` + - 可查看此消息或文件的搜索权限(角色)列表。仅在 ``permission_sync=true`` 时存在此字段。 + 除非脚本中指定了 ``role=message.roles``\ ,否则计算出的权限不会反映到已索引的文档中 Slack App设置 ============= 1. 创建Slack App ------------------- +---------------- 访问 https://api.slack.com/apps: @@ -188,32 +251,36 @@ Slack App设置 5. 点击「Create App」 2. OAuth & Permissions设置 ----------------------------- +-------------------------- 在「OAuth & Permissions」菜单中: **在Bot Token Scopes中添加以下权限**: -仅公共频道时: +基础权限(始终需要): - ``channels:history`` - 读取公共频道消息 - ``channels:read`` - 读取公共频道信息 - ``users:read`` - 读取用户信息(显示名称解析所需) +- ``team:read`` - 读取工作区信息。每次爬取都会调用 ``team.info``\ ,因此该权限是必需的; + 若缺少此权限,本连接器会针对每条消息回退到额外调用一次 ``chat.getPermalink``\ ,从而大幅 + 增加API调用次数 -包含私有频道时(``include_private=true``): +包含私有频道时(``include_private=true``)额外添加: -- ``channels:history`` -- ``channels:read`` - ``groups:history`` - 读取私有频道消息 - ``groups:read`` - 读取私有频道信息 -- ``users:read`` -也爬取文件时(``file_crawl=true``): +也爬取文件时(``file_crawl=true``)额外添加: - ``files:read`` - 读取文件内容 +同步私有频道权限时(``permission_sync=true``)额外添加: + +- ``users:read.email`` - 读取成员的邮箱地址(权限同步所必需) + 3. 安装应用 ------------------------ +----------- 在「Install App」菜单中: @@ -226,7 +293,7 @@ Slack App设置 但参数中也可以使用以 ``xoxp-`` 开头的User OAuth Token。 4. 添加到频道 ---------------------- +------------- 将App添加到爬取目标频道: @@ -236,11 +303,76 @@ Slack App设置 4. 点击「添加应用」 5. 添加创建的应用 +权限同步(ACL) +=============== + +Slack连接器可以将私有频道的成员关系转换为 |Fess| 的搜索权限(角色),使得只有该频道的成员 +才能搜索其内容。默认情况下此功能处于禁用状态。 + +.. note:: + + ``permission_sync`` 仅计算权限(角色),并不会自动应用它们。只有在脚本中添加 + ``role=message.roles`` 后,计算出的权限才会反映到已索引的文档中。若忘记添加此映射, + ``permission_sync=true`` 所带来的API调用增加和私有频道跳过依然会发生,却完全不会产生 + 任何访问控制效果。 + +启用方法 +-------- + +1. 为Slack App添加 ``users:read.email`` 权限(解析成员邮箱地址所必需) +2. 在参数中设置 ``permission_sync=true`` +3. 在脚本中添加 ``role=message.roles`` + +参数: + +:: + + include_private=true + permission_sync=true + +脚本: + +:: + + role=message.roles + +失败关闭(Fail-Closed)行为 +--------------------------- + +符合以下任一条件的私有频道,在该次爬取中将完全不会被索引(这是一种「失败关闭」行为:宁可 +索引不足,也绝不会将内容意外公开给所有人): + +- 获取该频道成员列表失败 +- 成员列表返回为空(当用于爬取的令牌所属的机器人用户本身未加入该私有频道时会发生此情况) +- 频道有成员,但无法解析其中任何一位的邮箱地址(通常是因为缺少 ``users:read.email`` 权限) + +公共频道从不调用 ``conversations.members``\ ,始终被视为所有人可见。 + +主体名称匹配 +------------ + +搜索时的权限判定使用 |Fess| 的登录名(即主体名称)。由于此功能计算出的权限来自Slack的邮箱 +地址,因此 |Fess| 的登录名必须与Slack的邮箱地址一致。Slack会将邮箱地址统一转换为小写,因此 +请同样将 |Fess| 一侧的登录名保持为小写。若两者不一致,并不会导致看到他人的内容,而是会使 +相应用户的搜索结果始终为0条(由于原因不易察觉,请特别注意)。 + +其他注意事项 +------------ + +- 不使用Slack的用户组(User Group)功能,权限直接根据每位成员的邮箱地址计算 +- 可通过 ``default_permissions`` 指定无论频道成员关系如何都授予所有文档的附加权限(仅在 + ``permission_sync=true`` 时生效) +- 若保持 ``permission_sync=false`` 而将 ``include_private=true``\ ,则私有频道的内容仅根据 + 数据存储设置中「权限」栏的设置进行索引;若该栏为空,则实际上对所有人公开 +- 对已经建立索引的工作区,事后启用 ``permission_sync`` 并不会为此前已索引的文档追溯授予 + 权限。如需应用权限,请设置 ``permission_sync=true`` 和 ``role=message.roles``\ 后重新爬取。 + 同样,之后禁用 ``permission_sync`` 也不会自动移除已应用到先前已索引文档上的权限 + 使用示例 ======== 爬取特定频道 --------------------------- +------------ 参数: @@ -263,7 +395,7 @@ Slack App设置 url=message.permalink 爬取所有频道 ----------------------------- +------------ 参数: @@ -284,7 +416,7 @@ Slack App设置 url=message.permalink 包含私有频道爬取 --------------------------------------- +---------------- 参数: @@ -306,7 +438,7 @@ Slack App设置 url=message.permalink 包含文件爬取 ------------------------- +------------ 参数: @@ -327,7 +459,7 @@ Slack App设置 url=message.permalink 包含详细消息信息 ----------------------------- +---------------- 脚本: @@ -340,11 +472,58 @@ Slack App设置 timestamp=message.timestamp url=message.permalink +同步权限进行爬取 +---------------- + +限制私有频道的内容,使其只能被该频道的成员搜索到。请事先为Slack App添加 +``users:read.email`` 权限。 + +参数: + +:: + + token=xoxb-your-slack-bot-token-here + channels=*all + include_private=true + permission_sync=true + +脚本: + +:: + + title=message.user + " #" + message.channel + content=message.text + created=message.timestamp + url=message.permalink + role=message.roles + +.. note:: + + 若忘记添加 ``role=message.roles``\ ,计算出的权限将不会反映到已索引的文档中。详情参见 + 「权限同步(ACL)」。 + 故障排除 -====================== +======== + +错误处理机制 +------------ + +Slack连接器将Slack API的错误分为以下三类进行处理: + +- **致命错误**\ (``invalid_auth``、``token_revoked``、``account_inactive``、 + ``missing_scope``、``not_authed``、``token_expired``): 令牌本身已不可用,因此会使整个 + 爬取任务失败 +- **临时错误**\ (``ratelimited``、``internal_error``、``fatal_error``、 + ``service_unavailable``、``request_timeout``): 若重试仍无法解决,会使整个爬取任务失败 + (重试行为详见后文「API速率限制」) +- **频道级错误**\ (``channel_not_found``、``not_in_channel``\ 等): 仅跳过该频道并给出 + 警告,其他频道的爬取继续进行 + +在早期版本中,即使发生致命错误,爬取仍可能被报告为「成功」,结果导致只索引了0条或部分 +文档的「静默部分成功」。目前按照上述三种分类,致命错误和临时错误都必定会被报告为任务失败。 认证错误 ----------- +-------- **症状**: ``invalid_auth`` 或 ``not_authed`` @@ -360,7 +539,7 @@ Slack App设置 4. 确认是否授予了所需权限 找不到频道 ------------------------- +---------- **症状**: ``channel_not_found`` @@ -369,38 +548,45 @@ Slack App设置 1. 确认频道名是否正确(不需要#) 2. 确认应用是否已添加到频道 3. 私有频道时,设置 ``include_private=true`` -4. 确认频道是否存在且未归档 +4. 请确认是否设置了 ``exclude_archived=true``\ 。默认情况下(``exclude_archived=false``), + 已归档的频道仍会被列出并爬取;只有设为 ``true``\ 时,在 ``channels`` 中按频道名指定的 + 已归档频道才会无法解析 无法获取消息 ------------------------- +------------ -**症状**: 爬取成功但消息数为0 +**症状**: 爬取成功,但索引的文档很少或为0条 **确认事项**: -1. 确认是否授予了所需权限范围: - - - ``channels:history`` - - ``channels:read`` - - 私有频道时: ``groups:history``、``groups:read`` - +1. ``ignore_system_events`` 的默认值为 ``true``\ 。若某频道内的消息全部为 + ``channel_join`` 等系统事件,则该频道会被索引0条文档(参见「高级参数」) 2. 确认频道中是否存在消息 3. 确认应用是否已添加到频道 -4. 确认Slack应用是否已启用 +4. 当 ``permission_sync=true`` 时,若私有频道的成员获取失败,该频道在本次爬取中将不会被 + 索引(失败关闭;参见「权限同步(ACL)」) + +.. note:: + + 在早期版本中,即使出现权限缺失(``missing_scope``),爬取仍可能以「成功」状态结束但消息 + 数为0。现在,包括 ``missing_scope`` 在内的致命错误会导致整个爬取任务失败。若您的任务 + 正在失败,请参阅后文的「权限不足错误」,而非本节。 权限不足错误 --------------- +------------ -**症状**: ``missing_scope`` +**症状**: ``missing_scope``\ (将导致整个爬取任务失败) **解决方法**: -1. 在Slack App设置中添加所需权限范围: +1. 在Slack App设置中添加所需权限: - **公共频道**: + **基础**\ (始终需要): - ``channels:history`` - ``channels:read`` + - ``users:read`` + - ``team:read`` **私有频道**: @@ -411,38 +597,59 @@ Slack App设置 - ``files:read`` + **权限同步**\ (``permission_sync=true``): + + - ``users:read.email`` + 2. 重新安装应用 3. 重启 |Fess| 无法爬取文件 --------------------------- +------------ **症状**: ``file_crawl=true`` 时也无法获取文件 **确认事项**: -1. 确认是否授予了 ``files:read`` 权限范围 +1. 确认是否授予了 ``files:read`` 权限 2. 确认频道中是否实际发布了文件 3. 确认文件的访问权限 +4. 超过 ``max_filesize`` 的文件不会被下载(请查看日志中的警告) API速率限制 -------------- +----------- -**症状**: ``rate_limited`` +**症状**: ``ratelimited``\ (将导致整个爬取任务失败) **解决方法**: -1. 增加爬取间隔 -2. 减少频道数 -3. 分割成多个数据存储并分散计划 +1. 若默认的 ``max_retry_count``、``retry_interval`` 无法解决问题,请增大取值 +2. 设置 ``read_interval`` 以降低爬取速度 +3. 减少频道数量,或拆分为多个数据存储并分散计划 + +Slack API的 ``ratelimited`` 错误会自动重试:若响应中带有 ``Retry-After`` 头,则使用其 +秒数;否则以 ``retry_interval`` 为起点按指数退避(最多重试 ``max_retry_count`` 次,上限 +为60秒)。若用尽所有重试后速率限制仍未解除,则整个爬取任务失败。 + +Slack API的Tier(可调用次数上限): -Slack API限制: +- Tier 1: 1+请求/分钟 +- Tier 2: 20+请求/分钟 —— ``conversations.list``、``users.list``\ (在每次爬取开始时无条件 + 全量获取,因此最容易耗尽此层级) +- Tier 3: 50+请求/分钟 —— ``conversations.history``、``conversations.replies``、 + ``files.list`` +- Tier 4: 100+请求/分钟 —— ``conversations.members``\ (仅在 ``permission_sync=true`` + 时),``files.info``\ (目前本连接器的爬取流程不会调用此接口) -- Tier 3方法: 50+请求/分钟 -- Tier 4方法: 100+请求/分钟 +.. note:: + + Slack于2025年5月29日实施的速率限制强化措施(将 ``conversations.history`` 和 + ``conversations.replies`` 两个方法限制为50+请求/分钟)仅适用于分发到创建该应用的工作区 + 之外的应用,例如通过Slack Marketplace分发的应用。它不适用于为 |Fess| 创建、仅安装在 + 创建该应用的工作区内的内部应用。 有大量消息的情况 --------------------------- +---------------- **症状**: 爬取耗时长或超时 @@ -450,13 +657,12 @@ Slack API限制: 1. 分割频道设置多个数据存储 2. 分散爬取计划 -3. 考虑设置排除旧消息 脚本应用示例 -======================== +============ 消息加工 ----------------- +-------- 长消息的摘要: @@ -483,5 +689,7 @@ Slack API限制: - :doc:`ds-overview` - 数据存储连接器概述 - :doc:`ds-atlassian` - Atlassian连接器 - :doc:`../../admin/dataconfig-guide` - 数据存储配置指南 +- :doc:`../security-role` - 基于角色的搜索配置指南 - `Slack API Documentation `_ - `Slack Bot Token Scopes `_ +- `Slack API Rate Limits `_