Amazon S3 から Cloud Storage への単純な移行

このページでは、Amazon Simple Storage Service(Amazon S3)から Cloud Storage への単純な移行を行う方法について説明します。単純な移行では、既存のツールとライブラリを使用して Amazon S3 への認証済み REST リクエストを生成し、認証済みリクエストを Cloud Storage に送信します。

Cloud Storage を初めて使用し、API を直接使用しない場合は、Google Cloud コンソールを使用して転送の設定と管理を行うことを検討してください。Google Cloud コンソールには、Cloud Storage へのグラフィック インターフェースが用意されています。これにより、Amazon S3 から Cloud Storage へのデータ移行など、多くのストレージ タスクをブラウザのみで行うことができます。

Cloud Storage に Amazon S3 データのバックアップを保存する場合は、イベント ドリブン転送の使用を検討してください。イベント ドリブン転送では、Amazon S3 イベント通知を使用して、Cloud Storage バケットを自動的に Amazon S3 ソースと同期します。

単純な移行シナリオでの Amazon S3 から Cloud Storage への移行

Cloud Storage にリクエストを送信するには、次の操作を行います。

  • デフォルトの Google Cloud プロジェクトを設定します。
  • HMAC(ハッシュベースのメッセージ認証コード)キーを取得します。
  • 既存のツールまたはライブラリで次の変更を加えます。

    • Cloud Storage XML API リクエスト エンドポイントを使用するようにリクエスト エンドポイントを変更します。
    • Amazon Web Services(AWS)のアクセスキーと秘密鍵を、対応する Cloud Storage のアクセス ID と秘密(総称して Cloud Storage HMAC キー)に置き換えます。
    • x-amz- ヘッダーで、サポートされている Cloud Storage の値が使用されていることを確認してください。たとえば、x-amz-storage-class では、使用可能ないずれかの Cloud Storage ストレージ クラスが使用されている必要があります。

      Cloud Storage XML API を単純な移行のシナリオで使用する場合、AWS 署名 ID を Authorization ヘッダーで使用すると、Cloud Storage では x-amz-* ヘッダーと Amazon S3 ACL XML 構文がリクエストに存在するものと想定します。Cloud Storage は、ヘッダー表にリストされているものなど、x-goog-* と同等のものを持つ x-amz-* ヘッダーを処理します。

これらの変更を行うと、既存のツールとライブラリの使用を開始し、HMAC リクエストを Cloud Storage に送信できます。

たとえば、次のサンプルは、Amazon S3 SDK を使用して Cloud Storage バケットをリストする方法を示しています。

Go

詳細については、Cloud Storage Go API のリファレンス ドキュメントをご覧ください。

Cloud Storage に対する認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証の設定をご覧ください。

import (
	"context"
	"fmt"
	"io"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/s3"
)

func listGCSBuckets(w io.Writer, googleAccessKeyID string, googleAccessKeySecret string) error {
	// googleAccessKeyID := "Your Google Access Key ID"
	// googleAccessKeySecret := "Your Google Access Key Secret"

	// Create a new client and do the following:
	// 1. Change the endpoint URL to use the Google Cloud Storage XML API endpoint.
	// 2. Use Cloud Storage HMAC Credentials.
	sess := session.Must(session.NewSession(&aws.Config{
		Region:      aws.String("auto"),
		Endpoint:    aws.String("https://storage.googleapis.com"),
		Credentials: credentials.NewStaticCredentials(googleAccessKeyID, googleAccessKeySecret, ""),
	}))

	client := s3.New(sess)
	ctx := context.Background()

	ctx, cancel := context.WithTimeout(ctx, time.Second*10)
	defer cancel()
	result, err := client.ListBucketsWithContext(ctx, &s3.ListBucketsInput{})
	if err != nil {
		return fmt.Errorf("ListBucketsWithContext: %w", err)
	}

	fmt.Fprintf(w, "Buckets:")
	for _, b := range result.Buckets {
		fmt.Fprintf(w, "%s\n", aws.StringValue(b.Name))
	}

	return nil
}

Java

詳細については、Cloud Storage Java API のリファレンス ドキュメントをご覧ください。

Cloud Storage に対する認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証の設定をご覧ください。

import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.Bucket;
import java.util.List;

public class ListGcsBuckets {
  public static void listGcsBuckets(String googleAccessKeyId, String googleAccessKeySecret) {

    // String googleAccessKeyId = "your-google-access-key-id";
    // String googleAccessKeySecret = "your-google-access-key-secret";

    // Create a BasicAWSCredentials using Cloud Storage HMAC credentials.
    BasicAWSCredentials googleCreds =
        new BasicAWSCredentials(googleAccessKeyId, googleAccessKeySecret);

    // Create a new client and do the following:
    // 1. Change the endpoint URL to use the Google Cloud Storage XML API endpoint.
    // 2. Use Cloud Storage HMAC Credentials.
    AmazonS3 interopClient =
        AmazonS3ClientBuilder.standard()
            .withEndpointConfiguration(
                new AwsClientBuilder.EndpointConfiguration(
                    "https://storage.googleapis.com", "auto"))
            .withCredentials(new AWSStaticCredentialsProvider(googleCreds))
            .build();

    // Call GCS to list current buckets
    List<Bucket> buckets = interopClient.listBuckets();

    // Print bucket names
    System.out.println("Buckets:");
    for (Bucket bucket : buckets) {
      System.out.println(bucket.getName());
    }

    // Explicitly clean up client resources.
    interopClient.shutdown();
  }

Python

詳細については、Cloud Storage Python API のリファレンス ドキュメントをご覧ください。

Cloud Storage に対する認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証の設定をご覧ください。

import boto3  # type: ignore


def list_gcs_buckets(
    google_access_key_id: str, google_access_key_secret: str
) -> List[str]:
    """Lists all Cloud Storage buckets using AWS SDK for Python (boto3)
    Positional arguments:
        google_access_key_id: hash-based message authentication code (HMAC) access ID
        google_access_key_secret: HMAC access secret

    Returned value is a list of strings, one for each bucket name.

    To use this sample:
    1. Create a Cloud Storage HMAC key: https://cloud.google.com/storage/docs/authentication/managing-hmackeys#create
    2. Change endpoint_url to a Google Cloud Storage XML API endpoint.

    To learn more about HMAC: https://cloud.google.com/storage/docs/authentication/hmackeys#overview
    """
    client = boto3.client(
        "s3",
        region_name="auto",
        endpoint_url="https://storage.googleapis.com",
        aws_access_key_id=google_access_key_id,
        aws_secret_access_key=google_access_key_secret,
    )

    # Call GCS to list current buckets
    response = client.list_buckets()

    # Return list of bucket names
    results = []
    for bucket in response["Buckets"]:
        results.append(bucket["Name"])
        print(bucket["Name"])  # Can remove if not needed after development
    return results

デフォルト プロジェクトの設定

単純な移行シナリオで Cloud Storage を使用するには、デフォルトのプロジェクトを設定することをおすすめします。このプロジェクトは、GET サービスまたは PUT バケットのような特定のオペレーションを実行するために使用されます。デフォルトのプロジェクトを設定しない場合は、特定のリクエストでプロジェクト ヘッダーを指定する必要があります。

デフォルトのプロジェクトを設定するには:

  1. Google Cloud コンソールで、[Cloud Storage の設定] ページを開きます
  2. [相互運用性] タブを選択します。
  3. [相互運用アクセスのデフォルト プロジェクト] にある [PROJECT-ID をデフォルト プロジェクトに設定する] をクリックします

    プロジェクトがすでにデフォルトになっている場合は、[PROJECT-ID が相互運用アクセスのデフォルト プロジェクトです] と表示されます。

これで、このプロジェクトがデフォルトのプロジェクトになりました。別のプロジェクトを選択して次の手順を行うことで、いつでもデフォルトのプロジェクトを変更できます。

プロジェクト ヘッダーの指定

デフォルト プロジェクトを設定したうえで、あるいは別の方法として、x-amz-project-id ヘッダーを個々のリクエストで使用してプロジェクトを指定できます。

  • x-amz-project-id を使用するリクエストでは、すでにデフォルト プロジェクトが存在している場合でも、ヘッダーで指定されたプロジェクトが使用されます。

x-amz-project-id ヘッダーは、次の場合に役立ちます。

  • 複数のプロジェクトで作業している場合。
  • サービス アカウントが親プロジェクトをデフォルト プロジェクトとして使用するため、リクエストが別のプロジェクトに関連したサービス アカウントで行われる場合。

Amazon S3 にはプロジェクトがないため、使用するツールやクライアント ライブラリによっては、x-amz-project-id ヘッダーを指定できない場合があります。この場合、デフォルト プロジェクトを設定する必要があります。

HMAC キーの使用

単純な移行シナリオで Cloud Storage XML API を使用するには、認証に Cloud Storage のハッシュベースのメッセージ認証コード(HMAC)キーを使用します。通常は、サービス アカウントに関連付けられた HMAC キーを作成する必要がありますが、ユーザー アカウントに関連付けられたものを使用することもできます。

単純な移行シナリオでの認証

Authorization ヘッダーの使用

認証が必要な単純な移行のシナリオのオペレーションでは、Amazon S3 にリクエストを送信するときと同じように、Authorization リクエスト ヘッダーを含めます。Amazon S3 リクエストの Authorization ヘッダーの構文は次のとおりです。

Authorization: AWS4-HMAC-SHA256 Credential=AWS-ACCESS-KEY/CREDENTIAL_SCOPE, SignedHeaders=SIGNED_HEADERS, Signature=SIGNATURE

単純な移行のシナリオでは、Cloud Storage HMAC アクセス ID を使用するようにヘッダーを変更し、付けた Signature が確実に Cloud Storage HMAC 秘密鍵で計算されるようにします。

Authorization: ALGORITHM Credential=GOOG-ACCESS-ID/CREDENTIAL_SCOPE, SignedHeaders=SIGNED_HEADERS, Signature=SIGNATURE

Authorization ヘッダーの各要素は次のとおりです。

  • ALGORITHM: 使用した署名アルゴリズムとバージョン。AWS4-HMAC-SHA256 を指定すると、HMAC V4 署名を使用し、x-amz-* ヘッダーを送信することになります。また、GOOG4-HMAC-SHA256 を指定した場合、HMAC V4 署名を使用し、x-goog-* ヘッダーを送信することになります。GOOG4-RSA-SHA256 を指定した場合は、RSA V4 署名を使用し、x-goog-* ヘッダーを送信することになります。

  • GOOG-ACCESS-ID: アクセス ID は、リクエストを作成して署名するエンティティを識別されます。単純な移行では、Amazon S3 にアクセスするために使用するアマゾン ウェブ サービス(AWS)のアクセスキー ID を、Cloud Storage HMAC アクセス ID に置き換えます。Cloud Storage HMAC アクセス ID は GOOG で始まります。

  • CREDENTIAL_SCOPE: 署名で定義されている認証情報スコープ。単純な移行では、ALGORITHM 値に AWS4-HMAC-SHA256 を使用している場合は認証情報スコープを変更する必要がありません。

  • SIGNED_HEADERS: リクエストに署名するために含めなければならないヘッダー名をセミコロンで区切ったリスト。すべてのヘッダーは小文字で表し文字コードで並べ替える必要があります。

    Amazon S3 スタイルの署名付きヘッダー文字列の例は次のとおりです。

    content-type;host;x-amz-date

    単純な移行では、署名付きヘッダー文字列を変更する必要はありません。

  • SIGNATURE: リクエストの認証を可能にする署名。簡単な移行では、AWS アクセスキー情報を同等の Cloud Storage HMAC キー情報に置き換えます。

サンプルの認証リクエスト

次の例では、/europe/france/paris.jpg という名前のオブジェクトを my-travel-maps という名前のバケットにアップロードし、定義済みの ACL public-read を適用して審査担当者用にカスタム メタデータ ヘッダーを定義します。Amazon S3 のバケットに対するリクエストを次に示します。

PUT europe/france/paris.jpg HTTP/1.1
Host: my-travel-maps.s3.amazonaws.com
Date: Mon, 11 Mar 2019 23:46:19 GMT
Content-Length: 888814
Content-Type: image/jpg
x-amz-acl: public-read
x-amz-date:20190311T192918Z
x-amz-meta-reviewer: joe,jane
Authorization: AWS4-HMAC-SHA256 Credential=AWS-ACCESS-KEY/20190311/us-east-1/s3/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-acl;x-amz-date;x-amz-meta-reviewer, Signature=SIGNATURE

Cloud Storage のバケットに対するリクエストを次に示します。

PUT europe/france/paris.jpg HTTP/1.1
Host: my-travel-maps.storage.googleapis.com
Date: Mon, 11 Mar 2019 23:46:19 GMT
Content-Length: 888814
Content-Type: image/jpg
x-amz-acl: public-read
x-amz-date:20190311T192918Z
x-amz-meta-reviewer: joe,jane
Authorization: AWS4-HMAC-SHA256 Credential=GOOG-ACCESS-ID/20190311/us-east-1/s3/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-acl;x-amz-date;x-amz-meta-reviewer, Signature=SIGNATURE

このリクエストによって作成される正規リクエストは次のとおりです。

PUT
/europe/france/paris.jpg

content-length:888814
content-type:image/jpg
host:my-travel-maps.storage.googleapis.com
x-amz-acl:public-read
x-amz-date:20190311T192918Z
x-amz-meta-reviewer:joe,jane

content-length,content-type,host,x-amz-acl,x-amz-date,x-amz-meta-reviewer
82e3da8b3f35989512e8d428add7eca73ab0e5f36586e66fbad8e1051343cbd2

このリクエストに対して作成される署名対象文字列は次のとおりです。

AWS4-HMAC-SHA256
20190311T192918Z
20190311/us-east-1/s3/aws4_request
73918a5ff373d7a03e406fbf9ea35675396b06fca2af76c27a5c451fa783ef65

このリクエストでは、Content-MD5 ヘッダーを指定しなかったため、メッセージの 2 行目に空文字列が表示されています。

単純な移行シナリオでのアクセス制御

単純な移行をサポートするために、Cloud Storage では Amazon S3 によって生成される ACL を使用できます。単純な移行のシナリオでは、AWS を署名 ID として使用することで、Amazon S3 ACL XML 構文を使用して、ACL 構文に対応するよう Cloud Storage に指示します。使用する Amazon S3 ACL が Cloud Storage ACL モデルにマッピングされることを確認する必要があります。たとえば、ツールやライブラリが、Amazon S3 の ACL 構文を使用してバケットの WRITE 権限を付与する場合、バケットの READ 権限も付与する必要があります。これは、Cloud Storage の権限が入れ子構造であるためです。Cloud Storage 構文を使用して WRITE 権限を付与するときには、WRITEREAD の両方の権限を指定する必要はありません。

Cloud Storage は、次のシナリオで Amazon S3 ACL 構文をサポートします。

  • Cloud Storage に対して ACL を取得させるリクエスト(GET Object や GET Bucket リクエストなど)で、Cloud Storage は Amazon S3 ACL 構文を返します。
  • Cloud Storage に対して ACL を適用させるリクエスト(PUT Object や PUT Bucket リクエストなど)で、Cloud Storage は Amazon S3 ACL 構文を受け取ることを予期します。

単純な移行のシナリオの Authorization ヘッダーは、署名 ID として AWS を使用しますが、Google アクセス ID もあわせて使用します。

Authorization: AWS4-HMAC-SHA256 Credential=GOOG-ACCESS-ID/CREDENTIAL_SCOPE, SignedHeaders=SIGNED_HEADERS, Signature=SIGNATURE

次の例は、オブジェクトの ACL を返す Cloud Storage に対する GET リクエストを示しています。

GET europe/france/paris.jpg?acl HTTP/1.1
Host: my-travel-maps.storage.googleapis.com
Date: Thu, 21 Feb 2019 23:50:10 GMT
Content-Type: application/xml
X-Amz-Date: 20190221T235010Z
Authorization: AWS4-HMAC-SHA256 Credential=GOOGMC5PDPA5JLZYQMHQHRAX/20190221/region/s3/aws4_request, SignedHeaders=host;x-amz-date, Signature=29088b1d6dfeb2549f6ff67bc3744abb7e45475f0ad60400485805415bbfc534

リクエストのレスポンスには、Amazon S3 ACL 構文を使用する ACL が含まれています。

<?xml version='1.0' encoding='UTF-8'?>
<AccessControlPolicy>
    <Owner>
        <ID>00b4903a972faa8bcce9382686e9129676f1cd6e5def1f5663affc2ba4652490
        </ID>
        <DisplayName>OwnerName</DisplayName>
    </Owner>
    <AccessControlList>
        <Grant>
            <Grantee xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
                xsi:type='CanonicalUser'>
                <ID>00b4903a972faa8bcce9382686e9129676f1cd6e5def1f5663affc2ba4652490</ID>
                <DisplayName>UserName</DisplayName>
            </Grantee>
            <Permission>FULL_CONTROL</Permission>
        </Grant>
    </AccessControlList>
</AccessControlPolicy>

次の例は、オブジェクトの ACL を設定する Cloud Storage に対する PUT リクエストを示しています。次の例は、Amazon S3 ACL 構文を使用するリクエストの本文を示しています。

PUT europe/france/paris.jpg?acl HTTP/1.1
Host: my-travel-maps.storage.googleapis.com
Date: Thu, 21 Feb 2019 23:50:10 GMT
Content-Type: application/xml
Content-Length: 337
X-Amz-Date: 20190221T235010Z
Authorization: AWS4-HMAC-SHA256 Credential=GOOGMC5PDPA5JLZYQMHQHRAX/20190221/region/s3/aws4_request, SignedHeaders=host;x-amz-date, Signature=29088b1d6dfeb2549f6ff67bc3744abb7e45475f0ad60400485805415bbfc534

<?xml version='1.0' encoding='utf-8'?>
<AccessControlPolicy>
  <AccessControlList>
    <Grant>
      <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="AmazonCustomerByEmail">
        <EmailAddress>jane@gmail.com</EmailAddress>
      </Grantee>
      <Permission>FULL_CONTROL</Permission>
    </Grant>
  </AccessControlList>
</AccessControlPolicy>

なお、単純な移行のシナリオでは、Authorization ヘッダーで GOOG1 署名 ID を使用することもできます。この場合、Cloud Storage ACL 構文を使用し、すべての x-amz-* ヘッダーが x-goog-* に変更されていることを確認する必要があります。以上の方法も可能ですが、Cloud Storage のすべての利点を実現するため、完全な移行を選択することをおすすめします。

Amazon S3 と XML API の互換性に関するサポート

XML API の相互運用性については、google-cloud-storage タグを使用してスタック オーバーフローを参照してください。

次のステップ