Works by

Ren's blog

@rennnosuke_rk 技術ブログです

【IBM COS】IBM Cloud Object Storageで署名付きURLを発行する

f:id:rennnosukesann:20181216025439p:plain:w200

IBM Cloud Object Storageとは

IBM Cloud Object Storage(COS)はIBMクラウド上で提供するストレージサービスです。IBM Cloud上でAWSのS3のようなオブジェクトベースでリソースを保存できるストレージ環境を提供します。IBM Cloud上でサービスとして提供されているので、クラウド上に立ち上げたアプリケーションサーバと連携して画像や音声の保存用ストレージとして利用する・・・といったことが可能です。それだけでなく、オンプレミス環境でホスト型クラウド環境を構築することでもCOSを利用することができます。

COSが使われるシーン

多くの場合、Webアプリケーションやシステムで使われるDB(RDBMS)では、文字列や数値といったデータと、それらのデータからなるいわゆる構造化データが扱われます。例えばRDBの場合、テーブルに挿入されるレコードが構造化データになります。このような構造化データはスキーマによって明確に定義されるため、RDBで管理しやすい傾向にあります。

しかし、画像や音声といったいわゆる非構造化データは、構造化されたデータを扱うシステムとはあまり相性がよくありません。例えば画像バイナリをRDBに保存する場合、数MBに及ぶバイナリを文字列(Base64など)に変換してどこかのテーブルの1カラムの値として保存する、といったことなどをやらなければいけません。このような実装は、RDBの設計にいびつな構造をもたらします。

そこで、そのような非構造化データは一旦別の場所に追いやり、そのデータへのアクセスポイントをRDBレコードのカラム値として保存するやり方が考えられます。そのような場合にCOSが威力を発揮します。

COSはKVSライクにデータを保存するオブジェクトベースのストレージです。特定のオブジェクトデータに一意なキーを対応付け、それをもとにアクセスポイントを発行してデータの更新/参照を可能にします。例えば画像であれば、COSに保存した画像のオブジェクトキーからURLを発行することができます。

IBM COSの署名付きURL

COSに保存したリソースを公開するとき、特定サービスのユーザに対してのみ限定公開したい場合があると思います。COSのエンドポイントをprivateにする方法もありますが、スマートフォンなどパブリックなネットワークに接続するクライアントに対してデータを提供したい場合など、適用しにくい場合も考えられます。

そのような場合、署名付きURLが使えます。COSの設定でエンドポイントに対するアクセスを原則禁止としつつ、署名付きのURL経由でのみリソースにアクセスさせるといったことが可能なため、パブリックなネットワークに接続するクライアントに対してもリソースの提供に対応できます。

署名付きURLの発行

AWS CLI

署名付きURLは、AWS CLIを利用して発行することができます。 Macの場合、 Homebrewでインストールすることができます。

IBM Cloud Docs

$ brew install awscli

Homebrew、およびAWS CLIのインストールには下記も参考にしてください。

brew.sh

docs.aws.amazon.com


インストール後、aws configure でCOSエンドポイントの設定を行います。

$ aws configure
AWS Access Key ID [None]: {Access Key ID}
AWS Secret Access Key [None]: {Secret Access Key}
Default region name [None]: {Provisioning Code}
Default output format [None]: json

設定後、下記コマンドを実行することで署名付きURLを発行できます。 --endpoint-url には署名付きURLを跛行したいしたいリソースのCOSエンドポイントを、 {bucketName} にはリソースのバケット名、 {objKey} にはオブジェクトキーを入力してください。

$ aws --endpoint-url=https://{endpoint} s3 presign s3://{bucketName}/{objKey}

バケットはCOS内で一意な保存領域を表し、複数のバケットを一つのCOSサービス内に生成することでリソースの保存領域を論理的に分割することができます。オブジェクトキーはCOS内リソースを一意に識別するためのキーになります。

また、下記のように署名付きURLには有効期限を任意に設定することができます。

$ aws --endpoint-url=https://{endpoint} s3 presign s3://bucket-1/new-file --expires-in 604800000

Java

COSのSDKを利用して、プログラム中でも署名付きURLを発行することができます。 今回はJavaを題材としてコード例を示します。

build.gradle
dependencies {
    ...  
    implementation('com.ibm.cos:ibm-cos-java-sdk:latest.release')
    ...
}
Java
private String getPreSignedUrl(String bucketName, String objectKey) {

    // COS認証情報(実際の運用では環境変数等で外出ししてください)
    String accessKey = "XXXXXX";
    String secretKey = "XXXXXXXXX";
    String endpoint = "XXXXXXXXXX";
    String region = "XXXXXXXX";

    // 署名有効期限までの時間
    long signExpiration = 604800000; // 1week

    // 認証情報
    AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);

    // クライアント設定
    ClientConfiguration clientConfig = new ClientConfiguration();
    clientConfig.setProtocol(Protocol.HTTPS); // プロトコル
    clientConfig.setConnectionTimeout(10000); // 接続タイムアウト(ms)

    // COSエンドポイント設定
    EndpointConfiguration endpointConfiguration = new EndpointConfiguration(endpoint, region);

    // クライアント生成
    AmazonS3 client = AmazonS3ClientBuilder.standard()
        .withCredentials(new AWSStaticCredentialsProvider(credentials)).withClientConfiguration(clientConfig)
        .withEndpointConfiguration(endpointConfiguration).build();

    // 署名有効期限
    Date expiration = new Date();
    long msec = expiration.getTime() + signExpiration;
    expiration.setTime(msec);

    // 署名つきURL生成
    GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, objectKey);
    generatePresignedUrlRequest.setMethod(HttpMethod.GET);
    generatePresignedUrlRequest.setExpiration(expiration);
    String url = client.generatePresignedUrl(generatePresignedUrlRequest).toString();
 
    return url;   
}

上記メソッドでは既にCOS上に保存されているリソースが置かれているバケット名と、リソースオブジェクトキーを受け取り、署名付きURLを生成しています。

署名付きURLによるリソースへのアクセス

生成した署名付きURLは以下のようになります(CredentialやSignatureなど、一部ぼかした表現にしています)。

https://hogehoge.us-south.objectstorage.softlayer.net/fugafuga.JPEG?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20181222T101615Z&X-Amz-SignedHeaders=host&X-Amz-Expires=604800&X-Amz-Credential=[Credential...]&X-Amz-Signature=[Signature...]

署名付きURLを生成すると、以下のようなパラメータがURLに付加されます。これらはURLに対する署名情報を表しています。

X-Amz-Algorithm ダイジェスト計算のためのハッシュアルゴリズム
X-Amz-Date URL生成時刻
X-Amz-SignedHeaders 署名対象ヘッダ情報
X-Amz-Expires URL署名有効期限
X-Amz-Credential 認証情報
X-Amz-Signature 署名

これら署名情報のないURLにアクセスするとHTTPステータスコード403が返され、「Access Denied」となりリソースにアクセスすることができません。

f:id:rennnosukesann:20181222193737p:plain

また署名付きURLの有効期限は任意に設定することができます。今回は有効期限を一週間としています。 有効期限を過ぎた署名付きエンドポイントにアクセスすると、下記のようなレスポンスが返され、リソースにアクセスできなくなります。

f:id:rennnosukesann:20181222193800p:plain

このように、リソースへのアクセス手段を署名付きURL経由で提供することで、COSに保存されたリソースをより安全に共有できるようになります。

参考文献

www.ibm.com

www.ibm.com

https://console.bluemix.net/docs/services/cloud-object-storage/hmac/presigned-urls.html#create-a-presigned-url