Fess 15.4.0のリリース

Fess 15.4.0をリリースしました。いつもは、codelibs/fessのリポジトリで修正件数は10件いかないくらいだと思いますが、今回はこんな感じで、52件に達しました。大幅に増えた感じではありますが、量だけでなく、質も向上している気はしますが、多くのことをClaude Codeで対応したので、生産性が爆上がりみたいな感じになっています。Fessの開発は、関連する依存ライブラリも毎回修正しているので、実際には52件以上の修正が入っている感じではあります。

コードの修正だけでも結構あったなという感じではありますが、ドキュメントやリリース作業周りでも活用することでかなり楽になりました。ドキュメントに関しても、fess.codelibs.orgでは、7言語で提供しているので、これを手動で作業すると、リリースするのにも数日かかりそうな感じになってしまいますが、Claude Codeに前回リリース作業を理解してもらって、任せることで、待っていれば、そのうち修正が終わるみたいな楽に更新ができるようになりました。

そのほかにもリリースノートの文面も修正内容をまとめるのも数が増えると面倒になりますが、Claude Codeがghコマンドを活用することで、修正内容をピックアップして、いい感じの文面を作って、リリースノートのドラフトまで作成できるので、あとはリリース物をアップロードして、公開するだけになりました。

という感じで、今回のリリースは開発の大幅な効率化して、いろいろと修正してみたリリースになるので、利用してみてください。

Fessにリクエスト制限機能を追加

最近、Fessを公開していると、AIクローラーなどが激しくクロールしてきて、サーバーに負荷がかかることがあります。このような問題に対応するため、Fess 15.4でIPベースのリクエスト制限機能を追加しました。

リクエスト制限機能とは

この機能は、特定のIPアドレスからの短時間での大量リクエストを検出し、自動的にブロックすることでサーバーを保護します。デフォルトでは無効になっているので、必要に応じて有効にしてください。

主な特徴は以下の通りです。

  • IPアドレスごとにリクエスト数をカウント
  • 一定時間内に許可されたリクエスト数を超えると自動的にブロック
  • ブロックされたIPは一定時間後に自動解除
  • ホワイトリストで特定のIPを除外可能
  • ブラックリストで特定のIPを常時ブロック可能

設定方法

fess_config.propertiesに以下の設定を追加することで有効にできます。

# リクエスト制限を有効にする
rate.limit.enabled=true

# 1分間に許可するリクエスト数(デフォルト: 100)
rate.limit.requests.per.window=100

# 計測するウィンドウサイズ(ミリ秒、デフォルト: 60000 = 1分)
rate.limit.window.ms=60000

# 制限超過時のブロック時間(ミリ秒、デフォルト: 300000 = 5分)
rate.limit.block.duration.ms=300000

# Retry-Afterヘッダーの値(秒、デフォルト: 60)
rate.limit.retry.after.seconds=60

ホワイトリストとブラックリスト

特定のIPアドレスを制限から除外したり、常時ブロックしたりすることができます。

# 制限から除外するIPアドレス(カンマ区切り)
rate.limit.whitelist.ips=127.0.0.1,::1,192.168.1.100

# 常時ブロックするIPアドレス(カンマ区切り)
rate.limit.blocked.ips=203.0.113.50,198.51.100.25

リバースプロキシ環境での設定

NginxやApacheなどのリバースプロキシを使用している場合、クライアントの実際のIPアドレスを取得するために、信頼できるプロキシのIPアドレスを設定する必要があります。

# 信頼するプロキシのIPアドレス(カンマ区切り)
rate.limit.trusted.proxies=127.0.0.1,::1,10.0.0.1

この設定がない場合、すべてのリクエストがプロキシのIPアドレスとして認識されてしまい、正しく制限が機能しません。

制限超過時の動作

リクエスト制限を超えた場合、HTTPステータス429(Too Many Requests)が返されます。レスポンスにはRetry-Afterヘッダーが含まれ、何秒後に再試行できるかが示されます。

ブラックリストに登録されたIPからのアクセスの場合は、HTTPステータス403(Forbidden)が返されます。

注意事項

  • この機能はFess 15.4以降で利用可能です
  • デフォルトでは無効になっています
  • 設定値は環境に応じて適切に調整してください
  • ホワイトリストにはローカルホスト(127.0.0.1, ::1)がデフォルトで含まれています

FessのMicrosoft 365プラグインの権限設定ドキュメントを追加

Fess Microsoft 365プラグイン(fess-ds-microsoft365)を使う際に、Azure App登録でどの権限を設定すればいいのかがわかりにくかったので、READMEに詳しくまとめました。fess-ds-microsoft365のPR #32 の話です。

背景

Microsoft 365プラグインでは、OneDrive、OneNote、Teams、SharePointなど複数のDataStoreをサポートしていますが、それぞれで必要なMicrosoft Graph APIの権限が異なります。今までは必要な権限がすべて列挙されているだけだったので、どのDataStoreを使う場合にどの権限が必要なのかがわかりにくい状態でした。

最小権限の原則に従って、必要な権限だけを設定できるようにドキュメントを整備しました。

DataStoreごとの必要権限

各DataStoreで必要な権限を表にまとめました。

DataStore必須権限条件付き権限
OneDriveDataStoreFiles.Read.AllUser.Read.All (1), Group.Read.All (2), Sites.Read.All (*3)
OneNoteDataStoreNotes.Read.AllUser.Read.All (1), Group.Read.All (2), Sites.Read.All (*4)
TeamsDataStoreTeam.ReadBasic.All, Group.Read.All, Channel.ReadBasic.All, ChannelMessage.Read.All, ChannelMember.Read.All, User.Read.AllChat.Read.All (5), Files.Read.All (6)
SharePointDocLibDataStoreFiles.Read.All, Sites.Read.All (*7)
SharePointListDataStoreSites.Read.All (*7)
SharePointPageDataStoreSites.Read.All (*7)

条件付き権限の説明:
– (1) user_drive_crawler=true または user_note_crawler=true の場合(デフォルト: true)
– (
2) group_drive_crawler=true または group_note_crawler=true の場合(デフォルト: true)
– (3) shared_documents_drive_crawler=true の場合(デフォルト: true)
– (
4) site_note_crawler=true の場合(デフォルト: true)
– (5) chat_id を指定している場合
– (
6) append_attachment=true の場合
– (*7) site_id を指定している場合は Sites.Selected で代替可能

Sites.Selected権限について

site_id を指定してSharePoint系のDataStoreを使う場合、Sites.Read.All の代わりに Sites.Selected を使うことで、より制限されたアクセスが可能です。

  1. Azure PortalでアプリにSites.Selected権限を付与
  2. Microsoft Graph PowerShellまたはAPIで特定サイトへのアクセスを許可
  3. 各対象サイトへのアクセスを明示的に許可

参考: https://learn.microsoft.com/en-us/graph/permissions-reference#sitesselected

最小権限の設定例

OneDriveのみ(ユーザードライブ)の場合:

Files.Read.All, User.Read.All

SharePointリスト(特定サイト)の場合:

Sites.Selected(サイトごとの設定が必要)

Teams(チャンネルのみ、チャットなし)の場合:

Team.ReadBasic.All, Group.Read.All, Channel.ReadBasic.All, ChannelMessage.Read.All, ChannelMember.Read.All, User.Read.All

まとめ

これで、使用するDataStoreに応じて必要最小限の権限だけを設定できるようになりました。Azureの管理者に権限申請する際も、「このDataStoreを使うからこれだけの権限が必要」と説明しやすくなったと思います。