AmazonS3の使い方 APIとか

①バケツの一覧確認
②バケツ作成
③最後にバケツの一覧を確認
するプログラムです。凄く雑です。

それにしてもサンプルコードが少ない。。ツールも少ない。。
LiteLanguageにはAmazonS3のライブラリが有るんですが、Cには無いのかな@@

clxのライブラリを使えば簡単にhttpsに出来るはずです。でも移植性が!

サンプルプログラム

#include <iostream>
#include <string>
#include <clx/https.h>
#include <clx/uri.h>
#include <clx/base64.h>
#include <clx/format.h>
#include <clx/time.h>
#include <boost/asio.hpp>
#include <openssl/sha.h>
#include <openssl/hmac.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>

// 参考サイトから
char *base64(const unsigned char *input, int length)
{
  BIO *bmem, *b64;
  BUF_MEM *bptr;

  b64 = BIO_new(BIO_f_base64());
  bmem = BIO_new(BIO_s_mem());
  b64 = BIO_push(b64, bmem);
  BIO_write(b64, input, length);
  BIO_flush(b64);
  BIO_get_mem_ptr(b64, &bptr);

  char *buff = (char *)malloc(bptr->length);
  memcpy(buff, bptr->data, bptr->length-1);
  buff[bptr->length-1] = 0;

  BIO_free_all(b64);

  return buff;
}

// バケットリストの一覧用シグネチャ
std::string cresig_Bucket_list(std::string date, std::string SecretAccessKey)
{
	std::string StringToSign = "GET\n\n\n" + date + "\n/";
	std::string sigunetya;

	unsigned int reslen;
    unsigned char res[SHA_DIGEST_LENGTH + 1];

	HMAC(EVP_sha1(), SecretAccessKey.c_str(), SecretAccessKey.size(), (unsigned const char*)StringToSign.c_str(), StringToSign.size(), res, &reslen);

	char* output = base64(res, reslen);

	return std::string(output);
}

// 新しいバケット作成用シグネチャ
std::string cresig_PUT_Bucket(std::string date, std::string SecretAccessKey)
{
    // ※helloidea埋め込み (雑)
	std::string StringToSign = "PUT\n\n\n" + date + "\n/helloidea/";
	std::string sigunetya;

	unsigned int reslen;
    unsigned char res[SHA_DIGEST_LENGTH + 1];

	HMAC(EVP_sha1(), SecretAccessKey.c_str(), SecretAccessKey.size(), (unsigned const char*)StringToSign.c_str(), StringToSign.size(), res, &reslen);

	char* output = base64(res, reslen);

	return std::string(output);
}

int main() {
    
	std::string AWSAccessKeyId = "■■■■あなたのAWSAccessKeyId ■■■■";
	std::string SecretAccessKey = "■■■■■■■あなたのSecretAccessKey ■■■■■■■■";
	
	std::string fmt = "%a, %d %b %Y %H:%M:%S GMT";
	std::string time;
	clx::date_time now;
	std::cout << now.to_string<char>(fmt) << std::endl;
	time = (now + clx::hours(-9)).to_string<char>(fmt);

	boost::asio::ip::tcp::iostream s("s3.amazonaws.com", "http");

	std::string line;

    /********************************************************************************
         バケツリスト表示
    ********************************************************************************/
	time = (now + clx::hours(-9)).to_string<char>(fmt);
	s << "GET / HTTP/1.1\r\n";
	s << "Host: s3.amazonaws.com\r\n";
	s << "Date: " + time + "\r\n";
	s << "Authorization: AWS " +  AWSAccessKeyId + ":" + cresig_Bucket_list(time, SecretAccessKey)  + "\r\n";
	s << "\r\n";
	s << std::flush;

	// 受信
	while( getline(s, line) )
	{
		if(line == "0\r") break;
		std::cout << line << std::endl;
	}

    /********************************************************************************
        新しいバケツ作成
    ********************************************************************************/
	time = (now + clx::hours(-9)).to_string<char>(fmt);
	s << "PUT / HTTP/1.1\r\n";
	s << "Host: helloidea.s3.amazonaws.com\r\n";
	s << "Content-Length: 0\r\n";
	s << "Date: " + time + "\r\n";
	s << "Authorization: AWS " +  AWSAccessKeyId + ":" + cresig_PUT_Bucket(time, SecretAccessKey)  + "\r\n";
	s << "\r\n";
	s << std::flush;

	// 受信
	while( getline(s, line) )
	{
		if(line == "\r") break;
		std::cout << line << std::endl;
	}
	

    /********************************************************************************
         バケツリスト表示
    ********************************************************************************/
	time = (now + clx::hours(-9)).to_string<char>(fmt);
	s << "GET / HTTP/1.1\r\n";
	s << "Host: s3.amazonaws.com\r\n";
	s << "Date: " + time + "\r\n";
	s << "Authorization: AWS " +  AWSAccessKeyId + ":" + cresig_Bucket_list(time, SecretAccessKey)  + "\r\n";
	s << "\r\n";
	s << std::flush;

	// 受信
	while( getline(s, line) )
	{
		if(line == "0\r") break;
		std::cout << line << std::endl;
	}
    
    return 0;
}

実行結果

Wed, 29 Dec 2010 02:10:45 GMT
HTTP/1.1 200 OK
x-amz-id-2: aC+IMQJqhaar2Ge7xPExs/89HxVa3uX0XkHh5UjyJg6r3q1eXE8i8amVJqkn+wEJ
x-amz-request-id: B938635CD29FA243
Date: Tue, 28 Dec 2010 17:10:47 GMT
Content-Type: application/xml
Transfer-Encoding: chunked
Server: AmazonS3

171
<?xml version="1.0" encoding="UTF-8"?>
<ListAllMyBucketsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/"><Owner><ID>48cf8016ac58fbcb1eac1d3494f2aa32a1c962e693e2cdcf07260dd32ad20c1b</ID><DisplayName>monyuonyu</DisplayName></Owner><Buckets><Bucket><Name>mk-pino</Name><CreationDate>2010-12-27T13:09:37.000Z</CreationDate></Bucket></Buckets></ListAllMyBucketsResult>
HTTP/1.1 200 OK
x-amz-id-2: RxRWtFXn+tC87ssZPN0ETtoJ9LRQb8Y+o6O/h8ROoUTWYejJE0mi7aL0OSc9E40I
x-amz-request-id: 394C83DC35E55C94
Date: Tue, 28 Dec 2010 17:10:47 GMT
Location: /helloidea
Content-Length: 0
Server: AmazonS3

HTTP/1.1 200 OK
x-amz-id-2: ND24MyAfKEysFZadhha3uGgKruXPaOUVqBNezeimYof8CFiTMIunxmtSQYp6Ytol
x-amz-request-id: F062E71478508082
Date: Tue, 28 Dec 2010 17:10:47 GMT
Content-Type: application/xml
Transfer-Encoding: chunked
Server: AmazonS3

1cd
<?xml version="1.0" encoding="UTF-8"?>
<ListAllMyBucketsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/"><Owner><ID>48cf8016ac58fbcb1eac1d3494f2aa32a1c962e693e2cdcf07260dd32ad20c1b</ID><DisplayName>monyuonyu</DisplayName></Owner><Buckets><Bucket><Name>helloidea</Name><CreationDate>2010-12-28T17:10:47.000Z</CreationDate></Bucket><Bucket><Name>mk-pino</Name><CreationDate>2010-12-27T13:09:37.000Z</CreationDate></Bucket></Buckets></ListAllMyBucketsResult>

パケットキャプチャ

GET / HTTP/1.1
Host: s3.amazonaws.com
Date: Tue, 28 Dec 2010 17:12:02 GMT
Authorization: AWS AKIAJEB3RUBMODUOMC2A:9MewU/ovOLenn16jxpJWDo/BFDA=

HTTP/1.1 200 OK
x-amz-id-2: qWXRbV7oveOX7lwgcgZHI1Qr3wGnrRfT5P/AcFKFLe2wpUCEi4HPqusWBDJDUhiB
x-amz-request-id: 38F96C42725BF3E0
Date: Tue, 28 Dec 2010 17:12:05 GMT
Content-Type: application/xml
Transfer-Encoding: chunked
Server: AmazonS3

171
<?xml version="1.0" encoding="UTF-8"?>
<ListAllMyBucketsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/"><Owner><ID>48cf8016ac58fbcb1eac1d3494f2aa32a1c962e693e2cdcf07260dd32ad20c1b</ID><DisplayName>monyuonyu</DisplayName></Owner><Buckets><Bucket><Name>mk-pino</Name><CreationDate>2010-12-27T13:09:37.000Z</CreationDate></Bucket></Buckets></ListAllMyBucketsResult>
0

PUT / HTTP/1.1
Host: helloidea.s3.amazonaws.com
Content-Length: 0
Date: Tue, 28 Dec 2010 17:12:02 GMT
Authorization: AWS AKIAJEB3RUBMODUOMC2A:o/kGf8J/7QGDL40p/J01VhOUMRQ=

GET / HTTP/1.1
Host: s3.amazonaws.com
Date: Tue, 28 Dec 2010 17:12:02 GMT
Authorization: AWS AKIAJEB3RUBMODUOMC2A:9MewU/ovOLenn16jxpJWDo/BFDA=
HTTP/1.1 200 OK
x-amz-id-2: 19v/z0GcSOurF1NVtKikSSvQJT5Ohq642c1weziUroWv99NBWmKOos17qwvjBvoF
x-amz-request-id: 5E30C041AB2E8523
Date: Tue, 28 Dec 2010 17:12:06 GMT
Location: /helloidea
Content-Length: 0
Server: AmazonS3

HTTP/1.1 200 OK
x-amz-id-2: 5sSB/Dr9tlFFjv8mFQxloozANn0ZEtL9/ZzMKLQkiR+HIglhiledhCwO/vMxNBU8
x-amz-request-id: 81FA9B5EB1BFD1A5
Date: Tue, 28 Dec 2010 17:12:06 GMT
Content-Type: application/xml
Transfer-Encoding: chunked
Server: AmazonS3

1cd
<?xml version="1.0" encoding="UTF-8"?>
<ListAllMyBucketsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/"><Owner><ID>48cf8016ac58fbcb1eac1d3494f2aa32a1c962e693e2cdcf07260dd32ad20c1b</ID><DisplayName>monyuonyu</DisplayName></Owner><Buckets><Bucket><Name>helloidea</Name><CreationDate>2010-12-28T17:12:06.000Z</CreationDate></Bucket><Bucket><Name>mk-pino</Name><CreationDate>2010-12-27T13:09:37.000Z</CreationDate></Bucket></Buckets></ListAllMyBucketsResult>
0

基本的にパケットキャプチャをしながら作業すると楽だと思います。
FirefixのプラグインのS3Foxをパケットキャプチャすると動作がよくわかります。
それとS3Foxはデータが暗号化されてない事もわかりました・・・気をつけてください。

sigunetyaの作成に関しては、Amazon Simple Storage Service Developer Guide(下参照)に詳しく書いてあります。
載っていないAPIのsigunetya生成に関しては、周りのAPIを見て判断します。

AWSAccessKeyId が丸見えですがなにか^^;
参考サイト

Amazon Simple Storage Service Developer Guide
Amazon Simple Storage Service API Reference
Howto base64 encode with C/C++ and OpenSSL
openssl HMAC を試す
CLX C++ Libraries
HTTP クライアントを作ってみよう(5) – Basic 認証編 –
REST APIでS3からオブジェクトを取得する
boost::asio
Web 2.0時代のWebServices ~SOAP/REST使い分けの指針

投稿者:

「AmazonS3の使い方 APIとか」への4件のフィードバック

コメントを残す

メールアドレスが公開されることはありません。