名前空間を使用したマルチテナンシーの実装

Namespaces API では、パッケージを使用して各テナントに対する名前空間文字列を選択するだけで、アプリケーションでマルチテナンシーを簡単に有効にできます。

現在の名前空間の設定

名前空間は取得、設定、検証できます。名前空間マネージャーを使用すると、名前空間に対応した API 用として現在の名前空間を設定できます。現在の名前空間を事前に設定すると、データストアと memcache では自動的にその名前空間が使用されます。

ほとんどの App Engine デベロッパーは、Google Workspace(旧 G Suite)ドメインを現在の名前空間として使用します。Google Workspace では、所有している任意のドメインにアプリをデプロイできるため、この仕組みを使用してドメインごとに異なる名前空間を簡単に構成できます。その後で、それらの個別の名前空間を使用して、データをドメイン間で分離できます。詳細については、カスタム ドメインのマッピングをご覧ください。

次のコードサンプルは、URL のマッピングに使用した Google Workspace ドメインを現在の名前空間として設定する方法を示しています。同じ Google Workspace ドメインでマッピングされるすべての URL に対して同じ文字列が使用されることに注意してください。

namespace の値を指定しない場合、名前空間が空の文字列に設定されます。namespace には任意の文字列を指定できますが、文字数は 100 文字までに制限されます。また、使用できる文字は英数字、ピリオド、アンダースコア、ハイフンだけです。より明示的に設定するには、名前空間文字列は正規表現 [0-9A-Za-z._-]{0,100} と同じ形式で設定する必要があります。

慣例として、「_」(アンダースコア)で始まるすべての名前空間はシステムで使用するために予約されています。システムの名前空間に関するこのルールは強制的なものではありませんが、従わないと予期しないマイナスの結果を引き起こす可能性があります。

データ漏洩の防止

マルチテナント アプリに関連する一般的なリスクの 1 つに名前空間でのデータ漏洩があります。次のようなさまざまな状況で、意図しないデータ漏洩が発生する可能性があります。

  • 名前空間をまだサポートしていない App Engine API で名前空間を使用した場合。たとえば、Blobstore では名前空間がサポートされていません。Blobstore で名前空間を使用する場合は、エンドユーザーのリクエストに対して Blobstore クエリを使用しないようにするか、信頼できないソースから取得した Blobstore キーを使用しないようにする必要があります。
  • URL Fetch やその他のメカニズムで、名前空間の区分化スキームを指定せずに外部ストレージ メディアを使用した場合(Memcache とデータストアは使用しない)。
  • ユーザーのメールドメインに基づいて名前空間を設定した場合。ほとんどの場合、特定のドメインのすべてのメールアドレスが特定の名前空間にアクセスするのは適切ではありません。また、メールドメインを使用すると、ユーザーがログインするまでアプリケーションで名前空間を使用できません。

名前空間のデプロイ

以降のセクションでは、その他の App Engine ツールや API を使用して名前空間をデプロイする方法について説明します。

ユーザー単位での名前空間の作成

一部のアプリケーションでは、名前空間をユーザー単位で作成する必要があります。ログインしているユーザーのユーザーレベルでデータを区分けする場合は、ユーザーを一意に識別する永続的な ID を返す user.Current(c).ID の使用を検討してください。次のコードサンプルは、この目的のために Users API を使用する方法を示したものです。

通常、名前空間をユーザー単位で作成するアプリでは、ユーザーごとに固有のランディング ページも用意します。その場合は、ユーザーに表示するランディング ページを決定する URL スキームをアプリケーションで指定する必要があります。

データストアでの名前空間の使用

デフォルトでは、データストアのリクエストには現在の名前空間が使用されます。datastore.Key オブジェクトの作成時には、API により現在の名前空間がこのオブジェクトに適用されます。したがって、アプリケーションで Key オブジェクトをシリアル化された形式で格納する場合は、それらのシリアル化で名前空間が保持されるので、注意が必要です。

シリアル化解除された Key オブジェクトを使用している場合は、意図したとおりに動作することを確認します。他のストレージ メカニズムを使用せずにデータストアを使用するシンプルなアプリケーション(put / query / get)の多くは、データストア API を呼び出す前に現在の名前空間を設定すれば、想定どおりに動作します。

QueryKey オブジェクトは、名前空間に関して次のような独特の動作をします。

  • Query オブジェクトと Key オブジェクトは、明示的な名前空間を設定しない限り、現在の名前空間を継承します。
  • アプリケーションが新しい Key を祖先から作成すると、新しい Key は祖先の名前空間を継承します。

Memcache での名前空間の使用

デフォルトで、Memcache のリクエストには名前空間マネージャーで設定された現在の名前空間が使用されます。ほとんどの場合、Memcache で名前空間を明示的に設定する必要はなく、設定すると予期しないバグの原因になることもあります。

ただし、特定のまれな状況では、Memcache で名前空間を明示的に設定した方がよい場合もあります。たとえば、すべての名前空間で共有される共通のデータ(国コードが格納されたテーブルなど)をアプリケーションで使用する場合などです。

次のコード スニペットは、Memcache で名前空間を明示的に設定する方法を示したものです。

タスクキューでの名前空間の使用

デフォルトで、push キューはタスクの作成時に名前空間マネージャーで設定された現在の名前空間を使用します。ほとんどの場合、タスクキューで名前空間を明示的に設定する必要はなく、設定すると予期しないバグの原因になることもあります。

タスク名はすべての名前空間で共有されます。使用する名前空間が異なる場合でも、同じ名前のタスクを複数作成することはできません。同じタスク名を複数の名前空間で使用したい場合は、タスク名にそれぞれの名前空間を付加できます。

新しいタスクでタスクキュー メソッドを呼び出すと、現在の名前空間と Google Workspace ドメイン(該当する場合)が名前空間マネージャーからコピーされます。タスクの実行時に、現在の名前空間と Google Workspace の名前空間が復元されます。

すべての名前空間に関連するタスクの名前空間を明示的に設定した方がよいような、まれな状況もあります。たとえば、すべての名前空間の使用統計情報を集約するタスクを作成する場合が挙げられます。この場合は、タスクの名前空間を明示的に設定できます。次のコードサンプルは、タスクキューで名前空間を明示的に設定する方法を示したものです。

Blobstore での名前空間の使用

Blobstore は名前空間で分割されません。Blobstore で名前空間を保持するには、名前空間に対応したストレージ メディア(現在は Memcache、データストア、タスクキューのみ)から Blobstore にアクセスする必要があります。たとえば、blob の Key がデータストア エンティティに格納されている場合、名前空間に対応したデータストアの Key を使用してアクセスできます。

名前空間対応のストレージに格納されたキーを使用してアプリケーションから Blobstore にアクセスする場合、Blobstore 自体を名前空間で分割する必要はありません。名前空間での blob のデータ漏洩を防ぐために、次の点に注意してください。

  • エンドユーザー リクエストに BlobInfo を使用しないでください。管理者のリクエスト(アプリケーションのすべての blob に関するレポートの生成など)には BlobInfo クエリを使用してもかまいませんが、エンドユーザーのリクエストに使用すると、すべての BlobInfo レコードが名前空間で区分されないためデータ漏洩が発生する可能性があります。
  • 信頼できないソースから取得した Blobstore キーは使用しないでください。

データストア クエリの名前空間の設定

Google Cloud Console では、データストア クエリの名前空間を設定できます。

デフォルト以外の名前空間を使用する場合は、使用する名前空間をプルダウンから選択します。

一括ローダーでの名前空間の使用

一括ローダーは、使用する名前空間を指定できる --namespace=NAMESPACE フラグをサポートしています。それぞれの名前空間が別々に処理されるため、すべての名前空間にアクセスする場合は反復処理が必要になります。