ある環境で AWS S3 の署名済み URL を用いて感動しました。
そこで,MinIO on Docker でマルチユーザ&署名済み URL によるアップロードやアクセスに対応し,手元の環境でも感動を味わえるようにします。
前提条件
- MinIO が使える状態であること
- 今回の環境は docker-compose の Volume で NFS を指定して MinIO を立ち上げる - Qiita で構築したものになります
MinIO クライアント
インストール
MinIO | MinIO Client Quickstart Guide を参考にクライアントツールをインストールし,mc
コマンドを使えるようにします。
docker を用いる場合は docker pull minio/mc
で macOS の方で Homebrew を導入済みの方は brew install minio/stable/mc
でコマンドで MinIO クライアントを導入できます。
docker を用いる際は,以降の mc コマンドを用いるところは docker run -it --entrypoint=/bin/sh minio/mc
で環境を立ち上げてからコマンドを入力してください。
セットアップ
サーバへの接続情報を設定します:
$ # mc config host add <ALIAS> <YOUR-S3-ENDPOINT> <YOUR-ACCESS-KEY> <YOUR-SECRET-KEY>
$ mc config host add minio http://127.0.0.1:9000 BKIKJAA5BMMU2RHO6IBB V7f1CwQqAcwo80UEIJEjc5gVQUSSx5ohQ9GSrr12
実際に動作確認としてすでにあるバケットの一覧を取得します:
$ # mc ls <ALIAS>
$ mc ls minio
ユーザ作成
全権アカウントとは別にバケット毎の作業用アカウントを作成します。
まずはバケットを作成します:
$ mc mb minio/my-bucketname
作成した my-bucketname
バケットに対して操作可能なアカウントを作成しましょう。
ポリシーの作成
新しく作成するアカウントに適応するポリシーを事前に追加します。
ポリシーは json で設定ファイルを作成し,mc コマンドで実際にサーバに登録します。
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::my-bucketname/*"
],
"Sid": ""
}
]
}
設定ファイルを作成したら,実際にサーバにポリシーを追加しましょう:
$ mc admin policy add minio my-bucketname my-bucketname.json
Added policy `my-bucketname` successfully.
と表示されれば成功です。
ユーザの作成
新しくユーザを作成し,上で作成したポリシーを適用します。
$ mc admin user add minio newuser newuser123 # 新しくユーザを作成
$ mc admin policy set minio my-bucketname user=newuser # 作成したユーザにポリシーを設定
Security Token Service(STS) による一時アカウントの発行と STS を用いた署名済み URL の発行
前準備
まずは Web 画面から事前に my-bucketname
バケットにファイルを保存します。
今回は test.txt
という名前で保存したものとして,以降進めます。
ソースコード
今回は AWS の SDK である boto3 を用います。
$ pip install boto3 # boto3 をインストール
実際にプログラムを作成して署名済み URL を取得・表示します。
下のプログラムでは,MinIO への認証情報も直接書いていますが,実際に利用する際は profile を作成したり,環境変数で設定しましょう。
import json
import boto3
from boto3.session import Session
from botocore.config import Config
endpoint = 'http://127.0.0.1:9000' # MinIO サーバの URL
my_config = Config(
signature_version = 'v4',
)
# 一時アカウントに設定するポリシーを定義
policy = {
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::my-bucketname/*"
],
"Sid": "Stmt1"
}
]
}
# boto3 を事前に作成したアカウントでクライアントを用意
client = boto3.client('sts',
aws_access_key_id='YOUR_ACCESS_KEY', # アクセスキーを設定する
aws_secret_access_key='YOUR_SECRET_KEY', # シークレットキーを設定する
config=my_config, endpoint_url=endpoint)
# 一時アカウントの取得
response = client.assume_role(
RoleArn='arn:xxx:xxx:xxx:xxxx', # AWS との互換のために適当に値を入れる
RoleSessionName='anything', # 同上
Policy=json.dumps(policy, separators=(',',':')), # ポリシーは JSON の文字列で渡す ※空白は付与しない
# 一時アカウントの有効期間 (900秒から43200秒の範囲で設定する
DurationSeconds=900,
)
# 上で取得した一時アカウントのうち,署名済み URL 発行に必要な分を取り出す
sts = {
'aws_access_key_id': response['Credentials']['AccessKeyId'],
'aws_secret_access_key': response['Credentials']['SecretAccessKey'],
'aws_session_token': response['Credentials']['SessionToken']
}
# 一時アカウントで接続する準備
session = Session(**sts)
# 一時アカウントでクライアントを用意
s3 = session.client('s3', config=Config(signature_version='s3v4'), endpoint_url=endpoint)
# 署名済み URL を取得 ()
url = s3.generate_presigned_url(
ClientMethod='get_object', # 許可するAPIメソッド(今回は get_object: ファイルの取得)
Params={'Bucket': 'my-bucketname', 'Key': 'test.txt'}, # ファイル情報
ExpiresIn=60, # URL の有効期間 (デフォルトは 3600秒)
HttpMethod='GET') # 許可する HTTP メソッド(今回は GET)
print(url) # 署名済み URL を出力
出力された URL にアクセスすると事前にアップロードしておいた test.txt
ファイルの中身が確認できると思います。