0
votes

The ACL after uploading an object to Google Cloud Storage is overwritten each time.

I'm creating BlobInfo with preset ACL, so that the uploaded object have to be public read:

 String blobId = "PUBLIC/1";
 com.google.cloud.storage.BlobInfo info = com.google.cloud.storage.BlobInfo.newBuilder(RuntimeConfig.USERDATA_BUCKET_NAME, blobId)
                .setContentType(mimetype)
                .setMetadata(metadata)
                .setAcl(new ArrayList<>(Arrays.asList(Acl.of(Acl.User.ofAllUsers(), Acl.Role.READER)))) // <-- HERE
                .build();

After this I'm signing the URL, like this:

URL signedUrl = storage.signUrl(info, 30,
                    TimeUnit.MINUTES,
                    Storage.SignUrlOption.httpMethod(com.google.cloud.storage.HttpMethod.valueOf("PUT")),
                    Storage.SignUrlOption.withContentType());

Then, I'm uploading the file from the web and this works fine, with only one problem - there is no ACL with public read.

Of course, I can change the ACL after the upload is done, like this:

storage.createAcl(info.getBlobId(), (Acl.of(Acl.User.ofAllUsers(), Acl.Role.READER)));

But is there a way to set it directly within the signed URL, without an additional trigger from the web after having successfully uploaded it?

Thanks!

1

1 Answers

0
votes

Signed URLs vs ACLs ( aka. Access Control Lists)

Access Control Lists (ACLs) and Signed URLs (query string authentication) are not the same thing.

While they both provide control of who has access to your Cloud Storage buckets and objects as well as as what level of access they have, ACLs grant read or write access to users for individual buckets or objects. In most instances, Cloud IAM permissions are used over ACLs since the latter are only used when fine-grained control over individual objects is needed.

On the other hand, Signed URLs provide time-limited read or write access to an object through a generated URL. Anyone who has this URL will have access to the object for a certain duration of time that is specified.

Therefore, I'm not aware of any way to implement ACLs directly within Signed URLs to answer your question.


Managing your ACLs

From Documentation:

To avoid setting ACLs every time you create a new object, you can set a default object ACL on a bucket. After you do this, every new object that is added to that bucket that does not explicitly have an ACL applied to it will have the default applied to it.


Changing the default object ACL

The following sample adds a default object ACL to a bucket:

Acl acl = storage.createDefaultAcl(bucketName, Acl.of(User.ofAllAuthenticatedUsers(), Role.READER));

The following sample deletes a default object ACL from a bucket:

boolean deleted = storage.deleteDefaultAcl(bucketName, User.ofAllAuthenticatedUsers());
if (deleted) {
  // the acl entry was deleted
} else {
  // the acl entry was not found
}

Propagation Details

If you change the default object ACL for a bucket, the change may take time to propagate, and new objects created in the bucket may still get the old default object ACL for a short period of time. In order to make sure that new objects created in the bucket get the updated default object ACL, you should wait at least 30 seconds between changing the default object ACL and creating new objects.