オンプレでデータレイクハウスのユーザを作って配る
今までのあらすじ
Apache Sparkでデータレイクハウスを作ってみました。
今回の目標
今回はオンプレデータレイクハウス(MinIO+PostgreSQL)を使ったときに、データのアクセス権を配る方法を編み出してみました。
ユーザを作る
材料
今回ユーザを作るには、以下のモジュールを使います。(Debianの場合)
- at
- pwgen
- expect
つまりこうします。
$ sudo apt install at pwgen expect
そして、MinIOの操作をするのにMinIO Clientをダウンロードしておく必要があります。
ここを参考にmc
をインストールしてください。
方針
方針としては以下の通りです。
- MinIOのユーザを作る
- MinIOのユーザにポリシーを与えてACCESS_KEYとSECRET_KEYを作る
- PostgreSQLユーザを作成する
- atコマンドでユーザを削除するスクリプトを登録する。
では一個ずつ解説してきます。
ユーザ作成ルーチンの作成
基本情報を作成する
基本情報は以下の通りで作っています。
# 頭文字がアルファベットでそれ以降31文字の計32文字のユーザ名を作成する。
USER_NAME=$(pwgen -1 -0 -B -A -s 1)$(pwgen -1 -B -A -n -s 31)
# パスワードは64文字。
USER_PASSWORD=$(pwgen -1 -B -c -n -s -y -r "\"\'\`!;&|" 64)
# 日時を取っておく。
DATE=$(date '+%Y%m%d-%H%M%S-%N')
# 作成したユーザを書き留めておくテキストファイルを作成する。(以後パスポートファイルと呼びます。)
PASSPORT_FILENAME="./userinfo/UserInfo-${DATE}-${USER_NAME}.txt"
# 消滅時間(分)を生成する。第一引数がなければ16とする。
DURATION=${1:-16}
MinIOとPostgreSQLのAdminアカウント情報を得る
MinIOとPostgreSQLのアカウント情報はあらかじめ環境変数で持っています。それを読んでいます。
. ../.env
情報をパスポートファイルに書き出す。
# 自サーバ名を書き込む
echo "export STORAGE_NAME='$(hostname -f)'" >> ${PASSPORT_FILENAME}
# PostgreSQLのポート番号を書き込む
echo "export POSTGRES_PORT='${POSTGRES_PORT}'" >> ${PASSPORT_FILENAME}
# PostgreSQLのデータベース名を書き込む
echo "export POSTGRES_DBNAME='${POSTGRES_DBNAME}'" >> ${PASSPORT_FILENAME}
# PostgreSQLのユーザ名を書き込む
echo "export POSTGRES_USERNAME='${USER_NAME}'" >> ${PASSPORT_FILENAME}
# PostgreSQLのユーザパスワードを書き込む
echo "export POSTGRES_PASSWORD='${USER_PASSWORD}'" >> ${PASSPORT_FILENAME}
# MinIOのCLIのポートを書き込む
echo "export MINIO_CLI_PORT='${MINIO_CLI_PORT}'" >> ${PASSPORT_FILENAME}
# MinIOのバケット名を書き込む
echo "export MINIO_BUCKET_NAME='${MINIO_BUCKET_NAME}'" >> ${PASSPORT_FILENAME}
MinIOのアカウントを作成する。
その1、テンポラリのAliasを作る
MinIOではCLIで動かすときにAliasを使用して色々します。ですのでアカウント追加用のAliasを作成します。
mc alias set MINIO_ADDUSER https://${DOMAIN_NAME}:${MINIO_CLI_PORT} ${MINIO_ROOT_USER} ${MINIO_ROOT_PASSWORD}
- DOMAIN_NAME:自サーバのFQDN
- MINIO_CLI_PORT:MinIOのCLIのポート番号
- MINIO_ROOT_USER:MinIOのAdmin名
- MINIO_ROOT_PASSWORD:MinIOのAdminパスワード
その2、ユーザを作成する
ユーザの作成をします。
mc admin user add MINIO_ADDUSER ${USER_NAME} ${USER_PASSWORD}
その3、MinIOのポリシーを与える
MinIOのユーザに readwrite
のポリシーを与えます。
mc admin policy attach MINIO_ADDUSER readwrite --user ${USER_NAME}
その4、MinIOのACCESS_KEYとSECRET_KEYを作成する
作成はJSONで与えるポリシーを作成します。
{
"Id": "Policy1747103409271",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1747103407593",
"Action": [
"s3:*"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::real-data-lakehouse/*",
"Principal": "*"
}
]
}
${DURATION}
の時間(分)でユーザに与えてJSONで作成したポリシーを与え、ACCESS_KEY
とSECRET_KEY
を取得します。その時の情報をsedで切り取り、パスポートファイルに書きます。
mc admin accesskey create MINIO_ADDUSER/ ${USER_NAME} --expiry-duration ${DURATION}m --policy ./json/getObject.json --description "" --name "${USER_NAME}" 2>&1 |sed -e "s/^Access Key: \(.*\)$/export MINIO_ACCESS_KEY='\1'/g" -e "s/^Secret Key: \(.*\)$/export MINIO_SECRET_KEY='\1'/g" -e '/^Expiration:/d' -e '/^Name:/d' -e '/^Description:/d'>> ${PASSPORT_FILENAME}
ここまでで情報は一通りできます。以下は情報の一例です。
$ cat UserInfo-20250802-183111-909782781-fq9d7ra733tjtt4chznr3vcanqpymyss.txt
export STORAGE_NAME='misumi.lan'
export POSTGRES_PORT='5432'
export POSTGRES_DBNAME='real-data-lakehouse-20250802'
export POSTGRES_USERNAME='fq9d7ra733tjtt4chznr3vcanqpymyss'
export POSTGRES_PASSWORD='<A:v,m(,H4x<@K3HPvRFgzL79]Pi3{*dAjg7t*z{b$M*pv<{-Xaw(Cj=MA~W3,}J'
export MINIO_CLI_PORT='9000'
export MINIO_BUCKET_NAME='real-data-lakehouse'
export MINIO_ACCESS_KEY='3VLUL0YO4L2S8MAGZOV4'
export MINIO_SECRET_KEY='B9ZJluEmj7FwkTPobK8eEu7wT4DGgRv6DQbIGvUl'
MinIOのテンポラリのAliasを削除する
mc alias remove MINIO_ADDUSER
PostgreSQLのユーザを作成する
PostgreSQLではexpectを使ってユーザを作ります。
./adduser.exp ${POSTGRES_USERNAME} ${POSTGRES_PASSWORD} ${USER_NAME} ${USER_PASSWORD}
このexpectファイルであるadduser.exp
を使ってユーザを作ります。
#!/usr/bin/expect
set POSTGRES_USERNAME [lindex $argv 0]
set PW [lindex $argv 1]
set USERNAME [lindex $argv 2]
set USERPWD [lindex $argv 3]
set timeout -1
spawn docker compose exec -u postgres -it rdlh-pgsql psql -h rdlh-pgsql -U ${POSTGRES_USERNAME} -W -c "CREATE USER ${USERNAME} WITH ENCRYPTED PASSWORD \'${USERPWD}\'" -c "GRANT SELECT,UPDATE,INSERT ON TABLE iceberg_tables,iceberg_namespace_properties TO ${USERNAME}"
expect {
-glob "Password:" {
send "${PW}\n"
exp_continue
}
}
ユーザの削除を予約する
さいごにMinIOとPostgreSQLユーザを削除することを予約しておきます。
# atコマンドで実行するためのスクリプトを作ります。
AT_COMMAND_FILENAME="/tmp/${DATE}-${USER_NAME}.sh"
cat < ./removeuser_header.sh > ${AT_COMMAND_FILENAME}
cat << EOF >> ${AT_COMMAND_FILENAME}
USER_NAME=${USER_NAME}
SCRIPT_DIR=${SCRIPT_DIR}
EOF
cat < ./removeuser_footer.sh >> ${AT_COMMAND_FILENAME}
# 実行権限をつけます。
chmod 755 ${AT_COMMAND_FILENAME}
# 最後ににatコマンドで${DURATION}分後に発行されるようにします。
at now+${DURATION}minutes -f ${AT_COMMAND_FILENAME}
このときのremoveuser_header.sh
とremoveuser_footer.sh
は以下の通りです。
#!/bin/bash
cd ${SCRIPT_DIR}
. ../.env
# MinIOで削除するユーザ用のテンポラリのAliasを作成します。
if ! mc alias set MINIO_REMOVEUSER https://${DOMAIN_NAME}:9000 ${MINIO_ROOT_USER} ${MINIO_ROOT_PASSWORD};then
echo "Alias set error!"
exit 254;
fi
# MinIOユーザを削除します
if ! mc admin user rm MINIO_REMOVEUSER ${USER_NAME}; then
echo "User remove error!"
exit 240;
fi
# MinIOで削除するユーザ用のテンポラリのAliasを削除します。
if ! mc alias remove MINIO_REMOVEUSER;then
echo "Alias remove error!"
exit 253;
fi
cd ${SCRIPT_DIR}/../PostgreSQL/bin/;
# PostgreSQLユーザを削除するExpectファイルを呼びます。
./dropuser.exp ${POSTGRES_USERNAME} ${POSTGRES_PASSWORD} ${USER_NAME}
このときのdropuser.exp
は以下の通りです。
#!/usr/bin/expect
set U [lindex $argv 0]
set PW [lindex $argv 1]
set USERNAME [lindex $argv 2]
set timeout -1
spawn docker compose exec -u postgres -it rdlh-pgsql psql -h rdlh-pgsql -U ${U} -W -c "REVOKE SELECT,UPDATE,INSERT ON iceberg_tables, iceberg_namespace_properties FROM ${USERNAME}" -c "DROP USER ${USERNAME}"
expect {
-glob "Password:" {
send "${PW}\n"
exp_continue
}
}
これで
$ ./adduser.sh 16
のようにするとユーザを作成し、16分後に削除される様になります。
おわりに
これの何がうれしいと言いますと、以下の事が言えます。
- お試しアカウントが配布しやすい。
- ユーザを時限的に作成できる。
これで自動的にユーザの作成と削除を実現できます。
Discussion