はじめに
本記事はApache PolarisのManagement REST APIの使い方をまとめてみたものになります。
詳細な内容や最新の情報は公式のドキュメント等を参考しにしてください。
公式のドキュメントのリンクはこちらです。
https://editor.swagger.io/?url=https://raw.githubusercontent.com/apache/polaris/refs/heads/main/spec/polaris-management-service.yml
同じだと思いますが、GitHubのspec/polaris-management-service.ymlも参照してみるといいかもしれません。
https://github.com/apache/polaris/blob/main/spec/polaris-management-service.yml
Polaris Role-Base Access Contorolについて
Polarisは権限の管理としてRole-Base Access Contorol(RBAC)の仕組みを持っています。これがどんなものかは、公式のページを確認してください。
RBACを実現するために以下のような要素があります。
- principal
- principal-role
- catalog-role
これらを管理(確認、追加、削除)するための機能がPolaris Management REST APIです。
環境構築
APIを試すために、環境を用意する必要があります。今回はDocker上にCeph+Polarisを構成してみようと思います。Cephは私が以前書いた記事をそのまま使います。
上記に追加してPolaris用のコンテナを追記します。
# ~~~~~~~~~~~ceph用コード~~~~~~~~~~~
polaris:
image: apache/polaris:1.3.0-incubating
ports:
# API port
- "8181:8181"
depends_on:
rgw1:
condition: service_started
environment:
AWS_REGION: ${S3_REGION}
AWS_ACCESS_KEY_ID: ${RGW_ACCESS_KEY}
AWS_SECRET_ACCESS_KEY: ${RGW_SECRET_KEY}
POLARIS_BOOTSTRAP_CREDENTIALS: POLARIS,root,s3cr3t
polaris.realm-context.realms: POLARIS
quarkus.otel.sdk.disabled: "true"
healthcheck:
test: ["CMD", "curl", "--fail", "http://localhost:8182/q/health"]
interval: 2s
timeout: 10s
retries: 10
start_period: 10s
networks:
ceph_network:
APIはホストPCからたたくので、8181をバインドしておきます。
APIを使ってみる
Oauth2
PolarisのAPI(Management API, Catalog API)は、たたく前にどのユーザーで操作するか認証する必要があり、認証の結果TOKENが渡されます。
そのTOKENをAPIをたたくとき、ヘッダーにくっつける必要があります。
Polarisコンテナの環境変数にPOLARIS_BOOTSTRAP_CREDENTIALSがあります。立ち上げ用の権限なので、まずはこれを使用して認証してみます。
curl http://localhost:8181/api/catalog/v1/oauth/tokens \
--user root:s3cr3t \
-H "Polaris-Realm: POLARIS" \
-d grant_type=client_credentials \
-d scope=PRINCIPAL_ROLE:ALL
こんなのが返ってきます。
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJwb2xhcmlzIiwic3ViIjoicm9vdCIsImlhdCI6MTc3MDI5MDA0OCwiZXhwIjoxNzcwMjkzNjQ4LCJqdGkiOiI5Y2ZmOTM4MS03NDU1LTQyNWEtODU1NS0zOTMwM2Q0YjY4NTkiLCJhY3RpdmUiOnRydWUsImNsaWVudF9pZCI6InJvb3QiLCJwcmluY2lwYWxJZCI6MSwic2NvcGUiOiJQUklOQ0lQQUxfUk9MRTpBTEwifQ.Q9yNcVcJHxSjfGjWpd3vK8Z2ugSrrNl2cvAExMzkGF4d0GycYCJomJm0YQoYP1tJrhnYC2Lvtpr6cxmgjNp_0ZrdSIyStRoKC-rcvPoTH1i2c2OFhjHDHL_zgZrFqSa8KBPSaCKqs82UaQqulfPce0QLzWickrHiXKPfzc5uT0pQzzYDU8bMlEn_3FgRF0WV8hinVqwMMkzwiryZIftBN-Su1Xn25h0ndgAAgGL7cXgYfGfUXGcqlb6zpRrG9VHCBpEY-lxyVYw5Tz29Lxcnq8Y_pB9somLpYpXHndAJFOe4kyBzatq9ZxoTLNjx-9Z9vA8Qg71y9jp9ohYqXSoO6Q",
"token_type": "bearer",
"issued_token_type": "urn:ietf:params:oauth:token-type:access_token",
"expires_in": 3600
}
これのaccess_tokenを今後ヘッダーへ埋め込むことになります。使いまわしやすいように変数にしておくと便利です。この記事ではTOKEN変数に入れるものとします。expires_in: 3600とあるように1時間だけ有効です。
Catalog
まずはCatalogの作成をします。Cephを利用するのでS3ストレージとして作成します。
リクエストボディが長いのでいったん変数に入れます。
body='{
"catalog": {
"name": "catalog_hoge",
"type": "INTERNAL",
"readOnly": false,
"properties": {
"default-base-location": "s3://bucket_hoge"
},
"storageConfigInfo": {
"storageType":"S3",
"allowedLocations": ["s3://bucket_hoge"],
"endpoint":"http://rgw1:7480",
"endpointInternal":"http://rgw1:7480",
"stsUnavailable": true,
"kmsUnavailable": true,
"pathStyleAccess": true
}
}
}'
curl http://localhost:8181/api/management/v1/catalogs \
-H "Authorization: Bearer $TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "Polaris-Realm: POLARIS" \
-d "$body"
作成済みのcatalog一覧はGETリクエストで取れます。
curl http://localhost:8181/api/management/v1/catalogs \
-H "Authorization: Bearer $TOKEN"
こんなのが返ってくるはずです。作ったカタログがあるみたいですね。
{
"catalogs": [
{
"type": "INTERNAL",
"name": "catalog_hoge",
"properties": {
"default-base-location": "s3://bucket_hoge"
},
"createTimestamp": 1770301900106,
"lastUpdateTimestamp": 1770301900106,
"entityVersion": 1,
"storageConfigInfo": {
"endpoint": "http://rgw1:7480",
"stsUnavailable": true,
"endpointInternal": "http://rgw1:7480",
"pathStyleAccess": true,
"storageType": "S3",
"allowedLocations": [
"s3://bucket_hoge"
]
}
}
]
}
Catalog-role
作ったカタログcatalog_hogeにcatalog-roleを新規作成してみましょう。今回は書き込むロールってことで名前はwriterとします。
curl http://localhost:8181/api/management/v1/catalogs/catalog_hoge/catalog-roles \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"catalogRole": {"name": "writer"}}'
こちらもGETリクエストでcatalogに存在するcatalog-role一覧が確認できます。
curl http://localhost:8181/api/management/v1/catalogs/catalog_hoge/catalog-roles \
-H "Authorization: Bearer $TOKEN"
こんなのが返ってきます。
{
"roles": [
{
"name": "catalog_admin",
"properties": {},
"createTimestamp": 1770301900124,
"lastUpdateTimestamp": 1770301900124,
"entityVersion": 1
},
{
"name": "writer",
"properties": {},
"createTimestamp": 1770302363339,
"lastUpdateTimestamp": 1770302363339,
"entityVersion": 1
}
]
}
カタログ作成時に自動でできるcatalog_adminと、今回作成したwriterがあることを確認できます。
catalog-role grants
作成したcatalog-roleがどんな権限をもっているか、確認するAPIになります。
catalog_adminがどんな権限をもっているか確認してみます。
curl http://localhost:8181/api/management/v1/catalogs/catalog_hoge/catalog-roles/catalog_admin/grants \
-H "Authorization: Bearer $TOKEN"
こんなのが返ってきました。
{
"grants": [
{
"privilege": "CATALOG_MANAGE_ACCESS",
"type": "catalog"
},
{
"privilege": "CATALOG_MANAGE_METADATA",
"type": "catalog"
}
]
}
これがどんな権限かはPolaris公式のAccess Controlのページを見ればわかります。
https://polaris.apache.org/releases/1.3.0/managing-security/access-control/
以下の権限を持っているみたいです。
CATALOG_MANAGE_ACCESS
Includes the ability to grant or revoke privileges on objects in a catalog to catalog roles, and the ability to grant or revoke catalog roles to or from principal roles.
CATALOG_MANAGE_METADATA
Enables full management of the catalog, catalog roles, namespaces, and tables.
では、今回新しく作ったwriterロールはどんな権限をもっているのでしょう。
curl http://localhost:8181/api/management/v1/catalogs/catalog_hoge/catalog-roles/writer/grants \
-H "Authorization: Bearer $TOKEN"
# output
{
"grants": []
}
何も持っていませんでした。
書き込み権限っぽいTABLE_WRITE_DATAを付与してみます。API仕様書を見ると、付与はPUTメソッドでPOSTメソッドは権限の削除です。
curl -X PUT http://localhost:8181/api/management/v1/catalogs/catalog_hoge/catalog-roles/writer/grants \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"type":"catalog", "privilege":"TABLE_WRITE_DATA"}'
再度確認のコマンドを送信してみると、権限が追加されていることがわかりました。
{
"grants": [
{
"privilege": "TABLE_WRITE_DATA",
"type": "catalog"
}
]
}
principal-role
ここからはprincipal関連のAPIを見ていきます。principalとは厳密には違いますがユーザーと読み替えていいと思います。つまり、principal-roleはユーザーロール(例:データサイエンティスト、データエンジニア)の管理となります。
catalog-roleは各カタログに対して作りましたが、principal-roleはcatalogに依存せず作ることとなります。
適切な単語じゃない気がしますが、data_entryというroleを作ってみます。
curl http://localhost:8181/api/management/v1/principal-roles \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"principalRole": {"name": "data_entry"}}'
作成したprincipal-roleにcatalog-roleを割り当てます。
curl -X PUT http://localhost:8181/api/management/v1/principal-roles/data_entry/catalog-roles/catalog_hoge \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"catalogRole": {"name": "writer"}}'
principal-roleがもっているcatalog-roleを確認します。
curl http://localhost:8181/api/management/v1/principal-roles/data_entry/catalog-roles/catalog_hoge \
-H "Authorization: Bearer $TOKEN"
こんなのが返ってきました。
{
"roles": [
{
"name": "writer",
"properties": {},
"createTimestamp": 1770448642341,
"lastUpdateTimestamp": 1770448642341,
"entityVersion": 1
}
]
}
principal
最後に、principalの作成をしてみます。名前はuser_fooとしてみます。
curl http://localhost:8181/api/management/v1/principals \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"principal": {"name": "user_foo"}}'
こんなレスポンスが返ってきたと思います。
この中のcredentialsの内容は再度確認できないので、どこかに控えておきましょう。user_fooとしてPolaris REST APIを扱いたいとき、この情報でOauth2を行ってTOKENを取得する必要があります。
{
"principal": {
"name": "user_foo",
"clientId": "6ed730f35c87fa2a",
"properties": {},
"createTimestamp": 1770449620129,
"lastUpdateTimestamp": 0,
"entityVersion": 1
},
"credentials": {
"clientId": "6ed730f35c87fa2a",
"clientSecret": "99c811836a807a85f67c0ef0da4b765a"
}
}
作成したprincipalにprincipal-roleを付与することができます。
curl -X PUT http://localhost:8181/api/management/v1/principals/user_foo/principal-roles \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"principalRole": {"name": "data_entry"}}'
user_fooがどんなroleを持っているか確認してみます。
curl http://localhost:8181/api/management/v1/principals/user_foo/principal-roles \
-H "Authorization: Bearer $TOKEN"
こんなのが返ってきました。
{
"roles": [
{
"name": "data_entry",
"federated": false,
"properties": {},
"createTimestamp": 1770448912216,
"lastUpdateTimestamp": 1770448912216,
"entityVersion": 1
}
]
}
追加の権限を付与したい場合の案
現在の状況をまとめると、
- principal
user_fooは - principal-role
data_entryを保持しており、このroleは - catalog-role
writerを保持しており、このroleは - catalog
catalog_hogeへの権限TABLE_WRITE_DATAを持っている
ので、user_fooはcatalog_hogeへデータを挿入することができます。
ここに追加して、新しいテーブルの作成の権限も追加していなと思ったとき、以下のような対応が思い浮かびます。
-
TABLE_CREATE権限をcatalog-rolewriterへ追加する -
TABLE_CREATE権限を持つ新しいcatalog-rolecreaterを作成し、principal-roledata_entryにcreaterも持たせる -
TABLE_CREATE権限を持つ新しいcatalog-rolecreaterを作成し、このroleを持つ新しいprincipal-roledata_warehouseを作成し、このroleをprincipaluser_foo
どれでも結果的には同じですが、ロールの命名や複数ユーザーでアクセスするときの管理を考えるとRBACの利点が見えてくるのかなと思います。
終わりに
すべてのAPIを紹介しきれていませんが、簡単にPolaris Management APIの紹介ができたかなと思います。
見返すとテストでつけた命名について、あまりよくない気がしています、すいません。
また、記事中の内容に誤り等ありましたら訂正のコメントを頂けますと幸いです。