ForbiddenError when attempting to write file to GC

2019-04-13 07:05发布

I have this code:

def save_to_gcs(self, img, img_obj):
    '''
    Image data, Image metadata object -> Blob Key
    Given an image and image metadata, stores it in a GCS bucket
    '''
    bucket = '/foo'
    filename = bucket + '/' + str(img_obj['filename'])

    self.tmp_filenames_to_clean_up = []

    logging.info('Creating file %s\n' % img_obj['filename'])

    write_retry_params = gcs.RetryParams(backoff_factor=1.1)
    gcs_file = gcs.open(filename,
                        'w',
                        content_type=img_obj['mimetype'],
                        retry_params=write_retry_params)
    gcs_file.write(img)
    gcs_file.close()
    self.tmp_filenames_to_clean_up.append(filename)

    return blobstore.create_gs_key('/gs/' + filename)

But it fails with this error:

Expect status [201] from Google Storage. But got status 403. Response headers: {'content-length': '145', 'via': 'HTTP/1.1 GWA', 'x-google-cache-control': 'remote-fetch', 'expires': 'Fri, 01 Jan 1990 00:00:00 GMT', 'server': 'HTTP Upload Server Built on Jun 7 2013 11:30:13 (1370629813)', 'pragma': 'no-cache', 'cache-control': 'no-cache, no-store, must-revalidate', 'date': 'Thu, 20 Jun 2013 23:13:55 GMT', 'content-type': 'application/xml; charset=UTF-8'}
Traceback (most recent call last):
  File "/python27_runtime/python27_lib/versions/third_party/webapp2-2.5.1/webapp2.py", line 1536, in __call__
    rv = self.handle_exception(request, response, e)
  File "/python27_runtime/python27_lib/versions/third_party/webapp2-2.5.1/webapp2.py", line 1530, in __call__
    rv = self.router.dispatch(request, response)
  File "/python27_runtime/python27_lib/versions/third_party/webapp2-2.5.1/webapp2.py", line 1278, in default_dispatcher
    return route.handler_adapter(request, response)
  File "/python27_runtime/python27_lib/versions/third_party/webapp2-2.5.1/webapp2.py", line 1102, in __call__
    return handler.dispatch()
  File "/python27_runtime/python27_lib/versions/third_party/webapp2-2.5.1/webapp2.py", line 572, in dispatch
    return self.handle_exception(e, self.app.debug)
  File "/python27_runtime/python27_lib/versions/third_party/webapp2-2.5.1/webapp2.py", line 570, in dispatch
    return method(*args, **kwargs)
  File "/base/data/home/apps/s~foo/5.368231578716365248/main.py", line 409, in post
    blob_key = self.save_to_gcs(img, img_obj)  # Save the image to a GCS bucket. returns a blob_key
  File "/base/data/home/apps/s~foo/5.368231578716365248/main.py", line 448, in save_to_gcs
    retry_params=write_retry_params)
  File "/base/data/home/apps/s~foo/5.368231578716365248/external/cloudstorage/cloudstorage_api.py", line 69, in open
    return storage_api.StreamingBuffer(api, filename, content_type, options)
  File "/base/data/home/apps/s~foo/5.368231578716365248/external/cloudstorage/storage_api.py", line 527, in __init__
    errors.check_status(status, [201], headers)
  File "/base/data/home/apps/s~foo/5.368231578716365248/external/cloudstorage/errors.py", line 99, in check_status
    raise ForbiddenError(msg)
ForbiddenError: Expect status [201] from Google Storage. But got status 403. Response headers: {'content-length': '145', 'via': 'HTTP/1.1 GWA', 'x-google-cache-control': 'remote-fetch', 'expires': 'Fri, 01 Jan 1990 00:00:00 GMT', 'server': 'HTTP Upload Server Built on Jun 7 2013 11:30:13 (1370629813)', 'pragma': 'no-cache', 'cache-control': 'no-cache, no-store, must-revalidate', 'date': 'Thu, 20 Jun 2013 23:13:55 GMT', 'content-type': 'application/xml; charset=UTF-8'}

Any help with deciphering that error and coming up with a solution would be much appreciated.

Thanks

4条回答
何必那么认真
2楼-- · 2019-04-13 07:33

This did not work from me. Google says we have to do below mentioned method.

Give permissions to your bucket or objects. To enable your app to create new objects in a bucket, you need to do the following:

Log into the App Engine Admin Console. Click on the application you want to authorize for your Cloud Storage bucket. Click on Application Settings under the Administration section on the left-hand side. Copy the value under Service Account Name. This is the service account name of your application, in the format application-id@appspot.gserviceaccount.com. If you are using an App Engine Premier Account, the service account name for your application is in the format application-id.example.com@appspot.gserviceaccount.com. Grant access permissions using one of the following methods: The easiest way to grant app access to a bucket is to use the Google Cloud Console to add the service account name of the app as a team member to the project that contains the bucket. You can do this under Permissions in the left sidebar of the Google Cloud Console. The app should have edit permissions if it needs to write to the bucket. For information about permissions in Cloud Storage, see Scopes and Permissions. Add more apps to the project team if desired. Note: In some circumstances, you might not be able to add the service account as a team member. If you cannot add the service account, use the alternative method, bucket ACLs, as described next.

查看更多
霸刀☆藐视天下
3楼-- · 2019-04-13 07:50

Same thing happened to me and it baffled me. I got it working by following the steps on this page under the Prerequisites section. A couple notes though:

  • For number 2, make sure you go to the APIs Console and turn on GCS under Services
  • For number 5, go to the Cloud Console, select your project, click the Settings wrench and click Teams. Add your gserviceaccount.com thing here.
  • Also for number 5, I think you have to edit the ACL files with gsutil. Follow the alternate instructions provided.

That should work for you since it did for me.

查看更多
Luminary・发光体
4楼-- · 2019-04-13 07:53

... besides the above, also go to "API's" (under "API's and Auth" under your project in the "Cloud Console", and make sure "Google Cloud Storage" is turned on. And under "Billing", make sure that is turned on.

查看更多
Fickle 薄情
5楼-- · 2019-04-13 07:58

The documentation is confusing for granting access to your app engine app (which is most likely your problem). Here is what worked for me in the latest Google Cloud Console:

  1. In the Google Cloud Console, click your project, then "APIs & auth". Turn on "Google Cloud Storage" and "Google Cloud Storage JSON API".
  2. Click back to the "Overview" screen, and click "Cloud Storage" in the left menu.
  3. Click the check box next to your bucket, and click the "Bucket Permissions" button.
  4. Add a new "User" permission and specify your app engine service account name, in the format of application-id@appspot.gserviceaccount.com. This is found in the Application Settings of the AppEngine Console. Better instructions to find this account name are here.
  5. Save your changes.
查看更多
登录 后发表回答