Riak CS の SSL を有効にして AWS SDK for Ruby でファイルをアップロードする

手順

1. 証明書を作成する
2. bucket を決めて,DNS にドメインを登録する
3. Riak CS の SSL 機能を有効にして起動させる
4. curl を使用して,admin ユーザのアカウントを作成する
5. AWS SDK for Ruby をインストールする
6. ファイルをアップロードする
7. boto で確認してみる

環境

  • Riak: 1.4.1
  • Stanchion: 1.4.0
  • Riak CS: 1.4.0
  • Ruby: 2.0.0-p195
  • aws-sdk: 1.15.0

1. 証明書を作成する

Amazon S3 と同様で,2 つの URL を使用します.

そのため,サーバ証明書の X509v3 Subject Alternative Name に example.com と,<bucketname>.example.com を指定しておきます.
後で bucket を追加する場合を考えて,Amazon S3サーバ証明書と同様に * を使用して,下記のように指定しておくと便利です.

            X509v3 Subject Alternative Name:
                DNS:*.example.com, DNS:example.com

2. bucket を決めて,DNS にドメインを登録する

HTTP の場合と異なり,SSL を使用する場合には,クライアントの HTTP プロキシの指定は使用できません.
HTTPS の場合,クライアントは,はじめに HTTP プロキシサーバに向かって CONNECT メソッドのリクエストを送り,トンネル接続の確立を要求するためです.

そのため,リクエストのホスト名の名前解決が必要になります.

例えば,bucket1 という bucket を使用する場合には,example.com と bucket1.example.com の 2 つを DNS サーバに登録しておきます.

簡易の動作確認のための unbound への設定例:

    local-data: "example.com A 192.168.1.6"
    local-data: "bucket1.example.com A 192.168.1.6"

3. Riak CS の SSL 機能を有効にして起動させる

下記のドキュメントを参考にして,Riak CS を起動させます.

また,今回はドメインを example.com で設定しているため,/etc/riak/app.config の下記の箇所も変更します.

<               {cs_root_host, "s3.amazonaws.com"},
---
>               {cs_root_host, "example.com"},

4. curl を使用して,admin ユーザのアカウントを作成する

--cacert オプションに,サーバ証明書を検証する CA 証明書を指定します.

# curl --cacert ca.pem -H 'Content-Type: application/json' -X POST https://example.com:8080/riak-cs/user --data '{"email":"admin@example.com", "name":"admin user"}'
{"email":"admin@example.com","display_name":"admin","name":"admin user","key_id":"BSNKJWA28Q9QYHRAQZVS","key_secret":"I3N_Nfh58X_Ypva4nb7_NtY-0p1RrEQabKKNtg==","id":"9062458e400b4faa5052dc8aae54dd5da58d38e6f958e555570804cc73af9588","status":"enabled"}

5. AWS SDK for Ruby をインストールする

gem で入れます.

$ gem install aws-sdk

6. ファイルをアップロードする

ファイルアップロードの例です.

#!/usr/bin/env ruby
# -*- coding: utf-8 -*-

require 'aws-sdk'

ACCESS_KEY_ID = 'BSNKJWA28Q9QYHRAQZVS'
SECRET_ACCESS_KEY = 'I3N_Nfh58X_Ypva4nb7_NtY-0p1RrEQabKKNtg=='
BUCKET_NAME = 'bucket1'
FILE_NAME = 'foo.txt'

s3 = AWS::S3.new(
  access_key_id: ACCESS_KEY_ID,
  secret_access_key: SECRET_ACCESS_KEY,
  s3_endpoint: 'example.com',
  use_ssl: true,
  s3_port: 8080,
  ssl_ca_file: '/tmp/ca.pem',
  ssl_verify_peer: true
)
bucket = s3.buckets.create(BUCKET_NAME)
object = bucket.objects[FILE_NAME]
object.write(File.open(FILE_NAME, 'rb'))

Riak CS のログ(/var/log/riak-cs/access.log)を見てみると PUT できていることが分かります.

192.168.1.104 - - [16/Aug/2013:15:29:07 +0000] "PUT /buckets/bucket1 HTTP/1.1" 200 0 "" "aws-sdk-ruby/1.15.0 ruby/2.0.0 x86_64-darwin12.3.0"
192.168.1.104 - - [16/Aug/2013:15:29:07 +0000] "PUT /buckets/bucket1/objects/foo.txt HTTP/1.1" 200 0 "" "aws-sdk-ruby/1.15.0 ruby/2.0.0 x86_64-darwin12.3.0"

7. boto で確認してみる

AWS SDK for Ruby で確認してもいいのですが,他のツールで確認してみます.

.boto の設定:

[boto]
ca_certificates_file = "/tmp/ca.pem"
https_validate_certificates = True
#!/usr/bin/env python

from boto.s3.connection import S3Connection

conn = S3Connection(
  aws_access_key_id = "BSNKJWA28Q9QYHRAQZVS",
  aws_secret_access_key = "I3N_Nfh58X_Ypva4nb7_NtY-0p1RrEQabKKNtg==",
  is_secure = True,
  host = 'example.com',
  port = 8080)

bucket_name = 'bucket1'
bucket = conn.get_bucket(bucket_name)

key = bucket.get_key("foo.txt")
key.get_contents_to_filename("bar.txt")

期待通りに,アップロードした foo.txt の内容で bar.txt が作成されていました.

念のため,Riak CS のログも確認

192.168.1.104 - - [16/Aug/2013:15:29:29 +0000] "GET /buckets/bucket1/objects?max-keys=0 HTTP/1.1" 200 252 "" "Boto/2.10.0 (darwin)"
192.168.1.104 - - [16/Aug/2013:15:29:29 +0000] "HEAD /buckets/bucket1/objects/foo.txt HTTP/1.1" 200 14 "" "Boto/2.10.0 (darwin)"
192.168.1.104 - - [16/Aug/2013:15:29:29 +0000] "GET /buckets/bucket1/objects/foo.txt HTTP/1.1" 200 14 "" "Boto/2.10.0 (darwin)"