Processo de assinatura V4 com ferramentas do Cloud Storage

Nesta página, você verá como usar o gsutil e as bibliotecas de cliente do Cloud Storage para gerar facilmente URLs assinados. Os URLs assinados fornecem acesso de leitura ou gravação por tempo limitado a um recurso específico do Cloud Storage. Qualquer pessoa que tiver o URL assinado poderá usá-lo enquanto ele estiver ativo, mesmo sem uma conta do Google. Para saber mais sobre URLs assinados, consulte a Visão geral de URLs assinados. Para criar URLs assinados, consulte Processo de assinatura da V4 com seu próprio programa.

Para gerar um URL assinado:

gsutil

  1. Gere uma nova chave privada ou use uma atual de uma conta de serviço. A chave pode estar no formato JSON ou PKCS12.

    Para mais informações sobre chaves privadas e contas de serviço, consulte Contas de serviço.

  2. Use o comando gsutil signurl, passando o caminho para a chave privada da etapa anterior e o nome do intervalo ou objeto para o qual você quer gerar um URL assinado.

    Por exemplo, usando uma chave armazenada na pasta Desktop, o comando a seguir gera um URL assinado para que os usuários visualizem o objeto cat.jpeg por 10 minutos.

    gsutil signurl -d 10m Desktop/private-key.json gs://example-bucket/cat.jpeg

Se bem-sucedida, a resposta será assim:

URL    HTTP Method    Expiration    Signed URL
gs://example-bucket/cat.jpeg GET 2018-10-26 15:19:52 https://storage.googleapis.
com/example-bucket/cat.jpeg?x-goog-signature=2d2a6f5055eb004b8690b9479883292ae74
50cdc15f17d7f99bc49b916f9e7429106ed7e5858ae6b4ab0bbbdb1a8ccc364dad3a0da2caebd308
87a70c5b2569d089ceb8afbde3eed4dff5086f0db5483998c175980991fe899fbd2cd8cb813b0016
5e8d56e0a8aa7b3d7a12ee1baa8400611040f05b50a1a8eab5ba223fe1375747748de950ec7a4dc5
0f8382a6ffd4994ac42498d7daa703d9a414d4475154d0e7edaa92d4f2507d92c1f7e8efa7cab64d
f68b5df48575b9259d8d0bdb5dc752bdf07bd162d98ff2924f2e4a26fa6b3cede73ad5333c47d146
a21c2ab2d97115986a12c68ff37346d6c2ca83e56b8ec8ad95632710b489b75c35697d781c38e&
x-goog-algorithm=GOOG4-RSA-SHA256&x-goog-credential=example%40example-project.
iam.gserviceaccount.com%2F20181026%2Fus%2Fstorage%2Fgoog4_request&x-goog-date=
20181026T211942Z&x-goog-expires=3600&x-goog-signedheaders=host

O URL assinado é a string que começa com https://storage.googleapis.com e provavelmente se estenderá por várias linhas. Este URL pode ser usado por qualquer pessoa para acessar o recurso associado (neste caso, cat.jpeg) no período designado (neste caso, 10 minutos).

Amostras de código

C++

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

O exemplo a seguir cria um URL assinado que pode conseguir um objeto de um intervalo:

namespace gcs = google::cloud::storage;
using ::google::cloud::StatusOr;
[](gcs::Client client, std::string bucket_name, std::string object_name) {
  StatusOr<std::string> signed_url = client.CreateV4SignedUrl(
      "GET", std::move(bucket_name), std::move(object_name),
      gcs::SignedUrlDuration(std::chrono::minutes(15)));

  if (!signed_url) {
    throw std::runtime_error(signed_url.status().message());
  }

  std::cout << "The signed url is: " << *signed_url << "\n\n"
            << "You can use this URL with any user agent, for example:\n"
            << "curl '" << *signed_url << "'\n";
}

O exemplo a seguir cria um URL assinado que pode fazer upload de um objeto para um intervalo:

namespace gcs = google::cloud::storage;
using ::google::cloud::StatusOr;
[](gcs::Client client, std::string bucket_name, std::string object_name) {
  StatusOr<std::string> signed_url = client.CreateV4SignedUrl(
      "PUT", std::move(bucket_name), std::move(object_name),
      gcs::SignedUrlDuration(std::chrono::minutes(15)),
      gcs::AddExtensionHeader("content-type", "application/octet-stream"));

  if (!signed_url) {
    throw std::runtime_error(signed_url.status().message());
  }

  std::cout << "The signed url is: " << *signed_url << "\n\n"
            << "You can use this URL with any user agent, for example:\n"
            << "curl -X PUT -H 'Content-Type: application/octet-stream'"
            << " --upload-file my-file '" << *signed_url << "'\n";
}

C#

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

O exemplo a seguir cria um URL assinado que pode conseguir um objeto de um intervalo:

private void GenerateV4SignedGetUrl(string bucketName, string objectName)
{
    UrlSigner urlSigner = UrlSigner
        .FromServiceAccountPath(Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS"))
        .WithSigningVersion(SigningVersion.V4);
    string url = urlSigner.Sign(bucketName, objectName, TimeSpan.FromHours(1), HttpMethod.Get);
    Console.WriteLine("Generated GET signed URL:");
    Console.WriteLine(url);
    Console.WriteLine("You can use this URL with any user agent, for example:");
    Console.WriteLine($"curl '{url}'");
}

O exemplo a seguir cria um URL assinado que pode fazer upload de um objeto para um intervalo:

        private void GenerateV4SignedPutUrl(string bucketName, string objectName)
        {
            UrlSigner urlSigner = UrlSigner
                .FromServiceAccountPath(Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS"))
                .WithSigningVersion(SigningVersion.V4);

            var contentHeaders = new Dictionary<string, IEnumerable<string>>
            {
                { "Content-Type", new[] { "text/plain" } }
            };

            string url = urlSigner.Sign(bucketName, objectName, TimeSpan.FromHours(1), HttpMethod.Put, contentHeaders);
            Console.WriteLine("Generated PUT signed URL:");
            Console.WriteLine(url);
            Console.WriteLine("You can use this URL with any user agent, for example:");
            Console.WriteLine($"curl -X PUT -H 'Content-Type: text/plain' --upload-file my-file '{url}'");
        }

Go

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

O exemplo a seguir cria um URL assinado que pode conseguir um objeto de um intervalo:

jsonKey, err := ioutil.ReadFile(serviceAccount)
if err != nil {
	return "", fmt.Errorf("cannot read the JSON key file, err: %v", err)
}

conf, err := google.JWTConfigFromJSON(jsonKey)
if err != nil {
	return "", fmt.Errorf("google.JWTConfigFromJSON: %v", err)
}

opts := &storage.SignedURLOptions{
	Scheme:         storage.SigningSchemeV4,
	Method:         "GET",
	GoogleAccessID: conf.Email,
	PrivateKey:     conf.PrivateKey,
	Expires:        time.Now().Add(15 * time.Minute),
}

u, err := storage.SignedURL(bucketName, objectName, opts)
if err != nil {
	return "", fmt.Errorf("Unable to generate a signed URL: %v", err)
}

fmt.Fprintln(w, "Generated GET signed URL:")
fmt.Fprintf(w, "%q\n", u)
fmt.Fprintln(w, "You can use this URL with any user agent, for example:")
fmt.Fprintf(w, "curl %q\n", u)

O exemplo a seguir cria um URL assinado que pode fazer upload de um objeto para um intervalo:

jsonKey, err := ioutil.ReadFile(serviceAccount)
if err != nil {
	return "", fmt.Errorf("cannot read the JSON key file, err: %v", err)
}
conf, err := google.JWTConfigFromJSON(jsonKey)
if err != nil {
	return "", fmt.Errorf("google.JWTConfigFromJSON: %v", err)
}

opts := &storage.SignedURLOptions{
	Scheme: storage.SigningSchemeV4,
	Method: "PUT",
	Headers: []string{
		"Content-Type:application/octet-stream",
	},
	GoogleAccessID: conf.Email,
	PrivateKey:     conf.PrivateKey,
	Expires:        time.Now().Add(15 * time.Minute),
}

u, err := storage.SignedURL(bucketName, objectName, opts)
if err != nil {
	return "", fmt.Errorf("Unable to generate a signed URL: %v", err)
}

fmt.Fprintln(w, "Generated PUT signed URL:")
fmt.Fprintf(w, "%q\n", u)
fmt.Fprintln(w, "You can use this URL with any user agent, for example:")
fmt.Fprintf(w, "curl -X PUT -H 'Content-Type: application/octet-stream' --upload-file my-file %q\n", u)

Java

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

O exemplo a seguir cria um URL assinado que pode conseguir um objeto de um intervalo:

import com.google.cloud.storage.BlobId;
import com.google.cloud.storage.BlobInfo;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageException;
import com.google.cloud.storage.StorageOptions;
import java.net.URL;
import java.util.concurrent.TimeUnit;

public class GenerateV4GetObjectSignedUrl {
  public static void generateV4GetObjectSignedUrl(
      String projectId, String bucketName, String objectName) throws StorageException {
    // String projectId = "my-project-id";
    // String bucketName = "my-bucket";
    // String objectName = "my-object";

    Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService();

    // Define resource
    BlobInfo blobInfo = BlobInfo.newBuilder(BlobId.of(bucketName, objectName)).build();

    /**
     * Signing a URL requires Credentials which implement ServiceAccountSigner. These can be set
     * explicitly using the Storage.SignUrlOption.signWith(ServiceAccountSigner) option. If you
     * don't, you could also pass a service account signer to StorageOptions, i.e.
     * StorageOptions().newBuilder().setCredentials(ServiceAccountSignerCredentials). In this
     * example, neither of these options are used, which means the following code only works when
     * the credentials are defined via the environment variable GOOGLE_APPLICATION_CREDENTIALS, and
     * those credentials are authorized to sign a URL. See the documentation for Storage.signUrl for
     * more details.
     */
    URL url =
        storage.signUrl(blobInfo, 15, TimeUnit.MINUTES, Storage.SignUrlOption.withV4Signature());

    System.out.println("Generated GET signed URL:");
    System.out.println(url);
    System.out.println("You can use this URL with any user agent, for example:");
    System.out.println("curl '" + url + "'");
  }
}

O exemplo a seguir cria um URL assinado que pode fazer upload de um objeto para um intervalo:

import com.google.cloud.storage.BlobId;
import com.google.cloud.storage.BlobInfo;
import com.google.cloud.storage.HttpMethod;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageException;
import com.google.cloud.storage.StorageOptions;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

public class GenerateV4PutObjectSignedUrl {
  public static void generateV4GPutObjectSignedUrl(
      String projectId, String bucketName, String objectName) throws StorageException {
    // String projectId = "my-project-id";
    // String bucketName = "my-bucket";
    // String objectName = "my-object";

    Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService();

    // Define Resource
    BlobInfo blobInfo = BlobInfo.newBuilder(BlobId.of(bucketName, objectName)).build();

    // Generate Signed URL
    Map<String, String> extensionHeaders = new HashMap<>();
    extensionHeaders.put("Content-Type", "application/octet-stream");

    /**
     * Signing a URL requires Credentials which implement ServiceAccountSigner. These can be set
     * explicitly using the Storage.SignUrlOption.signWith(ServiceAccountSigner) option. If you
     * don't, you could also pass a service account signer to StorageOptions, i.e.
     * StorageOptions().newBuilder().setCredentials(ServiceAccountSignerCredentials). In this
     * example, neither of these options are used, which means the following code only works when
     * the credentials are defined via the environment variable GOOGLE_APPLICATION_CREDENTIALS, and
     * those credentials are authorized to sign a URL. See the documentation for Storage.signUrl for
     * more details.
     */
    URL url =
        storage.signUrl(
            blobInfo,
            15,
            TimeUnit.MINUTES,
            Storage.SignUrlOption.httpMethod(HttpMethod.PUT),
            Storage.SignUrlOption.withExtHeaders(extensionHeaders),
            Storage.SignUrlOption.withV4Signature());

    System.out.println("Generated PUT signed URL:");
    System.out.println(url);
    System.out.println("You can use this URL with any user agent, for example:");
    System.out.println(
        "curl -X PUT -H 'Content-Type: application/octet-stream' --upload-file my-file '"
            + url
            + "'");
  }
}

Node.js

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

O exemplo a seguir cria um URL assinado que pode conseguir um objeto de um intervalo:

// Imports the Google Cloud client library
const {Storage} = require('@google-cloud/storage');

// Creates a client
const storage = new Storage();

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const bucketName = 'Name of a bucket, e.g. my-bucket';
// const filename = 'File to access, e.g. file.txt';

// These options will allow temporary read access to the file
const options = {
  version: 'v4',
  action: 'read',
  expires: Date.now() + 15 * 60 * 1000, // 15 minutes
};

// Get a v4 signed URL for reading the file
const [url] = await storage
  .bucket(bucketName)
  .file(filename)
  .getSignedUrl(options);

console.log('Generated GET signed URL:');
console.log(url);
console.log('You can use this URL with any user agent, for example:');
console.log(`curl '${url}'`);

O exemplo a seguir cria um URL assinado que pode fazer upload de um objeto para um intervalo:

// Imports the Google Cloud client library
const {Storage} = require('@google-cloud/storage');

// Creates a client
const storage = new Storage();

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const bucketName = 'Name of a bucket, e.g. my-bucket';
// const filename = 'File to access, e.g. file.txt';

// These options will allow temporary uploading of the file with outgoing
// Content-Type: application/octet-stream header.
const options = {
  version: 'v4',
  action: 'write',
  expires: Date.now() + 15 * 60 * 1000, // 15 minutes
  contentType: 'application/octet-stream',
};

// Get a v4 signed URL for uploading file
const [url] = await storage
  .bucket(bucketName)
  .file(filename)
  .getSignedUrl(options);

console.log('Generated PUT signed URL:');
console.log(url);
console.log('You can use this URL with any user agent, for example:');
console.log(
  "curl -X PUT -H 'Content-Type: application/octet-stream' " +
    `--upload-file my-file '${url}'`
);

PHP

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

O exemplo a seguir cria um URL assinado que pode conseguir um objeto de um intervalo:

use Google\Cloud\Storage\StorageClient;

/**
 * Generate a v4 signed URL for downloading an object.
 *
 * @param string $bucketName the name of your Google Cloud bucket.
 * @param string $objectName the name of your Google Cloud object.
 *
 * @return void
 */
function get_object_v4_signed_url($bucketName, $objectName)
{
    $storage = new StorageClient();
    $bucket = $storage->bucket($bucketName);
    $object = $bucket->object($objectName);
    $url = $object->signedUrl(
        # This URL is valid for 15 minutes
        new \DateTime('15 min'),
        [
            'version' => 'v4',
        ]
    );

    print('Generated GET signed URL:' . PHP_EOL);
    print($url . PHP_EOL);
    print('You can use this URL with any user agent, for example:' . PHP_EOL);
    print('curl ' . $url . PHP_EOL);
}

O exemplo a seguir cria um URL assinado que pode fazer upload de um objeto para um intervalo:

use Google\Cloud\Storage\StorageClient;

/**
 * Generate a v4 signed URL for uploading an object.
 *
 * @param string $bucketName the name of your Google Cloud bucket.
 * @param string $objectName the name of your Google Cloud object.
 *
 * @return void
 */
function upload_object_v4_signed_url($bucketName, $objectName)
{
    $storage = new StorageClient();
    $bucket = $storage->bucket($bucketName);
    $object = $bucket->object($objectName);
    $url = $object->signedUrl(
        # This URL is valid for 15 minutes
        new \DateTime('15 min'),
        [
            'method' => 'PUT',
            'contentType' => 'application/octet-stream',
            'version' => 'v4',
        ]
    );

    print('Generated PUT signed URL:' . PHP_EOL);
    print($url . PHP_EOL);
    print('You can use this URL with any user agent, for example:' . PHP_EOL);
    print("curl -X PUT -H 'Content-Type: application/octet-stream' " .
        '--upload-file my-file ' . $url . PHP_EOL);
}

Python

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

O exemplo a seguir cria um URL assinado que pode conseguir um objeto de um intervalo:

from google.cloud import storage
import datetime

def generate_download_signed_url_v4(bucket_name, blob_name):
    """Generates a v4 signed URL for downloading a blob.

    Note that this method requires a service account key file. You can not use
    this if you are using Application Default Credentials from Google Compute
    Engine or from the Google Cloud SDK.
    """
    # bucket_name = 'your-bucket-name'
    # blob_name = 'your-object-name'

    storage_client = storage.Client()
    bucket = storage_client.bucket(bucket_name)
    blob = bucket.blob(blob_name)

    url = blob.generate_signed_url(
        version="v4",
        # This URL is valid for 15 minutes
        expiration=datetime.timedelta(minutes=15),
        # Allow GET requests using this URL.
        method="GET",
    )

    print("Generated GET signed URL:")
    print(url)
    print("You can use this URL with any user agent, for example:")
    print("curl '{}'".format(url))
    return url

O exemplo a seguir cria um URL assinado que pode fazer upload de um objeto para um intervalo:

from google.cloud import storage
import datetime

def generate_upload_signed_url_v4(bucket_name, blob_name):
    """Generates a v4 signed URL for uploading a blob using HTTP PUT.

    Note that this method requires a service account key file. You can not use
    this if you are using Application Default Credentials from Google Compute
    Engine or from the Google Cloud SDK.
    """
    # bucket_name = 'your-bucket-name'
    # blob_name = 'your-object-name'

    storage_client = storage.Client()
    bucket = storage_client.bucket(bucket_name)
    blob = bucket.blob(blob_name)

    url = blob.generate_signed_url(
        version="v4",
        # This URL is valid for 15 minutes
        expiration=datetime.timedelta(minutes=15),
        # Allow GET requests using this URL.
        method="PUT",
        content_type="application/octet-stream",
    )

    print("Generated PUT signed URL:")
    print(url)
    print("You can use this URL with any user agent, for example:")
    print(
        "curl -X PUT -H 'Content-Type: application/octet-stream' "
        "--upload-file my-file '{}'".format(url)
    )
    return url

Ruby

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

O exemplo a seguir cria um URL assinado que pode conseguir um objeto de um intervalo:

# project_id  = "Your Google Cloud project ID"
# bucket_name = "Your Google Cloud Storage bucket name"
# file_name   = "Name of a file in the Google Cloud Storage bucket"
require "google/cloud/storage"

storage = Google::Cloud::Storage.new project_id: project_id
storage_expiry_time = 5 * 60 # 5 minutes

url = storage.signed_url bucket_name, file_name, method: "GET",
                         expires: storage_expiry_time, version: :v4

puts "Generated GET signed url:"
puts url
puts "You can use this URL with any user agent, for example:"
puts "curl #{url}"

O exemplo a seguir cria um URL assinado que pode fazer upload de um objeto para um intervalo:

# project_id  = "Your Google Cloud project ID"
# bucket_name = "Your Google Cloud Storage bucket name"
# file_name   = "Name of a file in the Cloud Storage bucket"
require "google/cloud/storage"

storage = Google::Cloud::Storage.new project_id: project_id
storage_expiry_time = 5 * 60 # 5 minutes

url = storage.signed_url bucket_name, file_name, method: "PUT",
                         expires: storage_expiry_time, version: :v4,
                         headers: { "Content-Type" => "text/plain" }
puts "Generated PUT signed URL:"
puts url
puts "You can use this URL with any user agent, for example:"
puts "curl -X PUT -H 'Content-Type: text/plain' --upload-file my-file '#{url}'"