Closed3

ベクトルデータベース「Weaviate」を試す 12: 認証

kun432kun432

APIキーを使ったシンプルな認証の例。

以下でミニマムなdocker-compose.yamlを作成

https://weaviate.io/developers/weaviate/installation/docker-compose

docker-compose.yaml
---
version: '3.4'
services:
  weaviate:
    command:
    - --host
    - 0.0.0.0
    - --port
    - '8080'
    - --scheme
    - http
    image: cr.weaviate.io/semitechnologies/weaviate:1.24.10
    ports:
    - 8080:8080
    - 50051:50051
    volumes:
    - ./weaviate_data:/var/lib/weaviate
    restart: on-failure:0
    environment:
      QUERY_DEFAULTS_LIMIT: 25
      PERSISTENCE_DATA_PATH: '/var/lib/weaviate'
      DEFAULT_VECTORIZER_MODULE: 'text2vec-openai'
      ENABLE_MODULES: 'text2vec-openai'
      CLUSTER_HOSTNAME: 'node1'
      AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: 'true'

AUTHENTICATION_ANONYMOUS_ACCESS_ENABLEDtrueになっているので、制限なしでアクセスができる状態になっている。

まずはこの状態で起動してみる。

$ docker compose up -d

curlでクエリを送ってみる。

$ curl http://localhost:8080/v1/meta
{"hostname":"http://[::]:8080","modules":{"text2vec-openai":{"documentationHref":"https://platform.openai.com/docs/guides/embeddings/what-are-embeddings","name":"OpenAI Module"}},"version":"1.24.10"}

普通にレスポンスが返ってくる。

では制限を追加する。

docker-compose.yaml
    (snip)
    environment:
      (snip)
      # 以下は true -> falseに変更
      AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: 'false'
      # 以下を追加
      AUTHENTICATION_APIKEY_ENABLED: 'true'
      AUTHENTICATION_APIKEY_ALLOWED_KEYS: 'AAAAA,BBBBB'
      AUTHENTICATION_APIKEY_USERS: 'user-A,user-B'

内容はこういう感じ

  • AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: 'false'で制限なしアクセスを無効化して、AUTHENTICATION_APIKEY_ENABLEDでAPIキーでの認証を有効化する。
  • AUTHENTICATION_APIKEY_ALLOWED_KEYSにAPIキーを登録。複数のAPIキーを登録する場合はカンマ区切りで記載。
  • AUTHENTICATION_APIKEY_USERSは、AUTHENTICATION_APIKEY_ALLOWED_KEYSで登録したAPIキーとマッチするユーザ名を設定する。
    • これだけだとそれほど大きな意味がないかもしれないが、詳細は後述。

コンテナを上げ直して反映

$ docker compose down && docker compose up -d

再度リクエストを送ってみるが、AUTHENTICATION_ANONYMOUS_ACCESS_ENABLEDが無効なため、認証なしでは拒否される。

$ curl http://localhost:8080/v1/meta
{"code":401,"message":"anonymous access not enabled, please provide an auth scheme such as OIDC"}

ではAuthorizationヘッダーを付与して送ってみる。

$ curl http://localhost:8080/v1/meta -H 'Authorization: Bearer AAAAA'
{"hostname":"http://[::]:8080","modules":{"text2vec-openai":{"documentationHref":"https://platform.openai.com/docs/guides/embeddings/what-are-embeddings","name":"OpenAI Module"}},"version":"1.24.10"}
$ curl http://localhost:8080/v1/meta -H 'Authorization: Bearer BBBBB'
{"hostname":"http://[::]:8080","modules":{"text2vec-openai":{"documentationHref":"https://platform.openai.com/docs/guides/embeddings/what-are-embeddings","name":"OpenAI Module"}},"version":"1.24.10"}
$ curl http://localhost:8080/v1/meta -H 'Authorization: Bearer CCCCC'
{"code":401,"message":"invalid api key, please provide a valid api key"}

正しいAPIキーの場合にはリクエストが成功することがわかる。

Pythonクライアントからも確認しておく。Jupyter Labで。

!pip install -U weaviate-client python-dotenv
from dotenv import load_dotenv

load_dotenv(verbose=True)

APIキー設定なしだと・・・

import weaviate
import weaviate.classes as wvc
import os

client_a = weaviate.connect_to_local(
    headers={
        "X-OpenAI-Api-Key": os.environ['OPENAI_API_KEY'],
    }
)

エラーになる。

UnexpectedStatusCodeError: Meta endpoint! Unexpected status code: 401, with response body: {'code': 401, 'message': 'anonymous access not enabled, please provide an auth scheme such as OIDC'}.

APIキーを設定してクライアント初期化、コレクションの作成までやってみる。

import weaviate
import weaviate.classes as wvc
import os

client_a = weaviate.connect_to_local(
    auth_credentials=weaviate.auth.AuthApiKey('AAAAA'),
    headers={
        "X-OpenAI-Api-Key": os.environ['OPENAI_API_KEY'],
    }
)

client_b = weaviate.connect_to_local(
    auth_credentials=weaviate.auth.AuthApiKey('BBBBB'),
    headers={
        "X-OpenAI-Api-Key": os.environ['OPENAI_API_KEY'],
    }
)

collection_a = client_a.collections.create(
    name="collection_a",
    vectorizer_config=wvc.config.Configure.Vectorizer.text2vec_openai(),
)


collection_b = client_a.collections.create(
    name="collection_b",
    vectorizer_config=wvc.config.Configure.Vectorizer.text2vec_openai(),
)

client_a.collections.list_all()
{'Collection_a': _CollectionConfigSimple(name='Collection_a', description=None, generative_config=None, properties=[], references=[], reranker_config=None, vectorizer_config=_VectorizerConfig(vectorizer=<Vectorizers.TEXT2VEC_OPENAI: 'text2vec-openai'>, model={'baseURL': 'https://api.openai.com', 'model': 'ada'}, vectorize_collection_name=True), vectorizer=<Vectorizers.TEXT2VEC_OPENAI: 'text2vec-openai'>, vector_config=None),
 'Collection_b': _CollectionConfigSimple(name='Collection_b', description=None, generative_config=None, properties=[], references=[], reranker_config=None, vectorizer_config=_VectorizerConfig(vectorizer=<Vectorizers.TEXT2VEC_OPENAI: 'text2vec-openai'>, model={'baseURL': 'https://api.openai.com', 'model': 'ada'}, vectorize_collection_name=True), vectorizer=<Vectorizers.TEXT2VEC_OPENAI: 'text2vec-openai'>, vector_config=None)}
Selection deleted

どちらのAPIキーでも、接続およびコレクションの作成ができていることがわかる。

当然ながら間違ったAPIキーを指定した場合は接続できない。

import weaviate
import weaviate.classes as wvc
import os

client_c = weaviate.connect_to_local(
    auth_credentials=weaviate.auth.AuthApiKey('CCCCC'),
    headers={
        "X-OpenAI-Api-Key": os.environ['OPENAI_API_KEY'],
    }
)
UnexpectedStatusCodeError: Meta endpoint! Unexpected status code: 401, with response body: {'code': 401, 'message': 'invalid api key, please provide a valid api key'}.

このあとのために一旦コレクションは削除しておく。

client_a.collections.delete_all()
client_a.collections.list_all()
{}

さらにユーザごとに権限を付与することができる。docker-compose.yamlに以下を追加

docker-compose.yaml
    (snip)
    environment:
      (snip)
      AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: 'false'
      AUTHENTICATION_APIKEY_ENABLED: 'true'
      AUTHENTICATION_APIKEY_ALLOWED_KEYS: 'AAAAA,BBBBB'
      AUTHENTICATION_APIKEY_USERS: 'user-A,user-B'
      # 以下を追加
      AUTHORIZATION_ADMINLIST_ENABLED: 'true'
      AUTHORIZATION_ADMINLIST_USERS: 'user-A'
      AUTHORIZATION_ADMINLIST_READONLY_USERS: 'user-B'

設定内容は以下

  • AUTHORIZATION_ADMINLIST_ENABLED: 'true'でユーザごとの権限設定を有効化
  • AUTHORIZATION_ADMINLIST_USERS: 読み取り・書き込みの両方が可能なユーザを設定
    • ここではuser-Aを指定
  • AUTHORIZATION_ADMINLIST_READONLY_USERS: 読み取りのみ可能なユーザを設定
    • ここではuser-Bを指定

つまりここでユーザ名とAPIキーのマッチングの意味が出てくるということね。

コンテナを上げ直して反映

$ docker compose down && docker compose up -d

では先ほどと同じようにやってみる。まずuser-A

import weaviate
import weaviate.classes as wvc
import os

client_a = weaviate.connect_to_local(
    auth_credentials=weaviate.auth.AuthApiKey('AAAAA'),
    headers={
        "X-OpenAI-Api-Key": os.environ['OPENAI_API_KEY'],
    }
)

collection_a = client_a.collections.create(
    name="collection_a",
    vectorizer_config=wvc.config.Configure.Vectorizer.text2vec_openai(),
)


client_a.collections.list_all()

接続およびコレクションの作成ができた。

{'Collection_a': _CollectionConfigSimple(name='Collection_a', description=None, generative_config=None, properties=[], references=[], reranker_config=None, vectorizer_config=_VectorizerConfig(vectorizer=<Vectorizers.TEXT2VEC_OPENAI: 'text2vec-openai'>, model={'baseURL': 'https://api.openai.com', 'model': 'ada'}, vectorize_collection_name=True), vectorizer=<Vectorizers.TEXT2VEC_OPENAI: 'text2vec-openai'>, vector_config=None)}

次にuser-B

import weaviate
import weaviate.classes as wvc
import os

client_b = weaviate.connect_to_local(
    auth_credentials=weaviate.auth.AuthApiKey('BBBBB'),
    headers={
        "X-OpenAI-Api-Key": os.environ['OPENAI_API_KEY'],
    }
)

collection_b = client_b.collections.create(
    name="collection_b",
    vectorizer_config=wvc.config.Configure.Vectorizer.text2vec_openai(),
)

コレクションの作成、つまり書き込み権限がないため拒否されている。

UnexpectedStatusCodeError: Collection may not have been created properly.! Unexpected status code: 403, with response body: {'error': [{'message': "forbidden: user 'user-B' has insufficient permissions to create schema/objects"}]}.

ただし読み取り権限があるので以下は成功する。

client_b.collections.list_all()
{'Collection_a': _CollectionConfigSimple(name='Collection_a', description=None, generative_config=None, properties=[], references=[], reranker_config=None, vectorizer_config=_VectorizerConfig(vectorizer=<Vectorizers.TEXT2VEC_OPENAI: 'text2vec-openai'>, model={'baseURL': 'https://api.openai.com', 'model': 'ada'}, vectorize_collection_name=True), vectorizer=<Vectorizers.TEXT2VEC_OPENAI: 'text2vec-openai'>, vector_config=None)}
このスクラップは16日前にクローズされました