このウォークスルーでは、永続的な Docker ボリュームを備えたシングルノードレプリカセットとして MongoDB 7.0.16 を使用します。PMS はポリシーを書き込み、ADS はチェンジストリームを介して同じデータベースを追跡します。サンプルでは、ローカル開発用に認証なしでループバックでリッスンします。本番環境の認証、TLS、およびレプリカセットの構成はウォークスルーの後に説明します。
MongoDB はレプリカセットまたはシャーディングされたクラスターとして実行する必要があります。ADS はチェンジストリームでデータベースを監視し、ポリシーストア全体の置換はトランザクション内で実行されます。スタンドアロンの mongod ではどちらもサポートされていません。開発用にはシングルノードのレプリカセットで十分です。
1. Speedle のビルド
Bash、Git、curl、Docker、および Go 1.26.10 または Go 1.27.3 を準備します。Docker を起動し、ネイティブサービスをビルドします:
git clone --depth 1 https://github.com/teramoby/speedle-plus.git
cd speedle-plus
mkdir -p bin
go build -o ./bin/ ./cmd/spctl ./cmd/speedle-pms ./cmd/speedle-ads後続のコマンドはこのチェックアウトから実行します。ローカルポート 27017、6733、6734 を利用可能にしておくか、コマンドと構成を同時に更新してください。
2. MongoDB の起動
名前付きボリュームが MongoDB のデータを保持します。--replSet は speedle-rs レプリカセットのメンバーとして mongod を起動します。ループバック上のデータベースポートのみが公開されます。
docker run --name speedle-mongodb --detach \
--publish 127.0.0.1:27017:27017 \
--volume speedle-mongodb-data:/data/db \
mongo:7.0.16 \
--replSet speedle-rs --bind_ip_allサーバーがコマンドを受け付けるのを待ちます:
until docker exec speedle-mongodb mongosh --quiet \
--eval 'db.adminCommand({ping: 1}).ok' >/dev/null 2>&1
do
sleep 1
doneすでに MongoDB レプリカセットを実行している場合は、コンテナコマンドとステップ 3 をスキップし、以下の接続文字列を使用してください。コンテナの詳細については 公式 Docker イメージ を参照してください。
3. レプリカセットの初期化
このサーバーを唯一のメンバーとしてレプリカセットを 1 回初期化し、プライマリになるまで待ちます:
docker exec speedle-mongodb mongosh --quiet --eval \
'rs.initiate({_id: "speedle-rs", members: [{_id: 0, host: "127.0.0.1:27017"}]})'
until docker exec speedle-mongodb mongosh --quiet \
--eval 'db.hello().isWritablePrimary' | grep -qx true
do
sleep 1
doneメンバーアドレス 127.0.0.1:27017 はクライアントに接続先として通知されるものであるため、PMS および ADS から到達可能である必要があります。ここではポートが同じループバックアドレスで公開されているため機能します。構成はボリュームに保存されます。再起動後に rs.initiate を再度実行しないでください。
4. 共有ストアの構成
このローカルの PMS/ADS ペア用の設定ファイルを 1 つ作成します:
mkdir -p mongodb-demo
cat > mongodb-demo/config.json <<'JSON'
{
"storeConfig": {
"storeType": "mongodb",
"storeProps": {
"MongoURI": "mongodb://127.0.0.1:27017/?replicaSet=speedle-rs",
"MongoDatabase": "speedle_demo"
}
},
"enableWatch": true
}
JSONPMS と ADS は同じデプロイメントとデータベースを使用する必要があります。独立したポリシーストアごとに個別のデータベースを使用します。ストアはサービスと関数を services および functions コレクションに保持します。MongoDB は最初の書き込み時にデータベースとコレクションを作成するため、スキーマの初期化は不要です。enableWatch: true はチェンジストリームを介した ADS の更新を有効にします。ポーリング間隔は構成されません。
5. PMS の起動
ターミナル A で PMS を起動し、実行したままにします:
./bin/speedle-pms --config-file mongodb-demo/config.json --endpoint 127.0.0.1:6733 --insecure=trueREST リスナーが起動するのを待ちます。このデモでは平文の HTTP がループバックにバインドされています。Speedle 独自の TLS および API 認可については セキュリティ を参照してください。
6. ポリシーの作成
ターミナル B で、同じチェックアウトから、Alice に book の読み取り権限を付与します:
curl -fsS -X POST http://127.0.0.1:6733/policy-mgmt/v1/service \
-H 'Content-Type: application/json' \
-d '{"name":"mongodb-demo","type":"application","policies":[{"name":"alice-read","effect":"grant","principals":[["user:alice"]],"permissions":[{"resource":"book","actions":["read"]}]}]}'PMS はサービスと生成されたポリシー ID を返します。ポリシーは MongoDB に保存されました。
7. ADS の起動と認可の確認
ターミナル C で、同じファイルを使用して ADS を起動し、実行したままにします:
./bin/speedle-ads --config-file mongodb-demo/config.json --endpoint 127.0.0.1:6734 --insecure=true起動を待ってから、ターミナル B で以下のチェックを実行します。Alice は許可されます:
curl -fsS -X POST http://127.0.0.1:6734/authz-check/v1/is-allowed \
-H 'Content-Type: application/json' \
-d '{"subject":{"principals":[{"type":"user","name":"alice"}]},"serviceName":"mongodb-demo","resource":"book","action":"read"}'期待値: {"allowed":true,"reason":0}。Bob には一致するグラントがありません:
curl -fsS -X POST http://127.0.0.1:6734/authz-check/v1/is-allowed \
-H 'Content-Type: application/json' \
-d '{"subject":{"principals":[{"type":"user","name":"bob"}]},"serviceName":"mongodb-demo","resource":"book","action":"read"}'期待値: {"allowed":false,"reason":3}。
8. 保存されたドキュメントと自動更新の検証
サービスドキュメントを検査します。サービス名は _id です:
docker exec speedle-mongodb mongosh speedle_demo --quiet --eval \
'db.services.find({}, {"policies.name": 1, "policies.effect": 1}).toArray()'出力には alice-read グラントを含む _id: 'mongodb-demo' が含まれます。ドキュメントはバックエンドが管理するデータとして扱い、ポリシーの変更は PMS を通じて行ってください。
ADS を実行したまま、拒否(deny)を追加します:
curl -fsS -X POST http://127.0.0.1:6733/policy-mgmt/v1/service/mongodb-demo/policy \
-H 'Content-Type: application/json' \
-d '{"name":"alice-deny","effect":"deny","principals":[["user:alice"]],"permissions":[{"resource":"book","actions":["read"]}]}'ステップ 7 の Alice のリクエストを繰り返します。非同期のチェンジストリーム更新後、{"allowed":false,"reason":1} が返されるはずです。同期がまだ進行中の場合はリクエストを再試行してください。この通常のポリシー更新のために ADS を再起動する必要はありません。
9. バックアップの保存と永続化の確認
ポリシーデータベースをアーカイブにダンプし、コンテナの外部にコピーします:
docker exec speedle-mongodb mongodump --quiet \
--db speedle_demo --archive=/tmp/speedle-demo.archive
docker cp speedle-mongodb:/tmp/speedle-demo.archive ./mongodb-demo/speedle-demo.archiveアーカイブには speedle_demo データベースのみが含まれます。バックアップは独立した保護されたストレージに保存してください。リストアするには、ポリシーライターを停止し、プライマリに対して mongorestore --drop --archive=... を実行します。MongoDB ツールを使用したバックアップとリストア を参照してください。
この再起動チェックの前に、PMS と ADS を Ctrl+C で停止します:
docker restart speedle-mongodbステップ 2 と 3 の両方の待機ループを実行し(rs.initiate はスキップ)、同じ構成で PMS と ADS を再起動して、Alice のリクエストを再度実行します。引き続き {"allowed":false,"reason":1} が返されるはずです。名前付きボリュームは、コンテナの再起動後もデータとレプリカセットの構成を保持します。
リストア後は、決定を提供する前にリストアされたストアを読み込むように ADS を再起動してください。リカバリ後に認可を再確認してください。以前実行されていたキャッシュは、復元されたポリシーセットを含んでいることの証明にはなりません。
本番環境: 認証、TLS、およびレプリカセット
アクセス制御を有効にし、PMS と ADS に別個のユーザーを付与して、TLS 経由で接続します。PMS にはポリシーデータベースに対する readWrite 権限が必要です。ADS は読み取りと監視のみを行うため、組み込みの read ロールで十分であり、そのユーザーはポリシーを変更できません:
use speedle
db.createUser({user: "speedle-pms", pwd: passwordPrompt(), roles: [{role: "readWrite", db: "speedle"}]})
db.createUser({user: "speedle-ads", pwd: passwordPrompt(), roles: [{role: "read", db: "speedle"}]})
次に、各サービスに独自の接続文字列を指定します:
{
"storeConfig": {
"storeType": "mongodb",
"storeProps": {
"MongoURI": "mongodb://speedle-ads:replace-me@mongo1.example.com:27017,mongo2.example.com:27017,mongo3.example.com:27017/?replicaSet=speedle-rs&authSource=speedle&tls=true&tlsCAFile=/etc/speedle/mongodb/ca.pem",
"MongoDatabase": "speedle"
}
},
"enableWatch": true
}CA パスは PMS/ADS マシン上に存在します。URI 内の認証情報はパーセントエンコードする必要があり、それらを含む設定ファイルはサービスアカウントのみが読み取り可能である必要があります。代わりに SPDL_MONGOSTORE_URI 経由で URI を指定することもできます。MongoDB 接続文字列 のすべてのオプション(クライアント証明書 tlsCertificateKeyFile やその他の認証メカニズムを含む)は変更されずに Go ドライバーに渡されます。MongoDB への TLS は、Speedle の REST/gRPC リスナー上の TLS とは個別に構成されます。
レプリカセットのアクセス制御には、キーファイルまたは X.509 証明書を使用したメンバー間の認証も必要です。キーファイルアクセス制御を使用したセルフマネージドレプリカセットのデプロイ および TLS の構成 に関する公式ガイドを参照してください。
高可用性を確保するには、少なくとも 3 つのデータ保持メンバーを使用し、接続文字列に複数のメンバーをリストします。シングルノードのデモは、唯一のメンバーの喪失に耐えることができません。新しいプライマリが選出されている間、PMS 経由の書き込みが失敗する可能性があります。選出後に再試行してください。
構成リファレンスとトラブルシューティング
| プロパティ | フラグ | 環境変数 | デフォルト |
|---|---|---|---|
MongoURI |
--mongostore_uri |
SPDL_MONGOSTORE_URI |
mongodb://localhost:27017 |
MongoDatabase |
--mongostore_database |
SPDL_MONGOSTORE_DATABASE |
speedleplus |
明示的なフラグは空でない環境変数をオーバーライドし、次に設定ファイル、最後にデフォルト値の順で優先されます。バックエンドを選択するには --store-type mongodb または SPDL_STORE_TYPE=mongodb を使用します。組み込み用途の場合、pkg/store/mongodb をインポートし、これらのプロパティを store.NewStore に渡します。
ストア運用時に知っておくべき動作:
- ストア全体の置換(
WritePolicyStore)は 1 つのトランザクションで実行されます。指定されたポリシー ID を保持し、欠落している ID を生成します。スタンドアロンサーバーでは、既存のデータを変更することなく失敗します。 - すべてのサービスまたは関数を削除してもコレクションは保持されるため、チェンジストリームは開いたままとなり、ADS はキャッシュされたエントリを削除します。
- ストア全体の読み取りでは、レプリカセットまたはシャーディングされたクラスター上で 1 つのスナップショットとしてサービスと関数が読み取られます。
- チェンジストリームが終了した場合、ADS は最大 30 秒のバックオフで再オープンし、ストア全体を再読み込みするため、その間に行われた変更は失われません。それまでは最後に読み込まれたポリシーを引き続き提供します。
- 検出リクエストの収集とポリシー生成はサポートされていません。これらはファイルストアおよび etcd ストアで利用可能です。
| 症状 | 確認事項 |
|---|---|
| 起動時のサーバー選択タイムアウト | レプリカセットが初期化されプライマリであるか、rs.conf() 内のメンバーホストが PMS/ADS から到達可能か、URI ホストとポート、ファイアウォール。 |
ADS が The $changeStream stage is only supported on replica sets で終了する |
デプロイメントがスタンドアロンの mongod です。レプリカセットまたはシャーディングされたクラスターを使用してください。 |
| PMS は書き込むが ADS にサービスがない | 両方の構成で同じ URI デプロイメントおよび MongoDatabase 名であるか。 |
| 変更が ADS に届かない | watch が有効か。ADS ログにチェンジストリームおよび再オープンエラーがないか(ADS がデータベースに再到達するまで繰り返されます)。 |
| 認証失敗(Authentication failed) | ユーザー名、パスワードのエンコーディング、authSource、ポリシーデータベース上のロール。 |
| TLS エラー | tls=true、CA ファイルパス、証明書のホスト名。 |
バックエンドインターフェースと構成の優先順位については、プラグイン可能なストレージ に戻って参照してください。
ストアの障害は、すべての組み込みストアと同じポリシーに従います。ADS は利用不能を検出した後にデフォルトでエラー付きの拒否を行い、実行を継続して再試行し、完全な再読み込みが成功した後に再開します。オプションの有限の猶予期間および失効遅延については、ストア障害とキャッシュされた認可 を参照してください。