ベクトルデータベース「Weaviate」を試す 12: 認証
WCSの場合はAPIキーが払い出されるが、docker compose等それ以外のセットアップの場合の認証について、少し試しておく。
APIキーを使ったシンプルな認証の例。
以下でミニマムな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_ENABLED
がtrue
になっているので、制限なしでアクセスができる状態になっている。
まずはこの状態で起動してみる。
$ 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"}
普通にレスポンスが返ってくる。
では制限を追加する。
(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に以下を追加
(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)}
上記以外にOIDCを使った認証方法も用意されている。ユースケースに合わせて選択。