0
votes

I'm trying to get user uploads direct to Google Cloud Storage from my app on AppEngine Flex (PHP 7.2). The code works locally (not using the GCP local dev server) but when I upload the code to AppEngine and open the page/view I get a 500 error. Wondering if anyone with more experience with GCP and GCS can point out what I'm doing wrong?

I put debugging statements (removed for brevity) into the live server code and I can see these stop directly before I call $object->beginSignedUploadSession() (see code below).

$config = [
    'projectId' => 'my-project-id'
];

$storage = new StorageClient($config);
$bucket = $storage->bucket('my-project-id.appspot.com'); 
$object = $bucket->object('csv_data/tmpcsvdata-' . $model->file_hash . '.csv');

$upload_url = $object->beginSignedUploadSession();

Locally this correctly generates the signed upload URL so I can insert it into the view and thereafter the AJAX takes care of uploading the user's file to GCS. Live, the application error handler (Yii2) returns Error(#403) but it presents no other details. The AppEngine logs don't show any information other than Error 500.

On the assumption that #403 might mean Forbidden and that the issue was with credentials I've re-checked this but it seems fine since I assume I don't need to provide a keyFile or keyFilePath because it's on AppEngine (unlike when I do it locally).

I've done some fairly extensive searches but can't find anything that seems to relate.

Any suggestions would be greatly appreciated.

Update

Managed to get some more error details. The error message is "IAM Service Account Credentials API has not been used in project XXXX" and the exception is "GuzzleHttp\Exception\ClientException". So it seems it is a 403 Forbidden and I guess must be credentials related but I'm still not sure how I should fix this.

2
Please check this link for the same issue: stackoverflow.com/questions/56157511/… - Jaroslav
The previous comment is incorrect. You should not manually create a service account for AppEngine applications. - jdp

2 Answers

1
votes

Make sure your AppEngine service account has the iam.serviceAccounts.signBlob permission. You can get it by granting the Service Account Token Creator role. Click here for a guide to granting access.

0
votes

In the end I solved my issue by uploading my service account JSON credentials file to the AppEngine in my deploy.

I had previously included this in the .gcloudignore file and wasn't using it in the live config for the StorageClient based on my understanding of the documentation for AppEngien and Cloud Storage which seemed to imply that credentials would be automatically detected by AppEngine and applied as necessary.

I'm not sure if this solution is secure or best practice but it worked for me in this case.