6
votes

I am trying to transfer data from S3 to GCS by using a Java client but I got this error.

Failed to obtain the location of the Google Cloud Storage (GCS) bucket ___ due to insufficient permissions. Please verify that the necessary permissions have been granted.

I am using a service account with the Project Owner role, which should grant unlimited access to all project resources.

3

3 Answers

15
votes

Google Transfer Service is using an internal service account to move the data back and forth. This account is created automatically and should not be confused with the service accounts you create yourself.

You need to give this user a permission called "Legacy bucket writer".

This is written in the documentation, but it's VERY easy to miss:

https://cloud.google.com/storage-transfer/docs/configure-access

0
votes

Thanks to @thnee's comment I was able to piece together a terraform script that adds the permissions to the hidden Storage Transfer service account:

data "google_project" "project" {}

locals {
  // the project number is also available from the Project Info section on the Dashboard
  transfer_service_id = "project-${data.google_project.project.number}@storage-transfer-service.iam.gserviceaccount.com"
}

resource "google_storage_bucket" "backups" {
  location      = "us-west1"
  name          = "backups"
  storage_class = "REGIONAL"
}

data "google_iam_policy" "transfer_job" {
  binding {
    role = "roles/storage.legacyBucketReader"

    members = [
      "serviceAccount:${local.transfer_service_id}",
    ]
  }

  binding {
    role = "roles/storage.objectAdmin"

    members = [
      "serviceAccount:${local.transfer_service_id}",
    ]
  }

  binding {
    role = "roles/storage.admin"

    members = [
      "user:<GCP console user>",
      "serviceAccount:<terraform user doing updates>",
    ]
  }
}

resource "google_storage_bucket_iam_policy" "policy" {
  bucket      = "${google_storage_bucket.backups.name}"
  policy_data = "${data.google_iam_policy.transfer_job.policy_data}"
}

Note that this removes the default acls of OWNER and READER present on the bucket. This would prevent you from being able to access the bucket in the console. We therefore add the roles/storage.admin back to owner users and the terraform service account that's doing the change.

0
votes

The service account's format is typically project-PROJECT_NUMBER@storage-transfer-service.iam.gserviceaccount.com. To find your service account's format, use the googleServiceAccounts.get API call. If you don't find it, use the aforementioned convention to assign the roles below (worked for me)

Then assign it the roles:

roles/storage.objectViewer  
roles/storage.legacyBucketReader    
roles/storage.legacyBucketWriter