Migração simples do Amazon S3 para o Cloud Storage

Nesta página, descrevemos como concluir uma migração simples do Amazon Simple Storage Service (Amazon S3) para o Cloud Storage. Em uma migração simples, use as ferramentas e bibliotecas existentes para gerar solicitações REST autenticadas para o Amazon S3 e para enviar solicitações autenticadas para o Cloud Storage.

Se você é novo no Cloud Storage e não usa a API diretamente, considere o uso do Console do Google Cloud para definir e gerenciar transferências. O Console do Google Cloud fornece uma interface gráfica para o Cloud Storage que permite realizar muitas tarefas de armazenamento usando apenas um navegador, incluindo a migração de dados do Amazon S3 para o Cloud Storage.

Se você quiser que o Cloud Storage armazene um backup dos seus dados do Amazon S3, use as transferências orientadas a eventos, que usam as notificações de eventos do Amazon S3 para manter automaticamente um bucket do Cloud Storage sincronizado com a fonte do Amazon S3.

Migrar do Amazon S3 para o Cloud Storage em um cenário de migração simples

Para fazer solicitações ao Cloud Storage, siga estas etapas:

  • Defina um projeto padrão do Google Cloud.
  • Gere uma chave de código de autenticação de mensagem baseada em hash (HMAC).
  • Nas ferramentas ou bibliotecas atuais, faça as alterações a seguir:

    • Alterar endpoint de solicitações para usar o endpoint de solicitações da API XML do Cloud Storage.
    • Substitua o acesso e a chave secreta do Amazon Web Services pelo código de acesso e secret do Cloud Storage correspondente (coletivamente chamado de chave HMAC do Cloud Storage).
    • Verifique se seus cabeçalhos x-amz- usam valores do Cloud Storage compatíveis. Por exemplo, x-amz-storage-class deve usar uma das classes de armazenamento do Cloud Storage disponíveis.

      Ao usar a API XML do Cloud Storage na migração simples, especifique o identificador de assinatura AWS no cabeçalho Authorization para que o Cloud Storage espere receber cabeçalhos x-amz-* e a sintaxe XML de lista de controle de acesso (ACL, na sigla em inglês) do Amazon S3 na solicitação. O Cloud Storage processa cabeçalhos x-amz-* que tenham um equivalente de x-goog-*, como os listados na tabela de cabeçalhos.

Depois de fazer essas mudanças, comece a usar suas ferramentas e bibliotecas existentes para enviar solicitações HMAC ao Cloud Storage.

Por exemplo: nas amostras a seguir, demonstramos como listar buckets do Cloud Storage usando o SDK do Amazon S3:

Go

Para mais informações, consulte a documentação de referência da API Cloud Storage Go.

Para autenticar no Cloud Storage, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

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

Para mais informações, consulte a documentação de referência da API Cloud Storage Java.

Para autenticar no Cloud Storage, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

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

Para mais informações, consulte a documentação de referência da API Cloud Storage Python.

Para autenticar no Cloud Storage, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

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

Configurar um projeto padrão

Para usar o Cloud Storage em um cenário de migração simples, é recomendável definir um projeto padrão, usado pelo Cloud Storage para executar determinadas operações, como Serviço GET ou bucket PUT. Se um projeto padrão não for definido, você deverá especificar um cabeçalho de projeto em determinadas solicitações.

Para definir um projeto padrão:

  1. Abra a página Configurações do Cloud Storage no Console do Google Cloud.
  2. Selecione a guia Interoperabilidade.
  3. Clique em Definir PROJECT-ID como projeto padrão, localizado na seção Projeto padrão para acesso interoperável.

    Se o projeto já for o padrão, você verá PROJECT-ID como o projeto padrão para acesso interoperável.

Agora, esse é seu projeto padrão. É possível alterar o projeto padrão a qualquer momento, basta escolher um projeto diferente e seguir as mesmas etapas.

Como alternativa, especifique um cabeçalho de projeto

Em vez de, ou além de, definir um projeto padrão, é possível usar o cabeçalho x-amz-project-id em solicitações individuais que exigem que um projeto seja especificado.

  • Uma solicitação que usa x-amz-project-id usa o projeto especificado no cabeçalho, mesmo que haja um projeto padrão atual.

O cabeçalho x-amz-project-id é útil quando:

  • estiver trabalhando com vários projetos;
  • suas solicitações são feitas por uma conta de serviço associada a um projeto diferente, já que as contas de serviço usam o projeto pai como padrão.

Observe que o Amazon S3 não tem projetos. Portanto, dependendo das ferramentas ou bibliotecas de cliente usadas, especificar um cabeçalho x-amz-project-id pode não ser uma opção. Nesse caso, defina um projeto padrão.

Usar chaves HMAC

Para usar a API XML do Cloud Storage na migração simples, use as chaves de código de autenticação de mensagem com base em hash (HMAC) do Cloud Storage para as credenciais. Normalmente, é preciso criar uma chave HMAC que esteja associada a uma conta de serviço. No entanto, é possível usar uma conta associada a uma conta de usuário.

Autenticar no cenário de migração simples

Usar o cabeçalho de autorização

Na migração simples, para as operações que exigem autenticação, inclua um cabeçalho de solicitação Authorization do mesmo modo como é feito para solicitações ao Amazon S3. A sintaxe do cabeçalho Authorization na solicitação do Amazon S3 é:

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

Em um cenário de migração simples, você só altera o cabeçalho para usar seu ID de acesso HMAC do Cloud Storage e verifica se a Signature anexada é calculada com sua chave secreta HMAC do Cloud Storage:

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

As partes do cabeçalho Authorization são:

  • ALGORITHM: o algoritmo de assinatura e a versão usada. Usar AWS4-HMAC-SHA256 indica que você está utilizando uma assinatura HMAC V4 e pretende enviar cabeçalhos x-amz-*. Também é possível usar GOOG4-HMAC-SHA256, que indica que você está usando uma assinatura HMAC V4 e pretende enviar cabeçalhos x-goog-*.

  • GOOG-ACCESS-ID: o ID de acesso identifica a entidade que faz e assina a solicitação. Em uma migração simples, substitua o ID da chave de acesso da Amazon Web Service (AWS) que você usa para acessar o Amazon S3 pelo ID de acesso HMAC do Cloud Storage. Seu ID de acesso HMAC do Cloud Storage começa com GOOG.

  • CREDENTIAL_SCOPE: o escopo da credencial, conforme definido na assinatura. Em uma migração simples, não é necessário alterar o escopo da credencial se você estiver usando AWS4-HMAC-SHA256 como valor ALGORITHM.

  • SIGNED_HEADERS: uma lista separada por ponto-e-vírgula de nomes de cabeçalhos que precisam ser incluídos para assinar essa solicitação. Todos os cabeçalhos precisam ser em letra minúscula e classificados por código de caractere.

    Veja abaixo um exemplo de string de cabeçalho assinada no estilo do Amazon S3:

    content-type;host;x-amz-date

    Na migração simples, não é necessário fazer qualquer alteração na string de cabeçalho assinada.

  • SIGNATURE: a assinatura que permite que a solicitação seja autenticada. Em uma migração simples, substitua as informações da chave de acesso da AWS pelas informações equivalentes da chave HMAC do Cloud Storage.

Exemplo de solicitação de autenticação

Os exemplos a seguir fazem upload de um objeto chamado /europe/france/paris.jpg em um bucket chamado my-travel-maps, aplicam a ACL public-read predefinida e definem um cabeçalho de metadados personalizado para revisores. Veja abaixo uma solicitação para um bucket no 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

Esta é uma solicitação para um bucket no 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

Esta é uma solicitação canônica correspondente que foi criada para a solicitação acima:

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

Esta é a string a ser assinada correspondente, criada para a solicitação:

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

A solicitação não forneceu um cabeçalho Content-MD5, portanto, uma string vazia é mostrada na segunda linha da mensagem.

Controle de acesso na migração simples

Para possibilitar as migrações simples, o Cloud Storage aceita ACLs produzidas pelo Amazon S3. Na migração simples, use AWS como o identificador de assinatura, para que o Cloud Storage saiba que receberá a sintaxe XML de ACL do Amazon S3. É necessário garantir que as ACLs do Amazon S3 usadas sejam mapeadas para o modelo de ACLs do Cloud Storage. Por exemplo, se suas ferramentas e bibliotecas usarem a sintaxe de ACL do Amazon S3 para conceder permissão WRITE ao bucket, elas também precisarão conceder permissão READ ao bucket, já que as permissões do Cloud Storage são concêntricas. Não é necessário especificar as duas permissões WRITE e READ ao conceder permissão WRITE usando a sintaxe do Cloud Storage.

O Cloud Storage aceita a sintaxe de ACL do Amazon S3 nos cenários a seguir:

  • Na solicitação ao Cloud Storage para recuperar ACLs (por exemplo, uma solicitação de objeto GET ou bucket GET), o Cloud Storage retorna a sintaxe de ACL do Amazon S3.
  • Na solicitação ao Cloud Storage para aplicar ACLs (por exemplo, uma solicitação de objeto PUT ou bucket PUT), o Cloud Storage espera receber a sintaxe de ACL do Amazon S3.

O cabeçalho Authorization na migração simples usa AWS para o identificador de assinatura, mas com seu código de acesso do Google.

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

O exemplo a seguir mostra uma solicitação GET ao Cloud Storage para retornar as ACLs de um objeto.

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

A resposta à solicitação inclui a ACL usando a sintaxe de ACL do Amazon S3.

<?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>

O exemplo a seguir mostra uma solicitação PUT ao Cloud Storage para definir as ACLs de um objeto. O exemplo mostra um corpo de solicitação com a sintaxe de ACL do Amazon S3.

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>

Por fim, na migração simples, também é possível usar o identificador de assinatura GOOG1 no cabeçalho Authorization. Nesse caso, é necessário usar a sintaxe de Access Control List do Cloud Storage e garantir que todos os cabeçalhos x-amz-* sejam alterados para x-goog-*. Embora isso seja possível, recomendamos que você escolha uma migração completa para usar todos os benefícios do Cloud Storage.

Compatibilidade da API XML com o Amazon S3

Para discussões sobre a interoperabilidade da API XML, consulte o Stack Overflow usando a tag google-cloud-storage.

A seguir