Rust rusoto_s3でS3読み書き用署名付きURLを取得する

個人開発したアプリの宣伝
目的地が設定できる手帳のような使い心地のTODOアプリを公開しています。
Todo with Location

Todo with Location

  • Yoshiko Ichikawa
  • Productivity
  • Free

スポンサードリンク

rusoto_s3でS3非公開bucketへのpresign URLを取得したので記録しておきます。

参考にしたページ

rusoto/s3.rs at master · rusoto/rusoto · GitHub

rusoto_s3 presignで検索するも上記のテストコードしかめぼしい情報がなく、テストコードを読み進めていく。どうやらPreSignedRequestというTraitを用いる模様。

rusoto_s3::util::PreSignedRequest - Rust

PreSignedRequestは、コードを読み進めていくと

impl PreSignedRequest for GetObjectRequest { ... }

のようにGetObjectRequestPutObjectRequestなんかのmixinになっている。

ということで、実装例。

書き込み用署名を取得する

use rusoto_core::{Region, credential::{DefaultCredentialsProvider, ProvideAwsCredentials}};
use rusoto_s3::{GetObjectRequest, PutObjectRequest, S3, S3Client, util::PreSignedRequest};
use dotenv::dotenv;

pub async fn get_s3_presign_for_put_object(bucket_name: String, key:String) -> String {
  dotenv().ok();
  let region = Region::ApNortheast1;
  let req = PutObjectRequest {
    bucket: bucket_name,
    key: key,
    ..Default::default()
  };
  let credentials = DefaultCredentialsProvider::new()
        .unwrap()
        .credentials()
        .await.unwrap();
  //PreSignedRequestOption expires_in: 3600
  req.get_presigned_url(&region, &credentials, &Default::default())
}

PutObjectRequestに書き込み先のbucketとPut対象とするkeyを指定する。もちろんディレクトリ階層を表現する時はpath/to/object_nameのように/スラッシュ区切りで指定できる。

credentials

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY

という環境変数名を見に行くので、僕の場合は.envに記載しておいた。もちろんシェルの.profileなんかに書いておいてもいいし、コード上でkeyを埋め込みたい場合は

std::env::set_var("AWS_ACCESS_KEY_ID", "xxxxx");
std::env::set_var("AWS_SECRET_ACCESS_KEY", "xxxxx");

とか書いておけばいいと思う笑

.aws/credentialsに定義されたprofileを指定する方法は調べていない...。

また、get_presigned_urlの3つめの引数は、コードを読む限り、PreSignedRequestOptionを渡せるみたい。PreSignedRequestOptionexpires_inというフィールドを持っており、デフォルトでは、Duration::from_secs(3600)となっているので、必要に応じて署名の有効時間を調節できるようになってるみたい。試してはないけど、コード読む限りの見解です。

読み出し用署名を取得する

書き込みと同じ、PutObjectRequestGetObjectRequestになるだけ。

pub async fn get_s3_presign_for_get_object(bucket_name:String, key:String) -> String {
  dotenv().ok();
  let region = Region::ApNortheast1;
  let req = GetObjectRequest {
    bucket: bucket_name,
    key: key,
    ..Default::default()
  };
  let credentials = DefaultCredentialsProvider::new()
        .unwrap()
        .credentials()
        .await.unwrap();
  req.get_presigned_url(&region, &credentials, &Default::default())
}

情報が少なくて結構調べてしまった(^^;)。まあ普段使いで署名取る分にはAWS lambda & boto3なんかでサクっとできるからね(^^;)