3

I am using gsutil to create pre-signed URLs for upload. When naming the object in the bucket, I can successfully upload. The following snipit from gsutil works fine with a curl PUT:

gsutil signurl -m PUT -d 10m -r eu ~/.ssh/mycreds.json gs://cjreyn-bucket-0/myobjectname.txt

However, when specifying just the bucket name, instead of an object within it, uploading an arbitrary object doesn't work:

gsutil signurl -m PUT -d 10m -r eu ~/.ssh/mycreds.json gs://cjreyn-bucket-0/

This returns the follwing from curl:

<?xml version='1.0' encoding='UTF-8'?><Error><Code>BucketAlreadyOwnedByYou</Code><Message>Your previous request to create the named bucket succeeded and you already own it.</Message></Error>

My curl line is as follows (signed URL replaced with for brevity):

curl -X PUT --upload-file myobj.txt "<mysignedurl>"

Is it even possible to create signed URLs for upload and download to/from the whole bucket, rather than for each object within it?

Chris
  • 617
  • 2
  • 6
  • 18

2 Answers2

7

No, this isn't possible.

A signed URL authorizes exactly one specific request, which is transformed to its canonical form before signing. The service then assembles the same representation and calculates what the signature should have been, and at that point there's only one correct answer for what the valid signature can be for a given verb (e.g. PUT), resource (bucket + key), set of credentials, timestamp, and expiration.

The signature doesn't actually include a copy of the request parameters being authorized -- they're inferred from the request when it is made -- so there is no mechanism for passing any information to the service that could be used to specify e.g. that a wildcard path should be allowed.

Signing a PUT URL for the bucket itself authorizes the bearer of that URL to send a request to create a bucket with that name, as implied by the error you received.

One solution is to create a web service which responds to an authorized request (whatever that might mean in your environment, e.g. based on a user's web cookie) with a pre-signed URL for the parameters supplied in the request, once the web service validates them. Keep in mind that if this is a web site or an app that needs to be writing to the bucket, you can never trust those things to only make reasonable/safe requests, because they are outside your control -- so parameter validation would be critical to avoid malicious actions.

Another option might be awscurl which a curl-like tool that does its own request signing. GCS has an AWS-compatibility mode, so this might mean you can use this tool, as-is, or perhaps it can be adapted or perhaps there's a comparable tool for GCS. But I assume you need the signed URL elsewhere, not the local machine, otherwise you would just be using gsutil to do the upload.

Michael - sqlbot
  • 169,571
  • 25
  • 353
  • 427
0

It is impossible to do because a pre-signed URL is valid for one object only.