Processus de signature V4 avec les outils Cloud Storage

Cette page explique comment utiliser gsutil et les bibliothèques clientes Cloud Storage pour générer facilement des URL signées. Les URL signées accordent un accès en lecture ou en écriture limité dans le temps à une ressource Cloud Storage spécifique. Toute personne disposant de l'URL signée peut l'utiliser lorsqu'elle est active, qu'elle possède ou non un compte Google. Pour en savoir plus sur les URL signées, consultez la présentation des URL signées. Pour créer vos propres URL signées, consultez la page Processus de signature V4 avec votre propre programme.

Pour générer une URL signée, procédez comme suit :

gsutil

  1. Générez une nouvelle clé privée ou utilisez une clé privée existante pour un compte de service. Elle peut être au format JSON ou PKCS12.

    Pour en savoir plus sur les clés privées et les comptes de service, consultez la page Comptes de service.

  2. Utilisez la commande gsutil signurl, en transmettant le chemin d'accès à la clé privée de l'étape précédente et le nom du bucket ou de l'objet pour lequel vous souhaitez générer une URL signée.

    Par exemple, si vous utilisez une clé stockée dans le dossier Desktop, la commande suivante génère une URL signée permettant aux utilisateurs d'afficher l'objet cat.jpeg pendant 10 minutes.

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

En cas de réussite, la réponse doit se présenter comme suit :

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

L'URL signée est la chaîne commençant par https://storage.googleapis.com. Il est probable qu'elle s'étende sur plusieurs lignes. Toute personne disposant de cette URL peut accéder à la ressource associée (dans le cas présent, cat.jpeg) pendant la période indiquée (ici, 10 minutes).

Exemples de code

C++

Pour en savoir plus, consultez la documentation de référence de l'API Cloud Storage en langage C++.

L'exemple suivant crée une URL signée permettant d'extraire un objet d'un bucket :

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";
}

L'exemple suivant crée une URL signée permettant d'importer un objet dans un bucket :

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#

Pour en savoir plus, consultez la documentation de référence de l'API Cloud Storage en langage C#.

L'exemple suivant crée une URL signée permettant d'extraire un objet d'un bucket :

private void GenerateV4SignedGetUrl(string bucketName, string objectName)
{
    UrlSigner urlSigner = UrlSigner
        .FromServiceAccountPath(Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS"));
    string url = urlSigner.Sign(bucketName, objectName, TimeSpan.FromHours(1), HttpMethod.Get, SigningVersion.V4);
    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}'");
}

L'exemple suivant crée une URL signée permettant d'importer un objet dans un bucket :

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

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

            UrlSigner.Options options = UrlSigner.Options
                .FromDuration(TimeSpan.FromHours(1))
                .WithSigningVersion(SigningVersion.V4);
            UrlSigner.RequestTemplate template = UrlSigner.RequestTemplate
                .FromBucket(bucketName)
                .WithObjectName(objectName)
                .WithHttpMethod(HttpMethod.Put)
                .WithContentHeaders(contentHeaders);

            string url = urlSigner.Sign(template, options);
            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

Pour en savoir plus, consultez la documentation de référence de l'API Cloud Storage en langage Go.

L'exemple suivant crée une URL signée permettant d'extraire un objet d'un bucket :

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)

L'exemple suivant crée une URL signée permettant d'importer un objet dans un bucket :

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

Pour en savoir plus, consultez la documentation de référence de l'API Cloud Storage en langage Java.

L'exemple suivant crée une URL signée permettant d'extraire un objet d'un bucket :

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 + "'");
  }
}

L'exemple suivant crée une URL signée permettant d'importer un objet dans un bucket :

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

Pour en savoir plus, consultez la documentation de référence de l'API Cloud Storage en langage Node.js.

L'exemple suivant crée une URL signée permettant d'extraire un objet d'un bucket :

/**
 * 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';

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

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

async function generateV4ReadSignedUrl() {
  // 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}'`);
}

generateV4ReadSignedUrl().catch(console.error);

L'exemple suivant crée une URL signée permettant d'importer un objet dans un bucket :

/**
 * 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';

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

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

async function generateV4UploadSignedUrl() {
  // 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}'`
  );
}

generateV4UploadSignedUrl().catch(console.error);

PHP

Pour en savoir plus, consultez la documentation de référence de l'API Cloud Storage en langage PHP.

L'exemple suivant crée une URL signée permettant d'extraire un objet d'un bucket :

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);
}

L'exemple suivant crée une URL signée permettant d'importer un objet dans un bucket :

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

Pour en savoir plus, consultez la documentation de référence de l'API Cloud Storage en langage Python.

L'exemple suivant crée une URL signée permettant d'extraire un objet d'un bucket :

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

L'exemple suivant crée une URL signée permettant d'importer un objet dans un bucket :

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

Pour en savoir plus, consultez la documentation de référence de l'API Cloud Storage en langage Ruby.

L'exemple suivant crée une URL signée permettant d'extraire un objet d'un bucket :

# 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
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}"

L'exemple suivant crée une URL signée permettant d'importer un objet dans un bucket :

# 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
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}'"